build156
This commit is contained in:
151338
agent/agent.log.1
151338
agent/agent.log.1
File diff suppressed because it is too large
Load Diff
2
app.py
2
app.py
@@ -30,7 +30,7 @@ from ui_builder import install_ui_builder
|
||||
from khl_site.khl_data_center import APP as khl_site_app
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
BUILD_VERSION = "2026.09.23.2"
|
||||
BUILD_VERSION = "2026.09.23.3"
|
||||
# compatibility: BUILD_VERSION = "2026.08.26.1"
|
||||
# compatibility: BUILD_VERSION = "2026.08.25.1"
|
||||
# compatibility: BUILD_VERSION = "2026.08.24.15"
|
||||
|
||||
@@ -101,6 +101,10 @@
|
||||
vmixTimerMirrors: new Map(),
|
||||
vmixPenaltyMirrors: new Map(),
|
||||
activeHockeyVmixTimerSteps: new Set(),
|
||||
// BUILD156: remember which native game-countdown targets have already received
|
||||
// a Runtime value in this browser session. This lets the first Space seed the
|
||||
// current web time exactly once, while later Pause/Resume remains native-only.
|
||||
vmixGameCountdownSeededTargets: new Set(),
|
||||
vmixPenaltyTargetAssignments: new Map(),
|
||||
hockeyPenaltyAdvantageCycle: { hadAdvantage: false, lastAdvantageSide: "" },
|
||||
hockeyPenaltyMappingContextSignature: "",
|
||||
@@ -4198,6 +4202,19 @@ function startCustomTooltips() {
|
||||
return `${padTimer(hours)}:${padTimer(minutes)}:${padTimer(seconds)}`;
|
||||
}
|
||||
|
||||
function vmixGameCountdownTargetKey(input, selectedName) {
|
||||
return `${String(input || "").trim()}\u0000${String(selectedName || "").trim()}`;
|
||||
}
|
||||
|
||||
function markVmixGameCountdownSeeded(input, selectedName) {
|
||||
const key = vmixGameCountdownTargetKey(input, selectedName);
|
||||
if (key !== "\u0000") state.vmixGameCountdownSeededTargets.add(key);
|
||||
}
|
||||
|
||||
function isVmixGameCountdownSeeded(input, selectedName) {
|
||||
return state.vmixGameCountdownSeededTargets.has(vmixGameCountdownTargetKey(input, selectedName));
|
||||
}
|
||||
|
||||
function vmixCountdownSyncCommands(input, selectedName, millisecondsProvider, action = "start") {
|
||||
// BUILD107: Runtime remains the source of truth, but normal operator control no
|
||||
// longer uses StopCountdown because vMix defines it as Stop + Reset.
|
||||
@@ -4926,6 +4943,7 @@ function startCustomTooltips() {
|
||||
commands.push(...vmixGameCountdownControlCommands(input, selectedName, valueProvider, "start"));
|
||||
} else if (eventName === "timer_restart") {
|
||||
commands.push(...vmixGameCountdownControlCommands(input, selectedName, valueProvider, "set"));
|
||||
markVmixGameCountdownSeeded(input, selectedName);
|
||||
commands.push(...vmixGameCountdownControlCommands(input, selectedName, valueProvider, "start"));
|
||||
} else if (eventName === "timer_pause") {
|
||||
commands.push(...vmixGameCountdownControlCommands(input, selectedName, valueProvider, "pause"));
|
||||
@@ -4933,6 +4951,7 @@ function startCustomTooltips() {
|
||||
commands.push(...vmixGameCountdownControlCommands(input, selectedName, valueProvider, "stop"));
|
||||
} else if (["timer_reset", "timer_set_time", "timer_add_time", "timer_subtract_time"].includes(eventName)) {
|
||||
commands.push(...vmixGameCountdownControlCommands(input, selectedName, valueProvider, "set"));
|
||||
markVmixGameCountdownSeeded(input, selectedName);
|
||||
}
|
||||
}
|
||||
if (!commands.length) return false;
|
||||
@@ -4971,6 +4990,7 @@ function startCustomTooltips() {
|
||||
commands.push(...vmixGameCountdownControlCommands(
|
||||
input, selectedName, () => timerState.currentMs, "set"
|
||||
));
|
||||
markVmixGameCountdownSeeded(input, selectedName);
|
||||
}
|
||||
});
|
||||
if (!commands.length) return { ok: true, applied: 0, requested: 0 };
|
||||
@@ -5508,8 +5528,16 @@ function startCustomTooltips() {
|
||||
step.game_vmix_input, step.game_vmix_selected_name, () => gameTimerState.currentMs, "pause"
|
||||
));
|
||||
} else {
|
||||
// BUILD108 Space start/resume: native start only. The countdown was seeded
|
||||
// when the operator set/reset the period time (or by F1 before first start).
|
||||
// BUILD156: the first Start for this exact Input + SelectedName must also
|
||||
// transfer the current Runtime value. This fixes a fresh vMix title where
|
||||
// StartCountdown arrived but the configured web time never did. After the
|
||||
// target is seeded, normal Resume is StartCountdown-only (BUILD108 rule).
|
||||
if (!isVmixGameCountdownSeeded(step.game_vmix_input, step.game_vmix_selected_name)) {
|
||||
commands.push(...vmixGameCountdownControlCommands(
|
||||
step.game_vmix_input, step.game_vmix_selected_name, () => gameTimerState.currentMs, "set"
|
||||
));
|
||||
markVmixGameCountdownSeeded(step.game_vmix_input, step.game_vmix_selected_name);
|
||||
}
|
||||
commands.push(...vmixGameCountdownControlCommands(
|
||||
step.game_vmix_input, step.game_vmix_selected_name, () => gameTimerState.currentMs, "start"
|
||||
));
|
||||
@@ -14718,7 +14746,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>Countdown vMix</b>: время передаётся в vMix только при явной установке/сбросе (например, 20:00 или 05:00). После этого Space не синхронизирует значение: Start/Resume отправляет только <code>StartCountdown</code>, Pause/Stop — только <code>PauseCountdown</code>. Это исключает скачки времени при паузе. <code>StopCountdown</code> в обычном управлении не используется. Команды идут в Agent без ACK. <b>Text mirror</b> оставлен только для совместимости со старыми титрами. Для верхнего счёта используется одна penalty-плашка: при реальном большинстве она показывает ближайшее изменение численного состава; при чистом равном обоюдном удалении сама по себе не появляется.</p>
|
||||
<p class="shortcut-step-note">Режим <b>Countdown vMix</b>: при первом Start для выбранного Input + SelectedName текущее веб-время один раз передаётся через <code>ChangeCountdown</code>, затем отправляется <code>StartCountdown</code>. После этого Space не пересылает значение: Resume отправляет только <code>StartCountdown</code>, Pause/Stop — только <code>PauseCountdown</code>. Явная установка/сброс времени также обновляет vMix через <code>ChangeCountdown</code>. Это исключает скачки времени при паузе. <code>StopCountdown</code> в обычном управлении не используется. Команды идут в Agent без ACK. <b>Text mirror</b> оставлен только для совместимости со старыми титрами. Для верхнего счёта используется одна penalty-плашка: при реальном большинстве она показывает ближайшее изменение численного состава; при чистом равном обоюдном удалении сама по себе не появляется.</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