-
Notifications
You must be signed in to change notification settings - Fork 0
/
modules.txt
297 lines (247 loc) · 8.66 KB
/
modules.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
(blueshirt commands are sent over a channel called BLUESHIRTS)
STATE CONTROLLER
EVENT real time clock pulse:
transmit HEARTBEAT(real-time, competition-time) on channel HEARTBEAT
compute current match and match state
if current match differs from match.current:
match.schedule.[match.current].state <- COMPLETED
match.schedule.[match].state <- IN-PROGRESS iff match is not NULL
match.current <- match
if current match became non-NULL and comp.state.global == DOWNTIME:
broadcast_state <- true
comp.state.global <- MATCH
elif current match became NULL and comp.state.global == MATCH:
broadcast_state <- true
comp.state.global <- MATCH
if match state differs from previous or broadcast_state:
comp.state.match <- new_state
transmit STATE(comp.state.global, comp.state.match) on channel STATE
if comp.pause != NULL
transmit OFFSET-SHIFT on channel HEARTBEAT
EVENT panic:
comp.pause <- current competition time
comp.state.global <- FAIL
transmit STATE(comp.state.global, comp.state.match) on channel STATE
EVENT panic-over:
comp.sync[] <- (current_real_time, comp.pause)
comp.pause <- NULL
if match.current is not NULL:
comp.state.global <- MATCH
else:
comp.state.global <- DOWNTIME
transmit STATE(comp.state.global, comp.state.match) on channel STATE
EVENT pause:
comp.pause <- current competition time
EVENT unpause:
comp.sync[] <- (current_real_time, comp.pause)
comp.pause <- NULL
EVENT competition-start:
comp.sync = [(current_real_time, 0)]
comp.state.global <- DOWNTIME
transmit 'trigger' on channel comp.kickoff
transmit comp.state.global, comp.state.match on channel comp.state
transmit current_real_time, 0 on channel comp.heartbeat
transmit 'trigger' on channel comp.offset_shift
EVENT delay-matches(match, amount):
if match is live or in the past:
deny
delay existing matches from match onwards by amount until the nearest break (of more than 1 minute)
transmit RECOMPUTE on channel SCHEDULE
EVENT schedule-match(match):
if match would be live or in the past:
deny
find earliest existing match overlapped by match and issue delay-matches(existing match, 390)
add match into schedule
transmit 'trigger' on channel match.reschedule
EVENT cancel-match(match):
if match is in the past:
deny
remove match from schedule
if match was current:
match.current <- NULL
comp.state.global <- DOWNTIME
transmit (comp.state.global, comp.state.match) on channel comp.state
else:
find next match
issue delay-matches(next, -390)
transmit 'trigger' on channel match.reschedule
EVENT add-team(team):
teams.roster[] <- team
transmit 'new' on channel teams.[team.tla]
EVENT update-team(team):
teams.roster[team.tla] <- team
transmit 'updated' on channel teams.[team.tla]
EVENT remove-team(tla):
for each match containing team:
issue cancel-match(match)
del teams.roster[team.tla]
transmit 'gone' on channel teams.[tla]
--
ARENA CONTROLLER
table permit-entry(global-state, match-state, tinker):
+----------+--------+-------+-------------+
| FAIL | x | x | HARD-CLOSED |
| DOWNTIME | x | TRUE | OPEN |
| DOWNTIME | x | FALSE | SOFT-CLOSED |
| MATCH | ENTER | x | OPEN |
| MATCH | BOOT | x | SOFT-CLOSED |
| MATCH | LIVE | x | HARD-CLOSED |
| MATCH | SETTLE | x | SOFT-CLOSED |
+----------+--------+-------+-------------+
RECEIVE STATE(global, match) on channel STATE:
enterable <- look up permit-entry(global, match, comp.state.tinker)
if enterable != comp.state.arena:
comp.state.arena <- enterable
transmit enterable on channel comp.arena
if match == LIVE:
initialise scores
transmit [0, 0, 0, 0], [0, 0, 0, 0] on channel match.current.scores
if match == SETTLE:
compute final scores
transmit final-scores, NULL on channel match.current.scores
EVENT enter-tinker-mode:
comp.state.tinker <- TRUE
enterable <- look up permit-entry(global, match, comp.state.tinker)
if enterable != comp.state.arena:
comp.state.arena <- enterable
transmit enterable on channel comp.arena
EVENT enter-briefing-mode:
comp.state.tinker <- FALSE
enterable <- look up permit-entry(global, match, comp.state.tinker)
if enterable != comp.state.arena:
comp.state.arena <- enterable
transmit enterable on channel comp.arena
EVENT record-game-event(event):
if comp.state.global is not MATCH:
deny
if comp.state.match is not in (MATCH, SETTLE):
deny
matches[match.current].events[] <- event
transmit event on channel match.current.events
update score prediction and current
transmit current-scores, predicted-scores on channel match.current.scores
--
MUSIC CONTROLLER
EVENT add-new-song(song):
issue add-song-to-playlist(song, 'all')
EVENT add-song-to-playlist(song, playlist):
music.playlist.[playlist][] <- (song, rand[0..1])
EVENT remove-song-from-playlist(song, playlists):
remove song from music.playlist.[playlist]
EVENT music-finished:
issue next-track
EVENT stop-music:
stop currently playing music
table music-actions(global, match):
+----------+--------+-------+
| FAIL | x | STOP |
| DOWNTIME | x | START |
| MATCH | ENTER | START |
| MATCH | BOOT | x |
| MATCH | LIVE | START |
| MATCH | SETTLE | x |
+----------+--------+-------+
RECEIVE STATE(global-state, match-state) on channel STATE:
look up music-actions(global-state, match-state):
issue either stop-music or next-track. possibly.
EVENT next-track:
pick a song meeting the current state
play that bastard
music.history[] = (real_time, uri)
--
SCREEN CONTROLLER (runs a miniature httpd to which the screens can connect)
EVENT add-screen(id, flavour, zone=null):
screens.[id].flavour <- flavour
screens.[id].zone <- zone
issue refresh-screen(id)
EVENT remove-screen(id)
del screens.[id].flavour
del screens.[id].zone
del screens.[id].override
EVENT refresh-screen(id)
compute CONTENT(id) and send to screen id
EVENT update-screen(id)
compute UPDATE(id)
if not null:
send to screen id
RECEIVE STATE(_, _) on channel STATE:
for each screen:
refresh-screen(id)
RECEIVE HEARTBEAT(_, _) on channel HEARTBEAT:
for each screen in flavour (CLOCK, ZONE, JUDGE):
issue update-screen(id)
RECEIVE OFFSET-SHIFT on channel HEARTBEAT:
if time mod 15 == 0:
for each screen in flavour (JUDGE, MATCH-INFO):
issue refresh-screen(id)
RECEIVE RECOMPUTE on channel SCHEDULE:
for each screen in flavour (LAYOUT, JUDGE, MATCH-INFO):
issue refresh-screen(id)
RECEIVE UPDATE(tla) on channel TEAMS:
for each screen in flavour (LAYOUT, ZONE, JUDGE, MATCH-INFO):
issue refresh-screen(id)
EVENT override-screen(id, message):
screens.override[id] <- message
issue refresh-screen(id)
EVENT cancel-override-screen(id):
del screens.override[id]
issue refresh-screen(id)
computation of CONTENT(id):
# specifics ignored, but here's a rough table, ignoring overrides
+------------+----------+-------+--------+--------------+
| FLAVOUR | GLOBAL | MATCH | ARENA | DISPLAY |
+------------+----------+-------+--------+--------------+
| x | FAIL | x | x | NO-ENTRY |
| CLOCK | x | x | x | CLOCK |
| LAYOUT | DOWNTIME | x | CLOSED | NO-ENTRY |
| LAYOUT | DOWNTIME | x | OPEN | NEXT-MATCH |
| LAYOUT | MATCH | x | CLOSED | NO-ENTRY |
| LAYOUT | MATCH | x | OPEN | LAYOUT |
| ZONE | DOWNTIME | x | x | CLOCK |
| ZONE | MATCH | x | x | ZONE |
| JUDGE | DOWNTIME | x | x | SCHED/LEAGUE |
| JUDGE | MATCH | x | x | STATS |
| MATCH-INFO | x | x | x | SCHED/LEAGUE |
| BLANK | x | x | x | NOTHING |
+------------+----------+-------+--------+--------------+
---
REDIS!
Keys:
match.schedule.[id].type
match.schedule.[id].teams
match.schedule.[id].start
match.schedule.[id].scores
match.schedule.[id].state
match.schedule.[id].stage
match.current
comp.state.global
comp.state.match
comp.state.tinker
comp.state.arena
comp.pause
comp.sync
teams.[tla].name
teams.[tla].college
teams.[tla].disqualified
teams.[tla].info
teams.[tla].notes
music.playlist.[list]
music.history
music.descriptions
screens.[id].flavour
screens.[id].zone
screens.[id].override
channels:
comp.heartbeat
comp.offset_shift
comp.kickoff
comp.state
comp.arena
teams.[tla]
match.reschedule
match.current.scores
match.current.events
comp.command
controller.[controller].heartbeat
#screens.[screen].refresh
#screens.[screen].update.[element]