идентификаторы удалений из вкладки Игра
This commit is contained in:
@@ -83,6 +83,9 @@
|
||||
vmixPenaltyMirrors: new Map(),
|
||||
activeHockeyVmixTimerSteps: new Set(),
|
||||
vmixPenaltyTargetAssignments: new Map(),
|
||||
hockeyPenaltyMappingContextSignature: "",
|
||||
hockeyPenaltyMappingContextPending: false,
|
||||
hockeyPenaltyMappingContextQueued: false,
|
||||
vmixFinishOverlayTimers: new Map(),
|
||||
vmixStrengthMappingRefreshPending: false,
|
||||
vmixStrengthMappingRefreshQueued: null,
|
||||
@@ -4493,6 +4496,84 @@ function startCustomTooltips() {
|
||||
|| Number(a.event.createdAt || 0) - Number(b.event.createdAt || 0));
|
||||
}
|
||||
|
||||
function hockeyPenaltySideMappingDetail(item, side) {
|
||||
if (!item?.event) return null;
|
||||
const event = item.event;
|
||||
const playerIds = hockeyPenaltyPlayerIdentifiers(item.component, event);
|
||||
return {
|
||||
penalty_id: String(event.external_id || event.id || ""),
|
||||
player_id: String(playerIds.externalId || ""),
|
||||
player_db_id: String(playerIds.dbId || ""),
|
||||
team_penalty: Boolean(event.teamPenalty),
|
||||
side: String(side || event.player?.side || event.side || ""),
|
||||
};
|
||||
}
|
||||
|
||||
async function hockeySyncPenaltySideMappingContext({ force = false } = {}) {
|
||||
const gameId = String(hockeyTimerSelectedGameId() || "").trim();
|
||||
if (!gameId) return false;
|
||||
|
||||
const home = hockeyPenaltySideMappingDetail(sortedPenaltyEntries("home")[0] || null, "home");
|
||||
const away = hockeyPenaltySideMappingDetail(sortedPenaltyEntries("away")[0] || null, "away");
|
||||
const values = {
|
||||
selected_home_penalty_id: home?.penalty_id || "",
|
||||
selected_home_penalty_player_id: home?.player_id || "",
|
||||
selected_home_penalty_player_db_id: home?.player_db_id || "",
|
||||
selected_home_penalty_team_penalty: home ? (home.team_penalty ? "1" : "0") : "",
|
||||
selected_away_penalty_id: away?.penalty_id || "",
|
||||
selected_away_penalty_player_id: away?.player_id || "",
|
||||
selected_away_penalty_player_db_id: away?.player_db_id || "",
|
||||
selected_away_penalty_team_penalty: away ? (away.team_penalty ? "1" : "0") : "",
|
||||
};
|
||||
const signature = JSON.stringify([gameId, values]);
|
||||
if (!force && signature === state.hockeyPenaltyMappingContextSignature) return false;
|
||||
|
||||
if (state.hockeyPenaltyMappingContextPending) {
|
||||
state.hockeyPenaltyMappingContextQueued = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
state.hockeyPenaltyMappingContextPending = true;
|
||||
try {
|
||||
const response = await fetch("/api/hockey/context/batch", {
|
||||
method: "POST", cache: "no-store", credentials: "same-origin",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
values,
|
||||
context: {
|
||||
game_id: gameId,
|
||||
device_id: currentRuntimeVmixDeviceId(),
|
||||
session_token: currentRuntimeHockeySessionToken(),
|
||||
},
|
||||
}),
|
||||
});
|
||||
let payload = {};
|
||||
try { payload = await response.json(); } catch (_) {}
|
||||
if (!response.ok) {
|
||||
throw new Error(errorDetailText(payload.detail, `HTTP ${response.status}`));
|
||||
}
|
||||
state.hockeyPenaltyMappingContextSignature = signature;
|
||||
window.UIBuilderRuntime?.patchData?.({
|
||||
hockey: {
|
||||
active_penalties: { home, away },
|
||||
},
|
||||
}, { render: false });
|
||||
window.dispatchEvent(new CustomEvent("hockey:mapping-context-updated", {
|
||||
detail: { game_id: gameId, values: clone(values) },
|
||||
}));
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Penalty side Mapping context error", error);
|
||||
return false;
|
||||
} finally {
|
||||
state.hockeyPenaltyMappingContextPending = false;
|
||||
if (state.hockeyPenaltyMappingContextQueued) {
|
||||
state.hockeyPenaltyMappingContextQueued = false;
|
||||
hockeySyncPenaltySideMappingContext({ force: true }).catch(() => {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function penaltyTargetAssignmentKey(step, side, target) {
|
||||
return `${String(step?.id || "")}:${side}:${String(target?.id || "")}`;
|
||||
}
|
||||
@@ -6211,6 +6292,7 @@ function openTimerQuickEditor(focusActionId = "") {
|
||||
if (hockeyEventReady(event) && state.activeHockeyVmixTimerSteps.size) {
|
||||
rebalanceVmixPenaltyTargets({ force: true, hideUnused: false }).catch((error) => console.error("Penalty target rebalance error", error));
|
||||
}
|
||||
hockeySyncPenaltySideMappingContext().catch(() => {});
|
||||
}
|
||||
|
||||
function createHockeyPenaltyDraft(component, seed = {}, source = "manual") {
|
||||
@@ -6492,6 +6574,7 @@ function openTimerQuickEditor(focusActionId = "") {
|
||||
if (board.selectedPreviewEventIds?.[side] === event.id) board.selectedPreviewEventIds[side] = "";
|
||||
persistHockeyBoard(component, board, true);
|
||||
refreshHockeyBoardNodes(component);
|
||||
hockeySyncPenaltySideMappingContext({ force: true }).catch(() => {});
|
||||
rebalanceVmixPenaltyTargets({ force: true, hideUnused: true })
|
||||
.catch((error) => console.error("Penalty target finish rebalance error", error))
|
||||
.finally(() => fireConfiguredTimerFinishActions("penalty", { side, component, event, remaining_on_side: remainingOnSide }));
|
||||
@@ -6526,6 +6609,7 @@ function openTimerQuickEditor(focusActionId = "") {
|
||||
...hockeyPenaltyContext(event)
|
||||
});
|
||||
state.vmixPenaltyMirrors.delete(penaltyMirrorKey(component, event));
|
||||
hockeySyncPenaltySideMappingContext({ force: true }).catch(() => {});
|
||||
rebalanceVmixPenaltyTargets({ force: true, hideUnused: true }).catch((error) => console.error("Penalty target remove rebalance error", error));
|
||||
return true;
|
||||
}
|
||||
@@ -6620,6 +6704,7 @@ function openTimerQuickEditor(focusActionId = "") {
|
||||
if (completed.has(board.selectedEventId)) board.selectedEventId = null;
|
||||
persistHockeyBoard(component, board, true);
|
||||
refreshHockeyBoardNodes(component);
|
||||
hockeySyncPenaltySideMappingContext({ force: true }).catch(() => {});
|
||||
const finishBySide = new Map();
|
||||
completedEvents.forEach((event) => {
|
||||
const side = String(event.player?.side || event.side || "").toLowerCase();
|
||||
@@ -10129,8 +10214,12 @@ function renderHockeyPenaltyDashboard(node, component, runtime) {
|
||||
|
||||
function hockeyCompactPlayer(player) {
|
||||
if (!player || typeof player !== "object") return null;
|
||||
const externalId = String(player.externalId || player.external_id || player.id || player.raw?.external_id || player.raw?.id || "");
|
||||
const dbId = String(player.dbId || player.db_id || player.database_id || player.raw?.db_id || player.raw?.database_id || "");
|
||||
return {
|
||||
id: String(player.id || ""),
|
||||
id: externalId,
|
||||
externalId,
|
||||
dbId,
|
||||
side: player.side === "away" ? "away" : player.side === "home" ? "home" : "",
|
||||
number: String(player.number || ""),
|
||||
name: String(player.name || ""),
|
||||
@@ -10254,6 +10343,8 @@ function renderHockeyPenaltyDashboard(node, component, runtime) {
|
||||
refreshHockeyBoardNodes(boardComponent);
|
||||
}
|
||||
state.hockeyTimerGameId = String(gameId || "");
|
||||
state.hockeyPenaltyMappingContextSignature = "";
|
||||
hockeySyncPenaltySideMappingContext({ force: true }).catch(() => {});
|
||||
}
|
||||
|
||||
async function hockeyPersistGameTimers(gameId, { keepalive = false, force = false } = {}) {
|
||||
|
||||
Reference in New Issue
Block a user