ёбанные удаления надеюсь финальные
This commit is contained in:
151
tests/test_build96_penalty_strength_transition_state_machine.py
Normal file
151
tests/test_build96_penalty_strength_transition_state_machine.py
Normal file
@@ -0,0 +1,151 @@
|
||||
from pathlib import Path
|
||||
|
||||
from hockey_data.service import HockeyDataService
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
APP_JS = (ROOT / "ui_builder/static/app.js").read_text(encoding="utf-8")
|
||||
APP = (ROOT / "app.py").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _penalty(side: str, remaining: int, *, started: bool) -> dict:
|
||||
return {
|
||||
"side": side,
|
||||
"infraction": {"id": "minor"},
|
||||
"preset": "2m",
|
||||
"durationMs": 120000,
|
||||
"remainingMs": remaining,
|
||||
"running": False,
|
||||
"startedOnce": started,
|
||||
"finished": False,
|
||||
}
|
||||
|
||||
|
||||
def _strength(*penalties: dict) -> dict:
|
||||
settings = {
|
||||
"strength_regulation_skaters": 5,
|
||||
"strength_min_skaters": 3,
|
||||
"strength_state_labels": {
|
||||
"regulation": {
|
||||
"5x4": {"ru": "БОЛ"},
|
||||
"4x4": {"ru": "4x4"},
|
||||
"4x3": {"ru": "4x3"},
|
||||
}
|
||||
},
|
||||
}
|
||||
return HockeyDataService._strength_payload(
|
||||
settings,
|
||||
stage="regular",
|
||||
current_period="2",
|
||||
timer_state={"penalty_board": {"penalties": list(penalties)}},
|
||||
language="ru",
|
||||
)
|
||||
|
||||
|
||||
def test_prepared_penalty_does_not_change_strength_until_explicit_start():
|
||||
prepared = _strength(_penalty("home", 120000, started=False))
|
||||
assert prepared["strength_label"] == "5×5"
|
||||
assert prepared["advantage_side"] == ""
|
||||
|
||||
started = _strength(_penalty("home", 120000, started=True))
|
||||
assert started["strength_label"] == "4×5"
|
||||
assert started["advantage_side"] == "away"
|
||||
assert started["state_label"] == "БОЛ"
|
||||
|
||||
|
||||
def test_complex_transition_strength_sequence_matches_requested_flow():
|
||||
# Initial HOME penalty: AWAY/right has the advantage.
|
||||
p1 = _penalty("home", 80000, started=True)
|
||||
value = _strength(p1)
|
||||
assert value["strength_label"] == "4×5"
|
||||
assert value["advantage_side"] == "away"
|
||||
|
||||
# Coincidental pair is added while the first penalty is still running.
|
||||
p2 = _penalty("home", 120000, started=True)
|
||||
p3 = _penalty("away", 120000, started=True)
|
||||
value = _strength(p1, p2, p3)
|
||||
assert value["strength_label"] == "3×4"
|
||||
assert value["advantage_side"] == "away"
|
||||
assert value["state_label"] == "4x3"
|
||||
|
||||
# The first penalty expires: the pair remains, so strength is equal 4x4.
|
||||
value = _strength(
|
||||
_penalty("home", 40000, started=True),
|
||||
_penalty("away", 40000, started=True),
|
||||
)
|
||||
assert value["strength_label"] == "4×4"
|
||||
assert value["advantage_side"] == ""
|
||||
assert value["state_label"] == "4x4"
|
||||
|
||||
# AWAY/right takes another penalty: HOME/left now has a 4x3 advantage.
|
||||
value = _strength(
|
||||
_penalty("home", 30000, started=True),
|
||||
_penalty("away", 30000, started=True),
|
||||
_penalty("away", 120000, started=True),
|
||||
)
|
||||
assert value["strength_label"] == "4×3"
|
||||
assert value["advantage_side"] == "home"
|
||||
assert value["state_label"] == "4x3"
|
||||
|
||||
# Coincidental pair expires, leaving ordinary HOME power play.
|
||||
value = _strength(_penalty("away", 90000, started=True))
|
||||
assert value["strength_label"] == "5×4"
|
||||
assert value["advantage_side"] == "home"
|
||||
assert value["state_label"] == "БОЛ"
|
||||
|
||||
|
||||
def test_runtime_holds_single_plate_through_temporary_equal_strength():
|
||||
start = APP_JS.index("function penaltyDisplayEntriesByTargetSide")
|
||||
end = APP_JS.index("function hockeyPenaltySideMappingDetail", start)
|
||||
block = APP_JS[start:end]
|
||||
assert "canHoldEqualStrength" in block
|
||||
assert "state.hockeyPenaltyAdvantageCycle.hadAdvantage" in block
|
||||
assert "lastAdvantageSide" in block
|
||||
assert "const canHoldEqualStrength = Boolean(state.hockeyPenaltyAdvantageCycle.hadAdvantage)" in block
|
||||
assert 'home: rememberedSide === "home" && transitionEntry ? [transitionEntry] : []' in block
|
||||
assert 'away: rememberedSide === "away" && transitionEntry ? [transitionEntry] : []' in block
|
||||
assert 'home: advantageSide === "home" && transitionEntry ? [transitionEntry] : []' in block
|
||||
assert 'away: advantageSide === "away" && transitionEntry ? [transitionEntry] : []' in block
|
||||
assert "holdingEqualStrength" in block
|
||||
# The countdown source remains the globally soonest active penalty.
|
||||
assert "const transitionEntry = all[0] || null;" in block
|
||||
|
||||
|
||||
def test_pure_equal_strength_without_previous_advantage_still_has_no_plate():
|
||||
start = APP_JS.index("function penaltyDisplayEntriesByTargetSide")
|
||||
end = APP_JS.index("function hockeyPenaltySideMappingDetail", start)
|
||||
block = APP_JS[start:end]
|
||||
assert "if (!canHoldEqualStrength)" in block
|
||||
assert "return { home: [], away: [], routedToAdvantage: false" in block
|
||||
|
||||
|
||||
def test_advantage_cycle_is_saved_and_restored_for_reload_during_4x4():
|
||||
snapshot = APP_JS.split("function hockeyGameTimerSnapshot", 1)[1].split("function hockeyApplySavedTimers", 1)[0]
|
||||
assert "advantage_cycle" in snapshot
|
||||
assert "had_advantage" in snapshot
|
||||
assert "last_advantage_side" in snapshot
|
||||
restore = APP_JS.split("function hockeyApplySavedTimers", 1)[1].split("async function hockeyPersistGameTimers", 1)[0]
|
||||
assert "restoredPenaltyAdvantageCycle" in restore
|
||||
assert "savedCycle.last_advantage_side" in restore
|
||||
|
||||
normalized = HockeyDataService._normalise_game_timer_state({
|
||||
"penalty_board": {
|
||||
"penalties": [],
|
||||
"history": [],
|
||||
"advantage_cycle": {"had_advantage": True, "last_advantage_side": "away"},
|
||||
}
|
||||
})
|
||||
assert normalized["penalty_board"]["advantage_cycle"] == {
|
||||
"had_advantage": True,
|
||||
"last_advantage_side": "away",
|
||||
}
|
||||
|
||||
|
||||
def test_full_strength_waits_for_last_started_penalty_not_prepared_draft():
|
||||
control = APP_JS.split("function controlHockeyPenalty", 1)[1].split("function formatHockeyPenaltyTime", 1)[0]
|
||||
assert "hockeyPenaltyHasStarted(item)" in control
|
||||
ticker = APP_JS.split("function updateHockeyPenaltyBoards", 1)[1].split("function registerHockeyBoardNode", 1)[0]
|
||||
assert "remainingTotal = board.penalties.filter((item) => !item.finished && hockeyEventReady(item) && hockeyPenaltyHasStarted(item)).length" in ticker
|
||||
|
||||
|
||||
def test_build96_runtime_version():
|
||||
assert 'BUILD_VERSION = "2026.08.20.17"' in APP
|
||||
Reference in New Issue
Block a user