commit b6b99c3ef44efaceb6430c82df937c9be3cedd63 Author: Aleksandr Zaitsev Date: Wed Jul 3 22:16:37 2024 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..daf4db9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/ +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/README.md b/README.md new file mode 100644 index 0000000..f04ed45 --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# wilg-game + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Compile and Minify for Production + +```sh +npm run build +``` diff --git a/index.html b/index.html new file mode 100644 index 0000000..3b9eb57 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + Game + + +
+ + + diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..5a1f2d2 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..3a84f6f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1372 @@ +{ + "name": "wilg-game", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "wilg-game", + "version": "0.0.0", + "dependencies": { + "axios": "^1.6.8", + "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", + "uuid": "^9.0.1", + "vue": "^3.4.21", + "vue-i18n": "^9.12.1", + "vue-router": "^4.3.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.4", + "autoprefixer": "^10.4.19", + "postcss": "^8.4.38", + "vite": "^5.2.8" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@intlify/core-base": { + "version": "9.12.1", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.12.1.tgz", + "integrity": "sha512-l7djJEmXLAR44PdtKDEBev/TN9tREQz967/+jvN3WtICqFoy2Cz8kPtjDfvZctqPNzOonp+ESsDCUm+rjHsmdA==", + "dependencies": { + "@intlify/message-compiler": "9.12.1", + "@intlify/shared": "9.12.1" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.12.1", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.12.1.tgz", + "integrity": "sha512-6QrMGdqKUJSkctyg56nvE+h86tjQZTjYFEfx3ghQAXKPXUd1v5josZXrwnSbIEWWeAentlwtB5qW1FE5r2S8AQ==", + "dependencies": { + "@intlify/shared": "9.12.1", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "9.12.1", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.12.1.tgz", + "integrity": "sha512-xAAAxaMS7yUCkwXwqUVQmGCPbXSm6oHqMzcqr2IrxJQmC0DmuqoaW0yBeWyd/pG03PPXqGtWhJLnefsiVElzAQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz", + "integrity": "sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz", + "integrity": "sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz", + "integrity": "sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz", + "integrity": "sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz", + "integrity": "sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz", + "integrity": "sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz", + "integrity": "sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz", + "integrity": "sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==", + "cpu": [ + "ppc64le" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz", + "integrity": "sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz", + "integrity": "sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz", + "integrity": "sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz", + "integrity": "sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz", + "integrity": "sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz", + "integrity": "sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz", + "integrity": "sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", + "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.21.tgz", + "integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==", + "dependencies": { + "@babel/parser": "^7.23.9", + "@vue/shared": "3.4.21", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz", + "integrity": "sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==", + "dependencies": { + "@vue/compiler-core": "3.4.21", + "@vue/shared": "3.4.21" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz", + "integrity": "sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==", + "dependencies": { + "@babel/parser": "^7.23.9", + "@vue/compiler-core": "3.4.21", + "@vue/compiler-dom": "3.4.21", + "@vue/compiler-ssr": "3.4.21", + "@vue/shared": "3.4.21", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.7", + "postcss": "^8.4.35", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz", + "integrity": "sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==", + "dependencies": { + "@vue/compiler-dom": "3.4.21", + "@vue/shared": "3.4.21" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz", + "integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==" + }, + "node_modules/@vue/reactivity": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.21.tgz", + "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==", + "dependencies": { + "@vue/shared": "3.4.21" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.21.tgz", + "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==", + "dependencies": { + "@vue/reactivity": "3.4.21", + "@vue/shared": "3.4.21" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz", + "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==", + "dependencies": { + "@vue/runtime-core": "3.4.21", + "@vue/shared": "3.4.21", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.21.tgz", + "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==", + "dependencies": { + "@vue/compiler-ssr": "3.4.21", + "@vue/shared": "3.4.21" + }, + "peerDependencies": { + "vue": "3.4.21" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz", + "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001608", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001608.tgz", + "integrity": "sha512-cjUJTQkk9fQlJR2s4HMuPMvTiRggl0rAVMtthQuyOlDWuqHXqN8azLq+pi8B2TjwKJ32diHjUqRIKeFX4z1FoA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.733", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.733.tgz", + "integrity": "sha512-gUI9nhI2iBGF0OaYYLKOaOtliFMl+Bt1rY7VmEjwxOxqoYLub/D9xmduPEhbw2imE6gYkJKhIE5it+KE2ulVxQ==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.9.tgz", + "integrity": "sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/pinia": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz", + "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==", + "dependencies": { + "@vue/devtools-api": "^6.5.0", + "vue-demi": ">=0.14.5" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.3.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia-plugin-persistedstate": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz", + "integrity": "sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==", + "peerDependencies": { + "pinia": "^2.0.0" + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/rollup": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.1.tgz", + "integrity": "sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.14.1", + "@rollup/rollup-android-arm64": "4.14.1", + "@rollup/rollup-darwin-arm64": "4.14.1", + "@rollup/rollup-darwin-x64": "4.14.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.14.1", + "@rollup/rollup-linux-arm64-gnu": "4.14.1", + "@rollup/rollup-linux-arm64-musl": "4.14.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.14.1", + "@rollup/rollup-linux-riscv64-gnu": "4.14.1", + "@rollup/rollup-linux-s390x-gnu": "4.14.1", + "@rollup/rollup-linux-x64-gnu": "4.14.1", + "@rollup/rollup-linux-x64-musl": "4.14.1", + "@rollup/rollup-win32-arm64-msvc": "4.14.1", + "@rollup/rollup-win32-ia32-msvc": "4.14.1", + "@rollup/rollup-win32-x64-msvc": "4.14.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vite": { + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz", + "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==", + "dev": true, + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz", + "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==", + "dependencies": { + "@vue/compiler-dom": "3.4.21", + "@vue/compiler-sfc": "3.4.21", + "@vue/runtime-dom": "3.4.21", + "@vue/server-renderer": "3.4.21", + "@vue/shared": "3.4.21" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-i18n": { + "version": "9.12.1", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.12.1.tgz", + "integrity": "sha512-cqkBt10YzxF3tNGA7/95VMfFdk8nEoguzB7K7R9rldiSnHyWeokq6GOWMThfK/siTr2lLfM9nqolD/er//t4Iw==", + "dependencies": { + "@intlify/core-base": "9.12.1", + "@intlify/shared": "9.12.1", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz", + "integrity": "sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ==", + "dependencies": { + "@vue/devtools-api": "^6.5.1" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6606072 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "wilg-game", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "axios": "^1.6.8", + "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", + "uuid": "^9.0.1", + "vue": "^3.4.21", + "vue-i18n": "^9.12.1", + "vue-router": "^4.3.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.4", + "autoprefixer": "^10.4.19", + "postcss": "^8.4.38", + "vite": "^5.2.8" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..b6dc034 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,5 @@ +export default { + plugins: { + autoprefixer: {}, + }, +} diff --git a/public/audio/fish.wav b/public/audio/fish.wav new file mode 100644 index 0000000..1027951 Binary files /dev/null and b/public/audio/fish.wav differ diff --git a/public/audio/move.wav b/public/audio/move.wav new file mode 100644 index 0000000..4afba2a Binary files /dev/null and b/public/audio/move.wav differ diff --git a/public/back/32.png b/public/back/32.png new file mode 100644 index 0000000..67589f2 Binary files /dev/null and b/public/back/32.png differ diff --git a/public/back/33.png b/public/back/33.png new file mode 100644 index 0000000..e64b512 Binary files /dev/null and b/public/back/33.png differ diff --git a/public/back/40.png b/public/back/40.png new file mode 100644 index 0000000..1d2d79c Binary files /dev/null and b/public/back/40.png differ diff --git a/public/back/41.png b/public/back/41.png new file mode 100644 index 0000000..1878544 Binary files /dev/null and b/public/back/41.png differ diff --git a/public/back/42.png b/public/back/42.png new file mode 100644 index 0000000..6b85cb8 Binary files /dev/null and b/public/back/42.png differ diff --git a/public/back/45.png b/public/back/45.png new file mode 100644 index 0000000..dc1dd8b Binary files /dev/null and b/public/back/45.png differ diff --git a/public/back/47.png b/public/back/47.png new file mode 100644 index 0000000..f9b8149 Binary files /dev/null and b/public/back/47.png differ diff --git a/public/back/50.png b/public/back/50.png new file mode 100644 index 0000000..4d98aef Binary files /dev/null and b/public/back/50.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/images/grass/1.png b/public/images/grass/1.png new file mode 100644 index 0000000..4e534d5 Binary files /dev/null and b/public/images/grass/1.png differ diff --git a/public/images/grass/2.png b/public/images/grass/2.png new file mode 100644 index 0000000..5208ebc Binary files /dev/null and b/public/images/grass/2.png differ diff --git a/public/images/grass/3.png b/public/images/grass/3.png new file mode 100644 index 0000000..64ee699 Binary files /dev/null and b/public/images/grass/3.png differ diff --git a/public/images/header.png b/public/images/header.png new file mode 100644 index 0000000..09fee01 Binary files /dev/null and b/public/images/header.png differ diff --git a/public/images/header_border.png b/public/images/header_border.png new file mode 100644 index 0000000..6ddf1a2 Binary files /dev/null and b/public/images/header_border.png differ diff --git a/public/images/logo.png b/public/images/logo.png new file mode 100644 index 0000000..9e8c1fe Binary files /dev/null and b/public/images/logo.png differ diff --git a/public/images/margin.png b/public/images/margin.png new file mode 100644 index 0000000..c025a87 Binary files /dev/null and b/public/images/margin.png differ diff --git a/public/images/shore.png b/public/images/shore.png new file mode 100644 index 0000000..8114e23 Binary files /dev/null and b/public/images/shore.png differ diff --git a/public/images/source/cloud/cloud_shape1_1.png b/public/images/source/cloud/cloud_shape1_1.png new file mode 100644 index 0000000..8dbaec3 Binary files /dev/null and b/public/images/source/cloud/cloud_shape1_1.png differ diff --git a/public/images/source/cloud/cloud_shape1_2.png b/public/images/source/cloud/cloud_shape1_2.png new file mode 100644 index 0000000..a6abd6d Binary files /dev/null and b/public/images/source/cloud/cloud_shape1_2.png differ diff --git a/public/images/source/cloud/cloud_shape1_3.png b/public/images/source/cloud/cloud_shape1_3.png new file mode 100644 index 0000000..975955c Binary files /dev/null and b/public/images/source/cloud/cloud_shape1_3.png differ diff --git a/public/images/source/cloud/cloud_shape1_4.png b/public/images/source/cloud/cloud_shape1_4.png new file mode 100644 index 0000000..5450853 Binary files /dev/null and b/public/images/source/cloud/cloud_shape1_4.png differ diff --git a/public/images/source/cloud/cloud_shape1_5.png b/public/images/source/cloud/cloud_shape1_5.png new file mode 100644 index 0000000..468ce67 Binary files /dev/null and b/public/images/source/cloud/cloud_shape1_5.png differ diff --git a/public/images/source/cloud/cloud_shape2_1.png b/public/images/source/cloud/cloud_shape2_1.png new file mode 100644 index 0000000..6520266 Binary files /dev/null and b/public/images/source/cloud/cloud_shape2_1.png differ diff --git a/public/images/source/cloud/cloud_shape2_2.png b/public/images/source/cloud/cloud_shape2_2.png new file mode 100644 index 0000000..2a7ba56 Binary files /dev/null and b/public/images/source/cloud/cloud_shape2_2.png differ diff --git a/public/images/source/cloud/cloud_shape2_3.png b/public/images/source/cloud/cloud_shape2_3.png new file mode 100644 index 0000000..3cecbd7 Binary files /dev/null and b/public/images/source/cloud/cloud_shape2_3.png differ diff --git a/public/images/source/cloud/cloud_shape2_4.png b/public/images/source/cloud/cloud_shape2_4.png new file mode 100644 index 0000000..642e3cb Binary files /dev/null and b/public/images/source/cloud/cloud_shape2_4.png differ diff --git a/public/images/source/cloud/cloud_shape2_5.png b/public/images/source/cloud/cloud_shape2_5.png new file mode 100644 index 0000000..406288b Binary files /dev/null and b/public/images/source/cloud/cloud_shape2_5.png differ diff --git a/public/images/source/cloud/cloud_shape3_1.png b/public/images/source/cloud/cloud_shape3_1.png new file mode 100644 index 0000000..90825a3 Binary files /dev/null and b/public/images/source/cloud/cloud_shape3_1.png differ diff --git a/public/images/source/cloud/cloud_shape3_2.png b/public/images/source/cloud/cloud_shape3_2.png new file mode 100644 index 0000000..7715e61 Binary files /dev/null and b/public/images/source/cloud/cloud_shape3_2.png differ diff --git a/public/images/source/cloud/cloud_shape3_3.png b/public/images/source/cloud/cloud_shape3_3.png new file mode 100644 index 0000000..d8b4cdd Binary files /dev/null and b/public/images/source/cloud/cloud_shape3_3.png differ diff --git a/public/images/source/cloud/cloud_shape3_4.png b/public/images/source/cloud/cloud_shape3_4.png new file mode 100644 index 0000000..f674083 Binary files /dev/null and b/public/images/source/cloud/cloud_shape3_4.png differ diff --git a/public/images/source/cloud/cloud_shape3_5.png b/public/images/source/cloud/cloud_shape3_5.png new file mode 100644 index 0000000..470c874 Binary files /dev/null and b/public/images/source/cloud/cloud_shape3_5.png differ diff --git a/public/images/source/cloud/cloud_shape4_1.png b/public/images/source/cloud/cloud_shape4_1.png new file mode 100644 index 0000000..86376bb Binary files /dev/null and b/public/images/source/cloud/cloud_shape4_1.png differ diff --git a/public/images/source/cloud/cloud_shape4_2.png b/public/images/source/cloud/cloud_shape4_2.png new file mode 100644 index 0000000..9d2f25d Binary files /dev/null and b/public/images/source/cloud/cloud_shape4_2.png differ diff --git a/public/images/source/cloud/cloud_shape4_3.png b/public/images/source/cloud/cloud_shape4_3.png new file mode 100644 index 0000000..bb77afb Binary files /dev/null and b/public/images/source/cloud/cloud_shape4_3.png differ diff --git a/public/images/source/cloud/cloud_shape4_4.png b/public/images/source/cloud/cloud_shape4_4.png new file mode 100644 index 0000000..0aa8145 Binary files /dev/null and b/public/images/source/cloud/cloud_shape4_4.png differ diff --git a/public/images/source/cloud/cloud_shape4_5.png b/public/images/source/cloud/cloud_shape4_5.png new file mode 100644 index 0000000..edf8846 Binary files /dev/null and b/public/images/source/cloud/cloud_shape4_5.png differ diff --git a/public/images/source/cloud/cloud_shape5_1.png b/public/images/source/cloud/cloud_shape5_1.png new file mode 100644 index 0000000..2bbc7c9 Binary files /dev/null and b/public/images/source/cloud/cloud_shape5_1.png differ diff --git a/public/images/source/cloud/cloud_shape5_2.png b/public/images/source/cloud/cloud_shape5_2.png new file mode 100644 index 0000000..651dde3 Binary files /dev/null and b/public/images/source/cloud/cloud_shape5_2.png differ diff --git a/public/images/source/cloud/cloud_shape5_3.png b/public/images/source/cloud/cloud_shape5_3.png new file mode 100644 index 0000000..b01553d Binary files /dev/null and b/public/images/source/cloud/cloud_shape5_3.png differ diff --git a/public/images/source/cloud/cloud_shape5_4.png b/public/images/source/cloud/cloud_shape5_4.png new file mode 100644 index 0000000..f36de1b Binary files /dev/null and b/public/images/source/cloud/cloud_shape5_4.png differ diff --git a/public/images/source/cloud/cloud_shape5_5.png b/public/images/source/cloud/cloud_shape5_5.png new file mode 100644 index 0000000..8403d95 Binary files /dev/null and b/public/images/source/cloud/cloud_shape5_5.png differ diff --git a/public/images/source/cloud/cloud_shape6_1.png b/public/images/source/cloud/cloud_shape6_1.png new file mode 100644 index 0000000..e179810 Binary files /dev/null and b/public/images/source/cloud/cloud_shape6_1.png differ diff --git a/public/images/source/cloud/cloud_shape6_2.png b/public/images/source/cloud/cloud_shape6_2.png new file mode 100644 index 0000000..83a6967 Binary files /dev/null and b/public/images/source/cloud/cloud_shape6_2.png differ diff --git a/public/images/source/cloud/cloud_shape6_3.png b/public/images/source/cloud/cloud_shape6_3.png new file mode 100644 index 0000000..bfabde1 Binary files /dev/null and b/public/images/source/cloud/cloud_shape6_3.png differ diff --git a/public/images/source/cloud/cloud_shape6_4.png b/public/images/source/cloud/cloud_shape6_4.png new file mode 100644 index 0000000..0ac6876 Binary files /dev/null and b/public/images/source/cloud/cloud_shape6_4.png differ diff --git a/public/images/source/cloud/cloud_shape6_5.png b/public/images/source/cloud/cloud_shape6_5.png new file mode 100644 index 0000000..8a0ed67 Binary files /dev/null and b/public/images/source/cloud/cloud_shape6_5.png differ diff --git a/public/images/source/fish/1.png b/public/images/source/fish/1.png new file mode 100644 index 0000000..e7a08f6 Binary files /dev/null and b/public/images/source/fish/1.png differ diff --git a/public/images/source/fish/10.png b/public/images/source/fish/10.png new file mode 100644 index 0000000..d409053 Binary files /dev/null and b/public/images/source/fish/10.png differ diff --git a/public/images/source/fish/11.png b/public/images/source/fish/11.png new file mode 100644 index 0000000..630dec8 Binary files /dev/null and b/public/images/source/fish/11.png differ diff --git a/public/images/source/fish/12.png b/public/images/source/fish/12.png new file mode 100644 index 0000000..ddb4e62 Binary files /dev/null and b/public/images/source/fish/12.png differ diff --git a/public/images/source/fish/13.png b/public/images/source/fish/13.png new file mode 100644 index 0000000..c925047 Binary files /dev/null and b/public/images/source/fish/13.png differ diff --git a/public/images/source/fish/14.png b/public/images/source/fish/14.png new file mode 100644 index 0000000..399e53c Binary files /dev/null and b/public/images/source/fish/14.png differ diff --git a/public/images/source/fish/15.png b/public/images/source/fish/15.png new file mode 100644 index 0000000..8c67073 Binary files /dev/null and b/public/images/source/fish/15.png differ diff --git a/public/images/source/fish/16.png b/public/images/source/fish/16.png new file mode 100644 index 0000000..95d9f3d Binary files /dev/null and b/public/images/source/fish/16.png differ diff --git a/public/images/source/fish/17.png b/public/images/source/fish/17.png new file mode 100644 index 0000000..f669be5 Binary files /dev/null and b/public/images/source/fish/17.png differ diff --git a/public/images/source/fish/18.png b/public/images/source/fish/18.png new file mode 100644 index 0000000..53118c9 Binary files /dev/null and b/public/images/source/fish/18.png differ diff --git a/public/images/source/fish/19.png b/public/images/source/fish/19.png new file mode 100644 index 0000000..48fee75 Binary files /dev/null and b/public/images/source/fish/19.png differ diff --git a/public/images/source/fish/2.png b/public/images/source/fish/2.png new file mode 100644 index 0000000..dac93ce Binary files /dev/null and b/public/images/source/fish/2.png differ diff --git a/public/images/source/fish/20.png b/public/images/source/fish/20.png new file mode 100644 index 0000000..8cf6053 Binary files /dev/null and b/public/images/source/fish/20.png differ diff --git a/public/images/source/fish/21.png b/public/images/source/fish/21.png new file mode 100644 index 0000000..f8528c6 Binary files /dev/null and b/public/images/source/fish/21.png differ diff --git a/public/images/source/fish/22.png b/public/images/source/fish/22.png new file mode 100644 index 0000000..06c84d3 Binary files /dev/null and b/public/images/source/fish/22.png differ diff --git a/public/images/source/fish/23.png b/public/images/source/fish/23.png new file mode 100644 index 0000000..78fdd11 Binary files /dev/null and b/public/images/source/fish/23.png differ diff --git a/public/images/source/fish/4.png b/public/images/source/fish/4.png new file mode 100644 index 0000000..bae970a Binary files /dev/null and b/public/images/source/fish/4.png differ diff --git a/public/images/source/fish/5.png b/public/images/source/fish/5.png new file mode 100644 index 0000000..9bd3afa Binary files /dev/null and b/public/images/source/fish/5.png differ diff --git a/public/images/source/fish/6.png b/public/images/source/fish/6.png new file mode 100644 index 0000000..31ad257 Binary files /dev/null and b/public/images/source/fish/6.png differ diff --git a/public/images/source/fish/7.png b/public/images/source/fish/7.png new file mode 100644 index 0000000..8aab270 Binary files /dev/null and b/public/images/source/fish/7.png differ diff --git a/public/images/source/fish/8.png b/public/images/source/fish/8.png new file mode 100644 index 0000000..b7966e2 Binary files /dev/null and b/public/images/source/fish/8.png differ diff --git a/public/images/source/fish/9.png b/public/images/source/fish/9.png new file mode 100644 index 0000000..e69c1f0 Binary files /dev/null and b/public/images/source/fish/9.png differ diff --git a/public/images/source/sprites.xcf b/public/images/source/sprites.xcf new file mode 100644 index 0000000..7cfd0dd Binary files /dev/null and b/public/images/source/sprites.xcf differ diff --git a/public/images/sprites.png b/public/images/sprites.png new file mode 100644 index 0000000..03471c6 Binary files /dev/null and b/public/images/sprites.png differ diff --git a/public/images/water/1.png b/public/images/water/1.png new file mode 100644 index 0000000..1d4e143 Binary files /dev/null and b/public/images/water/1.png differ diff --git a/public/images/water/2.png b/public/images/water/2.png new file mode 100644 index 0000000..b0e5ef8 Binary files /dev/null and b/public/images/water/2.png differ diff --git a/public/images/water/3.png b/public/images/water/3.png new file mode 100644 index 0000000..6024e4f Binary files /dev/null and b/public/images/water/3.png differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..b1c7128 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/src/assets/animation.css b/src/assets/animation.css new file mode 100644 index 0000000..fed01a2 --- /dev/null +++ b/src/assets/animation.css @@ -0,0 +1,61 @@ +@keyframes water { + 0% { + background-image: url('/public/images/water/1.png'); + } + + 25% { + background-image: url('/public/images/water/2.png'); + } + + 50% { + background-image: url('/public/images/water/3.png'); + } + + 75% { + background-image: url('/public/images/water/2.png'); + } +} + +@keyframes empty { + 0% { + transform: scale(0); + opacity: 0; + } + + 100% { + transform: scale(1); + opacity: 0.8; + } +} + +@keyframes caught { + 0% { + -webkit-transform: scale(0) rotate(360deg); + opacity: 0; + } + + 100% { + -webkit-transform: scale(1) rotate(-360deg); + opacity: 1; + } +} + +@keyframes hit { + 0% { + background-color: rgba(0, 102, 143, 1); + border-radius: 50%; + height: 30%; + width: 30%; + } + + 100% { + height: 100%; + width: 100%; + background-color: transparent; + } +} + + +.lake-cell { + animation: water 2s infinite; +} \ No newline at end of file diff --git a/src/assets/fonts/ShantellSans-Italic-VariableFont_BNCE,INFM,SPAC,wght.ttf b/src/assets/fonts/ShantellSans-Italic-VariableFont_BNCE,INFM,SPAC,wght.ttf new file mode 100644 index 0000000..d97ef47 Binary files /dev/null and b/src/assets/fonts/ShantellSans-Italic-VariableFont_BNCE,INFM,SPAC,wght.ttf differ diff --git a/src/assets/fonts/ShantellSans-VariableFont_BNCE,INFM,SPAC,wght.ttf b/src/assets/fonts/ShantellSans-VariableFont_BNCE,INFM,SPAC,wght.ttf new file mode 100644 index 0000000..ce889ae Binary files /dev/null and b/src/assets/fonts/ShantellSans-VariableFont_BNCE,INFM,SPAC,wght.ttf differ diff --git a/src/assets/item.css b/src/assets/item.css new file mode 100644 index 0000000..25fa754 --- /dev/null +++ b/src/assets/item.css @@ -0,0 +1,106 @@ +/* FISH */ +.lobby { + [class*="fish-"]::after { + opacity: 1; + } + .margin::after { + opacity: 0.2; + } +} +[class*="fish-"]::after, .margin::after, .empty-empty::after { + content: " "; + position: absolute; + height: 48px; + width: 48px; + scale: 0.9; + opacity: 0.2; + background-repeat: no-repeat; + background-size: 80%; + background-position: center; + +} +.hit[class*="fish-"]::after { + animation: caught 0.5s; + opacity: 1; +} +.hit::before { + content: " "; + position: absolute; + animation: hit 0.5s; +} +.fish-1::after { + background: url('/public/images/sprites.png') 0 0; +} +.fish-2::after { + background: url('/public/images/sprites.png') -48px 0; +} +.fish-3::after { + background: url('/public/images/sprites.png') -96px 0; +} +.fish-4::after { + background: url('/public/images/sprites.png') -144px 0; +} +.fish-5::after { + background: url('/public/images/sprites.png') -192px 0; +} +.fish-6::after { + background: url('/public/images/sprites.png') -240px 0; +} +.fish-7::after { + background: url('/public/images/sprites.png') -288px 0; +} +.fish-8::after { + background: url('/public/images/sprites.png') -336px 0; +} +.fish-9::after { + background: url('/public/images/sprites.png') -384px 0; +} +.fish-10::after { + background: url('/public/images/sprites.png') -432px 0; +} +.fish-11::after { + background: url('/public/images/sprites.png') 0 -48px; +} +.fish-12::after { + background: url('/public/images/sprites.png') -48px -48px; +} +.fish-13::after { + background: url('/public/images/sprites.png') -96px -48px; +} +.fish-14::after { + background: url('/public/images/sprites.png') -144px -48px; +} +.fish-15::after { + background: url('/public/images/sprites.png') -192px -48px; +} +.fish-16::after { + background: url('/public/images/sprites.png') -240px -48px; +} +.fish-17::after { + background: url('/public/images/sprites.png') -288px -48px; +} +.fish-18::after { + background: url('/public/images/sprites.png') -336px -48px; +} +.fish-19::after { + background: url('/public/images/sprites.png') -384px -48px; +} +.fish-20::after { + background: url('/public/images/sprites.png') -432px -48px; +} +.fish-21::after { + background: url('/public/images/sprites.png') 0 -96px; +} +.fish-22::after { + background: url('/public/images/sprites.png') -48px -96px; +} + +.margin::after{ + background: url('/public/images/sprites.png') -432px -432px; + opacity: 0.2; +} +.empty-empty::after { + background: url('/public/images/sprites.png') -432px -432px; + opacity: 0.8; + animation: empty 0.5s; +} \ No newline at end of file diff --git a/src/assets/main.css b/src/assets/main.css new file mode 100644 index 0000000..ab9b148 --- /dev/null +++ b/src/assets/main.css @@ -0,0 +1,242 @@ +@import url('./animation.css'); +@import url('./item.css'); + + +:root { + --cloud-color: rgba(255, 255, 255); + --shadow-color: rgba(0, 0, 0); + --water-color: rgba(111, 181, 213); + --water-deep-color: rgba(0, 74, 230); + --water-deep-border-color: rgba(0, 74, 230, 0.2); + --wood-color: rgba(147, 117, 96); +} + +@font-face { + font-family: 'ShantellSansItalic'; + src: url('./fonts/ShantellSans-Italic-VariableFont_BNCE,INFM,SPAC,wght.ttf') format("truetype-variations"); + font-weight: 300 800; +} + +@font-face { + font-family: 'ShantellSans'; + src: url('./fonts/ShantellSans-VariableFont_BNCE,INFM,SPAC,wght.ttf') format("truetype-variations"); + font-weight: 300 800; +} + +html, body, #app { + height: 100%; + width: 100%; + overscroll-behavior: none; + font-family: 'ShantellSans'; + font-weight: 400; + user-select: none; + overflow: hidden; +} +body { + background: url('/public/images/grass/1.png') 48px 48px, + url('/public/images/grass/2.png') 48px 48px, + url('/public/images/grass/3.png') 48px 48px; +} + +h1 { + font-size: xx-large; + font-weight: 600; + text-align: center; + color: var(--cloud-color); + text-shadow: .5rem .5rem 1rem var(--shadow-color); + margin-bottom: 1rem; +} +h2 { + font-size: xx-large; + font-weight: 600; + text-align: center; + color: var(--cloud-color); + text-shadow: .5rem .5rem 1rem var(--shadow-color); + margin-bottom: 2rem; +} +button { + background-color: var(--wood-color); + font-size: 1.5rem; + color: var(--cloud-color); + padding: 0.1rem 1rem; + margin-bottom: 2rem; +} + +.button-lobby { + margin-bottom: 0; + display: block; + margin-left: auto; + margin-right: auto; + border-radius: 0.5rem; + } +.button-lobby + .button-lobby { + margin-top: 0.7rem; +} + +.game, .lobby { + display: grid; + justify-items: center; + grid-template-columns: 100%; + grid-template-rows: 100px auto; + grid-auto-rows: 0; + height: calc(100% - 120px); + width: 100%; + overflow: hidden; +} +.player-view, .opponent-view { width: 100%; + height: 100%; + overflow: hidden; + background-color: var(--water-color); +} +.lake-border { + position: relative; + overflow: hidden; + max-width: calc(16px + 10 * 50px); + width: 100%; + max-height: calc(25px + 10 * 50px); + height: 100%; + border: 18px solid transparent; + border-image: url('/public/images/shore.png') 18 / 18px repeat; +} +.lake { + display: flex; + flex-direction: row; + flex-wrap: wrap; + width: fit-content; + height: fit-content; + justify-content: center; + background-color: var(--water-color); +} +.lake-title { + text-align: center; +} +.lake-row { + display: flex; + flex-direction: row; +} +.lake-cell { + display: flex; + height: 48px; + width: 48px; + cursor: pointer; + background-image: url('/public/images/water/1.png'); + align-items: center; + justify-content: center; + padding: 4px; + position: relative; + color: rgba(0, 102, 143, 0.3); +} +.lake-row + .lake-row { + border-top: 1px var(--water-deep-border-color) solid; +} +.lake-cell + .lake-cell { + border-left: 1px var(--water-deep-border-color) solid; +} + + +.hide { + height: 0; + animation: hide 2s; +} + +.player-view.active { + animation: active 2s; +} +.player-view.hide { + height: 0; + animation: hide 2s; +} + +.opponent-view.active { + animation: active-opponent 2s; +} +.opponent-view.hide { + height: 0; + animation: hide-opponent 2s; +} + + + + +@keyframes hide { + 0% { + max-width: calc(16px + 10 * 50px); + width: 100%; + max-height: calc(25px + 10 * 50px); + height: 100%; + } + 50% { + + height: 0; + } + 100% { + + height: 0; + + } +} + +@keyframes active { + 0% { + + height: 0; + + } + 50% { + max-width: calc(16px + 10 * 50px); + width: 100%; + max-height: calc(25px + 10 * 50px); + height: 100%; + + } + 100% { + max-width: calc(16px + 10 * 50px); + width: 100%; + max-height: calc(25px + 10 * 50px); + height: 100%; + + } +} + + + +@keyframes hide-opponent { + 0% { + /* border-top: 2rem #fff solid;*/ + max-width: calc(16px + 10 * 50px); + width: 100%; + max-height: calc(25px + 10 * 50px); + height: 100%; + } + 50% { + + height: 0; + } + 100% { + + height: 0; + + } +} + +@keyframes active-opponent { + 0% { + /* border-top: 2rem #fff solid;*/ + height: 0; + + } + 50% { + max-width: calc(16px + 10 * 50px); + width: 100%; + max-height: calc(25px + 10 * 50px); + height: 100%; + + } + 100% { + max-width: calc(16px + 10 * 50px); + width: 100%; + max-height: calc(25px + 10 * 50px); + height: 100%; + + } +} diff --git a/src/assets/preflight.css b/src/assets/preflight.css new file mode 100644 index 0000000..c4c8ae7 --- /dev/null +++ b/src/assets/preflight.css @@ -0,0 +1,363 @@ +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; /* 1 */ + border-width: 0; /* 2 */ + border-style: solid; /* 2 */ +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -moz-tab-size: 4; /* 3 */ + tab-size: 4; /* 3 */ +/* font-family: theme('fontFamily.sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); /* 4 */ +/* font-feature-settings: theme('fontFamily.sans[1].fontFeatureSettings', normal); /* 5 */ +/* font-variation-settings: theme('fontFamily.sans[1].fontVariationSettings', normal); /* 6 */ + -webkit-tap-highlight-color: transparent; /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; /* 1 */ + line-height: inherit; /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; /* 1 */ + color: inherit; /* 2 */ + border-top-width: 1px; /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; /* 1 */ + border-color: inherit; /* 2 */ + border-collapse: collapse; /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-feature-settings: inherit; /* 1 */ + font-variation-settings: inherit; /* 1 */ + font-size: 100%; /* 1 */ + font-weight: inherit; /* 1 */ + line-height: inherit; /* 1 */ + letter-spacing: inherit; /* 1 */ + color: inherit; /* 1 */ + margin: 0; /* 2 */ + padding: 0; /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; /* 1 */ + background-color: transparent; /* 2 */ + background-image: none; /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: none; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::placeholder, +textarea::placeholder { + opacity: 1; /* 1 */ + color: #9ca3af; /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; /* 1 */ + vertical-align: middle; /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ +[hidden] { + display: none; +} diff --git a/src/classes/audioPlayer.js b/src/classes/audioPlayer.js new file mode 100644 index 0000000..690b395 --- /dev/null +++ b/src/classes/audioPlayer.js @@ -0,0 +1,27 @@ +const gameSound = { + move: new Audio('/audio/move.wav'), + fish: new Audio('/audio/fish.wav'), +} + +export default class AudioPlayer { + + constructor(settings) { + this.settings = settings + } + + async gameAsync(name) { + if (!navigator.userActivation.isActive) return + return new Promise(ended=>{ + let sound = this.game(name) + sound.onended = ended + }) + } + + game(name) { + if (!navigator.userActivation.isActive) return + gameSound[name].play() + gameSound[name].muted = this.settings.muted + gameSound[name].volume = (this.settings.game * this.settings.master) / 10000 + return gameSound[name] + } +} \ No newline at end of file diff --git a/src/classes/boardConstructor.js b/src/classes/boardConstructor.js new file mode 100644 index 0000000..02442dd --- /dev/null +++ b/src/classes/boardConstructor.js @@ -0,0 +1,185 @@ +export default class boardConstructor { + constructor(boardSize = 10, availableItems) { + this.boardSize = boardSize; + this.availableItems = availableItems + } + + generateItems() { + let items = {}; + let itemsCount = 4; + let curentSize = 1; + for (let i = itemsCount; i > 0; i--) { + let key = this.__generateItemId(); + items[key] = { + id: key, + size: curentSize, + type: "fish", + name: this.availableItems.pop(Math.floor(Math.random() * this.availableItems.length) + 1), + orientation: "h", + margin: 1, + cells: [], + marginCells: [], + }; + if (i <= 1) { + i = itemsCount; + itemsCount--; + curentSize++; + } + } + return items; + } + + generateBoard(items) { + Object.keys(items).map((id) => { + items[id].cells = []; + items[id].marginCells = []; + }); + let itemlist = Object.values(items); + itemlist.sort((a, b) => b.size - a.size); + while (itemlist.length > 0) { + let currentItem = { ...itemlist.shift() }; + currentItem.orientation = Math.random() < 0.5 ? "h" : "v"; + while (!this.isItemAlreadyOnBoard(items[currentItem.id])) { + let targetCell = Math.floor( + Math.random() * this.boardSize * this.boardSize + ); + currentItem.cells = this.getItemCells(targetCell, currentItem); + currentItem.marginCells = this.getItemMarginCells(currentItem); + if ( + this.isItemHasMarginCollision(currentItem, items) || + this.isItemHasCellsCollision(currentItem, items) + ) + continue; + items[currentItem.id] = currentItem; + } + } + return items; + } + + getItemCells(targetCell, item) { + let cells = []; + let cellRow = Math.floor(targetCell / this.boardSize); + for (let i = 0; i <= item.size - 1; i++) { + if (item.orientation == "h") { + let currentCell = targetCell + i; + if ( + currentCell <= + cellRow * this.boardSize + (this.boardSize - 1) + ) { + cells.push(currentCell); + } else { + cells.push( + targetCell + + (cellRow * this.boardSize + + (this.boardSize - 1) - + currentCell) + ); + } + } else if (item.orientation == "v") { + let currentCell = targetCell + this.boardSize * i; + if (currentCell < this.boardSize * this.boardSize) { + cells.push(currentCell); + } else { + cells.push(targetCell - this.boardSize * (item.size - i)); + } + } + } + return cells; + } + + getItemMarginCells(item) { + if (item.margin <= 0 || item.cells.length <= 0) return []; + let marginCells = item.cells.map((cell) => { + return this.__getCellMargin(cell, item.margin); + }); + return marginCells + .flat(1) + .filter((cell) => item.cells.indexOf(cell) < 0); + } + + findItemIdInBoardCell(targetCell, items) { + let item = Object.keys(items).filter((id) => { + return items[id].cells.includes(targetCell); + }); + return item[0]; + } + + isItemAlreadyOnBoard(item) { + return Object.values(item.cells).length > 0; + } + + isItemHasMarginCollision(item, items) { + if (item.cells?.length <= 0 && item.cells.marginCells?.length <= 0) + return false; + return ( + Object.keys(items).filter((id) => { + let collisionWithBoardItem = + items[id].marginCells.filter((itemMarginCell) => + item.cells.includes(itemMarginCell) + ).length > 0; + let collisionWithCurrentItem = + items[id].cells.filter((itemCell) => + item.marginCells.includes(itemCell) + ).length > 0; + return collisionWithBoardItem || collisionWithCurrentItem; + })?.length > 0 + ); + } + + isItemHasCellsCollision(item, items) { + if (item.cells?.length <= 0) return false; + return ( + Object.keys(items).filter((id) => { + return ( + items[id].cells.filter((itemCell) => + item.cells.includes(itemCell) + ).length > 0 + ); + })?.length > 0 + ); + } + + isAllItemsReady(items) { + return ( + Object.keys(items).filter((id) => { + return items[id].cells?.length <= 0; + })?.length <= 0 + ); + } + + __getCellMargin(cell, margin = 0) { + let cellMargin = []; + let cellRow = Math.floor(cell / this.boardSize); + let maxCells = this.boardSize * this.boardSize - 1; + let calcCell = null; + for ( + let rowMargin = margin; + rowMargin >= -Math.abs(margin); + rowMargin-- + ) { + let currentRow = cellRow + rowMargin; + let rowOffset = this.boardSize * rowMargin; + let rowMin = currentRow * this.boardSize; + let rowMax = rowMin + this.boardSize - 1; + for ( + let colMargin = margin; + colMargin >= -Math.abs(margin); + colMargin-- + ) { + calcCell = cell + rowOffset + colMargin; + if ( + calcCell >= 0 && + calcCell <= maxCells && + calcCell >= rowMin && + calcCell <= rowMax + ) + cellMargin.push(calcCell); + } + } + return cellMargin; + } + + __generateItemId() { + return Math.random().toString(36).replace("0.", ""); + } +} diff --git a/src/classes/scrollable.js b/src/classes/scrollable.js new file mode 100644 index 0000000..10279c9 --- /dev/null +++ b/src/classes/scrollable.js @@ -0,0 +1,39 @@ +export default class Scrollable { + canScrolling = false; + x = 0; + y = 0; + constructor(elemet) { + this.elemet = elemet; + } + + start(event) { + if (event.changedTouches != undefined) { + this.x = event.changedTouches[0].screenX; + this.y = event.changedTouches[0].screenY; + } else { + this.x = event.screenX; + this.y = event.screenY; + } + this.canScrolling = true; + } + move(event) { + if (this.canScrolling == false) return; + let x = + event.changedTouches != undefined + ? event.changedTouches[0].screenX + : event.screenX; + let y = + event.changedTouches != undefined + ? event.changedTouches[0].screenY + : event.screenY; + this.elemet.value.scrollLeft += this.x - x; + this.elemet.value.scrollTop += this.y - y; + this.x = x; + this.y = y; + } + end() { + this.canScrolling = false; + this.x = 0; + this.y = 0; + } +} diff --git a/src/components/common/RangeSliderComponent.vue b/src/components/common/RangeSliderComponent.vue new file mode 100644 index 0000000..40474bc --- /dev/null +++ b/src/components/common/RangeSliderComponent.vue @@ -0,0 +1,130 @@ + + + \ No newline at end of file diff --git a/src/i18n/i18n.js b/src/i18n/i18n.js new file mode 100644 index 0000000..6b0701b --- /dev/null +++ b/src/i18n/i18n.js @@ -0,0 +1,20 @@ +import { createI18n } from 'vue-i18n' +import pluralRules from "./rules/pluralization.js" +import numberFormats from "./rules/numbers.js" +import datetimeFormats from "./rules/datetime.js" +import en from './locales/en.json' +import ru from './locales/ru.json' + +const i18n = createI18n({ + + legacy: false, + globalInjection: true, + messages: { + en, + ru + }, + pluralRules, + numberFormats, + datetimeFormats + }) + export default i18n \ No newline at end of file diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json new file mode 100644 index 0000000..6779ce6 --- /dev/null +++ b/src/i18n/locales/en.json @@ -0,0 +1,44 @@ +{ + "application": { + "name": "Fishing" + }, + "button": { + "exit": "Exit", + "close": "Close", + "newGame": "New Game", + "settings": "Settings", + "menu": "Menu", + "singlePlayer": "Single Player", + "multiPlayer": "Multi Player", + "generate": "Release the fish", + "ready": "Ready", + "cancel": "Cancel", + "mainScreen": "Go to main screen", + "instruction": "How to play", + "rules": "Game rules" + }, + "settings": { + "sound": { + "title": "Sound", + "mute": "Mute", + "master": "Master", + "effects": "Effects", + "music": "Music", + "ambient": "Ambient" + } + }, + "game": { + "yourTurn": "Your turn", + "opponentTurn": "Opponent`s turn", + "over": "Game Over", + "win": "You win!", + "loose": "You loose!" + }, + "title": { + "game": "Game", + "language": "Language", + "player": "Player" + } + + +} \ No newline at end of file diff --git a/src/i18n/locales/ru.json b/src/i18n/locales/ru.json new file mode 100644 index 0000000..23ad8b0 --- /dev/null +++ b/src/i18n/locales/ru.json @@ -0,0 +1,42 @@ +{ + "application": { + "name": "Рыбалка" + }, + "button": { + "exit": "Выйти", + "close": "Закрыть", + "newGame": "Новая игра", + "settings": "Настройки", + "menu": "Меню", + "singlePlayer": "Одиночная игра", + "multiPlayer": "Играть с другом", + "generate": "Запустить рыбу", + "ready": "Готов", + "cancel": "Отмена", + "mainScreen": "На главный экран", + "instruction": "Как играть", + "rules": "Правила" + }, + "settings": { + "sound": { + "title": "Звук", + "mute": "Выключить", + "master": "Общая", + "effects": "Эффекты", + "music": "Музыка", + "ambient": "Окружение" + } + }, + "game": { + "yourTurn": "Ваш ход", + "opponentTurn": "Ход соперника", + "over": "Игра окончена", + "win": "Вы выиграли!", + "loose": "Вы проиграли!" + }, + "title": { + "game": "Игра", + "language": "Язык", + "player": "Игрок" + } +} \ No newline at end of file diff --git a/src/i18n/rules/datetime.js b/src/i18n/rules/datetime.js new file mode 100644 index 0000000..0d96e7f --- /dev/null +++ b/src/i18n/rules/datetime.js @@ -0,0 +1,20 @@ +export default { + en: { + shortFormat: { + dateStyle: "short" + }, + longFormat: { + year: 'numeric', month: 'short', day: 'numeric', + weekday: 'short', hour: 'numeric', minute: 'numeric' + } + }, + ru: { + shortFormat: { + dateStyle: "short" + }, + longFormat: { + year: 'numeric', month: 'short', day: 'numeric', + weekday: 'short', hour: 'numeric', minute: 'numeric' + } + } + } \ No newline at end of file diff --git a/src/i18n/rules/numbers.js b/src/i18n/rules/numbers.js new file mode 100644 index 0000000..5a8080e --- /dev/null +++ b/src/i18n/rules/numbers.js @@ -0,0 +1,14 @@ +export default { + en: { + currencyFormat: { + style: "currency", + currency: "USD" + } + }, + ru: { + currencyFormat: { + style: "currency", + currency: "RUB" + } + } + } \ No newline at end of file diff --git a/src/i18n/rules/pluralization.js b/src/i18n/rules/pluralization.js new file mode 100644 index 0000000..a8782dd --- /dev/null +++ b/src/i18n/rules/pluralization.js @@ -0,0 +1,20 @@ +function ruPluralizationRules( + choice, + choicesLength + ) { + if (choice === 0) { + return 0 + } + const teen = choice > 10 && choice < 20 + const endsWithOne = choice % 10 === 1 + if (!teen && endsWithOne) { + return 1 + } + if (!teen && choice % 10 >= 2 && choice % 10 <= 4) { + return 2 + } + return choicesLength < 4 ? 2 : 3 + } + export default { + ru: ruPluralizationRules + }; \ No newline at end of file diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..fb80591 --- /dev/null +++ b/src/main.js @@ -0,0 +1,39 @@ +import './assets/preflight.css' +import './assets/main.css' + +import { createApp, markRaw } from 'vue' +import i18n from '@/i18n/i18n' +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +import App from './App.vue' +import router from './router' +import { usePlayerStore } from './stores/player' +import { useApplicationStore } from './stores/application' + +const app = createApp(App) +const pina = createPinia() + +pina.use(({ store }) => { + store.$router = markRaw(router) +}); +pina.use(piniaPluginPersistedstate) + +app.use(pina) +app.use(router) + +const player = usePlayerStore() +player.init() + +const application = useApplicationStore() +application.init() + +i18n.global.locale.value = application.language + +/* +const websocket = useWebsocketStore() +websocket.init() +*/ +app.use(i18n) +app.mount('#app') + diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..780b609 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,33 @@ +import { createRouter, createWebHistory } from 'vue-router' +import IndexView from '../views/IndexView.vue' +import LobbyView from '@/views/LobbyView.vue' +import JoinView from '@/views/JoinView.vue' +import GameView from '@/views/GameView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'index', + component: IndexView + }, + { + path: '/lobby/:gameId', + name: 'lobby', + component: LobbyView + }, + { + path: '/join/:gameId', + name: 'join', + component: JoinView + }, + { + path: '/game/:gameId', + name: 'game', + component: GameView + } + ] +}) + +export default router diff --git a/src/stores/application.js b/src/stores/application.js new file mode 100644 index 0000000..3c27bff --- /dev/null +++ b/src/stores/application.js @@ -0,0 +1,43 @@ +import { defineStore } from "pinia"; +export const useApplicationStore = defineStore("application", { + state: () => ({ + showSettings: false, + showMenu: false, + language: null, + settings: { + sound: { + muted: false, + master: 100, + game: 100, + ambient: 100, + music: 100 + } + } + }), + actions: { + init() { + if (this.language == null) { + let language = navigator.language.slice(0,2) || navigator.userLanguage.slice(0,2) + if (language == 'ua' || language == 'ru') { + language = 'ru' + } else { + language = 'en' + } + this.language = language + } + }, + async openSettings() { + this.showSettings = true + }, + async closeSettings() { + this.showSettings = false + }, + async openMenu() { + this.showMenu = true + }, + async closeMenu() { + this.showMenu = false + } + }, + persist: true, +}) diff --git a/src/stores/bot.js b/src/stores/bot.js new file mode 100644 index 0000000..5edc561 --- /dev/null +++ b/src/stores/bot.js @@ -0,0 +1,120 @@ +import { defineStore } from "pinia"; +import boardConstructor from "@/classes/boardConstructor"; +import { useGameStore } from "./game"; + +export const useBotStore = defineStore("bot", { + state: () => ({ + items: {}, + }), + actions: { + generate() { + const game = useGameStore(); + const board = new boardConstructor(game.boardSize, game.getAvailableItems()); + let items = board.generateItems(); + this.items = board.generateBoard(items); + let playerItems = {}; + Object.values(this.items).forEach((item) => { + playerItems[item.id] = { size: item.size, margin: item.margin }; + }); + game.opponent.id = "bot"; + game.opponent.items = playerItems; + game.opponent.status = "ready"; + }, + async makeMove() { + const game = useGameStore(); + if (game.winner != null) return + await game.sleep(1000) + let targetCell = this.getTargetCell() + console.log('%c Bot move ', 'color:#e2a520;', targetCell); + let move = await game.checkMove(targetCell, "bot"); + await game.completeMove(move) + switch (move.item.type) { + case "fish": + await this.makeMove(); + break; + } + }, + async checkMove(targetCell) { + const game = useGameStore(); + let move = {}; + let targetItem = Object.values(this.items).filter((item) => + item.cells.includes(targetCell) + )[0]; + move.targetCell = targetCell; + move.player = game.turn.player; + move.opponent = game.turn.opponent; + move.create = new Date(); + move.status = "move"; + if (targetItem != undefined) { + move.item = { + id: targetItem.id, + type: targetItem.type, + name: targetItem.name, + }; + } else { + move.item = { + id: "empty", + type: "empty", + name: "empty", + }; + } + return move; + }, + getTargetCell() { + return this.mediumMode(); + }, + easyMode() { + const game = useGameStore(); + let moves = []; + game.moves.forEach((move) => { + if (move.player == "bot") moves.push(move.targetCell); + }); + let board = Array.from( + Array(game.boardSize * game.boardSize).keys() + ); + let availableMoves = board.filter((cell) => !moves.includes(cell)); + let targetCell = + availableMoves[ + Math.floor(Math.random() * availableMoves.length) + ]; + return targetCell; + }, + mediumMode() { + const game = useGameStore(); + let moves = []; + game.moves.forEach((move) => { + if (move.player == "bot") moves.push(move.targetCell); + }); + let board = Array.from( + Array(game.boardSize * game.boardSize).keys() + ); + let availableMoves = board.filter((cell) => !moves.includes(cell)); + let marginCells = this.getMarginCells() + availableMoves = availableMoves.filter((cell) => !marginCells.includes(cell)); + let targetCell = + availableMoves[ + Math.floor(Math.random() * availableMoves.length) + ]; + return targetCell; + }, + getMarginCells() { + const game = useGameStore(); + let items = {} + game.moves.forEach((move) => { + if (move.player != "bot" || move.item.id == 'empty') return + if (items[move.item.id] == undefined) items[move.item.id] = 0 + items[move.item.id]++ + }); + let marginCells = [] + Object.keys(items).forEach((itemId) => { + if (game.player.items[itemId].size == items[itemId]) { + game.player.items[itemId].marginCells.forEach((cell) => { + marginCells.push(cell) + }) + } + }) + return marginCells + }, + }, + persist: true, +}); diff --git a/src/stores/game.js b/src/stores/game.js new file mode 100644 index 0000000..58762ea --- /dev/null +++ b/src/stores/game.js @@ -0,0 +1,301 @@ +import { defineStore } from "pinia"; +import router from "@/router"; +import { usePlayerStore } from "./player"; +import { v4 as uuid } from "uuid"; +import { useBotStore } from "./bot"; +import { useApplicationStore } from '@/stores/application'; +import audioPlayer from '@/classes/audioPlayer' +import { useWebsocketStore } from "./websocket"; +import boardConstructor from '@/classes/boardConstructor' + +export const useGameStore = defineStore("game", { + state: () => ({ + id: null, + mode: null, + status: null, + winner: null, + owner: null, + createdAt: null, + boardSize: 10, + currentMove: null, + turn: { + player: null, + opponent: null, + }, + player: { + id: null, + status: null, + items: {}, + }, + opponent: { + id: null, + status: null, + items: {} + }, + moves: [], + }), + getters: { + getId(state) { + if (state.id == null) router.replace({ name: "idnex" }); + return state.id; + }, + }, + actions: { + // Get items keys for generation + getAvailableItems() { + return [...Array(23).keys()].slice(1) + }, + // Create new game + create(mode) { + const player = usePlayerStore(); + this.id = uuid(); + this.mode = mode; + this.status = "new"; + this.owner = usePlayerStore().id; + this.createdAt = new Date(); + this.player = { + id: player.id, + status: 'lobby', + items: [] + } + this.moves = []; + router.replace({ name: "lobby", params: { gameId: this.id } }); + }, + // Send sync to connected player + connected(playerId) { + if (playerId != this.opponent.id) return + useWebsocketStore().send({ + action:'sync', + from: this.player.id, + to: playerId, + game: this.gameData() + }) + }, + // Recieve join request and send welcome or decline + join(opponentId) { + const player = usePlayerStore() + if (this.opponent.id != null && this.opponent.id != opponentId) { + useWebsocketStore().send({ + action:'decline', + from: player.id, + to: opponentId, + reason: '1' + }) + return + } + this.opponent = { + id: opponentId, + status: "lobby", + items: {} + }; + useWebsocketStore().send({ + action:'welcome', + from: player.id, + to: opponentId, + game: this.gameData() + }) + }, + // Recieve welcome request and sync data + welcome(game) { + const player = usePlayerStore() + this.player.id = player.id + this.player.status = 'lobby' + this.sync(game) + router.replace({name: 'lobby', params: {gameId: this.id}}) + }, + // Recieve join decline message + decline() { + console.log('Owner send decline response') + }, + // Recieve sync data + sync(game) { + this.id = game.id + this.boardSize = game.boardSize + this.createdAt = game.createdAt + this.mode = game.mode, + this.moves = game.moves, + this.owner = game.owner, + this.status = game.status, + this.turn = game.turn, + this.winner = game.winner, + this.opponent = game.opponent + }, + // Send player ready message + ready() { + const board = new boardConstructor(this.boardSize, this.getAvailableItems()) + if (!board.isAllItemsReady(this.player.items)) return + this.player.status = "ready" + if (this.mode == "single") { + useBotStore().generate() + return + } + useWebsocketStore().send({ + action:'sync', + from: this.player.id, + to: this.opponent.id, + game: this.gameData() + }) + }, + start() { + if (this.player.status != "ready" || this.opponent.status != "ready") return + if (this.owner == this.player.id) { + this.status = "played"; + this.turn = { + player: this.player.id, + opponent: this.opponent.id + } + if (this.mode != "single") { + useWebsocketStore().send({ + action:'sync', + from: this.player.id, + to: this.opponent.id, + game: this.gameData() + }) + } + } + router.replace({ name: "game", params: { gameId: this.id } }); + }, + async makeMove(targetCell) { + let move = undefined + console.log('%c Player move '+ this.player.id +' cell '+ targetCell + ' [gameStore]', "color:#e2a520;") + if (this.mode == "single") { + const bot = useBotStore() + move = await bot.checkMove(targetCell); + return move; + } + useWebsocketStore().send({ + action:'checkMove', + from: this.player.id, + to: this.opponent.id, + game: this.gameData(), + targetCell: targetCell + }) + return + }, + async checkMove(targetCell) { + console.log('%c Check move from '+ this.opponent.id +' cell '+ targetCell + ' [gameStore]', "color:#2dc9ac;") + const application = useApplicationStore() + const audio = new audioPlayer(application.settings.sound) + let move = {}; + let targetItem = Object.values(this.player.items).filter((item) => item.cells.includes(targetCell))[0]; + move.targetCell = targetCell + move.player = this.turn.player + move.opponent = this.turn.opponent + move.create = new Date() + move.type = "move" + if (targetItem != undefined) { + audio.game('fish') + move.item = { + id: targetItem.id, + type: targetItem.type, + name: targetItem.name, + }; + let moves = this.getSuccessPlayerMoves(this.opponent.id) + let itemsSize = this.getCompleteItemsSize(moves) + if (this.isGameComplete(this.player.items, itemsSize)) { + this.winner = this.opponent.id + } + } else { + audio.game('move') + move.item = { + id: 'empty', + type: 'empty', + name: 'empty', + }; + } + console.log('%c Check move complete from '+ this.opponent.id + ' [gameStore]', 'color:#2dc9ac;', move) + if (this.mode == 'single') return move; + let message = { + action:'completeMove', + from: move.opponent.id, + to: move.player.id, + game: this.gameData(), + move: move + }; + useWebsocketStore().send(message) + return + }, + async completeMove(move) { + console.log('%c Complete move START from ' + move.player + ' [gameStore]', 'color:#2dc9ac;',move) + this.moves.push(move); + const application = useApplicationStore() + const audio = new audioPlayer(application.settings.sound) + switch (move.item.type) { + case "empty": + console.log('%c Set player turn ' + move.opponent + ' [gameStore]', 'color: #e2202a') + await audio.gameAsync('move') + this.turn.opponent = move.player + this.turn.player = move.opponent + break; + case "fish": + await audio.gameAsync('fish') + let moves = this.getSuccessPlayerMoves(move.player) + let itemsSize = this.getCompleteItemsSize(moves) + if (itemsSize[move.item.id] == undefined) return + let items = this.opponent.items + if (move.player == 'bot' || move.player == this.opponent.id) items = this.player.items + if (itemsSize[move.item.id] == items[move.item.id].size) { + console.log('%c Player ' + move.player + ' complete item ' + move.item.id + ' [gameStore]', 'color:#2dc9ac;') + } + if (this.isGameComplete(items, itemsSize)) { + console.log('%c Game complete! Winner ' + move.player + ' [gameStore]', 'color:#2dc9ac;') + this.winner = move.player + useWebsocketStore().send({ + action:'sync', + from: this.player.id, + to: this.opponent.id, + game: this.gameData() + }) + } + break; + } + console.log('%c Complete move END from ' + move.player + ' [gameStore]', 'color:#2dc9ac;',move) + }, + async sleep(ms) { + console.log('%c SLEEP... ' + ms + 'ms' + ' [gameStore]', 'color:#e2bb20;') + return new Promise(resolve => setTimeout(resolve, ms)); + }, + getSuccessPlayerMoves(playerId) { + return this.moves.filter((playerMove) => playerMove.player == playerId && playerMove.item.id != 'empty') + }, + getCompleteItemsSize(moves) { + let items = {} + moves.forEach((move) => { + if (items[move.item.id] == undefined) items[move.item.id] = 0 + items[move.item.id]++ + }) + return items + }, + isGameComplete(items, completeItems) { + let gameComplete = true + Object.keys(items).forEach((itemId) => { + if (completeItems[itemId] == undefined) gameComplete = false + if (completeItems[itemId] != items[itemId].size) gameComplete = false + }) + return gameComplete + }, + gameData() { + let data = { + id: this.id, + boardSize: this.boardSize, + createdAt: this.createdAt, + mode: this.mode, + moves: this.moves, + owner: this.owner, + status: this.status, + turn: this.turn, + winner: this.winner, + opponent: { + id: this.player.id, + items: {}, + status: this.player.status + } + }; + Object.values(this.player.items).forEach((item) => { + data.opponent.items[item.id] = { size: item.size, margin: item.margin }; + }); + return data + } + }, + persist: true, +}); \ No newline at end of file diff --git a/src/stores/player.js b/src/stores/player.js new file mode 100644 index 0000000..9cc3ca4 --- /dev/null +++ b/src/stores/player.js @@ -0,0 +1,27 @@ +import { defineStore } from "pinia"; +import { v4 as uuid } from 'uuid' + +export const usePlayerStore = defineStore("player", { + state: () => ({ + id: null, + username: "Anonimus", + createdAt: null, + + }), + getters: { + getId(state) { + if (state.id == null) usePlayerStore().init(); + return state.id + } + }, + actions: { + init() { + if (this.id == null) { + this.id = uuid() + this.username = 'Anonimus' + this.createdAt = new Date() + } + }, + }, + persist: true, +}); diff --git a/src/stores/websocket.js b/src/stores/websocket.js new file mode 100644 index 0000000..2fffca7 --- /dev/null +++ b/src/stores/websocket.js @@ -0,0 +1,93 @@ +import { defineStore } from "pinia"; +import { usePlayerStore } from "./player"; +import { useGameStore } from "./game"; + +const connectionUrl = 'wss://fishingspot.serverhost.stream/socket' + +export const useWebsocketStore = defineStore("websocket", { + state: () => ({ + connection: null + }), + actions: { + init(gameId) { + const player = usePlayerStore() + const game = useGameStore() + this.connection = new WebSocket(connectionUrl + "?gameId=" + gameId + "&playerId=" + player.id); + this.connection.onopen = function (event) { + console.log(event); + console.log("Successfully connected websocket server to game: " + gameId); + }; + this.connection.onmessage = function (event) { + const player = usePlayerStore() + const game = useGameStore() + let data = {} + try { + data = JSON.parse(event.data) + } catch (e) { + return false; + } + switch(data.action) { + case 'connected': + console.log('Recieve connected from ' + data.from) + game.connected(data.from) + break + case 'disconnected': + if (data.from == game.owner) { + console.log("owner disconected start timer 30 sec and end game") + } + if (data.from == game.opponent.id) { + console.log("opponent disconected start timer 30 sec and end game") + } + console.log('Recieve disconnected from ' + data.from) + break + case 'sync': + console.log('Recieve sync from ' + data.from) + game.sync(data.game) + break + case 'join': + console.log('Recieve join from ' + data.from) + if (game.owner != player.id) return // Only owner ccan process join + game.join(data.from) + break + case 'welcome': + console.log('Recieve welcome from ' + data.from) + game.welcome(data.game) + break + case 'decline': + console.log('Recieve decline from ' + data.from) + break + case 'ready': + console.log('Recieve ready from ' + data.from) + game.sync(data.game) + break + case 'checkMove': + console.log('Recieve move from ' + data.from) + game.checkMove(data.targetCell) + break + case 'completeMove': + game.completeMove(data.move) + break + default: + console.error('Event data target not found') + } + }; + this.connection.onclose = (event) => { + console.log("Server close websocket connection for player " + player.id); + setTimeout(function () { + console.log("Try reconnect to websocket server for player " + player.id); + useWebsocketStore().init(game.id); + }, 1000); + }; + }, + send(data) { + console.log('send', JSON.stringify(data) ) + this.connection.send(JSON.stringify(data)) + }, + disconnect() { + if (this.connection == null) return + // this.connection.onclose = () => {} + // this.connection.close() + }, + + } +}) \ No newline at end of file diff --git a/src/views/GameView.vue b/src/views/GameView.vue new file mode 100644 index 0000000..7d55652 --- /dev/null +++ b/src/views/GameView.vue @@ -0,0 +1,140 @@ + + + + + \ No newline at end of file diff --git a/src/views/IndexView.vue b/src/views/IndexView.vue new file mode 100644 index 0000000..a459e8b --- /dev/null +++ b/src/views/IndexView.vue @@ -0,0 +1,69 @@ + + + + + \ No newline at end of file diff --git a/src/views/JoinView.vue b/src/views/JoinView.vue new file mode 100644 index 0000000..8e495a5 --- /dev/null +++ b/src/views/JoinView.vue @@ -0,0 +1,71 @@ + + + + + \ No newline at end of file diff --git a/src/views/LobbyView.vue b/src/views/LobbyView.vue new file mode 100644 index 0000000..79c6a33 --- /dev/null +++ b/src/views/LobbyView.vue @@ -0,0 +1,92 @@ + + + + + \ No newline at end of file diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..3ad1a26 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue() + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +})