diff --git a/.pnp.cjs b/.pnp.cjs index 908eb4c..34ee2ab 100644 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -37,6 +37,7 @@ const RAW_RUNTIME_STATE = ["eslint-plugin-vue", "virtual:7d6457be6b857bdb44066d1c6f9d2471ca71cf43c0df847ead5ae9289c5e9f98de3a67668fdd588c95fcb212da2ba4f12a34babd1f52380566b5d7bf44a88ca5#npm:10.0.0"],\ ["jiti", "npm:2.4.2"],\ ["npm-run-all2", "npm:7.0.2"],\ + ["peerjs", "npm:1.5.4"],\ ["pinia", "virtual:7d6457be6b857bdb44066d1c6f9d2471ca71cf43c0df847ead5ae9289c5e9f98de3a67668fdd588c95fcb212da2ba4f12a34babd1f52380566b5d7bf44a88ca5#npm:3.0.2"],\ ["prettier", "npm:3.5.3"],\ ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ @@ -1001,6 +1002,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@msgpack/msgpack", [\ + ["npm:2.8.0", {\ + "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/@msgpack-msgpack-npm-2.8.0-c4768c71d4-10c0.zip/node_modules/@msgpack/msgpack/",\ + "packageDependencies": [\ + ["@msgpack/msgpack", "npm:2.8.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@nodelib/fs.scandir", [\ ["npm:2.1.5", {\ "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-10c0.zip/node_modules/@nodelib/fs.scandir/",\ @@ -2107,6 +2117,7 @@ const RAW_RUNTIME_STATE = ["eslint-plugin-vue", "virtual:7d6457be6b857bdb44066d1c6f9d2471ca71cf43c0df847ead5ae9289c5e9f98de3a67668fdd588c95fcb212da2ba4f12a34babd1f52380566b5d7bf44a88ca5#npm:10.0.0"],\ ["jiti", "npm:2.4.2"],\ ["npm-run-all2", "npm:7.0.2"],\ + ["peerjs", "npm:1.5.4"],\ ["pinia", "virtual:7d6457be6b857bdb44066d1c6f9d2471ca71cf43c0df847ead5ae9289c5e9f98de3a67668fdd588c95fcb212da2ba4f12a34babd1f52380566b5d7bf44a88ca5#npm:3.0.2"],\ ["prettier", "npm:3.5.3"],\ ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ @@ -2765,6 +2776,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["eventemitter3", [\ + ["npm:4.0.7", {\ + "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/eventemitter3-npm-4.0.7-7afcdd74ae-10c0.zip/node_modules/eventemitter3/",\ + "packageDependencies": [\ + ["eventemitter3", "npm:4.0.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["execa", [\ ["npm:9.5.2", {\ "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/execa-npm-9.5.2-f74ad877bc-10c0.zip/node_modules/execa/",\ @@ -3951,6 +3971,28 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["peerjs", [\ + ["npm:1.5.4", {\ + "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/peerjs-npm-1.5.4-b1f39eb912-10c0.zip/node_modules/peerjs/",\ + "packageDependencies": [\ + ["peerjs", "npm:1.5.4"],\ + ["@msgpack/msgpack", "npm:2.8.0"],\ + ["eventemitter3", "npm:4.0.7"],\ + ["peerjs-js-binarypack", "npm:2.1.0"],\ + ["webrtc-adapter", "npm:9.0.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["peerjs-js-binarypack", [\ + ["npm:2.1.0", {\ + "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/peerjs-js-binarypack-npm-2.1.0-59ed32add7-10c0.zip/node_modules/peerjs-js-binarypack/",\ + "packageDependencies": [\ + ["peerjs-js-binarypack", "npm:2.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["perfect-debounce", [\ ["npm:1.0.0", {\ "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/perfect-debounce-npm-1.0.0-0968810009-10c0.zip/node_modules/perfect-debounce/",\ @@ -4226,6 +4268,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["sdp", [\ + ["npm:3.2.0", {\ + "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/sdp-npm-3.2.0-b1a5f85233-10c0.zip/node_modules/sdp/",\ + "packageDependencies": [\ + ["sdp", "npm:3.2.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["semver", [\ ["npm:6.3.1", {\ "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/semver-npm-6.3.1-bcba31fdbe-10c0.zip/node_modules/semver/",\ @@ -4959,6 +5010,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["webrtc-adapter", [\ + ["npm:9.0.3", {\ + "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/webrtc-adapter-npm-9.0.3-9d13b6cc5b-10c0.zip/node_modules/webrtc-adapter/",\ + "packageDependencies": [\ + ["webrtc-adapter", "npm:9.0.3"],\ + ["sdp", "npm:3.2.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["which", [\ ["npm:2.0.2", {\ "packageLocation": "../../../../AppData/Local/Yarn/Berry/cache/which-npm-2.0.2-320ddf72f7-10c0.zip/node_modules/which/",\ diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index 4c6d64c..1899a67 100644 Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ diff --git a/package.json b/package.json index a0dc640..71ce349 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "format": "prettier --write src/" }, "dependencies": { + "peerjs": "^1.5.4", "pinia": "^3.0.1", "vue": "^3.5.13", "vue-router": "^4.5.0" diff --git a/src/router/index.ts b/src/router/index.ts index 3e49915..0e4752b 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -17,6 +17,16 @@ const router = createRouter({ // which is lazy-loaded when the route is visited. component: () => import('../views/AboutView.vue'), }, + { + path: '/practice', + name: 'Practice', + component: () => import('../views/Practice.vue'), + }, + { + path: '/network-battle', + name: 'NetworkBattle', + component: () => import('../views/NetworkBattle.vue'), + }, ], }) diff --git a/src/utils/questionGenerator.ts b/src/utils/questionGenerator.ts new file mode 100644 index 0000000..3ee3782 --- /dev/null +++ b/src/utils/questionGenerator.ts @@ -0,0 +1,81 @@ +export function generateQuestion(difficulty: number): { question: string, answer: number } { + const ops = ['+', '-', '×', '÷']; + + const generateEasyAddition = (): { question: string, answer: number } => { + const a = Math.floor(Math.random() * 10); + const b = Math.floor(Math.random() * 10); + return { + question: `${a} + ${b}`, + answer: a + b, + }; + }; + + const generateEasySubtraction = (): { question: string, answer: number } => { + const a = Math.floor(Math.random() * 10); + const b = Math.floor(Math.random() * a); // 保证 a > b + return { + question: `${a} - ${b}`, + answer: a - b, + }; + }; + + const generateMultiplication = (): { question: string, answer: number } => { + const a = Math.floor(Math.random() * 10); + const b = Math.floor(Math.random() * 10); + return { + question: `${a} × ${b}`, + answer: a * b, + }; + }; + + const generateMediumAddition = (): { question: string, answer: number } => { + const a = Math.floor(Math.random() * 100); + const b = Math.floor(Math.random() * 100); + return { + question: `${a} + ${b}`, + answer: a + b, + }; + }; + + const generateMediumSubtraction = (): { question: string, answer: number } => { + const a = Math.floor(Math.random() * 100); + const b = Math.floor(Math.random() * a); // 保证 a > b + return { + question: `${a} - ${b}`, + answer: a - b, + }; + }; + + const generateMultiplicationDivision = (): { question: string, answer: number } => { + const table = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // 乘法表 + const a = table[Math.floor(Math.random() * table.length)]; + const b = table[Math.floor(Math.random() * table.length)]; + const result = a * b; + + return { + question: `${result} ÷ ${a}`, + answer: b, + }; + }; + + switch (difficulty) { + case 1: // 10以内加减法 + return Math.random() < 0.5 + ? generateEasyAddition() + : generateEasySubtraction(); + + case 2: // 10以内乘法 + return generateMultiplication(); + + case 3: // 100以内加减法 + return Math.random() < 0.5 + ? generateMediumAddition() + : generateMediumSubtraction(); + + case 4: // 乘法表除法 + return generateMultiplicationDivision(); + + default: + throw new Error('Invalid difficulty level'); + } +} diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 7182148..4f0a301 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -6,7 +6,7 @@

准备好练习你的数学计算能力,或者与他人一决高下了吗?

单人练习 - 在线比赛 + 在线比赛
diff --git a/src/views/NetworkBattle.vue b/src/views/NetworkBattle.vue new file mode 100644 index 0000000..ed7205e --- /dev/null +++ b/src/views/NetworkBattle.vue @@ -0,0 +1,838 @@ + + + + + \ No newline at end of file diff --git a/src/views/Practice.vue b/src/views/Practice.vue new file mode 100644 index 0000000..41efaf8 --- /dev/null +++ b/src/views/Practice.vue @@ -0,0 +1,371 @@ + + + + + diff --git a/yarn.lock b/yarn.lock index 36fa266..c294fd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -712,6 +712,13 @@ __metadata: languageName: node linkType: hard +"@msgpack/msgpack@npm:^2.8.0": + version: 2.8.0 + resolution: "@msgpack/msgpack@npm:2.8.0" + checksum: 10c0/5964ed3daad9ccf314238da81c91152dc693bca167b2469445c1d3ce0495443612e543d052281061a91ec48ed44a6a49dd3a334b5d0dbe2dc2db6ea6143e5787 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -1511,6 +1518,7 @@ __metadata: eslint-plugin-vue: "npm:~10.0.0" jiti: "npm:^2.4.2" npm-run-all2: "npm:^7.0.2" + peerjs: "npm:^1.5.4" pinia: "npm:^3.0.1" prettier: "npm:^3.5.3" typescript: "npm:~5.8.0" @@ -2098,6 +2106,13 @@ __metadata: languageName: node linkType: hard +"eventemitter3@npm:^4.0.7": + version: 4.0.7 + resolution: "eventemitter3@npm:4.0.7" + checksum: 10c0/5f6d97cbcbac47be798e6355e3a7639a84ee1f7d9b199a07017f1d2f1e2fe236004d14fa5dfaeba661f94ea57805385e326236a6debbc7145c8877fbc0297c6b + languageName: node + linkType: hard + "execa@npm:^9.5.2": version: 9.5.2 resolution: "execa@npm:9.5.2" @@ -3160,6 +3175,25 @@ __metadata: languageName: node linkType: hard +"peerjs-js-binarypack@npm:^2.1.0": + version: 2.1.0 + resolution: "peerjs-js-binarypack@npm:2.1.0" + checksum: 10c0/562b6ef27b0de6b152dcab3e13684d38decfff8b51967e12ae14707b1292a78c162ce6befc9ae63ffefec81555eb37372a0e8a530aeabdc69bea3348e4a43790 + languageName: node + linkType: hard + +"peerjs@npm:^1.5.4": + version: 1.5.4 + resolution: "peerjs@npm:1.5.4" + dependencies: + "@msgpack/msgpack": "npm:^2.8.0" + eventemitter3: "npm:^4.0.7" + peerjs-js-binarypack: "npm:^2.1.0" + webrtc-adapter: "npm:^9.0.0" + checksum: 10c0/f52d95693059917ae701c829f766b8c8c6ad13041f16e294d3f82a9f49357e769800895cba445139c3586c89a59f6d818b58c4f1251612139fa6a891d951ace7 + languageName: node + linkType: hard + "perfect-debounce@npm:^1.0.0": version: 1.0.0 resolution: "perfect-debounce@npm:1.0.0" @@ -3434,6 +3468,13 @@ __metadata: languageName: node linkType: hard +"sdp@npm:^3.2.0": + version: 3.2.0 + resolution: "sdp@npm:3.2.0" + checksum: 10c0/fa0146132b4c9185f276b80e09f52259b103e609565ac40c560250dbe7fc47723d30530c0db9cac6217c83153944a71af81fa70dc0367f195aabcf110f8185fd + languageName: node + linkType: hard + "semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -3990,6 +4031,15 @@ __metadata: languageName: node linkType: hard +"webrtc-adapter@npm:^9.0.0": + version: 9.0.3 + resolution: "webrtc-adapter@npm:9.0.3" + dependencies: + sdp: "npm:^3.2.0" + checksum: 10c0/bb8c1626cc0e18bd34c03074fc6a541666dbe473c8f063c5d0ea2a3a3a4887f498212a131c936777f660382185f44941476609a50df5f1543015240623375725 + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2"