/* * When a song is skipped or played successfully, song feedback * should occur. This routine alters these statistics and also * ensures that the global statistics are kept up to date. */ void feedback( song_info_t *song, short direction ) { double rating = get_rating( song->stat ); database_info.sum -= rating; database_info.sqr_sum -= rating * rating; if( direction < 0 ) { database_info.skip_sqr_sum -= song->stat.skip_count * song->stat.skip_count; song->stat.skip_count++; database_info.skip_sum++; database_info.skip_sqr_sum += song->stat.skip_count * song->stat.skip_count; } else { database_info.play_sqr_sum -= song->stat.play_count * song->stat.play_count; song->stat.play_count++; database_info.play_sum++; database_info.play_sqr_sum += song->stat.play_count * song->stat.play_count; } song->stat.changed = 1; rating = get_rating( song->stat ); database_info.sum += rating; database_info.sqr_sum += rating * rating; save_song( song ); }
/* * Initializes the statistics of all songs that are needed * to calculate which song to pick next. Currently this is * the average and the standard deviation. * If a song's rating changes (that is play_count or skip_count), * the sum and sqr_sum must be adjusted to reflect those changes. */ void start_song_picker() { int i; squash_wlock( database_info.lock ); database_info.sum = 0; database_info.sqr_sum = 0; database_info.play_sum = 0; database_info.play_sqr_sum = 0; database_info.skip_sum = 0; database_info.skip_sqr_sum = 0; for( i = 0; i < database_info.song_count; i++ ) { double rating; #ifdef EMPEG squash_wunlock( database_info.lock ); sched_yield(); squash_wlock( database_info.lock ); #endif rating = get_rating( database_info.songs[i].stat ); database_info.sum += rating; database_info.sqr_sum += rating * rating; database_info.play_sum += database_info.songs[i].stat.play_count; database_info.play_sqr_sum += database_info.songs[i].stat.play_count * database_info.songs[i].stat.play_count; database_info.skip_sum += database_info.songs[i].stat.skip_count; database_info.skip_sqr_sum += database_info.songs[i].stat.skip_count * database_info.songs[i].stat.skip_count; } database_info.stats_loaded = TRUE; squash_wunlock( database_info.lock ); }
/* * This routine picks a song on two criteria. * 1st: The songs rating (goodness) which is based on the play_count and * skip_count statistics that are gathered. See get_rating(). * 2nd: The repeat_counter. The song must count down from 10 before it * is actually picked. This helps avoid duplicate songs. */ unsigned int pick_song() { double avg; double std_dev; unsigned int canidate; double canidate_rating; /* This is a random pick. It sucks. */ /* return (int)((double)database_info.song_count * rand() / (RAND_MAX + 1.0)); */ avg = database_info.sum / database_info.song_count; std_dev = sqrt( fabs(database_info.sqr_sum / database_info.song_count - avg*avg) ); while( 1 ) { canidate = (int)((double)database_info.song_count * rand() / (RAND_MAX + 1.0)); canidate_rating = get_rating( database_info.songs[canidate].stat ); if( !normal_test( canidate_rating, avg, std_dev ) ) { continue; } database_info.songs[canidate].stat.changed = TRUE; if( database_info.songs[canidate].stat.repeat_counter-- != 0 ) { continue; } database_info.songs[canidate].stat.repeat_counter = 10; return canidate; } }
int main(int argc, char* argv[]) { board_t b, bb; memset(&b, 0, sizeof(b)); memset(&bb, 0, sizeof(bb)); const pos_t p = {0, 3}; set_cell(&b, W, p); set_cell(&b, W, (pos_t) {0,2}); set_cell(&b, B, (pos_t) {0,1}); set_cell(&b, W, (pos_t) {5, 5}); set_cell(&b, B, (pos_t) {6, 5}); set_cell(&b, B, (pos_t) {6, 6}); set_cell(&b, B, (pos_t) {4, 5}); // Why the heck is the old version equally fast? printf("black as max yields a rating of %d\n", get_rating(&b, B)); return 0; }
const char *get_font_path(const char *family, uint16_t size, const char *style, uint32_t flags, FT_Long *idx) { const char *best_path = NULL; double best_rating = 0.0; struct dstr face_and_style = {0}; struct dstr style_str = {0}; bool bold = !!(flags & OBS_FONT_BOLD); bool italic = !!(flags & OBS_FONT_ITALIC); if (!family || !*family) return NULL; if (style) { dstr_copy(&style_str, style); dstr_replace(&style_str, "Bold", ""); dstr_replace(&style_str, "Italic", ""); dstr_replace(&style_str, " ", " "); dstr_depad(&style_str); } dstr_copy(&face_and_style, family); if (!dstr_is_empty(&style_str)) { dstr_cat(&face_and_style, " "); dstr_cat_dstr(&face_and_style, &style_str); } for (size_t i = 0; i < font_list.num; i++) { struct font_path_info *info = font_list.array + i; double rating = (double)get_rating(info, &face_and_style); if (rating < info->face_len) continue; if (info->is_bitmap) { int best_diff = 1000; for (size_t j = 0; j < info->num_sizes; j++) { int diff = abs(info->sizes[j] - size); if (diff < best_diff) best_diff = diff; } rating /= (double)(best_diff + 1.0); } if (info->bold == bold) rating += 1.0; if (info->italic == italic) rating += 1.0; if (rating > best_rating) { best_path = info->path; *idx = info->index; best_rating = rating; } } dstr_free(&style_str); dstr_free(&face_and_style); return best_path; }
rating_info Netflix::get_rating(uint user_id, uint movie_id) { rating_info r(false); get_rating(user_id, movie_id, &r); return r; }