@hotlap.ai/telemetry 1.0.0 → 1.1.0
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/README.md +7 -0
- package/dist/binary-reader.js +18 -187
- package/dist/cli.js +6 -5
- package/dist/constants.js +40 -248
- package/dist/ibt.js +8 -291
- package/dist/index-c5jf6rjt.js +189 -0
- package/dist/index-ftpvnye9.js +5 -0
- package/dist/{index-k5bgtn4c.js → index-hxw291vy.js} +1 -1
- package/dist/index-t4qz2011.js +418 -0
- package/dist/index-tz5ph8p3.js +293 -0
- package/dist/index-wb6ebd0j.js +246 -0
- package/dist/index.js +1 -66
- package/dist/live.js +7 -414
- package/dist/neutral/ibt.js +6539 -0
- package/dist/neutral/normalize.js +349 -0
- package/dist/normalize.d.ts +92 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/telemetry-server.js +5 -4
- package/package.json +16 -3
package/dist/ibt.js
CHANGED
|
@@ -1,298 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
readVarValueBatch
|
|
12
|
-
} from "./binary-reader.js";
|
|
13
|
-
import {
|
|
14
|
-
DISK_SUB_HEADER_OFFSET
|
|
15
|
-
} from "./constants.js";
|
|
16
|
-
|
|
17
|
-
// src/ibt.ts
|
|
18
|
-
class IBT {
|
|
19
|
-
buffer = null;
|
|
20
|
-
view = null;
|
|
21
|
-
header = null;
|
|
22
|
-
diskHeader = null;
|
|
23
|
-
varHeaders = null;
|
|
24
|
-
sessionInfoCache = new Map;
|
|
25
|
-
rawSessionInfo = null;
|
|
26
|
-
filePath = null;
|
|
27
|
-
get fileName() {
|
|
28
|
-
return this.filePath;
|
|
29
|
-
}
|
|
30
|
-
get varHeaderBufferTick() {
|
|
31
|
-
return this.header?.varBuf[0]?.tickCount ?? null;
|
|
32
|
-
}
|
|
33
|
-
get varHeaderNames() {
|
|
34
|
-
if (!this.varHeaders)
|
|
35
|
-
return null;
|
|
36
|
-
return Array.from(this.varHeaders.keys());
|
|
37
|
-
}
|
|
38
|
-
get recordCount() {
|
|
39
|
-
return this.diskHeader?.sessionRecordCount ?? 0;
|
|
40
|
-
}
|
|
41
|
-
get sessionLapCount() {
|
|
42
|
-
return this.diskHeader?.sessionLapCount ?? 0;
|
|
43
|
-
}
|
|
44
|
-
get sessionStartTime() {
|
|
45
|
-
return this.diskHeader?.sessionStartTime ?? 0;
|
|
46
|
-
}
|
|
47
|
-
get sessionEndTime() {
|
|
48
|
-
return this.diskHeader?.sessionEndTime ?? 0;
|
|
49
|
-
}
|
|
50
|
-
get tickRate() {
|
|
51
|
-
return this.header?.tickRate ?? 60;
|
|
52
|
-
}
|
|
53
|
-
get bufLen() {
|
|
54
|
-
return this.header?.bufLen ?? 0;
|
|
55
|
-
}
|
|
56
|
-
async open(filePath) {
|
|
57
|
-
this.filePath = filePath;
|
|
58
|
-
const file = Bun.file(filePath);
|
|
59
|
-
const arrayBuffer = await file.arrayBuffer();
|
|
60
|
-
this.buffer = new Uint8Array(arrayBuffer);
|
|
61
|
-
this.view = new DataView(arrayBuffer);
|
|
62
|
-
this.header = parseHeader(this.view);
|
|
63
|
-
this.diskHeader = parseDiskSubHeader(this.view, DISK_SUB_HEADER_OFFSET);
|
|
64
|
-
this.varHeaders = parseVarHeaders(this.view, this.buffer, this.header);
|
|
65
|
-
this.sessionInfoCache.clear();
|
|
66
|
-
this.rawSessionInfo = null;
|
|
67
|
-
}
|
|
68
|
-
openSync(filePath) {
|
|
69
|
-
this.filePath = filePath;
|
|
70
|
-
const file = Bun.file(filePath);
|
|
71
|
-
const arrayBuffer = file.arrayBuffer();
|
|
72
|
-
if (arrayBuffer instanceof Promise) {
|
|
73
|
-
throw new Error("Sync file reading requires Bun.file().bytes() - use open() instead");
|
|
74
|
-
}
|
|
75
|
-
this.buffer = new Uint8Array(arrayBuffer);
|
|
76
|
-
this.view = new DataView(arrayBuffer);
|
|
77
|
-
this.header = parseHeader(this.view);
|
|
78
|
-
this.diskHeader = parseDiskSubHeader(this.view, DISK_SUB_HEADER_OFFSET);
|
|
79
|
-
this.varHeaders = parseVarHeaders(this.view, this.buffer, this.header);
|
|
80
|
-
this.sessionInfoCache.clear();
|
|
81
|
-
this.rawSessionInfo = null;
|
|
82
|
-
}
|
|
83
|
-
static async fromBuffer(buffer) {
|
|
84
|
-
const ibt = new IBT;
|
|
85
|
-
ibt.buffer = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
86
|
-
ibt.view = new DataView(ibt.buffer.buffer, ibt.buffer.byteOffset, ibt.buffer.byteLength);
|
|
87
|
-
ibt.header = parseHeader(ibt.view);
|
|
88
|
-
ibt.diskHeader = parseDiskSubHeader(ibt.view, DISK_SUB_HEADER_OFFSET);
|
|
89
|
-
ibt.varHeaders = parseVarHeaders(ibt.view, ibt.buffer, ibt.header);
|
|
90
|
-
return ibt;
|
|
91
|
-
}
|
|
92
|
-
close() {
|
|
93
|
-
this.buffer = null;
|
|
94
|
-
this.view = null;
|
|
95
|
-
this.header = null;
|
|
96
|
-
this.diskHeader = null;
|
|
97
|
-
this.varHeaders = null;
|
|
98
|
-
this.sessionInfoCache.clear();
|
|
99
|
-
this.rawSessionInfo = null;
|
|
100
|
-
this.filePath = null;
|
|
101
|
-
}
|
|
102
|
-
getVarHeader(name) {
|
|
103
|
-
return this.varHeaders?.get(name);
|
|
104
|
-
}
|
|
105
|
-
get(index, key) {
|
|
106
|
-
if (!this.header || !this.view || !this.varHeaders || !this.diskHeader)
|
|
107
|
-
return null;
|
|
108
|
-
if (index < 0 || index >= this.diskHeader.sessionRecordCount)
|
|
109
|
-
return null;
|
|
110
|
-
const varHeader = this.varHeaders.get(key);
|
|
111
|
-
if (!varHeader)
|
|
112
|
-
return null;
|
|
113
|
-
const varBuf = this.header.varBuf[0];
|
|
114
|
-
if (!varBuf)
|
|
115
|
-
return null;
|
|
116
|
-
const varOffset = varHeader.offset + varBuf.bufOffset + index * this.header.bufLen;
|
|
117
|
-
return readVarValue(this.view, varOffset, varHeader.type, varHeader.count);
|
|
118
|
-
}
|
|
119
|
-
getAll(key) {
|
|
120
|
-
if (!this.header || !this.view || !this.varHeaders || !this.diskHeader)
|
|
121
|
-
return null;
|
|
122
|
-
const varHeader = this.varHeaders.get(key);
|
|
123
|
-
if (!varHeader)
|
|
124
|
-
return null;
|
|
125
|
-
const varBuf = this.header.varBuf[0];
|
|
126
|
-
if (!varBuf)
|
|
127
|
-
return null;
|
|
128
|
-
const baseOffset = varBuf.bufOffset;
|
|
129
|
-
const bufLen = this.header.bufLen;
|
|
130
|
-
const recordCount = this.diskHeader.sessionRecordCount;
|
|
131
|
-
const varOffset = varHeader.offset;
|
|
132
|
-
const isArray = varHeader.count > 1;
|
|
133
|
-
const results = new Array(recordCount);
|
|
134
|
-
for (let i = 0;i < recordCount; i++) {
|
|
135
|
-
const offset = baseOffset + i * bufLen + varOffset;
|
|
136
|
-
results[i] = readVarValue(this.view, offset, varHeader.type, varHeader.count);
|
|
137
|
-
}
|
|
138
|
-
return results;
|
|
139
|
-
}
|
|
140
|
-
getAllTyped(key) {
|
|
141
|
-
if (!this.header || !this.view || !this.varHeaders || !this.diskHeader)
|
|
142
|
-
return null;
|
|
143
|
-
const varHeader = this.varHeaders.get(key);
|
|
144
|
-
if (!varHeader || varHeader.count !== 1)
|
|
145
|
-
return null;
|
|
146
|
-
const varBuf = this.header.varBuf[0];
|
|
147
|
-
if (!varBuf)
|
|
148
|
-
return null;
|
|
149
|
-
const baseOffset = varBuf.bufOffset;
|
|
150
|
-
const bufLen = this.header.bufLen;
|
|
151
|
-
const recordCount = this.diskHeader.sessionRecordCount;
|
|
152
|
-
const varOffset = varHeader.offset;
|
|
153
|
-
let output;
|
|
154
|
-
switch (varHeader.type) {
|
|
155
|
-
case 4:
|
|
156
|
-
output = new Float32Array(recordCount);
|
|
157
|
-
break;
|
|
158
|
-
case 5:
|
|
159
|
-
output = new Float64Array(recordCount);
|
|
160
|
-
break;
|
|
161
|
-
case 2:
|
|
162
|
-
output = new Int32Array(recordCount);
|
|
163
|
-
break;
|
|
164
|
-
case 3:
|
|
165
|
-
output = new Uint32Array(recordCount);
|
|
166
|
-
break;
|
|
167
|
-
default:
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
|
-
readVarValueBatch(this.view, baseOffset, varOffset, varHeader.type, bufLen, recordCount, output);
|
|
171
|
-
return output;
|
|
172
|
-
}
|
|
173
|
-
getAllMultiple(keys) {
|
|
174
|
-
const results = new Map;
|
|
175
|
-
if (!this.header || !this.view || !this.varHeaders || !this.diskHeader)
|
|
176
|
-
return results;
|
|
177
|
-
const varBuf = this.header.varBuf[0];
|
|
178
|
-
if (!varBuf)
|
|
179
|
-
return results;
|
|
180
|
-
const baseOffset = varBuf.bufOffset;
|
|
181
|
-
const bufLen = this.header.bufLen;
|
|
182
|
-
const recordCount = this.diskHeader.sessionRecordCount;
|
|
183
|
-
const varInfos = [];
|
|
184
|
-
for (const key of keys) {
|
|
185
|
-
const varHeader = this.varHeaders.get(key);
|
|
186
|
-
if (varHeader) {
|
|
187
|
-
const data = new Array(recordCount);
|
|
188
|
-
varInfos.push({ key, varHeader, data });
|
|
189
|
-
results.set(key, data);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
for (let i = 0;i < recordCount; i++) {
|
|
193
|
-
const recordOffset = baseOffset + i * bufLen;
|
|
194
|
-
for (const { varHeader, data } of varInfos) {
|
|
195
|
-
const offset = recordOffset + varHeader.offset;
|
|
196
|
-
data[i] = readVarValue(this.view, offset, varHeader.type, varHeader.count);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return results;
|
|
200
|
-
}
|
|
201
|
-
*iterate(keys) {
|
|
202
|
-
if (!this.header || !this.view || !this.varHeaders || !this.diskHeader)
|
|
203
|
-
return;
|
|
204
|
-
const varBuf = this.header.varBuf[0];
|
|
205
|
-
if (!varBuf)
|
|
206
|
-
return;
|
|
207
|
-
const baseOffset = varBuf.bufOffset;
|
|
208
|
-
const bufLen = this.header.bufLen;
|
|
209
|
-
const recordCount = this.diskHeader.sessionRecordCount;
|
|
210
|
-
const varInfos = [];
|
|
211
|
-
for (const key of keys) {
|
|
212
|
-
const varHeader = this.varHeaders.get(key);
|
|
213
|
-
if (varHeader) {
|
|
214
|
-
varInfos.push({ key, varHeader });
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
for (let i = 0;i < recordCount; i++) {
|
|
218
|
-
const recordOffset = baseOffset + i * bufLen;
|
|
219
|
-
const record = new Map;
|
|
220
|
-
for (const { key, varHeader } of varInfos) {
|
|
221
|
-
const offset = recordOffset + varHeader.offset;
|
|
222
|
-
record.set(key, readVarValue(this.view, offset, varHeader.type, varHeader.count));
|
|
223
|
-
}
|
|
224
|
-
yield record;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
getRawSessionInfo() {
|
|
228
|
-
if (!this.header || !this.buffer)
|
|
229
|
-
return null;
|
|
230
|
-
if (this.rawSessionInfo === null) {
|
|
231
|
-
const start = this.header.sessionInfoOffset;
|
|
232
|
-
const len = this.header.sessionInfoLen;
|
|
233
|
-
this.rawSessionInfo = readString(this.buffer, start, len);
|
|
234
|
-
}
|
|
235
|
-
return this.rawSessionInfo;
|
|
236
|
-
}
|
|
237
|
-
getSessionInfo(key) {
|
|
238
|
-
const raw = this.getRawSessionInfo();
|
|
239
|
-
if (!raw)
|
|
240
|
-
return null;
|
|
241
|
-
if (!key) {
|
|
242
|
-
if (!this.sessionInfoCache.has("__full__")) {
|
|
243
|
-
try {
|
|
244
|
-
const cleaned = this.cleanYaml(raw);
|
|
245
|
-
this.sessionInfoCache.set("__full__", $parse(cleaned));
|
|
246
|
-
} catch {
|
|
247
|
-
return null;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return this.sessionInfoCache.get("__full__");
|
|
251
|
-
}
|
|
252
|
-
if (this.sessionInfoCache.has(key)) {
|
|
253
|
-
return this.sessionInfoCache.get(key);
|
|
254
|
-
}
|
|
255
|
-
const sectionMatch = raw.match(new RegExp(`
|
|
256
|
-
${key}:
|
|
257
|
-
([\\s\\S]*?)(?=
|
|
258
|
-
|
|
259
|
-
|$)`));
|
|
260
|
-
if (!sectionMatch)
|
|
261
|
-
return null;
|
|
262
|
-
try {
|
|
263
|
-
const sectionYaml = `${key}:
|
|
264
|
-
${sectionMatch[1]}`;
|
|
265
|
-
const cleaned = this.cleanYaml(sectionYaml);
|
|
266
|
-
const parsed = $parse(cleaned);
|
|
267
|
-
const result = parsed?.[key] ?? null;
|
|
268
|
-
this.sessionInfoCache.set(key, result);
|
|
269
|
-
return result;
|
|
270
|
-
} catch {
|
|
271
|
-
return null;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
cleanYaml(yaml) {
|
|
275
|
-
let cleaned = yaml.replace(/[\x81\x8D\x8F\x90\x9D]/g, " ").replace(/[^\x09\x0A\x0D\x20-\x7E\xA0-\xFF]/g, "");
|
|
276
|
-
cleaned = cleaned.replace(/((?:DriverSetupName|UserName|TeamName|AbbrevName|Initials): )(.*)/g, (_, prefix, value) => {
|
|
277
|
-
const escaped = value.replace(/["\\]/g, "\\$&");
|
|
278
|
-
return `${prefix}"${escaped}"`;
|
|
279
|
-
});
|
|
280
|
-
cleaned = cleaned.replace(/(\w+: )(,.*)/g, '$1"$2"');
|
|
281
|
-
return cleaned;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
async function parseIbt(filePath) {
|
|
285
|
-
const ibt = new IBT;
|
|
286
|
-
await ibt.open(filePath);
|
|
287
|
-
return ibt;
|
|
288
|
-
}
|
|
289
|
-
async function parseIbtBuffer(buffer) {
|
|
290
|
-
return IBT.fromBuffer(buffer);
|
|
291
|
-
}
|
|
3
|
+
IBT,
|
|
4
|
+
parseIbt,
|
|
5
|
+
parseIbtBuffer
|
|
6
|
+
} from "./index-tz5ph8p3.js";
|
|
7
|
+
import"./index-hxw291vy.js";
|
|
8
|
+
import"./index-c5jf6rjt.js";
|
|
9
|
+
import"./index-wb6ebd0j.js";
|
|
10
|
+
import"./index-ftpvnye9.js";
|
|
292
11
|
export {
|
|
293
12
|
parseIbtBuffer,
|
|
294
13
|
parseIbt,
|
|
295
14
|
IBT
|
|
296
15
|
};
|
|
297
|
-
|
|
298
|
-
export { IBT, parseIbt, parseIbtBuffer };
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
VAR_TYPE_SIZES
|
|
4
|
+
} from "./index-wb6ebd0j.js";
|
|
5
|
+
|
|
6
|
+
// src/binary-reader.ts
|
|
7
|
+
var textDecoder = new TextDecoder;
|
|
8
|
+
function readInt32LE(view, offset) {
|
|
9
|
+
return view.getInt32(offset, true);
|
|
10
|
+
}
|
|
11
|
+
function readUint32LE(view, offset) {
|
|
12
|
+
return view.getUint32(offset, true);
|
|
13
|
+
}
|
|
14
|
+
function readFloat32LE(view, offset) {
|
|
15
|
+
return view.getFloat32(offset, true);
|
|
16
|
+
}
|
|
17
|
+
function readFloat64LE(view, offset) {
|
|
18
|
+
return view.getFloat64(offset, true);
|
|
19
|
+
}
|
|
20
|
+
function readBigUint64LE(view, offset) {
|
|
21
|
+
return view.getBigUint64(offset, true);
|
|
22
|
+
}
|
|
23
|
+
function readBoolLE(view, offset) {
|
|
24
|
+
return view.getUint8(offset) !== 0;
|
|
25
|
+
}
|
|
26
|
+
function readCharLE(view, offset) {
|
|
27
|
+
return view.getInt8(offset);
|
|
28
|
+
}
|
|
29
|
+
function readString(buffer, offset, length) {
|
|
30
|
+
let end = offset;
|
|
31
|
+
const maxEnd = offset + length;
|
|
32
|
+
while (end < maxEnd && buffer[end] !== 0)
|
|
33
|
+
end++;
|
|
34
|
+
return textDecoder.decode(buffer.subarray(offset, end));
|
|
35
|
+
}
|
|
36
|
+
function readVarValue(view, offset, type, count) {
|
|
37
|
+
const size = VAR_TYPE_SIZES[type];
|
|
38
|
+
if (count === 1) {
|
|
39
|
+
switch (type) {
|
|
40
|
+
case 0:
|
|
41
|
+
return readCharLE(view, offset);
|
|
42
|
+
case 1:
|
|
43
|
+
return readBoolLE(view, offset);
|
|
44
|
+
case 2:
|
|
45
|
+
return readInt32LE(view, offset);
|
|
46
|
+
case 3:
|
|
47
|
+
return readUint32LE(view, offset);
|
|
48
|
+
case 4:
|
|
49
|
+
return readFloat32LE(view, offset);
|
|
50
|
+
case 5:
|
|
51
|
+
return readFloat64LE(view, offset);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (type === 1) {
|
|
55
|
+
const result2 = new Array(count);
|
|
56
|
+
for (let i = 0;i < count; i++) {
|
|
57
|
+
result2[i] = readBoolLE(view, offset + i);
|
|
58
|
+
}
|
|
59
|
+
return result2;
|
|
60
|
+
}
|
|
61
|
+
const result = new Array(count);
|
|
62
|
+
for (let i = 0;i < count; i++) {
|
|
63
|
+
const pos = offset + i * size;
|
|
64
|
+
switch (type) {
|
|
65
|
+
case 0:
|
|
66
|
+
result[i] = readCharLE(view, pos);
|
|
67
|
+
break;
|
|
68
|
+
case 2:
|
|
69
|
+
result[i] = readInt32LE(view, pos);
|
|
70
|
+
break;
|
|
71
|
+
case 3:
|
|
72
|
+
result[i] = readUint32LE(view, pos);
|
|
73
|
+
break;
|
|
74
|
+
case 4:
|
|
75
|
+
result[i] = readFloat32LE(view, pos);
|
|
76
|
+
break;
|
|
77
|
+
case 5:
|
|
78
|
+
result[i] = readFloat64LE(view, pos);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
function readVarValueBatch(view, baseOffset, varOffset, type, bufLen, recordCount, output) {
|
|
85
|
+
const size = VAR_TYPE_SIZES[type];
|
|
86
|
+
let writeIdx = 0;
|
|
87
|
+
switch (type) {
|
|
88
|
+
case 4:
|
|
89
|
+
for (let i = 0;i < recordCount; i++) {
|
|
90
|
+
output[writeIdx++] = view.getFloat32(baseOffset + i * bufLen + varOffset, true);
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case 5:
|
|
94
|
+
for (let i = 0;i < recordCount; i++) {
|
|
95
|
+
output[writeIdx++] = view.getFloat64(baseOffset + i * bufLen + varOffset, true);
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
case 2:
|
|
99
|
+
for (let i = 0;i < recordCount; i++) {
|
|
100
|
+
output[writeIdx++] = view.getInt32(baseOffset + i * bufLen + varOffset, true);
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
case 3:
|
|
104
|
+
for (let i = 0;i < recordCount; i++) {
|
|
105
|
+
output[writeIdx++] = view.getUint32(baseOffset + i * bufLen + varOffset, true);
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function parseHeader(view) {
|
|
111
|
+
const version = readInt32LE(view, 0);
|
|
112
|
+
const status = readInt32LE(view, 4);
|
|
113
|
+
const tickRate = readInt32LE(view, 8);
|
|
114
|
+
const sessionInfoUpdate = readInt32LE(view, 12);
|
|
115
|
+
const sessionInfoLen = readInt32LE(view, 16);
|
|
116
|
+
const sessionInfoOffset = readInt32LE(view, 20);
|
|
117
|
+
const numVars = readInt32LE(view, 24);
|
|
118
|
+
const varHeaderOffset = readInt32LE(view, 28);
|
|
119
|
+
const numBuf = readInt32LE(view, 32);
|
|
120
|
+
const bufLen = readInt32LE(view, 36);
|
|
121
|
+
const varBuf = new Array(numBuf);
|
|
122
|
+
for (let i = 0;i < numBuf; i++) {
|
|
123
|
+
const offset = 48 + i * 16;
|
|
124
|
+
varBuf[i] = {
|
|
125
|
+
tickCount: readInt32LE(view, offset),
|
|
126
|
+
bufOffset: readInt32LE(view, offset + 4)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
version,
|
|
131
|
+
status,
|
|
132
|
+
tickRate,
|
|
133
|
+
sessionInfoUpdate,
|
|
134
|
+
sessionInfoLen,
|
|
135
|
+
sessionInfoOffset,
|
|
136
|
+
numVars,
|
|
137
|
+
varHeaderOffset,
|
|
138
|
+
numBuf,
|
|
139
|
+
bufLen,
|
|
140
|
+
varBuf
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function parseVarHeader(view, buffer, offset) {
|
|
144
|
+
return {
|
|
145
|
+
type: readInt32LE(view, offset),
|
|
146
|
+
offset: readInt32LE(view, offset + 4),
|
|
147
|
+
count: readInt32LE(view, offset + 8),
|
|
148
|
+
countAsTime: readBoolLE(view, offset + 12),
|
|
149
|
+
name: readString(buffer, offset + 16, 32),
|
|
150
|
+
desc: readString(buffer, offset + 48, 64),
|
|
151
|
+
unit: readString(buffer, offset + 112, 32)
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function parseDiskSubHeader(view, offset) {
|
|
155
|
+
return {
|
|
156
|
+
sessionStartDate: readBigUint64LE(view, offset),
|
|
157
|
+
sessionStartTime: readFloat64LE(view, offset + 8),
|
|
158
|
+
sessionEndTime: readFloat64LE(view, offset + 16),
|
|
159
|
+
sessionLapCount: readInt32LE(view, offset + 24),
|
|
160
|
+
sessionRecordCount: readInt32LE(view, offset + 28)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function parseVarHeaders(view, buffer, header) {
|
|
164
|
+
const headers = new Map;
|
|
165
|
+
for (let i = 0;i < header.numVars; i++) {
|
|
166
|
+
const varHeader = parseVarHeader(view, buffer, header.varHeaderOffset + i * 144);
|
|
167
|
+
headers.set(varHeader.name, varHeader);
|
|
168
|
+
}
|
|
169
|
+
return headers;
|
|
170
|
+
}
|
|
171
|
+
function getLatestVarBuffer(varBufs) {
|
|
172
|
+
if (varBufs.length === 0) {
|
|
173
|
+
throw new Error("varBufs array is empty");
|
|
174
|
+
}
|
|
175
|
+
let latest = varBufs[0];
|
|
176
|
+
let secondLatest = varBufs[1] ?? varBufs[0];
|
|
177
|
+
for (let i = 1;i < varBufs.length; i++) {
|
|
178
|
+
const current = varBufs[i];
|
|
179
|
+
if (current.tickCount > latest.tickCount) {
|
|
180
|
+
secondLatest = latest;
|
|
181
|
+
latest = current;
|
|
182
|
+
} else if (current.tickCount > secondLatest.tickCount) {
|
|
183
|
+
secondLatest = current;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return secondLatest;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export { readInt32LE, readUint32LE, readFloat32LE, readFloat64LE, readBigUint64LE, readBoolLE, readCharLE, readString, readVarValue, readVarValueBatch, parseHeader, parseVarHeader, parseDiskSubHeader, parseVarHeaders, getLatestVarBuffer };
|