Files
pgames-manager/backend/app/games/tomie/defects.py
T
mrleo1nidandClaude Sonnet 5.5 12ec82c7e6 refactor: move game-specific import logic into profiles; unblock Tomie import
- Add app/games: GameProfile base, registry, ReaderHooks and renpy/naninovel/
  tomie profiles. pipeline, preflight, detect and mods dispatch via the registry
- Move tomie_* converter modules to app/games/tomie and split out reader hooks,
  import, mod validation and known defects
- Tolerate the 31 authoring defects of the pinned Tomie build as report
  warnings (exact list, per-script counts); any new defect still blocks import
- Frontend: runtime registry (runtimes.ts) with lazy Tomie launcher
- Add profile/registry tests and docs/GAME_PROFILES.md; update IMPORT.md

Full media export of the original Tomie build is not yet verified.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 11:35:23 +03:00

64 lines
4.3 KiB
Python

"""Authoring defects of the pinned Tomie build that the importer tolerates.
These are mistakes in the original scripts (jumps to labels that do not exist,
branches without EndIf, assignments without a valid operator). The original
engine fails at the same place; so does the PGames player, which throws an
explicit error when execution reaches one (see nani-runtime.ts). They are listed
as warnings in the import report instead of blocking the whole game.
The list is exact: a key is (issue code, message, script) and the number is the
maximum count. Anything new or more frequent - for example from an edited mod -
is still refused. Do not add entries to make an import pass; add them only after
confirming that the defect exists in the original build.
"""
from collections import Counter
from app.converter.compatibility import Issue
KNOWN_DEFECTS: dict[tuple[str, str, str], int] = {
('invalid_branch', 'BeginIf не имеет завершающего EndIf', 'EP_Slum'): 1,
('invalid_branch', 'BeginIf не имеет завершающего EndIf', 'QuestHub'): 1,
('invalid_branch', 'BeginIf не имеет завершающего EndIf', 'System'): 1,
('invalid_branch', 'Else не имеет завершающего EndIf', 'EP_Slum'): 1,
('invalid_branch', 'Else не имеет завершающего EndIf', 'QuestHub'): 1,
('invalid_branch', 'ElseIf не имеет завершающего EndIf', 'EP_Slum'): 1,
('missing_target', 'Не найден переход AB_Studio.SkillUp', 'AB_Studio'): 1,
('missing_target', 'Не найден переход B_Beggar.Start', 'DicePlaySub'): 1,
('missing_target', 'Не найден переход B_Exercise.Start', 'DicePlaySub'): 1,
('missing_target', 'Не найден переход B_Harassment.endStreet', 'B_Harassment'): 1,
('missing_target', 'Не найден переход B_Job.Start', 'DicePlaySub'): 1,
('missing_target', 'Не найден переход B_Model.Start', 'DicePlaySub'): 1,
('missing_target', 'Не найден переход B_Police.Start', 'DicePlaySub'): 1,
('missing_target', 'Не найден переход B_R_Roaming_Normal.DemandSexByGroup', 'B_R_Roaming_Normal'): 1,
('missing_target', 'Не найден переход B_Rest.Start', 'DicePlaySub'): 1,
('missing_target', 'Не найден переход B_Study.Start', 'DicePlaySub'): 1,
('missing_target', 'Не найден переход Common.Failed', 'B_Approached'): 1,
('missing_target', 'Не найден переход Common.StatP', 'Common_Date'): 1,
('missing_target', 'Не найден переход E_VacationWithMari.DayPassVacation', 'DicePlaySub'): 1,
('missing_target', 'Не найден переход E_VacationWithMari.DayPassVacation', 'E_VacationWithMari'): 2,
('missing_target', 'Не найден переход Laptop.Cam_END', 'Laptop'): 1,
('missing_target', 'Не найден переход Laptop.SexPain_Defloration', 'Laptop'): 1,
('missing_target', 'Не найден переход LoanShark.End', 'LoanShark'): 1,
('missing_target', 'Не найден переход MessagePlay.End', 'MessagePlay'): 1,
('missing_target', 'Не найден переход ReturnToHome.return', 'ReturnToHome'): 1,
('missing_target', 'Не найден переход XEnding.Koman', 'QuestHub'): 1,
('missing_target', 'Не найден переход XEnding.Suicide_Continue', 'XEnding'): 1,
('unsupported_choice', 'Не поддерживается присваивание Naninovel: iCorruption+1.5', 'AppInswitter'): 1,
('unsupported_choice', 'Не поддерживается присваивание Naninovel: iWillpower-5', 'EP_Slum'): 1,
('unsupported_choice', 'Не поддерживается присваивание Naninovel: temp==2', 'B_HighStreet'): 1,
}
def split_known(issues: list[Issue]) -> tuple[list[Issue], list[Issue]]:
"""Return (blocking, known) issues. Each key is waived up to its recorded count."""
left = Counter(KNOWN_DEFECTS)
blocking, known = [], []
for issue in issues:
key = (issue.code, issue.message, issue.location.split(":")[0])
if left[key] > 0:
left[key] -= 1
known.append(issue)
else:
blocking.append(issue)
return blocking, known