Skip to content

Commit 7818483

Browse files
authored
Merge pull request Sofie-Automation#1612 from tv2norge-collab/contribute/EAV-640
fix(LSG): make current segment timing consider partInstances
2 parents 8c10a53 + b9628ad commit 7818483

3 files changed

Lines changed: 64 additions & 2 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { calculateSegmentTiming } from '../segmentTiming.js'
2+
import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part'
3+
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
4+
import { protectString } from '@sofie-automation/corelib/dist/protectedString'
5+
6+
function makeTestPart(id: string, expectedDuration: number): Partial<DBPart> {
7+
return {
8+
_id: protectString(`part_${id}`),
9+
segmentId: protectString('segment_1'),
10+
rundownId: protectString('rundown_1'),
11+
untimed: false,
12+
expectedDurationWithTransition: expectedDuration,
13+
}
14+
}
15+
16+
function makeTestPartInstance(id: string, partId: string, expectedDuration: number): Partial<DBPartInstance> {
17+
return {
18+
_id: protectString(`partInstance_${id}`),
19+
part: makeTestPart(partId, expectedDuration) as DBPart,
20+
rundownId: protectString('rundown_1'),
21+
segmentId: protectString('segment_1'),
22+
playlistActivationId: protectString('activation_1'),
23+
}
24+
}
25+
26+
describe('segmentTiming - calculateSegmentTiming', () => {
27+
it('should use partInstance duration when available instead of original part duration', () => {
28+
const parts = [makeTestPart('1', 5000), makeTestPart('2', 3000)]
29+
30+
// Create partInstances with modified durations
31+
const partInstances = [makeTestPartInstance('1', '1', 6000), makeTestPartInstance('2', '2', 4000)]
32+
33+
const result = calculateSegmentTiming(undefined, partInstances as DBPartInstance[], parts as DBPart[])
34+
35+
// Should use the modified durations from partInstances (6000 + 4000), not the original (5000 + 3000)
36+
expect(result.expectedDurationMs).toBe(10000)
37+
})
38+
39+
it('should fall back to original part duration when no matching partInstance', () => {
40+
const parts = [makeTestPart('1', 5000), makeTestPart('2', 3000), makeTestPart('3', 2000)]
41+
42+
// Only provide instances for parts 1 and 2, part 3 has no instance
43+
const partInstances = [
44+
makeTestPartInstance('1', '1', 6000), // modified from 5000
45+
makeTestPartInstance('2', '2', 3000), // unchanged
46+
]
47+
48+
const result = calculateSegmentTiming(undefined, partInstances as DBPartInstance[], parts as DBPart[])
49+
50+
// Should use: 6000 (instance) + 3000 (instance) + 2000 (original, no instance)
51+
expect(result.expectedDurationMs).toBe(11000)
52+
})
53+
})

packages/live-status-gateway/src/topics/helpers/segmentTiming.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartIns
44
import { SegmentCountdownType, SegmentTiming } from '@sofie-automation/live-status-gateway-api'
55
import { CountdownType } from '@sofie-automation/blueprints-integration'
66
import { assertNever } from '@sofie-automation/corelib/dist/lib'
7+
import { unprotectString } from '@sofie-automation/server-core-integration'
8+
import * as _ from 'underscore'
79

810
export interface CurrentSegmentTiming extends SegmentTiming {
911
projectedEndTime: number
@@ -16,7 +18,7 @@ export function calculateCurrentSegmentTiming(
1618
segmentPartInstances: DBPartInstance[],
1719
segmentParts: DBPart[]
1820
): CurrentSegmentTiming {
19-
const segmentTiming = calculateSegmentTiming(segmentTimingInfo, segmentParts)
21+
const segmentTiming = calculateSegmentTiming(segmentTimingInfo, segmentPartInstances, segmentParts)
2022
const playedDurations = segmentPartInstances.reduce((sum, partInstance) => {
2123
return (partInstance.timings?.duration ?? 0) + sum
2224
}, 0)
@@ -38,11 +40,18 @@ export function calculateCurrentSegmentTiming(
3840

3941
export function calculateSegmentTiming(
4042
segmentTimingInfo: SegmentTimingInfo | undefined,
43+
segmentPartInstances: DBPartInstance[],
4144
segmentParts: DBPart[]
4245
): SegmentTiming {
46+
// This might be a premature optimization, at least when the number of partInstances is reasonable.
47+
// Should we consider a separate path dependent on the length of the array?
48+
const partInstancesByPartId: Record<string, DBPartInstance> = _.indexBy(segmentPartInstances, (partInstance) =>
49+
unprotectString(partInstance.part._id)
50+
)
4351
return {
4452
budgetDurationMs: segmentTimingInfo?.budgetDuration,
4553
expectedDurationMs: segmentParts.reduce<number>((sum, part): number => {
54+
part = partInstancesByPartId[unprotectString(part._id)]?.part ?? part
4655
return part.expectedDurationWithTransition != null && !part.untimed
4756
? sum + part.expectedDurationWithTransition
4857
: sum

packages/live-status-gateway/src/topics/segmentsTopic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class SegmentsTopic extends WebSocketTopicBase implements WebSocketTopic
4141
id: segmentId,
4242
rundownId: unprotectString(segment.rundownId),
4343
name: segment.name,
44-
timing: calculateSegmentTiming(segment.segmentTiming, this._partsBySegment[segmentId] ?? []),
44+
timing: calculateSegmentTiming(segment.segmentTiming, [], this._partsBySegment[segmentId] ?? []), // TODO: this might be inaccurate for the current/next segment, where partInstances might have some changes from adlib actions etc.
4545
identifier: segment.identifier,
4646
publicData: segment.publicData,
4747
}

0 commit comments

Comments
 (0)