поправлены в какой то раз удаления для верхнего счета
This commit is contained in:
@@ -8,7 +8,7 @@ def test_ready_penalty_opens_target_when_scoreboard_is_live():
|
||||
end = APP_JS.index("function finishActionMatchesSource", start)
|
||||
snippet = APP_JS[start:end]
|
||||
assert "if (hockeyScoreboardIsLive())" in snippet
|
||||
assert 'commands.push({ Function: `OverlayInput${overlay}In`, Input: target.input });' in snippet
|
||||
assert 'inCommands.push({ Function: `OverlayInput${overlay}In`, Input: target.input });' in snippet
|
||||
|
||||
|
||||
def test_penalty_overlay_auto_in_does_not_retrigger_visible_target():
|
||||
|
||||
@@ -50,7 +50,7 @@ def test_mapping_input_picker_sorts_by_number_and_fields_naturally():
|
||||
assert "const allFields = [...(currentInput.fields || [])].sort(mappingVmixFieldOrder);" in ADMIN
|
||||
|
||||
|
||||
def test_coincidental_penalties_fill_both_home_and_away_labels():
|
||||
def test_coincidental_penalties_do_not_fill_side_powerplay_labels():
|
||||
settings = {
|
||||
"strength_regulation_skaters": 5,
|
||||
"strength_min_skaters": 3,
|
||||
@@ -62,5 +62,5 @@ def test_coincidental_penalties_fill_both_home_and_away_labels():
|
||||
value = HockeyDataService._strength_payload(settings, stage="regular", current_period="1", timer_state=timer_state, language="ru")
|
||||
assert value["advantage_side"] == ""
|
||||
assert value["state_key"] == "4x4"
|
||||
assert value["home_label"] == "4 на 4"
|
||||
assert value["away_label"] == "4 на 4"
|
||||
assert value["home_label"] == ""
|
||||
assert value["away_label"] == ""
|
||||
|
||||
@@ -7,13 +7,15 @@ APP_JS = (ROOT / "ui_builder/static/app.js").read_text(encoding="utf-8")
|
||||
BRIDGE = (ROOT / "hockey_data/agent_bridge.py").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_penalty_display_routes_single_side_to_opposite_advantage_target():
|
||||
def test_penalty_display_routes_only_one_transition_timer_to_advantage_target():
|
||||
start = APP_JS.index("function penaltyDisplayEntriesByTargetSide")
|
||||
end = APP_JS.index("function hockeyPenaltySideMappingDetail", start)
|
||||
block = APP_JS[start:end]
|
||||
assert 'if (home.length && away.length)' in block
|
||||
assert 'return { home: [], away: take(home), routedToAdvantage: true, advantageSide: "away" };' in block
|
||||
assert 'return { home: take(away), away: [], routedToAdvantage: true, advantageSide: "home" };' in block
|
||||
assert 'function penaltyLocalAdvantageSide' in APP_JS
|
||||
assert 'const all = [...home, ...away].sort' in block
|
||||
assert 'if (!advantageSide)' in block
|
||||
assert 'home: advantageSide === "home"' in block
|
||||
assert 'away: advantageSide === "away"' in block
|
||||
|
||||
|
||||
def test_penalty_rebalance_and_initial_timer_use_same_display_plan():
|
||||
|
||||
@@ -44,14 +44,16 @@ def test_strength_engine_reports_advantage_for_4x3_and_3x4():
|
||||
assert away_advantage["advantage_side"] == "away"
|
||||
|
||||
|
||||
def test_penalty_plate_routing_defers_powerplay_while_both_sides_have_penalties():
|
||||
def test_penalty_plate_routing_uses_single_advantage_side_and_global_shortest_timer():
|
||||
start = APP_JS.index("function penaltyDisplayEntriesByTargetSide")
|
||||
end = APP_JS.index("function hockeyPenaltySideMappingDetail", start)
|
||||
block = APP_JS[start:end]
|
||||
assert 'if (home.length && away.length)' in block
|
||||
assert 'return { home: take(home), away: take(away), routedToAdvantage: false, advantageSide: "" };' in block
|
||||
assert 'return { home: [], away: take(home), routedToAdvantage: true, advantageSide: "away" };' in block
|
||||
assert 'return { home: take(away), away: [], routedToAdvantage: true, advantageSide: "home" };' in block
|
||||
assert 'const all = [...home, ...away].sort' in block
|
||||
assert 'const advantageSide = penaltyLocalAdvantageSide(home.length, away.length);' in block
|
||||
assert 'if (!advantageSide)' in block
|
||||
assert 'transitionEntry = all[0]' in block
|
||||
assert 'home: advantageSide === "home"' in block
|
||||
assert 'away: advantageSide === "away"' in block
|
||||
|
||||
|
||||
def test_database_schema_reference_lists_real_hockey_tables(tmp_path: Path):
|
||||
|
||||
@@ -14,11 +14,12 @@ def test_authoritative_strength_change_rebalances_penalty_targets():
|
||||
assert "Penalty strength rebalance error" in block
|
||||
|
||||
|
||||
def test_penalty_plan_rebalances_after_strength_refresh_without_forcing_complex_powerplay():
|
||||
def test_penalty_plan_rebalances_after_strength_refresh_to_single_advantage_plate():
|
||||
start = APP_JS.index("function penaltyDisplayEntriesByTargetSide")
|
||||
end = APP_JS.index("function hockeyPenaltySideMappingDetail", start)
|
||||
block = APP_JS[start:end]
|
||||
assert 'if (home.length && away.length)' in block
|
||||
assert 'routedToAdvantage: false' in block
|
||||
assert 'if (home.length)' in block
|
||||
assert 'if (away.length)' in block
|
||||
assert 'penaltyLocalAdvantageSide(home.length, away.length)' in block
|
||||
assert 'transitionEntry = all[0]' in block
|
||||
assert 'routedToAdvantage: true' in block
|
||||
assert 'if (!advantageSide)' in block
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ def _penalty(side: str, remaining: int = 90000) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def test_complex_two_vs_one_keeps_real_strength_but_hides_pp_caption_until_one_side_clears():
|
||||
def test_complex_two_vs_one_keeps_real_strength_and_outputs_caption_on_advantage_side():
|
||||
settings = {
|
||||
"strength_regulation_skaters": 5,
|
||||
"strength_min_skaters": 3,
|
||||
@@ -33,7 +33,7 @@ def test_complex_two_vs_one_keeps_real_strength_but_hides_pp_caption_until_one_s
|
||||
assert value["strength_label"] == "3×4"
|
||||
assert value["advantage_side"] == "away"
|
||||
assert value["home_label"] == ""
|
||||
assert value["away_label"] == ""
|
||||
assert value["away_label"] == "Играют в большинстве"
|
||||
|
||||
|
||||
def test_single_remaining_penalty_outputs_pp_caption_on_opposite_team():
|
||||
@@ -54,12 +54,11 @@ def test_single_remaining_penalty_outputs_pp_caption_on_opposite_team():
|
||||
assert value["away_label"] == "Играют в большинстве"
|
||||
|
||||
|
||||
def test_display_plan_keeps_each_side_while_both_have_penalties_and_clears_when_none():
|
||||
def test_display_plan_never_outputs_two_penalty_plates():
|
||||
start = APP_JS.index("function penaltyDisplayEntriesByTargetSide")
|
||||
end = APP_JS.index("function hockeyPenaltySideMappingDetail", start)
|
||||
block = APP_JS[start:end]
|
||||
assert 'if (home.length && away.length)' in block
|
||||
assert 'return { home: take(home), away: take(away), routedToAdvantage: false, advantageSide: "" };' in block
|
||||
assert 'return { home: [], away: take(home), routedToAdvantage: true, advantageSide: "away" };' in block
|
||||
assert 'return { home: take(away), away: [], routedToAdvantage: true, advantageSide: "home" };' in block
|
||||
assert 'return { home: [], away: [], routedToAdvantage: false, advantageSide: "" };' in block
|
||||
assert 'const all = [...home, ...away].sort' in block
|
||||
assert 'return { home: [], away: [], routedToAdvantage: false' in block
|
||||
assert 'home: advantageSide === "home" && transitionEntry ? [transitionEntry] : []' in block
|
||||
assert 'away: advantageSide === "away" && transitionEntry ? [transitionEntry] : []' in block
|
||||
|
||||
91
tests/test_build89_single_penalty_plate_transition.py
Normal file
91
tests/test_build89_single_penalty_plate_transition.py
Normal file
@@ -0,0 +1,91 @@
|
||||
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")
|
||||
|
||||
|
||||
def _penalty(side: str, remaining: int) -> dict:
|
||||
return {
|
||||
"side": side,
|
||||
"infraction": {"code": "TEST"},
|
||||
"preset": "2",
|
||||
"durationMs": 120000,
|
||||
"remainingMs": remaining,
|
||||
"finished": False,
|
||||
}
|
||||
|
||||
|
||||
def test_equal_coincidental_penalties_have_no_side_caption():
|
||||
settings = {
|
||||
"strength_regulation_skaters": 5,
|
||||
"strength_min_skaters": 3,
|
||||
"strength_state_labels": {"regulation": {"4x4": {"ru": "4 на 4"}}},
|
||||
}
|
||||
payload = HockeyDataService._strength_payload(
|
||||
settings,
|
||||
stage="regular",
|
||||
current_period="2",
|
||||
timer_state={"penalty_board": {"penalties": [_penalty("home", 100000), _penalty("away", 100000)]}},
|
||||
language="ru",
|
||||
)
|
||||
assert payload["strength_label"] == "4×4"
|
||||
assert payload["advantage_side"] == ""
|
||||
assert payload["home_label"] == ""
|
||||
assert payload["away_label"] == ""
|
||||
|
||||
|
||||
def test_two_vs_one_penalties_caption_only_advantage_team():
|
||||
settings = {
|
||||
"strength_regulation_skaters": 5,
|
||||
"strength_min_skaters": 3,
|
||||
"strength_state_labels": {"regulation": {"4x3": {"ru": "Играют в большинстве"}}},
|
||||
}
|
||||
payload = HockeyDataService._strength_payload(
|
||||
settings,
|
||||
stage="regular",
|
||||
current_period="2",
|
||||
timer_state={"penalty_board": {"penalties": [
|
||||
_penalty("home", 103000),
|
||||
_penalty("home", 120000),
|
||||
_penalty("away", 103000),
|
||||
]}},
|
||||
language="ru",
|
||||
)
|
||||
assert payload["strength_label"] == "3×4"
|
||||
assert payload["advantage_side"] == "away"
|
||||
assert payload["home_label"] == ""
|
||||
assert payload["away_label"] == "Играют в большинстве"
|
||||
|
||||
|
||||
def test_runtime_plan_uses_one_plate_and_global_shortest_transition_timer():
|
||||
start = APP_JS.index("function penaltyDisplayEntriesByTargetSide")
|
||||
end = APP_JS.index("function hockeyPenaltySideMappingDetail", start)
|
||||
block = APP_JS[start:end]
|
||||
assert 'const all = [...home, ...away].sort' in block
|
||||
assert 'const transitionEntry = all[0] || null;' in block
|
||||
assert 'home: advantageSide === "home" && transitionEntry ? [transitionEntry] : []' in block
|
||||
assert 'away: advantageSide === "away" && transitionEntry ? [transitionEntry] : []' in block
|
||||
assert 'if (!advantageSide)' in block
|
||||
assert 'return { home: [], away: [], routedToAdvantage: false' in block
|
||||
|
||||
|
||||
def test_final_full_strength_action_only_runs_after_last_penalty_and_real_advantage():
|
||||
start = APP_JS.index("function fireConfiguredTimerFinishActions")
|
||||
end = APP_JS.index("async function runShortcutSequenceStep", start)
|
||||
block = APP_JS[start:end]
|
||||
assert 'Number(meta.remaining_total || 0) > 0' in block
|
||||
assert '!Boolean(meta.had_advantage)' in block
|
||||
assert 'full_strength_side' in block
|
||||
assert 'side !== fullStrengthSide' in block
|
||||
|
||||
|
||||
def test_rebalance_sends_old_plate_out_before_new_plate_in():
|
||||
start = APP_JS.index("async function rebalanceVmixPenaltyTargets")
|
||||
end = APP_JS.index("function finishActionMatchesSource", start)
|
||||
block = APP_JS[start:end]
|
||||
assert 'const outCommands = [];' in block
|
||||
assert 'const setCommands = [];' in block
|
||||
assert 'const inCommands = [];' in block
|
||||
assert 'const commands = [...outCommands, ...setCommands, ...inCommands];' in block
|
||||
Reference in New Issue
Block a user