Skip to content

Commit 2dab47c

Browse files
committed
fix: support session timing in demo and stories
1 parent f76f97f commit 2dab47c

4 files changed

Lines changed: 88 additions & 17 deletions

File tree

src/app/bridge/iracingSdk/mock-data/mockSdkBridge.spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,53 @@ describe('mockSdkBridge processor channels', () => {
8888
);
8989
});
9090

91+
it('publishes session timing without a lifecycle in demo mode', async () => {
92+
const bus = new ChannelBus();
93+
const publish = vi.spyOn(bus, 'publish');
94+
bus.subscribe(
95+
{
96+
id: 3,
97+
isDestroyed: () => false,
98+
isVisible: () => true,
99+
send: vi.fn(),
100+
},
101+
'session-timing.snapshot'
102+
);
103+
const bridge = await publishIRacingSDKEvents(
104+
{ publishMessage: vi.fn() } as never,
105+
undefined,
106+
bus
107+
);
108+
try {
109+
callbacks.session?.({
110+
DriverInfo: { DriverCarIdx: 0, Drivers: [{ CarIdx: 0 }] },
111+
SessionInfo: {
112+
Sessions: [{ SessionNum: 1, SessionType: 'Race', SessionLaps: 20 }],
113+
},
114+
} as unknown as Session);
115+
callbacks.telemetry?.({
116+
SessionTime: { value: [120] },
117+
SessionNum: { value: [1] },
118+
SessionState: { value: [4] },
119+
SessionTimeTotal: { value: [2400] },
120+
SessionTimeRemain: { value: [2280] },
121+
CamCarIdx: { value: [0] },
122+
CarIdxLap: { value: [2] },
123+
CarIdxPosition: { value: [1] },
124+
CarIdxLapDistPct: { value: [0.25] },
125+
CarIdxBestLapTime: { value: [60] },
126+
CarIdxLastLapTime: { value: [60] },
127+
} as unknown as Telemetry);
128+
129+
expect(publish).toHaveBeenCalledWith(
130+
'session-timing.snapshot',
131+
expect.objectContaining({ currentLap: 2, sessionType: 'Race' })
132+
);
133+
} finally {
134+
bridge.stop();
135+
}
136+
});
137+
91138
it('feeds mock data through the relative-gap runtime', async () => {
92139
const bus = new ChannelBus();
93140
const publish = vi.spyOn(bus, 'publish');

src/app/bridge/iracingSdk/mock-data/mockSdkBridge.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ export async function publishIRacingSDKEvents(
2121
perfMetrics.startReporting();
2222

2323
const bridge = generateMockData();
24-
const lapTimesRuntime =
25-
channelBus && lifecycle
26-
? new LapTimesRuntime(channelBus, lifecycle, perfMetrics)
27-
: undefined;
24+
const lapTimesRuntime = channelBus
25+
? new LapTimesRuntime(channelBus, lifecycle, perfMetrics)
26+
: undefined;
2827
const carSpeedsRuntime = channelBus
2928
? new CarSpeedsRuntime(channelBus, lifecycle, perfMetrics)
3029
: undefined;

src/app/processors/lapTimesRuntime.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class LapTimesRuntime {
2121

2222
constructor(
2323
private readonly bus: ChannelBus,
24-
lifecycle: SessionLifecycle,
24+
lifecycle: SessionLifecycle | undefined,
2525
private readonly metrics: PerformanceSections,
2626
private readonly aggregateReplay = false
2727
) {
@@ -31,18 +31,22 @@ export class LapTimesRuntime {
3131
if (count > 0) this.activate();
3232
else this.deactivateIfUnused();
3333
}),
34-
lifecycle.onEnter(({ replay }) => {
35-
this.replaySource = replay;
36-
this.onLifecycle({
37-
type: 'enter',
38-
replay: replay && !this.aggregateReplay,
39-
});
40-
}),
41-
lifecycle.onSessionNumChange(() =>
42-
this.onLifecycle({ type: 'sessionNumChange' })
43-
),
44-
lifecycle.onDisconnect(() => this.onLifecycle({ type: 'disconnect' })),
4534
];
35+
if (lifecycle) {
36+
this.disconnects.push(
37+
lifecycle.onEnter(({ replay }) => {
38+
this.replaySource = replay;
39+
this.onLifecycle({
40+
type: 'enter',
41+
replay: replay && !this.aggregateReplay,
42+
});
43+
}),
44+
lifecycle.onSessionNumChange(() =>
45+
this.onLifecycle({ type: 'sessionNumChange' })
46+
),
47+
lifecycle.onDisconnect(() => this.onLifecycle({ type: 'disconnect' }))
48+
);
49+
}
4650
}
4751

4852
onFrame(frame: Telemetry): void {

src/frontend/components/Standings/components/SessionBar/SessionBar.stories.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { Meta, StoryObj } from '@storybook/react-vite';
22
import type { ComponentType } from 'react';
33
import { SessionBar } from './SessionBar';
44
import { getIncidentDisplay } from './getIncidentDisplay';
5-
import { TelemetryDecorator } from '../../../../../../.storybook/telemetryDecorator';
5+
import {
6+
ChannelSnapshotDecorator,
7+
TelemetryDecorator,
8+
} from '@irdashies/storybook';
69
import { getWidgetDefaultConfig } from '@irdashies/types';
710
import {
811
SessionTimingStoreUpdater,
@@ -16,6 +19,24 @@ export default {
1619
title: 'widgets/Standings/components/SessionBar',
1720
decorators: [
1821
TelemetryDecorator(),
22+
ChannelSnapshotDecorator({
23+
'session-timing.snapshot': {
24+
sessionType: 'Race',
25+
state: 4,
26+
currentLap: 8,
27+
totalLaps: 20,
28+
time: 960,
29+
timeTotal: 2400,
30+
timeRemaining: 1440,
31+
greenFlagTimestamp: 0,
32+
isFixedLapRace: true,
33+
totalRaceLaps: 20,
34+
totalRaceTime: 2400,
35+
adjustedRaceTime: 2400,
36+
sessionNum: 0,
37+
version: 1,
38+
},
39+
}),
1940
(Story: ComponentType) => (
2041
<>
2142
<SessionTimingStoreUpdater enabled={true} />

0 commit comments

Comments
 (0)