diff --git a/app/blueprints/admin/admin.py b/app/blueprints/admin/admin.py index ff509f9..5c63fb2 100644 --- a/app/blueprints/admin/admin.py +++ b/app/blueprints/admin/admin.py @@ -87,7 +87,7 @@ def admin_page(): return redirect(url_for("admin.admin_page")) elif action == "recalcscores": for p in Package.query.all(): - p.setStartScore() + p.recalcScore() db.session.commit() return redirect(url_for("admin.admin_page")) diff --git a/app/blueprints/api/endpoints.py b/app/blueprints/api/endpoints.py index d5ef9d0..c12d59b 100644 --- a/app/blueprints/api/endpoints.py +++ b/app/blueprints/api/endpoints.py @@ -42,8 +42,7 @@ def package_scores(): qb = QueryBuilder(request.args) query = qb.buildPackageQuery() - pkgs = [{ "author": package.author.username, "name": package.name, "score": package.score } \ - for package in query.all()] + pkgs = [package.getScoreDict() for package in query.all()] return jsonify(pkgs) diff --git a/app/blueprints/packages/reviews.py b/app/blueprints/packages/reviews.py index 114afae..74070fc 100644 --- a/app/blueprints/packages/reviews.py +++ b/app/blueprints/packages/reviews.py @@ -82,6 +82,8 @@ def review(package): db.session.commit() + package.recalcScore() + notif_msg = None if was_new: notif_msg = "New review '{}' on package {}".format(form.title.data, package.title) diff --git a/app/flatpages/help/top_packages.md b/app/flatpages/help/top_packages.md index da3f38a..33e7d25 100644 --- a/app/flatpages/help/top_packages.md +++ b/app/flatpages/help/top_packages.md @@ -2,8 +2,12 @@ title: Top Packages Algorithm ## Score -A package's score is currently equal to a pseudo rolling average of downloads. -In the future, a package will also gain score through reviews. +A package's score is currently equal to a pseudo rolling average of downloads, +plus the sum of review scores. + +A review score is 100 if positive, -100 if negative. + + score = avg_downloads + Σ 100 * (positive ? 1 : -1) ## Pseudo rolling average of downloads @@ -35,7 +39,8 @@ which was 20% of the above value. ## Manual adjustments The admin occasionally reduces all packages by a set percentage to speed up -convergence. Convergence is when +convergence. Convergence is when the pseudo-rolling average matches the actual +rolling average - the effect of the legacy heuristic is gone. ## Transparency and Feedback diff --git a/app/models.py b/app/models.py index 7b07309..e026c77 100644 --- a/app/models.py +++ b/app/models.py @@ -712,28 +712,19 @@ class Package(db.Model): else: raise Exception("Permission {} is not related to packages".format(perm.name)) - def setStartScore(self): - downloads = self.downloads - - forum_score = 0 - forum_bonus = 0 - topic = self.forums and ForumTopic.query.get(self.forums) - if topic: - months = (datetime.datetime.now() - topic.created_at).days / 30 - years = months / 12 - forum_score = topic.views / max(years, 0.0416) + 80*min(max(months, 0.5), 6) - forum_bonus = topic.views + topic.posts - - self.score = max(downloads, forum_score * 0.6) + forum_bonus - - if self.getMainScreenshotURL() is None: - self.score *= 0.8 - - self.recalcScore() + def getScoreDict(self): + return { + "author": self.author.username, + "name": self.name, + "score": self.score, + "score_downloads": self.score_downloads, + "score_reviews": self.score - self.score_downloads, + "downloads": self.downloads + } def recalcScore(self): - self.score_downloads = self.score - + review_scores = [ 100 * r.asSign() for r in self.reviews ] + self.score = self.score_downloads + sum(review_scores) class MetaPackage(db.Model): @@ -1134,6 +1125,9 @@ class PackageReview(db.Model): thread = db.relationship("Thread", uselist=False, back_populates="review") + def asSign(self): + return 1 if self.recommends else -1 + def getEditURL(self): return url_for("packages.edit_review", author=self.package.author.username,