From d906cf486b0781b86f1d59085b6ee5c7f4c47179 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Tue, 19 Nov 2024 23:25:52 +0100 Subject: [PATCH 01/25] Created linter in interface module --- interface/.eslintrc.js | 17 + interface/constants/TrackType.ts | 6 +- interface/index.ts | 2 +- interface/package-lock.json | 1866 +++++++++++++++++++++++++++++- interface/package.json | 14 +- 5 files changed, 1895 insertions(+), 10 deletions(-) create mode 100644 interface/.eslintrc.js diff --git a/interface/.eslintrc.js b/interface/.eslintrc.js new file mode 100644 index 0000000..9700d32 --- /dev/null +++ b/interface/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + parser: "@typescript-eslint/parser", + parserOptions: { + project: "tsconfig.json", + tsconfigRootDir: __dirname, + sourceType: "module", + }, + plugins: ["@typescript-eslint/eslint-plugin"], + extends: ["plugin:@typescript-eslint/strict", "plugin:prettier/recommended"], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: [".eslintrc.js", "dist/"], + rules: {}, +}; diff --git a/interface/constants/TrackType.ts b/interface/constants/TrackType.ts index 4e68f01..c4e2830 100644 --- a/interface/constants/TrackType.ts +++ b/interface/constants/TrackType.ts @@ -1,4 +1,4 @@ export enum TrackType { - RAIL = "RAIL", - ROAD = "ROAD" -}; + RAIL = "RAIL", + ROAD = "ROAD", +} diff --git a/interface/index.ts b/interface/index.ts index f4c0cdf..ac13701 100644 --- a/interface/index.ts +++ b/interface/index.ts @@ -1 +1 @@ -export * from "./constants/TrackType" \ No newline at end of file +export * from "./constants/TrackType"; diff --git a/interface/package-lock.json b/interface/package-lock.json index 23ae191..3c02071 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -1,16 +1,240 @@ { - "name": "common_logic", + "name": "interface", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "common_logic", + "name": "interface", "version": "1.0.0", "license": "ISC", "devDependencies": { + "@eslint/js": "^8.0.0", "@types/node": "^22.9.0", - "typescript": "^5.6.3" + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", + "eslint": "^8.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.12.0", + "typescript": "^5.6.3", + "typescript-eslint": "^8.15.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" } }, "node_modules/@types/node": { @@ -22,6 +246,1559 @@ "undici-types": "~6.19.8" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/synckit": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", @@ -35,11 +1812,94 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz", + "integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.15.0", + "@typescript-eslint/parser": "8.15.0", + "@typescript-eslint/utils": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/interface/package.json b/interface/package.json index 0233457..4614b15 100644 --- a/interface/package.json +++ b/interface/package.json @@ -5,13 +5,21 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc" + "build": "npm run lint && tsc", + "lint": "eslint \"*.ts\" \"*/**/*.ts\" --fix" }, "author": "", "license": "ISC", "devDependencies": { + "@eslint/js": "^8.0.0", "@types/node": "^22.9.0", - "typescript": "^5.6.3" + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", + "eslint": "^8.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.12.0", + "typescript": "^5.6.3", + "typescript-eslint": "^8.15.0" } } -- 2.40.1 From 250325d8d21d0a5400a490701d7246587e403bf0 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Tue, 19 Nov 2024 23:33:22 +0100 Subject: [PATCH 02/25] Pass linter on server build and start --- app/package.json | 6 +++--- app/src/app.service.ts | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/package.json b/app/package.json index c4cc9fd..105a572 100644 --- a/app/package.json +++ b/app/package.json @@ -6,12 +6,12 @@ "private": true, "license": "UNLICENSED", "scripts": { - "build": "nest build", + "build": "npm run lint && nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", - "start": "nest start --watch", + "start": "npm run build && nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "lint": "eslint \"src/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", diff --git a/app/src/app.service.ts b/app/src/app.service.ts index d633b44..72ea3d2 100644 --- a/app/src/app.service.ts +++ b/app/src/app.service.ts @@ -1,5 +1,9 @@ import { Injectable, Logger } from '@nestjs/common'; -import { MessageBody, SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'; +import { + MessageBody, + SubscribeMessage, + WebSocketGateway, +} from '@nestjs/websockets'; @WebSocketGateway({ cors: true }) @Injectable() @@ -9,6 +13,9 @@ export class AppService { @SubscribeMessage('example-request') handleCustomEvent(@MessageBody() data: string): unknown { this.logger.debug(`Received request in backend with data: ${data}`); - return {event: "example-response", data: `Replying from backend, received data: ${data}`}; + return { + event: 'example-response', + data: `Replying from backend, received data: ${data}`, + }; } } -- 2.40.1 From 56705d35743fdadab4f7b51c050a8bef8e8ad07d Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Wed, 20 Nov 2024 23:29:21 +0100 Subject: [PATCH 03/25] Add eslint to web module --- web/.eslintrc.js | 17 + web/package-lock.json | 926 +++++++++++++++++++++++++++++++++++++++--- web/package.json | 13 +- web/src/App.test.tsx | 8 +- web/src/App.tsx | 13 +- web/src/index.tsx | 12 +- web/src/setupTests.ts | 2 +- 7 files changed, 916 insertions(+), 75 deletions(-) create mode 100644 web/.eslintrc.js diff --git a/web/.eslintrc.js b/web/.eslintrc.js new file mode 100644 index 0000000..9700d32 --- /dev/null +++ b/web/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + parser: "@typescript-eslint/parser", + parserOptions: { + project: "tsconfig.json", + tsconfigRootDir: __dirname, + sourceType: "module", + }, + plugins: ["@typescript-eslint/eslint-plugin"], + extends: ["plugin:@typescript-eslint/strict", "plugin:prettier/recommended"], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: [".eslintrc.js", "dist/"], + rules: {}, +}; diff --git a/web/package-lock.json b/web/package-lock.json index c572af6..cff312f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -24,14 +24,30 @@ "socket.io-client": "^4.8.1", "typescript": "^4.9.5", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "@eslint/js": "^8.0.0", + "@typescript-eslint/parser": "^8.15.0", + "eslint": "^8.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "typescript-eslint": "^8.15.0" } }, "../interface": { "version": "1.0.0", "license": "ISC", "devDependencies": { + "@eslint/js": "^8.0.0", "@types/node": "^22.9.0", - "typescript": "^5.6.3" + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", + "eslint": "^8.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.12.0", + "typescript": "^5.6.3", + "typescript-eslint": "^8.15.0" } }, "node_modules/@adobe/css-tools": { @@ -3391,6 +3407,19 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", @@ -4343,32 +4372,32 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", + "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -4376,6 +4405,152 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/experimental-utils": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", @@ -4396,25 +4571,27 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -4422,6 +4599,124 @@ } } }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", @@ -4440,25 +4735,26 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", + "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -4466,6 +4762,152 @@ } } }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/types": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", @@ -7663,6 +8105,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-config-react-app": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", @@ -7691,6 +8146,118 @@ "eslint": "^8.0.0" } }, + "node_modules/eslint-config-react-app/node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-react-app/node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-react-app/node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-react-app/node_modules/eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -7818,30 +8385,6 @@ "semver": "bin/semver.js" } }, - "node_modules/eslint-plugin-jest": { - "version": "25.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", - "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/experimental-utils": "^5.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", @@ -7871,6 +8414,37 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-plugin-react": { "version": "7.37.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", @@ -8367,6 +8941,13 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -13894,6 +14475,36 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -16218,6 +16829,23 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "license": "MIT" }, + "node_modules/synckit": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tailwindcss": { "version": "3.4.14", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", @@ -16517,6 +17145,19 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "license": "MIT" }, + "node_modules/ts-api-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -16724,6 +17365,179 @@ "node": ">=4.2.0" } }, + "node_modules/typescript-eslint": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz", + "integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.15.0", + "@typescript-eslint/parser": "8.15.0", + "@typescript-eslint/utils": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/typescript-eslint/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typescript-eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/typescript-eslint/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", diff --git a/web/package.json b/web/package.json index 6a469ba..f240e25 100644 --- a/web/package.json +++ b/web/package.json @@ -22,9 +22,10 @@ }, "scripts": { "start": "react-scripts start", - "build": "react-scripts build", + "build": "npm run lint && react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "lint": "eslint \"*/**/*.tsx\" \"*/**/*.ts\" --fix" }, "eslintConfig": { "extends": [ @@ -43,5 +44,13 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@eslint/js": "^8.0.0", + "@typescript-eslint/parser": "^8.15.0", + "eslint": "^8.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "typescript-eslint": "^8.15.0" } } diff --git a/web/src/App.test.tsx b/web/src/App.test.tsx index c1b280a..b97f69b 100644 --- a/web/src/App.test.tsx +++ b/web/src/App.test.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; +import React from "react"; +import { render, screen } from "@testing-library/react"; +import App from "./App"; -test('Renders hello world', () => { +test("Renders hello world", () => { render(); expect(screen.getByText("Hello World! Front")).toBeInTheDocument(); }); diff --git a/web/src/App.tsx b/web/src/App.tsx index c3f90f1..9e26c1a 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,17 +1,18 @@ -import React from 'react'; +import React from "react"; import { io } from "socket.io-client"; function App() { const socket = io("http://localhost:3010"); - const emitData = () => console.log(socket.emit("example-request", "custom-request")); - socket.on("example-response", (data) => console.log(`Received response in front end with data: ${data}`)); + const emitData = () => + console.log(socket.emit("example-request", "custom-request")); + socket.on("example-response", (data) => + console.log(`Received response in front end with data: ${data}`), + ); return (
- + Hello World! Front
diff --git a/web/src/index.tsx b/web/src/index.tsx index 359f3ed..dd89d8c 100644 --- a/web/src/index.tsx +++ b/web/src/index.tsx @@ -1,13 +1,13 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from './App'; -import './App.scss' +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import "./App.scss"; const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById("root") as HTMLElement, ); root.render( - + , ); diff --git a/web/src/setupTests.ts b/web/src/setupTests.ts index 8f2609b..1dd407a 100644 --- a/web/src/setupTests.ts +++ b/web/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +import "@testing-library/jest-dom"; -- 2.40.1 From 4497a0a2f2b94dfee2c4f8ebb7211ba31a86ec06 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sat, 23 Nov 2024 15:02:09 +0100 Subject: [PATCH 04/25] Created baseline for game page grid layout --- web/.eslintrc.js | 9 ++- web/src/App.scss | 5 +- web/src/App.tsx | 9 +-- web/src/pages/game/GamePage.scss | 5 ++ web/src/pages/game/GamePage.tsx | 15 ++++ web/src/pages/game/components/GameBoard.scss | 79 ++++++++++++++++++++ web/src/pages/game/components/GameBoard.tsx | 76 +++++++++++++++++++ 7 files changed, 189 insertions(+), 9 deletions(-) create mode 100644 web/src/pages/game/GamePage.scss create mode 100644 web/src/pages/game/GamePage.tsx create mode 100644 web/src/pages/game/components/GameBoard.scss create mode 100644 web/src/pages/game/components/GameBoard.tsx diff --git a/web/.eslintrc.js b/web/.eslintrc.js index 9700d32..7fd62a1 100644 --- a/web/.eslintrc.js +++ b/web/.eslintrc.js @@ -13,5 +13,12 @@ module.exports = { jest: true, }, ignorePatterns: [".eslintrc.js", "dist/"], - rules: {}, + rules: { + "prettier/prettier": [ + "error", + { + endOfLine: "auto", + }, + ], + }, }; diff --git a/web/src/App.scss b/web/src/App.scss index 56dbdc3..55aefe1 100644 --- a/web/src/App.scss +++ b/web/src/App.scss @@ -1,3 +1,6 @@ @use "node_modules/@picocss/pico/scss/pico" with ( $theme-color: "pumpkin" -); \ No newline at end of file +); + +@import "./pages/game/GamePage.scss"; +@import "./pages/game/components/GameBoard.scss"; diff --git a/web/src/App.tsx b/web/src/App.tsx index 9e26c1a..8778670 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,20 +1,15 @@ -import React from "react"; import { io } from "socket.io-client"; +import GamePage from "./pages/game/GamePage"; function App() { const socket = io("http://localhost:3010"); - const emitData = () => - console.log(socket.emit("example-request", "custom-request")); socket.on("example-response", (data) => console.log(`Received response in front end with data: ${data}`), ); return (
-
- - Hello World! Front -
+
); } diff --git a/web/src/pages/game/GamePage.scss b/web/src/pages/game/GamePage.scss new file mode 100644 index 0000000..1cbf756 --- /dev/null +++ b/web/src/pages/game/GamePage.scss @@ -0,0 +1,5 @@ +h1 { + text-align: center; + padding: 10px; + margin: 0; +} diff --git a/web/src/pages/game/GamePage.tsx b/web/src/pages/game/GamePage.tsx new file mode 100644 index 0000000..663aefc --- /dev/null +++ b/web/src/pages/game/GamePage.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import GameBoard from "./components/GameBoard"; + +const GamePage = () => { + return ( + +

Game Page Title

+
+ +
+
+ ); +}; + +export default GamePage; diff --git a/web/src/pages/game/components/GameBoard.scss b/web/src/pages/game/components/GameBoard.scss new file mode 100644 index 0000000..477f4cc --- /dev/null +++ b/web/src/pages/game/components/GameBoard.scss @@ -0,0 +1,79 @@ +.game-board { + height: 700px; + width: 700px; + display: grid; + grid-template-columns: repeat(11, auto); + gap: auto; + padding: 10px; + + .cell { + width: 60px; + height: 60px; + border: 2px solid black; + border-radius: 10%; + } + + .v-exit { + width: 60px; + height: 30px; + + > div { + width: 20px; + height: 100%; + margin: auto; + border: solid black; + border-width: 0 1px; + + .dotted { + margin: auto; + border: dashed black; + border-width: 0 1px; + height: 100%; + width: 0; + } + } + + &:has(.v-exit-up) { + margin-bottom: -9px; + } + + &:has(.v-exit-down) { + margin-top: -9px; + } + } + + .h-exit { + height: 60px; + width: 30px; + + > div { + height: 20px; + width: 100%; + margin: auto; + border: solid black; + border-width: 1px 0; + position: relative; + top: 50%; + transform: translateY(-50%); + + .dotted { + margin: auto; + border: dashed black; + border-width: 1px 0; + width: 100%; + height: 0; + position: relative; + top: 50%; + transform: translateY(-50%); + } + } + + &:has(.h-exit-left) { + margin-right: -9px; + } + + &:has(.h-exit-right) { + margin-left: -9px; + } + } +} \ No newline at end of file diff --git a/web/src/pages/game/components/GameBoard.tsx b/web/src/pages/game/components/GameBoard.tsx new file mode 100644 index 0000000..31078b1 --- /dev/null +++ b/web/src/pages/game/components/GameBoard.tsx @@ -0,0 +1,76 @@ +const GameBoard = () => { + const range = (n: number) => Array.from(Array(n).keys()); + const cells = range(11).flatMap((rowIndex) => { + return range(11).map((colIndex) => { + return { rowIndex, colIndex }; + }); + }); + + return ( +
+ {cells.map(({ rowIndex, colIndex }) => { + if ( + (rowIndex === 0 || rowIndex === 10) && + (colIndex === 0 || colIndex === 10) + ) { + return
; + } + if (rowIndex === 0) { + return ( +
+
+
+
+
+ ); + } + if (rowIndex === 10) { + return ( +
+
+
+
+
+ ); + } + if (colIndex === 0) { + return ( +
+
+
+
+
+ ); + } + if (colIndex === 10) { + return ( +
+
+
+
+
+ ); + } + return
; + })} +
+ ); + + /* + {range(9).map(() => ( +
+
+
+ ))} + {range(81).map(() => ( +
+ ))} + {range(9).map(() => ( +
+
+
+ ))} + */ +}; + +export default GameBoard; -- 2.40.1 From e9305893cbc5cfc805ad1e8815c299fd27074086 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sat, 23 Nov 2024 22:49:51 +0100 Subject: [PATCH 05/25] Create board object builder and supporting classes and types --- interface/BoardBuilder.ts | 110 +++++++++++++++++++++++++++++++ interface/constants/CellType.ts | 6 ++ interface/constants/Direction.ts | 6 ++ interface/constants/ExitType.ts | 5 ++ interface/index.ts | 9 +++ interface/types/Border.ts | 22 +++++++ interface/types/Cell.ts | 24 +++++++ interface/types/Exit.ts | 9 +++ interface/types/ExternalNode.ts | 24 +++++++ interface/types/Node.ts | 9 +++ 10 files changed, 224 insertions(+) create mode 100644 interface/BoardBuilder.ts create mode 100644 interface/constants/CellType.ts create mode 100644 interface/constants/Direction.ts create mode 100644 interface/constants/ExitType.ts create mode 100644 interface/types/Border.ts create mode 100644 interface/types/Cell.ts create mode 100644 interface/types/Exit.ts create mode 100644 interface/types/ExternalNode.ts create mode 100644 interface/types/Node.ts diff --git a/interface/BoardBuilder.ts b/interface/BoardBuilder.ts new file mode 100644 index 0000000..c4ed092 --- /dev/null +++ b/interface/BoardBuilder.ts @@ -0,0 +1,110 @@ +import { CellType } from "./constants/CellType"; +import { Direction } from "./constants/Direction"; +import { ExitType } from "./constants/ExitType"; +import { Cell } from "./types/Cell"; +import { Exit } from "./types/Exit"; + +const boardSize = 7; +const universityLocations = [ + [2, 0], + [4, 1], + [3, 3], +]; +const factoryLocations = [ + [0, 0], + [5, 2], + [4, 6], +]; +const houseLocations = [ + [0, 2], + [1, 5], + [2, 4], + [5, 4], +]; +const mapPosition = (position: number[], type: CellType) => { + return { + row: position[0], + col: position[1], + type: type, + }; +}; +const specialUniversityCells = universityLocations.map((position) => + mapPosition(position, CellType.UNIVERSITY), +); +const specialFactoryCells = factoryLocations.map((position) => + mapPosition(position, CellType.FACTORY), +); +const specialHouseCells = houseLocations.map((position) => + mapPosition(position, CellType.HOUSE), +); +const specialCells = specialUniversityCells + .concat(specialFactoryCells) + .concat(specialHouseCells); + +const specialExitIndexes1 = [1, 5]; +const specialExitIndexes2 = [3]; + +function createBoard(): Cell[][] { + const indexes = Array.from(Array(boardSize).keys()); + return indexes.map((rowIndex) => + indexes.map((colIndex) => { + const specialCell = specialCells.find( + (specialCell) => + specialCell.row === rowIndex && specialCell.col === colIndex, + ); + return new Cell(specialCell ? specialCell.type : CellType.NORMAL); + }), + ); +} + +function connectAdjacentCells(board: Cell[][]) { + const indexes = Array.from(Array(boardSize).keys()); + for (const rowIndex of indexes.slice(0, -1)) { + for (const colIndex of indexes.slice(0, -1)) { + const cell = board[rowIndex][colIndex]; + const rightCell = board[rowIndex][colIndex + 1]; + const bottomCell = board[rowIndex + 1][colIndex]; + + cell + .getNodeAt(Direction.SOUTH) + .linkToNode(bottomCell.getNodeAt(Direction.NORTH)); + cell + .getNodeAt(Direction.EAST) + .linkToNode(rightCell.getNodeAt(Direction.WEST)); + } + } +} + +function addExits(board: Cell[][]) { + // Add exits to top row + board[0].forEach((cell, colIndex) => { + let exitType = ExitType.AMBIVALENT; + if (specialExitIndexes1.includes(colIndex)) exitType = ExitType.ROAD; + if (specialExitIndexes2.includes(colIndex)) exitType = ExitType.RAIL; + cell.getNodeAt(Direction.NORTH).linkToNode(new Exit(exitType)); + }); + + // Add exits to bottom row + board[boardSize - 1].forEach((cell, colIndex) => { + let exitType = ExitType.AMBIVALENT; + if (specialExitIndexes1.includes(colIndex)) exitType = ExitType.ROAD; + if (specialExitIndexes2.includes(colIndex)) exitType = ExitType.RAIL; + cell.getNodeAt(Direction.SOUTH).linkToNode(new Exit(exitType)); + }); + + // Add exits to left and right columns + board.forEach((row, rowIndex) => { + let exitType = ExitType.AMBIVALENT; + if (specialExitIndexes1.includes(rowIndex)) exitType = ExitType.RAIL; + if (specialExitIndexes2.includes(rowIndex)) exitType = ExitType.ROAD; + row[0].getNodeAt(Direction.WEST).linkToNode(new Exit(exitType)); + row[boardSize - 1].getNodeAt(Direction.EAST).linkToNode(new Exit(exitType)); + }); +} + +export function buildBoard(): Cell[][] { + const board: Cell[][] = createBoard(); + connectAdjacentCells(board); + addExits(board); + return board; +} diff --git a/interface/constants/CellType.ts b/interface/constants/CellType.ts new file mode 100644 index 0000000..a22a68e --- /dev/null +++ b/interface/constants/CellType.ts @@ -0,0 +1,6 @@ +export enum CellType { + NORMAL = "NORMAL", + HOUSE = "HOUSE", + FACTORY = "FACTORY", + UNIVERSITY = "UNIVERSITY", +} diff --git a/interface/constants/Direction.ts b/interface/constants/Direction.ts new file mode 100644 index 0000000..1f54f0c --- /dev/null +++ b/interface/constants/Direction.ts @@ -0,0 +1,6 @@ +export enum Direction { + NORTH = "NORTH", + SOUTH = "SOUTH", + EAST = "EAST", + WEST = "WEST", +} diff --git a/interface/constants/ExitType.ts b/interface/constants/ExitType.ts new file mode 100644 index 0000000..2a6bf4c --- /dev/null +++ b/interface/constants/ExitType.ts @@ -0,0 +1,5 @@ +export enum ExitType { + RAIL = "RAIL", + ROAD = "ROAD", + AMBIVALENT = "AMBIVALENT", +} diff --git a/interface/index.ts b/interface/index.ts index ac13701..a686c28 100644 --- a/interface/index.ts +++ b/interface/index.ts @@ -1 +1,10 @@ +export * from "./constants/CellType"; +export * from "./constants/Direction"; +export * from "./constants/ExitType"; export * from "./constants/TrackType"; +export * from "./types/Border"; +export * from "./types/Cell"; +export * from "./types/Exit"; +export * from "./types/ExternalNode"; +export * from "./types/Node"; +export * from "./BoardBuilder"; diff --git a/interface/types/Border.ts b/interface/types/Border.ts new file mode 100644 index 0000000..f5618c9 --- /dev/null +++ b/interface/types/Border.ts @@ -0,0 +1,22 @@ +import { Exit } from "./Exit"; +import { ExternalNode } from "./ExternalNode"; + +export class Border { + private readonly firstNode: ExternalNode; + private readonly secondNode: ExternalNode | Exit; + + constructor(firstNode: ExternalNode, secondNode: ExternalNode | Exit) { + this.firstNode = firstNode; + this.secondNode = secondNode; + } + + public traverseFrom(node: ExternalNode): ExternalNode | Exit { + if (node === this.firstNode) { + return this.secondNode; + } + if (node === this.secondNode) { + return this.firstNode; + } + throw Error("Unable to traverse border"); + } +} diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts new file mode 100644 index 0000000..822ce34 --- /dev/null +++ b/interface/types/Cell.ts @@ -0,0 +1,24 @@ +import { CellType } from "../constants/CellType"; +import { Direction } from "../constants/Direction"; +import { ExternalNode } from "./ExternalNode"; + +export class Cell { + public readonly externalNodes: Map; + public readonly cellType: CellType; + + constructor(cellType: CellType) { + this.externalNodes = new Map([ + [Direction.NORTH, new ExternalNode(this, Direction.NORTH)], + [Direction.SOUTH, new ExternalNode(this, Direction.SOUTH)], + [Direction.EAST, new ExternalNode(this, Direction.EAST)], + [Direction.WEST, new ExternalNode(this, Direction.WEST)], + ]); + this.cellType = cellType; + } + + public getNodeAt(direction: Direction): ExternalNode { + const node = this.externalNodes.get(direction); + if (!node) throw Error(`Could not find node at ${direction}`); + return this.externalNodes.get(direction) as ExternalNode; + } +} diff --git a/interface/types/Exit.ts b/interface/types/Exit.ts new file mode 100644 index 0000000..38fe187 --- /dev/null +++ b/interface/types/Exit.ts @@ -0,0 +1,9 @@ +import { ExitType } from "../constants/ExitType"; + +export class Exit { + public readonly type: ExitType; + + constructor(type: ExitType) { + this.type = type; + } +} diff --git a/interface/types/ExternalNode.ts b/interface/types/ExternalNode.ts new file mode 100644 index 0000000..c951c54 --- /dev/null +++ b/interface/types/ExternalNode.ts @@ -0,0 +1,24 @@ +import { Direction } from "../constants/Direction"; +import { Border } from "./Border"; +import { Cell } from "./Cell"; +import { Exit } from "./Exit"; +import { Node } from "./Node"; + +export class ExternalNode extends Node { + public readonly direction: Direction; + private border?: Border; + + constructor(cell: Cell, direction: Direction) { + super(cell); + this.direction = direction; + } + + public linkToNode(other: ExternalNode | Exit) { + this.border = new Border(this, other); + } + + public traverseBorder(): ExternalNode | Exit { + if (!this.border) throw Error(`Missing border for node`); + return (this.border as Border).traverseFrom(this); + } +} diff --git a/interface/types/Node.ts b/interface/types/Node.ts new file mode 100644 index 0000000..b185ad2 --- /dev/null +++ b/interface/types/Node.ts @@ -0,0 +1,9 @@ +import { Cell } from "./Cell"; + +export abstract class Node { + public readonly cell: Cell; + + constructor(cell: Cell) { + this.cell = cell; + } +} -- 2.40.1 From 0945336463ba8e1853f6db96af7aa748a526d752 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sun, 24 Nov 2024 15:07:10 +0100 Subject: [PATCH 06/25] Implement board view based on board builder --- interface/BoardBuilder.ts | 11 +- interface/constants/Direction.ts | 7 + interface/types/ExternalNode.ts | 7 +- web/src/pages/game/components/GameBoard.scss | 150 ++++++++++++------- web/src/pages/game/components/GameBoard.tsx | 89 +++-------- 5 files changed, 141 insertions(+), 123 deletions(-) diff --git a/interface/BoardBuilder.ts b/interface/BoardBuilder.ts index c4ed092..e2e79c7 100644 --- a/interface/BoardBuilder.ts +++ b/interface/BoardBuilder.ts @@ -60,14 +60,19 @@ function createBoard(): Cell[][] { function connectAdjacentCells(board: Cell[][]) { const indexes = Array.from(Array(boardSize).keys()); for (const rowIndex of indexes.slice(0, -1)) { - for (const colIndex of indexes.slice(0, -1)) { + for (const colIndex of indexes) { const cell = board[rowIndex][colIndex]; - const rightCell = board[rowIndex][colIndex + 1]; const bottomCell = board[rowIndex + 1][colIndex]; - cell .getNodeAt(Direction.SOUTH) .linkToNode(bottomCell.getNodeAt(Direction.NORTH)); + } + } + + for (const rowIndex of indexes) { + for (const colIndex of indexes.slice(0, -1)) { + const cell = board[rowIndex][colIndex]; + const rightCell = board[rowIndex][colIndex + 1]; cell .getNodeAt(Direction.EAST) .linkToNode(rightCell.getNodeAt(Direction.WEST)); diff --git a/interface/constants/Direction.ts b/interface/constants/Direction.ts index 1f54f0c..6bc4347 100644 --- a/interface/constants/Direction.ts +++ b/interface/constants/Direction.ts @@ -4,3 +4,10 @@ export enum Direction { EAST = "EAST", WEST = "WEST", } + +export const directions: Direction[] = [ + Direction.NORTH, + Direction.SOUTH, + Direction.EAST, + Direction.WEST, +]; diff --git a/interface/types/ExternalNode.ts b/interface/types/ExternalNode.ts index c951c54..14dcbbe 100644 --- a/interface/types/ExternalNode.ts +++ b/interface/types/ExternalNode.ts @@ -15,10 +15,15 @@ export class ExternalNode extends Node { public linkToNode(other: ExternalNode | Exit) { this.border = new Border(this, other); + if (other instanceof ExternalNode) { + other.border = this.border; + } } public traverseBorder(): ExternalNode | Exit { - if (!this.border) throw Error(`Missing border for node`); + if (!this.border) { + throw Error(`Missing border for node`); + } return (this.border as Border).traverseFrom(this); } } diff --git a/web/src/pages/game/components/GameBoard.scss b/web/src/pages/game/components/GameBoard.scss index 477f4cc..fca4d47 100644 --- a/web/src/pages/game/components/GameBoard.scss +++ b/web/src/pages/game/components/GameBoard.scss @@ -1,79 +1,125 @@ .game-board { - height: 700px; - width: 700px; + height: 850px; + width: 850px; display: grid; - grid-template-columns: repeat(11, auto); + grid-template-columns: repeat(7, auto); gap: auto; - padding: 10px; + padding: 50px; .cell { - width: 60px; - height: 60px; + width: 100px; + height: 100px; border: 2px solid black; border-radius: 10%; - } - .v-exit { - width: 60px; - height: 30px; - - > div { - width: 20px; - height: 100%; - margin: auto; + &.house { + background-color: blue; + } + + &.university { + background-color: orange; + } + + &.factory { + background-color: grey; + } + + .exit:has(.exit-road) { border: solid black; border-width: 0 1px; - .dotted { + .exit-road { margin: auto; + width: 0; + height: 100%; border: dashed black; border-width: 0 1px; - height: 100%; + transform: translate(calc(50% - 1px)); + } + } + + .exit:has(.exit-road) { + border: solid black; + border-width: 0 1px; + + .exit-road { + margin: auto; width: 0; + height: 100%; + border: dashed black; + border-width: 0 1px; + transform: translate(calc(50% - 1px)); } } - &:has(.v-exit-up) { - margin-bottom: -9px; + .exit:has(.exit-rail) { + border-width: 0 1px; + + .exit-rail { + margin: auto; + width: 0; + height: 100%; + border: solid black; + border-width: 0 1px; + transform: translate(calc(50% - 1px)); + } } - &:has(.v-exit-down) { - margin-top: -9px; + .exit:has(.exit-ambivalent) { + border-width: 0 1px; + border-style: dotted; + + .exit-ambivalent { + margin: auto; + width: 0; + height: 100%; + border: dotted black; + border-width: 0 1px 0 0; + transform: translate(calc(50%)); + } + } + } +} + +.exit { + position: relative; + width: 20px; + height: 20px; + + &:has(.exit-north) { + left: 50%; + transform: translate(calc(-50% - 1px), -100%); + } + + &:has(.exit-south) { + left: 50%; + top: 100%; + transform: translate(calc(-50% - 1px), 0%); + } + + &:has(.exit-east) { + left: 100%; + top: 50%; + transform: rotate(90deg) translate(-50%, 0); + } + + &:has(.exit-west) { + left: 0%; + top: 50%; + transform: rotate(90deg) translate(-50%, 100%); + } + + &:has(.exit-north), &:has(.exit-south) { + + .exit:has(.exit-east) { + left: 100%; + transform: rotate(90deg) translate(-150%, 0); } } - .h-exit { - height: 60px; - width: 30px; - - > div { - height: 20px; - width: 100%; - margin: auto; - border: solid black; - border-width: 1px 0; - position: relative; + &:has(.exit-north), &:has(.exit-south) { + + .exit:has(.exit-west) { top: 50%; - transform: translateY(-50%); - - .dotted { - margin: auto; - border: dashed black; - border-width: 1px 0; - width: 100%; - height: 0; - position: relative; - top: 50%; - transform: translateY(-50%); - } - } - - &:has(.h-exit-left) { - margin-right: -9px; - } - - &:has(.h-exit-right) { - margin-left: -9px; + transform: rotate(90deg) translate(-150%, 100%); } } } \ No newline at end of file diff --git a/web/src/pages/game/components/GameBoard.tsx b/web/src/pages/game/components/GameBoard.tsx index 31078b1..bfacbe7 100644 --- a/web/src/pages/game/components/GameBoard.tsx +++ b/web/src/pages/game/components/GameBoard.tsx @@ -1,76 +1,31 @@ +import { buildBoard, Cell, directions, Exit } from "interface"; + const GameBoard = () => { - const range = (n: number) => Array.from(Array(n).keys()); - const cells = range(11).flatMap((rowIndex) => { - return range(11).map((colIndex) => { - return { rowIndex, colIndex }; - }); - }); + const board: Cell[][] = buildBoard(); return (
- {cells.map(({ rowIndex, colIndex }) => { - if ( - (rowIndex === 0 || rowIndex === 10) && - (colIndex === 0 || colIndex === 10) - ) { - return
; - } - if (rowIndex === 0) { - return ( -
-
-
-
-
- ); - } - if (rowIndex === 10) { - return ( -
-
-
-
-
- ); - } - if (colIndex === 0) { - return ( -
-
-
-
-
- ); - } - if (colIndex === 10) { - return ( -
-
-
-
-
- ); - } - return
; - })} + {board.flatMap((row) => + row.map((cell) => ( +
+ {directions.map((direction) => { + const traversedNode = cell.getNodeAt(direction).traverseBorder(); + const isExit = traversedNode instanceof Exit; + if (!isExit) return; + const className = + `exit-${direction.toLowerCase()}` + + ` exit-${(traversedNode as Exit).type.toLowerCase()}`; + return ( +
+
+
+ ); + })} +
+ )), + )}
); - - /* - {range(9).map(() => ( -
-
-
- ))} - {range(81).map(() => ( -
- ))} - {range(9).map(() => ( -
-
-
- ))} - */ }; export default GameBoard; -- 2.40.1 From af133bae8b6339eb95288ed42b5892d9babe245b Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sat, 30 Nov 2024 19:41:20 +0100 Subject: [PATCH 07/25] Add images of pieces --- web/public/pieces/P01.jpeg | Bin 0 -> 21554 bytes web/public/pieces/P02.jpeg | Bin 0 -> 25811 bytes web/public/pieces/P03.jpeg | Bin 0 -> 33791 bytes web/public/pieces/P04.jpeg | Bin 0 -> 29860 bytes web/public/pieces/P05.jpeg | Bin 0 -> 17221 bytes web/public/pieces/P06.jpeg | Bin 0 -> 21552 bytes web/public/pieces/P07.jpeg | Bin 0 -> 25342 bytes web/public/pieces/P08.jpeg | Bin 0 -> 29161 bytes web/public/pieces/P09.jpeg | Bin 0 -> 25400 bytes web/public/pieces/P10.jpeg | Bin 0 -> 21282 bytes web/public/pieces/P11.jpeg | Bin 0 -> 17460 bytes web/public/pieces/P12.jpeg | Bin 0 -> 25862 bytes web/public/pieces/P13.jpeg | Bin 0 -> 29945 bytes web/public/pieces/P14.jpeg | Bin 0 -> 30664 bytes web/public/pieces/P15.jpeg | Bin 0 -> 30207 bytes web/public/pieces/P16.jpeg | Bin 0 -> 44267 bytes web/public/pieces/P17.jpeg | Bin 0 -> 21764 bytes web/public/pieces/P18.jpeg | Bin 0 -> 27009 bytes web/public/pieces/P19.jpeg | Bin 0 -> 33553 bytes web/public/pieces/P20.jpeg | Bin 0 -> 60502 bytes web/public/pieces/P21.jpeg | Bin 0 -> 36170 bytes web/public/pieces/P22.jpeg | Bin 0 -> 47563 bytes 22 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 web/public/pieces/P01.jpeg create mode 100644 web/public/pieces/P02.jpeg create mode 100644 web/public/pieces/P03.jpeg create mode 100644 web/public/pieces/P04.jpeg create mode 100644 web/public/pieces/P05.jpeg create mode 100644 web/public/pieces/P06.jpeg create mode 100644 web/public/pieces/P07.jpeg create mode 100644 web/public/pieces/P08.jpeg create mode 100644 web/public/pieces/P09.jpeg create mode 100644 web/public/pieces/P10.jpeg create mode 100644 web/public/pieces/P11.jpeg create mode 100644 web/public/pieces/P12.jpeg create mode 100644 web/public/pieces/P13.jpeg create mode 100644 web/public/pieces/P14.jpeg create mode 100644 web/public/pieces/P15.jpeg create mode 100644 web/public/pieces/P16.jpeg create mode 100644 web/public/pieces/P17.jpeg create mode 100644 web/public/pieces/P18.jpeg create mode 100644 web/public/pieces/P19.jpeg create mode 100644 web/public/pieces/P20.jpeg create mode 100644 web/public/pieces/P21.jpeg create mode 100644 web/public/pieces/P22.jpeg diff --git a/web/public/pieces/P01.jpeg b/web/public/pieces/P01.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..bd398d8e14cfdaab6fde24be4483d50c79382492 GIT binary patch literal 21554 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 a>R12%-Aw)0FZ$}=f3?LwcWfDH=l=sIK}661 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P03.jpeg b/web/public/pieces/P03.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..1c75d63aebae680687243efce917f122f7bf75f7 GIT binary patch literal 33791 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 z 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P04.jpeg b/web/public/pieces/P04.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..6b8ee6b9fcb10995d2400f563f488231d137687c GIT binary patch literal 29860 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 IioEUr1N>X6Gynhq literal 0 HcmV?d00001 diff --git a/web/public/pieces/P05.jpeg b/web/public/pieces/P05.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..dbcb4029707f5eea6a74e4a832e95ae2cb05482d GIT binary patch literal 17221 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P06.jpeg b/web/public/pieces/P06.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..1df087284f67b03f8ae5d2b7bb31dcdb2c7279f4 GIT binary patch literal 21552 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P08.jpeg b/web/public/pieces/P08.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..46ab5e21327048df4495ffd3412dda35c694025c GIT binary patch literal 29161 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 CeC3M( literal 0 HcmV?d00001 diff --git a/web/public/pieces/P09.jpeg b/web/public/pieces/P09.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..bee659cbbaa0ccd3fa7acd64b198fe81d12c4f84 GIT binary patch literal 25400 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P10.jpeg b/web/public/pieces/P10.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..95cf7f695ce296ff28ecc5ea0a0a275deb6e256e GIT binary patch literal 21282 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P11.jpeg b/web/public/pieces/P11.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..283684800527c83ad951135ab856bb68805b3cce GIT binary patch literal 17460 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P13.jpeg b/web/public/pieces/P13.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..cb273a95065c25101c24d8e85f8cd290d88d2627 GIT binary patch literal 29945 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 HqHg&wf6Hg% literal 0 HcmV?d00001 diff --git a/web/public/pieces/P14.jpeg b/web/public/pieces/P14.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..86318514f571853a4a0dcd0126a317baf16b6d62 GIT binary patch literal 30664 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P15.jpeg b/web/public/pieces/P15.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..767ceab484403b44b18b0d907597348826e001a5 GIT binary patch literal 30207 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%0Dj2Sd2-d z&=y~sm=o#O>9&AVL|S3xG20W$m+`R&p_kjAmy1%b8%?}cIBWf-E(3h-S>v5SOCMf; zeEq?Kal3-7_~O5qbND@51i-2 z^!}6fr*2bUpx9yoJ`)B_TEduVvZX0U^CMDtAcw=a3ZrzEFEaq^$Ym>ycBxhe*z@a>3 zO1z)%wO02Pu3s1E9Jy=~wrs~C+VL^<@v>TW}E?W}si= zTH>i<^f=*g&1?I8M3ge(TPDrI(bSVe62kd^K_uS=wxZdtwL8$2y4O_lv`W>@3?i+vGF8U@ep| zi__M(=W;_4FIde>-FI$sYb%HC3nc;A$V5{20yLpjfvQ?#>hsSu3!_OEG2@GT9rh#R(YSvLtiiIc?Vax_attEBY-L*pcNHcW-l?^0 z?U)1W6Ne?W;iL2FT(0|H*(WNyGAZa*fm!CU8;-OQ+z01zGFlW+ z33EjK8+UF5sY8sxzm>oXs{HETzN$3u<){T%Z;%+D_q_HXrP;gh*_&AFxC65Uj-Kew z1Jd&8O)r`ryRHRGoy)~zP;$5VR!rLVJ7} z=~PmiVT=O(y%#JGSPsa7TO0Y?XvCy^fFQa_WpH5pXjPS2>|z*S#ySMJJ-I!61;v)Y z_}tghTJSM&HwBCBsN_R<40{+^#@57-Nan4;d4XvG;UZpm{*3y7$0c+MYrLeq*l5~; zyF6XiMv3cjgH3JC`nNKx)tbW(mZ#7UoO|N?RmF>i6#2tXEe_?@5xSn_$j9%w1dDZ&%t`dL3So6Xww{ zI-zvw&5*LSL!g3hgY2gLRzjc>OO(EQB5;qpryApmM55Q2s3}+~b%U>S9|F!f67A ze@DN>L>iAv01ikF$6`fx@t4~2Eou%R(QI|elxv=zX#uB~V3$K0TH`i#4cc z*19qOeHKE5L0Z3PRa6|!(MEkdcgngkiP(B#%BJv(hfw8#cdS!P1 z+dKdU2bQy`9cLv;QhoVFaspWfXU^m#wZdcU^sGbmOAJ;X<-KX1`plOWV@nh9A`a6U z=De7)EK}Bn6d9XU?(vk_#z=j>P0onbX?mEb@`i_-FbQo(DS$q~m(3qYD>Dkl7p=9 zmo@%-ThwnfzDjosIUHEM>NfdZRQS#2;rNjj0EC(fjMXt-7-<)#$ZQE``E~X@)-3sV>=AEr z_wXc6Vg(dw2BaKg;a1a;sX4oEV_w)HVOZaW>do_vZ1hevuCCLcnLZ8DIj2jJ34SZX z`E1LibbEFNf*sY47SQ=y%Nv@+)}2nW1uQGvH<1{JyXl8bk%Xls5?e60$T>cXBxsE7 zT%pmZMlW~gj@;1x^Ti3%D?4B5Nz!w2;(YGx8=*Z5A}oKRY=26YRR$d8p{THq-XtT3 zYsjV%Q{*@8Mi2}+hh>3PwHW0@?IFIrK&+I2KpJmYYV{>qEI>-&H%Gy-rUMrR{lnJ3Sj3Xd=g50k)kCyc0_vgkW#TN``!RCfL}c z5p1nsz?^%NN*W=Jpip(e6}Y(Il=l#0arb+Ok)nhc(<`X$2%%+8YR1X$0-tpr#axgu zK^C*rJPNtx7@2Q`&npy+vUH{|!B@4EM<0G2V{%u*2zz_rh>erxJaFQI!qT`<#?-7X zo8109;6&|G;fRXG`^RaGqP<=HQ{s-%8&gD_2=*NEdv2zAfk1tuw`;<5{2E3VhZpfR zU-;x$TOFR9f42ouYu{}A%(Lcg$Mr13GG8mx&V|(c+gVjzH^yggm=yL*ymR<(yZ>*wEZ+z;GX*Wk0G`za#!VQ6Zj_MTxldA8ir#9@ z!AeERv68RKiVc`Wj0jY#7gTHM<|pz;26W#y`0`l~e-z6YOE|mt>vr~(s#n#TPw(!k z@UDD8AM(8X3)c(?_5YMtf?r1g$2=8;owca&5+mz%XPs;X`HVlpZan*8BQwZu7U7sH zVTN93c}gtAVQ0lrzO#MJoo+4dO`Eq2pUCsBjScph>$KSW`fjaZkG1A*dz=W<(Bd%+ zY@Grcm<|KnWK7IG1J zX~WM!VcB&<=4GbWPLw#0xEbU`2Gt8^g|VY z8y%46Mrd31sUU=d;N!xHnH@wj#I{Lb~|K)X{pw7CxB;m$X6hmp_}$FMab@P%%m}GUOEc za+m_j$&p9!HNjgdSkn_}lCnfvUp~G`0Zl3gD~QMkLa9dSi6h&7+V-G07K8{}IsGen zod7m%LU#$|JIsRsD+SoKXl@%KOho_#2woLZf%pIlRo?ouNs<%z!alU$va9|yC>)eB z2GTAi(m=6l*mwmr?F5kiVYH!0$)!2RJpeCy(ELD>vB6vm%F%Zrw5Dq$fG`=a$t?f- zaX^`{`zPxC$TuPNbW#%_tTP5=AwxP8?*denqa-&7IrNL-{uM&|^cG|!@T)&?`xhde zod8jo7cu1wczCJ`@fCQdM_0Z+`p81LhHd7@&|bKzRVDXRttp^!G~8w)x#pS-;MY1v zLk=kMXb3eSbODTQHyPmI(`mpmqmUk2V@VLgKm4=xArU-$zJPR|Ck130TvOTeT}4yg)?d1GfnWBiMcckys=JWWY_d17u8To3JTh*VKNZ z+>g4VNp*mYYzN?RDF0@x{AfNfnf6u0o|W{#1AFwn!mB9e1DfK6NsJs`DYwaDh5Sn1TlXs#20uVmc78N_s%;{vf_M!_UT zv4|)M7Djm(ncC-7fQ$pAD4|R2W*!G}@Il@%8bL_O*!C`u-wQXKVk#i_Op09n(*#nN zLJ(jF+z0n9Wq{Ctx$#3_;G>F=W3UcsOw6h#wODkC{)wz34q_u-#GdO}PDY-EF^LYI zDZKFOJWr3*8;0d4Z)i=JgARZA0(#E(*(5jNo-$5U+ z;WQKh(m1@xoZLMXIFGOr`AMX;4e_KAcJK&(e=0~14GpD>KsKBTsB{cx%?4E0MF6x0 z2OX5@A7D~Hz6Ix_8~zy2{=O^ycnhM63Saa47le1#fUX6=<$;*sepl!Wp`5f2VN~~H zHS9C%TR;CEg#>S$`T3<^|38YDpXt`oj(JFL;a|3J8rr4dm~p(sS|})va-LaQl25H+ zX2s7g^T?^3BR73uute@ylzWboR$rcshdVr*6FBdl#hP2W!P3I!rLPQ^j)PAjk`aBx zsBSVEDMIi=sJA)EIs;&>g#dFXAD9I?6@bHiDZj+;f2Sk~N0p-mG^DkNumFrutn?J% z0v`b;!~uXaRa>y}X;?XF%xH81l;vbVoczzBDa2^til4zZ1s!QJP`IsHOFyvmv@VTAPF4bQ5u^%ncudiS}1H?THotJALRDnE_bf57tl3fE6L@IEP5!?8}Ftle|oEr(3 zHzomzoK;H1jTluBxrIse6n9M-OYmcCOu>QlD?Q~{I2L_CoF z$S0O5y?^0y03Ob*1syD5eBlXx564{T{nbr5!mrdpI(ZF! zyoL>Q*bu}5`BrVD{Hk)(hD=AnNedVO2Q8)n(7u@cIFmwh5Bz!u{kz^t?GHu^+63U( zM-VFA0&5`P)W`0t5F&ic?O)C;Etk!rMWO?hj9Y0Cn)2dbk21gMA}Hh*E_OJFxNI$i z<=;>X%jI6Y#;X7o&Q2j$pOZnZB#3I)?BO?kA5yMA@VSRjRj@Dz{=j+O!1aNx+#8cY7c(EoDq|CM9@AGB|( zT}qwzEkbk(n&e*UJ9&sG+Sf`A#nmcS_c&W70?2D0|>h#0@3cRAml9pyIu{HR1#A< zDnarxpWlBID08AJ2#-Z*#Tuy>h{(nQqTYqtqEG0$k;50umVxFW(kg(_(%0#@Pw2ym zFdl_(xX3cD6x=r+Z8xeiJS3B*hYL#L4sU#uvbx4rzQTtw%GQ2YzHH&4?6jTCA9xKp z4*|%r;R6~nGnUZqZt;w?L)c}p#zS-Pqo6tv8Yd{|+)ALLHDdV~d>%u>47T-7otzyv z$ISd;_0ud2OzM?kS0-|HcTP6xbR>nf1wnQqSO()g8C8p%?momqIIw=$1AhEtL z7|vQC@@<3Mv*!Pvvn4_6-h9;;}m@8T^7kR0b9RdjXa_%5FAV0N((O zaHgC{fq~svmOCTbmDCGg#t6@4L}tEvW@vxP|GPE-DmS>RtBPGF$gJKCn|h`;6YRom(a~2M-B%~ zR>HFk1+=bzi~I=Eh?yPTW|+I)iPXr+}rn~znpCcp1*19)*i zpmh>JcaN{k7ZqK^0jKr8wJZ8HsSfC_MNLvrcqm$o0mJ~>^U$#!1Dn)=jQoE zM_}>H(9u~xG^X8q9*ecPJW6?>dGFqndVo`gcA^E&s3#AfY~7hAagc_~FI&aZI$|kj2}A- zJrQhK*T57(b{%P8evA)lE2%2dHKck70N70VH+*55@d!Mnh1U>Uq=3e-kR;IeXA(}B zi6ipOagRb$kAJ&5Z&|XSEshmuX*@EvtUmwT@5Rmu97UtZt){q?6oaO#^(=0m~%lUVny~=fJosl))u5G=xMw9nsh+L0~8WC)j zU;vcal_HP0B56`U-`Ids%jaG17l;M-yJAqtcG*s07pMVK$!RQI3H$OzkAU+lG2R1y zI5`7nik%&b{9^~so%IxJn9)jXmc(3n;T7wi5OdwTw(+{&t@U*D@^06C8|OcWson>{ z>ULC?4>%Ssb`nro!*E36)WV4Bd7=HfxRDde)@C6R&ti_YH))u`uR3t8eAMPv_Q+>* z;#bx!%Bt>-hgaUI@yt3=s3CWA&NwHUX`Z(Ij7lp9Kgc0;{mGM{X6cKHr?U=%yk#WF zTR!J9!l&aFr=gVLn;l@}x>$R-S%uMjwntLbxM1b$hb5ma)IHa|dDqZ&<=Nty3$?vp{{}BopL`#2| z&5M>2|K{iMMNC7gyQ!c1Gqs zn`a*3!6l7<2|~^>@I!rsE>HR95O6?K?9KwD^D7br&Cj`Pw-+yv2wK8BHN+mU0qY1} zCh=(DL?3uEys2=28D%$%1v+|*`Py$tgIm>e=DU{{W!rSc%!y&H&8$e9s=hk1hk&5apOc|7gGY!(SH;#72RlE*P_juH9yA zaIf0(iF;gwPi{Wmx>wYc_w0? zs3tSLzLLgQclKX)-%MAvc;T`Bk*c+hgKoyeJg@sIvdN$JJN>#ot>20eMKlm$GJ-L~ zI{;c#TaWjPxQ*sgj-<46qKI!4;3jemCr7@?hKJei$NGvkkBu#CHk2@8i0xbb4{a6m zkC8UjJ8OTau|1Nu*w0^&r}o`B7w<~P6bDOvef=$PyaJM_brIU9$;i^qGEms|5d!Gz za2eF9Kj$)Pz`*v=2pvP|5s?3^VmI+{^i=25VrE$xW+c2tC@;rc7X7jhhNzYEU3-c~2~2O3|nOR9XrrTY^f^N2P?de}IU+pC%`gWPZUH*l zRzqfib6c#B_n=YaWWeP|vQ}A_&~*bGiw8n)B#F{M`|a|ZoWq+Y|mnm>N|y{6FN< B^k4u0 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P16.jpeg b/web/public/pieces/P16.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..c7442cf8e90726339179a29afe30e78edfa3849b GIT binary patch literal 44267 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�MoBHUH_mth>Q18O)Kjaqo_X^w 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P17.jpeg b/web/public/pieces/P17.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..6d9ef32dae146df7cdf1048d9f373a01d6f5f674 GIT binary patch literal 21764 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P18.jpeg b/web/public/pieces/P18.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..e6e9d38ae2c46bc266f6a87446efbcc92a2a4763 GIT binary patch literal 27009 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 P#yM)7|DBCeWG(*(@@pNK literal 0 HcmV?d00001 diff --git a/web/public/pieces/P20.jpeg b/web/public/pieces/P20.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..f82c543fb77e822caf2c1e62fd4b082de97995ff GIT binary patch literal 60502 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 literal 0 HcmV?d00001 diff --git a/web/public/pieces/P21.jpeg b/web/public/pieces/P21.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..a3c8ee3c0593637960d6d23e1a096523a7903835 GIT binary patch literal 36170 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 Date: Sat, 30 Nov 2024 21:53:42 +0100 Subject: [PATCH 08/25] Create dice view to present all available dice to place in the board --- web/src/App.scss | 3 --- web/src/App.tsx | 1 + web/src/index.tsx | 1 - web/src/pages/game/GamePage.scss | 11 +++++++++++ web/src/pages/game/GamePage.tsx | 5 +++++ web/src/pages/game/components/DiceSet.scss | 17 +++++++++++++++++ web/src/pages/game/components/DiceSet.tsx | 20 ++++++++++++++++++++ web/src/pages/game/components/GameBoard.scss | 2 ++ web/src/pages/game/components/GameBoard.tsx | 1 + 9 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 web/src/pages/game/components/DiceSet.scss create mode 100644 web/src/pages/game/components/DiceSet.tsx diff --git a/web/src/App.scss b/web/src/App.scss index 55aefe1..5992e9f 100644 --- a/web/src/App.scss +++ b/web/src/App.scss @@ -1,6 +1,3 @@ @use "node_modules/@picocss/pico/scss/pico" with ( $theme-color: "pumpkin" ); - -@import "./pages/game/GamePage.scss"; -@import "./pages/game/components/GameBoard.scss"; diff --git a/web/src/App.tsx b/web/src/App.tsx index 8778670..45a0843 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,5 +1,6 @@ import { io } from "socket.io-client"; import GamePage from "./pages/game/GamePage"; +import "./App.scss"; function App() { const socket = io("http://localhost:3010"); diff --git a/web/src/index.tsx b/web/src/index.tsx index dd89d8c..46075e1 100644 --- a/web/src/index.tsx +++ b/web/src/index.tsx @@ -1,7 +1,6 @@ import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; -import "./App.scss"; const root = ReactDOM.createRoot( document.getElementById("root") as HTMLElement, diff --git a/web/src/pages/game/GamePage.scss b/web/src/pages/game/GamePage.scss index 1cbf756..9847b6c 100644 --- a/web/src/pages/game/GamePage.scss +++ b/web/src/pages/game/GamePage.scss @@ -3,3 +3,14 @@ h1 { padding: 10px; margin: 0; } + +.game-panel { + user-select: none; /* Standard syntax */ + display: flex; + flex-direction: row; + + .right-panel { + display: flex; + flex-direction: column; + } +} diff --git a/web/src/pages/game/GamePage.tsx b/web/src/pages/game/GamePage.tsx index 663aefc..3b42ea0 100644 --- a/web/src/pages/game/GamePage.tsx +++ b/web/src/pages/game/GamePage.tsx @@ -1,5 +1,7 @@ import React from "react"; import GameBoard from "./components/GameBoard"; +import DiceSet from "./components/DiceSet"; +import "./GamePage.scss"; const GamePage = () => { return ( @@ -7,6 +9,9 @@ const GamePage = () => {

Game Page Title

+
+ +
); diff --git a/web/src/pages/game/components/DiceSet.scss b/web/src/pages/game/components/DiceSet.scss new file mode 100644 index 0000000..22145b0 --- /dev/null +++ b/web/src/pages/game/components/DiceSet.scss @@ -0,0 +1,17 @@ +.dice-set { + display: grid; + grid-template-columns: repeat(2, auto); + gap: 20px; + padding: 50px; + + .dice { + height: 150px; + width: 150px; + border: 2px solid black; + border-radius: 10%; + + img{ + border-radius: 10%; + } + } +} \ No newline at end of file diff --git a/web/src/pages/game/components/DiceSet.tsx b/web/src/pages/game/components/DiceSet.tsx new file mode 100644 index 0000000..28ae505 --- /dev/null +++ b/web/src/pages/game/components/DiceSet.tsx @@ -0,0 +1,20 @@ +import "./DiceSet.scss"; + +const DiceSet = () => { + const diceImages = [1, 2, 3, 4] + .map(() => Math.floor(Math.random() * 22 + 1)) + .map((index) => ("0" + index).slice(-2)) + .map((index) => `${process.env.PUBLIC_URL}/pieces/P${index}.jpeg`); + + return ( +
+ {diceImages.map((file) => ( +
+ +
+ ))} +
+ ); +}; + +export default DiceSet; diff --git a/web/src/pages/game/components/GameBoard.scss b/web/src/pages/game/components/GameBoard.scss index fca4d47..4d6cc7b 100644 --- a/web/src/pages/game/components/GameBoard.scss +++ b/web/src/pages/game/components/GameBoard.scss @@ -1,6 +1,8 @@ .game-board { height: 850px; width: 850px; + min-height: 850px; + min-width: 850px; display: grid; grid-template-columns: repeat(7, auto); gap: auto; diff --git a/web/src/pages/game/components/GameBoard.tsx b/web/src/pages/game/components/GameBoard.tsx index bfacbe7..e3dabf0 100644 --- a/web/src/pages/game/components/GameBoard.tsx +++ b/web/src/pages/game/components/GameBoard.tsx @@ -1,4 +1,5 @@ import { buildBoard, Cell, directions, Exit } from "interface"; +import "./GameBoard.scss"; const GameBoard = () => { const board: Cell[][] = buildBoard(); -- 2.40.1 From 7354586ef5867445c3109b6db031f97caf3fe5c0 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sat, 30 Nov 2024 22:31:16 +0100 Subject: [PATCH 09/25] Created piece and placed piece abstractions --- interface/types/ExternalNode.ts | 6 +-- interface/types/InternalNode.ts | 11 ++++++ interface/types/Node.ts | 11 ++---- interface/types/Piece.ts | 69 +++++++++++++++++++++++++++++++++ interface/types/PlacedPiece.ts | 29 ++++++++++++++ 5 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 interface/types/InternalNode.ts create mode 100644 interface/types/Piece.ts create mode 100644 interface/types/PlacedPiece.ts diff --git a/interface/types/ExternalNode.ts b/interface/types/ExternalNode.ts index 14dcbbe..78447d3 100644 --- a/interface/types/ExternalNode.ts +++ b/interface/types/ExternalNode.ts @@ -2,14 +2,14 @@ import { Direction } from "../constants/Direction"; import { Border } from "./Border"; import { Cell } from "./Cell"; import { Exit } from "./Exit"; -import { Node } from "./Node"; -export class ExternalNode extends Node { +export class ExternalNode { public readonly direction: Direction; private border?: Border; + public readonly cell: Cell; constructor(cell: Cell, direction: Direction) { - super(cell); + this.cell = cell; this.direction = direction; } diff --git a/interface/types/InternalNode.ts b/interface/types/InternalNode.ts new file mode 100644 index 0000000..e60434b --- /dev/null +++ b/interface/types/InternalNode.ts @@ -0,0 +1,11 @@ +import { randomUUID } from "crypto"; + +export class InternalNode { + id: string; + type: string; + + constructor() { + this.id = randomUUID(); + this.type = "STATION"; + } +} diff --git a/interface/types/Node.ts b/interface/types/Node.ts index b185ad2..fa5bbe0 100644 --- a/interface/types/Node.ts +++ b/interface/types/Node.ts @@ -1,9 +1,4 @@ -import { Cell } from "./Cell"; +import { ExternalNode } from "./ExternalNode"; +import { InternalNode } from "./InternalNode"; -export abstract class Node { - public readonly cell: Cell; - - constructor(cell: Cell) { - this.cell = cell; - } -} +export type Node = ExternalNode | InternalNode; diff --git a/interface/types/Piece.ts b/interface/types/Piece.ts new file mode 100644 index 0000000..a1de677 --- /dev/null +++ b/interface/types/Piece.ts @@ -0,0 +1,69 @@ +import { Direction } from "../constants/Direction"; +import { TrackType } from "../constants/TrackType"; +import { Cell } from "./Cell"; +import { InternalNode } from "./InternalNode"; +import { PlacedPiece } from "./PlacedPiece"; +import { Node } from "./Node"; + +export interface TrackProps { + startPoint: Direction; + endPoint?: Direction; + isInternal: boolean; + type: TrackType; +} + +export class Piece { + tracks: Set<{ + joinedPoints: { + firstPoint: Direction; + secondPoint: Direction | InternalNode; + }; + type: TrackType; + }>; + internalNodes: Set; + + constructor(hasInternalNode: boolean, trackDefinitions: TrackProps[]) { + const internalNode = new InternalNode(); + this.internalNodes = new Set(); + if (hasInternalNode) { + this.internalNodes.add(internalNode); + } + this.tracks = new Set( + trackDefinitions.map((track) => { + if (!track.isInternal && !track.endPoint) { + throw Error("Missing direction for non-internal track"); + } + return { + joinedPoints: { + firstPoint: track.startPoint, + secondPoint: track.isInternal + ? internalNode + : (track.endPoint as Direction), + }, + type: track.type, + }; + }), + ); + } + + toPlacedPiece(cell: Cell) { + return new PlacedPiece( + new Set( + Array.from(this.tracks).map((track) => { + return { + nodes: { + firstNode: cell.getNodeAt(track.joinedPoints.firstPoint), + secondNode: + track.joinedPoints.secondPoint instanceof Node + ? track.joinedPoints.secondPoint as Node + : cell.getNodeAt(track.joinedPoints.secondPoint as Direction), + }, + type: track.type, + }; + }), + ), + this.internalNodes, + cell, + ); + } +} diff --git a/interface/types/PlacedPiece.ts b/interface/types/PlacedPiece.ts new file mode 100644 index 0000000..e1e83b5 --- /dev/null +++ b/interface/types/PlacedPiece.ts @@ -0,0 +1,29 @@ +import { TrackType } from "../constants/TrackType"; +import { Cell } from "./Cell"; +import { InternalNode } from "./InternalNode"; +import { Node } from "./Node"; + +export class PlacedPiece { + tracks: Set<{ + nodes: { + firstNode: Node; + secondNode: Node; + }; + type: TrackType; + }>; + internalNodes: Set; + cell: Cell; + + constructor( + tracks: Set<{ + nodes: { firstNode: Node; secondNode: Node }; + type: TrackType; + }>, + internalNodes: Set, + cell: Cell, + ) { + this.tracks = tracks; + this.internalNodes = internalNodes; + this.cell = cell; + } +} -- 2.40.1 From 406e4d2f751911e461f1dac7ededa0859a96cd23 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sun, 1 Dec 2024 12:30:59 +0100 Subject: [PATCH 10/25] Re-structure pieces builder and add include first pieces batch --- interface/.eslintrc.js | 4 +- interface/constants/InternalNodeType.ts | 4 + interface/constants/Pieces.ts | 200 ++++++++++++++++++++++++ interface/types/Cell.ts | 2 +- interface/types/ExternalNode.ts | 2 +- interface/types/InternalNode.ts | 7 +- interface/types/Piece.ts | 94 ++++++----- interface/types/PlacedPiece.ts | 6 +- 8 files changed, 273 insertions(+), 46 deletions(-) create mode 100644 interface/constants/InternalNodeType.ts create mode 100644 interface/constants/Pieces.ts diff --git a/interface/.eslintrc.js b/interface/.eslintrc.js index 9700d32..5b53304 100644 --- a/interface/.eslintrc.js +++ b/interface/.eslintrc.js @@ -13,5 +13,7 @@ module.exports = { jest: true, }, ignorePatterns: [".eslintrc.js", "dist/"], - rules: {}, + rules: { + "@typescript-eslint/no-non-null-assertion": "off", + }, }; diff --git a/interface/constants/InternalNodeType.ts b/interface/constants/InternalNodeType.ts new file mode 100644 index 0000000..708179d --- /dev/null +++ b/interface/constants/InternalNodeType.ts @@ -0,0 +1,4 @@ +export enum InternalNodeType { + NONE = "NONE", + STATION = "STATION", +} diff --git a/interface/constants/Pieces.ts b/interface/constants/Pieces.ts new file mode 100644 index 0000000..2eb8c2e --- /dev/null +++ b/interface/constants/Pieces.ts @@ -0,0 +1,200 @@ +import { Piece } from "../types/Piece"; +import { Direction } from "./Direction"; +import { InternalNodeType } from "./InternalNodeType"; +import { TrackType } from "./TrackType"; + +const STRAIGHT_RAIL: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + endPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + ], +}); + +const TURN_RAIL: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.SOUTH, + endPoint: Direction.EAST, + type: TrackType.RAIL, + }, + ], +}); +const FOUR_WAY_CROSS_RAIL: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.NONE, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.RAIL, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); +const T_JUNCTION_RAIL: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.NONE, + trackDefinitions: [ + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.RAIL, + }, + ], +}); +const DEAD_END_STATION_RAIL: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + ], +}); +const TURN_RAIL_TO_ROAD: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + ], +}); +const T_JUNCTION_WITH_ROAD_ON_SIDE: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + ], +}); +const FOUR_WAY_WITH_ONE_ROAD: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); +const T_JUNCTION_WITH_ROAD_AT_CENTER: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + ], +}); +const STRAIGHT_TRACK_CHANGE: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); + +export enum PieceId { + P01 = "P01", + P02 = "P02", + P03 = "P03", + P04 = "P04", + P05 = "P05", + P06 = "P06", + P07 = "P07", + P08 = "P08", + P09 = "P09", + P10 = "P10", + P11 = "P11", + P12 = "P12", + P13 = "P13", + P14 = "P14", + P15 = "P15", + P16 = "P16", + P17 = "P17", + P18 = "P18", + P19 = "P19", + P20 = "P20", + P21 = "P21", + P22 = "P22", +} + +export const pieceMap: Record = { + [PieceId.P01]: STRAIGHT_RAIL, + [PieceId.P02]: TURN_RAIL, + [PieceId.P03]: FOUR_WAY_CROSS_RAIL, + [PieceId.P04]: T_JUNCTION_RAIL, + [PieceId.P05]: DEAD_END_STATION_RAIL, + [PieceId.P06]: TURN_RAIL_TO_ROAD, + [PieceId.P07]: T_JUNCTION_WITH_ROAD_ON_SIDE, + [PieceId.P08]: FOUR_WAY_WITH_ONE_ROAD, + [PieceId.P09]: T_JUNCTION_WITH_ROAD_AT_CENTER, + [PieceId.P10]: STRAIGHT_TRACK_CHANGE, +}; diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index 822ce34..8dc8236 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -19,6 +19,6 @@ export class Cell { public getNodeAt(direction: Direction): ExternalNode { const node = this.externalNodes.get(direction); if (!node) throw Error(`Could not find node at ${direction}`); - return this.externalNodes.get(direction) as ExternalNode; + return node!; } } diff --git a/interface/types/ExternalNode.ts b/interface/types/ExternalNode.ts index 78447d3..f23d312 100644 --- a/interface/types/ExternalNode.ts +++ b/interface/types/ExternalNode.ts @@ -24,6 +24,6 @@ export class ExternalNode { if (!this.border) { throw Error(`Missing border for node`); } - return (this.border as Border).traverseFrom(this); + return this.border.traverseFrom(this); } } diff --git a/interface/types/InternalNode.ts b/interface/types/InternalNode.ts index e60434b..f4826d6 100644 --- a/interface/types/InternalNode.ts +++ b/interface/types/InternalNode.ts @@ -1,11 +1,12 @@ import { randomUUID } from "crypto"; +import { InternalNodeType } from "../constants/InternalNodeType"; export class InternalNode { id: string; - type: string; + type: InternalNodeType; - constructor() { + constructor(type: InternalNodeType) { this.id = randomUUID(); - this.type = "STATION"; + this.type = type; } } diff --git a/interface/types/Piece.ts b/interface/types/Piece.ts index a1de677..dae249a 100644 --- a/interface/types/Piece.ts +++ b/interface/types/Piece.ts @@ -4,46 +4,66 @@ import { Cell } from "./Cell"; import { InternalNode } from "./InternalNode"; import { PlacedPiece } from "./PlacedPiece"; import { Node } from "./Node"; +import { InternalNodeType } from "../constants/InternalNodeType"; -export interface TrackProps { - startPoint: Direction; - endPoint?: Direction; - isInternal: boolean; - type: TrackType; +export interface PieceProps { + readonly useInternalTracks: boolean; + readonly internalNodeType?: InternalNodeType; + readonly trackDefinitions: { + readonly startPoint: Direction; + readonly endPoint?: Direction; + readonly type: TrackType; + }[]; } -export class Piece { - tracks: Set<{ - joinedPoints: { - firstPoint: Direction; - secondPoint: Direction | InternalNode; - }; - type: TrackType; - }>; - internalNodes: Set; +type Track = { + readonly joinedPoints: { + readonly firstPoint: Direction; + readonly secondPoint: Direction | InternalNode; + }; + readonly type: TrackType; +}; - constructor(hasInternalNode: boolean, trackDefinitions: TrackProps[]) { - const internalNode = new InternalNode(); - this.internalNodes = new Set(); - if (hasInternalNode) { - this.internalNodes.add(internalNode); +export class Piece { + readonly tracks: Set; + readonly internalNode?: InternalNode; + + constructor(pieceProps: PieceProps) { + if (pieceProps.useInternalTracks) { + if (!pieceProps.internalNodeType) { + throw Error( + "Expected to find internal node type when useInternalTracks is set", + ); + } + this.internalNode = new InternalNode(pieceProps.internalNodeType); + this.tracks = new Set( + pieceProps.trackDefinitions.map((trackDefinition) => { + return { + joinedPoints: { + firstPoint: trackDefinition.startPoint, + secondPoint: this.internalNode!, + }, + type: trackDefinition.type, + }; + }), + ); + } else { + this.internalNode = undefined; + this.tracks = new Set( + pieceProps.trackDefinitions.map((trackDefinition) => { + if (!trackDefinition.endPoint) { + throw Error("Missing end point for non-internal track"); + } + return { + joinedPoints: { + firstPoint: trackDefinition.startPoint, + secondPoint: trackDefinition.endPoint, + }, + type: trackDefinition.type, + }; + }), + ); } - this.tracks = new Set( - trackDefinitions.map((track) => { - if (!track.isInternal && !track.endPoint) { - throw Error("Missing direction for non-internal track"); - } - return { - joinedPoints: { - firstPoint: track.startPoint, - secondPoint: track.isInternal - ? internalNode - : (track.endPoint as Direction), - }, - type: track.type, - }; - }), - ); } toPlacedPiece(cell: Cell) { @@ -55,14 +75,14 @@ export class Piece { firstNode: cell.getNodeAt(track.joinedPoints.firstPoint), secondNode: track.joinedPoints.secondPoint instanceof Node - ? track.joinedPoints.secondPoint as Node + ? (track.joinedPoints.secondPoint as Node) : cell.getNodeAt(track.joinedPoints.secondPoint as Direction), }, type: track.type, }; }), ), - this.internalNodes, + this.internalNode, cell, ); } diff --git a/interface/types/PlacedPiece.ts b/interface/types/PlacedPiece.ts index e1e83b5..7582a42 100644 --- a/interface/types/PlacedPiece.ts +++ b/interface/types/PlacedPiece.ts @@ -11,7 +11,7 @@ export class PlacedPiece { }; type: TrackType; }>; - internalNodes: Set; + internalNode?: InternalNode; cell: Cell; constructor( @@ -19,11 +19,11 @@ export class PlacedPiece { nodes: { firstNode: Node; secondNode: Node }; type: TrackType; }>, - internalNodes: Set, + internalNodes: InternalNode | undefined, cell: Cell, ) { this.tracks = tracks; - this.internalNodes = internalNodes; + this.internalNode = internalNodes; this.cell = cell; } } -- 2.40.1 From 39d1ec9a77bd88e0d68cd11159f31388ba799049 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sun, 1 Dec 2024 16:28:17 +0100 Subject: [PATCH 11/25] Add the remaining pieces to the set --- interface/constants/Pieces.ts | 212 ++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) diff --git a/interface/constants/Pieces.ts b/interface/constants/Pieces.ts index 2eb8c2e..fc12356 100644 --- a/interface/constants/Pieces.ts +++ b/interface/constants/Pieces.ts @@ -160,6 +160,206 @@ const STRAIGHT_TRACK_CHANGE: Piece = new Piece({ }, ], }); +const DEAD_END_STATION_ROAD: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.EAST, + type: TrackType.RAIL, + }, + ], +}); +const T_JUNCTION_WITH_RAIL_AT_CENTER: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.ROAD, + }, + ], +}); +const FOUR_WAY_PERPENDICULAR_CROSSING: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + ], +}); +const FOUR_WAY_WITH_ONE_RAIL: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.ROAD, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.ROAD, + }, + ], +}); + +const FOUR_WAY_TURNING_CROSSING: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.ROAD, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); +const LEVEL_CROSSING: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + endPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + endPoint: Direction.WEST, + type: TrackType.ROAD, + }, + ], +}); +const STRAIGHT_ROAD: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.EAST, + endPoint: Direction.WEST, + type: TrackType.ROAD, + }, + ], +}); +const T_JUNCTION_ROAD: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.NONE, + trackDefinitions: [ + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.ROAD, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); +const FOUR_WAY_CROSS_ROAD: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.NONE, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.ROAD, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.ROAD, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); +const DOUBLE_TURN_ROAD: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + endPoint: Direction.WEST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.EAST, + endPoint: Direction.SOUTH, + type: TrackType.ROAD, + }, + ], +}); +const TURN_ROAD: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + endPoint: Direction.WEST, + type: TrackType.ROAD, + }, + ], +}); +const DOUBLE_TURN_RAIL: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + endPoint: Direction.WEST, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + endPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + ], +}); export enum PieceId { P01 = "P01", @@ -197,4 +397,16 @@ export const pieceMap: Record = { [PieceId.P08]: FOUR_WAY_WITH_ONE_ROAD, [PieceId.P09]: T_JUNCTION_WITH_ROAD_AT_CENTER, [PieceId.P10]: STRAIGHT_TRACK_CHANGE, + [PieceId.P11]: DEAD_END_STATION_ROAD, + [PieceId.P12]: T_JUNCTION_WITH_RAIL_AT_CENTER, + [PieceId.P13]: FOUR_WAY_PERPENDICULAR_CROSSING, + [PieceId.P14]: FOUR_WAY_WITH_ONE_RAIL, + [PieceId.P15]: FOUR_WAY_TURNING_CROSSING, + [PieceId.P16]: LEVEL_CROSSING, + [PieceId.P17]: STRAIGHT_ROAD, + [PieceId.P18]: T_JUNCTION_ROAD, + [PieceId.P19]: FOUR_WAY_CROSS_ROAD, + [PieceId.P20]: DOUBLE_TURN_ROAD, + [PieceId.P21]: TURN_ROAD, + [PieceId.P22]: DOUBLE_TURN_RAIL, }; -- 2.40.1 From 835ce2c62a3f917f150fe1be7a40f2250cd983e4 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sun, 1 Dec 2024 22:19:42 +0100 Subject: [PATCH 12/25] Set up dice view from modelled pieces --- interface/index.ts | 5 +++++ interface/package-lock.json | 16 ++++++++++++++++ interface/package.json | 3 +++ interface/types/InternalNode.ts | 4 ++-- web/src/pages/game/components/DiceSet.tsx | 14 ++++++++------ 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/interface/index.ts b/interface/index.ts index a686c28..0cf1028 100644 --- a/interface/index.ts +++ b/interface/index.ts @@ -1,10 +1,15 @@ export * from "./constants/CellType"; export * from "./constants/Direction"; export * from "./constants/ExitType"; +export * from "./constants/InternalNodeType"; +export * from "./constants/Pieces"; export * from "./constants/TrackType"; export * from "./types/Border"; export * from "./types/Cell"; export * from "./types/Exit"; export * from "./types/ExternalNode"; +export * from "./types/InternalNode"; +export * from "./types/Piece"; +export * from "./types/PlacedPiece"; export * from "./types/Node"; export * from "./BoardBuilder"; diff --git a/interface/package-lock.json b/interface/package-lock.json index 3c02071..f8fa15f 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -8,6 +8,9 @@ "name": "interface", "version": "1.0.0", "license": "ISC", + "dependencies": { + "uuid": "^11.0.3" + }, "devDependencies": { "@eslint/js": "^8.0.0", "@types/node": "^22.9.0", @@ -1855,6 +1858,19 @@ "punycode": "^2.1.0" } }, + "node_modules/uuid": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/interface/package.json b/interface/package.json index 4614b15..2ca8ae0 100644 --- a/interface/package.json +++ b/interface/package.json @@ -21,5 +21,8 @@ "globals": "^15.12.0", "typescript": "^5.6.3", "typescript-eslint": "^8.15.0" + }, + "dependencies": { + "uuid": "^11.0.3" } } diff --git a/interface/types/InternalNode.ts b/interface/types/InternalNode.ts index f4826d6..e2e4cc6 100644 --- a/interface/types/InternalNode.ts +++ b/interface/types/InternalNode.ts @@ -1,4 +1,4 @@ -import { randomUUID } from "crypto"; +import { v4 as uuidv4 } from "uuid"; import { InternalNodeType } from "../constants/InternalNodeType"; export class InternalNode { @@ -6,7 +6,7 @@ export class InternalNode { type: InternalNodeType; constructor(type: InternalNodeType) { - this.id = randomUUID(); + this.id = uuidv4(); this.type = type; } } diff --git a/web/src/pages/game/components/DiceSet.tsx b/web/src/pages/game/components/DiceSet.tsx index 28ae505..c81e7d1 100644 --- a/web/src/pages/game/components/DiceSet.tsx +++ b/web/src/pages/game/components/DiceSet.tsx @@ -1,16 +1,18 @@ +import { PieceId } from "interface"; import "./DiceSet.scss"; const DiceSet = () => { - const diceImages = [1, 2, 3, 4] - .map(() => Math.floor(Math.random() * 22 + 1)) - .map((index) => ("0" + index).slice(-2)) - .map((index) => `${process.env.PUBLIC_URL}/pieces/P${index}.jpeg`); + const getRandomPieceId = () => { + const randomId = Math.floor(Math.random() * Object.keys(PieceId).length); + return Object.values(PieceId)[randomId]; + }; + const displayedPieceIds = [1, 2, 3, 4].map(getRandomPieceId); return (
- {diceImages.map((file) => ( + {displayedPieceIds.map((pieceId) => (
- +
))}
-- 2.40.1 From 1ab3db8f671553064436801823811a2048272952 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Tue, 3 Dec 2024 12:29:10 +0100 Subject: [PATCH 13/25] Enable placing pieces in the game board --- interface/types/Cell.ts | 14 ++ interface/types/Piece.ts | 5 +- web/src/pages/game/GamePage.tsx | 22 +++- web/src/pages/game/components/BoardCell.scss | 129 +++++++++++++++++++ web/src/pages/game/components/BoardCell.tsx | 68 ++++++++++ web/src/pages/game/components/DiceSet.scss | 11 -- web/src/pages/game/components/DiceSet.tsx | 44 +++++-- web/src/pages/game/components/Die.scss | 18 +++ web/src/pages/game/components/Die.tsx | 27 ++++ web/src/pages/game/components/GameBoard.scss | 117 ----------------- web/src/pages/game/components/GameBoard.tsx | 52 +++++--- 11 files changed, 345 insertions(+), 162 deletions(-) create mode 100644 web/src/pages/game/components/BoardCell.scss create mode 100644 web/src/pages/game/components/BoardCell.tsx create mode 100644 web/src/pages/game/components/Die.scss create mode 100644 web/src/pages/game/components/Die.tsx diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index 8dc8236..757e471 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -1,10 +1,16 @@ import { CellType } from "../constants/CellType"; import { Direction } from "../constants/Direction"; +import { PieceId, pieceMap } from "../constants/Pieces"; import { ExternalNode } from "./ExternalNode"; +import { PlacedPiece } from "./PlacedPiece"; export class Cell { public readonly externalNodes: Map; public readonly cellType: CellType; + public placedPiece?: { + piece: PlacedPiece; + id: PieceId; + }; constructor(cellType: CellType) { this.externalNodes = new Map([ @@ -21,4 +27,12 @@ export class Cell { if (!node) throw Error(`Could not find node at ${direction}`); return node!; } + + public placePiece(pieceId: PieceId) { + if (this.placedPiece !== undefined) return; + this.placedPiece = { + piece: pieceMap[pieceId].toPlacedPiece(this), + id: pieceId, + }; + } } diff --git a/interface/types/Piece.ts b/interface/types/Piece.ts index dae249a..f684cf4 100644 --- a/interface/types/Piece.ts +++ b/interface/types/Piece.ts @@ -3,7 +3,6 @@ import { TrackType } from "../constants/TrackType"; import { Cell } from "./Cell"; import { InternalNode } from "./InternalNode"; import { PlacedPiece } from "./PlacedPiece"; -import { Node } from "./Node"; import { InternalNodeType } from "../constants/InternalNodeType"; export interface PieceProps { @@ -74,8 +73,8 @@ export class Piece { nodes: { firstNode: cell.getNodeAt(track.joinedPoints.firstPoint), secondNode: - track.joinedPoints.secondPoint instanceof Node - ? (track.joinedPoints.secondPoint as Node) + track.joinedPoints.secondPoint instanceof InternalNode + ? (track.joinedPoints.secondPoint as InternalNode) : cell.getNodeAt(track.joinedPoints.secondPoint as Direction), }, type: track.type, diff --git a/web/src/pages/game/GamePage.tsx b/web/src/pages/game/GamePage.tsx index 3b42ea0..499bd51 100644 --- a/web/src/pages/game/GamePage.tsx +++ b/web/src/pages/game/GamePage.tsx @@ -1,16 +1,32 @@ -import React from "react"; +import React, { useState } from "react"; import GameBoard from "./components/GameBoard"; import DiceSet from "./components/DiceSet"; import "./GamePage.scss"; +import { PieceId } from "interface"; const GamePage = () => { + const getRandomPieceId = () => { + const randomId = Math.floor(Math.random() * Object.keys(PieceId).length); + return Object.values(PieceId)[randomId]; + }; + + const [dice, setDice] = useState( + [1, 2, 3, 4].map(() => { + return { + pieceId: getRandomPieceId(), + isSelected: false, + isDisabled: false, + }; + }), + ); + return (

Game Page Title

- +
- +
diff --git a/web/src/pages/game/components/BoardCell.scss b/web/src/pages/game/components/BoardCell.scss new file mode 100644 index 0000000..a7822ed --- /dev/null +++ b/web/src/pages/game/components/BoardCell.scss @@ -0,0 +1,129 @@ +.cell { + width: 100px; + height: 100px; + border: 2px solid black; + border-radius: 10%; + + .piece { + border-radius: 10%; + position: relative; + + &:nth-child(2) { + top: -20px; + } + + &:nth-child(3) { + top: -40px; + } + } + + &.house { + background-color: blue; + } + + &.university { + background-color: orange; + } + + &.factory { + background-color: grey; + } + + .exit:has(.exit-road) { + border: solid black; + border-width: 0 1px; + + .exit-road { + margin: auto; + width: 0; + height: 100%; + border: dashed black; + border-width: 0 1px; + transform: translate(calc(50% - 1px)); + } + } + + .exit:has(.exit-road) { + border: solid black; + border-width: 0 1px; + + .exit-road { + margin: auto; + width: 0; + height: 100%; + border: dashed black; + border-width: 0 1px; + transform: translate(calc(50% - 1px)); + } + } + + .exit:has(.exit-rail) { + border-width: 0 1px; + + .exit-rail { + margin: auto; + width: 0; + height: 100%; + border: solid black; + border-width: 0 1px; + transform: translate(calc(50% - 1px)); + } + } + + .exit:has(.exit-ambivalent) { + border-width: 0 1px; + border-style: dotted; + + .exit-ambivalent { + margin: auto; + width: 0; + height: 100%; + border: dotted black; + border-width: 0 1px 0 0; + transform: translate(calc(50%)); + } + } +} + +.exit { + position: relative; + width: 20px; + height: 20px; + + &:has(.exit-north) { + left: 50%; + transform: translate(calc(-50% - 1px), -100%); + } + + &:has(.exit-south) { + left: 50%; + top: 100%; + transform: translate(calc(-50% - 1px), 0%); + } + + &:has(.exit-east) { + left: 100%; + top: 50%; + transform: rotate(90deg) translate(-50%, 0); + } + + &:has(.exit-west) { + left: 0%; + top: 50%; + transform: rotate(90deg) translate(-50%, 100%); + } + + &:has(.exit-north), &:has(.exit-south) { + + .exit:has(.exit-east) { + left: 100%; + transform: rotate(90deg) translate(-150%, 0); + } + } + + &:has(.exit-north), &:has(.exit-south) { + + .exit:has(.exit-west) { + top: 50%; + transform: rotate(90deg) translate(-150%, 100%); + } + } +} \ No newline at end of file diff --git a/web/src/pages/game/components/BoardCell.tsx b/web/src/pages/game/components/BoardCell.tsx new file mode 100644 index 0000000..2e1d5af --- /dev/null +++ b/web/src/pages/game/components/BoardCell.tsx @@ -0,0 +1,68 @@ +import { Cell, directions, Exit, PieceId } from "interface"; +import "./BoardCell.scss"; + +export interface BoardCellProps { + cell: Cell; + dice: { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + }[]; + setDice: React.Dispatch< + React.SetStateAction< + { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + }[] + > + >; + refreshBoardRender: () => void; +} + +const BoardCell = (props: BoardCellProps) => { + const { cell, dice, setDice, refreshBoardRender } = props; + const handleBoardCellClick = () => { + const selectedDie = dice.find((die) => die.isSelected); + if (!selectedDie) return; + cell.placePiece(selectedDie.pieceId); + setDice( + dice.map((die) => { + return die !== selectedDie + ? die + : { + pieceId: selectedDie.pieceId, + isSelected: false, + isDisabled: true, + }; + }), + ); + refreshBoardRender(); + }; + + return ( +
+ {directions.map((direction) => { + const traversedNode = cell.getNodeAt(direction).traverseBorder(); + const isExit = traversedNode instanceof Exit; + if (!isExit) return; + const className = + `exit-${direction.toLowerCase()}` + + ` exit-${(traversedNode as Exit).type.toLowerCase()}`; + return ( +
+
+
+ ); + })} + {cell.placedPiece && ( + + )} +
+ ); +}; + +export default BoardCell; diff --git a/web/src/pages/game/components/DiceSet.scss b/web/src/pages/game/components/DiceSet.scss index 22145b0..1152b08 100644 --- a/web/src/pages/game/components/DiceSet.scss +++ b/web/src/pages/game/components/DiceSet.scss @@ -3,15 +3,4 @@ grid-template-columns: repeat(2, auto); gap: 20px; padding: 50px; - - .dice { - height: 150px; - width: 150px; - border: 2px solid black; - border-radius: 10%; - - img{ - border-radius: 10%; - } - } } \ No newline at end of file diff --git a/web/src/pages/game/components/DiceSet.tsx b/web/src/pages/game/components/DiceSet.tsx index c81e7d1..8e10fe0 100644 --- a/web/src/pages/game/components/DiceSet.tsx +++ b/web/src/pages/game/components/DiceSet.tsx @@ -1,19 +1,45 @@ import { PieceId } from "interface"; import "./DiceSet.scss"; +import Die from "./Die"; -const DiceSet = () => { - const getRandomPieceId = () => { - const randomId = Math.floor(Math.random() * Object.keys(PieceId).length); - return Object.values(PieceId)[randomId]; +export interface DiceSetProps { + dice: { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + }[]; + setDice: React.Dispatch< + React.SetStateAction< + { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + }[] + > + >; +} +const DiceSet = (props: DiceSetProps) => { + const { dice, setDice } = props; + const handleDieClick = (die: { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + }) => { + if (die.isDisabled) return; + const newDiceState = dice.map((oldDie) => { + const isSelected = die === oldDie; + return { + ...oldDie, + isSelected: isSelected, + }; + }); + setDice(newDiceState); }; - const displayedPieceIds = [1, 2, 3, 4].map(getRandomPieceId); return (
- {displayedPieceIds.map((pieceId) => ( -
- -
+ {dice.map((die) => ( + ))}
); diff --git a/web/src/pages/game/components/Die.scss b/web/src/pages/game/components/Die.scss new file mode 100644 index 0000000..d96f7f8 --- /dev/null +++ b/web/src/pages/game/components/Die.scss @@ -0,0 +1,18 @@ +.dice { + height: 150px; + width: 150px; + border: 2px solid black; + border-radius: 10%; + + img{ + border-radius: 10%; + } + + &.selected { + box-shadow: 0 0 20px green; + } + + &.disabled { + box-shadow: 0 0 20px grey; + } +} \ No newline at end of file diff --git a/web/src/pages/game/components/Die.tsx b/web/src/pages/game/components/Die.tsx new file mode 100644 index 0000000..f6644b0 --- /dev/null +++ b/web/src/pages/game/components/Die.tsx @@ -0,0 +1,27 @@ +import { PieceId } from "interface"; +import "./Die.scss"; + +interface DieProps { + die: { pieceId: PieceId; isSelected: boolean; isDisabled: boolean }; + handleDieClick: (die: { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + }) => void; +} + +const Die = (props: DieProps) => { + const { die, handleDieClick } = props; + const { pieceId, isSelected, isDisabled } = die; + + return ( +
handleDieClick(die)} + > + +
+ ); +}; + +export default Die; diff --git a/web/src/pages/game/components/GameBoard.scss b/web/src/pages/game/components/GameBoard.scss index 4d6cc7b..a11648f 100644 --- a/web/src/pages/game/components/GameBoard.scss +++ b/web/src/pages/game/components/GameBoard.scss @@ -7,121 +7,4 @@ grid-template-columns: repeat(7, auto); gap: auto; padding: 50px; - - .cell { - width: 100px; - height: 100px; - border: 2px solid black; - border-radius: 10%; - - &.house { - background-color: blue; - } - - &.university { - background-color: orange; - } - - &.factory { - background-color: grey; - } - - .exit:has(.exit-road) { - border: solid black; - border-width: 0 1px; - - .exit-road { - margin: auto; - width: 0; - height: 100%; - border: dashed black; - border-width: 0 1px; - transform: translate(calc(50% - 1px)); - } - } - - .exit:has(.exit-road) { - border: solid black; - border-width: 0 1px; - - .exit-road { - margin: auto; - width: 0; - height: 100%; - border: dashed black; - border-width: 0 1px; - transform: translate(calc(50% - 1px)); - } - } - - .exit:has(.exit-rail) { - border-width: 0 1px; - - .exit-rail { - margin: auto; - width: 0; - height: 100%; - border: solid black; - border-width: 0 1px; - transform: translate(calc(50% - 1px)); - } - } - - .exit:has(.exit-ambivalent) { - border-width: 0 1px; - border-style: dotted; - - .exit-ambivalent { - margin: auto; - width: 0; - height: 100%; - border: dotted black; - border-width: 0 1px 0 0; - transform: translate(calc(50%)); - } - } - } } - -.exit { - position: relative; - width: 20px; - height: 20px; - - &:has(.exit-north) { - left: 50%; - transform: translate(calc(-50% - 1px), -100%); - } - - &:has(.exit-south) { - left: 50%; - top: 100%; - transform: translate(calc(-50% - 1px), 0%); - } - - &:has(.exit-east) { - left: 100%; - top: 50%; - transform: rotate(90deg) translate(-50%, 0); - } - - &:has(.exit-west) { - left: 0%; - top: 50%; - transform: rotate(90deg) translate(-50%, 100%); - } - - &:has(.exit-north), &:has(.exit-south) { - + .exit:has(.exit-east) { - left: 100%; - transform: rotate(90deg) translate(-150%, 0); - } - } - - &:has(.exit-north), &:has(.exit-south) { - + .exit:has(.exit-west) { - top: 50%; - transform: rotate(90deg) translate(-150%, 100%); - } - } -} \ No newline at end of file diff --git a/web/src/pages/game/components/GameBoard.tsx b/web/src/pages/game/components/GameBoard.tsx index e3dabf0..a713e7d 100644 --- a/web/src/pages/game/components/GameBoard.tsx +++ b/web/src/pages/game/components/GameBoard.tsx @@ -1,28 +1,42 @@ -import { buildBoard, Cell, directions, Exit } from "interface"; +import { buildBoard, PieceId } from "interface"; import "./GameBoard.scss"; +import { useState } from "react"; +import BoardCell from "./BoardCell"; -const GameBoard = () => { - const board: Cell[][] = buildBoard(); +export interface GameBoardProps { + dice: { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + }[]; + setDice: React.Dispatch< + React.SetStateAction< + { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + }[] + > + >; +} + +const GameBoard = (props: GameBoardProps) => { + const [board, setBoard] = useState(buildBoard()); + const [id, setId] = useState(1); + const refreshBoardRender = () => { + setBoard(board); + setId(id + 1); + }; return ( -
+
{board.flatMap((row) => row.map((cell) => ( -
- {directions.map((direction) => { - const traversedNode = cell.getNodeAt(direction).traverseBorder(); - const isExit = traversedNode instanceof Exit; - if (!isExit) return; - const className = - `exit-${direction.toLowerCase()}` + - ` exit-${(traversedNode as Exit).type.toLowerCase()}`; - return ( -
-
-
- ); - })} -
+ )), )}
-- 2.40.1 From b1d57ebfcdefa82bd95453c78ee4dbb16dea783c Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Tue, 3 Dec 2024 13:46:52 +0100 Subject: [PATCH 14/25] Disallow placing piece in places with invalid adjacent connections --- interface/index.ts | 1 - interface/types/Cell.ts | 41 ++++++++++++++++++++- interface/types/Node.ts | 4 -- interface/types/PlacedPiece.ts | 22 ++++++++--- web/src/pages/game/components/BoardCell.tsx | 7 +++- 5 files changed, 63 insertions(+), 12 deletions(-) delete mode 100644 interface/types/Node.ts diff --git a/interface/index.ts b/interface/index.ts index 0cf1028..66f3650 100644 --- a/interface/index.ts +++ b/interface/index.ts @@ -11,5 +11,4 @@ export * from "./types/ExternalNode"; export * from "./types/InternalNode"; export * from "./types/Piece"; export * from "./types/PlacedPiece"; -export * from "./types/Node"; export * from "./BoardBuilder"; diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index 757e471..9f79fad 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -1,7 +1,10 @@ import { CellType } from "../constants/CellType"; import { Direction } from "../constants/Direction"; +import { ExitType } from "../constants/ExitType"; import { PieceId, pieceMap } from "../constants/Pieces"; +import { Exit } from "./Exit"; import { ExternalNode } from "./ExternalNode"; +import { InternalNode } from "./InternalNode"; import { PlacedPiece } from "./PlacedPiece"; export class Cell { @@ -30,8 +33,44 @@ export class Cell { public placePiece(pieceId: PieceId) { if (this.placedPiece !== undefined) return; + const piece = pieceMap[pieceId]; + const connectionTypes = Array.from(piece.tracks).flatMap((track) => { + const directions = + track.joinedPoints.secondPoint instanceof InternalNode + ? [track.joinedPoints.firstPoint] + : [track.joinedPoints.firstPoint, track.joinedPoints.secondPoint]; + return directions.map((direction) => { + return { direction: direction, type: track.type }; + }); + }); + connectionTypes.forEach(({ direction, type }) => { + const adjacentPoint = this.getNodeAt(direction).traverseBorder(); + if (adjacentPoint instanceof Exit) { + if ( + adjacentPoint.type !== ExitType.AMBIVALENT && + adjacentPoint.type.toString() !== type.toString() + ) { + throw Error( + `Unable to place piece, invalid border at direction ${direction}`, + ); + } + } else { + if (adjacentPoint.cell.placedPiece !== undefined) { + const adjacentTrack = + adjacentPoint.cell.placedPiece.piece.findTrackForDirection( + adjacentPoint.direction, + ); + if (adjacentTrack !== undefined && adjacentTrack.type !== type) { + throw Error( + `Unable to place piece next to another due to conflicting track types at ${direction}`, + ); + } + } + } + }); + this.placedPiece = { - piece: pieceMap[pieceId].toPlacedPiece(this), + piece: piece.toPlacedPiece(this), id: pieceId, }; } diff --git a/interface/types/Node.ts b/interface/types/Node.ts deleted file mode 100644 index fa5bbe0..0000000 --- a/interface/types/Node.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { ExternalNode } from "./ExternalNode"; -import { InternalNode } from "./InternalNode"; - -export type Node = ExternalNode | InternalNode; diff --git a/interface/types/PlacedPiece.ts b/interface/types/PlacedPiece.ts index 7582a42..cdbc1f0 100644 --- a/interface/types/PlacedPiece.ts +++ b/interface/types/PlacedPiece.ts @@ -1,22 +1,25 @@ +import { Direction } from "../constants/Direction"; import { TrackType } from "../constants/TrackType"; import { Cell } from "./Cell"; +import { ExternalNode } from "./ExternalNode"; import { InternalNode } from "./InternalNode"; -import { Node } from "./Node"; export class PlacedPiece { tracks: Set<{ nodes: { - firstNode: Node; - secondNode: Node; + firstNode: ExternalNode; + secondNode: ExternalNode | InternalNode; }; type: TrackType; }>; internalNode?: InternalNode; cell: Cell; - constructor( tracks: Set<{ - nodes: { firstNode: Node; secondNode: Node }; + nodes: { + firstNode: ExternalNode; + secondNode: ExternalNode | InternalNode; + }; type: TrackType; }>, internalNodes: InternalNode | undefined, @@ -26,4 +29,13 @@ export class PlacedPiece { this.internalNode = internalNodes; this.cell = cell; } + + public findTrackForDirection(direction: Direction) { + return Array.from(this.tracks).find( + (track) => + track.nodes.firstNode.direction === direction || + (track.nodes.secondNode instanceof ExternalNode && + track.nodes.secondNode.direction === direction), + ); + } } diff --git a/web/src/pages/game/components/BoardCell.tsx b/web/src/pages/game/components/BoardCell.tsx index 2e1d5af..220e7f6 100644 --- a/web/src/pages/game/components/BoardCell.tsx +++ b/web/src/pages/game/components/BoardCell.tsx @@ -25,7 +25,12 @@ const BoardCell = (props: BoardCellProps) => { const handleBoardCellClick = () => { const selectedDie = dice.find((die) => die.isSelected); if (!selectedDie) return; - cell.placePiece(selectedDie.pieceId); + try { + cell.placePiece(selectedDie.pieceId); + } catch (error) { + console.log(error); + return; + } setDice( dice.map((die) => { return die !== selectedDie -- 2.40.1 From 035b7da335ca4d7cc76b579c87d05ddfa5da1b12 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Tue, 3 Dec 2024 18:09:04 +0100 Subject: [PATCH 15/25] Disallow piece placement when piece is not connected to adjacent piece or exit --- interface/constants/Pieces.ts | 2 +- interface/types/Cell.ts | 101 ++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/interface/constants/Pieces.ts b/interface/constants/Pieces.ts index fc12356..e71f635 100644 --- a/interface/constants/Pieces.ts +++ b/interface/constants/Pieces.ts @@ -294,7 +294,7 @@ const T_JUNCTION_ROAD: Piece = new Piece({ }, { startPoint: Direction.WEST, - type: TrackType.RAIL, + type: TrackType.ROAD, }, ], }); diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index 9f79fad..9bac0ba 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -1,10 +1,12 @@ import { CellType } from "../constants/CellType"; -import { Direction } from "../constants/Direction"; +import { Direction, directions } from "../constants/Direction"; import { ExitType } from "../constants/ExitType"; import { PieceId, pieceMap } from "../constants/Pieces"; +import { TrackType } from "../constants/TrackType"; import { Exit } from "./Exit"; import { ExternalNode } from "./ExternalNode"; import { InternalNode } from "./InternalNode"; +import { Piece } from "./Piece"; import { PlacedPiece } from "./PlacedPiece"; export class Cell { @@ -33,45 +35,72 @@ export class Cell { public placePiece(pieceId: PieceId) { if (this.placedPiece !== undefined) return; - const piece = pieceMap[pieceId]; - const connectionTypes = Array.from(piece.tracks).flatMap((track) => { - const directions = - track.joinedPoints.secondPoint instanceof InternalNode - ? [track.joinedPoints.firstPoint] - : [track.joinedPoints.firstPoint, track.joinedPoints.secondPoint]; - return directions.map((direction) => { - return { direction: direction, type: track.type }; - }); - }); - connectionTypes.forEach(({ direction, type }) => { - const adjacentPoint = this.getNodeAt(direction).traverseBorder(); - if (adjacentPoint instanceof Exit) { - if ( - adjacentPoint.type !== ExitType.AMBIVALENT && - adjacentPoint.type.toString() !== type.toString() - ) { - throw Error( - `Unable to place piece, invalid border at direction ${direction}`, - ); - } - } else { - if (adjacentPoint.cell.placedPiece !== undefined) { - const adjacentTrack = - adjacentPoint.cell.placedPiece.piece.findTrackForDirection( - adjacentPoint.direction, - ); - if (adjacentTrack !== undefined && adjacentTrack.type !== type) { - throw Error( - `Unable to place piece next to another due to conflicting track types at ${direction}`, - ); - } - } - } - }); + const piece: Piece = pieceMap[pieceId]; + + this.validatePiecePlacement(piece); this.placedPiece = { piece: piece.toPlacedPiece(this), id: pieceId, }; } + + private validatePiecePlacement(piece: Piece) { + const hasAnyConnection = Array.from(piece.tracks) + .map((track) => { + const trackExternalNodes = [ + this.getNodeAt(track.joinedPoints.firstPoint), + ]; + if (!(track.joinedPoints.secondPoint instanceof InternalNode)) { + trackExternalNodes.push( + this.getNodeAt(track.joinedPoints.secondPoint), + ); + } + return { + trackExternalNodes: trackExternalNodes, + trackType: track.type, + }; + }) + .some(({ trackExternalNodes, trackType }) => { + let isTrackConnected: boolean = false; + trackExternalNodes + .filter((node) => node.traverseBorder() instanceof Exit) + .forEach((node) => { + const exitType = (node.traverseBorder() as Exit).type; + isTrackConnected = true; + if ( + exitType !== ExitType.AMBIVALENT && + exitType.toString() !== trackType.toString() + ) { + throw Error( + `Unable to place piece, invalid exit type at direction ${node.direction}`, + ); + } + }); + + trackExternalNodes + .filter((node) => node.traverseBorder() instanceof ExternalNode) + .forEach((node) => { + const adjacentExternalNode = node.traverseBorder() as ExternalNode; + const adjacentTrack = + adjacentExternalNode.cell.placedPiece?.piece.findTrackForDirection( + adjacentExternalNode.direction, + ); + if (adjacentTrack !== undefined) { + isTrackConnected = true; + if (adjacentTrack.type !== trackType) { + throw Error( + `Unable to place piece next to another due to conflicting track types at ${node.direction}`, + ); + } + } + }); + + return isTrackConnected; + }); + + if (!hasAnyConnection) { + throw Error("No adjacent exit or piece available to connect to"); + } + } } -- 2.40.1 From 5fc02aa6a6fc62f59e0a3cd0a3f073801215e7ae Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Tue, 3 Dec 2024 23:03:28 +0100 Subject: [PATCH 16/25] Enable pieces rotation in dice set and board --- interface/constants/Direction.ts | 17 ++++++++ interface/constants/Pieces.ts | 6 +-- interface/types/Cell.ts | 10 +++-- interface/types/Piece.ts | 29 +++++++++++++- web/public/rotate-icon.png | Bin 0 -> 14454 bytes web/src/pages/game/GamePage.tsx | 1 + web/src/pages/game/components/BoardCell.scss | 12 ++++++ web/src/pages/game/components/BoardCell.tsx | 17 ++++++-- web/src/pages/game/components/DiceSet.scss | 22 +++++++++++ web/src/pages/game/components/DiceSet.tsx | 39 ++++++++++++++++--- web/src/pages/game/components/Die.scss | 14 +++++++ web/src/pages/game/components/Die.tsx | 20 +++++++--- web/src/pages/game/components/GameBoard.tsx | 2 + 13 files changed, 166 insertions(+), 23 deletions(-) create mode 100644 web/public/rotate-icon.png diff --git a/interface/constants/Direction.ts b/interface/constants/Direction.ts index 6bc4347..d44deda 100644 --- a/interface/constants/Direction.ts +++ b/interface/constants/Direction.ts @@ -11,3 +11,20 @@ export const directions: Direction[] = [ Direction.EAST, Direction.WEST, ]; + +export function rotateDirection( + initialDirection: Direction, + rotationAngle: 0 | 90 | 180 | 270, +): Direction { + const angleToDirectionMap: Record = { + [Direction.NORTH]: 0, + [Direction.EAST]: 90, + [Direction.SOUTH]: 180, + [Direction.WEST]: 270, + }; + const finalAngle = + (360 + angleToDirectionMap[initialDirection] - rotationAngle) % 360; + return (Object.keys(angleToDirectionMap) as Direction[]).find( + (direction) => angleToDirectionMap[direction] === finalAngle, + )!; +} diff --git a/interface/constants/Pieces.ts b/interface/constants/Pieces.ts index e71f635..e4bddc3 100644 --- a/interface/constants/Pieces.ts +++ b/interface/constants/Pieces.ts @@ -13,7 +13,6 @@ const STRAIGHT_RAIL: Piece = new Piece({ }, ], }); - const TURN_RAIL: Piece = new Piece({ useInternalTracks: false, trackDefinitions: [ @@ -166,7 +165,7 @@ const DEAD_END_STATION_ROAD: Piece = new Piece({ trackDefinitions: [ { startPoint: Direction.EAST, - type: TrackType.RAIL, + type: TrackType.ROAD, }, ], }); @@ -232,7 +231,6 @@ const FOUR_WAY_WITH_ONE_RAIL: Piece = new Piece({ }, ], }); - const FOUR_WAY_TURNING_CROSSING: Piece = new Piece({ useInternalTracks: true, internalNodeType: InternalNodeType.STATION, @@ -316,7 +314,7 @@ const FOUR_WAY_CROSS_ROAD: Piece = new Piece({ }, { startPoint: Direction.WEST, - type: TrackType.RAIL, + type: TrackType.ROAD, }, ], }); diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index 9bac0ba..6412cc5 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -1,8 +1,7 @@ import { CellType } from "../constants/CellType"; -import { Direction, directions } from "../constants/Direction"; +import { Direction } from "../constants/Direction"; import { ExitType } from "../constants/ExitType"; import { PieceId, pieceMap } from "../constants/Pieces"; -import { TrackType } from "../constants/TrackType"; import { Exit } from "./Exit"; import { ExternalNode } from "./ExternalNode"; import { InternalNode } from "./InternalNode"; @@ -33,9 +32,12 @@ export class Cell { return node!; } - public placePiece(pieceId: PieceId) { + /** + * @param rotation in degrees counter-clockwise + */ + public placePiece(pieceId: PieceId, rotation: 0 | 90 | 180 | 270) { if (this.placedPiece !== undefined) return; - const piece: Piece = pieceMap[pieceId]; + const piece: Piece = pieceMap[pieceId].rotate(rotation); this.validatePiecePlacement(piece); diff --git a/interface/types/Piece.ts b/interface/types/Piece.ts index f684cf4..953c04d 100644 --- a/interface/types/Piece.ts +++ b/interface/types/Piece.ts @@ -1,4 +1,4 @@ -import { Direction } from "../constants/Direction"; +import { Direction, rotateDirection } from "../constants/Direction"; import { TrackType } from "../constants/TrackType"; import { Cell } from "./Cell"; import { InternalNode } from "./InternalNode"; @@ -65,6 +65,33 @@ export class Piece { } } + rotate(rotation: 0 | 90 | 180 | 270): Piece { + return new Piece({ + useInternalTracks: this.internalNode !== undefined, + internalNodeType: this.internalNode?.type, + trackDefinitions: Array.from(this.tracks).map((track) => { + if (track.joinedPoints.secondPoint instanceof InternalNode) { + return { + type: track.type, + startPoint: rotateDirection( + track.joinedPoints.firstPoint, + rotation, + ), + }; + } else { + return { + type: track.type, + startPoint: rotateDirection( + track.joinedPoints.firstPoint, + rotation, + ), + endPoint: rotateDirection(track.joinedPoints.secondPoint, rotation), + }; + } + }), + }); + } + toPlacedPiece(cell: Cell) { return new PlacedPiece( new Set( diff --git a/web/public/rotate-icon.png b/web/public/rotate-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5af53cacb2d1bb2d8102f5023eb9da43174c7e32 GIT binary patch literal 14454 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 literal 0 HcmV?d00001 diff --git a/web/src/pages/game/GamePage.tsx b/web/src/pages/game/GamePage.tsx index 499bd51..4b06b3d 100644 --- a/web/src/pages/game/GamePage.tsx +++ b/web/src/pages/game/GamePage.tsx @@ -16,6 +16,7 @@ const GamePage = () => { pieceId: getRandomPieceId(), isSelected: false, isDisabled: false, + rotation: 0, }; }), ); diff --git a/web/src/pages/game/components/BoardCell.scss b/web/src/pages/game/components/BoardCell.scss index a7822ed..1250a30 100644 --- a/web/src/pages/game/components/BoardCell.scss +++ b/web/src/pages/game/components/BoardCell.scss @@ -15,6 +15,18 @@ &:nth-child(3) { top: -40px; } + + &.rotate-90 { + transform: rotate(-90deg); + } + + &.rotate-180 { + transform: rotate(180deg); + } + + &.rotate-270 { + transform: rotate(90deg); + } } &.house { diff --git a/web/src/pages/game/components/BoardCell.tsx b/web/src/pages/game/components/BoardCell.tsx index 220e7f6..3170438 100644 --- a/web/src/pages/game/components/BoardCell.tsx +++ b/web/src/pages/game/components/BoardCell.tsx @@ -1,5 +1,6 @@ import { Cell, directions, Exit, PieceId } from "interface"; import "./BoardCell.scss"; +import { useState } from "react"; export interface BoardCellProps { cell: Cell; @@ -7,6 +8,7 @@ export interface BoardCellProps { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; + rotation: number; }[]; setDice: React.Dispatch< React.SetStateAction< @@ -14,6 +16,7 @@ export interface BoardCellProps { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; + rotation: number; }[] > >; @@ -22,11 +25,15 @@ export interface BoardCellProps { const BoardCell = (props: BoardCellProps) => { const { cell, dice, setDice, refreshBoardRender } = props; + const [pieceRotationAngle, setPieceRotationAngle] = useState(0); const handleBoardCellClick = () => { const selectedDie = dice.find((die) => die.isSelected); if (!selectedDie) return; try { - cell.placePiece(selectedDie.pieceId); + cell.placePiece( + selectedDie.pieceId, + selectedDie.rotation as 0 | 90 | 180 | 270, + ); } catch (error) { console.log(error); return; @@ -36,12 +43,13 @@ const BoardCell = (props: BoardCellProps) => { return die !== selectedDie ? die : { - pieceId: selectedDie.pieceId, + ...selectedDie, isSelected: false, isDisabled: true, }; }), ); + setPieceRotationAngle(selectedDie.rotation); refreshBoardRender(); }; @@ -64,7 +72,10 @@ const BoardCell = (props: BoardCellProps) => { ); })} {cell.placedPiece && ( - + )}
); diff --git a/web/src/pages/game/components/DiceSet.scss b/web/src/pages/game/components/DiceSet.scss index 1152b08..87776c6 100644 --- a/web/src/pages/game/components/DiceSet.scss +++ b/web/src/pages/game/components/DiceSet.scss @@ -1,3 +1,25 @@ +.dice-set-actions { + display: flex; + flex-direction: row; + padding: 50px 50px 0; + width: max-content; + margin: auto; + + img { + border: 3px solid green; + box-shadow: 0 0 10px green; + border-radius: 20%; + padding: 5px; + width: 80px; + height: 80px; + margin-right: 10px; + + &.icon-inverted { + transform: scaleX(-1); + } + } +} + .dice-set { display: grid; grid-template-columns: repeat(2, auto); diff --git a/web/src/pages/game/components/DiceSet.tsx b/web/src/pages/game/components/DiceSet.tsx index 8e10fe0..1779190 100644 --- a/web/src/pages/game/components/DiceSet.tsx +++ b/web/src/pages/game/components/DiceSet.tsx @@ -1,12 +1,14 @@ import { PieceId } from "interface"; import "./DiceSet.scss"; import Die from "./Die"; +import React from "react"; export interface DiceSetProps { dice: { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; + rotation: number; }[]; setDice: React.Dispatch< React.SetStateAction< @@ -14,6 +16,7 @@ export interface DiceSetProps { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; + rotation: number; }[] > >; @@ -24,6 +27,7 @@ const DiceSet = (props: DiceSetProps) => { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; + rotation: number; }) => { if (die.isDisabled) return; const newDiceState = dice.map((oldDie) => { @@ -36,12 +40,37 @@ const DiceSet = (props: DiceSetProps) => { setDice(newDiceState); }; + const handleRotateButton = (rotation: number) => { + const newDiceState = dice.map((die) => { + if (!die.isSelected) return die; + const rotationAngle = (die.rotation + rotation + 360) % 360; + return { + ...die, + rotation: rotationAngle, + }; + }); + setDice(newDiceState); + }; + return ( -
- {dice.map((die) => ( - - ))} -
+ +
+ handleRotateButton(-90)} + > + handleRotateButton(90)} + > +
+
+ {dice.map((die) => ( + + ))} +
+
); }; diff --git a/web/src/pages/game/components/Die.scss b/web/src/pages/game/components/Die.scss index d96f7f8..b3f4195 100644 --- a/web/src/pages/game/components/Die.scss +++ b/web/src/pages/game/components/Die.scss @@ -15,4 +15,18 @@ &.disabled { box-shadow: 0 0 20px grey; } + + &.rotate-90 { + transform: rotate(-90deg); + } + + &.rotate-180 { + transform: rotate(180deg); + } + + &.rotate-270 { + transform: rotate(90deg); + } + + transition: transform 0.5s cubic-bezier(.47,1.64,.41,.8); } \ No newline at end of file diff --git a/web/src/pages/game/components/Die.tsx b/web/src/pages/game/components/Die.tsx index f6644b0..ba8474f 100644 --- a/web/src/pages/game/components/Die.tsx +++ b/web/src/pages/game/components/Die.tsx @@ -2,23 +2,31 @@ import { PieceId } from "interface"; import "./Die.scss"; interface DieProps { - die: { pieceId: PieceId; isSelected: boolean; isDisabled: boolean }; + die: { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + rotation: number; + }; handleDieClick: (die: { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; + rotation: number; }) => void; } const Die = (props: DieProps) => { const { die, handleDieClick } = props; - const { pieceId, isSelected, isDisabled } = die; + const { pieceId, isSelected, isDisabled, rotation } = die; + const className = + "dice" + + (isSelected ? " selected" : "") + + (isDisabled ? " disabled" : "") + + ` rotate-${rotation}`; return ( -
handleDieClick(die)} - > +
handleDieClick(die)}>
); diff --git a/web/src/pages/game/components/GameBoard.tsx b/web/src/pages/game/components/GameBoard.tsx index a713e7d..0997041 100644 --- a/web/src/pages/game/components/GameBoard.tsx +++ b/web/src/pages/game/components/GameBoard.tsx @@ -8,6 +8,7 @@ export interface GameBoardProps { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; + rotation: number; }[]; setDice: React.Dispatch< React.SetStateAction< @@ -15,6 +16,7 @@ export interface GameBoardProps { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; + rotation: number; }[] > >; -- 2.40.1 From 4f9950c6a9eb8e2d2dc5544fe1510af1e0d27981 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sat, 8 Feb 2025 16:23:55 +0100 Subject: [PATCH 17/25] Create landing page base layout --- web/src/App.tsx | 4 ++- web/src/pages/lobby/LobbyPage.scss | 42 ++++++++++++++++++++++++++++++ web/src/pages/lobby/LobbyPage.tsx | 23 ++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 web/src/pages/lobby/LobbyPage.scss create mode 100644 web/src/pages/lobby/LobbyPage.tsx diff --git a/web/src/App.tsx b/web/src/App.tsx index b1fc803..ac08d68 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -2,17 +2,19 @@ import React from "react"; import { Socket } from "socket.io-client"; import LandingPage from "./pages/landing/LandingPage"; import GamePage from "./pages/game/GamePage"; +import LobbyPage from "./pages/lobby/LobbyPage"; export interface AppProps { socket: Socket; } const App = (props: AppProps) => { - const renderedPage: string = "LANDING"; + const renderedPage: string = "LOBBY"; return (
{renderedPage === "LANDING" && } + {renderedPage === "LOBBY" && } {renderedPage === "GAME" && }
); diff --git a/web/src/pages/lobby/LobbyPage.scss b/web/src/pages/lobby/LobbyPage.scss new file mode 100644 index 0000000..226320d --- /dev/null +++ b/web/src/pages/lobby/LobbyPage.scss @@ -0,0 +1,42 @@ +.lobby-page { + height: 100%; + width: 100%; + padding: 2%; + margin: 0 auto; + text-align: center; + + background: linear-gradient(-45deg, #03444a, #00a8a8, #f1bc52, #ff8f4b); + background-size: 400% 400%; + animation: gradient 15s ease infinite; + height: 100vh; + + @keyframes gradient { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } + } + + .lobby-page-body { + margin: auto; + width: 20%; + min-width: 300px; + + .lobby-user-name { + margin: 0 auto 10px; + padding: 10px; + width: 60%; + border: 2px solid cyan; + border-radius: 10px; + } + + .start-game-button { + margin-top: 30px; + } + } +} diff --git a/web/src/pages/lobby/LobbyPage.tsx b/web/src/pages/lobby/LobbyPage.tsx new file mode 100644 index 0000000..231027a --- /dev/null +++ b/web/src/pages/lobby/LobbyPage.tsx @@ -0,0 +1,23 @@ +import "./LobbyPage.scss"; + +const LobbyPage = () => { + const userNames = ["Laura", "Miguel", "David"]; + + return ( +
+
+

Trains And Roads

+
+
+ {userNames.map((name) => ( +
{name}
+ ))} +
+ +
+
+
+ ); +}; + +export default LobbyPage; -- 2.40.1 From 00c365de84def4576c8e2aa8fce11c6c8ff716f2 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sun, 9 Feb 2025 14:38:08 +0100 Subject: [PATCH 18/25] Add transition to lobby page --- interface/server-events/UpdateLobbyEvent.ts | 6 ++--- web/src/App.tsx | 29 ++++++++++++++++++--- web/src/pages/lobby/LobbyPage.scss | 10 ++++++- web/src/pages/lobby/LobbyPage.tsx | 23 +++++++++++++--- 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/interface/server-events/UpdateLobbyEvent.ts b/interface/server-events/UpdateLobbyEvent.ts index 90f696a..2f0881d 100644 --- a/interface/server-events/UpdateLobbyEvent.ts +++ b/interface/server-events/UpdateLobbyEvent.ts @@ -3,12 +3,12 @@ import { ServerEvent } from "./ServerEvent"; export type UpdateLobbyEvent = { playerNames: Array; + gameCode: string; }; export function attachHandlerToUpdateLobbyEvent( socket: Socket, handler: (event: UpdateLobbyEvent) => void, -): () => void { - socket.on(ServerEvent.LOBBY_UPDATE, handler); - return () => socket.off(ServerEvent.LOBBY_UPDATE, handler); +): void { + socket.once(ServerEvent.LOBBY_UPDATE, handler); } diff --git a/web/src/App.tsx b/web/src/App.tsx index ac08d68..7b878b6 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,20 +1,43 @@ -import React from "react"; +import React, { useCallback, useState } from "react"; import { Socket } from "socket.io-client"; import LandingPage from "./pages/landing/LandingPage"; import GamePage from "./pages/game/GamePage"; import LobbyPage from "./pages/lobby/LobbyPage"; +import { attachHandlerToUpdateLobbyEvent } from "interface"; export interface AppProps { socket: Socket; } const App = (props: AppProps) => { - const renderedPage: string = "LOBBY"; + const { socket } = props; + const [renderedPage, setRenderedPage] = useState("LANDING"); + + const [initialPlayerNames, setInitialPlayerNames] = useState([""]); + const [gameCode, setGameCode] = useState(""); + + const setupNextPageTransition = useCallback(() => { + if (renderedPage === "LANDING") { + attachHandlerToUpdateLobbyEvent(socket, (event) => { + setInitialPlayerNames(event.playerNames); + setGameCode(event.gameCode); + setRenderedPage("LOBBY"); + }); + } + }, [renderedPage]); + + setupNextPageTransition(); return (
{renderedPage === "LANDING" && } - {renderedPage === "LOBBY" && } + {renderedPage === "LOBBY" && ( + + )} {renderedPage === "GAME" && }
); diff --git a/web/src/pages/lobby/LobbyPage.scss b/web/src/pages/lobby/LobbyPage.scss index 226320d..5a935f7 100644 --- a/web/src/pages/lobby/LobbyPage.scss +++ b/web/src/pages/lobby/LobbyPage.scss @@ -35,8 +35,16 @@ border-radius: 10px; } + .game-code { + margin: 0 auto 10px; + padding: 10px; + width: 60%; + border: 2px solid blue; + border-radius: 10px; + } + .start-game-button { - margin-top: 30px; + margin: 30px 0; } } } diff --git a/web/src/pages/lobby/LobbyPage.tsx b/web/src/pages/lobby/LobbyPage.tsx index 231027a..e92f168 100644 --- a/web/src/pages/lobby/LobbyPage.tsx +++ b/web/src/pages/lobby/LobbyPage.tsx @@ -1,7 +1,21 @@ +import { useState } from "react"; import "./LobbyPage.scss"; +import { Socket } from "socket.io-client"; +import { attachHandlerToUpdateLobbyEvent } from "interface"; -const LobbyPage = () => { - const userNames = ["Laura", "Miguel", "David"]; +export interface LobbyPageProps { + initialPlayerNames: string[]; + gameCode: string; + socket: Socket; +} + +const LobbyPage = (props: LobbyPageProps) => { + const { initialPlayerNames, gameCode, socket } = props; + const [playerNames, setPlayerNames] = useState(initialPlayerNames); + + attachHandlerToUpdateLobbyEvent(socket, (event) => { + setPlayerNames(event.playerNames); + }); return (
@@ -9,12 +23,13 @@ const LobbyPage = () => {

Trains And Roads

- {userNames.map((name) => ( -
{name}
+ {playerNames.map((name) => ( +
{name}
))}
+
Game code: {gameCode}
); -- 2.40.1 From b72a74789c6cdc8295c7dba1e84fc40017b9e94a Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Wed, 4 Dec 2024 12:25:24 +0100 Subject: [PATCH 19/25] Add icons for special cells and fix piece placement issues --- interface/types/Cell.ts | 6 +- web/public/factory-icon.png | Bin 0 -> 19135 bytes web/public/house-icon.png | Bin 0 -> 17778 bytes web/public/university-icon.png | Bin 0 -> 17895 bytes web/src/pages/game/components/BoardCell.scss | 85 ++++++------------- web/src/pages/game/components/BoardCell.tsx | 13 +-- 6 files changed, 37 insertions(+), 67 deletions(-) create mode 100644 web/public/factory-icon.png create mode 100644 web/public/house-icon.png create mode 100644 web/public/university-icon.png diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index 6412cc5..c71bb2b 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -63,7 +63,7 @@ export class Cell { trackType: track.type, }; }) - .some(({ trackExternalNodes, trackType }) => { + .reduce((isConnected, { trackExternalNodes, trackType }) => { let isTrackConnected: boolean = false; trackExternalNodes .filter((node) => node.traverseBorder() instanceof Exit) @@ -98,8 +98,8 @@ export class Cell { } }); - return isTrackConnected; - }); + return isConnected || isTrackConnected; + }, false); if (!hasAnyConnection) { throw Error("No adjacent exit or piece available to connect to"); diff --git a/web/public/factory-icon.png b/web/public/factory-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e7c3ad86ab6038748a4477ad8fd1f72e3a2d46fb GIT binary patch literal 19135 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

`oTS6=D}!v^Ls2N_ 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

TFeg{gjCvHo|fq}@;d3Ozwk!F`>t@VI=8 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 { }; return ( -

+
{directions.map((direction) => { const traversedNode = cell.getNodeAt(direction).traverseBorder(); const isExit = traversedNode instanceof Exit; @@ -77,6 +74,12 @@ const BoardCell = (props: BoardCellProps) => { src={`pieces/${cell.placedPiece.id}.jpeg`} > )} + {cell.cellType !== CellType.NORMAL && ( + + )}
); }; -- 2.40.1 From 86d5137857ea41e0fac1a10e831e327927870b4c Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Wed, 4 Dec 2024 17:09:21 +0100 Subject: [PATCH 20/25] Implement special dice usage and layout --- web/src/pages/game/GamePage.scss | 1 + web/src/pages/game/GamePage.tsx | 67 ++++++++++++++++-- web/src/pages/game/components/BoardCell.tsx | 57 ++++++++-------- web/src/pages/game/components/DiceSet.scss | 14 +++- web/src/pages/game/components/DiceSet.tsx | 76 +++++++++------------ web/src/pages/game/components/Die.scss | 5 ++ web/src/pages/game/components/Die.tsx | 16 +---- web/src/pages/game/components/GameBoard.tsx | 27 +++----- web/src/pages/game/types/DieViewProps.ts | 9 +++ 9 files changed, 164 insertions(+), 108 deletions(-) create mode 100644 web/src/pages/game/types/DieViewProps.ts diff --git a/web/src/pages/game/GamePage.scss b/web/src/pages/game/GamePage.scss index 9847b6c..87b1eba 100644 --- a/web/src/pages/game/GamePage.scss +++ b/web/src/pages/game/GamePage.scss @@ -12,5 +12,6 @@ h1 { .right-panel { display: flex; flex-direction: column; + padding: 50px; } } diff --git a/web/src/pages/game/GamePage.tsx b/web/src/pages/game/GamePage.tsx index 4b06b3d..4e15ed6 100644 --- a/web/src/pages/game/GamePage.tsx +++ b/web/src/pages/game/GamePage.tsx @@ -3,6 +3,7 @@ import GameBoard from "./components/GameBoard"; import DiceSet from "./components/DiceSet"; import "./GamePage.scss"; import { PieceId } from "interface"; +import { DieViewProps } from "./types/DieViewProps"; const GamePage = () => { const getRandomPieceId = () => { @@ -12,22 +13,80 @@ const GamePage = () => { const [dice, setDice] = useState( [1, 2, 3, 4].map(() => { - return { + const dieViewProps: DieViewProps = { pieceId: getRandomPieceId(), isSelected: false, isDisabled: false, + isSpecial: false, + rotation: 0, + }; + return dieViewProps; + }), + ); + const [specialDice, setSpecialDice] = useState( + [ + PieceId.P03, + PieceId.P08, + PieceId.P13, + PieceId.P14, + PieceId.P15, + PieceId.P19, + ].map((pieceId) => { + return { + pieceId: pieceId, + isSelected: false, + isDisabled: false, + isSpecial: true, rotation: 0, }; }), ); + const [specialDieUsedInRound, setSpecialDieUsedInRound] = useState(false); + + const modifyDieState = ( + matcher: (die: DieViewProps) => boolean, + newStateComputer: (die: DieViewProps) => Partial, + ) => { + setDice( + dice.map((die) => { + if (!matcher(die)) return die; + return { + ...die, + ...newStateComputer(die), + }; + }), + ); + setSpecialDice( + specialDice.map((die) => { + if (!matcher(die)) return die; + return { + ...die, + ...newStateComputer(die), + }; + }), + ); + }; + + const fetchDie = (matcher: (die: DieViewProps) => boolean) => { + return dice.concat(specialDice).find((die) => matcher(die)); + }; return (

Game Page Title

- -
- + +
+
diff --git a/web/src/pages/game/components/BoardCell.tsx b/web/src/pages/game/components/BoardCell.tsx index ecfa25f..1c426a6 100644 --- a/web/src/pages/game/components/BoardCell.tsx +++ b/web/src/pages/game/components/BoardCell.tsx @@ -1,33 +1,32 @@ -import { Cell, CellType, directions, Exit, PieceId } from "interface"; +import { Cell, CellType, directions, Exit } from "interface"; import "./BoardCell.scss"; import { useState } from "react"; +import { DieViewProps } from "../types/DieViewProps"; export interface BoardCellProps { cell: Cell; - dice: { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }[]; - setDice: React.Dispatch< - React.SetStateAction< - { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }[] - > - >; refreshBoardRender: () => void; + modifyDieState: ( + matcher: (die: DieViewProps) => boolean, + newStateComputer: (die: DieViewProps) => Partial, + ) => void; + fetchDie: ( + matcher: (die: DieViewProps) => boolean, + ) => DieViewProps | undefined; + setSpecialDieUsedInRound: React.Dispatch>; } const BoardCell = (props: BoardCellProps) => { - const { cell, dice, setDice, refreshBoardRender } = props; + const { + cell, + refreshBoardRender, + modifyDieState, + fetchDie, + setSpecialDieUsedInRound, + } = props; const [pieceRotationAngle, setPieceRotationAngle] = useState(0); const handleBoardCellClick = () => { - const selectedDie = dice.find((die) => die.isSelected); + const selectedDie = fetchDie((die) => die.isSelected); if (!selectedDie) return; try { cell.placePiece( @@ -38,17 +37,17 @@ const BoardCell = (props: BoardCellProps) => { console.log(error); return; } - setDice( - dice.map((die) => { - return die !== selectedDie - ? die - : { - ...selectedDie, - isSelected: false, - isDisabled: true, - }; - }), + modifyDieState( + (die) => die === selectedDie, + () => { + return { + isSelected: false, + isDisabled: true, + }; + }, ); + if (selectedDie.isSpecial) setSpecialDieUsedInRound(true); + // Set rotation to the piece in the board, not the die setPieceRotationAngle(selectedDie.rotation); refreshBoardRender(); }; diff --git a/web/src/pages/game/components/DiceSet.scss b/web/src/pages/game/components/DiceSet.scss index 87776c6..da09ab7 100644 --- a/web/src/pages/game/components/DiceSet.scss +++ b/web/src/pages/game/components/DiceSet.scss @@ -1,9 +1,8 @@ .dice-set-actions { display: flex; flex-direction: row; - padding: 50px 50px 0; width: max-content; - margin: auto; + margin: auto auto 50px auto; img { border: 3px solid green; @@ -24,5 +23,14 @@ display: grid; grid-template-columns: repeat(2, auto); gap: 20px; - padding: 50px; + margin: 0 0 50px 0; +} + +.special-dice-set { + display: grid; + grid-template-columns: repeat(3, auto); + margin: 0 0 50px 0; + column-gap: 12%; + row-gap: 20px; + width: 100%; } \ No newline at end of file diff --git a/web/src/pages/game/components/DiceSet.tsx b/web/src/pages/game/components/DiceSet.tsx index 1779190..518e2a1 100644 --- a/web/src/pages/game/components/DiceSet.tsx +++ b/web/src/pages/game/components/DiceSet.tsx @@ -1,55 +1,42 @@ -import { PieceId } from "interface"; import "./DiceSet.scss"; import Die from "./Die"; import React from "react"; +import { DieViewProps } from "../types/DieViewProps"; export interface DiceSetProps { - dice: { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }[]; - setDice: React.Dispatch< - React.SetStateAction< - { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }[] - > - >; + dice: DieViewProps[]; + specialDice: DieViewProps[]; + modifyDieState: ( + matcher: (die: DieViewProps) => boolean, + newStateComputer: (die: DieViewProps) => Partial, + ) => void; + specialDieUsedInRound: boolean; } const DiceSet = (props: DiceSetProps) => { - const { dice, setDice } = props; - const handleDieClick = (die: { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }) => { - if (die.isDisabled) return; - const newDiceState = dice.map((oldDie) => { - const isSelected = die === oldDie; - return { - ...oldDie, - isSelected: isSelected, - }; - }); - setDice(newDiceState); + const { dice, specialDice, modifyDieState, specialDieUsedInRound } = props; + const handleDieClick = (clickedDie: DieViewProps) => { + if (clickedDie.isDisabled) return; + const isSpecialDie = clickedDie.isSpecial; + if (isSpecialDie && specialDieUsedInRound) return; + modifyDieState( + () => true, + (die) => { + return { + isSelected: die === clickedDie, + }; + }, + ); }; const handleRotateButton = (rotation: number) => { - const newDiceState = dice.map((die) => { - if (!die.isSelected) return die; - const rotationAngle = (die.rotation + rotation + 360) % 360; - return { - ...die, - rotation: rotationAngle, - }; - }); - setDice(newDiceState); + modifyDieState( + (die) => die.isSelected, + (die) => { + return { + rotation: (die.rotation + rotation + 360) % 360, + }; + }, + ); }; return ( @@ -70,6 +57,11 @@ const DiceSet = (props: DiceSetProps) => { ))}
+
+ {specialDice.map((die) => ( + + ))} +
); }; diff --git a/web/src/pages/game/components/Die.scss b/web/src/pages/game/components/Die.scss index b3f4195..675582d 100644 --- a/web/src/pages/game/components/Die.scss +++ b/web/src/pages/game/components/Die.scss @@ -29,4 +29,9 @@ } transition: transform 0.5s cubic-bezier(.47,1.64,.41,.8); +} + +.special-dice-set .dice { + height: 80px; + width: 80px; } \ No newline at end of file diff --git a/web/src/pages/game/components/Die.tsx b/web/src/pages/game/components/Die.tsx index ba8474f..c039c39 100644 --- a/web/src/pages/game/components/Die.tsx +++ b/web/src/pages/game/components/Die.tsx @@ -1,19 +1,9 @@ -import { PieceId } from "interface"; import "./Die.scss"; +import { DieViewProps } from "../types/DieViewProps"; interface DieProps { - die: { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }; - handleDieClick: (die: { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }) => void; + die: DieViewProps; + handleDieClick: (die: DieViewProps) => void; } const Die = (props: DieProps) => { diff --git a/web/src/pages/game/components/GameBoard.tsx b/web/src/pages/game/components/GameBoard.tsx index 0997041..8ea33b9 100644 --- a/web/src/pages/game/components/GameBoard.tsx +++ b/web/src/pages/game/components/GameBoard.tsx @@ -1,25 +1,18 @@ -import { buildBoard, PieceId } from "interface"; +import { buildBoard } from "interface"; import "./GameBoard.scss"; import { useState } from "react"; import BoardCell from "./BoardCell"; +import { DieViewProps } from "../types/DieViewProps"; export interface GameBoardProps { - dice: { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }[]; - setDice: React.Dispatch< - React.SetStateAction< - { - pieceId: PieceId; - isSelected: boolean; - isDisabled: boolean; - rotation: number; - }[] - > - >; + modifyDieState: ( + matcher: (die: DieViewProps) => boolean, + newStateComputer: (die: DieViewProps) => Partial, + ) => void; + fetchDie: ( + matcher: (die: DieViewProps) => boolean, + ) => DieViewProps | undefined; + setSpecialDieUsedInRound: React.Dispatch>; } const GameBoard = (props: GameBoardProps) => { diff --git a/web/src/pages/game/types/DieViewProps.ts b/web/src/pages/game/types/DieViewProps.ts new file mode 100644 index 0000000..05f049a --- /dev/null +++ b/web/src/pages/game/types/DieViewProps.ts @@ -0,0 +1,9 @@ +import { PieceId } from "interface"; + +export interface DieViewProps { + pieceId: PieceId; + isSelected: boolean; + isDisabled: boolean; + isSpecial: boolean; + rotation: number; +} -- 2.40.1 From 0a0ca65e3b05a866e3add6da5a40aec020db4468 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Wed, 4 Dec 2024 22:38:28 +0100 Subject: [PATCH 21/25] Introduce clean and commit action buttons --- web/public/clean-icon.png | Bin 0 -> 9113 bytes web/public/commit-icon.png | Bin 0 -> 16323 bytes web/src/pages/game/GamePage.tsx | 42 ++++++++++++++++---- web/src/pages/game/components/DiceSet.scss | 8 +++- web/src/pages/game/components/DiceSet.tsx | 13 +++++- web/src/pages/game/components/GameBoard.tsx | 22 +++------- web/src/pages/game/types/DieViewProps.ts | 2 +- 7 files changed, 60 insertions(+), 27 deletions(-) create mode 100644 web/public/clean-icon.png create mode 100644 web/public/commit-icon.png diff --git a/web/public/clean-icon.png b/web/public/clean-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c06ba906d80c3f150600d10e774ef0842bb30a62 GIT binary patch literal 9113 zcmd5?hg%cR(+>oYu2Q7;1f+MQC?HJ^1T?^xULpcgM0$}LiGV0ANa#(16zNEj8bClg zB2A?Pk=~nhc#q#-@jl5txt+|;d}e26cW?IIJkozaL&-`Bfk0>gZ4CqjLbQK%k&}Ux zzVX>;@Q3V)?gI_T<<%#rxgZgwP`GQGc|jml^j8-VBrSs(0^x=L8uyL-e{D<$?i()z zFYO#2TM-WDLlVNK{(dNA*8EOhSU9T7CZ1yYqG;qDz`v}M`K(mEYJJj(U%JMpQ!;Ph z9ZM;Etp96O+QP`fvgrp8%_2!29S*1-vxWw>riO;b*V(h3bsPD!Gpj-S?CR{`!PA;? zYdyY*;Fclfp`~?4mD2!K3=H`H|6SE=qtnLlj*z`0(}IMDS>e}Ilk*c`f*0w1KTr=6 z37Y}yq!$d#c118C`UktM7uWrn-yTfEPCvo+QrX$K)T^eWNuvH*GzMnRwRmX4yx7^D zibY^>>r<&}DSljDA_Xwu;P5p=M-$Z~g}3Q{0A|(EycanW95g+mgE8XTcz-9oIm6Co zw^ba#IIp8vUk4m|py60pQSD%K z;zVj;KusmPe5HQq#D9IF0OCX+_it$6ZQKgh5`**hxiM~0?wHe9{|*KS3PB9U75Z&z z*DK_yM; zwKWI_bb6k(yEz`v?lt4x`@{jnfq58{RD+Vr(C$^|7f%@$g+-fTz=}M7p2RGTw|NMF zDV_k%lYKXoZ<&FOksWs}WJ~-1RP{+y?s4F4|0jla;C6pw7%A2UgIld3Vw0lW3lwby z<$QB?n%KZ||Bpu>-kAIE%l}wtuKfd5`TbA43FJRVhD8hVp$#~INOFULOm-q*-!UcL z4hb8#V>nPe!%Y}?*B%5NcBa?H7&Tv$YEn{}0udWEcd|qrOZ`uJ7vvPw8Y4d{R-_Ha z1fvs?bB5B}DkKq4_YZBLt~D&MgT+ti0T_&C{VmH(YIzq>f;sUJm-r#2 z4NZHGOi>yYb5dnPQHh3+mV+*cK(>74j~~sB#Z~*`5!&YsDxfL$$8egz-*6q1Z-*9f zEg6}}lr5;%ZxRfdr_bYV$r(>=uEd3rGAle>4uwOM2(QYwI4j`7KSRWyGB3t~d^(a1 z50)ySk<LpTiYW2IaBmS8kFLfvUA79I4vASJ>RJ|9(rSj3Vv4S4a@sd5mf1}43b3;? z!$P^gPrbb%y}anWMC$~9yiqan_T3~JC~aksvn^lPJmsP$j_GVkCIiqf85*rd?gVXojIhA9uUH5NeItN%&MiBi38AvLbA+Z zuOsJ}-4{2u9lB5OKxtB$BDqPkZ{1*gN_4&4qF%V zIBw=0Sxc(NHRGUlQa3W%N+*U~3#p3`*RQ$0fF>oLn$QyUs;T^NoQa4-E|qt?h`fc~ z5VR%}zk|0)*q}=qyX$!Qa3uG5rgZf=7-sWZ_yalhCO>V&uL&bvI$u5%1zyIM(_Pm6 zS$Ob_4Y2`KoLHP_E$lFnOPCAJk@Ft=AZ$~sS9KwzSlcb+3+gm!OJwV=EF^) zqAJ0W@TB1t=}0qJV=fvx82ZKUn>o#V_K<*ZG9{XPjwi6$>ms zm-NWcStY|?L7B@aXySqjbc=H6Umcy_YR=UZo$2VB`TWT#oqy^Z$&=I=XXLGwGLb`S ziHwYfL@8zs0m@uvvX~Zd~!}@2U+u{bL+G;233Bc+Q-zhFEvt=NPZSswJ>oUytMNPyWq- z+0Bt%`5art5UowMtpgfNbVmU5o=>HFX(_so4AX-ds)l=PzN% zix0Ec0F2NNE&qEW5vtiwytEM^?dl$8H-QxK8bO$#N`%>~!VESbrM%1J4qVX0GEs@s zE-V-v$`IRWN@yx;RdNxJT9e^*BW`gmUM zHEdyGLzCkqsPD0#i5A^rAZku761HGSb#3d0x-CYlgtpsV+Cx%M}2{;+<%%^!c2rKYO?i1po9M9 zNsqr)es*C(LYVP z9Z4Nko=-KvfVsjUn;Jf=Aig9&yK8JOQ6UPN8>_SiAlx`KO({y!xJ|YE$x3!hqn0

!iBoxHS#BHtQ)Me=SZvZC8V2&_S+r400#mz_7j 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 literal 0 HcmV?d00001 diff --git a/web/public/commit-icon.png b/web/public/commit-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d254d8d86fe123985ce1e9f5a02a34a84fbc27df GIT binary patch literal 16323 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 V{Loa7JqUj`bye-F1y?K|{6GGnGu;3H literal 0 HcmV?d00001 diff --git a/web/src/pages/game/GamePage.tsx b/web/src/pages/game/GamePage.tsx index 4e15ed6..4ad8707 100644 --- a/web/src/pages/game/GamePage.tsx +++ b/web/src/pages/game/GamePage.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import GameBoard from "./components/GameBoard"; import DiceSet from "./components/DiceSet"; import "./GamePage.scss"; -import { PieceId } from "interface"; +import { buildBoard, PieceId } from "interface"; import { DieViewProps } from "./types/DieViewProps"; const GamePage = () => { @@ -11,18 +11,18 @@ const GamePage = () => { return Object.values(PieceId)[randomId]; }; - const [dice, setDice] = useState( + const getRandomDiceSet: () => DieViewProps[] = () => [1, 2, 3, 4].map(() => { - const dieViewProps: DieViewProps = { + return { pieceId: getRandomPieceId(), isSelected: false, isDisabled: false, isSpecial: false, rotation: 0, }; - return dieViewProps; - }), - ); + }); + + const [dice, setDice] = useState(getRandomDiceSet()); const [specialDice, setSpecialDice] = useState( [ PieceId.P03, @@ -71,14 +71,40 @@ const GamePage = () => { return dice.concat(specialDice).find((die) => matcher(die)); }; + const [storedBoard, setStoredBoard] = useState(buildBoard()); + const [board, setBoard] = useState(buildBoard()); + const [id, setId] = useState(1); + const refreshBoardRender = () => { + setBoard(board); + setId(id + 1); + }; + const resetBoard = () => { + setBoard(storedBoard); + modifyDieState( + () => true, + () => { + return { isSelected: false, isDisabled: false }; + }, + ); + setId(id + 1); + }; + const commitBoard = () => { + if (dice.some((die) => !die.isDisabled)) return; + setStoredBoard(board); + setDice(getRandomDiceSet()); + setSpecialDieUsedInRound(false); + }; + return (

Game Page Title

-
+
{ specialDice={specialDice} modifyDieState={modifyDieState} specialDieUsedInRound={specialDieUsedInRound} + resetBoard={resetBoard} + commitBoard={commitBoard} />
diff --git a/web/src/pages/game/components/DiceSet.scss b/web/src/pages/game/components/DiceSet.scss index da09ab7..114a733 100644 --- a/web/src/pages/game/components/DiceSet.scss +++ b/web/src/pages/game/components/DiceSet.scss @@ -9,13 +9,17 @@ box-shadow: 0 0 10px green; border-radius: 20%; padding: 5px; - width: 80px; - height: 80px; + width: 70px; + height: 70px; margin-right: 10px; &.icon-inverted { transform: scaleX(-1); } + + &:last-child { + margin-right: 0; + } } } diff --git a/web/src/pages/game/components/DiceSet.tsx b/web/src/pages/game/components/DiceSet.tsx index 518e2a1..bf0b5a2 100644 --- a/web/src/pages/game/components/DiceSet.tsx +++ b/web/src/pages/game/components/DiceSet.tsx @@ -11,9 +11,18 @@ export interface DiceSetProps { newStateComputer: (die: DieViewProps) => Partial, ) => void; specialDieUsedInRound: boolean; + resetBoard: () => void; + commitBoard: () => void; } const DiceSet = (props: DiceSetProps) => { - const { dice, specialDice, modifyDieState, specialDieUsedInRound } = props; + const { + dice, + specialDice, + modifyDieState, + specialDieUsedInRound, + resetBoard, + commitBoard, + } = props; const handleDieClick = (clickedDie: DieViewProps) => { if (clickedDie.isDisabled) return; const isSpecialDie = clickedDie.isSpecial; @@ -51,6 +60,8 @@ const DiceSet = (props: DiceSetProps) => { className="icon-inverted" onClick={() => handleRotateButton(90)} > + +
{dice.map((die) => ( diff --git a/web/src/pages/game/components/GameBoard.tsx b/web/src/pages/game/components/GameBoard.tsx index 8ea33b9..2ddfb81 100644 --- a/web/src/pages/game/components/GameBoard.tsx +++ b/web/src/pages/game/components/GameBoard.tsx @@ -1,6 +1,5 @@ -import { buildBoard } from "interface"; +import { Cell } from "interface"; import "./GameBoard.scss"; -import { useState } from "react"; import BoardCell from "./BoardCell"; import { DieViewProps } from "../types/DieViewProps"; @@ -13,26 +12,17 @@ export interface GameBoardProps { matcher: (die: DieViewProps) => boolean, ) => DieViewProps | undefined; setSpecialDieUsedInRound: React.Dispatch>; + refreshBoardRender: () => void; + board: Cell[][]; } const GameBoard = (props: GameBoardProps) => { - const [board, setBoard] = useState(buildBoard()); - const [id, setId] = useState(1); - const refreshBoardRender = () => { - setBoard(board); - setId(id + 1); - }; + const { board } = props; return ( -
+
{board.flatMap((row) => - row.map((cell) => ( - - )), + row.map((cell) => ), )}
); diff --git a/web/src/pages/game/types/DieViewProps.ts b/web/src/pages/game/types/DieViewProps.ts index 05f049a..71914ed 100644 --- a/web/src/pages/game/types/DieViewProps.ts +++ b/web/src/pages/game/types/DieViewProps.ts @@ -4,6 +4,6 @@ export interface DieViewProps { pieceId: PieceId; isSelected: boolean; isDisabled: boolean; - isSpecial: boolean; + readonly isSpecial: boolean; rotation: number; } -- 2.40.1 From 7c4a6f560320f3b08d7ea2ecf0bff5c68bcb4dd9 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Thu, 5 Dec 2024 10:46:38 +0100 Subject: [PATCH 22/25] Fix commit and reset actions crossing pointers by creating an action stack (will be used to send data to backend) --- interface/types/Cell.ts | 4 ++ web/package-lock.json | 8 ++-- web/package.json | 2 +- web/src/pages/game/GamePage.tsx | 13 ++++-- web/src/pages/game/components/BoardCell.tsx | 9 ++--- web/src/pages/game/components/GameBoard.tsx | 24 +++++++++-- web/src/pages/game/types/PlacePieceAction.ts | 32 +++++++++++++++ .../pages/game/types/PlacePieceActionStack.ts | 40 +++++++++++++++++++ 8 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 web/src/pages/game/types/PlacePieceAction.ts create mode 100644 web/src/pages/game/types/PlacePieceActionStack.ts diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index c71bb2b..cd12587 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -105,4 +105,8 @@ export class Cell { throw Error("No adjacent exit or piece available to connect to"); } } + + public removePiece() { + this.placedPiece = undefined; + } } diff --git a/web/package-lock.json b/web/package-lock.json index 936fa4a..6028a80 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -13,7 +13,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.5.2", - "@types/node": "^16.18.119", + "@types/node": "^17.0.29", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "interface": "file:../interface", @@ -4202,9 +4202,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "16.18.119", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.119.tgz", - "integrity": "sha512-ia7V9a2FnhUFfetng4/sRPBMTwHZUkPFY736rb1cg9AgG7MZdR97q7/nLR9om+sq5f1la9C857E0l/nrI0RiFQ==", + "version": "17.0.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.29.tgz", + "integrity": "sha512-tx5jMmMFwx7wBwq/V7OohKDVb/JwJU5qCVkeLMh1//xycAJ/ESuw9aJ9SEtlCZDYi2pBfe4JkisSoAtbOsBNAA==", "license": "MIT" }, "node_modules/@types/node-forge": { diff --git a/web/package.json b/web/package.json index f240e25..b5e64b2 100644 --- a/web/package.json +++ b/web/package.json @@ -8,7 +8,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.5.2", - "@types/node": "^16.18.119", + "@types/node": "^17.0.29", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "interface": "file:../interface", diff --git a/web/src/pages/game/GamePage.tsx b/web/src/pages/game/GamePage.tsx index 4ad8707..529308b 100644 --- a/web/src/pages/game/GamePage.tsx +++ b/web/src/pages/game/GamePage.tsx @@ -4,6 +4,7 @@ import DiceSet from "./components/DiceSet"; import "./GamePage.scss"; import { buildBoard, PieceId } from "interface"; import { DieViewProps } from "./types/DieViewProps"; +import { PlacePieceActionStack } from "./types/PlacePieceActionStack"; const GamePage = () => { const getRandomPieceId = () => { @@ -71,15 +72,19 @@ const GamePage = () => { return dice.concat(specialDice).find((die) => matcher(die)); }; - const [storedBoard, setStoredBoard] = useState(buildBoard()); const [board, setBoard] = useState(buildBoard()); const [id, setId] = useState(1); const refreshBoardRender = () => { setBoard(board); setId(id + 1); }; + + const [placePieceActionStack, setPlacePieceActionStack] = useState( + new PlacePieceActionStack(), + ); const resetBoard = () => { - setBoard(storedBoard); + placePieceActionStack.resetActions(board); + setBoard(board); modifyDieState( () => true, () => { @@ -90,7 +95,7 @@ const GamePage = () => { }; const commitBoard = () => { if (dice.some((die) => !die.isDisabled)) return; - setStoredBoard(board); + placePieceActionStack.commitActions(); setDice(getRandomDiceSet()); setSpecialDieUsedInRound(false); }; @@ -105,6 +110,8 @@ const GamePage = () => { setSpecialDieUsedInRound={setSpecialDieUsedInRound} refreshBoardRender={refreshBoardRender} board={board} + placePieceActionStack={placePieceActionStack} + setPlacePieceActionStack={setPlacePieceActionStack} />
boolean, ) => DieViewProps | undefined; setSpecialDieUsedInRound: React.Dispatch>; + placePieceActionHandler: (pieceId: PieceId, rotation: number) => void; } const BoardCell = (props: BoardCellProps) => { @@ -23,16 +24,14 @@ const BoardCell = (props: BoardCellProps) => { modifyDieState, fetchDie, setSpecialDieUsedInRound, + placePieceActionHandler, } = props; const [pieceRotationAngle, setPieceRotationAngle] = useState(0); const handleBoardCellClick = () => { const selectedDie = fetchDie((die) => die.isSelected); if (!selectedDie) return; try { - cell.placePiece( - selectedDie.pieceId, - selectedDie.rotation as 0 | 90 | 180 | 270, - ); + placePieceActionHandler(selectedDie.pieceId, selectedDie.rotation); } catch (error) { console.log(error); return; diff --git a/web/src/pages/game/components/GameBoard.tsx b/web/src/pages/game/components/GameBoard.tsx index 2ddfb81..94a94f2 100644 --- a/web/src/pages/game/components/GameBoard.tsx +++ b/web/src/pages/game/components/GameBoard.tsx @@ -2,6 +2,8 @@ import { Cell } from "interface"; import "./GameBoard.scss"; import BoardCell from "./BoardCell"; import { DieViewProps } from "../types/DieViewProps"; +import { PlacePieceActionStack } from "../types/PlacePieceActionStack"; +import { PlacePieceAction } from "../types/PlacePieceAction"; export interface GameBoardProps { modifyDieState: ( @@ -14,15 +16,31 @@ export interface GameBoardProps { setSpecialDieUsedInRound: React.Dispatch>; refreshBoardRender: () => void; board: Cell[][]; + placePieceActionStack: PlacePieceActionStack; + setPlacePieceActionStack: React.Dispatch< + React.SetStateAction + >; } const GameBoard = (props: GameBoardProps) => { - const { board } = props; + const { board, placePieceActionStack, setPlacePieceActionStack } = props; return (
- {board.flatMap((row) => - row.map((cell) => ), + {board.flatMap((row, rowIndex) => + row.map((cell, colIndex) => ( + { + placePieceActionStack.executeAction( + new PlacePieceAction(pieceId, rotation, rowIndex, colIndex), + board, + ); + setPlacePieceActionStack(placePieceActionStack); + }} + /> + )), )}
); diff --git a/web/src/pages/game/types/PlacePieceAction.ts b/web/src/pages/game/types/PlacePieceAction.ts new file mode 100644 index 0000000..6fe46d3 --- /dev/null +++ b/web/src/pages/game/types/PlacePieceAction.ts @@ -0,0 +1,32 @@ +import { Cell, PieceId } from "interface"; + +export class PlacePieceAction { + pieceId: PieceId; + rotation: number; + cell: { + row: number; + col: number; + }; + + constructor(pieceId: PieceId, rotation: number, row: number, col: number) { + this.pieceId = pieceId; + this.rotation = rotation; + this.cell = { + row: row, + col: col, + }; + } + + do(board: Cell[][]) { + const cell = board[this.cell.row][this.cell.col]; + cell.placePiece(this.pieceId, this.rotation as 0 | 90 | 180 | 270); + } + + undo(board: Cell[][]) { + const cell = board[this.cell.row][this.cell.col]; + if (!cell.placedPiece || cell.placedPiece.id !== this.pieceId) { + throw Error("Un-doing action error"); + } + cell.removePiece(); + } +} diff --git a/web/src/pages/game/types/PlacePieceActionStack.ts b/web/src/pages/game/types/PlacePieceActionStack.ts new file mode 100644 index 0000000..4a6841f --- /dev/null +++ b/web/src/pages/game/types/PlacePieceActionStack.ts @@ -0,0 +1,40 @@ +import { Cell } from "interface"; +import { PlacePieceAction } from "./PlacePieceAction"; + +export class PlacePieceActionStack { + readonly committedActions: PlacePieceAction[] = []; + inProgressActions: PlacePieceAction[] = []; + + executeAction(action: PlacePieceAction, board: Cell[][]) { + action.do(board); + this.inProgressActions.push(action); + } + + undoLastAction(board: Cell[][]) { + const lastAction = this.inProgressActions.pop(); + if (!lastAction) { + throw Error("No in progress action to undo"); + } + lastAction.undo(board); + } + + resetActions(board: Cell[][]) { + try { + while (true) { + this.undoLastAction(board); + } + } catch (error) { + if ( + !(error instanceof Error) || + error.message !== "No in progress action to undo" + ) { + throw error; + } + } + } + + commitActions() { + this.committedActions.push(...this.inProgressActions); + this.inProgressActions = []; + } +} -- 2.40.1 From 0b5684f2b9f9fea2185f8c44c954762590e9840d Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Thu, 5 Dec 2024 10:46:38 +0100 Subject: [PATCH 23/25] Fix commit and reset actions crossing pointers by creating an action stack (will be used to send data to backend) --- web/src/App.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 7b878b6..30a0cc5 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -27,7 +27,6 @@ const App = (props: AppProps) => { }, [renderedPage]); setupNextPageTransition(); - return (
{renderedPage === "LANDING" && } -- 2.40.1 From 09bd13f772c99d69b568128126c73d785a9e683b Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sun, 9 Feb 2025 15:24:43 +0100 Subject: [PATCH 24/25] Create page transition from lobby to in-game --- interface/index.ts | 1 + interface/server-events/StartRoundEvent.ts | 14 ++++++++++++++ web/src/App.tsx | 9 ++++++++- web/src/pages/lobby/LobbyPage.tsx | 5 +++-- 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 interface/server-events/StartRoundEvent.ts diff --git a/interface/index.ts b/interface/index.ts index 17a354e..cacd699 100644 --- a/interface/index.ts +++ b/interface/index.ts @@ -14,6 +14,7 @@ export * from "./types/PlacedPiece"; export * from "./BoardBuilder"; export * from "./server-events/ServerError"; export * from "./server-events/ServerEvent"; +export * from "./server-events/StartRoundEvent"; export * from "./server-events/UpdateLobbyEvent"; export * from "./client-events/ClientEvent"; export * from "./client-events/CreateLobbyEvent"; diff --git a/interface/server-events/StartRoundEvent.ts b/interface/server-events/StartRoundEvent.ts new file mode 100644 index 0000000..75179fc --- /dev/null +++ b/interface/server-events/StartRoundEvent.ts @@ -0,0 +1,14 @@ +import { Socket } from "socket.io-client"; +import { ServerEvent } from "./ServerEvent"; +import { PieceId } from "../constants/Pieces"; + +export type StartRoundEvent = { + pieceIds: PieceId[]; +}; + +export function attachHandlerToStartRoundEvent( + socket: Socket, + handler: (event: StartRoundEvent) => void, +): void { + socket.once(ServerEvent.START_ROUND, handler); +} diff --git a/web/src/App.tsx b/web/src/App.tsx index 30a0cc5..12ad8e7 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -3,7 +3,10 @@ import { Socket } from "socket.io-client"; import LandingPage from "./pages/landing/LandingPage"; import GamePage from "./pages/game/GamePage"; import LobbyPage from "./pages/lobby/LobbyPage"; -import { attachHandlerToUpdateLobbyEvent } from "interface"; +import { + attachHandlerToStartRoundEvent, + attachHandlerToUpdateLobbyEvent, +} from "interface"; export interface AppProps { socket: Socket; @@ -23,6 +26,10 @@ const App = (props: AppProps) => { setGameCode(event.gameCode); setRenderedPage("LOBBY"); }); + } else if (renderedPage === "LOBBY") { + attachHandlerToStartRoundEvent(socket, (event) => { + setRenderedPage("GAME"); + }); } }, [renderedPage]); diff --git a/web/src/pages/lobby/LobbyPage.tsx b/web/src/pages/lobby/LobbyPage.tsx index e92f168..a336d29 100644 --- a/web/src/pages/lobby/LobbyPage.tsx +++ b/web/src/pages/lobby/LobbyPage.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import "./LobbyPage.scss"; import { Socket } from "socket.io-client"; -import { attachHandlerToUpdateLobbyEvent } from "interface"; +import { attachHandlerToUpdateLobbyEvent, ClientEvent } from "interface"; export interface LobbyPageProps { initialPlayerNames: string[]; @@ -16,6 +16,7 @@ const LobbyPage = (props: LobbyPageProps) => { attachHandlerToUpdateLobbyEvent(socket, (event) => { setPlayerNames(event.playerNames); }); + const startGame = () => socket.emit(ClientEvent.START_GAME); return (
@@ -27,7 +28,7 @@ const LobbyPage = (props: LobbyPageProps) => {
{name}
))}
- +
Game code: {gameCode}
-- 2.40.1 From 10949f30df104e8afcec373be71f26a0794f5adc Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sun, 9 Feb 2025 15:45:07 +0100 Subject: [PATCH 25/25] Use server response to consume dice as defined by the backend --- interface/server-events/StartRoundEvent.ts | 12 +++++++++-- interface/server-events/UpdateLobbyEvent.ts | 12 +++++++++-- web/src/App.tsx | 9 ++++++-- web/src/pages/game/GamePage.tsx | 23 ++++++++++++--------- 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/interface/server-events/StartRoundEvent.ts b/interface/server-events/StartRoundEvent.ts index 75179fc..7b870ec 100644 --- a/interface/server-events/StartRoundEvent.ts +++ b/interface/server-events/StartRoundEvent.ts @@ -1,4 +1,5 @@ -import { Socket } from "socket.io-client"; +import { Socket as ServerSocket } from "socket.io"; +import { Socket as ClientSocket } from "socket.io-client"; import { ServerEvent } from "./ServerEvent"; import { PieceId } from "../constants/Pieces"; @@ -6,8 +7,15 @@ export type StartRoundEvent = { pieceIds: PieceId[]; }; +export const emitStartRoundEvent = ( + socket: ServerSocket, + payload: StartRoundEvent, +) => { + socket.emit(ServerEvent.START_ROUND, payload); +}; + export function attachHandlerToStartRoundEvent( - socket: Socket, + socket: ClientSocket, handler: (event: StartRoundEvent) => void, ): void { socket.once(ServerEvent.START_ROUND, handler); diff --git a/interface/server-events/UpdateLobbyEvent.ts b/interface/server-events/UpdateLobbyEvent.ts index 2f0881d..9cbbb79 100644 --- a/interface/server-events/UpdateLobbyEvent.ts +++ b/interface/server-events/UpdateLobbyEvent.ts @@ -1,4 +1,5 @@ -import { Socket } from "socket.io-client"; +import { Socket as ServerSocket } from "socket.io"; +import { Socket as ClientSocket } from "socket.io-client"; import { ServerEvent } from "./ServerEvent"; export type UpdateLobbyEvent = { @@ -6,8 +7,15 @@ export type UpdateLobbyEvent = { gameCode: string; }; +export const emitUpdateLobbyEvent = ( + socket: ServerSocket, + payload: UpdateLobbyEvent, +) => { + socket.emit(ServerEvent.LOBBY_UPDATE, payload); +}; + export function attachHandlerToUpdateLobbyEvent( - socket: Socket, + socket: ClientSocket, handler: (event: UpdateLobbyEvent) => void, ): void { socket.once(ServerEvent.LOBBY_UPDATE, handler); diff --git a/web/src/App.tsx b/web/src/App.tsx index 12ad8e7..93d4015 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -6,6 +6,7 @@ import LobbyPage from "./pages/lobby/LobbyPage"; import { attachHandlerToStartRoundEvent, attachHandlerToUpdateLobbyEvent, + PieceId, } from "interface"; export interface AppProps { @@ -16,8 +17,9 @@ const App = (props: AppProps) => { const { socket } = props; const [renderedPage, setRenderedPage] = useState("LANDING"); - const [initialPlayerNames, setInitialPlayerNames] = useState([""]); + const [initialPlayerNames, setInitialPlayerNames] = useState([] as string[]); const [gameCode, setGameCode] = useState(""); + const [initialPieceIds, setInitialPieceIds] = useState([] as PieceId[]); const setupNextPageTransition = useCallback(() => { if (renderedPage === "LANDING") { @@ -28,6 +30,7 @@ const App = (props: AppProps) => { }); } else if (renderedPage === "LOBBY") { attachHandlerToStartRoundEvent(socket, (event) => { + setInitialPieceIds(event.pieceIds); setRenderedPage("GAME"); }); } @@ -44,7 +47,9 @@ const App = (props: AppProps) => { gameCode={gameCode} /> )} - {renderedPage === "GAME" && } + {renderedPage === "GAME" && ( + + )}
); }; diff --git a/web/src/pages/game/GamePage.tsx b/web/src/pages/game/GamePage.tsx index 529308b..c66ee9e 100644 --- a/web/src/pages/game/GamePage.tsx +++ b/web/src/pages/game/GamePage.tsx @@ -6,16 +6,19 @@ import { buildBoard, PieceId } from "interface"; import { DieViewProps } from "./types/DieViewProps"; import { PlacePieceActionStack } from "./types/PlacePieceActionStack"; -const GamePage = () => { - const getRandomPieceId = () => { - const randomId = Math.floor(Math.random() * Object.keys(PieceId).length); - return Object.values(PieceId)[randomId]; - }; +export interface GamePageProps { + initialPieceIds: PieceId[]; +} - const getRandomDiceSet: () => DieViewProps[] = () => - [1, 2, 3, 4].map(() => { +const GamePage = (props: GamePageProps) => { + const { initialPieceIds } = props; + + const [pieceIds] = useState(initialPieceIds); + + const getDiceSet: () => DieViewProps[] = () => + pieceIds.map((pieceId) => { return { - pieceId: getRandomPieceId(), + pieceId: pieceId, isSelected: false, isDisabled: false, isSpecial: false, @@ -23,7 +26,7 @@ const GamePage = () => { }; }); - const [dice, setDice] = useState(getRandomDiceSet()); + const [dice, setDice] = useState(getDiceSet()); const [specialDice, setSpecialDice] = useState( [ PieceId.P03, @@ -96,7 +99,7 @@ const GamePage = () => { const commitBoard = () => { if (dice.some((die) => !die.isDisabled)) return; placePieceActionStack.commitActions(); - setDice(getRandomDiceSet()); + setDice(getDiceSet()); setSpecialDieUsedInRound(false); }; -- 2.40.1