/* scope can be NULL. * lang can be -1 */ static int fill_find_tags_array (GPtrArray *dst, const GPtrArray *src, const char *name, const char *scope, int type, gboolean partial, gint lang, gboolean first) { TMTag **match; int tagIter, count; if ((!src) || (!dst) || (!name) || (!*name)) return 0; match = tm_tags_find (src, name, partial, &count); if (count && match && *match) { for (tagIter = 0; tagIter < count; ++tagIter) { if (! scope || (match[tagIter]->atts.entry.scope && 0 == strcmp(match[tagIter]->atts.entry.scope, scope))) { if (type & match[tagIter]->type) if (lang == -1 || match_langs(lang, match[tagIter])) { g_ptr_array_add (dst, match[tagIter]); if (first) break; } } } } return dst->len; }
int nearest_neighbour(User *user, User ** set, int langs) { int i, k; double vote; Repo *repo, *candidates[WATCH_SIZE]; Match *match; int votes = 0; int candidate_count; int matches; if(langs) get_langs(user); /* Each user in the set */ for(i = 0; i < stats.filtered_user_count; i++) { if(user == set[i]) continue; matches = candidate_count = 0; /* Get number of matches, and store the rest in candidates[] */ for(k = 0; k < set[i]->watch_count; k++) { repo = set[i]->watch[k]; if(find(repo, user->watch, user->watch_count)) matches++; else candidates[candidate_count++] = repo; } /* If the watch-list is similar enough (lots of matches) */ if(matches > (user->watch_count * REPO_MATCH_TRESHOLD)) { vote = normalize(matches, set[i]->watch_count, 100); /* Go through candidates, and add them to recommendations */ for(k = 0; k < candidate_count; k++) { repo = candidates[k]; if(langs) vote += match_langs(user->langs, repo->langs, user->lang_count, repo->lang_count); /* repo is already in recommendation list, add a vote */ if(match = find_match(repo, user->recommend, votes)) match->weight += vote; else { user->recommend[votes].repo = repo; user->recommend[votes++].weight = vote + normalize(repo->watchers, stats.max_watchers, 1); } } } } return votes; }