fpv-laptimer-client 0.0.0-stage → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +218 -2
- package/package.json +40 -4
- package/src/index.js +16 -0
- package/src/laptimer.js +395 -0
- package/src/types.js +276 -0
- package/types/index.d.ts +13 -0
- package/types/laptimer.d.ts +253 -0
- package/types/types.d.ts +368 -0
package/types/types.d.ts
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A channel (a seat on the page: slot 1 = index 0).
|
|
3
|
+
*/
|
|
4
|
+
export type Channel = {
|
|
5
|
+
/**
|
|
6
|
+
* 0, 1, …
|
|
7
|
+
*/
|
|
8
|
+
index: number;
|
|
9
|
+
/**
|
|
10
|
+
* "R1" … "R8" or the MHz as text
|
|
11
|
+
*/
|
|
12
|
+
name: string;
|
|
13
|
+
mhz: number;
|
|
14
|
+
/**
|
|
15
|
+
* false: does not fly along
|
|
16
|
+
*/
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
pilot_id: number | null;
|
|
19
|
+
/**
|
|
20
|
+
* callsign of the assigned pilot
|
|
21
|
+
*/
|
|
22
|
+
pilot: string | null;
|
|
23
|
+
/**
|
|
24
|
+
* free text instead of a pilot (wins over `pilot`)
|
|
25
|
+
*/
|
|
26
|
+
label: string;
|
|
27
|
+
/**
|
|
28
|
+
* what the page shows
|
|
29
|
+
*/
|
|
30
|
+
shown: string;
|
|
31
|
+
};
|
|
32
|
+
export type Pilot = {
|
|
33
|
+
id: number;
|
|
34
|
+
/**
|
|
35
|
+
* callsign (unique)
|
|
36
|
+
*/
|
|
37
|
+
name: string;
|
|
38
|
+
/**
|
|
39
|
+
* may be empty
|
|
40
|
+
*/
|
|
41
|
+
full_name: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* One seat's result in a session (`results`, in seat order).
|
|
45
|
+
*/
|
|
46
|
+
export type SeatResult = {
|
|
47
|
+
channel: number;
|
|
48
|
+
channel_name: string;
|
|
49
|
+
mhz: number;
|
|
50
|
+
pilot_id: number | null;
|
|
51
|
+
/**
|
|
52
|
+
* shown name: callsign, free text or channel name
|
|
53
|
+
*/
|
|
54
|
+
pilot: string;
|
|
55
|
+
/**
|
|
56
|
+
* null without a lap
|
|
57
|
+
*/
|
|
58
|
+
position: number | null;
|
|
59
|
+
laps: number;
|
|
60
|
+
lap_times_us: number[];
|
|
61
|
+
last_lap_us: number | null;
|
|
62
|
+
best_lap_us: number | null;
|
|
63
|
+
best_consecutive_us: number | null;
|
|
64
|
+
total_us: number | null;
|
|
65
|
+
holeshot_us: number | null;
|
|
66
|
+
finished: boolean;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* A pass through the gate (only in `sessions.get`).
|
|
70
|
+
*/
|
|
71
|
+
export type Pass = {
|
|
72
|
+
id: number;
|
|
73
|
+
channel: number;
|
|
74
|
+
time_us: number;
|
|
75
|
+
peak_db: number;
|
|
76
|
+
/**
|
|
77
|
+
* added by hand
|
|
78
|
+
*/
|
|
79
|
+
manual: boolean;
|
|
80
|
+
deleted: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* 0 = finish, 1 = arming gate
|
|
83
|
+
*/
|
|
84
|
+
gate: number;
|
|
85
|
+
/**
|
|
86
|
+
* deleted by the server, and why
|
|
87
|
+
*/
|
|
88
|
+
rejected?: "no_arming" | null | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* where the detector put it (null: added by hand; differs from time_us: moved by hand)
|
|
91
|
+
*/
|
|
92
|
+
detected_us?: number | null | undefined;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* A correction of a pass (only in `sessions.get`, as `changes`).
|
|
96
|
+
*/
|
|
97
|
+
export type PassChange = {
|
|
98
|
+
pass_id: number | null;
|
|
99
|
+
channel: number;
|
|
100
|
+
action: "add" | "delete" | "restore" | "move" | "reject";
|
|
101
|
+
from_us: number | null;
|
|
102
|
+
to_us: number | null;
|
|
103
|
+
rejected: string | null;
|
|
104
|
+
/**
|
|
105
|
+
* while the session ran
|
|
106
|
+
*/
|
|
107
|
+
live: boolean;
|
|
108
|
+
origin: "seite" | "editor" | "api" | "server";
|
|
109
|
+
at_us: number;
|
|
110
|
+
};
|
|
111
|
+
export type StartMode = "holeshot" | "from_start" | "flying";
|
|
112
|
+
export type Session = {
|
|
113
|
+
id: number;
|
|
114
|
+
/**
|
|
115
|
+
* false = training
|
|
116
|
+
*/
|
|
117
|
+
race: boolean;
|
|
118
|
+
phase: "countdown" | "running" | "ended";
|
|
119
|
+
start_mode: StartMode;
|
|
120
|
+
end: "open" | "laps" | "seconds";
|
|
121
|
+
end_value: number | null;
|
|
122
|
+
countdown_s: number;
|
|
123
|
+
min_lap_s: number;
|
|
124
|
+
created_us: number;
|
|
125
|
+
start_us: number;
|
|
126
|
+
ended_us: number | null;
|
|
127
|
+
confirmed_us: number | null;
|
|
128
|
+
needs_confirmation: boolean;
|
|
129
|
+
results: SeatResult[];
|
|
130
|
+
/**
|
|
131
|
+
* only from `sessions.get`
|
|
132
|
+
*/
|
|
133
|
+
passes?: Pass[] | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* only from `sessions.get`: every correction of a pass
|
|
136
|
+
*/
|
|
137
|
+
changes?: PassChange[] | undefined;
|
|
138
|
+
};
|
|
139
|
+
export type Board = {
|
|
140
|
+
id: string;
|
|
141
|
+
port: string;
|
|
142
|
+
/**
|
|
143
|
+
* finish, arming or off
|
|
144
|
+
*/
|
|
145
|
+
role: string;
|
|
146
|
+
ok: boolean;
|
|
147
|
+
error: string | null;
|
|
148
|
+
levels_per_s: number;
|
|
149
|
+
};
|
|
150
|
+
export type State = {
|
|
151
|
+
now_us: number;
|
|
152
|
+
/**
|
|
153
|
+
* the running session
|
|
154
|
+
*/
|
|
155
|
+
session: Session | null;
|
|
156
|
+
/**
|
|
157
|
+
* the ended race waiting for confirmation
|
|
158
|
+
*/
|
|
159
|
+
unconfirmed: Session | null;
|
|
160
|
+
channels: Channel[];
|
|
161
|
+
pilots: Pilot[];
|
|
162
|
+
boards: Board[];
|
|
163
|
+
};
|
|
164
|
+
export type PilotStats = {
|
|
165
|
+
pilot_id: number | null;
|
|
166
|
+
label: string;
|
|
167
|
+
best_lap_us: number | null;
|
|
168
|
+
best_consecutive_us: number | null;
|
|
169
|
+
sessions: number;
|
|
170
|
+
races: number;
|
|
171
|
+
wins: number;
|
|
172
|
+
};
|
|
173
|
+
export type Stats = {
|
|
174
|
+
today_races: number;
|
|
175
|
+
/**
|
|
176
|
+
* best lap first
|
|
177
|
+
*/
|
|
178
|
+
all: PilotStats[];
|
|
179
|
+
today: PilotStats[];
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Arguments of `session.start`.
|
|
183
|
+
*/
|
|
184
|
+
export type StartOptions = {
|
|
185
|
+
/**
|
|
186
|
+
* true: race, false: training (default)
|
|
187
|
+
*/
|
|
188
|
+
race?: boolean | undefined;
|
|
189
|
+
/**
|
|
190
|
+
* race: end after this many laps (1–100)
|
|
191
|
+
*/
|
|
192
|
+
laps?: number | undefined;
|
|
193
|
+
/**
|
|
194
|
+
* race: end after this many seconds (10–3600), instead of laps
|
|
195
|
+
*/
|
|
196
|
+
seconds?: number | undefined;
|
|
197
|
+
/**
|
|
198
|
+
* race: 0–60
|
|
199
|
+
*/
|
|
200
|
+
countdown_s?: number | undefined;
|
|
201
|
+
/**
|
|
202
|
+
* race
|
|
203
|
+
*/
|
|
204
|
+
start_mode?: StartMode | undefined;
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Arguments of `channels.set` (only given fields change).
|
|
208
|
+
*/
|
|
209
|
+
export type ChannelChange = {
|
|
210
|
+
/**
|
|
211
|
+
* callsign, null = nobody
|
|
212
|
+
*/
|
|
213
|
+
pilot?: string | null | undefined;
|
|
214
|
+
/**
|
|
215
|
+
* instead of `pilot`
|
|
216
|
+
*/
|
|
217
|
+
pilot_id?: number | null | undefined;
|
|
218
|
+
/**
|
|
219
|
+
* make an unknown callsign a pilot
|
|
220
|
+
*/
|
|
221
|
+
create?: boolean | undefined;
|
|
222
|
+
/**
|
|
223
|
+
* free text instead of a pilot ("" = none)
|
|
224
|
+
*/
|
|
225
|
+
label?: string | undefined;
|
|
226
|
+
enabled?: boolean | undefined;
|
|
227
|
+
/**
|
|
228
|
+
* "R1" … "R8" or MHz (5300–6000); not during a session
|
|
229
|
+
*/
|
|
230
|
+
frequency?: string | number | undefined;
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* Fields every event about a pilot has ("Sitz" in docs/api/events.md).
|
|
234
|
+
*/
|
|
235
|
+
export type Seat = {
|
|
236
|
+
channel: number;
|
|
237
|
+
channel_name: string;
|
|
238
|
+
mhz: number;
|
|
239
|
+
pilot_id: number | null;
|
|
240
|
+
pilot: string;
|
|
241
|
+
};
|
|
242
|
+
export type SessionStartedData = {
|
|
243
|
+
session_id: number;
|
|
244
|
+
race: boolean;
|
|
245
|
+
start_mode: StartMode;
|
|
246
|
+
end: "open" | "laps" | "seconds";
|
|
247
|
+
end_value: number | null;
|
|
248
|
+
countdown_s: number;
|
|
249
|
+
created_us: number;
|
|
250
|
+
start_us: number;
|
|
251
|
+
pilot_count: number;
|
|
252
|
+
seats: Seat[];
|
|
253
|
+
};
|
|
254
|
+
export type CountdownData = {
|
|
255
|
+
session_id: number;
|
|
256
|
+
race: boolean;
|
|
257
|
+
seconds_left: number;
|
|
258
|
+
};
|
|
259
|
+
export type StartSignalData = {
|
|
260
|
+
session_id: number;
|
|
261
|
+
race: boolean;
|
|
262
|
+
start_us: number;
|
|
263
|
+
};
|
|
264
|
+
export type PilotPassData = Seat & {
|
|
265
|
+
session_id: number;
|
|
266
|
+
race: boolean;
|
|
267
|
+
pass_id: number;
|
|
268
|
+
time_us: number;
|
|
269
|
+
manual: boolean;
|
|
270
|
+
kind: "lap" | "holeshot" | "start" | "ignored";
|
|
271
|
+
lap: number | null;
|
|
272
|
+
lap_time_us: number | null;
|
|
273
|
+
lap_time_s: number | null;
|
|
274
|
+
laps: number;
|
|
275
|
+
best_lap_us: number | null;
|
|
276
|
+
best_lap_s: number | null;
|
|
277
|
+
personal_best: boolean;
|
|
278
|
+
session_best: boolean;
|
|
279
|
+
holeshot_us: number | null;
|
|
280
|
+
finished: boolean;
|
|
281
|
+
position: number | null;
|
|
282
|
+
};
|
|
283
|
+
export type PilotFinishedData = Seat & {
|
|
284
|
+
session_id: number;
|
|
285
|
+
laps: number;
|
|
286
|
+
total_us: number | null;
|
|
287
|
+
total_s: number | null;
|
|
288
|
+
best_lap_us: number | null;
|
|
289
|
+
best_lap_s: number | null;
|
|
290
|
+
position: number | null;
|
|
291
|
+
};
|
|
292
|
+
export type SessionStoppedData = {
|
|
293
|
+
session_id: number;
|
|
294
|
+
race: boolean;
|
|
295
|
+
reason: "stopped" | "finished" | "cancelled";
|
|
296
|
+
ended_us: number;
|
|
297
|
+
needs_confirmation: boolean;
|
|
298
|
+
/**
|
|
299
|
+
* race only
|
|
300
|
+
*/
|
|
301
|
+
winner: string | null;
|
|
302
|
+
results: SeatResult[];
|
|
303
|
+
};
|
|
304
|
+
export type RaceConfirmedData = {
|
|
305
|
+
session_id: number;
|
|
306
|
+
race: boolean;
|
|
307
|
+
confirmed_us: number;
|
|
308
|
+
winner: string | null;
|
|
309
|
+
results: SeatResult[];
|
|
310
|
+
};
|
|
311
|
+
export type PilotEventData = {
|
|
312
|
+
pilot_id: number;
|
|
313
|
+
name: string;
|
|
314
|
+
/**
|
|
315
|
+
* not in pilot_deleted
|
|
316
|
+
*/
|
|
317
|
+
full_name?: string | undefined;
|
|
318
|
+
};
|
|
319
|
+
/**
|
|
320
|
+
* Event name → its `data`.
|
|
321
|
+
*/
|
|
322
|
+
export type EventMap = {
|
|
323
|
+
session_started: SessionStartedData;
|
|
324
|
+
countdown: CountdownData;
|
|
325
|
+
start_signal: StartSignalData;
|
|
326
|
+
pilot_pass: PilotPassData;
|
|
327
|
+
pilot_finished: PilotFinishedData;
|
|
328
|
+
session_stopped: SessionStoppedData;
|
|
329
|
+
race_confirmed: RaceConfirmedData;
|
|
330
|
+
session_deleted: {
|
|
331
|
+
session_id: number;
|
|
332
|
+
race: boolean;
|
|
333
|
+
};
|
|
334
|
+
sessions_reset: {
|
|
335
|
+
deleted: number;
|
|
336
|
+
};
|
|
337
|
+
passes_changed: {
|
|
338
|
+
session_id: number;
|
|
339
|
+
};
|
|
340
|
+
channels_changed: {
|
|
341
|
+
channels: Channel[];
|
|
342
|
+
};
|
|
343
|
+
pilot_added: PilotEventData;
|
|
344
|
+
pilot_updated: PilotEventData;
|
|
345
|
+
pilot_deleted: PilotEventData;
|
|
346
|
+
};
|
|
347
|
+
/**
|
|
348
|
+
* An event as it comes over the WebSocket.
|
|
349
|
+
*/
|
|
350
|
+
export type EventMessage<D = any> = {
|
|
351
|
+
type: "event";
|
|
352
|
+
event: string;
|
|
353
|
+
/**
|
|
354
|
+
* counts from 1 since the server started; a gap = missed events
|
|
355
|
+
*/
|
|
356
|
+
seq: number;
|
|
357
|
+
time_us: number;
|
|
358
|
+
data: D;
|
|
359
|
+
};
|
|
360
|
+
/**
|
|
361
|
+
* The first message after connecting.
|
|
362
|
+
*/
|
|
363
|
+
export type Hello = {
|
|
364
|
+
type: "hello";
|
|
365
|
+
api: number;
|
|
366
|
+
state: State | null;
|
|
367
|
+
commands: string[];
|
|
368
|
+
};
|