1
- import type { RundownId , PartId } from '@sofie-automation/corelib/dist/dataModel/Ids'
1
+ import type { RundownId } from '@sofie-automation/corelib/dist/dataModel/Ids'
2
2
import { NrcsIngestCacheType } from '@sofie-automation/corelib/dist/dataModel/NrcsIngestDataCache'
3
- import type { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
4
3
import {
5
4
IngestRundownStatus ,
6
5
IngestPartPlaybackStatus ,
7
6
IngestRundownActiveStatus ,
8
7
IngestPartStatus ,
8
+ IngestPartNotifyItemReady ,
9
9
} from '@sofie-automation/shared-lib/dist/ingest/rundownStatus'
10
10
import type { ReadonlyDeep } from 'type-fest'
11
11
import _ from 'underscore'
@@ -15,6 +15,7 @@ import { ReactiveCacheCollection } from '../lib/ReactiveCacheCollection'
15
15
import { PartInstance } from '@sofie-automation/meteor-lib/dist/collections/PartInstances'
16
16
import { IngestPart } from '@sofie-automation/blueprints-integration'
17
17
import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part'
18
+ import { unprotectString } from '@sofie-automation/corelib/dist/protectedString'
18
19
19
20
export function createIngestRundownStatus (
20
21
cache : ReadonlyDeep < ContentCache > ,
@@ -41,9 +42,6 @@ export function createIngestRundownStatus(
41
42
newDoc . active = playlist . rehearsal ? IngestRundownActiveStatus . REHEARSAL : IngestRundownActiveStatus . ACTIVE
42
43
}
43
44
44
- // Find the most important part instance for each part
45
- const partInstanceMap = findPartInstanceForEachPart ( playlist , rundownId , cache . PartInstances )
46
-
47
45
const nrcsSegments = cache . NrcsIngestData . find ( { rundownId, type : NrcsIngestCacheType . SEGMENT } ) . fetch ( )
48
46
for ( const nrcsSegment of nrcsSegments ) {
49
47
const nrcsParts = cache . NrcsIngestData . find ( {
@@ -58,10 +56,25 @@ export function createIngestRundownStatus(
58
56
nrcsParts . map ( ( nrcsPart ) => {
59
57
if ( ! nrcsPart . partId || ! nrcsPart . segmentId ) return null
60
58
61
- const part = cache . Parts . findOne ( { _id : nrcsPart . partId , rundownId } )
62
- const partInstance = partInstanceMap . get ( nrcsPart . partId )
63
-
64
- return createIngestPartStatus ( playlist , partInstance , part , nrcsPart . data as IngestPart )
59
+ const parts = cache . Parts . find ( {
60
+ rundownId : rundownId ,
61
+ $or : [
62
+ {
63
+ externalId : nrcsPart . data . externalId ,
64
+ } ,
65
+ {
66
+ ingestNotifyPartExternalId : nrcsPart . data . externalId ,
67
+ } ,
68
+ ] ,
69
+ } ) . fetch ( )
70
+ const partInstances = findPartInstancesForIngestPart (
71
+ playlist ,
72
+ rundownId ,
73
+ cache . PartInstances ,
74
+ nrcsPart . data . externalId
75
+ )
76
+
77
+ return createIngestPartStatus ( playlist , partInstances , parts , nrcsPart . data as IngestPart )
65
78
} )
66
79
) ,
67
80
} )
@@ -70,64 +83,110 @@ export function createIngestRundownStatus(
70
83
return newDoc
71
84
}
72
85
73
- function findPartInstanceForEachPart (
86
+ function findPartInstancesForIngestPart (
74
87
playlist : Pick < DBRundownPlaylist , PlaylistFields > | undefined ,
75
88
rundownId : RundownId ,
76
- partInstancesCache : ReadonlyDeep < ReactiveCacheCollection < Pick < PartInstance , PartInstanceFields > > >
89
+ partInstancesCache : ReadonlyDeep < ReactiveCacheCollection < Pick < PartInstance , PartInstanceFields > > > ,
90
+ partExternalId : string
77
91
) {
78
- const partInstanceMap = new Map < PartId , Pick < DBPartInstance , PartInstanceFields > > ( )
79
- if ( ! playlist ) return partInstanceMap
92
+ const result : Record < string , Pick < PartInstance , PartInstanceFields > > = { }
93
+ if ( ! playlist ) return result
94
+
95
+ const candidatePartInstances = partInstancesCache
96
+ . find ( {
97
+ rundownId : rundownId ,
98
+ $or : [
99
+ {
100
+ 'part.externalId' : partExternalId ,
101
+ } ,
102
+ {
103
+ 'part.ingestNotifyPartExternalId' : partExternalId ,
104
+ } ,
105
+ ] ,
106
+ } )
107
+ . fetch ( )
80
108
81
- for ( const partInstance of partInstancesCache . find ( { } ) . fetch ( ) ) {
109
+ for ( const partInstance of candidatePartInstances ) {
82
110
if ( partInstance . rundownId !== rundownId ) continue
83
111
// Ignore the next partinstance
84
112
if ( partInstance . _id === playlist . nextPartInfo ?. partInstanceId ) continue
85
113
114
+ const partId = unprotectString ( partInstance . part . _id )
115
+
86
116
// The current part instance is the most important
87
117
if ( partInstance . _id === playlist . currentPartInfo ?. partInstanceId ) {
88
- partInstanceMap . set ( partInstance . part . _id , partInstance )
118
+ result [ partId ] = partInstance
89
119
continue
90
120
}
91
121
92
122
// Take the part with the highest takeCount
93
- const existingEntry = partInstanceMap . get ( partInstance . part . _id )
123
+ const existingEntry = result [ partId ]
94
124
if ( ! existingEntry || existingEntry . takeCount < partInstance . takeCount ) {
95
- partInstanceMap . set ( partInstance . part . _id , partInstance )
125
+ result [ partId ] = partInstance
96
126
}
97
127
}
98
128
99
- return partInstanceMap
129
+ return result
100
130
}
101
131
102
132
function createIngestPartStatus (
103
133
playlist : Pick < DBRundownPlaylist , PlaylistFields > | undefined ,
104
- partInstance : Pick < PartInstance , PartInstanceFields > | undefined ,
105
- part : Pick < DBPart , PartFields > | undefined ,
134
+ partInstances : Record < string , Pick < PartInstance , PartInstanceFields > > ,
135
+ parts : Pick < DBPart , PartFields > [ ] ,
106
136
ingestPart : IngestPart
107
137
) : IngestPartStatus {
108
138
// Determine the playback status from the PartInstance
109
139
let playbackStatus = IngestPartPlaybackStatus . UNKNOWN
110
- if ( playlist && partInstance && partInstance . part . shouldNotifyCurrentPlayingPart ) {
111
- const isCurrentPartInstance = playlist . currentPartInfo ?. partInstanceId === partInstance . _id
112
-
113
- if ( isCurrentPartInstance ) {
114
- // If the current, it is playing
115
- playbackStatus = IngestPartPlaybackStatus . PLAY
116
- } else {
117
- // If not the current, but has been played, it is stopped
118
- playbackStatus = IngestPartPlaybackStatus . STOP
140
+
141
+ let isReady : boolean | null = null // Start off as null, the first value will make this true or false
142
+
143
+ const itemsReady : IngestPartNotifyItemReady [ ] = [ ]
144
+
145
+ const updateStatusWithPart = ( part : Pick < DBPart , PartFields > ) => {
146
+ // If the part affects the ready status, update it
147
+ if ( typeof part . ingestNotifyPartReady === 'boolean' ) {
148
+ isReady = ( isReady ?? true ) && part . ingestNotifyPartReady
149
+ }
150
+
151
+ // Include the items
152
+ if ( part . ingestNotifyItemsReady ) {
153
+ itemsReady . push ( ...part . ingestNotifyItemsReady )
119
154
}
120
155
}
121
156
122
- // Determine the ready status from the PartInstance or Part
123
- const isReady = partInstance ? partInstance . part . ingestNotifyPartReady : part ?. ingestNotifyPartReady
124
- const itemsReady = partInstance ? partInstance . part . ingestNotifyItemsReady : part ?. ingestNotifyItemsReady
157
+ // Loop through the partInstances, starting off the state
158
+ if ( playlist ) {
159
+ for ( const partInstance of Object . values < Pick < PartInstance , PartInstanceFields > > ( partInstances ) ) {
160
+ if ( ! partInstance ) continue
161
+
162
+ if ( partInstance . part . shouldNotifyCurrentPlayingPart ) {
163
+ const isCurrentPartInstance = playlist . currentPartInfo ?. partInstanceId === partInstance . _id
164
+
165
+ if ( isCurrentPartInstance ) {
166
+ // If the current, it is playing
167
+ playbackStatus = IngestPartPlaybackStatus . PLAY
168
+ } else if ( playbackStatus === IngestPartPlaybackStatus . UNKNOWN ) {
169
+ // If not the current, but has been played, it is stopped
170
+ playbackStatus = IngestPartPlaybackStatus . STOP
171
+ }
172
+ }
173
+
174
+ updateStatusWithPart ( partInstance . part )
175
+ }
176
+ }
177
+
178
+ for ( const part of parts ) {
179
+ // Check if the part has already been handled by a partInstance
180
+ if ( partInstances [ unprotectString ( part . _id ) ] ) continue
181
+
182
+ updateStatusWithPart ( part )
183
+ }
125
184
126
185
return {
127
186
externalId : ingestPart . externalId ,
128
187
129
- isReady : isReady ?? null ,
130
- itemsReady : itemsReady ?? [ ] ,
188
+ isReady : isReady ,
189
+ itemsReady : itemsReady ,
131
190
132
191
playbackStatus,
133
192
}
0 commit comments