@hotlap.ai/telemetry 1.2.0 → 1.4.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/CONTRIBUTING.md +3 -3
- package/README.md +4 -2
- package/dist/cli.js +3 -3
- package/dist/{index-t4qz2011.js → index-ndbp3f5t.js} +194 -34
- package/dist/lap-points.d.ts +76 -0
- package/dist/lap-points.d.ts.map +1 -0
- package/dist/live.d.ts +34 -1
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +1 -1
- package/dist/neutral/lap-points.js +156 -0
- package/dist/telemetry-server.d.ts +100 -1
- package/dist/telemetry-server.d.ts.map +1 -1
- package/dist/telemetry-server.js +462 -126
- package/package.json +9 -2
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// src/lap-points.ts
|
|
2
|
+
var DEFAULT_MAX_POINTS = 500;
|
|
3
|
+
function channel(source, key) {
|
|
4
|
+
const typed = source.getAllTyped(key);
|
|
5
|
+
if (typed)
|
|
6
|
+
return typed;
|
|
7
|
+
return source.getAll(key);
|
|
8
|
+
}
|
|
9
|
+
function channelWithFallback(source, ...keys) {
|
|
10
|
+
for (const key of keys) {
|
|
11
|
+
const c = channel(source, key);
|
|
12
|
+
if (c)
|
|
13
|
+
return c;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function readNum(arr, i) {
|
|
18
|
+
if (!arr)
|
|
19
|
+
return null;
|
|
20
|
+
const v = arr[i];
|
|
21
|
+
return typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
22
|
+
}
|
|
23
|
+
function readBool(arr, i) {
|
|
24
|
+
if (!arr)
|
|
25
|
+
return null;
|
|
26
|
+
const v = arr[i];
|
|
27
|
+
if (typeof v === "boolean")
|
|
28
|
+
return v;
|
|
29
|
+
if (v === 1)
|
|
30
|
+
return true;
|
|
31
|
+
if (v === 0)
|
|
32
|
+
return false;
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function extractLapPoints(source, lap, opts) {
|
|
36
|
+
const maxPoints = Math.max(1, Math.floor(opts?.maxPoints ?? DEFAULT_MAX_POINTS));
|
|
37
|
+
const timeArr = channel(source, "SessionTime");
|
|
38
|
+
const distArr = channel(source, "LapDist");
|
|
39
|
+
if (!timeArr || !distArr || source.recordCount === 0) {
|
|
40
|
+
return { byDist: [], byTime: [], downsampledFrom: 0 };
|
|
41
|
+
}
|
|
42
|
+
const lapArr = channel(source, "Lap");
|
|
43
|
+
const sessArr = channel(source, "SessionNum");
|
|
44
|
+
const speedArr = channel(source, "Speed");
|
|
45
|
+
const throttleArr = channel(source, "Throttle");
|
|
46
|
+
const brakeArr = channel(source, "Brake");
|
|
47
|
+
const absArr = channel(source, "BrakeABSactive");
|
|
48
|
+
const gearArr = channel(source, "Gear");
|
|
49
|
+
const rpmArr = channel(source, "RPM");
|
|
50
|
+
const steerArr = channel(source, "SteeringWheelAngle");
|
|
51
|
+
const latArr = channel(source, "Lat");
|
|
52
|
+
const lonArr = channel(source, "Lon");
|
|
53
|
+
const altArr = channel(source, "Alt");
|
|
54
|
+
const latAccelArr = channel(source, "LatAccel");
|
|
55
|
+
const longAccelArr = channel(source, "LongAccel");
|
|
56
|
+
const yawRateArr = channel(source, "YawRate");
|
|
57
|
+
const tempLF = channelWithFallback(source, "LFtempM", "LFtempCM");
|
|
58
|
+
const tempRF = channelWithFallback(source, "RFtempM", "RFtempCM");
|
|
59
|
+
const tempLR = channelWithFallback(source, "LRtempM", "LRtempCM");
|
|
60
|
+
const tempRR = channelWithFallback(source, "RRtempM", "RRtempCM");
|
|
61
|
+
const pressLF = channel(source, "LFpressure");
|
|
62
|
+
const pressRF = channel(source, "RFpressure");
|
|
63
|
+
const pressLR = channel(source, "LRpressure");
|
|
64
|
+
const pressRR = channel(source, "RRpressure");
|
|
65
|
+
const wearLF = channel(source, "LFwearM");
|
|
66
|
+
const wearRF = channel(source, "RFwearM");
|
|
67
|
+
const wearLR = channel(source, "LRwearM");
|
|
68
|
+
const wearRR = channel(source, "RRwearM");
|
|
69
|
+
const first = Math.max(0, lap.firstSampleIndex);
|
|
70
|
+
const last = Math.min(source.recordCount - 1, lap.lastSampleIndex);
|
|
71
|
+
const expectedSess = readNum(sessArr, first);
|
|
72
|
+
const indices = [];
|
|
73
|
+
for (let i = first;i <= last; i++) {
|
|
74
|
+
if (lapArr) {
|
|
75
|
+
const l = readNum(lapArr, i);
|
|
76
|
+
if (l != null && l !== lap.lapNumber)
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (sessArr && expectedSess != null) {
|
|
80
|
+
const s = readNum(sessArr, i);
|
|
81
|
+
if (s != null && s !== expectedSess)
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
indices.push(i);
|
|
85
|
+
}
|
|
86
|
+
let minTime = Infinity;
|
|
87
|
+
let minDist = Infinity;
|
|
88
|
+
for (const i of indices) {
|
|
89
|
+
const t = readNum(timeArr, i);
|
|
90
|
+
const d = readNum(distArr, i);
|
|
91
|
+
if (t == null || d == null)
|
|
92
|
+
continue;
|
|
93
|
+
if (t < minTime)
|
|
94
|
+
minTime = t;
|
|
95
|
+
if (d < minDist)
|
|
96
|
+
minDist = d;
|
|
97
|
+
}
|
|
98
|
+
if (!Number.isFinite(minTime) || !Number.isFinite(minDist)) {
|
|
99
|
+
return { byDist: [], byTime: [], downsampledFrom: 0 };
|
|
100
|
+
}
|
|
101
|
+
const points = [];
|
|
102
|
+
for (const i of indices) {
|
|
103
|
+
const t = readNum(timeArr, i);
|
|
104
|
+
const d = readNum(distArr, i);
|
|
105
|
+
if (t == null || d == null)
|
|
106
|
+
continue;
|
|
107
|
+
const speed = readNum(speedArr, i);
|
|
108
|
+
const throttle = readNum(throttleArr, i);
|
|
109
|
+
const brake = readNum(brakeArr, i);
|
|
110
|
+
const steerRad = readNum(steerArr, i);
|
|
111
|
+
const yawRateRad = readNum(yawRateArr, i);
|
|
112
|
+
const wLF = readNum(wearLF, i);
|
|
113
|
+
const wRF = readNum(wearRF, i);
|
|
114
|
+
const wLR = readNum(wearLR, i);
|
|
115
|
+
const wRR = readNum(wearRR, i);
|
|
116
|
+
points.push({
|
|
117
|
+
distanceKm: (d - minDist) / 1000,
|
|
118
|
+
timeSec: t - minTime,
|
|
119
|
+
speedKmh: speed != null ? speed * 3.6 : null,
|
|
120
|
+
throttlePct: throttle != null ? throttle * 100 : null,
|
|
121
|
+
brakePct: brake != null ? brake * 100 : null,
|
|
122
|
+
brakeABSactive: readBool(absArr, i),
|
|
123
|
+
gear: readNum(gearArr, i),
|
|
124
|
+
rpm: readNum(rpmArr, i),
|
|
125
|
+
steeringDeg: steerRad != null ? steerRad * 180 / Math.PI : null,
|
|
126
|
+
lat: readNum(latArr, i),
|
|
127
|
+
lon: readNum(lonArr, i),
|
|
128
|
+
altitudeM: readNum(altArr, i),
|
|
129
|
+
latAccelMs2: readNum(latAccelArr, i),
|
|
130
|
+
longAccelMs2: readNum(longAccelArr, i),
|
|
131
|
+
yawRateDegS: yawRateRad != null ? yawRateRad * 180 / Math.PI : null,
|
|
132
|
+
tireTempLF: readNum(tempLF, i),
|
|
133
|
+
tireTempRF: readNum(tempRF, i),
|
|
134
|
+
tireTempLR: readNum(tempLR, i),
|
|
135
|
+
tireTempRR: readNum(tempRR, i),
|
|
136
|
+
tirePressureLF: readNum(pressLF, i),
|
|
137
|
+
tirePressureRF: readNum(pressRF, i),
|
|
138
|
+
tirePressureLR: readNum(pressLR, i),
|
|
139
|
+
tirePressureRR: readNum(pressRR, i),
|
|
140
|
+
tireWearLF: wLF != null ? wLF * 100 : null,
|
|
141
|
+
tireWearRF: wRF != null ? wRF * 100 : null,
|
|
142
|
+
tireWearLR: wLR != null ? wLR * 100 : null,
|
|
143
|
+
tireWearRR: wRR != null ? wRR * 100 : null
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const valid = points.filter((p) => Number.isFinite(p.distanceKm) && Number.isFinite(p.timeSec) && p.distanceKm >= 0 && p.timeSec >= 0);
|
|
147
|
+
const byDistFull = [...valid].sort((a, b) => a.distanceKm - b.distanceKm);
|
|
148
|
+
const byTimeFull = [...valid].sort((a, b) => a.timeSec - b.timeSec);
|
|
149
|
+
const stride = Math.max(1, Math.ceil(valid.length / maxPoints));
|
|
150
|
+
const byDist = stride > 1 ? byDistFull.filter((_, i) => i % stride === 0) : byDistFull;
|
|
151
|
+
const byTime = stride > 1 ? byTimeFull.filter((_, i) => i % stride === 0) : byTimeFull;
|
|
152
|
+
return { byDist, byTime, downsampledFrom: valid.length };
|
|
153
|
+
}
|
|
154
|
+
export {
|
|
155
|
+
extractLapPoints
|
|
156
|
+
};
|
|
@@ -15,6 +15,10 @@ export interface SessionInfoMessage {
|
|
|
15
15
|
sessionType: string;
|
|
16
16
|
sessionNum: number;
|
|
17
17
|
tickRate: number;
|
|
18
|
+
sectors: Array<{
|
|
19
|
+
sectorNum: number;
|
|
20
|
+
startPct: number;
|
|
21
|
+
}>;
|
|
18
22
|
};
|
|
19
23
|
}
|
|
20
24
|
export interface TelemetryMessage {
|
|
@@ -58,6 +62,24 @@ export interface TelemetryFrame {
|
|
|
58
62
|
tireTempRF: number;
|
|
59
63
|
tireTempLR: number;
|
|
60
64
|
tireTempRR: number;
|
|
65
|
+
tirePressureLF: number | null;
|
|
66
|
+
tirePressureRF: number | null;
|
|
67
|
+
tirePressureLR: number | null;
|
|
68
|
+
tirePressureRR: number | null;
|
|
69
|
+
tireWearLF: number | null;
|
|
70
|
+
tireWearRF: number | null;
|
|
71
|
+
tireWearLR: number | null;
|
|
72
|
+
tireWearRR: number | null;
|
|
73
|
+
sessionNum: number;
|
|
74
|
+
onPitRoad: boolean;
|
|
75
|
+
playerCarIdx: number;
|
|
76
|
+
/** All cars' lap-distance pct at this tick (4dp) — head-to-head sector
|
|
77
|
+
* timing needs the full 60Hz stream, not the 15Hz field snapshot. */
|
|
78
|
+
carIdxLapDistPct: number[];
|
|
79
|
+
/** irsdk_Flags bitfield (green/yellow/blue/white/checkered...). */
|
|
80
|
+
sessionFlags: number;
|
|
81
|
+
/** irsdk_CarLeftRight spotter enum: 1 clear, 2 left, 3 right, 4 both, 5 two left, 6 two right. */
|
|
82
|
+
carLeftRight: number;
|
|
61
83
|
}
|
|
62
84
|
export interface LapChangeMessage {
|
|
63
85
|
type: 'lap_change';
|
|
@@ -76,5 +98,82 @@ export interface StatusMessage {
|
|
|
76
98
|
error?: string;
|
|
77
99
|
};
|
|
78
100
|
}
|
|
79
|
-
export
|
|
101
|
+
export interface FieldMessage {
|
|
102
|
+
type: 'field';
|
|
103
|
+
data: FieldData;
|
|
104
|
+
}
|
|
105
|
+
/** Live multi-car snapshot, published at ~15Hz. Parallel arrays indexed by CarIdx. */
|
|
106
|
+
export interface FieldData {
|
|
107
|
+
tick: number;
|
|
108
|
+
sessionTime: number;
|
|
109
|
+
sessionNum: number;
|
|
110
|
+
sessionState: number;
|
|
111
|
+
sessionTimeRemain: number;
|
|
112
|
+
sessionLapsRemain: number;
|
|
113
|
+
playerCarIdx: number;
|
|
114
|
+
paceCarIdx: number;
|
|
115
|
+
position: number[];
|
|
116
|
+
classPosition: number[];
|
|
117
|
+
lap: number[];
|
|
118
|
+
lapCompleted: number[];
|
|
119
|
+
lapDistPct: number[];
|
|
120
|
+
estTime: number[];
|
|
121
|
+
f2Time: number[];
|
|
122
|
+
onPitRoad: boolean[];
|
|
123
|
+
trackSurface: number[];
|
|
124
|
+
lastLapTime: number[];
|
|
125
|
+
bestLapTime: number[];
|
|
126
|
+
}
|
|
127
|
+
export interface OverlayDriver {
|
|
128
|
+
carIdx: number;
|
|
129
|
+
userName: string;
|
|
130
|
+
teamName?: string;
|
|
131
|
+
carNumber: string;
|
|
132
|
+
carClassId: number;
|
|
133
|
+
carClassShortName: string;
|
|
134
|
+
carClassColor: number;
|
|
135
|
+
carClassRelSpeed: number;
|
|
136
|
+
carClassEstLapTime: number;
|
|
137
|
+
iRating: number;
|
|
138
|
+
licString: string;
|
|
139
|
+
licColor: number;
|
|
140
|
+
incidentCount: number;
|
|
141
|
+
}
|
|
142
|
+
export interface ClassInfo {
|
|
143
|
+
classId: number;
|
|
144
|
+
shortName: string;
|
|
145
|
+
color: number;
|
|
146
|
+
sof: number;
|
|
147
|
+
carCount: number;
|
|
148
|
+
}
|
|
149
|
+
export interface SessionStateMessage {
|
|
150
|
+
type: 'session_state';
|
|
151
|
+
data: SessionStateData;
|
|
152
|
+
}
|
|
153
|
+
/** Roster + results snapshot, published when iRacing bumps its session-info counter. */
|
|
154
|
+
export interface SessionStateData {
|
|
155
|
+
sessionInfoUpdate: number;
|
|
156
|
+
subSessionId: number;
|
|
157
|
+
trackId: number;
|
|
158
|
+
sessionNum: number;
|
|
159
|
+
sessionType: string;
|
|
160
|
+
sessionLaps: string | number;
|
|
161
|
+
sessionTimeTotal: string | number;
|
|
162
|
+
drivers: OverlayDriver[];
|
|
163
|
+
classes: ClassInfo[];
|
|
164
|
+
results: Array<{
|
|
165
|
+
carIdx: number;
|
|
166
|
+
position: number;
|
|
167
|
+
classPosition: number;
|
|
168
|
+
fastestTime: number;
|
|
169
|
+
lastTime: number;
|
|
170
|
+
lapsComplete: number;
|
|
171
|
+
incidents: number;
|
|
172
|
+
}>;
|
|
173
|
+
fastestLap: Array<{
|
|
174
|
+
carIdx: number;
|
|
175
|
+
fastestTime: number;
|
|
176
|
+
}>;
|
|
177
|
+
}
|
|
178
|
+
export type ServerMessage = SessionInfoMessage | TelemetryMessage | LapChangeMessage | StatusMessage | FieldMessage | SessionStateMessage;
|
|
80
179
|
//# sourceMappingURL=telemetry-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry-server.d.ts","sourceRoot":"","sources":["../src/telemetry-server.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"telemetry-server.d.ts","sourceRoot":"","sources":["../src/telemetry-server.ts"],"names":[],"mappings":";AAwBA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAA;IACpB,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAA;QACf,SAAS,EAAE,MAAM,CAAA;QACjB,gBAAgB,EAAE,MAAM,CAAA;QACxB,WAAW,EAAE,MAAM,CAAA;QACnB,WAAW,EAAE,MAAM,CAAA;QACnB,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;QACnB,UAAU,EAAE,MAAM,CAAA;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,OAAO,EAAE,KAAK,CAAC;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KACxD,CAAA;CACF;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,cAAc,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,OAAO,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,cAAc,EAAE,OAAO,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB;yEACqE;IACrE,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAA;IACpB,kGAAkG;IAClG,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAA;IAClB,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,UAAU,EAAE,MAAM,CAAA;KACnB,CAAA;CACF;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE;QACJ,SAAS,EAAE,OAAO,CAAA;QAClB,WAAW,EAAE,OAAO,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,sFAAsF;AACtF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,SAAS,EAAE,OAAO,EAAE,CAAA;IACpB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAA;IACrB,IAAI,EAAE,gBAAgB,CAAA;CACvB;AAED,wFAAwF;AACxF,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAA;IAC5B,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAA;IACjC,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,OAAO,EAAE,KAAK,CAAC;QACb,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,aAAa,EAAE,MAAM,CAAA;QACrB,WAAW,EAAE,MAAM,CAAA;QACnB,QAAQ,EAAE,MAAM,CAAA;QAChB,YAAY,EAAE,MAAM,CAAA;QACpB,SAAS,EAAE,MAAM,CAAA;KAClB,CAAC,CAAA;IACF,UAAU,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC3D;AAED,MAAM,MAAM,aAAa,GACrB,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,aAAa,GACb,YAAY,GACZ,mBAAmB,CAAA"}
|