Build a Recommender for Reviewer Suggestion

Until now, reviewer suggestion was purely based on a search. I've built
a small recommender to improve the suggestions based on past
contributions by the individual reviewers and added an extension point
so that people can customize this feature.

The built-in recommender makes a default suggestion of reviewers before
the user types a query. These are based on people that have reviewed the
last contributions that a user made.

If the user starts typing in the box, we generate a list of candidates
using the account index and feed it into a small recommender. The
recommender ranks the list by looking at recent contributions of the
candidates made in the same project. Contributions include reviews,
owned-changes and comments at different weights.

Change-Id: I5aca23ddd2442146fd26bdc12e7c18da85de7ac1
This commit is contained in:
Patrick Hiesel
2016-05-03 18:15:08 +02:00
parent a4b637d578
commit 87880b0543
17 changed files with 723 additions and 143 deletions

View File

@@ -43,7 +43,7 @@ public abstract class HighlightSuggestOracle extends SuggestOracle {
}
@Override
public final void requestSuggestions(final Request request, final Callback cb) {
public final void requestSuggestions(Request request, Callback cb) {
onRequestSuggestions(request, new Callback() {
@Override
public void onSuggestionsReady(final Request request,
@@ -88,27 +88,28 @@ public abstract class HighlightSuggestOracle extends SuggestOracle {
ds = escape(ds);
}
StringBuilder pattern = new StringBuilder();
for (String qterm : splitQuery(qstr)) {
qterm = escape(qterm);
// We now surround qstr by <strong>. But the chosen approach is not too
// smooth, if qstr is small (e.g.: "t") and this small qstr may occur in
// escapes (e.g.: "Tim &lt;email@example.org&gt;"). Those escapes will
// get <strong>-ed as well (e.g.: "&lt;" -> "&<strong>l</strong>t;"). But
// as repairing those mangled escapes is easier than not mangling them in
// the first place, we repair them afterwards.
if (pattern.length() > 0) {
pattern.append("|");
if (qstr != null && !qstr.isEmpty()) {
StringBuilder pattern = new StringBuilder();
for (String qterm : splitQuery(qstr)) {
qterm = escape(qterm);
// We now surround qstr by <strong>. But the chosen approach is not too
// smooth, if qstr is small (e.g.: "t") and this small qstr may occur in
// escapes (e.g.: "Tim &lt;email@example.org&gt;"). Those escapes will
// get <strong>-ed as well (e.g.: "&lt;" -> "&<strong>l</strong>t;"). But
// as repairing those mangled escapes is easier than not mangling them in
// the first place, we repair them afterwards.
if (pattern.length() > 0) {
pattern.append("|");
}
pattern.append(qterm);
}
pattern.append(qterm);
ds = sgi(ds, "(" + pattern.toString() + ")", "<strong>$1</strong>");
// Repairing <strong>-ed escapes.
ds = sgi(ds, "(&[a-z]*)<strong>([a-z]*)</strong>([a-z]*;)", "$1$2$3");
}
ds = sgi(ds, "(" + pattern.toString() + ")", "<strong>$1</strong>");
// Repairing <strong>-ed escapes.
ds = sgi(ds, "(&[a-z]*)<strong>([a-z]*)</strong>([a-z]*;)", "$1$2$3");
displayString = ds;
}