diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..3b5eb83 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,27 @@ +module.exports = { + root: true, + env: { + node: true, + es2023: true, + browser: true, + }, + parserOptions: { + ecmaVersion: 2023, + sourceType: 'module', + }, + ignores: ['data/**', 'public/**/vendor/**', 'scripts/**/tmp/**', 'tmp/**'], + plugins: ['import'], + extends: [ + 'eslint:recommended', + 'plugin:import/recommended', + 'plugin:import/errors', + 'plugin:import/warnings', + 'plugin:import/typescript', + 'prettier', + ], + rules: { + 'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + 'no-console': 'off', + 'import/no-unresolved': 'off', + }, +}; diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..451e943 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +data/ +public/audio/ +public/cover/ +**/*.mp3 +node_modules/ +.tmp/ +dist/ +coverage/ diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..c7a55c7 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "singleQuote": true, + "semi": true, + "trailingComma": "es5", + "printWidth": 100, + "tabWidth": 2 +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..03e918c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.formatOnSave": true, + "files.eol": "\n", + "eslint.validate": ["javascript"], + "eslint.format.enable": true +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..8b2baf8 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,13 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "start-dev", + "type": "shell", + "command": "npm run start", + "isBackground": false, + "problemMatcher": ["$eslint-stylish"], + "group": "build" + } + ] +} diff --git a/README.md b/README.md index aa39367..edb9fa8 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,29 @@ Run the app in a container while using your local `data/` music folder: -1) Build the image +1. Build the image ```powershell docker compose build ``` -2) Start the service +2. Start the service ```powershell docker compose up -d ``` -3) Open http://localhost:5173 +3. Open http://localhost:5173 Notes: + - Your local `data/` is mounted read/write at `/app/data` inside the container, so you can manage tracks on the host. - To rebuild after changes: `docker compose build --no-cache && docker compose up -d`. Lokales Multiplayer-Webspiel inspiriert von HITSTER. Nutzt eure MP3-Dateien im Ordner `data/`, eine Lobby mit Raum-Code sowie WebSockets für den Mehrspieler-Modus. ## Features + - Lobby mit Raum-Erstellung und -Beitritt (Code) - Mehrere Spieler pro Raum, Host startet das Spiel - Lokale MP3-Wiedergabe via Browser-Audio (`/audio/`) – keine externen Dienste @@ -34,10 +36,12 @@ Lokales Multiplayer-Webspiel inspiriert von HITSTER. Nutzt eure MP3-Dateien im O Hinweis: Regeln sind vereinfacht; „HITSTER!“-Challenges und exakter Zwischenplatzierungsmodus sind als Ausbaustufe geplant. ## Setup + 1. MP3-Dateien in `data/` legen (Dateiname wird als Fallback-Titel genutzt; falls Tags vorhanden, werden Titel/Künstler/Jahr ausgelesen). 2. Abhängigkeiten installieren und Server starten. ### PowerShell-Befehle + ```powershell # In den Projektordner wechseln Set-Location e:\git\hitstar @@ -52,25 +56,30 @@ npm start Dann im Browser öffnen: http://localhost:5173 ## Nutzung + - Namen setzen, Raum erstellen oder mit Code beitreten (Code wird angezeigt). - Host klickt „Spiel starten“. - DJ klickt „Lied scannen“; der Track spielt bei allen. - Aktiver Spieler wählt „Vor“ oder „Nach“. Bei Erfolg wandert das Lied in seine Zeitleiste. ## Ordnerstruktur + - `public/` – Client (HTML/CSS/JS) - `server.js` – Express + WebSocket Server, Game-State - `data/` – eure MP3-Dateien ## Git & Audio-Dateien + - In `.gitignore` sind alle gängigen Audio-Dateitypen ausgeschlossen (z. B. .mp3, .wav, .flac, .m4a, .ogg, …). - Legt eure Musik lokal in `data/`. Diese Dateien werden nicht ins Git-Repo eingecheckt und bleiben nur auf eurem Rechner. ## Nächste Schritte (optional) + - „HITSTER!“-Challenges per Token mit Positionsauswahl (zwischen zwei Karten) - Team-Modus, Pro-/Expert-Regeln, exaktes Jahr - Persistenz (Räume/Spielstände), Reconnect - Drag & Drop-Zeitleiste, visuelle Platzierung ## Hinweis + Nur für privaten Gebrauch. Musikdateien bleiben lokal bei euch. diff --git a/data/years.json b/data/years.json index 533a42c..14df92d 100644 --- a/data/years.json +++ b/data/years.json @@ -1816,8 +1816,8 @@ "mbid": "e9eb684a-5c5a-485e-ac76-ce799aeba7a0" }, "The Beach Boys - Surfin' U.S.A. (Mono).mp3": { - "year": 2008, - "date": "2008-06-10", + "year": 1963, + "date": "1963", "title": "Surfin' U.S.A. (Mono)", "artist": "The Beach Boys", "mbid": "fa52f01e-6c8c-46ff-860d-daa4930f93a4" @@ -5176,8 +5176,8 @@ "title": "Under Pressure", "artist": "Queen, David Bowie", "mbid": null, - "earliestDate": null, - "year": null, + "earliestDate": "1981", + "year": 1981, "error": "No recordings found" }, { @@ -6151,8 +6151,8 @@ "title": "China In Your Hand (Single Version)", "artist": "T'pau", "mbid": "56a5d0fc-a0c3-4e07-91b5-0c8c77b43ab2", - "earliestDate": "2009-06-08", - "year": 2009, + "earliestDate": "1987", + "year": 1987, "confidence": { "mbScore": 100, "titleSim": 1, diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..0b29d1c --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,32 @@ +import js from '@eslint/js'; +import globals from 'globals'; + +export default [ + { + files: ['**/*.js'], + ignores: [ + 'node_modules/**', + 'data/**', + 'public/audio/**', + 'public/cover/**', + '**/*.mp3', + '.tmp/**', + 'dist/**', + 'coverage/**', + ], + languageOptions: { + ecmaVersion: 2023, + sourceType: 'module', + globals: { + ...globals.node, + ...globals.browser, + }, + }, + rules: { + ...js.configs.recommended.rules, + 'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + 'no-console': 'off', + 'no-empty': ['warn', { allowEmptyCatch: true }], + }, + }, +]; diff --git a/package.json b/package.json index bfad438..b32fae1 100644 --- a/package.json +++ b/package.json @@ -6,21 +6,31 @@ "main": "src/server/index.js", "type": "module", "scripts": { - "start": "node src/server/index.js", - "dev": "nodemon src/server/index.js", - "years:resolve": "node scripts/resolve-years.js", - "years:resolve:10": "node scripts/resolve-years.js --max 10", - "years:force": "node scripts/resolve-years.js --force" + "start": "node src/server/index.js", + "dev": "nodemon src/server/index.js", + "years:resolve": "node scripts/resolve-years.js", + "years:resolve:10": "node scripts/resolve-years.js --max 10", + "years:force": "node scripts/resolve-years.js --force", + "lint": "eslint . --ext .js", + "lint:fix": "eslint . --ext .js --fix", + "format": "prettier --write \"**/*.{js,json,md,css,html}\"", + "format:check": "prettier --check \"**/*.{js,json,md,css,html}\"" }, "dependencies": { "express": "^4.19.2", "mime": "^3.0.0", "music-metadata": "^7.14.0", - "undici": "^6.19.8", + "undici": "^6.19.8", "uuid": "^9.0.1", - "ws": "^8.18.0" + "socket.io": "^4.7.5" }, "devDependencies": { - "nodemon": "^3.1.0" + "nodemon": "^3.1.0", + "eslint": "^9.11.1", + "@eslint/js": "^9.11.1", + "globals": "^13.24.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "prettier": "^3.3.3" } } diff --git a/public/index.html b/public/index.html index dfb6e56..ba246d1 100644 --- a/public/index.html +++ b/public/index.html @@ -5,53 +5,118 @@ Hitstar Web +

Hitstar

-

Lokales Multiplayer-Spiel mit deiner eigenen Musik

+

+ Lokales Multiplayer-Spiel mit deiner eigenen Musik +

- -
Code kopiert!
+ +
+ Code kopiert! +
-
+
- +
- - - + + +
-