diff --git a/.eslintrc.json b/.eslintrc.json index 201789d..6f107d4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -42,6 +42,10 @@ "node/no-extraneous-require": "off", "node/no-unsupported-features/node-builtins": "off", "no-empty": "warn", - "no-mixed-spaces-and-tabs": "warn" + "no-mixed-spaces-and-tabs": "warn", + "no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0, "maxBOF": 0 }], + "no-trailing-spaces": "error", + "padded-blocks": ["error", "never"], + "eol-last": ["error", "always"] } } \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5c46032..b2d322c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ logs/ dist/ release/ bin/ -/release-builds -/logs/*.log +release-builds/ +logs/*.log +dev/agents/ \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4083d42 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,34 @@ +Mini4wdChrono is a Mini4wd lap timer program with race management. It is aimed at Mini4wd clubs who want to host races. +It is a standalone program which is meant to be paired with a hardware lap timer. + +## Your role +- You are a backend developer, expert in plain javascript and electron. +- Your job is to help upgrading parts of the program and to develop new features. + +## Project knowledge +- **Tech Stack:** Electron with vanilla javascript. Plain html with Bulma for css. +- **Architecture:** IPC-based separation between main and renderer processes + - Main process handles all hardware communication (johnny-five, serialport v13, firmata) + - Renderer process handles UI and race logic + - Communication via Electron IPC (contextIsolation: false) + +- **File Structure:** + - `index.html` - main frontend + - `window.js` - Electron main process entry point (handles IPC, hardware, file system) + - `preload.js` - Exposes IPC APIs to renderer via `window.electronAPI` + - `js/` – Application source code (renderer process) + - `js/main.js` – Renderer initialization and IPC event handlers + - `js/client.js` - Race handling logic and program orchestrator + - `js/chrono.js` - Lap timer logic with microsecond-precision timestamps (DO NOT change this file) + - `js/ui.js` - Frontend rendering logic + - `js/led_managers/` - LED abstraction layer (talks to main process via IPC) + +## Boundaries +- Only change code in the `js/` folder, and other javascript files in the root directory. +- Do not change `js/chrono.js` which contains battle-tested lap timer logic. +- Do not change the `index.html` and css files. +- Hardware operations must go through IPC - never use johnny-five or serialport directly in renderer +- Timestamps for lap timing are captured in main process at sensor trigger for accuracy + +## Lap timer hardware +Mini4wdChrono connects via usb to a physical lap timer. The lap timer looks like a bridge over the three lanes of a mini4wd track. It is powered by an arduino with firmata firmware, and has 3 light sensor to detect the cars passing under the lap timer. It also sports an rgb led strip for visual feedback and a buzzer for alerts. \ No newline at end of file diff --git a/i18n/en.json b/i18n/en.json index 1d5ef54..6ee8f5a 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -82,13 +82,10 @@ "label-best-speed-km": "Best speed km/h", "label-custom-title": "Your team/club name", "label-starting-tab": "Starting screen", - "label-led-type": "LED type", "label-led-animation": "LED animation at race start (only for RGB strip)", "button-led-animation-full": "Animation + countdown", "button-led-animation-cd": "Countdown only", "button-led-animation-off": "None", - "button-led-type-normal": "3 single LEDs", - "button-led-type-strip": "Multicolor LED strip", "label-usb-port": "USB Port", "label-direction": "Direction", "label-reverse": "Invert left-right", diff --git a/i18n/i18n.js b/i18n/i18n.js index 04f32b2..9844eb6 100644 --- a/i18n/i18n.js +++ b/i18n/i18n.js @@ -1,6 +1,5 @@ 'use strict'; -const { app } = require('electron').remote; const fs = require('fs'); const path = require('path'); let loadedLanguage; @@ -8,13 +7,20 @@ let loadedLanguage; module.exports = i18n; function i18n() { - const tnpath = path.join(__dirname, app.getLocale().substring(0, 2) + '.json'); - // tnpath = path.join(__dirname, 'it.json'); // uncomment this line to force italian language - if (fs.existsSync(tnpath)) { - loadedLanguage = JSON.parse(fs.readFileSync(tnpath), 'utf8'); - } - else { - loadedLanguage = JSON.parse(fs.readFileSync(path.join(__dirname, 'en.json'), 'utf8')); + // Load English by default, we'll try to get the proper locale asynchronously + loadedLanguage = JSON.parse(fs.readFileSync(path.join(__dirname, 'en.json'), 'utf8')); + + // Try to load the correct locale asynchronously + if (window.electronAPI && window.electronAPI.getAppLocale) { + window.electronAPI.getAppLocale().then(locale => { + const tnpath = path.join(__dirname, locale.substring(0, 2) + '.json'); + // tnpath = path.join(__dirname, 'it.json'); // uncomment this line to force italian language + if (fs.existsSync(tnpath)) { + loadedLanguage = JSON.parse(fs.readFileSync(tnpath), 'utf8'); + } + }).catch(err => { + console.warn('Could not load locale, using English:', err); + }); } } diff --git a/i18n/it.json b/i18n/it.json index ab97b1b..fcc1536 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -86,9 +86,6 @@ "button-led-animation-full": "Animazione + conto alla rovescia", "button-led-animation-cd": "Solo conto alla rovescia", "button-led-animation-off": "Nessuna", - "label-led-type": "Tipo di LED", - "button-led-type-normal": "3 LED singoli", - "button-led-type-strip": "Striscia LED multicolore", "label-usb-port": "Porta USB", "label-direction": "Senso di marcia", "label-reverse": "Inverti destra-sinistra", diff --git a/index.html b/index.html index 3f77f43..76d2762 100644 --- a/index.html +++ b/index.html @@ -494,18 +494,6 @@
-