diff --git a/app/blueprints/admin/admin.py b/app/blueprints/admin/admin.py index 2a2bace..c3591f5 100644 --- a/app/blueprints/admin/admin.py +++ b/app/blueprints/admin/admin.py @@ -75,7 +75,7 @@ def admin_page(): return redirect(url_for("admin.admin_page")) elif action == "recalcscores": for p in Package.query.all(): - p.recalcScore() + p.setStartScore() db.session.commit() return redirect(url_for("admin.admin_page")) diff --git a/app/blueprints/packages/releases.py b/app/blueprints/packages/releases.py index 60a54bd..a7f161e 100644 --- a/app/blueprints/packages/releases.py +++ b/app/blueprints/packages/releases.py @@ -130,9 +130,18 @@ def download_release(package, id): if not has_key(key): set_key(key, "true") + bonus = 1 + if not package.getIsFOSS(): + bonus *= 0.1 + PackageRelease.query.filter_by(id=release.id).update({ "downloads": PackageRelease.downloads + 1 }) + + Package.query.filter_by(id=package.id).update({ + "score": Package.score + bonus + }) + db.session.commit() return redirect(release.url, code=300) diff --git a/app/models.py b/app/models.py index 3632ebc..9a80873 100644 --- a/app/models.py +++ b/app/models.py @@ -24,6 +24,7 @@ from flask import Flask, url_for from flask_sqlalchemy import SQLAlchemy, BaseQuery from flask_migrate import Migrate from flask_user import login_required, UserManager, UserMixin, SQLAlchemyAdapter +from sqlalchemy import func from sqlalchemy.orm import validates from sqlalchemy_searchable import SearchQueryMixin from sqlalchemy_utils.types import TSVectorType @@ -425,6 +426,9 @@ class Package(db.Model): for e in PackagePropertyKey: setattr(self, e.name, getattr(package, e.name)) + def getIsFOSS(self): + return self.license.is_foss and self.media_license.is_foss + def getState(self): if self.approved: return "approved" @@ -602,16 +606,20 @@ class Package(db.Model): else: raise Exception("Permission {} is not related to packages".format(perm.name)) - def recalcScore(self): - self.score = 10 + def setStartScore(self): + downloads = db.session.query(func.sum(PackageRelease.downloads)). \ + filter(PackageRelease.package_id == self.id).scalar() or 0 - if self.forums is not None: - topic = ForumTopic.query.get(self.forums) - if topic: - days = (datetime.datetime.now() - topic.created_at).days - months = days / 30 - years = days / 365 - self.score = topic.views / max(years, 0.0416) + 80*min(max(months, 0.5), 6) + 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 @@ -619,6 +627,7 @@ class Package(db.Model): if not self.license.is_foss or not self.media_license.is_foss: self.score *= 0.1 + class MetaPackage(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), unique=True, nullable=False) diff --git a/app/tasks/__init__.py b/app/tasks/__init__.py index fb62cb0..1f3df02 100644 --- a/app/tasks/__init__.py +++ b/app/tasks/__init__.py @@ -69,6 +69,10 @@ CELERYBEAT_SCHEDULE = { 'topic_list_import': { 'task': 'app.tasks.forumtasks.importTopicList', 'schedule': crontab(minute=1, hour=1), + }, + 'package_score_update': { + 'task': 'app.tasks.pkgtasks.updatePackageScores', + 'schedule': crontab(minute=10, hour=1), } } celery.conf.beat_schedule = CELERYBEAT_SCHEDULE diff --git a/app/tasks/forumtasks.py b/app/tasks/forumtasks.py index 9b200fc..4a4e27f 100644 --- a/app/tasks/forumtasks.py +++ b/app/tasks/forumtasks.py @@ -171,7 +171,4 @@ def importTopicList(): topic.views = int(info["views"]) topic.created_at = info["date"] - for p in Package.query.all(): - p.recalcScore() - db.session.commit() diff --git a/app/tasks/pkgtasks.py b/app/tasks/pkgtasks.py new file mode 100644 index 0000000..8ff5836 --- /dev/null +++ b/app/tasks/pkgtasks.py @@ -0,0 +1,23 @@ +# Content DB +# Copyright (C) 2018 rubenwardy +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +from app.models import Package, PackageRelease +from app.tasks import celery + +@celery.task() +def updatePackageScores(): + Package.query.update({ "score": PackageRelease.score * 0.8 })