BUILD196 — обновлять большинство и составы, задерживать связанные плашки

This commit is contained in:
2026-10-22 11:51:28 +03:00
parent 6491e95143
commit f3018b97c3
31 changed files with 3226 additions and 81 deletions

View File

@@ -34,7 +34,8 @@ function runtime(extra = []) {
runningShortcutSequences:new Set(),pendingShortcutSequenceRuns:new Map(),data:{}};
let allowed = true;
const compact = raw => Object.fromEntries(Object.entries(raw).map(([key,value])=>[key,typeof value==='function'?value():value]));
const context = {console,performance:{now:()=>1000},state,boot:{mode:'runtime'},
const context = {console,performance:{now:()=>1000},state,boot:{mode:'runtime'},setTimeout,clearTimeout,
window:{HockeyMatchAccess:{storage:{getItem:()=> 'account-a'}}},
padTimer:value=>String(value).padStart(2,'0'),clamp:(n,l,h)=>Math.max(l,Math.min(h,n)),
hockeyCanControl:()=>allowed,componentByActionId:id=>id===game.action_id?game:id===boardComponent.action_id?boardComponent:null,
isTimerComponent:c=>c===game,ensureTimerState:()=>main,
@@ -42,7 +43,7 @@ function runtime(extra = []) {
currentHockeyPenaltyEntries:()=>board.penalties.filter(event=>!event.finished && context.hockeyEventReady(event)).map(event=>({component:boardComponent,event,side:event.side})),
sequencePenaltyTargets:(s,side)=>s[side+'_penalty_targets'],
penaltyDisplayEntriesByTargetSide:()=>({home:context.currentHockeyPenaltyEntries(),away:[]}),
rememberPenaltyAdvantagePlan:noop,hockeyScoreboardIsLive:()=>false,
rememberPenaltyAdvantagePlan:noop,vmixInputByRef:()=>null,
emitInteraction:(component,event,detail)=>{events.push({component,event,detail});order.push('event:'+event);},
updateTimerNodes:noop,formatTimerValue:()=>String(main.currentMs),persistTimer:noop,
timerInitialMilliseconds:c=>context.parseTimerMilliseconds(c.props.startTime),
@@ -68,7 +69,11 @@ function runtime(extra = []) {
'configuredHockeyVmixGameCountdownTargets','syncConfiguredScoreboardCountdownsToRuntime',
'emitTimerEvent','controlTimer','runShortcutSequenceStep','updateSingleTimer',
'penaltyMirrorKey','penaltyTargetAssignmentKey','activateConfiguredPenaltyCountdowns',
'rebalanceVmixPenaltyTargets','controlHockeyPenalty','hockeyApplyTimerRules',...extra];
'rebalanceVmixPenaltyTargets','controlHockeyPenalty','hockeyApplyTimerRules',
'hockeyTimerSelectedGameId','normalizeRuntimeVmixInputRef','runtimeOverlayInputRefs','runtimeOverlayMatchesInput','vmixOverlayLayer',
'templateSequenceValue','templateValue','formatValue',
'hockeyTeamStateSequenceStep','hockeyScoreboardPrimaryOverlayTargets','hockeyScoreboardSequenceIsLive','hockeyScoreboardIsLive',
'hockeyScoreboardDelaySeconds','hockeyScoreboardPresentationContext','hockeyObserveScoreboardPresentation','hockeyScoreboardAuxiliaryReady',...extra];
vm.createContext(context);
vm.runInContext([...new Set(names)].map(extract).join('\n'),context);
return {context,game,main,board,boardComponent,step,sequence,target,state,sent,events,order,
@@ -199,6 +204,10 @@ cases.scoreboard_seed = async()=>{
cases.prepared_penalty = async()=>{
const h=runtime();h.step.sync_vmix_penalties=true;h.state.activeHockeyVmixTimerSteps.add(h.step.id);
const penalty={id:'p1',side:'home',durationMs:120000,remainingMs:120000,running:false,startedOnce:false};h.board.penalties.push(penalty);
h.state.data.hockey={selected_game:{external_id:'game-a'}};
h.state.config.shortcut_sequences.push({id:'scoreboard',enabled:true,is_scoreboard_sequence:true,
steps:[{type:'vmix_command',enabled:true,function:'OverlayInput1In',input:'Upper score',condition:'always'}]});
h.state.vmixOverlayRuntime.set('1',{input:'Upper score'}); // Actual upper-score ACK/tally before auxiliary IN.
await h.context.rebalanceVmixPenaltyTargets({scoreboardActive:true});
assert.deepEqual(h.functions(),['SetCountdown','StopCountdown','OverlayInput2In']);
assert.equal(penalty.startedOnce,false);assert.equal(penalty.running,false);