mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-12 13:03:54 -06:00
feat: read a search list as one need
A core that loads the first of several names (yabause: saturn_bios.bin, sega_101.bin, mpr-17933.bin) needs one of them. Profiles wrote this as required on the first name and optional on the others, so verify and the gap report called saturn_bios.bin a missing required file while sega_101.bin was held, and a set held only through a name marked optional read as a need met by an optional file. Model: an explicit group on the file entry, mirroring the platform field. priority was not reused: it is a rank, read by slot.py, region.py and truth.py inside a (system, region) slot, and that slot is not the set. px68k-sdl ranks its IPL list and its font list each from 1 in one system, pom2 ranks one list per machine model, DuckStation ranks 105 images across every region and takes any of them. A rank cannot say where one list ends. priority stays the order inside a group. Readers, through alternatives.settle_sets: - verify --emulator and the emulator pack: a held member fills the set, the others leave the report, a set nobody holds is one gap under its first member naming the others. - find_undeclared_files (verify platform, core complement of packs and manifests): same rule, a platform declaration or launcher counts as answering the set. - cross_reference: excused members are set aside as other versions. - slot.py: ranks compare members of one set only. - archive members: a required set inside an archive is met by one. - truth: a member gives no requirement of its own, one_of and one_of_required carry the set, and the exporters and the diff leave such a line's required as the platform wrote it. - validate_schemas: members of a group share required.
This commit is contained in:
1 parent
a40f8416e1
commit
2c76cc7df9
13 files changed
+599
-41
No files matched your search
+36
-4
@@ -1267,7 +1267,39 @@ _archive_index: dict[int, tuple[list[dict], int, dict[str | None, list[dict]]]]
|
||||
|
||||
|
||||
def _member(f: dict) -> dict:
|
||||
return {"crc32": str(f["crc32"]).lower(), "required": bool(f.get("required", True))}
|
||||
member = {"crc32": str(f["crc32"]).lower(), "required": bool(f.get("required", True))}
|
||||
if f.get("group"):
|
||||
# One of the members sharing it is enough (alternatives.py).
|
||||
member["group"] = f["group"]
|
||||
return member
|
||||
|
||||
|
||||
def _required_met(members: list[dict], held: Callable[[dict], bool]) -> tuple[int, bool]:
|
||||
"""How many requirements an archive meets, and whether it meets all.
|
||||
|
||||
A required member is one requirement, and so is a required set of
|
||||
alternatives, met when one of its members is held: Odin reads the
|
||||
first of three Hikaru boot ROMs it finds in hikaru.zip.
|
||||
"""
|
||||
from alternatives import groups_of
|
||||
|
||||
met = 0
|
||||
complete = True
|
||||
sets: dict[str, bool] = {}
|
||||
for m in members:
|
||||
if not m["required"]:
|
||||
continue
|
||||
names = groups_of(m)
|
||||
if names:
|
||||
for name in names:
|
||||
sets[name] = sets.get(name, False) or held(m)
|
||||
continue
|
||||
if held(m):
|
||||
met += 1
|
||||
else:
|
||||
complete = False
|
||||
met += sum(sets.values())
|
||||
return met, complete and all(sets.values())
|
||||
|
||||
|
||||
def archive_members(archive: str, files: list[dict]) -> list[dict]:
|
||||
@@ -1316,7 +1348,7 @@ def holds_required_members(path: str, members: list[dict]) -> bool:
|
||||
"""Whether an archive holds every member a profile requires inside it."""
|
||||
crcs = zip_member_crcs(path)
|
||||
names = zip_member_names(path)
|
||||
return all(_member_held(m, crcs, names) for m in members if m["required"])
|
||||
return _required_met(members, lambda m: _member_held(m, crcs, names))[1]
|
||||
|
||||
|
||||
def contents_members(file_entry: dict) -> list[dict]:
|
||||
@@ -1360,8 +1392,8 @@ def _holding_members(paths: list[str], members: list[dict]) -> list[str]:
|
||||
def held(path: str) -> tuple[int, int]:
|
||||
crcs = zip_member_crcs(path)
|
||||
names = zip_member_names(path)
|
||||
found = [m for m in members if _member_held(m, crcs, names)]
|
||||
return sum(1 for m in found if m["required"]), len(found)
|
||||
found = {id(m) for m in members if _member_held(m, crcs, names)}
|
||||
return _required_met(members, lambda m: id(m) in found)[0], len(found)
|
||||
|
||||
scores = {path: held(path) for path in paths}
|
||||
best = max(scores.values(), default=(0, 0))
|
||||
|
||||
Reference in new issue
Block a user