Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ typings/
out/

*storybook.log
test-data/*.png
test-data/**/*.png
test-data/unused
src/**/tracks/*.svg
asset-data
Expand Down
3 changes: 3 additions & 0 deletions src/app/bridge/iracingSdk/dumpTelemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ export async function dumpCurrentTelemetry() {
await writeFile(`${dirPath}/session.json`, session, 'utf-8'),
]);
console.log(`Saved to: ${dirPath}`);
return { dirPath };
} else {
console.warn('No telemetry data received');
}
}

return { dirPath: null };
}
37 changes: 31 additions & 6 deletions src/app/setupTaskbar.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { nativeImage, Tray, Menu, app, globalShortcut } from 'electron';
import { nativeImage, Tray, Menu, app, globalShortcut, desktopCapturer } from 'electron';
import { TelemetrySink } from './bridge/iracingSdk/telemetrySink';
import { OverlayManager } from './overlayManager';
import { writeFile } from 'node:fs/promises';
import path from 'node:path';

class Taskbar {
private tray: Tray;
Expand Down Expand Up @@ -65,11 +67,34 @@ class Taskbar {
this.overlayManager.toggleLockOverlays();
}

private saveTelemetry(): void {
if (process.platform === 'darwin') return;
import('./bridge/iracingSdk/dumpTelemetry').then(
async ({ dumpCurrentTelemetry }) => await dumpCurrentTelemetry()
);
private async saveTelemetry(): Promise<void> {
try {
// First, import and call dumpTelemetry to get the directory path
const { dumpCurrentTelemetry } = await import('./bridge/iracingSdk/dumpTelemetry');
const telemetryResult = await dumpCurrentTelemetry();

// Check if dirPath exists and is not null
const dirPath = telemetryResult && 'dirPath' in telemetryResult ? telemetryResult.dirPath : null;
if (dirPath) {
// Capture all screens
const sources = await desktopCapturer.getSources({
types: ['screen'],
thumbnailSize: { width: 1920, height: 1080 } // Use a standard resolution
});

// Save each screen as a separate file
await Promise.all(sources.map(async (source, index) => {
if (source.thumbnail) {
const screenshotPath = path.join(dirPath, `screenshot_${index + 1}.png`);
const pngData = source.thumbnail.toPNG();
await writeFile(screenshotPath, pngData);
console.log(`Screenshot ${index + 1} saved to: ${screenshotPath}`);
}
}));
}
} catch (error) {
console.error('Error capturing screenshots:', error);
}
}

private registerShortcuts(): void {
Expand Down
70 changes: 43 additions & 27 deletions src/frontend/components/Standings/hooks/useDriverRelatives.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,56 @@
import { useMemo } from 'react';
import {
useDriverCarIdx,
useSessionStore,
useTelemetryValues,
} from '@irdashies/context';
import { useDriverStandings } from './useDriverPositions';

export const useDriverRelatives = ({ buffer }: { buffer: number }) => {
const carIdxEstTime = useTelemetryValues('CarIdxEstTime');
const drivers = useDriverStandings();
const carIdxLapDistPct = useTelemetryValues('CarIdxLapDistPct');
const carIdxLap = useTelemetryValues('CarIdxLap');

const playerIndex = useDriverCarIdx();
const driverCarEstLapTime = useSessionStore(
(s) => s.session?.DriverInfo?.DriverCarEstLapTime ?? 0
);

const standings = useMemo(() => {
const player = drivers.find((d) => d.carIdx === playerIndex);
if (!player) {
return [];
}
const calculateDelta = (otherCarIdx: number) => {
const playerCarIdx = playerIndex ?? 0;

const driverEstLapTime = player.carClass.estLapTime ?? 0;
const playerLapNum = carIdxLap?.[playerCarIdx];
const playerDistPct = carIdxLapDistPct?.[playerCarIdx];

const calculateDelta = (carIdx: number, isAhead: boolean) => {
const playerEstTime = carIdxEstTime?.[playerIndex ?? 0];
const oppositionEstTime = carIdxEstTime?.[carIdx];
const opposition = drivers.find((d) => d.carIdx === carIdx);
const otherLapNum = carIdxLap?.[otherCarIdx];
const otherDistPct = carIdxLapDistPct?.[otherCarIdx];

if (!opposition) {
return 0;
if (
playerLapNum === undefined || playerLapNum < 0 ||
playerDistPct === undefined || playerDistPct < 0 || playerDistPct > 1 ||
otherLapNum === undefined || otherLapNum < 0 ||
otherDistPct === undefined || otherDistPct < 0 || otherDistPct > 1 ||
driverCarEstLapTime <= 0
) {
return NaN;
}

let delta = (oppositionEstTime - playerEstTime);
let distPctDifference = otherDistPct - playerDistPct;

if (isAhead) {
// For cars ahead, use their lap time since they determine the full lap duration
while (delta < 0) delta += driverEstLapTime;
while (delta > 0.5 * driverEstLapTime) delta -= driverEstLapTime;
} else {
// For cars behind, use player's lap time since we're measuring against our lap
while (delta > 0) delta -= driverEstLapTime;
while (delta < -0.5 * driverEstLapTime) delta += driverEstLapTime;
if (distPctDifference > 0.5) {
distPctDifference -= 1.0;
} else if (distPctDifference < -0.5) {
distPctDifference += 1.0;
}

const timeDelta = distPctDifference * driverCarEstLapTime;

return delta;
return timeDelta;
};

const isHalfLapDifference = (car1: number, car2: number) => {
const diff = (car1 - car2 + 1) % 1; // Normalize the difference to [0, 1)
const diff = (car1 - car2 + 1) % 1;
return diff <= 0.5;
};

Expand All @@ -60,7 +66,7 @@ export const useDriverRelatives = ({ buffer }: { buffer: number }) => {
})
.map((result) => ({
...result,
delta: calculateDelta(result.carIdx, isAhead),
delta: calculateDelta(result.carIdx),
}))
.filter((result) => (isAhead ? result.delta > 0 : result.delta < 0))
.sort((a, b) => (isAhead ? a.delta - b.delta : b.delta - a.delta))
Expand All @@ -69,14 +75,24 @@ export const useDriverRelatives = ({ buffer }: { buffer: number }) => {
};

const carsAhead = filterAndMapDrivers(true);
const player = drivers.find((result) => result.carIdx === playerIndex);
const carsBehind = filterAndMapDrivers(false);

const relatives = [...carsAhead, { ...player, delta: 0 }, ...carsBehind];
if (!player) {
return [];
}

// TODO: remove pace car if not under caution or pacing
const relatives = [...carsAhead, { ...player, delta: 0 }, ...carsBehind];

return relatives;
}, [drivers, buffer, carIdxEstTime, playerIndex, carIdxLapDistPct]);
}, [
drivers,
buffer,
playerIndex,
driverCarEstLapTime,
carIdxLapDistPct,
carIdxLap,
]);

return standings;
};
2 changes: 1 addition & 1 deletion src/frontend/components/TrackMap/hooks/useTrackId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useSessionStore } from '@irdashies/context';

export const useTrackId = () => {
const trackId = useSessionStore(
(state) => state.session?.WeekendInfo.TrackID
(state) => state.session?.WeekendInfo?.TrackID
);
return trackId;
};