diff --git a/app/flatpages/help/package_config.md b/app/flatpages/help/package_config.md index 5ddc5c09..114a3841 100644 --- a/app/flatpages/help/package_config.md +++ b/app/flatpages/help/package_config.md @@ -37,6 +37,8 @@ ContentDB understands the following information: and for mods only: * `name` - the mod technical name. +* `supported_games` - List of supported game technical names. +* `unsupported_games` - List of not supported game technical names. Useful to override game support detection. ## .cdb.json diff --git a/app/logic/game_support.py b/app/logic/game_support.py index 23d11731..6348087b 100644 --- a/app/logic/game_support.py +++ b/app/logic/game_support.py @@ -17,7 +17,7 @@ import sys -from typing import List, Dict, Optional, Iterator, Iterable +from typing import List, Dict, Optional, Iterator, Iterable, Tuple from app.logic.LogicError import LogicError from app.models import Package, MetaPackage, PackageType, PackageState, PackageGameSupport, db @@ -167,25 +167,23 @@ class GameSupportResolver: db.session.add(support) """ - Add supported game to a package, given the confidence. + Update game supported package on a package, given the confidence. Higher confidences outweigh lower ones. """ - def add_supported(self, package: Package, supported_games: PackageSet, confidence: int): - previous_supported: Dict[str, PackageGameSupport] = {} + def set_supported(self, package: Package, game_is_supported: List[Tuple[Package, bool]], confidence: int): + previous_supported: Dict[int, PackageGameSupport] = {} for support in package.supported_games.all(): db.session.merge(support.game) - previous_supported[support.game.getId()] = support + previous_supported[support.game.id] = support - for game in supported_games: - assert game - - lookup = previous_supported.pop(game.getId(), None) + for game, supports in game_is_supported: + lookup = previous_supported.pop(game.id, None) if lookup is None: support = PackageGameSupport(package, game, confidence) db.session.add(support) elif lookup.confidence <= confidence: - lookup.supports = True + lookup.supports = supports lookup.confidence = confidence db.session.merge(lookup) @@ -195,4 +193,9 @@ class GameSupportResolver: def update(self, package: Package) -> None: retval = self.resolve(package, []) - self.add_supported(package, retval, 1) + + game_is_supported = [] + for game in retval: + game_is_supported.append((game, True)) + + self.set_supported(package, game_is_supported, 1) diff --git a/app/models/packages.py b/app/models/packages.py index 783485af..cf5da522 100644 --- a/app/models/packages.py +++ b/app/models/packages.py @@ -507,8 +507,8 @@ class Package(db.Model): return self.getSortedDependencies(False) def getSortedSupportedGames(self): - supported = self.supported_games.all() - supported.sort(key=lambda x: -x.game.score) + supported = self.supported_games.filter_by(supports=True).all() + supported.sort(key=lambda x: -(x.game.score + 100000*x.confidence)) return supported def getAsDictionaryKey(self): diff --git a/app/tasks/importtasks.py b/app/tasks/importtasks.py index 2ef9a6c7..b125c207 100644 --- a/app/tasks/importtasks.py +++ b/app/tasks/importtasks.py @@ -20,6 +20,7 @@ from zipfile import ZipFile from git import GitCommandError from git_archive_all import GitArchiver from kombu import uuid +from sqlalchemy import or_, and_ from app.models import * from app.tasks import celery, TaskError @@ -27,7 +28,7 @@ from app.utils import randomString, post_bot_message, addSystemNotification, add from app.utils.git import clone_repo, get_latest_tag, get_latest_commit, get_temp_dir from .minetestcheck import build_tree, MinetestCheckError, ContentType from ..logic.LogicError import LogicError -from ..logic.game_support import GameSupportResolver +from ..logic.game_support import GameSupportResolver, PackageSet from ..logic.packages import do_edit_package, ALIASES from ..utils.image import get_image_size @@ -73,6 +74,20 @@ def getMeta(urlstr, author): return result +def get_games_from_csv(csv: str) -> List[Package]: + retval = [] + supported_games_raw = csv.split(",") + for game_name in supported_games_raw: + game_name = game_name.strip() + if game_name.endswith("_game"): + game_name = game_name[:-5] + games = Package.query.filter(and_(Package.state==PackageState.APPROVED, Package.type==PackageType.GAME, + or_(Package.name==game_name, Package.name==game_name + "_game"))).all() + retval.extend(games) + + return retval + + def postReleaseCheckUpdate(self, release: PackageRelease, path): try: tree = build_tree(path, expected_type=ContentType[release.package.type.name], @@ -118,6 +133,15 @@ def postReleaseCheckUpdate(self, release: PackageRelease, path): # Update game supports if package.type == PackageType.MOD: resolver = GameSupportResolver() + game_is_supported = [] + if "supported_games" in tree.meta: + for game in get_games_from_csv(tree.meta["supported_games"]): + game_is_supported.append((game, True)) + if "unsupported_games" in tree.meta: + for game in get_games_from_csv(tree.meta["unsupported_games"]): + game_is_supported.append((game, False)) + + resolver.set_supported(package, game_is_supported, 10) resolver.update(package) # Update min/max