поправлены сложные удаления
This commit is contained in:
@@ -4635,42 +4635,35 @@ function startCustomTooltips() {
|
||||
|| Number(a.event.createdAt || 0) - Number(b.event.createdAt || 0));
|
||||
}
|
||||
|
||||
// BUILD85: HOME/AWAY penalty targets describe the TEAM THAT HAS THE NUMERICAL
|
||||
// ADVANTAGE, not the bench that committed the penalty. This matters not only
|
||||
// for a normal 5x4/5x3 power play, but also for 4x3 and 3x4 when both benches
|
||||
// still have active penalties. The authoritative advantage_side is calculated
|
||||
// by the hockey strength engine. When strength is equal (4x4 / 3x3), keep the
|
||||
// traditional one-per-side coincidental display. If the strength payload has
|
||||
// not arrived yet, the single-penalty fallback still routes to the opposite
|
||||
// target exactly as BUILD83 did.
|
||||
// BUILD88: complex/coincidental penalties must not immediately switch the
|
||||
// scorebug extension into a power-play side merely because the raw skater
|
||||
// count is 4x3/3x4. While both benches still have active penalties, keep one
|
||||
// penalty on each team's own target. Only after one bench becomes completely
|
||||
// clear does the remaining penalty move to the opposite target (the team that
|
||||
// is now actually shown as playing on the power play). If both benches clear
|
||||
// together, the plan is empty and both extra plates are removed.
|
||||
function penaltyDisplayEntriesByTargetSide(step) {
|
||||
const home = sortedPenaltyEntries("home");
|
||||
const away = sortedPenaltyEntries("away");
|
||||
const soonestOnly = String(step?.penalty_display_mode || "soonest") !== "all";
|
||||
const strength = getByPath(state.data, "hockey.game_control.strength") || {};
|
||||
const advantageSide = String(strength.advantage_side || "").trim().toLowerCase();
|
||||
const take = (items) => soonestOnly ? items.slice(0, 1) : items;
|
||||
|
||||
if (advantageSide === "home") {
|
||||
// HOME has more skaters, therefore an AWAY penalty controls the PP clock.
|
||||
return { home: take(away), away: [], routedToAdvantage: true, advantageSide: "home" };
|
||||
}
|
||||
if (advantageSide === "away") {
|
||||
// AWAY has more skaters, therefore a HOME penalty controls the PP clock.
|
||||
return { home: [], away: take(home), routedToAdvantage: true, advantageSide: "away" };
|
||||
}
|
||||
|
||||
// Complex/coincidental state: do not announce a power-play side yet.
|
||||
if (home.length && away.length) {
|
||||
return { home: take(home), away: take(away), routedToAdvantage: false, advantageSide: "" };
|
||||
}
|
||||
|
||||
// Only HOME still has a penalty -> AWAY is the displayed PP side.
|
||||
if (home.length) {
|
||||
if (soonestOnly) return { home: [], away: home.slice(0, 1), routedToAdvantage: true };
|
||||
return { home: [], away: home, routedToAdvantage: true, advantageSide: "away" };
|
||||
return { home: [], away: take(home), routedToAdvantage: true, advantageSide: "away" };
|
||||
}
|
||||
|
||||
// Only AWAY still has a penalty -> HOME is the displayed PP side.
|
||||
if (away.length) {
|
||||
if (soonestOnly) return { home: away.slice(0, 1), away: [], routedToAdvantage: true };
|
||||
return { home: away, away: [], routedToAdvantage: true, advantageSide: "home" };
|
||||
return { home: take(away), away: [], routedToAdvantage: true, advantageSide: "home" };
|
||||
}
|
||||
|
||||
// Both sides cleared at the same tick: show nothing.
|
||||
return { home: [], away: [], routedToAdvantage: false, advantageSide: "" };
|
||||
}
|
||||
|
||||
@@ -11136,12 +11129,10 @@ function renderHockeyPenaltyDashboard(node, component, runtime) {
|
||||
|| hockeyStrengthMappingSignature(previousControl) !== hockeyStrengthMappingSignature(payload);
|
||||
if (strengthChanged) {
|
||||
hockeyRefreshVmixMappingForStrength(gameId, previousControl, payload).catch(() => {});
|
||||
// BUILD87: penalty routing depends on the recalculated numerical strength.
|
||||
// The local penalty editor can rebalance a few milliseconds before the
|
||||
// timer save response arrives, while state.data still contains the old
|
||||
// 4x4/5x5 strength. Re-run the routing as soon as the authoritative
|
||||
// control payload is stored so 2 penalties vs 1 immediately becomes
|
||||
// 3x4/4x3 and the plate moves to the team with the advantage.
|
||||
// BUILD88: keep a second rebalance after the authoritative control payload
|
||||
// arrives. The display plan itself intentionally keeps HOME/AWAY on their
|
||||
// own sides while both benches have active penalties; once one bench clears,
|
||||
// this refresh moves the remaining timer to the actual power-play side.
|
||||
if (state.activeHockeyVmixTimerSteps.size) {
|
||||
rebalanceVmixPenaltyTargets({ force: true, hideUnused: true })
|
||||
.catch((error) => console.error("Penalty strength rebalance error", error));
|
||||
@@ -13288,7 +13279,7 @@ function renderHockeyPenaltyDashboard(node, component, runtime) {
|
||||
<div class="shortcut-finish-action-list">${timerFinishActionRows(step)}</div>
|
||||
|
||||
<div class="shortcut-vmix-inventory-note"><span>${escapeHtml(shortcutInventoryLabel())}</span><small>Для каждого countdown теперь обязательно выбирается конкретный Text / SelectedName. Это исключает отправку времени в первый текстовый элемент по умолчанию.</small></div>
|
||||
<p class="shortcut-step-note">Режим <b>Text mirror</b> рекомендуется: веб-таймер является источником истины и раз в секунду отправляет <code>SetText</code> строго в выбранные <code>Input + SelectedName</code>. Режим <b>Countdown</b> оставлен для титров, где countdown уже настроен внутри vMix. Для верхнего счёта по умолчанию используется одно ближайшее к окончанию удаление. Пока удаления есть у обеих команд, HOME/AWAY показываются по своим сторонам. Когда штраф остаётся только у одной команды, его таймер автоматически переезжает на Input противоположной команды — стороны большинства. Режим «Все удаления по слотам» оставлен как дополнительный. Действие по окончании показывает выбранный Input в заданном Overlay и автоматически убирает его через указанное время.</p>
|
||||
<p class="shortcut-step-note">Режим <b>Text mirror</b> рекомендуется: веб-таймер является источником истины и раз в секунду отправляет <code>SetText</code> строго в выбранные <code>Input + SelectedName</code>. Режим <b>Countdown</b> оставлен для титров, где countdown уже настроен внутри vMix. Для верхнего счёта по умолчанию используется одно ближайшее к окончанию удаление. При сложных/обоюдных удалениях, пока штрафы есть у обеих команд, HOME/AWAY остаются на своих сторонах и режим «играют в большинстве» не включается. Только когда одна сторона полностью очистится, оставшийся таймер переезжает на Input противоположной команды — стороны большинства. Если обе стороны очистились одновременно, дополнительные плашки просто снимаются. Режим «Все удаления по слотам» оставлен как дополнительный. Действие по окончании показывает выбранный Input в заданном Overlay и автоматически убирает его через указанное время.</p>
|
||||
</div>`;
|
||||
} else if (step.type === "delay") {
|
||||
body.innerHTML = `<div class="shortcut-step-grid"><label>Задержка, мс<input type="number" min="0" max="10000" step="10" data-step-field="milliseconds" value="${Number(step.milliseconds) || 0}"></label></div>`;
|
||||
|
||||
Reference in New Issue
Block a user