From 537a674da015f7e9ed5e1a081ec0b73fd89d4ca7 Mon Sep 17 00:00:00 2001 From: hnu202326010427 <2944528150@qq.com> Date: Thu, 9 Oct 2025 17:46:22 +0800 Subject: [PATCH 01/30] Initial commit --- README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..aacf4a3 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Pair-Programming + -- 2.34.1 From 47f3e9580144dc4e98dbf43adf0ef5c317768f48 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Thu, 9 Oct 2025 18:36:23 +0800 Subject: [PATCH 02/30] =?UTF-8?q?=E6=96=B0=E5=A2=9Efrontend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md => doc/README.md | 0 src/electron-frontend/package-lock.json | 3821 +++++++++++++++++ src/electron-frontend/package.json | 34 + src/electron-frontend/resources/main.js | 100 + src/electron-frontend/resources/preload.js | 129 + .../resources/renderer/login.html | 119 + .../resources/renderer/main.html | 464 ++ .../resources/renderer/quiz.html | 264 ++ .../resources/renderer/register.html | 260 ++ .../resources/renderer/result.html | 104 + .../resources/style/common.css | 37 + src/electron-frontend/start-backend.bat | 6 + 12 files changed, 5338 insertions(+) rename README.md => doc/README.md (100%) create mode 100644 src/electron-frontend/package-lock.json create mode 100644 src/electron-frontend/package.json create mode 100644 src/electron-frontend/resources/main.js create mode 100644 src/electron-frontend/resources/preload.js create mode 100644 src/electron-frontend/resources/renderer/login.html create mode 100644 src/electron-frontend/resources/renderer/main.html create mode 100644 src/electron-frontend/resources/renderer/quiz.html create mode 100644 src/electron-frontend/resources/renderer/register.html create mode 100644 src/electron-frontend/resources/renderer/result.html create mode 100644 src/electron-frontend/resources/style/common.css create mode 100644 src/electron-frontend/start-backend.bat diff --git a/README.md b/doc/README.md similarity index 100% rename from README.md rename to doc/README.md diff --git a/src/electron-frontend/package-lock.json b/src/electron-frontend/package-lock.json new file mode 100644 index 0000000..cc0a9c4 --- /dev/null +++ b/src/electron-frontend/package-lock.json @@ -0,0 +1,3821 @@ +{ + "name": "math-learning-app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "math-learning-app", + "version": "1.0.0", + "dependencies": { + "node-fetch": "^2.7.0" + }, + "devDependencies": { + "electron": "^22.0.0", + "electron-builder": "^24.0.0" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron/asar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "dev": true, + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/asar/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/notarize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", + "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/notarize/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/notarize/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@electron/osx-sign/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/osx-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", + "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "dev": true, + "dependencies": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "22.18.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.8.tgz", + "integrity": "sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw==", + "dev": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true + }, + "node_modules/app-builder-lib": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", + "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "dev": true, + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.2.1", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.5.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.13.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "24.13.3", + "electron-builder-squirrel-windows": "24.13.3" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "peer": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "peer": true + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builder-util": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", + "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "dev": true, + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", + "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/builder-util/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "dependencies": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "peer": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "optional": true + }, + "node_modules/dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "node_modules/dir-compare/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", + "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "dev": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "22.3.27", + "resolved": "https://registry.npmjs.org/electron/-/electron-22.3.27.tgz", + "integrity": "sha512-7Rht21vHqj4ZFRnKuZdFqZFsvMBCmDqmjetiMqPtF+TmTBiGne1mnstVXOA/SRGhN2Qy5gY5bznJKpiqogjM8A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^16.11.26", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", + "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "dev": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "dmg-builder": "24.13.3", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder-squirrel-windows": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", + "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", + "dev": true, + "peer": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "archiver": "^5.3.1", + "builder-util": "24.13.1", + "fs-extra": "^10.1.0" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-publish": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", + "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-publish/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron/node_modules/@types/node": { + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "peer": true + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "peer": true + }, + "node_modules/isbinaryfile": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", + "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", + "dev": true, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "peer": true + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "peer": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "peer": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "peer": true + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "dev": true, + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "peer": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "peer": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "optional": true + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "peer": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "peer": true + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "peer": true, + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/src/electron-frontend/package.json b/src/electron-frontend/package.json new file mode 100644 index 0000000..85b1de1 --- /dev/null +++ b/src/electron-frontend/package.json @@ -0,0 +1,34 @@ +{ + "name": "math-learning-app", + "version": "1.0.0", + "description": "小初高数学学习软件", + "main": "src/main.js", + "scripts": { + "start": "electron .", + "dev": "electron . --dev", + "build": "electron-builder" + }, + "devDependencies": { + "electron": "^22.0.0", + "electron-builder": "^24.0.0" + }, + "build": { + "appId": "com.mathlearning.app", + "productName": "数学学习系统", + "directories": { + "output": "dist" + }, + "files": [ + "src/**/*", + "styles/**/*", + "assets/**/*" + ], + "win": { + "target": "nsis", + "icon": "assets/icon.ico" + } + }, + "dependencies": { + "node-fetch": "^2.7.0" + } +} diff --git a/src/electron-frontend/resources/main.js b/src/electron-frontend/resources/main.js new file mode 100644 index 0000000..688dacc --- /dev/null +++ b/src/electron-frontend/resources/main.js @@ -0,0 +1,100 @@ +const fetch = require('node-fetch'); +const { app, BrowserWindow, Menu, ipcMain } = require('electron'); +const path = require('path'); + +let mainWindow; + +function createWindow() { + mainWindow = new BrowserWindow({ + width: 1200, + height: 800, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + preload: path.join(__dirname, 'preload.js'), // 确保路径正确 + webSecurity: false // 开发时可以关闭,避免CORS问题 + }, + icon: path.join(__dirname, 'assets/icon.png') // 可选 + }); + + // 加载登录页面 + mainWindow.loadFile(path.join(__dirname, 'renderer/login.html')); + + // 开发时打开开发者工具 + mainWindow.webContents.openDevTools(); +} + +function createMenu() { + const template = [ + { + label: '文件', + submenu: [ + { + label: '退出', + click: () => app.quit() + } + ] + }, + { + label: '查看', + submenu: [ + { role: 'reload' }, + { role: 'toggleDevTools' } + ] + } + ]; + + const menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); +} + +// API 基础URL +const API_BASE_URL = 'http://localhost:8080/api'; + +// 处理API请求 +ipcMain.handle('api-request', async (event, { endpoint, method = 'POST', data = {} }) => { + try { + const url = `${API_BASE_URL}${endpoint}`; + const formData = new URLSearchParams(); + + for (const [key, value] of Object.entries(data)) { + formData.append(key, value); + } + + const response = await fetch(url, { + method: method, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: formData + }); + + const result = await response.json(); + return result; + } catch (error) { + return { + success: false, + message: `网络错误: ${error.message}`, + data: null + }; + } +}); + +// 页面导航 +ipcMain.handle('navigate-to', (event, page) => { + mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`)); +}); + +app.whenReady().then(createWindow); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } +}); \ No newline at end of file diff --git a/src/electron-frontend/resources/preload.js b/src/electron-frontend/resources/preload.js new file mode 100644 index 0000000..5f08f7e --- /dev/null +++ b/src/electron-frontend/resources/preload.js @@ -0,0 +1,129 @@ +const { contextBridge, ipcRenderer } = require('electron'); + +// 统一的会话管理器 +const SessionManager = { + // 获取当前用户会话(强制从存储读取) + getCurrentUser() { + try { + const session = localStorage.getItem('userSession'); + return session ? JSON.parse(session) : null; + } catch (error) { + console.error('获取用户会话失败:', error); + return null; + } + }, + + // 获取当前考试会话 + getCurrentExam() { + try { + const exam = localStorage.getItem('currentExam'); + return exam ? JSON.parse(exam) : null; + } catch (error) { + console.error('获取考试会话失败:', error); + return null; + } + }, + + // 清除所有会话 + clearAllSessions() { + localStorage.removeItem('userSession'); + localStorage.removeItem('currentExam'); + localStorage.removeItem('examResult'); + console.log('所有会话已清除'); + }, + + // 验证会话是否有效 + validateUserSession() { + const user = this.getCurrentUser(); + if (!user || !user.sessionId) { + return false; + } + + // 可以添加更多验证逻辑,比如检查过期时间等 + return true; + }, + + // 刷新用户会话(在修改密码等操作后) + refreshUserSession(updatedUserData) { + if (updatedUserData) { + localStorage.setItem('userSession', JSON.stringify(updatedUserData)); + } + } + +}; + +// 暴露安全的API给渲染进程 +contextBridge.exposeInMainWorld('electronAPI', { + // 页面导航 + navigateTo: (page) => ipcRenderer.invoke('navigate-to', page), + + // 存储会话数据 + setSession: (key, value) => { + localStorage.setItem(key, JSON.stringify(value)); + }, + + getSession: (key) => { + const item = localStorage.getItem(key); + return item ? JSON.parse(item) : null; + }, + + removeSession: (key) => { + localStorage.removeItem(key); + }, + + // 新增:获取当前会话状态 + getSessionState: () => { + return SessionManager.validateSession(); + }, + + // 新增:强制清除所有会话 + clearAllSessions: () => { + SessionManager.clearAllSessions(); + }, + // 新增会话验证方法 + validateSession: () => { + return SessionManager.validateUserSession(); + }, + + // 新增会话刷新方法 + refreshSession: (userData) => { + SessionManager.refreshUserSession(userData); + } +}); + +// 直接在渲染进程中暴露 API 调用函数 +contextBridge.exposeInMainWorld('api', { + request: async (endpoint, method = 'POST', data = {}) => { + try { + console.log('API Request:', endpoint, method, data); + + const url = `http://localhost:8080/api${endpoint}`; + const formData = new URLSearchParams(); + + for (const [key, value] of Object.entries(data)) { + formData.append(key, value); + } + + const response = await fetch(url, { + method: method, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: formData + }); + + const result = await response.json(); + console.log('API Response:', result); + return result; + } catch (error) { + console.error('API Error:', error); + return { + success: false, + message: `网络错误: ${error.message}`, + data: null + }; + } + } +}); + +console.log('Preload script loaded successfully'); \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/login.html b/src/electron-frontend/resources/renderer/login.html new file mode 100644 index 0000000..7d51f60 --- /dev/null +++ b/src/electron-frontend/resources/renderer/login.html @@ -0,0 +1,119 @@ + + + + + + 数学试卷自动生成系统 - 登录 + + + + + +
+

数学试卷自动生成系统

+
+
+ +
+
+ +
+ +
+ 没有账号?立即注册 +
+
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/main.html b/src/electron-frontend/resources/renderer/main.html new file mode 100644 index 0000000..4aa30de --- /dev/null +++ b/src/electron-frontend/resources/renderer/main.html @@ -0,0 +1,464 @@ + + + + + + 数学学习系统 - 主页 + + + + + +
+

数学学习系统

+ +
+ +
+ +
+ + + +
+ + + +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/quiz.html b/src/electron-frontend/resources/renderer/quiz.html new file mode 100644 index 0000000..bc7962d --- /dev/null +++ b/src/electron-frontend/resources/renderer/quiz.html @@ -0,0 +1,264 @@ + + + + + + 数学学习系统 - 答题 + + + + + +
+
+ +
+ +
+ +
+ +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/register.html b/src/electron-frontend/resources/renderer/register.html new file mode 100644 index 0000000..dbffcca --- /dev/null +++ b/src/electron-frontend/resources/renderer/register.html @@ -0,0 +1,260 @@ + + + + + + 数学学习系统 - 注册 + + + + + +
+

用户注册

+ +
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/result.html b/src/electron-frontend/resources/renderer/result.html new file mode 100644 index 0000000..a229fd5 --- /dev/null +++ b/src/electron-frontend/resources/renderer/result.html @@ -0,0 +1,104 @@ + + + + + + 数学学习系统 - 成绩 + + + + + +
+

考试完成

+
+ +
+

+ +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/style/common.css b/src/electron-frontend/resources/style/common.css new file mode 100644 index 0000000..d779eb6 --- /dev/null +++ b/src/electron-frontend/resources/style/common.css @@ -0,0 +1,37 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + padding: 20px; +} + +.message { + padding: 10px; + margin-top: 15px; + border-radius: 5px; + text-align: center; +} + +.message.success { + background: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.message.error { + background: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +.message.info { + background: #d1ecf1; + color: #0c5460; + border: 1px solid #bee5eb; +} \ No newline at end of file diff --git a/src/electron-frontend/start-backend.bat b/src/electron-frontend/start-backend.bat new file mode 100644 index 0000000..81b488e --- /dev/null +++ b/src/electron-frontend/start-backend.bat @@ -0,0 +1,6 @@ +@echo off +echo 启动数学学习系统后端服务器... +cd java-backend +javac math_question.java +java math_question +pause \ No newline at end of file -- 2.34.1 From 1d2587226f1f2c8641b612f7decb247ef95f003a Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Thu, 9 Oct 2025 20:34:51 +0800 Subject: [PATCH 03/30] backend --- src/java-backend/math_learn/.gitignore | 30 + src/java-backend/math_learn/.idea/.gitignore | 8 + src/java-backend/math_learn/.idea/misc.xml | 6 + src/java-backend/math_learn/.idea/modules.xml | 8 + src/java-backend/math_learn/.idea/vcs.xml | 6 + src/java-backend/math_learn/math_learn.iml | 11 + .../2025-10-09-19-22-22_score_100.0.txt | 64 ++ .../math_learn/src/com/mathlearn/Main.java | 829 ++++++++++++++++++ .../generator/JuniorHighGenerator.java | 221 +++++ .../generator/PrimarySchoolGenerator.java | 219 +++++ .../generator/QuestionGenerator.java | 8 + .../generator/SeniorHighGenerator.java | 425 +++++++++ .../generator/StableQuestionGenerator.java | 107 +++ .../com/mathlearn/model/api/ApiResponse.java | 17 + .../src/com/mathlearn/model/exam/Exam.java | 46 + .../com/mathlearn/model/exam/Question.java | 19 + .../com/mathlearn/model/user/UserAccount.java | 49 ++ 17 files changed, 2073 insertions(+) create mode 100644 src/java-backend/math_learn/.gitignore create mode 100644 src/java-backend/math_learn/.idea/.gitignore create mode 100644 src/java-backend/math_learn/.idea/misc.xml create mode 100644 src/java-backend/math_learn/.idea/modules.xml create mode 100644 src/java-backend/math_learn/.idea/vcs.xml create mode 100644 src/java-backend/math_learn/math_learn.iml create mode 100644 src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt create mode 100644 src/java-backend/math_learn/src/com/mathlearn/Main.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.java create mode 100644 src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java diff --git a/src/java-backend/math_learn/.gitignore b/src/java-backend/math_learn/.gitignore new file mode 100644 index 0000000..13275f1 --- /dev/null +++ b/src/java-backend/math_learn/.gitignore @@ -0,0 +1,30 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ +.kotlin + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/.gitignore b/src/java-backend/math_learn/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/src/java-backend/math_learn/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/src/java-backend/math_learn/.idea/misc.xml b/src/java-backend/math_learn/.idea/misc.xml new file mode 100644 index 0000000..6f29fee --- /dev/null +++ b/src/java-backend/math_learn/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml new file mode 100644 index 0000000..422d56a --- /dev/null +++ b/src/java-backend/math_learn/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/vcs.xml b/src/java-backend/math_learn/.idea/vcs.xml new file mode 100644 index 0000000..c2365ab --- /dev/null +++ b/src/java-backend/math_learn/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/math_learn.iml b/src/java-backend/math_learn/math_learn.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/src/java-backend/math_learn/math_learn.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt b/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt new file mode 100644 index 0000000..67cd00c --- /dev/null +++ b/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt @@ -0,0 +1,64 @@ +考试ID: 20251009192152 +考试时间: 2025-10-09 19:21:52 +得分: 100.0分 + +1. 20 ÷ 5 - 3 = ? + A. 9 + B. 0 + C. 3 + D. [正确答案] 1 + +2. 10 ÷ 5 = ? + A. 12 + B. 1 + C. 0 + D. [正确答案] 2 + +3. 7 - 7 + 27 = ? + A. 34 + B. [正确答案] 27 + C. 18 + D. 23 + +4. 48 - 18 = ? + A. 33 + B. [正确答案] 30 + C. 28 + D. 39 + +5. 10 - 9 = ? + A. [正确答案] 1 + B. 10 + C. 3 + D. 0 + +6. 2 × 4 × 1 = ? + A. 0 + B. 12 + C. 4 + D. [正确答案] 8 + +7. 45 + 46 × 1 = ? + A. [正确答案] 91 + B. 101 + C. 88 + D. 89 + +8. 4 × 1 + 39 = ? + A. 40 + B. 45 + C. 41 + D. [正确答案] 43 + +9. 28 ÷ 1 = ? + A. [正确答案] 28 + B. 33 + C. 35 + D. 23 + +10. 47 × 5 = ? + A. 226 + B. 243 + C. [正确答案] 235 + D. 228 + diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main.java b/src/java-backend/math_learn/src/com/mathlearn/Main.java new file mode 100644 index 0000000..543d29a --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/Main.java @@ -0,0 +1,829 @@ +package com.mathlearn; + +import com.mathlearn.generator.*; +import com.mathlearn.model.api.ApiResponse; +import com.mathlearn.model.exam.Exam; +import com.mathlearn.model.exam.Question; +import com.mathlearn.model.user.UserAccount; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +import java.io.*; +import java.net.InetSocketAddress; +import java.text.SimpleDateFormat; +import java.util.*; + +// 主系统类 - 改造为HTTP服务器 +public class Main { + private Map accounts; + private Map pendingRegistrations; // 待完成注册的用户 + private Map userExams; // 用户当前试卷 + private Map userSessions; // 用户会话 + private String baseDirectory = "math_questions"; + private Random random = new Random(); + + public Main() { + initializeAccounts(); + pendingRegistrations = new HashMap<>(); + userExams = new HashMap<>(); + userSessions = new HashMap<>(); + createBaseDirectory(); + } + + // 初始化预设账户 + private void initializeAccounts() { + accounts = new HashMap<>(); + + // 小学账号 + accounts.put("张三1", new UserAccount("张三1", "Abc123", "小学")); + accounts.put("张三2", new UserAccount("张三2", "Abc123", "小学")); + accounts.put("张三3", new UserAccount("张三3", "Abc123", "小学")); + + // 初中账号 + accounts.put("李四1", new UserAccount("李四1", "Abc123", "初中")); + accounts.put("李四2", new UserAccount("李四2", "Abc123", "初中")); + accounts.put("李四3", new UserAccount("李四3", "Abc123", "初中")); + + // 高中账号 + accounts.put("王五1", new UserAccount("王五1", "Abc123", "高中")); + accounts.put("王五2", new UserAccount("王五2", "Abc123", "高中")); + accounts.put("王五3", new UserAccount("王五3", "Abc123", "高中")); + } + + // 创建基础目录 + private void createBaseDirectory() { + File dir = new File(baseDirectory); + if (!dir.exists()) { + dir.mkdir(); + } + } + + // 生成注册码 + public String generateRegistrationCode(String email) { + String code = "REG" + random.nextInt(10000); + pendingRegistrations.put(email, new UserAccount(email, code)); + return code; + } + + // 用户注册 - 修改以保存邮箱 + public ApiResponse register(String email, String registrationCode, String username, String password, String confirmPassword, String userType) { + System.out.println("处理注册请求: " + username + ", 邮箱: " + email); + + // 验证注册码 + if (!pendingRegistrations.containsKey(email) || + !pendingRegistrations.get(email).getRegistrationCode().equals(registrationCode)) { + return new ApiResponse(false, "无效的注册码", null); + } + + // 验证用户名是否已存在 + if (accounts.containsKey(username)) { + return new ApiResponse(false, "用户名已存在", null); + } + + // 验证密码 + if (!password.equals(confirmPassword)) { + return new ApiResponse(false, "两次输入的密码不匹配", null); + } + + if (!isValidPassword(password)) { + return new ApiResponse(false, "密码必须为6-10位,且包含大小写字母和数字", null); + } + + // 验证用户类型 + if (!userType.equals("小学") && !userType.equals("初中") && !userType.equals("高中")) { + return new ApiResponse(false, "无效的用户类型", null); + } + + // 创建用户账户并保存邮箱 + UserAccount newAccount = new UserAccount(username, password, userType, email); + accounts.put(username, newAccount); + pendingRegistrations.remove(email); + + System.out.println("注册成功: " + username); + return new ApiResponse(true, "注册成功", null); + } + // 在math_question类中添加发送注册码的方法 + public ApiResponse sendRegistrationCode(String email) { + System.out.println("收到发送注册码请求,邮箱: " + email); + + // 验证邮箱格式 + if (!isValidEmail(email)) { + return new ApiResponse(false, "无效的邮箱格式", null); + } + + // 检查邮箱是否已注册 + for (UserAccount account : accounts.values()) { + if (email.equals(account.getEmail())) { + return new ApiResponse(false, "该邮箱已被注册", null); + } + } + + // 生成注册码 + String code = generateRegistrationCode(email); + + // 模拟发送邮件 + System.out.println("=== 邮件发送模拟 ==="); + System.out.println("收件人: " + email); + System.out.println("验证码: " + code); + System.out.println("=== 邮件发送完成 ==="); + + Map data = new HashMap<>(); + data.put("email", email); + // 注意:实际生产中不应该返回验证码,这里仅用于演示和测试 + data.put("debugCode", code); + + return new ApiResponse(true, "验证码已发送到您的邮箱", data); + } + + // 验证邮箱格式 + private boolean isValidEmail(String email) { + if (email == null) return false; + String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; + return email.matches(emailRegex); + } + + + + + // 验证密码格式 + private boolean isValidPassword(String password) { + if (password.length() < 6 || password.length() > 10) { + return false; + } + + boolean hasUpper = false; + boolean hasLower = false; + boolean hasDigit = false; + + for (char c : password.toCharArray()) { + if (Character.isUpperCase(c)) hasUpper = true; + if (Character.isLowerCase(c)) hasLower = true; + if (Character.isDigit(c)) hasDigit = true; + } + + return hasUpper && hasLower && hasDigit; + } + + // 用户登录 + public ApiResponse login(String username, String password) { + UserAccount account = accounts.get(username); + if (account != null && account.getPassword().equals(password)) { + // 生成会话ID + String sessionId = generateSessionId(); + userSessions.put(sessionId, username); + + Map data = new HashMap<>(); + data.put("sessionId", sessionId); + data.put("userType", account.getUserType()); + data.put("username", username); + + return new ApiResponse(true, "登录成功", data); + } + return new ApiResponse(false, "用户名或密码错误", null); + } + + // 生成会话ID + private String generateSessionId() { + return "SESS" + System.currentTimeMillis() + random.nextInt(1000); + } + + // 验证会话 + private String validateSession(String sessionId) { + return userSessions.get(sessionId); + } + + // 修改密码 + public ApiResponse changePassword(String sessionId, String oldPassword, String newPassword, String confirmPassword) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + UserAccount account = accounts.get(username); + if (!account.getPassword().equals(oldPassword)) { + return new ApiResponse(false, "原密码错误", null); + } + + if (!newPassword.equals(confirmPassword)) { + return new ApiResponse(false, "两次输入的新密码不匹配", null); + } + + if (!isValidPassword(newPassword)) { + return new ApiResponse(false, "新密码必须为6-10位,且包含大小写字母和数字", null); + } + + account.setPassword(newPassword); + return new ApiResponse(true, "密码修改成功", null); + } + + // 生成试卷 - 添加详细日志 + public ApiResponse generateExam(String sessionId, String userType, int questionCount) { + System.out.println("🚀 === 开始生成试卷 ==="); + System.out.println("📅 时间: " + new Date()); + System.out.println("👤 用户: " + validateSession(sessionId)); + System.out.println("🎯 类型: " + userType); + System.out.println("📊 数量: " + questionCount); + + try { + String username = validateSession(sessionId); + if (username == null) { + System.out.println("❌ 会话验证失败"); + return new ApiResponse(false, "会话无效或已过期", null); + } + + if (questionCount < 10 || questionCount > 30) { + return new ApiResponse(false, "题目数量应在10-30之间", null); + } + + // 获取题目生成器 + QuestionGenerator generator = getQuestionGenerator(userType); + if (generator == null) { + return new ApiResponse(false, "无效的用户类型", null); + } + + System.out.println("✅ 开始生成题目..."); + + // 完全移除去重逻辑,先保证能生成题目 + List questions = new ArrayList<>(); + + for (int i = 0; i < questionCount; i++) { + System.out.println("🔄 尝试生成第 " + (i + 1) + " 题..."); + + try { + Question question = generator.generateQuestion(); + if (question == null) { + System.out.println("❌ 第 " + (i + 1) + " 题生成返回了null"); + continue; + } + + questions.add(question); + System.out.println("✅ 第 " + (i + 1) + " 题: " + question.getQuestionText()); + System.out.println(" 选项: " + question.getOptions()); + System.out.println(" 答案: " + question.getCorrectAnswerIndex()); + + } catch (Exception e) { + System.err.println("💥 生成第 " + (i + 1) + " 题时发生异常: " + e.getMessage()); + e.printStackTrace(); + // 继续生成下一题,不要因为一题失败就停止 + } + + // 添加小延迟,避免快速循环问题 + Thread.sleep(50); + } + + if (questions.isEmpty()) { + System.err.println("💥 严重错误:一道题目都没有生成成功!"); + return new ApiResponse(false, "无法生成任何题目,请检查系统配置", null); + } + + System.out.println("🎉 题目生成完成,共 " + questions.size() + " 题"); + + // 创建试卷 + Exam exam = new Exam(questions); + userExams.put(sessionId, exam); + + // 返回第一题 + Map data = new HashMap<>(); + data.put("examId", exam.getExamId()); + data.put("totalQuestions", questions.size()); // 使用实际生成的数量 + data.put("currentQuestion", 0); + data.put("question", questions.get(0).getQuestionText()); + data.put("options", questions.get(0).getOptions()); + + System.out.println("✅ === 试卷生成成功 ==="); + return new ApiResponse(true, "试卷生成成功", data); + + } catch (Exception e) { + System.err.println("💥 生成试卷时发生严重异常: " + e.getMessage()); + e.printStackTrace(); + return new ApiResponse(false, "系统错误: " + e.getMessage(), null); + } + } + + + + // 获取题目 + public ApiResponse getQuestion(String sessionId, int questionIndex) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + List questions = exam.getQuestions(); + if (questionIndex < 0 || questionIndex >= questions.size()) { + return new ApiResponse(false, "无效的题目索引", null); + } + + Question question = questions.get(questionIndex); + + Map data = new HashMap<>(); + data.put("examId", exam.getExamId()); + data.put("totalQuestions", questions.size()); + data.put("currentQuestion", questionIndex); + data.put("question", question.getQuestionText()); + data.put("options", question.getOptions()); + data.put("userAnswer", exam.getUserAnswers().get(questionIndex)); + + return new ApiResponse(true, "获取题目成功", data); + } + + // 提交答案 + public ApiResponse submitAnswer(String sessionId, int questionIndex, int answerIndex) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + exam.setAnswer(questionIndex, answerIndex); + + Map data = new HashMap<>(); + data.put("currentQuestion", questionIndex); + + return new ApiResponse(true, "答案提交成功", data); + } + + // 完成考试 + public ApiResponse finishExam(String sessionId) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + double score = exam.calculateScore(); + + // 保存考试记录 + saveExamResult(username, exam, score); + + // 移除当前考试 + userExams.remove(sessionId); + + Map data = new HashMap<>(); + data.put("score", score); + data.put("totalQuestions", exam.getQuestions().size()); + + return new ApiResponse(true, "考试完成", data); + } + + // 保存考试结果 + private void saveExamResult(String username, Exam exam, double score) { + String userDir = baseDirectory + File.separator + username; + File dir = new File(userDir); + if (!dir.exists()) { + dir.mkdir(); + } + + String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String filename = userDir + File.separator + timestamp + "_score_" + String.format("%.1f", score) + ".txt"; + + try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) { + writer.println("考试ID: " + exam.getExamId()); + writer.println("考试时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(exam.getStartTime())); + writer.println("得分: " + String.format("%.1f", score) + "分"); + writer.println(); + + List questions = exam.getQuestions(); + List userAnswers = exam.getUserAnswers(); + + for (int i = 0; i < questions.size(); i++) { + Question q = questions.get(i); + writer.println((i + 1) + ". " + q.getQuestionText()); + List options = q.getOptions(); + for (int j = 0; j < options.size(); j++) { + String prefix = (j == q.getCorrectAnswerIndex()) ? "[正确答案] " : + (j == userAnswers.get(i)) ? "[您的答案] " : ""; + writer.println(" " + (char)('A' + j) + ". " + prefix + options.get(j)); + } + writer.println(); + } + } catch (IOException e) { + System.out.println("保存考试结果失败: " + e.getMessage()); + } + } + + // 获取对应的题目生成器 + private QuestionGenerator getQuestionGenerator(String userType) { + System.out.println("🎯 为类型 '" + userType + "' 选择题目生成器"); + switch (userType) { + case "小学": + System.out.println("使用修复后的小学题目生成器 - 支持1-5个操作数"); + return new PrimarySchoolGenerator(); + case "初中": + System.out.println("使用修复后的初中题目生成器"); + return new JuniorHighGenerator(); + case "高中": + System.out.println("使用修复后的高中题目生成器"); + return new SeniorHighGenerator(); + default: + System.out.println("未知用户类型,使用稳定生成器"); + return new StableQuestionGenerator(); + } + } + + // 退出登录 + // 在logout方法中添加更详细的日志 + public ApiResponse logout(String sessionId) { + System.out.println("=== 退出登录处理 ==="); + System.out.println("请求的sessionId: " + sessionId); + System.out.println("当前活跃会话: " + userSessions.keySet()); + + String username = userSessions.remove(sessionId); + userExams.remove(sessionId); + + System.out.println("移除的用户名: " + username); + System.out.println("移除后活跃会话: " + userSessions.keySet()); + + // 即使sessionId无效,也返回成功,确保前端可以继续流程 + if (username != null) { + System.out.println("退出登录成功 - 用户: " + username); + return new ApiResponse(true, "退出成功", null); + } else { + System.out.println("退出登录 - sessionId无效,但返回成功"); + return new ApiResponse(true, "退出成功", null); + } + } + + // 启动HTTP服务器 + public void startServer(int port) throws IOException { + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + + // 注册端点 + server.createContext("/api/register", new RegisterHandler()); + server.createContext("/api/login", new LoginHandler()); + server.createContext("/api/change-password", new ChangePasswordHandler()); + server.createContext("/api/generate-exam", new GenerateExamHandler()); + server.createContext("/api/get-question", new GetQuestionHandler()); + server.createContext("/api/submit-answer", new SubmitAnswerHandler()); + server.createContext("/api/finish-exam", new FinishExamHandler()); + server.createContext("/api/logout", new LogoutHandler()); + // 添加新的注册码相关端点 + server.createContext("/api/send-registration-code", new SendRegistrationCodeHandler()); + + server.setExecutor(null); + server.start(); + + System.out.println("数学学习系统服务器已启动,端口: " + port); + } + + // 内部HTTP处理器类 + private abstract class BaseHandler implements HttpHandler { + protected Map parseFormData(String formData) { + Map params = new HashMap<>(); + if (formData != null && !formData.isEmpty()) { + String[] pairs = formData.split("&"); + for (String pair : pairs) { + String[] keyValue = pair.split("="); + if (keyValue.length == 2) { + try { + params.put(keyValue[0], java.net.URLDecoder.decode(keyValue[1], "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + } + return params; + } + + protected void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException { + exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8"); + exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*"); + exchange.getResponseHeaders().set("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + exchange.getResponseHeaders().set("Access-Control-Allow-Headers", "Content-Type"); + + exchange.sendResponseHeaders(statusCode, response.getBytes("UTF-8").length); + OutputStream os = exchange.getResponseBody(); + os.write(response.getBytes("UTF-8")); + os.close(); + } + + protected String toJson(ApiResponse response) { + // 简化的JSON序列化,实际应用中可以使用Jackson等库 + return "{\"success\":" + response.isSuccess() + + ",\"message\":\"" + response.getMessage() + "\"" + + ",\"data\":" + objectToJson(response.getData()) + "}"; + } + + private String objectToJson(Object obj) { + if (obj == null) return "null"; + if (obj instanceof Map) { + Map map = (Map) obj; + StringBuilder sb = new StringBuilder("{"); + boolean first = true; + for (Map.Entry entry : map.entrySet()) { + if (!first) sb.append(","); + sb.append("\"").append(entry.getKey()).append("\":"); + sb.append(objectToJson(entry.getValue())); + first = false; + } + sb.append("}"); + return sb.toString(); + } else if (obj instanceof List) { + List list = (List) obj; + StringBuilder sb = new StringBuilder("["); + boolean first = true; + for (Object item : list) { + if (!first) sb.append(","); + sb.append(objectToJson(item)); + first = false; + } + sb.append("]"); + return sb.toString(); + } else if (obj instanceof String) { + return "\"" + obj.toString().replace("\"", "\\\"") + "\""; + } else { + return obj.toString(); + } + } + } + + private class RegisterHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String email = params.get("email"); + String registrationCode = params.get("registrationCode"); + String username = params.get("username"); + String password = params.get("password"); + String confirmPassword = params.get("confirmPassword"); + String userType = params.get("userType"); + + ApiResponse response = register(email, registrationCode, username, password, confirmPassword, userType); + sendResponse(exchange, 200, toJson(response)); + } + } + + private class LoginHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String username = params.get("username"); + String password = params.get("password"); + + ApiResponse response = login(username, password); + sendResponse(exchange, 200, toJson(response)); + } + } + + //处理器都正确实现 + private class GenerateExamHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + String userType = params.get("userType"); + int questionCount = Integer.parseInt(params.get("questionCount")); + + ApiResponse response = generateExam(sessionId, userType, questionCount); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "生成试卷失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class GetQuestionHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + int questionIndex = Integer.parseInt(params.get("questionIndex")); + + ApiResponse response = getQuestion(sessionId, questionIndex); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "获取题目失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class SubmitAnswerHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + int questionIndex = Integer.parseInt(params.get("questionIndex")); + int answerIndex = Integer.parseInt(params.get("answerIndex")); + + ApiResponse response = submitAnswer(sessionId, questionIndex, answerIndex); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "提交答案失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class FinishExamHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + + ApiResponse response = finishExam(sessionId); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "完成考试失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class ChangePasswordHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + String oldPassword = params.get("oldPassword"); + String newPassword = params.get("newPassword"); + String confirmPassword = params.get("confirmPassword"); + + ApiResponse response = changePassword(sessionId, oldPassword, newPassword, confirmPassword); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "修改密码失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class LogoutHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + + ApiResponse response = logout(sessionId); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "退出登录失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + // 发送注册码的处理器 + private class SendRegistrationCodeHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + System.out.println("处理发送注册码请求"); + + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + System.out.println("请求体: " + requestBody); + + Map params = parseFormData(requestBody); + String email = params.get("email"); + + System.out.println("解析到的邮箱: " + email); + + ApiResponse response = sendRegistrationCode(email); + System.out.println("发送响应: " + toJson(response)); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + System.err.println("发送注册码时发生错误: " + e.getMessage()); + e.printStackTrace(); + ApiResponse errorResponse = new ApiResponse(false, "获取验证码失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + + public static void main(String[] args) { + try { + Main system = new Main(); + system.startServer(8080); // 启动在8080端口 + } catch (IOException e) { + System.err.println("启动服务器失败: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java new file mode 100644 index 0000000..f10929e --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java @@ -0,0 +1,221 @@ +package com.mathlearn.generator; + +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class JuniorHighGenerator implements QuestionGenerator { + private Random random = new Random(); + + @Override + public Question generateQuestion() { + int type = random.nextInt(5); // 0-4: 五种题型 + String questionText = ""; + double correctAnswerValue = 0; + boolean isIntegerAnswer = true; + + switch (type) { + case 0: // 基本四则运算(考虑优先级) + questionText = generateArithmeticQuestion(); + correctAnswerValue = evaluateExpression(questionText.replace(" = ?", "")); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 1: // 平方运算(支持负数) + int base = random.nextInt(25) - 12; // -12到12的平方 + questionText = "(" + base + ")² = ?"; + correctAnswerValue = base * base; + break; + + case 2: // 平方根运算(完全平方数) + int square = getPerfectSquare(); + int root = (int)Math.sqrt(square); + questionText = "√" + square + " = ?"; + correctAnswerValue = root; + break; + + case 3: // 次方运算(合理大小) + int baseNum = random.nextInt(8) + 2; // 2-9 + int exponent = random.nextInt(4) + 2; // 2-5次方 + questionText = baseNum + "^" + exponent + " = ?"; + correctAnswerValue = Math.pow(baseNum, exponent); + break; + + case 4: // 带负数的简单运算 + int a = random.nextInt(20) - 10; // -10到10 + int b = random.nextInt(20) - 10; + String[] ops = {"+", "-", "×"}; + String op = ops[random.nextInt(ops.length)]; + questionText = "(" + a + ") " + op + " (" + b + ") = ?"; + correctAnswerValue = calculateSimpleOperation(a, b, op); + isIntegerAnswer = true; + break; + } + + List options = generateOptions(correctAnswerValue, isIntegerAnswer); + String correctAnswerStr = isIntegerAnswer ? + String.valueOf((int)correctAnswerValue) : + String.format("%.2f", correctAnswerValue); + int correctIndex = options.indexOf(correctAnswerStr); + + return new Question(questionText, options, correctIndex); + } + + // 生成考虑优先级的算术题目 + private String generateArithmeticQuestion() { + int operandCount = random.nextInt(3) + 2; // 2-4个操作数 + StringBuilder question = new StringBuilder(); + List tokens = new ArrayList<>(); + + // 生成操作数 + for (int i = 0; i < operandCount; i++) { + if (i > 0) { + // 随机选择运算符,考虑优先级 + String[] availableOps; + if (i == 1 && operandCount > 2) { + // 第一个运算符倾向于用乘除,确保优先级测试 + availableOps = new String[]{"×", "÷", "+", "-"}; + } else { + availableOps = new String[]{"+", "-", "×", "÷"}; + } + String op = availableOps[random.nextInt(availableOps.length)]; + tokens.add(op); + question.append(" ").append(op).append(" "); + } + + // 生成合适的操作数 + int num; + if (tokens.size() > 0 && (tokens.get(tokens.size()-1).equals("÷"))) { + // 除法:生成能整除的数 + num = generateDivisibleNumber(); + } else { + num = random.nextInt(30) + 1; // 1-30 + } + tokens.add(String.valueOf(num)); + question.append(num); + } + question.append(" = ?"); + + return question.toString(); + } + + // 生成能整除的数(用于除法运算) + private int generateDivisibleNumber() { + int[] smallNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + return smallNumbers[random.nextInt(smallNumbers.length)]; + } + + // 计算简单运算(支持负数) + private int calculateSimpleOperation(int a, int b, String op) { + switch (op) { + case "+": return a + b; + case "-": return a - b; + case "×": return a * b; + default: return a + b; + } + } + + // 计算表达式(考虑运算优先级)- 使用自定义解析器避免ScriptEngine问题 + private double evaluateExpression(String expression) { + try { + // 移除空格 + expression = expression.replaceAll(" ", ""); + + // 使用递归下降解析器计算表达式 + return evaluate(expression); + } catch (Exception e) { + System.err.println("计算表达式失败: " + expression + ", 错误: " + e.getMessage()); + return 0; + } + } + + // 递归计算表达式 + private double evaluate(String expr) { + if (expr.isEmpty()) return 0; + + // 处理加减法 + String[] plusMinus = expr.split("(?=[+-])", 2); + if (plusMinus.length > 1) { + double left = evaluate(plusMinus[0]); + double right = evaluate(plusMinus[1].substring(1)); + return plusMinus[1].charAt(0) == '+' ? left + right : left - right; + } + + // 处理乘除法 + String[] multDiv = expr.split("(?=[×÷])", 2); + if (multDiv.length > 1) { + double left = evaluateTerm(multDiv[0]); + double right = evaluateTerm(multDiv[1].substring(1)); + return multDiv[1].charAt(0) == '×' ? left * right : left / right; + } + + // 处理基本项(数字或括号表达式) + return evaluateTerm(expr); + } + + // 计算基本项 + private double evaluateTerm(String term) { + if (term.startsWith("(") && term.endsWith(")")) { + return evaluate(term.substring(1, term.length() - 1)); + } + + // 处理平方符号 + if (term.endsWith("²")) { + double base = evaluateTerm(term.substring(0, term.length() - 1)); + return base * base; + } + + try { + return Double.parseDouble(term); + } catch (NumberFormatException e) { + System.err.println("解析数字失败: " + term); + return 0; + } + } + + private int getPerfectSquare() { + int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; + return perfectSquares[random.nextInt(perfectSquares.length)]; + } + + private List generateOptions(double correctAnswer, boolean isInteger) { + List options = new ArrayList<>(); + + String correctStr = isInteger ? + String.valueOf((int)correctAnswer) : + String.format("%.2f", correctAnswer); + options.add(correctStr); + + Set used = new HashSet<>(); + used.add(correctStr); + + // 生成3个错误选项 + while (options.size() < 4) { + double wrongValue; + String wrongStr; + + do { + // 根据正确答案的大小调整变化范围 + double range = Math.max(5, Math.abs(correctAnswer) * 0.3); + double variation = (random.nextDouble() * range) + 1; + boolean positive = random.nextBoolean(); + + wrongValue = correctAnswer + (positive ? variation : -variation); + + if (isInteger) { + wrongValue = Math.round(wrongValue); + wrongStr = String.valueOf((int)wrongValue); + } else { + wrongValue = Math.round(wrongValue * 100) / 100.0; + wrongStr = String.format("%.2f", wrongValue); + } + } while (used.contains(wrongStr) || Double.isNaN(wrongValue) || Double.isInfinite(wrongValue)); + + options.add(wrongStr); + used.add(wrongStr); + } + + Collections.shuffle(options); + return options; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java new file mode 100644 index 0000000..01a4cec --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java @@ -0,0 +1,219 @@ +package com.mathlearn.generator; + +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class PrimarySchoolGenerator implements QuestionGenerator { + private Random random = new Random(); + private String[] operators = {"+", "-", "×", "÷"}; + private int maxAttempts = 100; // 最大尝试次数,避免无限循环 + + @Override + public Question generateQuestion() { + int attempts = 0; + while (attempts < maxAttempts) { + attempts++; + try { + // 生成2-3个操作数,避免太复杂 + int operandCount = random.nextInt(2) + 2; // 2-3个操作数 + StringBuilder question = new StringBuilder(); + List operands = new ArrayList<>(); + List usedOperators = new ArrayList<>(); + + // 生成操作数和运算符,确保表达式合法 + for (int i = 0; i < operandCount; i++) { + if (i > 0) { + String op = operators[random.nextInt(operators.length)]; + question.append(" ").append(op).append(" "); + usedOperators.add(op); + } + // 生成合适的操作数范围 + int num = generateSuitableNumber(i, usedOperators, operands); + question.append(num); + operands.add(num); + } + question.append(" = ?"); + + // 验证表达式合法性 + if (!isExpressionValid(operands, usedOperators)) { + continue; // 重新生成 + } + + // 计算正确答案 + int correctAnswer = calculateAnswerWithPriority(operands, usedOperators); + + // 确保结果不为负数 + if (correctAnswer < 0) { + continue; // 重新生成 + } + + // 生成选项并获取正确答案索引 + List options = generateOptions(correctAnswer); + int correctIndex = options.indexOf(String.valueOf(correctAnswer)); + + System.out.println("✅ 成功生成小学题目: " + question.toString() + " = " + correctAnswer); + return new Question(question.toString(), options, correctIndex); + + } catch (Exception e) { + System.err.println("生成小学题目失败,尝试次数: " + attempts + ", 错误: " + e.getMessage()); + // 继续尝试 + } + } + + // 如果多次尝试都失败,返回一个简单的默认题目 + System.out.println("⚠️ 使用默认小学题目"); + return new Question("2 + 3 = ?", Arrays.asList("5", "6", "4", "7"), 0); + } + + // 生成合适的数字 + private int generateSuitableNumber(int index, List operators, List operands) { + if (index == 0) { + // 第一个操作数 + return random.nextInt(50) + 1; // 1-50 + } + + // 根据前一个运算符决定当前操作数的范围 + String lastOperator = operators.get(operators.size() - 1); + switch (lastOperator) { + case "-": + // 减法:第二个操作数不能太大,避免负数 + int previous = operands.get(operands.size() - 1); + return random.nextInt(Math.min(previous, 20)) + 1; + case "÷": + // 除法:除数要小,且要能整除 + previous = operands.get(operands.size() - 1); + List divisors = findDivisors(previous); + if (!divisors.isEmpty()) { + return divisors.get(random.nextInt(divisors.size())); + } + return random.nextInt(10) + 1; // 备选 + case "×": + // 乘法:避免结果太大 + return random.nextInt(5) + 1; // 1-5 + default: + return random.nextInt(50) + 1; // 1-50 + } + } + + // 找到能整除的数 + private List findDivisors(int number) { + List divisors = new ArrayList<>(); + for (int i = 1; i <= Math.min(number, 10); i++) { + if (number % i == 0) { + divisors.add(i); + } + } + return divisors; + } + + // 验证表达式是否合法 + private boolean isExpressionValid(List operands, List operators) { + try { + // 计算中间结果,验证每一步都合法 + int result = operands.get(0); + for (int i = 0; i < operators.size(); i++) { + String op = operators.get(i); + int next = operands.get(i + 1); + + switch (op) { + case "-": + if (result < next) return false; // 减法结果不能为负 + break; + case "÷": + if (next == 0 || result % next != 0) return false; // 除数不能为0且要能整除 + break; + } + + result = applyOperation(result, op, next); + if (result < 0) return false; // 最终结果不能为负 + } + return true; + } catch (Exception e) { + return false; + } + } + + // 考虑运算优先级的计算 + private int calculateAnswerWithPriority(List operands, List operators) { + if (operands.size() == 1) return operands.get(0); + + // 先处理所有乘除法 + List processed = new ArrayList<>(); + processed.add(operands.get(0)); + + for (int i = 0; i < operators.size(); i++) { + String op = operators.get(i); + int nextOperand = operands.get(i + 1); + + if (op.equals("×") || op.equals("÷")) { + // 执行乘除运算 + int lastIndex = processed.size() - 1; + int lastValue = (Integer) processed.get(lastIndex); + int result = applyOperation(lastValue, op, nextOperand); + processed.set(lastIndex, result); + } else { + // 加减法先保留 + processed.add(op); + processed.add(nextOperand); + } + } + + // 再处理加减法 + int result = (Integer) processed.get(0); + for (int i = 1; i < processed.size(); i += 2) { + String op = (String) processed.get(i); + int nextOperand = (Integer) processed.get(i + 1); + result = applyOperation(result, op, nextOperand); + } + + return result; + } + + // 执行单个运算 + private int applyOperation(int a, String operator, int b) { + switch (operator) { + case "+": return a + b; + case "-": return a - b; // 前面已经验证不会为负 + case "×": return a * b; + case "÷": return a / b; // 前面已经验证能整除 + default: return a; + } + } + + private List generateOptions(int correctAnswer) { + List options = new ArrayList<>(); + options.add(String.valueOf(correctAnswer)); + + Set used = new HashSet<>(); + used.add(correctAnswer); + + // 生成3个错误选项 + while (options.size() < 4) { + int variation = random.nextInt(10) + 1; + boolean add = random.nextBoolean(); + int wrongAnswer = add ? correctAnswer + variation : Math.max(0, correctAnswer - variation); + + if (!used.contains(wrongAnswer) && wrongAnswer != correctAnswer) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } + + // 防止无限循环 + if (options.size() < 4 && used.size() > 10) { + // 强制添加一些选项 + for (int i = 1; i <= 3; i++) { + int forcedOption = correctAnswer + i * 2; + if (!used.contains(forcedOption)) { + options.add(String.valueOf(forcedOption)); + used.add(forcedOption); + if (options.size() >= 4) break; + } + } + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.java new file mode 100644 index 0000000..4dcc04c --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.java @@ -0,0 +1,8 @@ +package com.mathlearn.generator; + +import com.mathlearn.model.exam.Question; + +public interface QuestionGenerator { + Question generateQuestion(); + +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java new file mode 100644 index 0000000..97113ff --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java @@ -0,0 +1,425 @@ +package com.mathlearn.generator; + +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class SeniorHighGenerator implements QuestionGenerator { + private Random random = new Random(); + + @Override + public Question generateQuestion() { + int type = random.nextInt(6); // 六种题型 + String questionText = ""; + double correctAnswerValue = 0; + boolean isIntegerAnswer = true; + + switch (type) { + case 0: // 三角函数(特殊角,包括负角) + String[] trigFunctions = {"sin", "cos", "tan"}; + String func = trigFunctions[random.nextInt(trigFunctions.length)]; + int angle = getSpecialAngle(); + questionText = func + "(" + angle + "°) = ?"; + correctAnswerValue = calculateTrigValue(func, angle); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 1: // 平方根(包括非完全平方数的近似值) + if (random.nextBoolean()) { + // 完全平方数 + int square = getPerfectSquare(); + questionText = "√" + square + " = ?"; + correctAnswerValue = Math.sqrt(square); + } else { + // 非完全平方数的近似值 + int num = getNonPerfectSquare(); + questionText = "√" + num + " ≈ ?"; + correctAnswerValue = Math.sqrt(num); + isIntegerAnswer = false; + } + break; + + case 2: // 对数运算 + questionText = generateLogQuestion(); + correctAnswerValue = evaluateLogQuestion(questionText); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 3: // 复合表达式(考虑优先级) + ExpressionResult exprResult = generateCompositeExpression(); + questionText = exprResult.expression; + correctAnswerValue = exprResult.value; + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 4: // 二次方程 + int root = random.nextInt(15) - 7; // -7到7的根 + int a = 1; + int b = -2 * root; + int c = root * root; + questionText = String.format("方程 %dx² %s %dx %s %d = 0 的一个根是?", + a, b >= 0 ? "+" : "", b, c >= 0 ? "+" : "", c); + correctAnswerValue = root; + break; + + case 5: // 带指数的复合运算 + questionText = generateExponentialExpression(); + correctAnswerValue = evaluateExponentialExpression(questionText.replace(" = ?", "")); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + } + + List options = generateOptions(correctAnswerValue, isIntegerAnswer); + String correctAnswerStr = isIntegerAnswer ? + String.valueOf((int)correctAnswerValue) : + String.format("%.2f", correctAnswerValue); + int correctIndex = options.indexOf(correctAnswerStr); + + return new Question(questionText, options, correctIndex); + } + + // 表达式和结果封装类 + private static class ExpressionResult { + String expression; + double value; + + ExpressionResult(String expression, double value) { + this.expression = expression; + this.value = value; + } + } + + // 生成复合表达式并同时计算结果 + private ExpressionResult generateCompositeExpression() { + // 使用预定义的简单表达式模板,确保可计算 + String[][] templates = { + {"%d + %d × %d", "先乘后加"}, + {"%d × %d + %d", "先乘后加"}, + {"%d - %d × %d", "先乘后减"}, + {"%d × %d - %d", "先乘后减"}, + {"%d + %d ÷ %d", "先除后加"}, + {"%d ÷ %d + %d", "先除后加"}, + {"%d² + %d", "先平方后加"}, + {"%d² - %d", "先平方后减"}, + {"%d × (%d + %d)", "先加后乘"}, + {"(%d + %d) × %d", "先加后乘"} + }; + + String[] template = templates[random.nextInt(templates.length)]; + String pattern = template[0]; + String description = template[1]; + + // 生成合适的数字,确保计算有效 + int a, b, c=1; + double result = 0; + + // 根据模板类型生成合适的数字 + if (pattern.contains("÷")) { + // 除法模板:确保除数不为0且能整除 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + + // 调整数字确保除法有效 + if (pattern.startsWith("%d ÷")) { + // 第一个操作数是除法:确保b能整除a + a = b * (random.nextInt(5) + 1); // a是b的倍数 + } else if (pattern.contains("÷ %d")) { + // 其他位置的除法:确保除数不为0 + b = random.nextInt(9) + 1; // 1-9 + } + } else if (pattern.contains("²")) { + // 平方模板 + a = random.nextInt(10) + 1; // 1-10 + b = random.nextInt(20) + 1; // 1-20 + result = a * a + (pattern.contains("+") ? b : -b); + } else if (pattern.contains("(")) { + // 括号模板 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + result = pattern.contains("× (") ? a * (b + c) : (a + b) * c; + } else { + // 基本四则运算 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + + // 根据运算符计算结果 + if (pattern.contains("+ %d ×")) { + result = a + b * c; // a + b × c + } else if (pattern.contains("× %d +")) { + result = a * b + c; // a × b + c + } else if (pattern.contains("- %d ×")) { + result = a - b * c; // a - b × c + } else if (pattern.contains("× %d -")) { + result = a * b - c; // a × b - c + } else if (pattern.contains("+ %d ÷")) { + result = a + (double)b / c; // a + b ÷ c + } else if (pattern.contains("÷ %d +")) { + result = (double)a / b + c; // a ÷ b + c + } + } + + // 如果还没有计算结果,使用安全的表达式计算 + if (result == 0) { + result = safeEvaluateExpression(pattern, a, b, c); + } + + String expression = String.format(pattern, a, b, c) + " = ?"; + System.out.println("生成表达式: " + expression + " [规则: " + description + "] = " + result); + + return new ExpressionResult(expression, result); + } + + // 安全的表达式计算 + private double safeEvaluateExpression(String pattern, int a, int b, int c) { + try { + if (pattern.equals("%d + %d × %d")) { + return a + b * c; + } else if (pattern.equals("%d × %d + %d")) { + return a * b + c; + } else if (pattern.equals("%d - %d × %d")) { + return a - b * c; + } else if (pattern.equals("%d × %d - %d")) { + return a * b - c; + } else if (pattern.equals("%d + %d ÷ %d")) { + return a + (double)b / c; + } else if (pattern.equals("%d ÷ %d + %d")) { + return (double)a / b + c; + } else if (pattern.equals("%d² + %d")) { + return a * a + b; + } else if (pattern.equals("%d² - %d")) { + return a * a - b; + } else if (pattern.equals("%d × (%d + %d)")) { + return a * (b + c); + } else if (pattern.equals("(%d + %d) × %d")) { + return (a + b) * c; + } + } catch (Exception e) { + System.err.println("计算表达式失败: " + String.format(pattern, a, b, c) + ", 错误: " + e.getMessage()); + } + return 0; + } + + // 获取特殊角度(包括负角) + private int getSpecialAngle() { + int[] angles = {-360, -270, -180, -135, -120, -90, -60, -45, -30, 0, + 30, 45, 60, 90, 120, 135, 180, 270, 360}; + return angles[random.nextInt(angles.length)]; + } + + // 获取非完全平方数 + private int getNonPerfectSquare() { + int[] nonSquares = {2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20}; + return nonSquares[random.nextInt(nonSquares.length)]; + } + + // 生成对数题目 + private String generateLogQuestion() { + if (random.nextBoolean()) { + // 简单对数:log₁₀ + int value = (int)Math.pow(10, random.nextInt(4)); // 1, 10, 100, 1000 + return "log₁₀" + value + " = ?"; + } else { + // 以2为底的对数 + int value = (int)Math.pow(2, random.nextInt(6) + 1); // 2,4,8,16,32,64 + return "log₂" + value + " = ?"; + } + } + + // 计算对数题目 + private double evaluateLogQuestion(String question) { + if (question.startsWith("log₁₀")) { + int value = Integer.parseInt(question.replace("log₁₀", "").replace(" = ?", "")); + return Math.log10(value); + } else if (question.startsWith("log₂")) { + int value = Integer.parseInt(question.replace("log₂", "").replace(" = ?", "")); + return Math.log(value) / Math.log(2); + } + return 0; + } + + // 生成指数表达式 + private String generateExponentialExpression() { + int base = random.nextInt(5) + 2; // 2-6 + int exponent = random.nextInt(4) + 2; // 2-5 + return base + "^" + exponent + " = ?"; + } + + // 计算指数表达式 + private double evaluateExponentialExpression(String expr) { + String cleanExpr = expr.replace(" = ?", ""); + String[] parts = cleanExpr.split("\\^"); + int base = Integer.parseInt(parts[0]); + int exponent = Integer.parseInt(parts[1]); + return Math.pow(base, exponent); + } + + private double calculateTrigValue(String function, int angle) { + // 规范化角度到0-360度 + angle = angle % 360; + if (angle < 0) angle += 360; + + // 特殊角的精确值 + switch (angle) { + case 0: + if (function.equals("sin")) return 0; + if (function.equals("cos")) return 1; + if (function.equals("tan")) return 0; + break; + case 30: + if (function.equals("sin")) return 0.5; + if (function.equals("cos")) return Math.sqrt(3)/2; + if (function.equals("tan")) return 1/Math.sqrt(3); + break; + case 45: + double sqrt2 = Math.sqrt(2); + if (function.equals("sin")) return sqrt2/2; + if (function.equals("cos")) return sqrt2/2; + if (function.equals("tan")) return 1; + break; + case 60: + if (function.equals("sin")) return Math.sqrt(3)/2; + if (function.equals("cos")) return 0.5; + if (function.equals("tan")) return Math.sqrt(3); + break; + case 90: + if (function.equals("sin")) return 1; + if (function.equals("cos")) return 0; + if (function.equals("tan")) return Double.POSITIVE_INFINITY; + break; + case 120: + if (function.equals("sin")) return Math.sqrt(3)/2; + if (function.equals("cos")) return -0.5; + if (function.equals("tan")) return -Math.sqrt(3); + break; + case 135: + double sqrt22 = Math.sqrt(2)/2; + if (function.equals("sin")) return sqrt22; + if (function.equals("cos")) return -sqrt22; + if (function.equals("tan")) return -1; + break; + case 150: + if (function.equals("sin")) return 0.5; + if (function.equals("cos")) return -Math.sqrt(3)/2; + if (function.equals("tan")) return -1/Math.sqrt(3); + break; + case 180: + if (function.equals("sin")) return 0; + if (function.equals("cos")) return -1; + if (function.equals("tan")) return 0; + break; + case 270: + if (function.equals("sin")) return -1; + if (function.equals("cos")) return 0; + if (function.equals("tan")) return Double.NEGATIVE_INFINITY; + break; + } + + // 对于非特殊角,使用近似计算 + double rad = Math.toRadians(angle); + switch (function) { + case "sin": + return Math.round(Math.sin(rad) * 100) / 100.0; + case "cos": + return Math.round(Math.cos(rad) * 100) / 100.0; + case "tan": + if (angle % 180 == 90) { + return angle % 360 == 90 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; + } + double result = Math.tan(rad); + return Math.round(result * 100) / 100.0; + default: + return 0; + } + } + + private int getPerfectSquare() { + int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; + return perfectSquares[random.nextInt(perfectSquares.length)]; + } + + private List generateOptions(double correctAnswer, boolean isInteger) { + List options = new ArrayList<>(); + + String correctStr; + if (Double.isInfinite(correctAnswer)) { + correctStr = correctAnswer > 0 ? "∞" : "-∞"; + } else if (Double.isNaN(correctAnswer)) { + correctStr = "无解"; + } else { + correctStr = isInteger ? + String.valueOf((int)correctAnswer) : + String.format("%.2f", correctAnswer); + } + options.add(correctStr); + + Set used = new HashSet<>(); + used.add(correctStr); + + // 生成3个错误选项 + int attempts = 0; + while (options.size() < 4 && attempts < 50) { + attempts++; + double wrongValue; + String wrongStr; + + // 根据正确答案调整变化范围 + double baseRange; + if (Double.isInfinite(correctAnswer) || Double.isNaN(correctAnswer)) { + baseRange = 5; + } else { + baseRange = Math.max(2, Math.abs(correctAnswer) * 0.3); + } + + double variation = (random.nextDouble() * baseRange) + 1; + boolean positive = random.nextBoolean(); + + if (Double.isInfinite(correctAnswer)) { + wrongValue = random.nextDouble() * 10 - 5; // -5到5的随机数 + } else if (Double.isNaN(correctAnswer)) { + wrongValue = random.nextDouble() * 10; // 0到10的随机数 + } else { + wrongValue = correctAnswer + (positive ? variation : -variation); + } + + if (Double.isInfinite(wrongValue)) { + wrongStr = wrongValue > 0 ? "∞" : "-∞"; + } else if (Double.isNaN(wrongValue)) { + wrongStr = "无解"; + } else if (isInteger) { + wrongValue = Math.round(wrongValue); + wrongStr = String.valueOf((int)wrongValue); + } else { + wrongValue = Math.round(wrongValue * 100) / 100.0; + wrongStr = String.format("%.2f", wrongValue); + } + + if (!used.contains(wrongStr)) { + options.add(wrongStr); + used.add(wrongStr); + } + } + + // 如果选项不够,添加一些固定选项 + while (options.size() < 4) { + String extraOption; + if (isInteger) { + int extraValue = (int)correctAnswer + options.size() * 2 + 1; + extraOption = String.valueOf(extraValue); + } else { + double extraValue = correctAnswer + options.size() * 0.5 + 0.1; + extraOption = String.format("%.2f", extraValue); + } + + if (!used.contains(extraOption)) { + options.add(extraOption); + used.add(extraOption); + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java new file mode 100644 index 0000000..ace3ab1 --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java @@ -0,0 +1,107 @@ +package com.mathlearn.generator; +//稳定生成器 +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class StableQuestionGenerator implements QuestionGenerator { + private Random random = new Random(); + private int questionCounter = 0; + + @Override + public Question generateQuestion() { + questionCounter++; + System.out.println(" 🔧 生成第 " + questionCounter + " 道题目..."); + + try { + // 极度简化的题目生成,确保不会卡住 + int a = random.nextInt(20) + 1; + int b = random.nextInt(20) + 1; + + // 随机选择运算符 + String[] operators = {"+", "-", "×"}; + String operator = operators[random.nextInt(operators.length)]; + + String questionText; + int correctAnswer; + + switch (operator) { + case "+": + questionText = a + " + " + b + " = ?"; + correctAnswer = a + b; + break; + case "-": + // 确保减法结果不为负数 + int larger = Math.max(a, b); + int smaller = Math.min(a, b); + questionText = larger + " - " + smaller + " = ?"; + correctAnswer = larger - smaller; + break; + case "×": + // 简化乘法,避免过大数字 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + questionText = a + " × " + b + " = ?"; + correctAnswer = a * b; + break; + default: + questionText = a + " + " + b + " = ?"; + correctAnswer = a + b; + } + + // 生成稳定的选项 + List options = generateStableOptions(correctAnswer); + + System.out.println(" ✅ 题目生成成功: " + questionText); + return new Question(questionText, options, 0); // 第一个选项是正确答案 + + } catch (Exception e) { + System.err.println(" 💥 题目生成过程中发生异常: " + e.getMessage()); + // 返回一个默认题目,确保不卡住 + return new Question("1 + 1 = ?", Arrays.asList("2", "3", "4", "5"), 0); + } + } + + private List generateStableOptions(int correctAnswer) { + List options = new ArrayList<>(); + options.add(String.valueOf(correctAnswer)); + + // 生成3个稳定的错误选项 + Set used = new HashSet<>(); + used.add(correctAnswer); + + int[] variations = {1, 2, 3, 5, 7, 10}; // 固定的变化量 + + for (int i = 0; i < 3 && options.size() < 4; i++) { + int variation = variations[i % variations.length]; + boolean addVariation = random.nextBoolean(); + + int wrongAnswer = addVariation ? correctAnswer + variation : correctAnswer - variation; + + // 确保不为负数且不重复 + if (wrongAnswer > 0 && !used.contains(wrongAnswer)) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } else { + // 如果生成失败,使用备选方案 + wrongAnswer = correctAnswer + (i + 1) * 2; + if (!used.contains(wrongAnswer)) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } + } + } + + // 如果选项还不够,用固定值补全 + while (options.size() < 4) { + int filler = correctAnswer + options.size() * 5 + 1; + if (!used.contains(filler)) { + options.add(String.valueOf(filler)); + used.add(filler); + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java b/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java new file mode 100644 index 0000000..97e218a --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java @@ -0,0 +1,17 @@ +package com.mathlearn.model.api; + +public class ApiResponse { + private boolean success; + private String message; + private Object data; + + public ApiResponse(boolean success, String message, Object data) { + this.success = success; + this.message = message; + this.data = data; + } + + public boolean isSuccess() { return success; } + public String getMessage() { return message; } + public Object getData() { return data; } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java new file mode 100644 index 0000000..ce3c1cd --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java @@ -0,0 +1,46 @@ +package com.mathlearn.model.exam; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class Exam { + private List questions; + private List userAnswers; + private Date startTime; + private String examId; + + public Exam(List questions) { + this.questions = questions; + this.userAnswers = new ArrayList<>(); + this.startTime = new Date(); + this.examId = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + + // 初始化用户答案列表 + for (int i = 0; i < questions.size(); i++) { + userAnswers.add(-1); // -1表示未作答 + } + } + + public List getQuestions() { return questions; } + public List getUserAnswers() { return userAnswers; } + public Date getStartTime() { return startTime; } + public String getExamId() { return examId; } + + public void setAnswer(int questionIndex, int answerIndex) { + if (questionIndex >= 0 && questionIndex < userAnswers.size()) { + userAnswers.set(questionIndex, answerIndex); + } + } + + public double calculateScore() { + int correctCount = 0; + for (int i = 0; i < questions.size(); i++) { + if (userAnswers.get(i) == questions.get(i).getCorrectAnswerIndex()) { + correctCount++; + } + } + return (double) correctCount / questions.size() * 100; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.java b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.java new file mode 100644 index 0000000..eac0e02 --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.java @@ -0,0 +1,19 @@ +package com.mathlearn.model.exam; + +import java.util.List; + +public class Question { + private String questionText; + private List options; + private int correctAnswerIndex; + + public Question(String questionText, List options, int correctAnswerIndex) { + this.questionText = questionText; + this.options = options; + this.correctAnswerIndex = correctAnswerIndex; + } + + public String getQuestionText() { return questionText; } + public List getOptions() { return options; } + public int getCorrectAnswerIndex() { return correctAnswerIndex; } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java b/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java new file mode 100644 index 0000000..0760366 --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java @@ -0,0 +1,49 @@ +package com.mathlearn.model.user; + +// 用户账户类 +public class UserAccount { + private String username; + private String password; + private String userType; + private String email; // 添加邮箱字段 + private String registrationCode; + private boolean registered; + + public UserAccount(String username, String password, String userType) { + this.username = username; + this.password = password; + this.userType = userType; + this.registered = true; + } + + public UserAccount(String username, String password, String userType, String email) { + this.username = username; + this.password = password; + this.userType = userType; + this.email = email; + this.registered = true; + } + + public UserAccount(String email, String registrationCode) { + this.email = email; + this.registrationCode = registrationCode; + this.registered = false; + } + + public void completeRegistration(String username, String password, String userType) { + this.username = username; + this.password = password; + this.userType = userType; + this.registered = true; + } + + public String getUsername() { return username; } + public String getPassword() { return password; } + public String getUserType() { return userType; } + public String getRegistrationCode() { return registrationCode; } + public boolean isRegistered() { return registered; } + + public void setPassword(String password) { this.password = password; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } +} -- 2.34.1 From 729bd1ffec624477b4a87d694bd3a6268354268d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B1=AA?= <2297852620@qq.com> Date: Fri, 10 Oct 2025 19:58:40 +0800 Subject: [PATCH 04/30] =?UTF-8?q?=E9=A6=96=E6=AC=A1=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=EF=BC=9A=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pair-programming/doc/README.md | 2 + .../src/electron-frontend/package-lock.json | 3821 +++++++++++++++++ .../src/electron-frontend/package.json | 34 + .../src/electron-frontend/resources/main.js | 100 + .../electron-frontend/resources/preload.js | 129 + .../resources/renderer/login.html | 119 + .../resources/renderer/main.html | 432 ++ .../resources/renderer/quiz.html | 264 ++ .../resources/renderer/register.html | 260 ++ .../resources/renderer/result.html | 104 + .../resources/style/common.css | 118 + .../src/electron-frontend/start-backend.bat | 6 + .../src/java-backend/math_learn/.gitignore | 30 + .../java-backend/math_learn/.idea/.gitignore | 8 + .../java-backend/math_learn/.idea/misc.xml | 6 + .../java-backend/math_learn/.idea/modules.xml | 8 + .../src/java-backend/math_learn/.idea/vcs.xml | 6 + .../java-backend/math_learn/math_learn.iml | 11 + .../2025-10-09-19-22-22_score_100.0.txt | 64 + .../src/com/mathlearn/Main$BaseHandler.class | Bin 0 -> 4196 bytes .../Main$ChangePasswordHandler.class | Bin 0 -> 2465 bytes .../mathlearn/Main$FinishExamHandler.class | Bin 0 -> 2287 bytes .../mathlearn/Main$GenerateExamHandler.class | Bin 0 -> 2454 bytes .../mathlearn/Main$GetQuestionHandler.class | Bin 0 -> 2400 bytes .../src/com/mathlearn/Main$LoginHandler.class | Bin 0 -> 1669 bytes .../com/mathlearn/Main$LogoutHandler.class | Bin 0 -> 2275 bytes .../com/mathlearn/Main$RegisterHandler.class | Bin 0 -> 1894 bytes .../Main$SendRegistrationCodeHandler.class | Bin 0 -> 2772 bytes .../mathlearn/Main$SubmitAnswerHandler.class | Bin 0 -> 2443 bytes .../math_learn/src/com/mathlearn/Main.class | Bin 0 -> 16119 bytes .../math_learn/src/com/mathlearn/Main.java | 829 ++++ .../generator/JuniorHighGenerator.class | Bin 0 -> 5985 bytes .../generator/JuniorHighGenerator.java | 221 + .../generator/PrimarySchoolGenerator.class | Bin 0 -> 5880 bytes .../generator/PrimarySchoolGenerator.java | 219 + .../generator/QuestionGenerator.class | Bin 0 -> 206 bytes .../generator/QuestionGenerator.java | 8 + ...SeniorHighGenerator$ExpressionResult.class | Bin 0 -> 500 bytes .../generator/SeniorHighGenerator.class | Bin 0 -> 10033 bytes .../generator/SeniorHighGenerator.java | 425 ++ .../generator/StableQuestionGenerator.class | Bin 0 -> 3453 bytes .../generator/StableQuestionGenerator.java | 107 + .../com/mathlearn/model/api/ApiResponse.class | Bin 0 -> 637 bytes .../com/mathlearn/model/api/ApiResponse.java | 17 + .../src/com/mathlearn/model/exam/Exam.class | Bin 0 -> 2001 bytes .../src/com/mathlearn/model/exam/Exam.java | 46 + .../com/mathlearn/model/exam/Question.class | Bin 0 -> 842 bytes .../com/mathlearn/model/exam/Question.java | 19 + .../mathlearn/model/user/UserAccount.class | Bin 0 -> 1426 bytes .../com/mathlearn/model/user/UserAccount.java | 49 + 50 files changed, 7462 insertions(+) create mode 100644 pair-programming/doc/README.md create mode 100644 pair-programming/src/electron-frontend/package-lock.json create mode 100644 pair-programming/src/electron-frontend/package.json create mode 100644 pair-programming/src/electron-frontend/resources/main.js create mode 100644 pair-programming/src/electron-frontend/resources/preload.js create mode 100644 pair-programming/src/electron-frontend/resources/renderer/login.html create mode 100644 pair-programming/src/electron-frontend/resources/renderer/main.html create mode 100644 pair-programming/src/electron-frontend/resources/renderer/quiz.html create mode 100644 pair-programming/src/electron-frontend/resources/renderer/register.html create mode 100644 pair-programming/src/electron-frontend/resources/renderer/result.html create mode 100644 pair-programming/src/electron-frontend/resources/style/common.css create mode 100644 pair-programming/src/electron-frontend/start-backend.bat create mode 100644 pair-programming/src/java-backend/math_learn/.gitignore create mode 100644 pair-programming/src/java-backend/math_learn/.idea/.gitignore create mode 100644 pair-programming/src/java-backend/math_learn/.idea/misc.xml create mode 100644 pair-programming/src/java-backend/math_learn/.idea/modules.xml create mode 100644 pair-programming/src/java-backend/math_learn/.idea/vcs.xml create mode 100644 pair-programming/src/java-backend/math_learn/math_learn.iml create mode 100644 pair-programming/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$FinishExamHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$GetQuestionHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator$ExpressionResult.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.java create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class create mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java diff --git a/pair-programming/doc/README.md b/pair-programming/doc/README.md new file mode 100644 index 0000000..aacf4a3 --- /dev/null +++ b/pair-programming/doc/README.md @@ -0,0 +1,2 @@ +# Pair-Programming + diff --git a/pair-programming/src/electron-frontend/package-lock.json b/pair-programming/src/electron-frontend/package-lock.json new file mode 100644 index 0000000..cc0a9c4 --- /dev/null +++ b/pair-programming/src/electron-frontend/package-lock.json @@ -0,0 +1,3821 @@ +{ + "name": "math-learning-app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "math-learning-app", + "version": "1.0.0", + "dependencies": { + "node-fetch": "^2.7.0" + }, + "devDependencies": { + "electron": "^22.0.0", + "electron-builder": "^24.0.0" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron/asar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "dev": true, + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/asar/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/notarize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", + "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/notarize/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/notarize/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@electron/osx-sign/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/osx-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", + "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "dev": true, + "dependencies": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "22.18.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.8.tgz", + "integrity": "sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw==", + "dev": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true + }, + "node_modules/app-builder-lib": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", + "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "dev": true, + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.2.1", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.5.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.13.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "24.13.3", + "electron-builder-squirrel-windows": "24.13.3" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "peer": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "peer": true + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builder-util": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", + "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "dev": true, + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", + "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/builder-util/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "dependencies": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "peer": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "optional": true + }, + "node_modules/dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "node_modules/dir-compare/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", + "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "dev": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "22.3.27", + "resolved": "https://registry.npmjs.org/electron/-/electron-22.3.27.tgz", + "integrity": "sha512-7Rht21vHqj4ZFRnKuZdFqZFsvMBCmDqmjetiMqPtF+TmTBiGne1mnstVXOA/SRGhN2Qy5gY5bznJKpiqogjM8A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^16.11.26", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", + "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "dev": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "dmg-builder": "24.13.3", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder-squirrel-windows": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", + "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", + "dev": true, + "peer": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "archiver": "^5.3.1", + "builder-util": "24.13.1", + "fs-extra": "^10.1.0" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-publish": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", + "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-publish/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron/node_modules/@types/node": { + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "peer": true + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "peer": true + }, + "node_modules/isbinaryfile": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", + "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", + "dev": true, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "peer": true + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "peer": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "peer": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "peer": true + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "dev": true, + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "peer": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "peer": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "optional": true + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "peer": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "peer": true + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "peer": true, + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/pair-programming/src/electron-frontend/package.json b/pair-programming/src/electron-frontend/package.json new file mode 100644 index 0000000..85b1de1 --- /dev/null +++ b/pair-programming/src/electron-frontend/package.json @@ -0,0 +1,34 @@ +{ + "name": "math-learning-app", + "version": "1.0.0", + "description": "小初高数学学习软件", + "main": "src/main.js", + "scripts": { + "start": "electron .", + "dev": "electron . --dev", + "build": "electron-builder" + }, + "devDependencies": { + "electron": "^22.0.0", + "electron-builder": "^24.0.0" + }, + "build": { + "appId": "com.mathlearning.app", + "productName": "数学学习系统", + "directories": { + "output": "dist" + }, + "files": [ + "src/**/*", + "styles/**/*", + "assets/**/*" + ], + "win": { + "target": "nsis", + "icon": "assets/icon.ico" + } + }, + "dependencies": { + "node-fetch": "^2.7.0" + } +} diff --git a/pair-programming/src/electron-frontend/resources/main.js b/pair-programming/src/electron-frontend/resources/main.js new file mode 100644 index 0000000..688dacc --- /dev/null +++ b/pair-programming/src/electron-frontend/resources/main.js @@ -0,0 +1,100 @@ +const fetch = require('node-fetch'); +const { app, BrowserWindow, Menu, ipcMain } = require('electron'); +const path = require('path'); + +let mainWindow; + +function createWindow() { + mainWindow = new BrowserWindow({ + width: 1200, + height: 800, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + preload: path.join(__dirname, 'preload.js'), // 确保路径正确 + webSecurity: false // 开发时可以关闭,避免CORS问题 + }, + icon: path.join(__dirname, 'assets/icon.png') // 可选 + }); + + // 加载登录页面 + mainWindow.loadFile(path.join(__dirname, 'renderer/login.html')); + + // 开发时打开开发者工具 + mainWindow.webContents.openDevTools(); +} + +function createMenu() { + const template = [ + { + label: '文件', + submenu: [ + { + label: '退出', + click: () => app.quit() + } + ] + }, + { + label: '查看', + submenu: [ + { role: 'reload' }, + { role: 'toggleDevTools' } + ] + } + ]; + + const menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); +} + +// API 基础URL +const API_BASE_URL = 'http://localhost:8080/api'; + +// 处理API请求 +ipcMain.handle('api-request', async (event, { endpoint, method = 'POST', data = {} }) => { + try { + const url = `${API_BASE_URL}${endpoint}`; + const formData = new URLSearchParams(); + + for (const [key, value] of Object.entries(data)) { + formData.append(key, value); + } + + const response = await fetch(url, { + method: method, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: formData + }); + + const result = await response.json(); + return result; + } catch (error) { + return { + success: false, + message: `网络错误: ${error.message}`, + data: null + }; + } +}); + +// 页面导航 +ipcMain.handle('navigate-to', (event, page) => { + mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`)); +}); + +app.whenReady().then(createWindow); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } +}); \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/preload.js b/pair-programming/src/electron-frontend/resources/preload.js new file mode 100644 index 0000000..5f08f7e --- /dev/null +++ b/pair-programming/src/electron-frontend/resources/preload.js @@ -0,0 +1,129 @@ +const { contextBridge, ipcRenderer } = require('electron'); + +// 统一的会话管理器 +const SessionManager = { + // 获取当前用户会话(强制从存储读取) + getCurrentUser() { + try { + const session = localStorage.getItem('userSession'); + return session ? JSON.parse(session) : null; + } catch (error) { + console.error('获取用户会话失败:', error); + return null; + } + }, + + // 获取当前考试会话 + getCurrentExam() { + try { + const exam = localStorage.getItem('currentExam'); + return exam ? JSON.parse(exam) : null; + } catch (error) { + console.error('获取考试会话失败:', error); + return null; + } + }, + + // 清除所有会话 + clearAllSessions() { + localStorage.removeItem('userSession'); + localStorage.removeItem('currentExam'); + localStorage.removeItem('examResult'); + console.log('所有会话已清除'); + }, + + // 验证会话是否有效 + validateUserSession() { + const user = this.getCurrentUser(); + if (!user || !user.sessionId) { + return false; + } + + // 可以添加更多验证逻辑,比如检查过期时间等 + return true; + }, + + // 刷新用户会话(在修改密码等操作后) + refreshUserSession(updatedUserData) { + if (updatedUserData) { + localStorage.setItem('userSession', JSON.stringify(updatedUserData)); + } + } + +}; + +// 暴露安全的API给渲染进程 +contextBridge.exposeInMainWorld('electronAPI', { + // 页面导航 + navigateTo: (page) => ipcRenderer.invoke('navigate-to', page), + + // 存储会话数据 + setSession: (key, value) => { + localStorage.setItem(key, JSON.stringify(value)); + }, + + getSession: (key) => { + const item = localStorage.getItem(key); + return item ? JSON.parse(item) : null; + }, + + removeSession: (key) => { + localStorage.removeItem(key); + }, + + // 新增:获取当前会话状态 + getSessionState: () => { + return SessionManager.validateSession(); + }, + + // 新增:强制清除所有会话 + clearAllSessions: () => { + SessionManager.clearAllSessions(); + }, + // 新增会话验证方法 + validateSession: () => { + return SessionManager.validateUserSession(); + }, + + // 新增会话刷新方法 + refreshSession: (userData) => { + SessionManager.refreshUserSession(userData); + } +}); + +// 直接在渲染进程中暴露 API 调用函数 +contextBridge.exposeInMainWorld('api', { + request: async (endpoint, method = 'POST', data = {}) => { + try { + console.log('API Request:', endpoint, method, data); + + const url = `http://localhost:8080/api${endpoint}`; + const formData = new URLSearchParams(); + + for (const [key, value] of Object.entries(data)) { + formData.append(key, value); + } + + const response = await fetch(url, { + method: method, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: formData + }); + + const result = await response.json(); + console.log('API Response:', result); + return result; + } catch (error) { + console.error('API Error:', error); + return { + success: false, + message: `网络错误: ${error.message}`, + data: null + }; + } + } +}); + +console.log('Preload script loaded successfully'); \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/login.html b/pair-programming/src/electron-frontend/resources/renderer/login.html new file mode 100644 index 0000000..7d51f60 --- /dev/null +++ b/pair-programming/src/electron-frontend/resources/renderer/login.html @@ -0,0 +1,119 @@ + + + + + + 数学试卷自动生成系统 - 登录 + + + + + + + + + + + \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/main.html b/pair-programming/src/electron-frontend/resources/renderer/main.html new file mode 100644 index 0000000..37435c4 --- /dev/null +++ b/pair-programming/src/electron-frontend/resources/renderer/main.html @@ -0,0 +1,432 @@ + + + + + + 数学学习系统 - 主页 + + + + + +
+

数学学习系统

+ + + +
+ + + +
+ + + +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/quiz.html b/pair-programming/src/electron-frontend/resources/renderer/quiz.html new file mode 100644 index 0000000..bc7962d --- /dev/null +++ b/pair-programming/src/electron-frontend/resources/renderer/quiz.html @@ -0,0 +1,264 @@ + + + + + + 数学学习系统 - 答题 + + + + + +
+
+ +
+ +
+ +
+ +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/register.html b/pair-programming/src/electron-frontend/resources/renderer/register.html new file mode 100644 index 0000000..dbffcca --- /dev/null +++ b/pair-programming/src/electron-frontend/resources/renderer/register.html @@ -0,0 +1,260 @@ + + + + + + 数学学习系统 - 注册 + + + + + +
+

用户注册

+ +
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/result.html b/pair-programming/src/electron-frontend/resources/renderer/result.html new file mode 100644 index 0000000..a229fd5 --- /dev/null +++ b/pair-programming/src/electron-frontend/resources/renderer/result.html @@ -0,0 +1,104 @@ + + + + + + 数学学习系统 - 成绩 + + + + + +
+

考试完成

+
+ +
+

+ +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/style/common.css b/pair-programming/src/electron-frontend/resources/style/common.css new file mode 100644 index 0000000..19382d9 --- /dev/null +++ b/pair-programming/src/electron-frontend/resources/style/common.css @@ -0,0 +1,118 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + padding: 20px; +} + +.message { + padding: 10px; + margin-top: 15px; + border-radius: 5px; + text-align: center; +} + +.message.success { + background: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.message.error { + background: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +.message.info { + background: #d1ecf1; + color: #0c5460; + border: 1px solid #bee5eb; +} + +/* 基础按钮样式 */ +.btn { + padding: 10px 20px; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +/* 按钮交互效果 */ +.btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.btn:active { + transform: translateY(0); + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); +} + +/* 主按钮 - 用于主要操作 */ +.btn-primary { + background: #007acc; + color: white; +} + +.btn-primary:hover { + background: #005fa3; +} + +/* 次要按钮 - 用于辅助操作 */ +.btn-secondary { + background: #6c757d; + color: white; +} + +.btn-secondary:hover { + background: #5a6268; +} + +/* 成功按钮 - 用于提交、确认等操作 */ +.btn-success { + background: #28a745; + color: white; +} + +.btn-success:hover { + background: #218838; +} + +/* 危险按钮 - 用于删除、退出等操作 */ +.btn-danger { + background: #dc3545; + color: white; +} + +.btn-danger:hover { + background: #c82333; +} + +/* 禁用状态 */ +.btn:disabled { + opacity: 0.7; + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +/* 图标按钮样式(如果需要) */ +.btn-icon-left i { + margin-right: 8px; +} + +.btn-icon-right i { + margin-left: 8px; +} \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/start-backend.bat b/pair-programming/src/electron-frontend/start-backend.bat new file mode 100644 index 0000000..81b488e --- /dev/null +++ b/pair-programming/src/electron-frontend/start-backend.bat @@ -0,0 +1,6 @@ +@echo off +echo 启动数学学习系统后端服务器... +cd java-backend +javac math_question.java +java math_question +pause \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/.gitignore b/pair-programming/src/java-backend/math_learn/.gitignore new file mode 100644 index 0000000..13275f1 --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/.gitignore @@ -0,0 +1,30 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ +.kotlin + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/.idea/.gitignore b/pair-programming/src/java-backend/math_learn/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/pair-programming/src/java-backend/math_learn/.idea/misc.xml b/pair-programming/src/java-backend/math_learn/.idea/misc.xml new file mode 100644 index 0000000..6f29fee --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/.idea/modules.xml b/pair-programming/src/java-backend/math_learn/.idea/modules.xml new file mode 100644 index 0000000..422d56a --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/.idea/vcs.xml b/pair-programming/src/java-backend/math_learn/.idea/vcs.xml new file mode 100644 index 0000000..c2365ab --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/math_learn.iml b/pair-programming/src/java-backend/math_learn/math_learn.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/math_learn.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt b/pair-programming/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt new file mode 100644 index 0000000..67cd00c --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt @@ -0,0 +1,64 @@ +考试ID: 20251009192152 +考试时间: 2025-10-09 19:21:52 +得分: 100.0分 + +1. 20 ÷ 5 - 3 = ? + A. 9 + B. 0 + C. 3 + D. [正确答案] 1 + +2. 10 ÷ 5 = ? + A. 12 + B. 1 + C. 0 + D. [正确答案] 2 + +3. 7 - 7 + 27 = ? + A. 34 + B. [正确答案] 27 + C. 18 + D. 23 + +4. 48 - 18 = ? + A. 33 + B. [正确答案] 30 + C. 28 + D. 39 + +5. 10 - 9 = ? + A. [正确答案] 1 + B. 10 + C. 3 + D. 0 + +6. 2 × 4 × 1 = ? + A. 0 + B. 12 + C. 4 + D. [正确答案] 8 + +7. 45 + 46 × 1 = ? + A. [正确答案] 91 + B. 101 + C. 88 + D. 89 + +8. 4 × 1 + 39 = ? + A. 40 + B. 45 + C. 41 + D. [正确答案] 43 + +9. 28 ÷ 1 = ? + A. [正确答案] 28 + B. 33 + C. 35 + D. 23 + +10. 47 × 5 = ? + A. 226 + B. 243 + C. [正确答案] 235 + D. 228 + diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..353bdc304f1b1484376f7bff793065ae0e3c0462 GIT binary patch literal 4196 zcmai1dw3LA760AI?#^U0Kp05E@=TVH=Cxf*YlK~(l8``X9>@kFk5-4xm<-vS+0M-J zkYZ~s)(6%{s}{71wSsS{+NFRZ_$XSn+SY1))<-{I{e1l4AELGK+?idn%P#HrC9`+W zoO{l>=lss^+(? zm7y#<2}ey%j#z3^3!)Pd5!cFy;#CYwlV&<u|{{> zrV(!>PnNAYtMldR!fQmVkg*amhQ%-Mg%V3UE5oBGu?4_vm9UCo!P;a}v+W3v%`#Jw zwW*Z3H!^JLza(my_*?rowr%BlLo$Z3 ziRxZdvTk#Xx@#WQtAL*2tV3X=lxS)?9>iuOM2yJTf~^d5D=ASY?X`4=u;6dq(al|L z#_MHl;}G*FQ>IP8+JT)SZkBNiZ*&(}Y1NrXX{u#J)6`?BsG8BEYcqNwe1>Y>PGsFm z@a=Dup<)+9kYXRC>Zlxha|>a+{FARD*B+Ch;Z4LJq`gjc)GJlB{Od^#B z({x;es%|uQs|0J+7)x;)kWH83M$C-_Ooo=?lH^SmH)lQ|g^1ITVS@U+A+1ho1S|sh zsP0VA%63%4q57_D-CmB!a!CdI5-2pEkxivU5Y`*q8Wm-vJFBOtEhX$B=pG2d#y(Eo zRQ9^!16*zbPE`kF+=hb$Kx$5Fe}ebW>_W0#9w$+}2Djr55pR`oC*D@VY3>GzFkz{V zNzv7p?CsCX$-p7JUBulo-obI9xRJZ&3o2B?3Dq9b_BmYlT{7Oy%jz>oAmTj*x^}k^ zk2d%6XeGRt4%*2N`hFQ7z`exZ#46Mq43SDFF3WO0W5iJ(Bun8M9L9%b+|OMH2vIj_ z`?>L>-1tYXuz6J&Oxt{bK?ujV(T~eG#*Oke->RmvM1c>I!-L%VLozA1Q5p?bV{Do#mm962)g2$Dy%=vJ z2J-a~TM&f}=!Q0wP4CjI5p`FJB()y#Zc;5Ztr5VerDkOK;OH~0w8sHUi_cveW&uHQ z+T{*JLX&G)#05fGg_{HsR6-v&R3~eZ_x@Kly{bGR<&rfNfLu)D3~?_PuP}(?{pH4Z zzJix0zb)dsg@&O^LjUmPH-u^@PiZT!OngOhj#t0~xk{K>E2;JAyd2e>J+I|xB?u2` zwzI*ssbzmeUCseeT3M=Iw`n@IW2u?T^YbaX(Hscd-UtZCSZ6rx@qRcKX5r5881XuZ z4@&q6jd>Ey3gD+f{0z^E_&EpWFA7&8mkV`ck2$GDy|Q}@+@~gqornkTFRor*(Tl@F zq}@DVnv>Z~aew6TQAWLA@AA6{sR_qDM`o62zVy4E=_oSv@J$w)rifreq%Z zUA`0X9K*6{)-Q>p^Z+7$M`P~gRS6B=X?=|}9tCRiQ#8Q*wDRLLJ;q;d00n;UDQo$)7NX{TcJwUvNG9D_#3u zKo9#HM%h2Ho&6m<**~DtyK(j}e1k$Bf^Q1TAc~j}Q6r*B#CiH-bjT^(fa)^2t92es zM9U=vrYLvxqba|a?0u8|1$>JV@@;&_OApOJAE^PGC?y@rb;|WQyxLvHmDPpijmp}> zvPZd&FBe9Xc{%i+JCs8|X%F%QdZHX&7xLvWI$fU@RMYAIjT&|d_3S@rV*f=a`yW=a zmvAGS!bYm;u)y#bMd72|U8Lvt@Hnk_(PQ+D7rma`Y^VP>w9_M*!}uAbfs^#cLxDni z5d8290R#mRb+i`v4a>8`o`U7Jf7ZFfyJ=t*qO-FEB$9Xgjo`tqTUeNZIl@dV5@w-Ms6~%3 zn~I`96XqZ*%*8&T4hMvK+$l8RZebqo5kk0En2!g91vn-w#93hxE((kBl&}QP2#t7F zXu@+s7|#n!@q*Bd7ljrV(i;&JIi>?HE~!q0X`AqR2zZgN4_`tDL1hY!(<;Y{R2GX6 zE}@oG8mQpkchB+z{LuY;0zanDnRL2msOV3+&!_QAlFg^$Pv8ms$|ukTs0qIgRO2`J JEq;&C{{g`EdAa}q literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..b5329c7850143c7fe0bb18926c3368b7b2f43bb7 GIT binary patch literal 2465 zcmb7GU2qds6#niu&2G~LN}#Plh0+F0Qqtfr&>+$jY71>zNhp@8uuU$_(#>wz-Lw=$ z#}{9G)fsVc#s?kW)H)aj7|}<^cW2ZY^+Em||7V=>&GGCeX;T_uoKAP|J$uf%=X~co z=jO|Qu3Q7qhnJfmph1L3MkBlop^TA_Hp_(-}8@hL&k=AL6Hq+_Fcw zoinl&dMG@6Qkhj^8l@OZ*`}&bQ|N7I7jd7A05*`>oeGpXc~LZrp*2)vK00-hXY6?R zsDuX?;3H%=%GiVs2HE0z_7JxUhHi0&csa*=L>wQgabAhd!J(7EGd7w^O9&FMXFIuR z8fIs2XE~`3-LN|pO*7_rw)30=)K(b}A;hqHDgT6#op+$FWUm^rA-zzv=@72u34jQ? zMQoE1MGwO|7l7qDloF|C`!p>vZ*xMz6ADizny?)Yi+DuFqj-#Avumi6C6&Oms5U8^ z*rS+PqLi~IyT-%mfnz%vHk5O%Rjw$x^?1VJ(GG@9p~=L5Ylg=i(09q`MVw((!8v5W zF!TEqTOpRz7ORS9*;&z6H6nW^++64aEgB9gG5q1n)~)lQP|GzoM*wOMO8(FT!l!6-TE2vdQQ;7sTBjXTK&Rj4KSccB9>&{ND zZ(FAWMI5fu&TUNUVP3GQA|j4dx_xOz)%EH_8WS>(I@7^NRT`m+D%0FgL+?2m&*KGR ze_om4{f3@V>?5k3qm@PMbU3-Jpv#G}d`^txxWh~0Rw#7zuJ~4IF;1P*PY_a_hgF>? zi}@*Trj;p;BrW9z9#c#u&uwl}BwiX_G;JOKZXND5F~a136*XCAhR9rT>sv(65^=JM ztJBV-i(d$&luz8kQ`0A~9Ub*q^!tIOi^>(l|UYI^uutgLdz-JkPZuhtds`{)k!z%-~T!R56V;d$- zr8jH2TTv{ZSH3K);ILuL6btdY0=~>JJzwB;)F*2^R0~uis<`N?d@yjFDBH3f>{i(!Ca6`0p>_!3F>3iuf&8%--;KIpV8mo1hO{N(g_9*d;tZ64_S5&SccT`!e3 z^awvs6VrrIGd%5W ze9~%vBfs6O({YZyiG36(#>wzy(x4Y zXPn{12Osc(8TDDmH=Q~d22jQy4>F9u{|B7@0nYfwcsALzTUy1*WcTjfbH01dcfND> z-h*3r01RTO844Oy1T-|Fi6N4+iiskZ1w(M#OpJ5gjHGo_cM8Lod2xiBc|+I?O|qan zk%J67#x^=6LkOZ-MMy&nG=|+9O(H4oh&8k$bb>s}&=K7XE;bXyRt9xqa(Z+klMSH_ z+f;-#Y{w3U9v9syn+a3ML_x}uBkVZh6JcTI3*0uaoR({E)+RI+I5~F6REa?!zi$p*iy($i9=tDol z_9_AEZ73x&%?}zzYDo%WA`p$urkZgOPpf!F!?SpfVQ+yoCqZb+WL}yd~ZW)_#Nk6P%07-@|CHK&@WfzZg$w?*t zV%7Pqft96hkkCuXAYNiDO>#*SbJonP%UhQof`)p*yt6|KB561=1*21|NfV8ob$S2c`b+-+0q zgkzaixc}q3NkgcZsH>pbC)84+B#9suuX)Y4HZC@eD1;2M8m8T54H0SML@=KhVVXZP z8cyML5@V4sh#||&ad}FY1zI^I7D*CW$L}f+4|gRcJ&7}}OlBFP(KEgRcs{@R^JdwS*vX4L|S)GYj#I)znd^aFhk>O#BxY?Z7Iu=jfJ1s3nU0d?6m$D4F*qC1qEI7{nBS`r4sIlSfhKJXAf2yf}F zptXXXA7N{}cN^}8AFtramS%;(axn zWeT$&1}tiArJ6~KzBN$3hNgUjcI6H_l<&}^e2+fm2lOjH;+S$5Y2_ZW%1=0}{0u|+ z9hUM7O3JUeqWp%d${*mwLJI;N?SH#-H`9eV+6d55Il2m3D>#q&>U|gmx(Dgq0{wMd Yq^DhIAd6wxbPdwo2`G?Q#AS5;1NY~EkN^Mx literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..293b2db69ca5858fbbb3a0309b84f1f33122d2cb GIT binary patch literal 2454 zcmah~-E$LF6#w0AnoZLMN`Thl2c->=q_n{=ga(l&P#SETN=kuNh1=wsY@6(c-J8;a zh#xP$FoQEPqrUipX+_^bm8+EjQnw8P7=KVuf7MK1FN!7U>?$#o-mS{TCOQk+`h#c^(A3&LXX%Dip| z4>9bVXm*MD;X{WCzlKg|3@!m~bXWl&SoGs)Cc+K(=5 zR}s*#13MW89CW*EL=7RMc_~Y_u$F}t9jD=`l}w%+Il<7C6Y{LMQWmzH6f$pS>FA;G z#3Enj(E^!7)6&w7938zIJu05l(2L#Vw%LF}Clp?=8FqzS?x}@Ek&&_RoDVNBz)!rs zq+t*G7&KcL*|WkfnTAa#iPd6!#))G|7kK?_4iEhdp6OJ2#)lvgd%a&+mTC2m^w)yw zGfdgX3kCD4$oAiGh}y5=0748~H{y?**;R+?di1&(O&X=Lq)h}b5&;nmsyL`&2*V6J zssuc3Lm`oAcC=84uS!8octYX%cn1#QWfiYzconZP?5#Q)bmmf=~4^rIR^5M$UQ^8IjO{* ztOlPou(H$(B=u6vhc_8IY+>8FX(Y3qcnc>~jB1D@L5S6W8paH5#3)sa8@C|>SL*6Z zKAd9kl}Va2t0m#XX~L_Dk#6FuQgBYg zEY3R(!aQS}2E)y(y~$4sV85Eq_kPKGGa`3cI$B3|F9!O(%uv`&T-Qw?RCXXQ`*wv zrP@ht9~?#g`Q^8Ne17}!4|g8jT7PtR?eYEZM*7$`FP8ndiWL>B4&m1rf*Z=#jb(F5 z)H`o22V*=VO^e#oS8id}4Qu<=ZVfv)VVX3bR#AT+@@AROt!orJ6#u?ikl4kn&NI1j*3sHt^dC%38EG|`l#T1Bxcst z<=o#iQs_r_E*+6v;bVde$1d9x=LtS&sk)x-V-cT+hPvdqP5(a~g#hNcWK!^_Z zy}*{i3bs|S>uYR{3~tA7f#)lDaV@a7zWhyfncWEtILi;weUU!ws~~(2(RI8&897+N zk*T4;v7d2V!LR5Z@eBn{KAE%+1;!eapD=#d8@UhG>*;OZ<*i_9M6GTa=~XM3A^h(V zoP3D6i){q@?gLz+VAheDA|v)!WTAdihtrpHFJLA0P% zMo7VCY+>ke(CxAw*SUxngfMMx&2uY0OvA$$as^eNk3>h# zs`F~RNG9>Durz&^TyIB*j7Jo7Vk>Q1Z9t(DidwW8+9ICqV>4%YP9&nI19*%9L85h= zg6-&HP;9Q}C%A1Ix=o%WYB4^<<3!p6?)v8N(9Pf*AInY#5GG*)<2vw%1u^~dQ>YvRGZVj z#^aNzGy52})?)P~(bX9K-g=bn?F~qf-v)`xOiz!LY$}4ow+W>5wW^Qi(TN zbv|ogWuX;G>1HB;=NX!8ZrddFbiNrc;-HK{1xXAMVl|+;F+&3}%CO6eTNi;Rb?#CC zhY6u7KL=aS^9w;7!LW?9f}?nep>;)RX1eSs_IHco)_b)sl^9Pt*%^3g@mkvNgQ|T-#BU;I>Y|e6}$f4 zbt+B9iMqV11xU5ZO{dAoIOSILN+VhqHHaxpD|p%I0zry0Lzz=&d5AjOs|wEGHBxy= zo#R7>o>RpMO%!NklL`fC?}5bC3H2n-T?*nPW*q(H7$T9=YYjXr_4H3sMGO&z44XzY zosX7FGu)a~XNpcAsuk+EYN;hIxJ91$sYOv&b?~cscvxqM68;7%rraEf)`bn;XU~>V ztn=!W?b!V297ktE~>WxX_>XOIF~bx zB>K^fO3ysada84vIoA6lSgdy$@{(f?PES9*AzjAnG;X9JVKB_1P}|G45TZ<PT$5W z>7P^__u9?*M(X>3>vdG{KdIsoy(I??ea`bI<{tK|Aoz?&V literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..b1499eaa7a2c365b58418106b69d1c58ca13a056 GIT binary patch literal 1669 zcma)6ZBr9h6n^d{$%e2XMh(Tbih*iggtc#0iM0|m5C};m0Tq1dlH4I{H@oTXjn=XK z8U4`y3!OGj+nG*3cKV?|snfHYfQ!(nvom|&&Uwx`&w2UlpI?6muz*Ly;22U6QV~Xk z;cUZhYi(V&OrblLwx%1_Ov&CgtYzJ5n!;g-$d=*GTw*v`IxL%uA&OxIF%=_F8O|IQ znaS&}c#U?=unc*fVIp-DTzWH#F$SeltrsihS`6bjt{|@B1Wqzcd+2W0(kvmhmXsY= zI8TJ5Ez|baH;tBV?FxqRT_M-S*InVtH6dGelUz@wOON#@x@MAyR+Ell?UL&WOelCq z#UxIX+M5CtI-%&M%Wx_cP_OJf77dw8Z$kuH0`INnf%Tp>b!~zNHL7P zjz4cVpLtXdqBm@Gd1KYS6&I?*RUOBnL6tc2k&|-Z8X=jXqg z9?>e4_eHY9aI9olqTFro2&b;^m|nN_%dx6EM5GiB^>+22-XzYcWEx*l zY6h?|>SxiB1~rm`yTRhD?7uL?YIfIYh=So+8}^3RoR>RFK$*IK*>)*!YSFTUvuILA zyaHAaPPdW3bix#|7Ns%C#>c(sNIOm+4L15$=``)1fssu1XRu866_gjAIBwHFLM!+Z z)@dK6EnzU!P#@_2O^6CTeH$Om_He9+Q$JuVlRb_<+HTyn3?Op$d z#65cWpojEJXs__;TIOO8SIV>TYro(+#~(<{hi2n9_YdLBPhgXw$#4&a`G{{IGa2cj zeZK?ou6 ki3B$N9m5?A;hvAXg>8Rb!hKrfK37Y4Kx>q`;9-dW3x(CM9{>OV literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..b371211d0f671fa22e3e2d6b0c31649100c335c9 GIT binary patch literal 2275 zcma)8-*XdH6#njR+D+3fEdg4K3ZX5Sq_n}`&>+&3))w2el2U{!xJ|Cj(#_sw_omQs zoMFZXU-f|*@ma^`Iv7S69UmS44@P}w2AxsHv&p92(kf1;d+**o=ey^8_dDn2m&f;h z1Tc!VHYiXvM0B*El_60Sl}yEuWs4iGotZIAdth2Di>jP7?2^S@hE`cNy@6v4d#AS> zXJd$>O+!paJ9LHv+f4>?hQ~M2PMWqUPcif)cY;eTM6ruOo1L4Vn#~tt=)!IdaUFZG zm!aQB_o{Zr<}y>3(($;v%H7N)O~-E(%Z9zo8M>CaJjbt9xhH41EQ=C_o=i<&HCBy` zMJAbobWMAiLhnY8hG%s2Vn4Y(X+WtHieY&S`;sB|*`=$zD6^?cQ9Q?h7%_T4$3Y|* zbdTGmbKG-;?NKDzMvhO3I6D;r4`TCq=wpb?%@*dP7$9Ol>f^2}+`f^%Mp6k|$b?~8 z;yN$&ee4r;M8^wAGVI#SKPO6SKGi|?rpQd$PF2z-+^7%%X$)#Os$&Sl414MXY_*}3 z$h0(SS-CaIiHS%uwU}$eF}$eZB^@v06^27~N1Ht92wacOrXWc@hFcnIypvzc`T2<} z#~JoFat#{?M)mV}&DYWE3CL&@qB6Lx7Koop0uFtmBx^Gsn+mD=$pPHPy|k;51v))Q(PGpNKU!;vsQWIUZel$}-J75{e{wY~gl;hbJqNlAgmQUm}YP$>gOF`GHSprFlXNB-$~ekfC$h zw0XW-S>o=zv1IwJqESn8hHF%~BEg z`1Ibdx9>mr;nst%)_=S6^+p#;mK$zcp#5&>!7*^n8!r z`s?pNdwTFYu=LWSQs)`A<1qJ$jaaoPRQgsNm4UQVaCu%!B zQ#)V~3+;&XbU*U@Z9ah|T8PkAMS60YEBFx0^>G|!8l&`Wh5k)kqqqG~$zmKXJ)<;w M5d{*fxPjh(0H+~#Z~y=R literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..de3d7545570ca66b33dd37bd23a31ede7ed7914c GIT binary patch literal 1894 zcmb_cZC4vr5Pt3@WH({U%eD;$wWR@TUK$o{t3W7)KqFKjNK&*#ZI|RWY~Ad}-AyZc z{Ok{~e$ap5$9gpQa*oH39)Fa_*-c0z;L#7BoU?c4W@hfpGtbN)fByU{fF;x-;OLVO zQqYeuL!x5WwYu)@n?iRiZ9_M#$!$?HTu(Twx>YrW!w~lN4R>;y;oSO3^IQ}%A`+qs z2B0upIB7DO*In^E+Pq;I-U7pD^0aWN9T|fRQgN%iR@^K_F^mxjs)DmP$1veXcbk@G z2~XSiyoM{B$HLK8Nxbz*WnZ^yf?>EOylwGuQ@GxS@b>L0rJhW!KhhuTnn@;F$#V>= zMybazD&YkMag34MaRVxyqUff}a6Z}NUfg>mDqb#iPsU3Oh!Un36kNnOgW?LSx-Hy> zZMl?5u3h85WSm>;3Es)g$05NG+A5aHGA0Sw&l19MY$q|7XcskZ+1|Krn)VY>O?>VH zby>lyNHPpQuRm{B4}7RQ)f=|9W;L1~JtFiv0gy&U!W9KsOfj4d0QkENl|-i1CDY6w zc!H1!B~!ck2&VCxgx3{Z#WjXYfulv9)B?w)-jqCIkM2~L+dBF6-zgXF&oGR&Ywb1e z7zO=!!{^bP3>TBT`G2-d?f9V2Dwso#;Y`DSv|u~+72VT`CB4l$!m}N$=@}-`ypfY} zgK`pe-7p7m6N?g-6y&i?(Sl-*3>o?eO@_<8F^>q))3(l)j9Ww`Cm10|_YB)wwyQ$M zTMTlO$ZF|z($+|8=&t+3cB(SoW*Dm2)Iu7N7hKQnwEeY=^*hYy#Jvm}z z+>HmC_IyS|1s@K%?hM_GrjH5}Q)^glYu!DE~ePZ8sZHr;{_y#!L z_ms&c8v3{raO;L8Hkf*23I~J zrgXwaX}ySs-%wY=gWg#wcK>0Bmh7fe5e374E#j}!DW6T$o=sXttF}u_Qr0X>ILjur z+MlPP6Z>|cXJ2BRfRkx=v*BTXWs}6|N2`{;?~yhU=)gca^8;8qa|r2~Z;re44busp z!99}uNu(GIyLi9t%f=v4B;ZH&Os0jQ7S4Z-!E|N>zpF2{@bWYDQs?@c;F^7o+_%&qt zbxiRYEb>_tcn&2#j|cn)>U;s8@|*aAFXAcB<6FLrL%xC!C}IeFG=>iYiQzu_pa<{l Wp%R=$ROwU$+=~!&$~2!3L;NpiIqwqy literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..e2419eb2144be39a18e68480ebca674f5a1a14d6 GIT binary patch literal 2772 zcma)8+jA3D82_DY+D+31O1KsfN*gfgg@DMdMU)mwi@ixofmX$Ba%{IvcEj!lsEAxd zMCDSXTpv&r2ge7n2;-R=~cE`A^tD#0&QT<`AMtATo#V~c*R5Z0li}E^IjmEgn zkZX1;hJPi)?1rgZtGw_aPlQ)OJ|u?4Q&s%cvXOzdQBf6h6T`efHn?D09;Rc4hyn>S z;bSQ1k@w4?n5=e%!hMFx;|zk9G#TbJ*ei+_YS9(d44XQa<5eEaW>`3K^TcTX$&qvC z$B!O+^wakvCr^)leQfN`(4)cQUd+Wj5%VP!VgbXfEFcVG!h(#cbV|TE#xcMoaaUEa z&4Wdx)ZEfq-`o`TVlkG8D3Y)g#SA4@1dOB_Qn?xGHqC^=_5EBA)zNh8!ALiG!pW^J zZtmdwlH4#Gx!J8nDZGK;)U&+sW0{EM5?)4Nax`pXC_RKC$Bd^;ZSL&h5wj}T?m;O7 zyi^0_5-PBQK{D)Y8wpJ{$dW224==E|s(z|%Rvf4-+%3)FRu5jGLx~}QPmBo%z zMXF{N$+4JrfJciDTY-92!Wyh)nEu57YAxDll|$NlN@%^BNKPcwi}lzbqEbQ?HfH22 zLx)_V+($RZV%2>nr%1R1!H()YY{Kgz-jJvVsu`BriB<`nQlJ}@o3Ke0F6+@6=bQHB z>};*wyPjcz<7=jJT8YZtk1bZMZ)I2#=%{|SX0Xji{kKg*9qP%wxZKNYG&LfdyA-pV zW(FN^(xJ<o}k8PCI@+3R$}>h z3p+%FCA4BEq1lm{P^9*v)I4R@L^WlYl@|HHu+59z*dwA{LI>Vv@J;0as&1$1CUXqK zhODMf28a_I#X@pI32ja&JGfK0lnEE!m9Q7@SrnyhH#BNjg8M&vvoxBI;I@f~Oq7`2 z@YJt7VG*K5N?gMG79$B%<6d;4TY_RWyqDtD$PGj8;ywsgG&&KJ5C_>a!zL1{v`BBO zE=Q={gg~%OL?X=-Pk1=1lRmgDJPn3ba+H-opgki8#CaAUWk@Cx)kaNVkvLhH202+!t!bup6(t-?4G%u19(VZruU{@y z7BLS#A;KHG_3fkU{UfJ-9KCj8{P^wB+k^Jfr{uN6{UaC7j0_Lh!q12Tp1KeoT~3i? zbl|J;fvaP8?$~NyFw7r2J2Z0c()bUj$L<`Xdt>D0;Ml$IXmv&|&UkSa=S1{dZGE1> zZ}*N}D~h^b>*d5MR!*EwuazUFrW3hc$*l6UqT`!$%NqU$P3ui2GE+GoqaiFf8g^_}pKC{EVwy#3hDhQ~b~7mWV5KIXqvL ziqMGxil`GkM4hal!1`mMnTsC!yPz>iUnTZ8kY8GMAFQ-&2;!inj{P*|(i=hn4$wS@ zri8(85Pi;G){#d1^Dd_OW~DI4x3DaQmr^LXis_|gGx5+DOrdPh7fOq-*-WG4-6`y< z%prMcVNMF~3`2I-tg{^v9drxp2sui4UBl?H6=>f30NNhG5$+?0hoCo+&Ft^e3PQ5% zBVX6zI&KgHx$JPX)87t+S?~yRFk6_5#lk!+5f-3KSco;kBCHjPP$w)!t5AY=!H+Is zIZPpdBSH}ULMg5bD{(_8!#6@X289aT7gpe*5W*kADttg8&WC%++<(v`qH{G4k-$wR zd`RO*GjF?D3>Mp0dZ!@g-?3AP#lWg>r#L54{K6E?mTA HTt(r3RPG%8 literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..bf68e842f2a3edcb45e524bc6754792a6e045a86 GIT binary patch literal 2443 zcmah~ZF3V<6n^eD?WXBMOQ5Yqh0+F0Qrh4fLW4+Cs13GFC8a>C;x@T9OOxHOdsC>0 zFZji8G6T-|GULk#!{~@(u>^$~$B&M`L(w1LjNcs3ZZ>3Tqf92d_ntlXx%WKhIp_ZR z&+VT84B_2oNNAAZQ_zSeh8-EB5G$x6m*=Xf$HrAn52Z_U1x*a;)){V&s(LohO@=0s z)2z@ghD~E@m&60`qgh5kK?@XyEo)su3Dx2?w0)YciTweF+Iv25=5Jiidi`z0%Tsfwct*q{Gk!e6 zfB^BjMZs2dGbk3>uf?A*vP(AAZuFWFOX|gvpiQ`1AOfQ3ld)4l zKL!{!It1MBLm`oCb|{}uED26b_`;FdL^F2baT!l2coI)BY;zXsw31R_T9li#AoZwb zcDOR9b&W@-Mo#Ww*j$O#>+Cu?`Pgmi=oyBs;n~E0dq$>h()TJDM4Vw=(cW~#FbfA& zp^{3x$*S^M0V@eDPf{<&{dkt4+2WR^8G16?g6D8R#*l&ph6&LLsOrqnK#WqwcyX&D z@TAT)`EiI49QoPUdX}FJ;CYP7NGdpt7Z^6wl$O*5pSP>b?*u{9Rbs22Kk3IfLyPLv zrVEL9896_2PxVG|aJ$fqI(PM3E7de@XtSZEUk>&ZATGV1gMXf4k%8rDi3Z`+) zZVAR=%g`D2t}f#GYwHxBj1yJGIWRgOKmbWH)wAZtsKia8vfS?l1j zR24BzMKVkjGPI6qI-e*N=D0bf&gIF{R;k@d)l>^yaFb5bL|uy-t&Q*G;X%zJLip>b zzA_7>V;44Xk3CBUrKMKMse50Dq_j~oGkip|cWbsA{(!9p(%uBM%2C52?X@KgLs-I8 ziZeRK1`sKS{y!ZQ+G>MXdYw7Y679PQ7VWzQdD(WyJUyG}4e1l)XxvCc!eG#FsO<~!&(K_9l45xIfbEj&FQ z-C4$-iT>ceAF*G;&*&KR^#>1DCqH0hcVmBW%sX$2u7Gv<+8f)O%9t3Gon50{av4*! z#WjS+?_lOc1L3}O8z(8ATgXh16ZA?{Q69!HQJI0@2a} zUuVbP$jUh0jXW8Av}J*w28|^YaoTyOVA9)9-%9kiaE@l1(Lf$4yg^Stz0dn3yotAQ H0bTzBRRXMe literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main.class new file mode 100644 index 0000000000000000000000000000000000000000..cd98b8c74bfc37346a2cc9babaadc4b24ae200e1 GIT binary patch literal 16119 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 accounts; + private Map pendingRegistrations; // 待完成注册的用户 + private Map userExams; // 用户当前试卷 + private Map userSessions; // 用户会话 + private String baseDirectory = "math_questions"; + private Random random = new Random(); + + public Main() { + initializeAccounts(); + pendingRegistrations = new HashMap<>(); + userExams = new HashMap<>(); + userSessions = new HashMap<>(); + createBaseDirectory(); + } + + // 初始化预设账户 + private void initializeAccounts() { + accounts = new HashMap<>(); + + // 小学账号 + accounts.put("张三1", new UserAccount("张三1", "Abc123", "小学")); + accounts.put("张三2", new UserAccount("张三2", "Abc123", "小学")); + accounts.put("张三3", new UserAccount("张三3", "Abc123", "小学")); + + // 初中账号 + accounts.put("李四1", new UserAccount("李四1", "Abc123", "初中")); + accounts.put("李四2", new UserAccount("李四2", "Abc123", "初中")); + accounts.put("李四3", new UserAccount("李四3", "Abc123", "初中")); + + // 高中账号 + accounts.put("王五1", new UserAccount("王五1", "Abc123", "高中")); + accounts.put("王五2", new UserAccount("王五2", "Abc123", "高中")); + accounts.put("王五3", new UserAccount("王五3", "Abc123", "高中")); + } + + // 创建基础目录 + private void createBaseDirectory() { + File dir = new File(baseDirectory); + if (!dir.exists()) { + dir.mkdir(); + } + } + + // 生成注册码 + public String generateRegistrationCode(String email) { + String code = "REG" + random.nextInt(10000); + pendingRegistrations.put(email, new UserAccount(email, code)); + return code; + } + + // 用户注册 - 修改以保存邮箱 + public ApiResponse register(String email, String registrationCode, String username, String password, String confirmPassword, String userType) { + System.out.println("处理注册请求: " + username + ", 邮箱: " + email); + + // 验证注册码 + if (!pendingRegistrations.containsKey(email) || + !pendingRegistrations.get(email).getRegistrationCode().equals(registrationCode)) { + return new ApiResponse(false, "无效的注册码", null); + } + + // 验证用户名是否已存在 + if (accounts.containsKey(username)) { + return new ApiResponse(false, "用户名已存在", null); + } + + // 验证密码 + if (!password.equals(confirmPassword)) { + return new ApiResponse(false, "两次输入的密码不匹配", null); + } + + if (!isValidPassword(password)) { + return new ApiResponse(false, "密码必须为6-10位,且包含大小写字母和数字", null); + } + + // 验证用户类型 + if (!userType.equals("小学") && !userType.equals("初中") && !userType.equals("高中")) { + return new ApiResponse(false, "无效的用户类型", null); + } + + // 创建用户账户并保存邮箱 + UserAccount newAccount = new UserAccount(username, password, userType, email); + accounts.put(username, newAccount); + pendingRegistrations.remove(email); + + System.out.println("注册成功: " + username); + return new ApiResponse(true, "注册成功", null); + } + // 在math_question类中添加发送注册码的方法 + public ApiResponse sendRegistrationCode(String email) { + System.out.println("收到发送注册码请求,邮箱: " + email); + + // 验证邮箱格式 + if (!isValidEmail(email)) { + return new ApiResponse(false, "无效的邮箱格式", null); + } + + // 检查邮箱是否已注册 + for (UserAccount account : accounts.values()) { + if (email.equals(account.getEmail())) { + return new ApiResponse(false, "该邮箱已被注册", null); + } + } + + // 生成注册码 + String code = generateRegistrationCode(email); + + // 模拟发送邮件 + System.out.println("=== 邮件发送模拟 ==="); + System.out.println("收件人: " + email); + System.out.println("验证码: " + code); + System.out.println("=== 邮件发送完成 ==="); + + Map data = new HashMap<>(); + data.put("email", email); + // 注意:实际生产中不应该返回验证码,这里仅用于演示和测试 + data.put("debugCode", code); + + return new ApiResponse(true, "验证码已发送到您的邮箱", data); + } + + // 验证邮箱格式 + private boolean isValidEmail(String email) { + if (email == null) return false; + String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; + return email.matches(emailRegex); + } + + + + + // 验证密码格式 + private boolean isValidPassword(String password) { + if (password.length() < 6 || password.length() > 10) { + return false; + } + + boolean hasUpper = false; + boolean hasLower = false; + boolean hasDigit = false; + + for (char c : password.toCharArray()) { + if (Character.isUpperCase(c)) hasUpper = true; + if (Character.isLowerCase(c)) hasLower = true; + if (Character.isDigit(c)) hasDigit = true; + } + + return hasUpper && hasLower && hasDigit; + } + + // 用户登录 + public ApiResponse login(String username, String password) { + UserAccount account = accounts.get(username); + if (account != null && account.getPassword().equals(password)) { + // 生成会话ID + String sessionId = generateSessionId(); + userSessions.put(sessionId, username); + + Map data = new HashMap<>(); + data.put("sessionId", sessionId); + data.put("userType", account.getUserType()); + data.put("username", username); + + return new ApiResponse(true, "登录成功", data); + } + return new ApiResponse(false, "用户名或密码错误", null); + } + + // 生成会话ID + private String generateSessionId() { + return "SESS" + System.currentTimeMillis() + random.nextInt(1000); + } + + // 验证会话 + private String validateSession(String sessionId) { + return userSessions.get(sessionId); + } + + // 修改密码 + public ApiResponse changePassword(String sessionId, String oldPassword, String newPassword, String confirmPassword) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + UserAccount account = accounts.get(username); + if (!account.getPassword().equals(oldPassword)) { + return new ApiResponse(false, "原密码错误", null); + } + + if (!newPassword.equals(confirmPassword)) { + return new ApiResponse(false, "两次输入的新密码不匹配", null); + } + + if (!isValidPassword(newPassword)) { + return new ApiResponse(false, "新密码必须为6-10位,且包含大小写字母和数字", null); + } + + account.setPassword(newPassword); + return new ApiResponse(true, "密码修改成功", null); + } + + // 生成试卷 - 添加详细日志 + public ApiResponse generateExam(String sessionId, String userType, int questionCount) { + System.out.println("🚀 === 开始生成试卷 ==="); + System.out.println("📅 时间: " + new Date()); + System.out.println("👤 用户: " + validateSession(sessionId)); + System.out.println("🎯 类型: " + userType); + System.out.println("📊 数量: " + questionCount); + + try { + String username = validateSession(sessionId); + if (username == null) { + System.out.println("❌ 会话验证失败"); + return new ApiResponse(false, "会话无效或已过期", null); + } + + if (questionCount < 10 || questionCount > 30) { + return new ApiResponse(false, "题目数量应在10-30之间", null); + } + + // 获取题目生成器 + QuestionGenerator generator = getQuestionGenerator(userType); + if (generator == null) { + return new ApiResponse(false, "无效的用户类型", null); + } + + System.out.println("✅ 开始生成题目..."); + + // 完全移除去重逻辑,先保证能生成题目 + List questions = new ArrayList<>(); + + for (int i = 0; i < questionCount; i++) { + System.out.println("🔄 尝试生成第 " + (i + 1) + " 题..."); + + try { + Question question = generator.generateQuestion(); + if (question == null) { + System.out.println("❌ 第 " + (i + 1) + " 题生成返回了null"); + continue; + } + + questions.add(question); + System.out.println("✅ 第 " + (i + 1) + " 题: " + question.getQuestionText()); + System.out.println(" 选项: " + question.getOptions()); + System.out.println(" 答案: " + question.getCorrectAnswerIndex()); + + } catch (Exception e) { + System.err.println("💥 生成第 " + (i + 1) + " 题时发生异常: " + e.getMessage()); + e.printStackTrace(); + // 继续生成下一题,不要因为一题失败就停止 + } + + // 添加小延迟,避免快速循环问题 + Thread.sleep(50); + } + + if (questions.isEmpty()) { + System.err.println("💥 严重错误:一道题目都没有生成成功!"); + return new ApiResponse(false, "无法生成任何题目,请检查系统配置", null); + } + + System.out.println("🎉 题目生成完成,共 " + questions.size() + " 题"); + + // 创建试卷 + Exam exam = new Exam(questions); + userExams.put(sessionId, exam); + + // 返回第一题 + Map data = new HashMap<>(); + data.put("examId", exam.getExamId()); + data.put("totalQuestions", questions.size()); // 使用实际生成的数量 + data.put("currentQuestion", 0); + data.put("question", questions.get(0).getQuestionText()); + data.put("options", questions.get(0).getOptions()); + + System.out.println("✅ === 试卷生成成功 ==="); + return new ApiResponse(true, "试卷生成成功", data); + + } catch (Exception e) { + System.err.println("💥 生成试卷时发生严重异常: " + e.getMessage()); + e.printStackTrace(); + return new ApiResponse(false, "系统错误: " + e.getMessage(), null); + } + } + + + + // 获取题目 + public ApiResponse getQuestion(String sessionId, int questionIndex) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + List questions = exam.getQuestions(); + if (questionIndex < 0 || questionIndex >= questions.size()) { + return new ApiResponse(false, "无效的题目索引", null); + } + + Question question = questions.get(questionIndex); + + Map data = new HashMap<>(); + data.put("examId", exam.getExamId()); + data.put("totalQuestions", questions.size()); + data.put("currentQuestion", questionIndex); + data.put("question", question.getQuestionText()); + data.put("options", question.getOptions()); + data.put("userAnswer", exam.getUserAnswers().get(questionIndex)); + + return new ApiResponse(true, "获取题目成功", data); + } + + // 提交答案 + public ApiResponse submitAnswer(String sessionId, int questionIndex, int answerIndex) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + exam.setAnswer(questionIndex, answerIndex); + + Map data = new HashMap<>(); + data.put("currentQuestion", questionIndex); + + return new ApiResponse(true, "答案提交成功", data); + } + + // 完成考试 + public ApiResponse finishExam(String sessionId) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + double score = exam.calculateScore(); + + // 保存考试记录 + saveExamResult(username, exam, score); + + // 移除当前考试 + userExams.remove(sessionId); + + Map data = new HashMap<>(); + data.put("score", score); + data.put("totalQuestions", exam.getQuestions().size()); + + return new ApiResponse(true, "考试完成", data); + } + + // 保存考试结果 + private void saveExamResult(String username, Exam exam, double score) { + String userDir = baseDirectory + File.separator + username; + File dir = new File(userDir); + if (!dir.exists()) { + dir.mkdir(); + } + + String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String filename = userDir + File.separator + timestamp + "_score_" + String.format("%.1f", score) + ".txt"; + + try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) { + writer.println("考试ID: " + exam.getExamId()); + writer.println("考试时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(exam.getStartTime())); + writer.println("得分: " + String.format("%.1f", score) + "分"); + writer.println(); + + List questions = exam.getQuestions(); + List userAnswers = exam.getUserAnswers(); + + for (int i = 0; i < questions.size(); i++) { + Question q = questions.get(i); + writer.println((i + 1) + ". " + q.getQuestionText()); + List options = q.getOptions(); + for (int j = 0; j < options.size(); j++) { + String prefix = (j == q.getCorrectAnswerIndex()) ? "[正确答案] " : + (j == userAnswers.get(i)) ? "[您的答案] " : ""; + writer.println(" " + (char)('A' + j) + ". " + prefix + options.get(j)); + } + writer.println(); + } + } catch (IOException e) { + System.out.println("保存考试结果失败: " + e.getMessage()); + } + } + + // 获取对应的题目生成器 + private QuestionGenerator getQuestionGenerator(String userType) { + System.out.println("🎯 为类型 '" + userType + "' 选择题目生成器"); + switch (userType) { + case "小学": + System.out.println("使用修复后的小学题目生成器 - 支持1-5个操作数"); + return new PrimarySchoolGenerator(); + case "初中": + System.out.println("使用修复后的初中题目生成器"); + return new JuniorHighGenerator(); + case "高中": + System.out.println("使用修复后的高中题目生成器"); + return new SeniorHighGenerator(); + default: + System.out.println("未知用户类型,使用稳定生成器"); + return new StableQuestionGenerator(); + } + } + + // 退出登录 + // 在logout方法中添加更详细的日志 + public ApiResponse logout(String sessionId) { + System.out.println("=== 退出登录处理 ==="); + System.out.println("请求的sessionId: " + sessionId); + System.out.println("当前活跃会话: " + userSessions.keySet()); + + String username = userSessions.remove(sessionId); + userExams.remove(sessionId); + + System.out.println("移除的用户名: " + username); + System.out.println("移除后活跃会话: " + userSessions.keySet()); + + // 即使sessionId无效,也返回成功,确保前端可以继续流程 + if (username != null) { + System.out.println("退出登录成功 - 用户: " + username); + return new ApiResponse(true, "退出成功", null); + } else { + System.out.println("退出登录 - sessionId无效,但返回成功"); + return new ApiResponse(true, "退出成功", null); + } + } + + // 启动HTTP服务器 + public void startServer(int port) throws IOException { + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + + // 注册端点 + server.createContext("/api/register", new RegisterHandler()); + server.createContext("/api/login", new LoginHandler()); + server.createContext("/api/change-password", new ChangePasswordHandler()); + server.createContext("/api/generate-exam", new GenerateExamHandler()); + server.createContext("/api/get-question", new GetQuestionHandler()); + server.createContext("/api/submit-answer", new SubmitAnswerHandler()); + server.createContext("/api/finish-exam", new FinishExamHandler()); + server.createContext("/api/logout", new LogoutHandler()); + // 添加新的注册码相关端点 + server.createContext("/api/send-registration-code", new SendRegistrationCodeHandler()); + + server.setExecutor(null); + server.start(); + + System.out.println("数学学习系统服务器已启动,端口: " + port); + } + + // 内部HTTP处理器类 + private abstract class BaseHandler implements HttpHandler { + protected Map parseFormData(String formData) { + Map params = new HashMap<>(); + if (formData != null && !formData.isEmpty()) { + String[] pairs = formData.split("&"); + for (String pair : pairs) { + String[] keyValue = pair.split("="); + if (keyValue.length == 2) { + try { + params.put(keyValue[0], java.net.URLDecoder.decode(keyValue[1], "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + } + return params; + } + + protected void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException { + exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8"); + exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*"); + exchange.getResponseHeaders().set("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + exchange.getResponseHeaders().set("Access-Control-Allow-Headers", "Content-Type"); + + exchange.sendResponseHeaders(statusCode, response.getBytes("UTF-8").length); + OutputStream os = exchange.getResponseBody(); + os.write(response.getBytes("UTF-8")); + os.close(); + } + + protected String toJson(ApiResponse response) { + // 简化的JSON序列化,实际应用中可以使用Jackson等库 + return "{\"success\":" + response.isSuccess() + + ",\"message\":\"" + response.getMessage() + "\"" + + ",\"data\":" + objectToJson(response.getData()) + "}"; + } + + private String objectToJson(Object obj) { + if (obj == null) return "null"; + if (obj instanceof Map) { + Map map = (Map) obj; + StringBuilder sb = new StringBuilder("{"); + boolean first = true; + for (Map.Entry entry : map.entrySet()) { + if (!first) sb.append(","); + sb.append("\"").append(entry.getKey()).append("\":"); + sb.append(objectToJson(entry.getValue())); + first = false; + } + sb.append("}"); + return sb.toString(); + } else if (obj instanceof List) { + List list = (List) obj; + StringBuilder sb = new StringBuilder("["); + boolean first = true; + for (Object item : list) { + if (!first) sb.append(","); + sb.append(objectToJson(item)); + first = false; + } + sb.append("]"); + return sb.toString(); + } else if (obj instanceof String) { + return "\"" + obj.toString().replace("\"", "\\\"") + "\""; + } else { + return obj.toString(); + } + } + } + + private class RegisterHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String email = params.get("email"); + String registrationCode = params.get("registrationCode"); + String username = params.get("username"); + String password = params.get("password"); + String confirmPassword = params.get("confirmPassword"); + String userType = params.get("userType"); + + ApiResponse response = register(email, registrationCode, username, password, confirmPassword, userType); + sendResponse(exchange, 200, toJson(response)); + } + } + + private class LoginHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String username = params.get("username"); + String password = params.get("password"); + + ApiResponse response = login(username, password); + sendResponse(exchange, 200, toJson(response)); + } + } + + //处理器都正确实现 + private class GenerateExamHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + String userType = params.get("userType"); + int questionCount = Integer.parseInt(params.get("questionCount")); + + ApiResponse response = generateExam(sessionId, userType, questionCount); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "生成试卷失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class GetQuestionHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + int questionIndex = Integer.parseInt(params.get("questionIndex")); + + ApiResponse response = getQuestion(sessionId, questionIndex); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "获取题目失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class SubmitAnswerHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + int questionIndex = Integer.parseInt(params.get("questionIndex")); + int answerIndex = Integer.parseInt(params.get("answerIndex")); + + ApiResponse response = submitAnswer(sessionId, questionIndex, answerIndex); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "提交答案失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class FinishExamHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + + ApiResponse response = finishExam(sessionId); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "完成考试失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class ChangePasswordHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + String oldPassword = params.get("oldPassword"); + String newPassword = params.get("newPassword"); + String confirmPassword = params.get("confirmPassword"); + + ApiResponse response = changePassword(sessionId, oldPassword, newPassword, confirmPassword); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "修改密码失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class LogoutHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + + ApiResponse response = logout(sessionId); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "退出登录失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + // 发送注册码的处理器 + private class SendRegistrationCodeHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + System.out.println("处理发送注册码请求"); + + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + System.out.println("请求体: " + requestBody); + + Map params = parseFormData(requestBody); + String email = params.get("email"); + + System.out.println("解析到的邮箱: " + email); + + ApiResponse response = sendRegistrationCode(email); + System.out.println("发送响应: " + toJson(response)); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + System.err.println("发送注册码时发生错误: " + e.getMessage()); + e.printStackTrace(); + ApiResponse errorResponse = new ApiResponse(false, "获取验证码失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + + public static void main(String[] args) { + try { + Main system = new Main(); + system.startServer(8080); // 启动在8080端口 + } catch (IOException e) { + System.err.println("启动服务器失败: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..83e17f3b359761a1129f6a1fd01d4c70f4966b34 GIT binary patch literal 5985 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 options = generateOptions(correctAnswerValue, isIntegerAnswer); + String correctAnswerStr = isIntegerAnswer ? + String.valueOf((int)correctAnswerValue) : + String.format("%.2f", correctAnswerValue); + int correctIndex = options.indexOf(correctAnswerStr); + + return new Question(questionText, options, correctIndex); + } + + // 生成考虑优先级的算术题目 + private String generateArithmeticQuestion() { + int operandCount = random.nextInt(3) + 2; // 2-4个操作数 + StringBuilder question = new StringBuilder(); + List tokens = new ArrayList<>(); + + // 生成操作数 + for (int i = 0; i < operandCount; i++) { + if (i > 0) { + // 随机选择运算符,考虑优先级 + String[] availableOps; + if (i == 1 && operandCount > 2) { + // 第一个运算符倾向于用乘除,确保优先级测试 + availableOps = new String[]{"×", "÷", "+", "-"}; + } else { + availableOps = new String[]{"+", "-", "×", "÷"}; + } + String op = availableOps[random.nextInt(availableOps.length)]; + tokens.add(op); + question.append(" ").append(op).append(" "); + } + + // 生成合适的操作数 + int num; + if (tokens.size() > 0 && (tokens.get(tokens.size()-1).equals("÷"))) { + // 除法:生成能整除的数 + num = generateDivisibleNumber(); + } else { + num = random.nextInt(30) + 1; // 1-30 + } + tokens.add(String.valueOf(num)); + question.append(num); + } + question.append(" = ?"); + + return question.toString(); + } + + // 生成能整除的数(用于除法运算) + private int generateDivisibleNumber() { + int[] smallNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + return smallNumbers[random.nextInt(smallNumbers.length)]; + } + + // 计算简单运算(支持负数) + private int calculateSimpleOperation(int a, int b, String op) { + switch (op) { + case "+": return a + b; + case "-": return a - b; + case "×": return a * b; + default: return a + b; + } + } + + // 计算表达式(考虑运算优先级)- 使用自定义解析器避免ScriptEngine问题 + private double evaluateExpression(String expression) { + try { + // 移除空格 + expression = expression.replaceAll(" ", ""); + + // 使用递归下降解析器计算表达式 + return evaluate(expression); + } catch (Exception e) { + System.err.println("计算表达式失败: " + expression + ", 错误: " + e.getMessage()); + return 0; + } + } + + // 递归计算表达式 + private double evaluate(String expr) { + if (expr.isEmpty()) return 0; + + // 处理加减法 + String[] plusMinus = expr.split("(?=[+-])", 2); + if (plusMinus.length > 1) { + double left = evaluate(plusMinus[0]); + double right = evaluate(plusMinus[1].substring(1)); + return plusMinus[1].charAt(0) == '+' ? left + right : left - right; + } + + // 处理乘除法 + String[] multDiv = expr.split("(?=[×÷])", 2); + if (multDiv.length > 1) { + double left = evaluateTerm(multDiv[0]); + double right = evaluateTerm(multDiv[1].substring(1)); + return multDiv[1].charAt(0) == '×' ? left * right : left / right; + } + + // 处理基本项(数字或括号表达式) + return evaluateTerm(expr); + } + + // 计算基本项 + private double evaluateTerm(String term) { + if (term.startsWith("(") && term.endsWith(")")) { + return evaluate(term.substring(1, term.length() - 1)); + } + + // 处理平方符号 + if (term.endsWith("²")) { + double base = evaluateTerm(term.substring(0, term.length() - 1)); + return base * base; + } + + try { + return Double.parseDouble(term); + } catch (NumberFormatException e) { + System.err.println("解析数字失败: " + term); + return 0; + } + } + + private int getPerfectSquare() { + int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; + return perfectSquares[random.nextInt(perfectSquares.length)]; + } + + private List generateOptions(double correctAnswer, boolean isInteger) { + List options = new ArrayList<>(); + + String correctStr = isInteger ? + String.valueOf((int)correctAnswer) : + String.format("%.2f", correctAnswer); + options.add(correctStr); + + Set used = new HashSet<>(); + used.add(correctStr); + + // 生成3个错误选项 + while (options.size() < 4) { + double wrongValue; + String wrongStr; + + do { + // 根据正确答案的大小调整变化范围 + double range = Math.max(5, Math.abs(correctAnswer) * 0.3); + double variation = (random.nextDouble() * range) + 1; + boolean positive = random.nextBoolean(); + + wrongValue = correctAnswer + (positive ? variation : -variation); + + if (isInteger) { + wrongValue = Math.round(wrongValue); + wrongStr = String.valueOf((int)wrongValue); + } else { + wrongValue = Math.round(wrongValue * 100) / 100.0; + wrongStr = String.format("%.2f", wrongValue); + } + } while (used.contains(wrongStr) || Double.isNaN(wrongValue) || Double.isInfinite(wrongValue)); + + options.add(wrongStr); + used.add(wrongStr); + } + + Collections.shuffle(options); + return options; + } +} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..bbca5cb70b0d4c3394c1ef20aed1e7e82578c44e GIT binary patch literal 5880 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 literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java new file mode 100644 index 0000000..01a4cec --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java @@ -0,0 +1,219 @@ +package com.mathlearn.generator; + +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class PrimarySchoolGenerator implements QuestionGenerator { + private Random random = new Random(); + private String[] operators = {"+", "-", "×", "÷"}; + private int maxAttempts = 100; // 最大尝试次数,避免无限循环 + + @Override + public Question generateQuestion() { + int attempts = 0; + while (attempts < maxAttempts) { + attempts++; + try { + // 生成2-3个操作数,避免太复杂 + int operandCount = random.nextInt(2) + 2; // 2-3个操作数 + StringBuilder question = new StringBuilder(); + List operands = new ArrayList<>(); + List usedOperators = new ArrayList<>(); + + // 生成操作数和运算符,确保表达式合法 + for (int i = 0; i < operandCount; i++) { + if (i > 0) { + String op = operators[random.nextInt(operators.length)]; + question.append(" ").append(op).append(" "); + usedOperators.add(op); + } + // 生成合适的操作数范围 + int num = generateSuitableNumber(i, usedOperators, operands); + question.append(num); + operands.add(num); + } + question.append(" = ?"); + + // 验证表达式合法性 + if (!isExpressionValid(operands, usedOperators)) { + continue; // 重新生成 + } + + // 计算正确答案 + int correctAnswer = calculateAnswerWithPriority(operands, usedOperators); + + // 确保结果不为负数 + if (correctAnswer < 0) { + continue; // 重新生成 + } + + // 生成选项并获取正确答案索引 + List options = generateOptions(correctAnswer); + int correctIndex = options.indexOf(String.valueOf(correctAnswer)); + + System.out.println("✅ 成功生成小学题目: " + question.toString() + " = " + correctAnswer); + return new Question(question.toString(), options, correctIndex); + + } catch (Exception e) { + System.err.println("生成小学题目失败,尝试次数: " + attempts + ", 错误: " + e.getMessage()); + // 继续尝试 + } + } + + // 如果多次尝试都失败,返回一个简单的默认题目 + System.out.println("⚠️ 使用默认小学题目"); + return new Question("2 + 3 = ?", Arrays.asList("5", "6", "4", "7"), 0); + } + + // 生成合适的数字 + private int generateSuitableNumber(int index, List operators, List operands) { + if (index == 0) { + // 第一个操作数 + return random.nextInt(50) + 1; // 1-50 + } + + // 根据前一个运算符决定当前操作数的范围 + String lastOperator = operators.get(operators.size() - 1); + switch (lastOperator) { + case "-": + // 减法:第二个操作数不能太大,避免负数 + int previous = operands.get(operands.size() - 1); + return random.nextInt(Math.min(previous, 20)) + 1; + case "÷": + // 除法:除数要小,且要能整除 + previous = operands.get(operands.size() - 1); + List divisors = findDivisors(previous); + if (!divisors.isEmpty()) { + return divisors.get(random.nextInt(divisors.size())); + } + return random.nextInt(10) + 1; // 备选 + case "×": + // 乘法:避免结果太大 + return random.nextInt(5) + 1; // 1-5 + default: + return random.nextInt(50) + 1; // 1-50 + } + } + + // 找到能整除的数 + private List findDivisors(int number) { + List divisors = new ArrayList<>(); + for (int i = 1; i <= Math.min(number, 10); i++) { + if (number % i == 0) { + divisors.add(i); + } + } + return divisors; + } + + // 验证表达式是否合法 + private boolean isExpressionValid(List operands, List operators) { + try { + // 计算中间结果,验证每一步都合法 + int result = operands.get(0); + for (int i = 0; i < operators.size(); i++) { + String op = operators.get(i); + int next = operands.get(i + 1); + + switch (op) { + case "-": + if (result < next) return false; // 减法结果不能为负 + break; + case "÷": + if (next == 0 || result % next != 0) return false; // 除数不能为0且要能整除 + break; + } + + result = applyOperation(result, op, next); + if (result < 0) return false; // 最终结果不能为负 + } + return true; + } catch (Exception e) { + return false; + } + } + + // 考虑运算优先级的计算 + private int calculateAnswerWithPriority(List operands, List operators) { + if (operands.size() == 1) return operands.get(0); + + // 先处理所有乘除法 + List processed = new ArrayList<>(); + processed.add(operands.get(0)); + + for (int i = 0; i < operators.size(); i++) { + String op = operators.get(i); + int nextOperand = operands.get(i + 1); + + if (op.equals("×") || op.equals("÷")) { + // 执行乘除运算 + int lastIndex = processed.size() - 1; + int lastValue = (Integer) processed.get(lastIndex); + int result = applyOperation(lastValue, op, nextOperand); + processed.set(lastIndex, result); + } else { + // 加减法先保留 + processed.add(op); + processed.add(nextOperand); + } + } + + // 再处理加减法 + int result = (Integer) processed.get(0); + for (int i = 1; i < processed.size(); i += 2) { + String op = (String) processed.get(i); + int nextOperand = (Integer) processed.get(i + 1); + result = applyOperation(result, op, nextOperand); + } + + return result; + } + + // 执行单个运算 + private int applyOperation(int a, String operator, int b) { + switch (operator) { + case "+": return a + b; + case "-": return a - b; // 前面已经验证不会为负 + case "×": return a * b; + case "÷": return a / b; // 前面已经验证能整除 + default: return a; + } + } + + private List generateOptions(int correctAnswer) { + List options = new ArrayList<>(); + options.add(String.valueOf(correctAnswer)); + + Set used = new HashSet<>(); + used.add(correctAnswer); + + // 生成3个错误选项 + while (options.size() < 4) { + int variation = random.nextInt(10) + 1; + boolean add = random.nextBoolean(); + int wrongAnswer = add ? correctAnswer + variation : Math.max(0, correctAnswer - variation); + + if (!used.contains(wrongAnswer) && wrongAnswer != correctAnswer) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } + + // 防止无限循环 + if (options.size() < 4 && used.size() > 10) { + // 强制添加一些选项 + for (int i = 1; i <= 3; i++) { + int forcedOption = correctAnswer + i * 2; + if (!used.contains(forcedOption)) { + options.add(String.valueOf(forcedOption)); + used.add(forcedOption); + if (options.size() >= 4) break; + } + } + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..2bfb7d72953038e7a332fe74d3cf7ade377a5fcc GIT binary patch literal 206 zcmX^0Z`VEs1_nn4PId++Mh4B~{9OIq#FC7h)Wo7Z{q)ql)S|?a{389p($wOT%=|oe zmR%&tyPzb6g6{drcK~+Q32i4r%{FKxj{nU!YT)4s3 zj0{}C`K3k4scxA$sf-L_F#T{F^+1-fF)}bRFaur8z`zJ}04oC zL$X#M<&Z_rg6&`p4nunq%-uN;r@r7?xt>r$^DxlvP$(Jbp7f^YpWMOeIVIt&bQ|o#38&3Vo@>AexVb zzUE_}7<(8*dLqtbe5wBNyH+gDkR1pU_5u@Hs4_JFVUNMNP-MU3b7O>|RsQsgeX^6F zwZ}p0BSh?tkWr+uLAgYyLnM)kYmH~HMso?PQCnjDY1Oz%SXz}wgg40H7J1y!lP#(w Tu#NI6SFl6brjc1xunYSGAUbwI literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..4967054c76996721a92c3d694eb00a1d42016ae7 GIT binary patch literal 10033 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 literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java new file mode 100644 index 0000000..97113ff --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java @@ -0,0 +1,425 @@ +package com.mathlearn.generator; + +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class SeniorHighGenerator implements QuestionGenerator { + private Random random = new Random(); + + @Override + public Question generateQuestion() { + int type = random.nextInt(6); // 六种题型 + String questionText = ""; + double correctAnswerValue = 0; + boolean isIntegerAnswer = true; + + switch (type) { + case 0: // 三角函数(特殊角,包括负角) + String[] trigFunctions = {"sin", "cos", "tan"}; + String func = trigFunctions[random.nextInt(trigFunctions.length)]; + int angle = getSpecialAngle(); + questionText = func + "(" + angle + "°) = ?"; + correctAnswerValue = calculateTrigValue(func, angle); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 1: // 平方根(包括非完全平方数的近似值) + if (random.nextBoolean()) { + // 完全平方数 + int square = getPerfectSquare(); + questionText = "√" + square + " = ?"; + correctAnswerValue = Math.sqrt(square); + } else { + // 非完全平方数的近似值 + int num = getNonPerfectSquare(); + questionText = "√" + num + " ≈ ?"; + correctAnswerValue = Math.sqrt(num); + isIntegerAnswer = false; + } + break; + + case 2: // 对数运算 + questionText = generateLogQuestion(); + correctAnswerValue = evaluateLogQuestion(questionText); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 3: // 复合表达式(考虑优先级) + ExpressionResult exprResult = generateCompositeExpression(); + questionText = exprResult.expression; + correctAnswerValue = exprResult.value; + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 4: // 二次方程 + int root = random.nextInt(15) - 7; // -7到7的根 + int a = 1; + int b = -2 * root; + int c = root * root; + questionText = String.format("方程 %dx² %s %dx %s %d = 0 的一个根是?", + a, b >= 0 ? "+" : "", b, c >= 0 ? "+" : "", c); + correctAnswerValue = root; + break; + + case 5: // 带指数的复合运算 + questionText = generateExponentialExpression(); + correctAnswerValue = evaluateExponentialExpression(questionText.replace(" = ?", "")); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + } + + List options = generateOptions(correctAnswerValue, isIntegerAnswer); + String correctAnswerStr = isIntegerAnswer ? + String.valueOf((int)correctAnswerValue) : + String.format("%.2f", correctAnswerValue); + int correctIndex = options.indexOf(correctAnswerStr); + + return new Question(questionText, options, correctIndex); + } + + // 表达式和结果封装类 + private static class ExpressionResult { + String expression; + double value; + + ExpressionResult(String expression, double value) { + this.expression = expression; + this.value = value; + } + } + + // 生成复合表达式并同时计算结果 + private ExpressionResult generateCompositeExpression() { + // 使用预定义的简单表达式模板,确保可计算 + String[][] templates = { + {"%d + %d × %d", "先乘后加"}, + {"%d × %d + %d", "先乘后加"}, + {"%d - %d × %d", "先乘后减"}, + {"%d × %d - %d", "先乘后减"}, + {"%d + %d ÷ %d", "先除后加"}, + {"%d ÷ %d + %d", "先除后加"}, + {"%d² + %d", "先平方后加"}, + {"%d² - %d", "先平方后减"}, + {"%d × (%d + %d)", "先加后乘"}, + {"(%d + %d) × %d", "先加后乘"} + }; + + String[] template = templates[random.nextInt(templates.length)]; + String pattern = template[0]; + String description = template[1]; + + // 生成合适的数字,确保计算有效 + int a, b, c=1; + double result = 0; + + // 根据模板类型生成合适的数字 + if (pattern.contains("÷")) { + // 除法模板:确保除数不为0且能整除 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + + // 调整数字确保除法有效 + if (pattern.startsWith("%d ÷")) { + // 第一个操作数是除法:确保b能整除a + a = b * (random.nextInt(5) + 1); // a是b的倍数 + } else if (pattern.contains("÷ %d")) { + // 其他位置的除法:确保除数不为0 + b = random.nextInt(9) + 1; // 1-9 + } + } else if (pattern.contains("²")) { + // 平方模板 + a = random.nextInt(10) + 1; // 1-10 + b = random.nextInt(20) + 1; // 1-20 + result = a * a + (pattern.contains("+") ? b : -b); + } else if (pattern.contains("(")) { + // 括号模板 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + result = pattern.contains("× (") ? a * (b + c) : (a + b) * c; + } else { + // 基本四则运算 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + + // 根据运算符计算结果 + if (pattern.contains("+ %d ×")) { + result = a + b * c; // a + b × c + } else if (pattern.contains("× %d +")) { + result = a * b + c; // a × b + c + } else if (pattern.contains("- %d ×")) { + result = a - b * c; // a - b × c + } else if (pattern.contains("× %d -")) { + result = a * b - c; // a × b - c + } else if (pattern.contains("+ %d ÷")) { + result = a + (double)b / c; // a + b ÷ c + } else if (pattern.contains("÷ %d +")) { + result = (double)a / b + c; // a ÷ b + c + } + } + + // 如果还没有计算结果,使用安全的表达式计算 + if (result == 0) { + result = safeEvaluateExpression(pattern, a, b, c); + } + + String expression = String.format(pattern, a, b, c) + " = ?"; + System.out.println("生成表达式: " + expression + " [规则: " + description + "] = " + result); + + return new ExpressionResult(expression, result); + } + + // 安全的表达式计算 + private double safeEvaluateExpression(String pattern, int a, int b, int c) { + try { + if (pattern.equals("%d + %d × %d")) { + return a + b * c; + } else if (pattern.equals("%d × %d + %d")) { + return a * b + c; + } else if (pattern.equals("%d - %d × %d")) { + return a - b * c; + } else if (pattern.equals("%d × %d - %d")) { + return a * b - c; + } else if (pattern.equals("%d + %d ÷ %d")) { + return a + (double)b / c; + } else if (pattern.equals("%d ÷ %d + %d")) { + return (double)a / b + c; + } else if (pattern.equals("%d² + %d")) { + return a * a + b; + } else if (pattern.equals("%d² - %d")) { + return a * a - b; + } else if (pattern.equals("%d × (%d + %d)")) { + return a * (b + c); + } else if (pattern.equals("(%d + %d) × %d")) { + return (a + b) * c; + } + } catch (Exception e) { + System.err.println("计算表达式失败: " + String.format(pattern, a, b, c) + ", 错误: " + e.getMessage()); + } + return 0; + } + + // 获取特殊角度(包括负角) + private int getSpecialAngle() { + int[] angles = {-360, -270, -180, -135, -120, -90, -60, -45, -30, 0, + 30, 45, 60, 90, 120, 135, 180, 270, 360}; + return angles[random.nextInt(angles.length)]; + } + + // 获取非完全平方数 + private int getNonPerfectSquare() { + int[] nonSquares = {2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20}; + return nonSquares[random.nextInt(nonSquares.length)]; + } + + // 生成对数题目 + private String generateLogQuestion() { + if (random.nextBoolean()) { + // 简单对数:log₁₀ + int value = (int)Math.pow(10, random.nextInt(4)); // 1, 10, 100, 1000 + return "log₁₀" + value + " = ?"; + } else { + // 以2为底的对数 + int value = (int)Math.pow(2, random.nextInt(6) + 1); // 2,4,8,16,32,64 + return "log₂" + value + " = ?"; + } + } + + // 计算对数题目 + private double evaluateLogQuestion(String question) { + if (question.startsWith("log₁₀")) { + int value = Integer.parseInt(question.replace("log₁₀", "").replace(" = ?", "")); + return Math.log10(value); + } else if (question.startsWith("log₂")) { + int value = Integer.parseInt(question.replace("log₂", "").replace(" = ?", "")); + return Math.log(value) / Math.log(2); + } + return 0; + } + + // 生成指数表达式 + private String generateExponentialExpression() { + int base = random.nextInt(5) + 2; // 2-6 + int exponent = random.nextInt(4) + 2; // 2-5 + return base + "^" + exponent + " = ?"; + } + + // 计算指数表达式 + private double evaluateExponentialExpression(String expr) { + String cleanExpr = expr.replace(" = ?", ""); + String[] parts = cleanExpr.split("\\^"); + int base = Integer.parseInt(parts[0]); + int exponent = Integer.parseInt(parts[1]); + return Math.pow(base, exponent); + } + + private double calculateTrigValue(String function, int angle) { + // 规范化角度到0-360度 + angle = angle % 360; + if (angle < 0) angle += 360; + + // 特殊角的精确值 + switch (angle) { + case 0: + if (function.equals("sin")) return 0; + if (function.equals("cos")) return 1; + if (function.equals("tan")) return 0; + break; + case 30: + if (function.equals("sin")) return 0.5; + if (function.equals("cos")) return Math.sqrt(3)/2; + if (function.equals("tan")) return 1/Math.sqrt(3); + break; + case 45: + double sqrt2 = Math.sqrt(2); + if (function.equals("sin")) return sqrt2/2; + if (function.equals("cos")) return sqrt2/2; + if (function.equals("tan")) return 1; + break; + case 60: + if (function.equals("sin")) return Math.sqrt(3)/2; + if (function.equals("cos")) return 0.5; + if (function.equals("tan")) return Math.sqrt(3); + break; + case 90: + if (function.equals("sin")) return 1; + if (function.equals("cos")) return 0; + if (function.equals("tan")) return Double.POSITIVE_INFINITY; + break; + case 120: + if (function.equals("sin")) return Math.sqrt(3)/2; + if (function.equals("cos")) return -0.5; + if (function.equals("tan")) return -Math.sqrt(3); + break; + case 135: + double sqrt22 = Math.sqrt(2)/2; + if (function.equals("sin")) return sqrt22; + if (function.equals("cos")) return -sqrt22; + if (function.equals("tan")) return -1; + break; + case 150: + if (function.equals("sin")) return 0.5; + if (function.equals("cos")) return -Math.sqrt(3)/2; + if (function.equals("tan")) return -1/Math.sqrt(3); + break; + case 180: + if (function.equals("sin")) return 0; + if (function.equals("cos")) return -1; + if (function.equals("tan")) return 0; + break; + case 270: + if (function.equals("sin")) return -1; + if (function.equals("cos")) return 0; + if (function.equals("tan")) return Double.NEGATIVE_INFINITY; + break; + } + + // 对于非特殊角,使用近似计算 + double rad = Math.toRadians(angle); + switch (function) { + case "sin": + return Math.round(Math.sin(rad) * 100) / 100.0; + case "cos": + return Math.round(Math.cos(rad) * 100) / 100.0; + case "tan": + if (angle % 180 == 90) { + return angle % 360 == 90 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; + } + double result = Math.tan(rad); + return Math.round(result * 100) / 100.0; + default: + return 0; + } + } + + private int getPerfectSquare() { + int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; + return perfectSquares[random.nextInt(perfectSquares.length)]; + } + + private List generateOptions(double correctAnswer, boolean isInteger) { + List options = new ArrayList<>(); + + String correctStr; + if (Double.isInfinite(correctAnswer)) { + correctStr = correctAnswer > 0 ? "∞" : "-∞"; + } else if (Double.isNaN(correctAnswer)) { + correctStr = "无解"; + } else { + correctStr = isInteger ? + String.valueOf((int)correctAnswer) : + String.format("%.2f", correctAnswer); + } + options.add(correctStr); + + Set used = new HashSet<>(); + used.add(correctStr); + + // 生成3个错误选项 + int attempts = 0; + while (options.size() < 4 && attempts < 50) { + attempts++; + double wrongValue; + String wrongStr; + + // 根据正确答案调整变化范围 + double baseRange; + if (Double.isInfinite(correctAnswer) || Double.isNaN(correctAnswer)) { + baseRange = 5; + } else { + baseRange = Math.max(2, Math.abs(correctAnswer) * 0.3); + } + + double variation = (random.nextDouble() * baseRange) + 1; + boolean positive = random.nextBoolean(); + + if (Double.isInfinite(correctAnswer)) { + wrongValue = random.nextDouble() * 10 - 5; // -5到5的随机数 + } else if (Double.isNaN(correctAnswer)) { + wrongValue = random.nextDouble() * 10; // 0到10的随机数 + } else { + wrongValue = correctAnswer + (positive ? variation : -variation); + } + + if (Double.isInfinite(wrongValue)) { + wrongStr = wrongValue > 0 ? "∞" : "-∞"; + } else if (Double.isNaN(wrongValue)) { + wrongStr = "无解"; + } else if (isInteger) { + wrongValue = Math.round(wrongValue); + wrongStr = String.valueOf((int)wrongValue); + } else { + wrongValue = Math.round(wrongValue * 100) / 100.0; + wrongStr = String.format("%.2f", wrongValue); + } + + if (!used.contains(wrongStr)) { + options.add(wrongStr); + used.add(wrongStr); + } + } + + // 如果选项不够,添加一些固定选项 + while (options.size() < 4) { + String extraOption; + if (isInteger) { + int extraValue = (int)correctAnswer + options.size() * 2 + 1; + extraOption = String.valueOf(extraValue); + } else { + double extraValue = correctAnswer + options.size() * 0.5 + 0.1; + extraOption = String.format("%.2f", extraValue); + } + + if (!used.contains(extraOption)) { + options.add(extraOption); + used.add(extraOption); + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..77c835a92fa785434db6a6547504560a530cc812 GIT binary patch literal 3453 zcmaJ@TXa-c8UFU%&Y6<~2?GO8lj4waNhX&mP{xuWR7eX%5~l4?=z!H6l9Oa$=1iD5 zL!n-Jv9+~WdsU#VP|=#&LZt{HgcjGb%e7p-)dyWZxRy&r>;o@8d8x*4pOZ-@5-qP8{r-RNU;caIDu7Lx(BOerflr4Y0fD;x#vvn~GpwO_YTtgd-xdgL$XZ!@qky-m zd6xpULR7Z1x%mBtHBiWFP~Z)s2D*ZII_9HRAl_fd$Mc3goHLE06(2G!vuN0bVmxgd z`*P-eWwT^w3)a@kJ_QvWW&)ueM~f-}Ny&VHjt~|K)E=BV+f^uAwpkPq-9d!0Siuq< zpF*Ufp<_n+NXa(y)V@%rF=3Z=wh+I!n6>P*T{Mk+GDKh0>uA8O0!#A70kf-M^&9r? ztUb(G$u=yz#IsG^&F*oRu}uy`Ne!PyRKYSGjkrx)D@{#vIafzQy<=E1U&b1bS-#*KHfc~1xe>!mk31Qs`S&u#PubSl`W<1TzwVEznh zdKqy_%o~RV{PHj*Z@^|9U6Rn7&srfOZhZ(|tk)RStva@$n|_%Bi0Q&3H6p=56&FrB z-GM_-wq!G0K5Ul?_6V$;%b!(NF~TxR3U&xAn+?f4os)~3hmCx^f<_I!xL2maeRFem z8P90aEi)oriMj)edk*)Tj`9+c59rt>@#r;+MGg1kK^+veDjpIDu8y`uS4TUecd7UyqrFCj!C|e6ehzo2APcch!w`lQWOeMvfeK(8MK=|T z#u0ilV3efy1XeWdt#VK$?Eh_=0w#@%<{37UfrcEs5>6vJ4$6#C4jH+!nHsD?3ATc= zjzbbv#b#5~ni)x(c}*E2N84r8Ha~9LzBm3#Sk{ZFy3Hc zO2MntwHgW2sq#9D$zJAUFr6K;47*&U+*Q+_pSEj56^f?LZloA3T__j(%`I7}ZiAc7 z6=kO_Y?p4NHT1t-vWvz@uW1h#21+WvFVGl`MsK|F!Ho-}(d)0A`tvg{Tt9OrDxx1h z{_@ACk6(Z7-S+l&6>m~M!OReDW{f(^w#xEH)I&r+JXTr1LsiK253fHJb$Pgq$@|)~ zr#hlS#aV&&DY@t0oJI7PpFVy4t)qV$KYQ)@7kTX3`%hdOALp6c0Di3D9NtrKURI-@ z2rPHd;b1mv9V#3!dE3eQ*us|34{f zkZTu~vGRL(&Ai0kBi{=EN8aunz1-(pg#9aAt#j5uICcplb_Gi25`q_@#k?0$_Z|rZ zzRi9<$-w0HK_#;wcfW&UE(?#r{TdP;jb$#N&ez9-=dmcp`2=nO#;}xgt!~j6miziP zRLwgBAD}7Y4aL$KU#K;m@rT;eJK7{c+f@>;>F`B-9f~KRMwBt!{tgvDicMplJ5FGwH=&Lq%5|%=UhI?WIUY57jq}Bbf-wVN*g22gBL~?v?~{Iv`0p9J9146Ww{I$xvT&-F>q z?Mr6@p@H-`2Axw3O+@Sz5AaU(H~}m&fq;3?7|IBdu!2}vjm6Y$327Se3oOM)d}{p~ zQT!IS;rCdM>!kWCA5DM9Dtv+%lek4JLaVryucAh@ixs$Cv}3hci*+K&qP`7xQeubL zg`_aiiQ|-bH?&EX{U9MCgn|3Wqkfr#ve#! z0%|Iw)G4WqTBoHteBOjV><^sAvDV9Yf|u=SJQwkW{Sn{Qk@iGDhII^2C6uso0$P1I z&^HQ&!+-?PNwl_wRY%e{Ja`pLTjgp>mC7Hf!zk9)hyA`j|8QSIt^9C~)c>y|Px{5^ zWOiDoj(T^h4)^)`68^TZe?}~Ma5XK~{o{z8{8{TbzS(+?ad1&E=zx4PlemlV--3E< zWqi9i+s=nm4+i)?%QMLyrO#hN8Yi(6XR#ZX@F0FpijS}dza#A*(T5u_@K5X$LB5m1 z7!b=aD3)VbG$HFmJ_dD?tOGK%3RvqNQ}7zY{x3eJMVI)5!`~492mGBLeAm(NBvbp8 qGkXKyRlrFwA25<>3`_-Z#n(jPJad$NUM?VBK5qC$bSH6Y+p(M literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java new file mode 100644 index 0000000..ace3ab1 --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java @@ -0,0 +1,107 @@ +package com.mathlearn.generator; +//稳定生成器 +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class StableQuestionGenerator implements QuestionGenerator { + private Random random = new Random(); + private int questionCounter = 0; + + @Override + public Question generateQuestion() { + questionCounter++; + System.out.println(" 🔧 生成第 " + questionCounter + " 道题目..."); + + try { + // 极度简化的题目生成,确保不会卡住 + int a = random.nextInt(20) + 1; + int b = random.nextInt(20) + 1; + + // 随机选择运算符 + String[] operators = {"+", "-", "×"}; + String operator = operators[random.nextInt(operators.length)]; + + String questionText; + int correctAnswer; + + switch (operator) { + case "+": + questionText = a + " + " + b + " = ?"; + correctAnswer = a + b; + break; + case "-": + // 确保减法结果不为负数 + int larger = Math.max(a, b); + int smaller = Math.min(a, b); + questionText = larger + " - " + smaller + " = ?"; + correctAnswer = larger - smaller; + break; + case "×": + // 简化乘法,避免过大数字 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + questionText = a + " × " + b + " = ?"; + correctAnswer = a * b; + break; + default: + questionText = a + " + " + b + " = ?"; + correctAnswer = a + b; + } + + // 生成稳定的选项 + List options = generateStableOptions(correctAnswer); + + System.out.println(" ✅ 题目生成成功: " + questionText); + return new Question(questionText, options, 0); // 第一个选项是正确答案 + + } catch (Exception e) { + System.err.println(" 💥 题目生成过程中发生异常: " + e.getMessage()); + // 返回一个默认题目,确保不卡住 + return new Question("1 + 1 = ?", Arrays.asList("2", "3", "4", "5"), 0); + } + } + + private List generateStableOptions(int correctAnswer) { + List options = new ArrayList<>(); + options.add(String.valueOf(correctAnswer)); + + // 生成3个稳定的错误选项 + Set used = new HashSet<>(); + used.add(correctAnswer); + + int[] variations = {1, 2, 3, 5, 7, 10}; // 固定的变化量 + + for (int i = 0; i < 3 && options.size() < 4; i++) { + int variation = variations[i % variations.length]; + boolean addVariation = random.nextBoolean(); + + int wrongAnswer = addVariation ? correctAnswer + variation : correctAnswer - variation; + + // 确保不为负数且不重复 + if (wrongAnswer > 0 && !used.contains(wrongAnswer)) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } else { + // 如果生成失败,使用备选方案 + wrongAnswer = correctAnswer + (i + 1) * 2; + if (!used.contains(wrongAnswer)) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } + } + } + + // 如果选项还不够,用固定值补全 + while (options.size() < 4) { + int filler = correctAnswer + options.size() * 5 + 1; + if (!used.contains(filler)) { + options.add(String.valueOf(filler)); + used.add(filler); + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class new file mode 100644 index 0000000000000000000000000000000000000000..649edee4601be6aaecd8da31c12a1cc46d167f02 GIT binary patch literal 637 zcmZXR%TB^j5QhH)g-Wg5z2Y@)pi%n(8WW>&)Dl_i=X`v=y#qMGwt)naIy4h0qy_SA`5^6%3|#xV)mBas3VYokR04W9a2yqe0-_lU zWKHCdXWeH}x+IDhe{<_m-wWKs7%ZA7p)8=?$w*F9-|h|ts@3NI=84J}tTiZeN`C^m z3olSt1HYyEx3bk?CF6zlAB)_wDPXuNy8LlhuGS_5$Np%a%-P7;H1KQ9sCNf_N1c1| zjQqrr9K_pVhZ`n%3rR+vCf^eAxr{Q`X4W8hEsKmx{5s-)jk#>SLRgg{bZc*j1#5qZ z!ZYgv%Zy9x0F^al_!!7iyF_(?6|9bxHkbvel=TAr@wYWSDrOniP+^RRPNEA>GiZ*` S`Usgt3$tjR=qB3}*!lvsuy*eN literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java new file mode 100644 index 0000000..97e218a --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java @@ -0,0 +1,17 @@ +package com.mathlearn.model.api; + +public class ApiResponse { + private boolean success; + private String message; + private Object data; + + public ApiResponse(boolean success, String message, Object data) { + this.success = success; + this.message = message; + this.data = data; + } + + public boolean isSuccess() { return success; } + public String getMessage() { return message; } + public Object getData() { return data; } +} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class new file mode 100644 index 0000000000000000000000000000000000000000..fa6df17e059f8094551bf8df2214194994bb812d GIT binary patch literal 2001 zcma)7ZBrXn6n<_3EQIBqP$eLsr6i#?we|%~z)~m@h0+=tq`of67Pn0{b$3&#pF7hp z{sX^s{G#8~83EB5$ItyA{)x_Lea^ChK!y zq@x)v3f*^%`$no{*qf=9jXP$+Q)tOpw&l$zgyV^P8(Pt(A)=!ly25awQcjf(?~9UY zICiRBDVn8}xn-17SGg#(eOWbK&#KriO)vSjtDaR#Em^LY*3hZYcX&AKIK~6HiJ${v z@zkTESKPE$UDKJh-LFi?)zGidd5D@fJTrp6eZUDFFX3hSbv?uJR;{vm)UPPhZ%kp( zx8RvuUMgpm@0CosTBtZorWM2V@PNPN$fjo>Wa&~Q%2n>eq~<0tFKo3%Z2({vQH`$nm1uH04_h-d4g3N+HbWKZnTTiWqOU179tmH@ISTx-ZF1J8 zZFp6OG+x+`_n=)fOaJRDJ(E@#Z@@K>@9Xu|w}w9ti9BmK#}QKKTC!~OTD81kI;+M; zi6B4}T!o{0F9XLRLsYtjkDjACeq2@Te2h;5)%VD|Fh3Ui79%ksFCem4 z_OT(K$+yB-JLIs_2aJ-rF^uvd7p}rkqqO)bJ`3!A6I661oMCl@n80pI><;Z=I)p!Q zb_cU^SCi*=u<#fy50&x@_aye{0QsoWkL=wa=_};3J4k+|o+182=wVBpM}lwg1g3G? VkEk8tztN=Bxu@(ih0lGU@h_~W##{gZ literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java new file mode 100644 index 0000000..ce3c1cd --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java @@ -0,0 +1,46 @@ +package com.mathlearn.model.exam; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class Exam { + private List questions; + private List userAnswers; + private Date startTime; + private String examId; + + public Exam(List questions) { + this.questions = questions; + this.userAnswers = new ArrayList<>(); + this.startTime = new Date(); + this.examId = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + + // 初始化用户答案列表 + for (int i = 0; i < questions.size(); i++) { + userAnswers.add(-1); // -1表示未作答 + } + } + + public List getQuestions() { return questions; } + public List getUserAnswers() { return userAnswers; } + public Date getStartTime() { return startTime; } + public String getExamId() { return examId; } + + public void setAnswer(int questionIndex, int answerIndex) { + if (questionIndex >= 0 && questionIndex < userAnswers.size()) { + userAnswers.set(questionIndex, answerIndex); + } + } + + public double calculateScore() { + int correctCount = 0; + for (int i = 0; i < questions.size(); i++) { + if (userAnswers.get(i) == questions.get(i).getCorrectAnswerIndex()) { + correctCount++; + } + } + return (double) correctCount / questions.size() * 100; + } +} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class new file mode 100644 index 0000000000000000000000000000000000000000..8942b24d1523223070cc269dfa50194f22c7ad42 GIT binary patch literal 842 zcmaiyU279T6o%i)*P87nX=1FOQL9CgwRG=ID3pQ_2o_1{{U#mal-*g~%xZp=7YYr6 z7ySYLDDmB7VupR8c5!fF`p%?n*Lm>TFdtr1b15eKU(0iZAsZo&@a6V=3 zxttN#7~GZ^npo*cH-%Om)UYdHMIY0&DO*_z6Qcrepr&RaYdE-zCMn}6j@jOco_>*W zUth|ZfanX9hiamIlf+WsV2#k*EPdP+c-7vFuVr@ooeP1&Dc>hh8z?Q`CE-ZM=l&>Q zL<_zs& zl*D8CR;6#Nta>|2_lAA$D#x#r=gBWXFPAP3WG?(Y-nk+A1;&cF&-(-3db9=FruzfJ zeLaWe9?ns5TXWREGcNFu=N>Zvo5~%ONw1 options; + private int correctAnswerIndex; + + public Question(String questionText, List options, int correctAnswerIndex) { + this.questionText = questionText; + this.options = options; + this.correctAnswerIndex = correctAnswerIndex; + } + + public String getQuestionText() { return questionText; } + public List getOptions() { return options; } + public int getCorrectAnswerIndex() { return correctAnswerIndex; } +} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class new file mode 100644 index 0000000000000000000000000000000000000000..d02c2fae41688ff0102fee2e1b72d4ebdf28465e GIT binary patch literal 1426 zcmbV~TTc^F6ouF6oic?&TS~bUxwpe*cr~I4G58`8BgzABLpiBK+9{b%HU1|bG_f)9 z!5`p{GOj&SEe;byOp|lY?5_QtwfEUSet!E7;0OnKB#_J^Wgv}=Lh;&uXImZHZCj_8 z*Sh5^WDXtI@t-Ip8_n|xy%-oPXbg^gCPYjth^ZAaUlYjt~9x?>Ic+OytpIcl|f z1DA-Lgj~C;6=qMyH=OyNiRfE+O1F`;5IU>+i?0}Fl;{O;)02N?T;~)80%s*N8qu%4v$P29rI_sf!ET{9O+^4 z*68fZuwa!hnc%o)xN_`xO31VXI|n4#`S8Kc=MHwx2zLXV1}t-}^Xr&-Deg7%E0no2 zMAqCLqG0X~Q8ZISls@xMg%z#~yiC$lC}09p{7s{TBIYp@ARmm7r$nZyT!};0$gD=d zbz~_o5nLv?Lhu~FsvO*TdaMQT)e-!V@Fdmc-|(vVT`-e>S)B_EERwiH;xdVK5?9Dr z`&0SjQRS6?R~@3(2wX=V8?1SgHn)gc=U3Q7X{Ms7wD|?uPdtPT%LKs&*UeaIAu4TB zx)m!eMx`dD+p*GxsC0+Y281mSe%ov5W5nw&MJ6Ocq;+;Em@(;4VLS+7UHeq+#yY4* U9axm^#bc{c>;bj=ygUKx7uQVtbpQYW literal 0 HcmV?d00001 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java new file mode 100644 index 0000000..0760366 --- /dev/null +++ b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java @@ -0,0 +1,49 @@ +package com.mathlearn.model.user; + +// 用户账户类 +public class UserAccount { + private String username; + private String password; + private String userType; + private String email; // 添加邮箱字段 + private String registrationCode; + private boolean registered; + + public UserAccount(String username, String password, String userType) { + this.username = username; + this.password = password; + this.userType = userType; + this.registered = true; + } + + public UserAccount(String username, String password, String userType, String email) { + this.username = username; + this.password = password; + this.userType = userType; + this.email = email; + this.registered = true; + } + + public UserAccount(String email, String registrationCode) { + this.email = email; + this.registrationCode = registrationCode; + this.registered = false; + } + + public void completeRegistration(String username, String password, String userType) { + this.username = username; + this.password = password; + this.userType = userType; + this.registered = true; + } + + public String getUsername() { return username; } + public String getPassword() { return password; } + public String getUserType() { return userType; } + public String getRegistrationCode() { return registrationCode; } + public boolean isRegistered() { return registered; } + + public void setPassword(String password) { this.password = password; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } +} -- 2.34.1 From af38715ddcbc384a6a12241c8af8351afa587f3f Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Fri, 10 Oct 2025 20:59:02 +0800 Subject: [PATCH 05/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9main=E5=85=A5=E5=8F=A3?= =?UTF-8?q?=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/electron-frontend/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/electron-frontend/package.json b/src/electron-frontend/package.json index 85b1de1..9d636c7 100644 --- a/src/electron-frontend/package.json +++ b/src/electron-frontend/package.json @@ -2,14 +2,14 @@ "name": "math-learning-app", "version": "1.0.0", "description": "小初高数学学习软件", - "main": "src/main.js", + "main": "resources/main.js", "scripts": { "start": "electron .", "dev": "electron . --dev", "build": "electron-builder" }, "devDependencies": { - "electron": "^22.0.0", + "electron": "^22.3.27", "electron-builder": "^24.0.0" }, "build": { @@ -31,4 +31,4 @@ "dependencies": { "node-fetch": "^2.7.0" } -} +} \ No newline at end of file -- 2.34.1 From e0f7315964514cd58735f14d1bce7bd50d76e6b1 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Fri, 10 Oct 2025 21:33:29 +0800 Subject: [PATCH 06/30] =?UTF-8?q?=E8=BE=93=E5=85=A5=E6=A1=86=E8=81=9A?= =?UTF-8?q?=E7=84=A6=E4=BF=AE=E6=94=B9=E6=96=B9=E6=A1=881?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/electron-frontend/resources/main.js | 15 +++++++++-- .../resources/renderer/login.html | 25 +++++++++++++------ .../resources/renderer/main.html | 11 +++++--- .../resources/style/common.css | 17 +++++++++++++ 4 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/electron-frontend/resources/main.js b/src/electron-frontend/resources/main.js index 688dacc..3075cfb 100644 --- a/src/electron-frontend/resources/main.js +++ b/src/electron-frontend/resources/main.js @@ -80,9 +80,20 @@ ipcMain.handle('api-request', async (event, { endpoint, method = 'POST', data = } }); -// 页面导航 + +// 页面导航 - 强制新窗口 ipcMain.handle('navigate-to', (event, page) => { - mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`)); + // 先强制清除任何可能的内存缓存 + mainWindow.webContents.executeJavaScript(` + if (document.activeElement) { + document.activeElement.blur(); + } + `); + + // 使用 loadURL 而不是 loadFile,避免缓存问题 + mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`), { + extraHeaders: 'pragma: no-cache\n' + }); }); app.whenReady().then(createWindow); diff --git a/src/electron-frontend/resources/renderer/login.html b/src/electron-frontend/resources/renderer/login.html index 7d51f60..f1a018f 100644 --- a/src/electron-frontend/resources/renderer/login.html +++ b/src/electron-frontend/resources/renderer/login.html @@ -69,20 +69,29 @@ + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/main.html b/src/electron-frontend/resources/renderer/main.html new file mode 100644 index 0000000..37435c4 --- /dev/null +++ b/src/electron-frontend/resources/renderer/main.html @@ -0,0 +1,432 @@ + + + + + + 数学学习系统 - 主页 + + + + + +
+

数学学习系统

+ + + +
+ + + +
+ + + +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/quiz.html b/src/electron-frontend/resources/renderer/quiz.html new file mode 100644 index 0000000..bc7962d --- /dev/null +++ b/src/electron-frontend/resources/renderer/quiz.html @@ -0,0 +1,264 @@ + + + + + + 数学学习系统 - 答题 + + + + + +
+
+ +
+ +
+ +
+ +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/register.html b/src/electron-frontend/resources/renderer/register.html new file mode 100644 index 0000000..dbffcca --- /dev/null +++ b/src/electron-frontend/resources/renderer/register.html @@ -0,0 +1,260 @@ + + + + + + 数学学习系统 - 注册 + + + + + +
+

用户注册

+ +
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/result.html b/src/electron-frontend/resources/renderer/result.html new file mode 100644 index 0000000..a229fd5 --- /dev/null +++ b/src/electron-frontend/resources/renderer/result.html @@ -0,0 +1,104 @@ + + + + + + 数学学习系统 - 成绩 + + + + + +
+

考试完成

+
+ +
+

+ +
+ + +
+
+ + + + + \ No newline at end of file diff --git a/src/electron-frontend/resources/style/common.css b/src/electron-frontend/resources/style/common.css new file mode 100644 index 0000000..19382d9 --- /dev/null +++ b/src/electron-frontend/resources/style/common.css @@ -0,0 +1,118 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + padding: 20px; +} + +.message { + padding: 10px; + margin-top: 15px; + border-radius: 5px; + text-align: center; +} + +.message.success { + background: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.message.error { + background: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +.message.info { + background: #d1ecf1; + color: #0c5460; + border: 1px solid #bee5eb; +} + +/* 基础按钮样式 */ +.btn { + padding: 10px 20px; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +/* 按钮交互效果 */ +.btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.btn:active { + transform: translateY(0); + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); +} + +/* 主按钮 - 用于主要操作 */ +.btn-primary { + background: #007acc; + color: white; +} + +.btn-primary:hover { + background: #005fa3; +} + +/* 次要按钮 - 用于辅助操作 */ +.btn-secondary { + background: #6c757d; + color: white; +} + +.btn-secondary:hover { + background: #5a6268; +} + +/* 成功按钮 - 用于提交、确认等操作 */ +.btn-success { + background: #28a745; + color: white; +} + +.btn-success:hover { + background: #218838; +} + +/* 危险按钮 - 用于删除、退出等操作 */ +.btn-danger { + background: #dc3545; + color: white; +} + +.btn-danger:hover { + background: #c82333; +} + +/* 禁用状态 */ +.btn:disabled { + opacity: 0.7; + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +/* 图标按钮样式(如果需要) */ +.btn-icon-left i { + margin-right: 8px; +} + +.btn-icon-right i { + margin-left: 8px; +} \ No newline at end of file diff --git a/src/electron-frontend/start-backend.bat b/src/electron-frontend/start-backend.bat new file mode 100644 index 0000000..81b488e --- /dev/null +++ b/src/electron-frontend/start-backend.bat @@ -0,0 +1,6 @@ +@echo off +echo 启动数学学习系统后端服务器... +cd java-backend +javac math_question.java +java math_question +pause \ No newline at end of file diff --git a/src/java-backend/math_learn/.gitignore b/src/java-backend/math_learn/.gitignore new file mode 100644 index 0000000..13275f1 --- /dev/null +++ b/src/java-backend/math_learn/.gitignore @@ -0,0 +1,30 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ +.kotlin + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/.gitignore b/src/java-backend/math_learn/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/src/java-backend/math_learn/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/src/java-backend/math_learn/.idea/misc.xml b/src/java-backend/math_learn/.idea/misc.xml new file mode 100644 index 0000000..6f29fee --- /dev/null +++ b/src/java-backend/math_learn/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml new file mode 100644 index 0000000..422d56a --- /dev/null +++ b/src/java-backend/math_learn/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/vcs.xml b/src/java-backend/math_learn/.idea/vcs.xml new file mode 100644 index 0000000..c2365ab --- /dev/null +++ b/src/java-backend/math_learn/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/math_learn.iml b/src/java-backend/math_learn/math_learn.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/src/java-backend/math_learn/math_learn.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt b/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt new file mode 100644 index 0000000..67cd00c --- /dev/null +++ b/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt @@ -0,0 +1,64 @@ +考试ID: 20251009192152 +考试时间: 2025-10-09 19:21:52 +得分: 100.0分 + +1. 20 ÷ 5 - 3 = ? + A. 9 + B. 0 + C. 3 + D. [正确答案] 1 + +2. 10 ÷ 5 = ? + A. 12 + B. 1 + C. 0 + D. [正确答案] 2 + +3. 7 - 7 + 27 = ? + A. 34 + B. [正确答案] 27 + C. 18 + D. 23 + +4. 48 - 18 = ? + A. 33 + B. [正确答案] 30 + C. 28 + D. 39 + +5. 10 - 9 = ? + A. [正确答案] 1 + B. 10 + C. 3 + D. 0 + +6. 2 × 4 × 1 = ? + A. 0 + B. 12 + C. 4 + D. [正确答案] 8 + +7. 45 + 46 × 1 = ? + A. [正确答案] 91 + B. 101 + C. 88 + D. 89 + +8. 4 × 1 + 39 = ? + A. 40 + B. 45 + C. 41 + D. [正确答案] 43 + +9. 28 ÷ 1 = ? + A. [正确答案] 28 + B. 33 + C. 35 + D. 23 + +10. 47 × 5 = ? + A. 226 + B. 243 + C. [正确答案] 235 + D. 228 + diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..353bdc304f1b1484376f7bff793065ae0e3c0462 GIT binary patch literal 4196 zcmai1dw3LA760AI?#^U0Kp05E@=TVH=Cxf*YlK~(l8``X9>@kFk5-4xm<-vS+0M-J zkYZ~s)(6%{s}{71wSsS{+NFRZ_$XSn+SY1))<-{I{e1l4AELGK+?idn%P#HrC9`+W zoO{l>=lss^+(? zm7y#<2}ey%j#z3^3!)Pd5!cFy;#CYwlV&<u|{{> zrV(!>PnNAYtMldR!fQmVkg*amhQ%-Mg%V3UE5oBGu?4_vm9UCo!P;a}v+W3v%`#Jw zwW*Z3H!^JLza(my_*?rowr%BlLo$Z3 ziRxZdvTk#Xx@#WQtAL*2tV3X=lxS)?9>iuOM2yJTf~^d5D=ASY?X`4=u;6dq(al|L z#_MHl;}G*FQ>IP8+JT)SZkBNiZ*&(}Y1NrXX{u#J)6`?BsG8BEYcqNwe1>Y>PGsFm z@a=Dup<)+9kYXRC>Zlxha|>a+{FARD*B+Ch;Z4LJq`gjc)GJlB{Od^#B z({x;es%|uQs|0J+7)x;)kWH83M$C-_Ooo=?lH^SmH)lQ|g^1ITVS@U+A+1ho1S|sh zsP0VA%63%4q57_D-CmB!a!CdI5-2pEkxivU5Y`*q8Wm-vJFBOtEhX$B=pG2d#y(Eo zRQ9^!16*zbPE`kF+=hb$Kx$5Fe}ebW>_W0#9w$+}2Djr55pR`oC*D@VY3>GzFkz{V zNzv7p?CsCX$-p7JUBulo-obI9xRJZ&3o2B?3Dq9b_BmYlT{7Oy%jz>oAmTj*x^}k^ zk2d%6XeGRt4%*2N`hFQ7z`exZ#46Mq43SDFF3WO0W5iJ(Bun8M9L9%b+|OMH2vIj_ z`?>L>-1tYXuz6J&Oxt{bK?ujV(T~eG#*Oke->RmvM1c>I!-L%VLozA1Q5p?bV{Do#mm962)g2$Dy%=vJ z2J-a~TM&f}=!Q0wP4CjI5p`FJB()y#Zc;5Ztr5VerDkOK;OH~0w8sHUi_cveW&uHQ z+T{*JLX&G)#05fGg_{HsR6-v&R3~eZ_x@Kly{bGR<&rfNfLu)D3~?_PuP}(?{pH4Z zzJix0zb)dsg@&O^LjUmPH-u^@PiZT!OngOhj#t0~xk{K>E2;JAyd2e>J+I|xB?u2` zwzI*ssbzmeUCseeT3M=Iw`n@IW2u?T^YbaX(Hscd-UtZCSZ6rx@qRcKX5r5881XuZ z4@&q6jd>Ey3gD+f{0z^E_&EpWFA7&8mkV`ck2$GDy|Q}@+@~gqornkTFRor*(Tl@F zq}@DVnv>Z~aew6TQAWLA@AA6{sR_qDM`o62zVy4E=_oSv@J$w)rifreq%Z zUA`0X9K*6{)-Q>p^Z+7$M`P~gRS6B=X?=|}9tCRiQ#8Q*wDRLLJ;q;d00n;UDQo$)7NX{TcJwUvNG9D_#3u zKo9#HM%h2Ho&6m<**~DtyK(j}e1k$Bf^Q1TAc~j}Q6r*B#CiH-bjT^(fa)^2t92es zM9U=vrYLvxqba|a?0u8|1$>JV@@;&_OApOJAE^PGC?y@rb;|WQyxLvHmDPpijmp}> zvPZd&FBe9Xc{%i+JCs8|X%F%QdZHX&7xLvWI$fU@RMYAIjT&|d_3S@rV*f=a`yW=a zmvAGS!bYm;u)y#bMd72|U8Lvt@Hnk_(PQ+D7rma`Y^VP>w9_M*!}uAbfs^#cLxDni z5d8290R#mRb+i`v4a>8`o`U7Jf7ZFfyJ=t*qO-FEB$9Xgjo`tqTUeNZIl@dV5@w-Ms6~%3 zn~I`96XqZ*%*8&T4hMvK+$l8RZebqo5kk0En2!g91vn-w#93hxE((kBl&}QP2#t7F zXu@+s7|#n!@q*Bd7ljrV(i;&JIi>?HE~!q0X`AqR2zZgN4_`tDL1hY!(<;Y{R2GX6 zE}@oG8mQpkchB+z{LuY;0zanDnRL2msOV3+&!_QAlFg^$Pv8ms$|ukTs0qIgRO2`J JEq;&C{{g`EdAa}q literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..b5329c7850143c7fe0bb18926c3368b7b2f43bb7 GIT binary patch literal 2465 zcmb7GU2qds6#niu&2G~LN}#Plh0+F0Qqtfr&>+$jY71>zNhp@8uuU$_(#>wz-Lw=$ z#}{9G)fsVc#s?kW)H)aj7|}<^cW2ZY^+Em||7V=>&GGCeX;T_uoKAP|J$uf%=X~co z=jO|Qu3Q7qhnJfmph1L3MkBlop^TA_Hp_(-}8@hL&k=AL6Hq+_Fcw zoinl&dMG@6Qkhj^8l@OZ*`}&bQ|N7I7jd7A05*`>oeGpXc~LZrp*2)vK00-hXY6?R zsDuX?;3H%=%GiVs2HE0z_7JxUhHi0&csa*=L>wQgabAhd!J(7EGd7w^O9&FMXFIuR z8fIs2XE~`3-LN|pO*7_rw)30=)K(b}A;hqHDgT6#op+$FWUm^rA-zzv=@72u34jQ? zMQoE1MGwO|7l7qDloF|C`!p>vZ*xMz6ADizny?)Yi+DuFqj-#Avumi6C6&Oms5U8^ z*rS+PqLi~IyT-%mfnz%vHk5O%Rjw$x^?1VJ(GG@9p~=L5Ylg=i(09q`MVw((!8v5W zF!TEqTOpRz7ORS9*;&z6H6nW^++64aEgB9gG5q1n)~)lQP|GzoM*wOMO8(FT!l!6-TE2vdQQ;7sTBjXTK&Rj4KSccB9>&{ND zZ(FAWMI5fu&TUNUVP3GQA|j4dx_xOz)%EH_8WS>(I@7^NRT`m+D%0FgL+?2m&*KGR ze_om4{f3@V>?5k3qm@PMbU3-Jpv#G}d`^txxWh~0Rw#7zuJ~4IF;1P*PY_a_hgF>? zi}@*Trj;p;BrW9z9#c#u&uwl}BwiX_G;JOKZXND5F~a136*XCAhR9rT>sv(65^=JM ztJBV-i(d$&luz8kQ`0A~9Ub*q^!tIOi^>(l|UYI^uutgLdz-JkPZuhtds`{)k!z%-~T!R56V;d$- zr8jH2TTv{ZSH3K);ILuL6btdY0=~>JJzwB;)F*2^R0~uis<`N?d@yjFDBH3f>{i(!Ca6`0p>_!3F>3iuf&8%--;KIpV8mo1hO{N(g_9*d;tZ64_S5&SccT`!e3 z^awvs6VrrIGd%5W ze9~%vBfs6O({YZyiG36(#>wzy(x4Y zXPn{12Osc(8TDDmH=Q~d22jQy4>F9u{|B7@0nYfwcsALzTUy1*WcTjfbH01dcfND> z-h*3r01RTO844Oy1T-|Fi6N4+iiskZ1w(M#OpJ5gjHGo_cM8Lod2xiBc|+I?O|qan zk%J67#x^=6LkOZ-MMy&nG=|+9O(H4oh&8k$bb>s}&=K7XE;bXyRt9xqa(Z+klMSH_ z+f;-#Y{w3U9v9syn+a3ML_x}uBkVZh6JcTI3*0uaoR({E)+RI+I5~F6REa?!zi$p*iy($i9=tDol z_9_AEZ73x&%?}zzYDo%WA`p$urkZgOPpf!F!?SpfVQ+yoCqZb+WL}yd~ZW)_#Nk6P%07-@|CHK&@WfzZg$w?*t zV%7Pqft96hkkCuXAYNiDO>#*SbJonP%UhQof`)p*yt6|KB561=1*21|NfV8ob$S2c`b+-+0q zgkzaixc}q3NkgcZsH>pbC)84+B#9suuX)Y4HZC@eD1;2M8m8T54H0SML@=KhVVXZP z8cyML5@V4sh#||&ad}FY1zI^I7D*CW$L}f+4|gRcJ&7}}OlBFP(KEgRcs{@R^JdwS*vX4L|S)GYj#I)znd^aFhk>O#BxY?Z7Iu=jfJ1s3nU0d?6m$D4F*qC1qEI7{nBS`r4sIlSfhKJXAf2yf}F zptXXXA7N{}cN^}8AFtramS%;(axn zWeT$&1}tiArJ6~KzBN$3hNgUjcI6H_l<&}^e2+fm2lOjH;+S$5Y2_ZW%1=0}{0u|+ z9hUM7O3JUeqWp%d${*mwLJI;N?SH#-H`9eV+6d55Il2m3D>#q&>U|gmx(Dgq0{wMd Yq^DhIAd6wxbPdwo2`G?Q#AS5;1NY~EkN^Mx literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..293b2db69ca5858fbbb3a0309b84f1f33122d2cb GIT binary patch literal 2454 zcmah~-E$LF6#w0AnoZLMN`Thl2c->=q_n{=ga(l&P#SETN=kuNh1=wsY@6(c-J8;a zh#xP$FoQEPqrUipX+_^bm8+EjQnw8P7=KVuf7MK1FN!7U>?$#o-mS{TCOQk+`h#c^(A3&LXX%Dip| z4>9bVXm*MD;X{WCzlKg|3@!m~bXWl&SoGs)Cc+K(=5 zR}s*#13MW89CW*EL=7RMc_~Y_u$F}t9jD=`l}w%+Il<7C6Y{LMQWmzH6f$pS>FA;G z#3Enj(E^!7)6&w7938zIJu05l(2L#Vw%LF}Clp?=8FqzS?x}@Ek&&_RoDVNBz)!rs zq+t*G7&KcL*|WkfnTAa#iPd6!#))G|7kK?_4iEhdp6OJ2#)lvgd%a&+mTC2m^w)yw zGfdgX3kCD4$oAiGh}y5=0748~H{y?**;R+?di1&(O&X=Lq)h}b5&;nmsyL`&2*V6J zssuc3Lm`oAcC=84uS!8octYX%cn1#QWfiYzconZP?5#Q)bmmf=~4^rIR^5M$UQ^8IjO{* ztOlPou(H$(B=u6vhc_8IY+>8FX(Y3qcnc>~jB1D@L5S6W8paH5#3)sa8@C|>SL*6Z zKAd9kl}Va2t0m#XX~L_Dk#6FuQgBYg zEY3R(!aQS}2E)y(y~$4sV85Eq_kPKGGa`3cI$B3|F9!O(%uv`&T-Qw?RCXXQ`*wv zrP@ht9~?#g`Q^8Ne17}!4|g8jT7PtR?eYEZM*7$`FP8ndiWL>B4&m1rf*Z=#jb(F5 z)H`o22V*=VO^e#oS8id}4Qu<=ZVfv)VVX3bR#AT+@@AROt!orJ6#u?ikl4kn&NI1j*3sHt^dC%38EG|`l#T1Bxcst z<=o#iQs_r_E*+6v;bVde$1d9x=LtS&sk)x-V-cT+hPvdqP5(a~g#hNcWK!^_Z zy}*{i3bs|S>uYR{3~tA7f#)lDaV@a7zWhyfncWEtILi;weUU!ws~~(2(RI8&897+N zk*T4;v7d2V!LR5Z@eBn{KAE%+1;!eapD=#d8@UhG>*;OZ<*i_9M6GTa=~XM3A^h(V zoP3D6i){q@?gLz+VAheDA|v)!WTAdihtrpHFJLA0P% zMo7VCY+>ke(CxAw*SUxngfMMx&2uY0OvA$$as^eNk3>h# zs`F~RNG9>Durz&^TyIB*j7Jo7Vk>Q1Z9t(DidwW8+9ICqV>4%YP9&nI19*%9L85h= zg6-&HP;9Q}C%A1Ix=o%WYB4^<<3!p6?)v8N(9Pf*AInY#5GG*)<2vw%1u^~dQ>YvRGZVj z#^aNzGy52})?)P~(bX9K-g=bn?F~qf-v)`xOiz!LY$}4ow+W>5wW^Qi(TN zbv|ogWuX;G>1HB;=NX!8ZrddFbiNrc;-HK{1xXAMVl|+;F+&3}%CO6eTNi;Rb?#CC zhY6u7KL=aS^9w;7!LW?9f}?nep>;)RX1eSs_IHco)_b)sl^9Pt*%^3g@mkvNgQ|T-#BU;I>Y|e6}$f4 zbt+B9iMqV11xU5ZO{dAoIOSILN+VhqHHaxpD|p%I0zry0Lzz=&d5AjOs|wEGHBxy= zo#R7>o>RpMO%!NklL`fC?}5bC3H2n-T?*nPW*q(H7$T9=YYjXr_4H3sMGO&z44XzY zosX7FGu)a~XNpcAsuk+EYN;hIxJ91$sYOv&b?~cscvxqM68;7%rraEf)`bn;XU~>V ztn=!W?b!V297ktE~>WxX_>XOIF~bx zB>K^fO3ysada84vIoA6lSgdy$@{(f?PES9*AzjAnG;X9JVKB_1P}|G45TZ<PT$5W z>7P^__u9?*M(X>3>vdG{KdIsoy(I??ea`bI<{tK|Aoz?&V literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..b1499eaa7a2c365b58418106b69d1c58ca13a056 GIT binary patch literal 1669 zcma)6ZBr9h6n^d{$%e2XMh(Tbih*iggtc#0iM0|m5C};m0Tq1dlH4I{H@oTXjn=XK z8U4`y3!OGj+nG*3cKV?|snfHYfQ!(nvom|&&Uwx`&w2UlpI?6muz*Ly;22U6QV~Xk z;cUZhYi(V&OrblLwx%1_Ov&CgtYzJ5n!;g-$d=*GTw*v`IxL%uA&OxIF%=_F8O|IQ znaS&}c#U?=unc*fVIp-DTzWH#F$SeltrsihS`6bjt{|@B1Wqzcd+2W0(kvmhmXsY= zI8TJ5Ez|baH;tBV?FxqRT_M-S*InVtH6dGelUz@wOON#@x@MAyR+Ell?UL&WOelCq z#UxIX+M5CtI-%&M%Wx_cP_OJf77dw8Z$kuH0`INnf%Tp>b!~zNHL7P zjz4cVpLtXdqBm@Gd1KYS6&I?*RUOBnL6tc2k&|-Z8X=jXqg z9?>e4_eHY9aI9olqTFro2&b;^m|nN_%dx6EM5GiB^>+22-XzYcWEx*l zY6h?|>SxiB1~rm`yTRhD?7uL?YIfIYh=So+8}^3RoR>RFK$*IK*>)*!YSFTUvuILA zyaHAaPPdW3bix#|7Ns%C#>c(sNIOm+4L15$=``)1fssu1XRu866_gjAIBwHFLM!+Z z)@dK6EnzU!P#@_2O^6CTeH$Om_He9+Q$JuVlRb_<+HTyn3?Op$d z#65cWpojEJXs__;TIOO8SIV>TYro(+#~(<{hi2n9_YdLBPhgXw$#4&a`G{{IGa2cj zeZK?ou6 ki3B$N9m5?A;hvAXg>8Rb!hKrfK37Y4Kx>q`;9-dW3x(CM9{>OV literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..b371211d0f671fa22e3e2d6b0c31649100c335c9 GIT binary patch literal 2275 zcma)8-*XdH6#njR+D+3fEdg4K3ZX5Sq_n}`&>+&3))w2el2U{!xJ|Cj(#_sw_omQs zoMFZXU-f|*@ma^`Iv7S69UmS44@P}w2AxsHv&p92(kf1;d+**o=ey^8_dDn2m&f;h z1Tc!VHYiXvM0B*El_60Sl}yEuWs4iGotZIAdth2Di>jP7?2^S@hE`cNy@6v4d#AS> zXJd$>O+!paJ9LHv+f4>?hQ~M2PMWqUPcif)cY;eTM6ruOo1L4Vn#~tt=)!IdaUFZG zm!aQB_o{Zr<}y>3(($;v%H7N)O~-E(%Z9zo8M>CaJjbt9xhH41EQ=C_o=i<&HCBy` zMJAbobWMAiLhnY8hG%s2Vn4Y(X+WtHieY&S`;sB|*`=$zD6^?cQ9Q?h7%_T4$3Y|* zbdTGmbKG-;?NKDzMvhO3I6D;r4`TCq=wpb?%@*dP7$9Ol>f^2}+`f^%Mp6k|$b?~8 z;yN$&ee4r;M8^wAGVI#SKPO6SKGi|?rpQd$PF2z-+^7%%X$)#Os$&Sl414MXY_*}3 z$h0(SS-CaIiHS%uwU}$eF}$eZB^@v06^27~N1Ht92wacOrXWc@hFcnIypvzc`T2<} z#~JoFat#{?M)mV}&DYWE3CL&@qB6Lx7Koop0uFtmBx^Gsn+mD=$pPHPy|k;51v))Q(PGpNKU!;vsQWIUZel$}-J75{e{wY~gl;hbJqNlAgmQUm}YP$>gOF`GHSprFlXNB-$~ekfC$h zw0XW-S>o=zv1IwJqESn8hHF%~BEg z`1Ibdx9>mr;nst%)_=S6^+p#;mK$zcp#5&>!7*^n8!r z`s?pNdwTFYu=LWSQs)`A<1qJ$jaaoPRQgsNm4UQVaCu%!B zQ#)V~3+;&XbU*U@Z9ah|T8PkAMS60YEBFx0^>G|!8l&`Wh5k)kqqqG~$zmKXJ)<;w M5d{*fxPjh(0H+~#Z~y=R literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..de3d7545570ca66b33dd37bd23a31ede7ed7914c GIT binary patch literal 1894 zcmb_cZC4vr5Pt3@WH({U%eD;$wWR@TUK$o{t3W7)KqFKjNK&*#ZI|RWY~Ad}-AyZc z{Ok{~e$ap5$9gpQa*oH39)Fa_*-c0z;L#7BoU?c4W@hfpGtbN)fByU{fF;x-;OLVO zQqYeuL!x5WwYu)@n?iRiZ9_M#$!$?HTu(Twx>YrW!w~lN4R>;y;oSO3^IQ}%A`+qs z2B0upIB7DO*In^E+Pq;I-U7pD^0aWN9T|fRQgN%iR@^K_F^mxjs)DmP$1veXcbk@G z2~XSiyoM{B$HLK8Nxbz*WnZ^yf?>EOylwGuQ@GxS@b>L0rJhW!KhhuTnn@;F$#V>= zMybazD&YkMag34MaRVxyqUff}a6Z}NUfg>mDqb#iPsU3Oh!Un36kNnOgW?LSx-Hy> zZMl?5u3h85WSm>;3Es)g$05NG+A5aHGA0Sw&l19MY$q|7XcskZ+1|Krn)VY>O?>VH zby>lyNHPpQuRm{B4}7RQ)f=|9W;L1~JtFiv0gy&U!W9KsOfj4d0QkENl|-i1CDY6w zc!H1!B~!ck2&VCxgx3{Z#WjXYfulv9)B?w)-jqCIkM2~L+dBF6-zgXF&oGR&Ywb1e z7zO=!!{^bP3>TBT`G2-d?f9V2Dwso#;Y`DSv|u~+72VT`CB4l$!m}N$=@}-`ypfY} zgK`pe-7p7m6N?g-6y&i?(Sl-*3>o?eO@_<8F^>q))3(l)j9Ww`Cm10|_YB)wwyQ$M zTMTlO$ZF|z($+|8=&t+3cB(SoW*Dm2)Iu7N7hKQnwEeY=^*hYy#Jvm}z z+>HmC_IyS|1s@K%?hM_GrjH5}Q)^glYu!DE~ePZ8sZHr;{_y#!L z_ms&c8v3{raO;L8Hkf*23I~J zrgXwaX}ySs-%wY=gWg#wcK>0Bmh7fe5e374E#j}!DW6T$o=sXttF}u_Qr0X>ILjur z+MlPP6Z>|cXJ2BRfRkx=v*BTXWs}6|N2`{;?~yhU=)gca^8;8qa|r2~Z;re44busp z!99}uNu(GIyLi9t%f=v4B;ZH&Os0jQ7S4Z-!E|N>zpF2{@bWYDQs?@c;F^7o+_%&qt zbxiRYEb>_tcn&2#j|cn)>U;s8@|*aAFXAcB<6FLrL%xC!C}IeFG=>iYiQzu_pa<{l Wp%R=$ROwU$+=~!&$~2!3L;NpiIqwqy literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..e2419eb2144be39a18e68480ebca674f5a1a14d6 GIT binary patch literal 2772 zcma)8+jA3D82_DY+D+31O1KsfN*gfgg@DMdMU)mwi@ixofmX$Ba%{IvcEj!lsEAxd zMCDSXTpv&r2ge7n2;-R=~cE`A^tD#0&QT<`AMtATo#V~c*R5Z0li}E^IjmEgn zkZX1;hJPi)?1rgZtGw_aPlQ)OJ|u?4Q&s%cvXOzdQBf6h6T`efHn?D09;Rc4hyn>S z;bSQ1k@w4?n5=e%!hMFx;|zk9G#TbJ*ei+_YS9(d44XQa<5eEaW>`3K^TcTX$&qvC z$B!O+^wakvCr^)leQfN`(4)cQUd+Wj5%VP!VgbXfEFcVG!h(#cbV|TE#xcMoaaUEa z&4Wdx)ZEfq-`o`TVlkG8D3Y)g#SA4@1dOB_Qn?xGHqC^=_5EBA)zNh8!ALiG!pW^J zZtmdwlH4#Gx!J8nDZGK;)U&+sW0{EM5?)4Nax`pXC_RKC$Bd^;ZSL&h5wj}T?m;O7 zyi^0_5-PBQK{D)Y8wpJ{$dW224==E|s(z|%Rvf4-+%3)FRu5jGLx~}QPmBo%z zMXF{N$+4JrfJciDTY-92!Wyh)nEu57YAxDll|$NlN@%^BNKPcwi}lzbqEbQ?HfH22 zLx)_V+($RZV%2>nr%1R1!H()YY{Kgz-jJvVsu`BriB<`nQlJ}@o3Ke0F6+@6=bQHB z>};*wyPjcz<7=jJT8YZtk1bZMZ)I2#=%{|SX0Xji{kKg*9qP%wxZKNYG&LfdyA-pV zW(FN^(xJ<o}k8PCI@+3R$}>h z3p+%FCA4BEq1lm{P^9*v)I4R@L^WlYl@|HHu+59z*dwA{LI>Vv@J;0as&1$1CUXqK zhODMf28a_I#X@pI32ja&JGfK0lnEE!m9Q7@SrnyhH#BNjg8M&vvoxBI;I@f~Oq7`2 z@YJt7VG*K5N?gMG79$B%<6d;4TY_RWyqDtD$PGj8;ywsgG&&KJ5C_>a!zL1{v`BBO zE=Q={gg~%OL?X=-Pk1=1lRmgDJPn3ba+H-opgki8#CaAUWk@Cx)kaNVkvLhH202+!t!bup6(t-?4G%u19(VZruU{@y z7BLS#A;KHG_3fkU{UfJ-9KCj8{P^wB+k^Jfr{uN6{UaC7j0_Lh!q12Tp1KeoT~3i? zbl|J;fvaP8?$~NyFw7r2J2Z0c()bUj$L<`Xdt>D0;Ml$IXmv&|&UkSa=S1{dZGE1> zZ}*N}D~h^b>*d5MR!*EwuazUFrW3hc$*l6UqT`!$%NqU$P3ui2GE+GoqaiFf8g^_}pKC{EVwy#3hDhQ~b~7mWV5KIXqvL ziqMGxil`GkM4hal!1`mMnTsC!yPz>iUnTZ8kY8GMAFQ-&2;!inj{P*|(i=hn4$wS@ zri8(85Pi;G){#d1^Dd_OW~DI4x3DaQmr^LXis_|gGx5+DOrdPh7fOq-*-WG4-6`y< z%prMcVNMF~3`2I-tg{^v9drxp2sui4UBl?H6=>f30NNhG5$+?0hoCo+&Ft^e3PQ5% zBVX6zI&KgHx$JPX)87t+S?~yRFk6_5#lk!+5f-3KSco;kBCHjPP$w)!t5AY=!H+Is zIZPpdBSH}ULMg5bD{(_8!#6@X289aT7gpe*5W*kADttg8&WC%++<(v`qH{G4k-$wR zd`RO*GjF?D3>Mp0dZ!@g-?3AP#lWg>r#L54{K6E?mTA HTt(r3RPG%8 literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..bf68e842f2a3edcb45e524bc6754792a6e045a86 GIT binary patch literal 2443 zcmah~ZF3V<6n^eD?WXBMOQ5Yqh0+F0Qrh4fLW4+Cs13GFC8a>C;x@T9OOxHOdsC>0 zFZji8G6T-|GULk#!{~@(u>^$~$B&M`L(w1LjNcs3ZZ>3Tqf92d_ntlXx%WKhIp_ZR z&+VT84B_2oNNAAZQ_zSeh8-EB5G$x6m*=Xf$HrAn52Z_U1x*a;)){V&s(LohO@=0s z)2z@ghD~E@m&60`qgh5kK?@XyEo)su3Dx2?w0)YciTweF+Iv25=5Jiidi`z0%Tsfwct*q{Gk!e6 zfB^BjMZs2dGbk3>uf?A*vP(AAZuFWFOX|gvpiQ`1AOfQ3ld)4l zKL!{!It1MBLm`oCb|{}uED26b_`;FdL^F2baT!l2coI)BY;zXsw31R_T9li#AoZwb zcDOR9b&W@-Mo#Ww*j$O#>+Cu?`Pgmi=oyBs;n~E0dq$>h()TJDM4Vw=(cW~#FbfA& zp^{3x$*S^M0V@eDPf{<&{dkt4+2WR^8G16?g6D8R#*l&ph6&LLsOrqnK#WqwcyX&D z@TAT)`EiI49QoPUdX}FJ;CYP7NGdpt7Z^6wl$O*5pSP>b?*u{9Rbs22Kk3IfLyPLv zrVEL9896_2PxVG|aJ$fqI(PM3E7de@XtSZEUk>&ZATGV1gMXf4k%8rDi3Z`+) zZVAR=%g`D2t}f#GYwHxBj1yJGIWRgOKmbWH)wAZtsKia8vfS?l1j zR24BzMKVkjGPI6qI-e*N=D0bf&gIF{R;k@d)l>^yaFb5bL|uy-t&Q*G;X%zJLip>b zzA_7>V;44Xk3CBUrKMKMse50Dq_j~oGkip|cWbsA{(!9p(%uBM%2C52?X@KgLs-I8 ziZeRK1`sKS{y!ZQ+G>MXdYw7Y679PQ7VWzQdD(WyJUyG}4e1l)XxvCc!eG#FsO<~!&(K_9l45xIfbEj&FQ z-C4$-iT>ceAF*G;&*&KR^#>1DCqH0hcVmBW%sX$2u7Gv<+8f)O%9t3Gon50{av4*! z#WjS+?_lOc1L3}O8z(8ATgXh16ZA?{Q69!HQJI0@2a} zUuVbP$jUh0jXW8Av}J*w28|^YaoTyOVA9)9-%9kiaE@l1(Lf$4yg^Stz0dn3yotAQ H0bTzBRRXMe literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main.class b/src/java-backend/math_learn/src/com/mathlearn/Main.class new file mode 100644 index 0000000000000000000000000000000000000000..cd98b8c74bfc37346a2cc9babaadc4b24ae200e1 GIT binary patch literal 16119 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 accounts; + private Map pendingRegistrations; // 待完成注册的用户 + private Map userExams; // 用户当前试卷 + private Map userSessions; // 用户会话 + private String baseDirectory = "math_questions"; + private Random random = new Random(); + + public Main() { + initializeAccounts(); + pendingRegistrations = new HashMap<>(); + userExams = new HashMap<>(); + userSessions = new HashMap<>(); + createBaseDirectory(); + } + + // 初始化预设账户 + private void initializeAccounts() { + accounts = new HashMap<>(); + + // 小学账号 + accounts.put("张三1", new UserAccount("张三1", "Abc123", "小学")); + accounts.put("张三2", new UserAccount("张三2", "Abc123", "小学")); + accounts.put("张三3", new UserAccount("张三3", "Abc123", "小学")); + + // 初中账号 + accounts.put("李四1", new UserAccount("李四1", "Abc123", "初中")); + accounts.put("李四2", new UserAccount("李四2", "Abc123", "初中")); + accounts.put("李四3", new UserAccount("李四3", "Abc123", "初中")); + + // 高中账号 + accounts.put("王五1", new UserAccount("王五1", "Abc123", "高中")); + accounts.put("王五2", new UserAccount("王五2", "Abc123", "高中")); + accounts.put("王五3", new UserAccount("王五3", "Abc123", "高中")); + } + + // 创建基础目录 + private void createBaseDirectory() { + File dir = new File(baseDirectory); + if (!dir.exists()) { + dir.mkdir(); + } + } + + // 生成注册码 + public String generateRegistrationCode(String email) { + String code = "REG" + random.nextInt(10000); + pendingRegistrations.put(email, new UserAccount(email, code)); + return code; + } + + // 用户注册 - 修改以保存邮箱 + public ApiResponse register(String email, String registrationCode, String username, String password, String confirmPassword, String userType) { + System.out.println("处理注册请求: " + username + ", 邮箱: " + email); + + // 验证注册码 + if (!pendingRegistrations.containsKey(email) || + !pendingRegistrations.get(email).getRegistrationCode().equals(registrationCode)) { + return new ApiResponse(false, "无效的注册码", null); + } + + // 验证用户名是否已存在 + if (accounts.containsKey(username)) { + return new ApiResponse(false, "用户名已存在", null); + } + + // 验证密码 + if (!password.equals(confirmPassword)) { + return new ApiResponse(false, "两次输入的密码不匹配", null); + } + + if (!isValidPassword(password)) { + return new ApiResponse(false, "密码必须为6-10位,且包含大小写字母和数字", null); + } + + // 验证用户类型 + if (!userType.equals("小学") && !userType.equals("初中") && !userType.equals("高中")) { + return new ApiResponse(false, "无效的用户类型", null); + } + + // 创建用户账户并保存邮箱 + UserAccount newAccount = new UserAccount(username, password, userType, email); + accounts.put(username, newAccount); + pendingRegistrations.remove(email); + + System.out.println("注册成功: " + username); + return new ApiResponse(true, "注册成功", null); + } + // 在math_question类中添加发送注册码的方法 + public ApiResponse sendRegistrationCode(String email) { + System.out.println("收到发送注册码请求,邮箱: " + email); + + // 验证邮箱格式 + if (!isValidEmail(email)) { + return new ApiResponse(false, "无效的邮箱格式", null); + } + + // 检查邮箱是否已注册 + for (UserAccount account : accounts.values()) { + if (email.equals(account.getEmail())) { + return new ApiResponse(false, "该邮箱已被注册", null); + } + } + + // 生成注册码 + String code = generateRegistrationCode(email); + + // 模拟发送邮件 + System.out.println("=== 邮件发送模拟 ==="); + System.out.println("收件人: " + email); + System.out.println("验证码: " + code); + System.out.println("=== 邮件发送完成 ==="); + + Map data = new HashMap<>(); + data.put("email", email); + // 注意:实际生产中不应该返回验证码,这里仅用于演示和测试 + data.put("debugCode", code); + + return new ApiResponse(true, "验证码已发送到您的邮箱", data); + } + + // 验证邮箱格式 + private boolean isValidEmail(String email) { + if (email == null) return false; + String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; + return email.matches(emailRegex); + } + + + + + // 验证密码格式 + private boolean isValidPassword(String password) { + if (password.length() < 6 || password.length() > 10) { + return false; + } + + boolean hasUpper = false; + boolean hasLower = false; + boolean hasDigit = false; + + for (char c : password.toCharArray()) { + if (Character.isUpperCase(c)) hasUpper = true; + if (Character.isLowerCase(c)) hasLower = true; + if (Character.isDigit(c)) hasDigit = true; + } + + return hasUpper && hasLower && hasDigit; + } + + // 用户登录 + public ApiResponse login(String username, String password) { + UserAccount account = accounts.get(username); + if (account != null && account.getPassword().equals(password)) { + // 生成会话ID + String sessionId = generateSessionId(); + userSessions.put(sessionId, username); + + Map data = new HashMap<>(); + data.put("sessionId", sessionId); + data.put("userType", account.getUserType()); + data.put("username", username); + + return new ApiResponse(true, "登录成功", data); + } + return new ApiResponse(false, "用户名或密码错误", null); + } + + // 生成会话ID + private String generateSessionId() { + return "SESS" + System.currentTimeMillis() + random.nextInt(1000); + } + + // 验证会话 + private String validateSession(String sessionId) { + return userSessions.get(sessionId); + } + + // 修改密码 + public ApiResponse changePassword(String sessionId, String oldPassword, String newPassword, String confirmPassword) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + UserAccount account = accounts.get(username); + if (!account.getPassword().equals(oldPassword)) { + return new ApiResponse(false, "原密码错误", null); + } + + if (!newPassword.equals(confirmPassword)) { + return new ApiResponse(false, "两次输入的新密码不匹配", null); + } + + if (!isValidPassword(newPassword)) { + return new ApiResponse(false, "新密码必须为6-10位,且包含大小写字母和数字", null); + } + + account.setPassword(newPassword); + return new ApiResponse(true, "密码修改成功", null); + } + + // 生成试卷 - 添加详细日志 + public ApiResponse generateExam(String sessionId, String userType, int questionCount) { + System.out.println("🚀 === 开始生成试卷 ==="); + System.out.println("📅 时间: " + new Date()); + System.out.println("👤 用户: " + validateSession(sessionId)); + System.out.println("🎯 类型: " + userType); + System.out.println("📊 数量: " + questionCount); + + try { + String username = validateSession(sessionId); + if (username == null) { + System.out.println("❌ 会话验证失败"); + return new ApiResponse(false, "会话无效或已过期", null); + } + + if (questionCount < 10 || questionCount > 30) { + return new ApiResponse(false, "题目数量应在10-30之间", null); + } + + // 获取题目生成器 + QuestionGenerator generator = getQuestionGenerator(userType); + if (generator == null) { + return new ApiResponse(false, "无效的用户类型", null); + } + + System.out.println("✅ 开始生成题目..."); + + // 完全移除去重逻辑,先保证能生成题目 + List questions = new ArrayList<>(); + + for (int i = 0; i < questionCount; i++) { + System.out.println("🔄 尝试生成第 " + (i + 1) + " 题..."); + + try { + Question question = generator.generateQuestion(); + if (question == null) { + System.out.println("❌ 第 " + (i + 1) + " 题生成返回了null"); + continue; + } + + questions.add(question); + System.out.println("✅ 第 " + (i + 1) + " 题: " + question.getQuestionText()); + System.out.println(" 选项: " + question.getOptions()); + System.out.println(" 答案: " + question.getCorrectAnswerIndex()); + + } catch (Exception e) { + System.err.println("💥 生成第 " + (i + 1) + " 题时发生异常: " + e.getMessage()); + e.printStackTrace(); + // 继续生成下一题,不要因为一题失败就停止 + } + + // 添加小延迟,避免快速循环问题 + Thread.sleep(50); + } + + if (questions.isEmpty()) { + System.err.println("💥 严重错误:一道题目都没有生成成功!"); + return new ApiResponse(false, "无法生成任何题目,请检查系统配置", null); + } + + System.out.println("🎉 题目生成完成,共 " + questions.size() + " 题"); + + // 创建试卷 + Exam exam = new Exam(questions); + userExams.put(sessionId, exam); + + // 返回第一题 + Map data = new HashMap<>(); + data.put("examId", exam.getExamId()); + data.put("totalQuestions", questions.size()); // 使用实际生成的数量 + data.put("currentQuestion", 0); + data.put("question", questions.get(0).getQuestionText()); + data.put("options", questions.get(0).getOptions()); + + System.out.println("✅ === 试卷生成成功 ==="); + return new ApiResponse(true, "试卷生成成功", data); + + } catch (Exception e) { + System.err.println("💥 生成试卷时发生严重异常: " + e.getMessage()); + e.printStackTrace(); + return new ApiResponse(false, "系统错误: " + e.getMessage(), null); + } + } + + + + // 获取题目 + public ApiResponse getQuestion(String sessionId, int questionIndex) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + List questions = exam.getQuestions(); + if (questionIndex < 0 || questionIndex >= questions.size()) { + return new ApiResponse(false, "无效的题目索引", null); + } + + Question question = questions.get(questionIndex); + + Map data = new HashMap<>(); + data.put("examId", exam.getExamId()); + data.put("totalQuestions", questions.size()); + data.put("currentQuestion", questionIndex); + data.put("question", question.getQuestionText()); + data.put("options", question.getOptions()); + data.put("userAnswer", exam.getUserAnswers().get(questionIndex)); + + return new ApiResponse(true, "获取题目成功", data); + } + + // 提交答案 + public ApiResponse submitAnswer(String sessionId, int questionIndex, int answerIndex) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + exam.setAnswer(questionIndex, answerIndex); + + Map data = new HashMap<>(); + data.put("currentQuestion", questionIndex); + + return new ApiResponse(true, "答案提交成功", data); + } + + // 完成考试 + public ApiResponse finishExam(String sessionId) { + String username = validateSession(sessionId); + if (username == null) { + return new ApiResponse(false, "会话无效或已过期", null); + } + + Exam exam = userExams.get(sessionId); + if (exam == null) { + return new ApiResponse(false, "没有进行中的考试", null); + } + + double score = exam.calculateScore(); + + // 保存考试记录 + saveExamResult(username, exam, score); + + // 移除当前考试 + userExams.remove(sessionId); + + Map data = new HashMap<>(); + data.put("score", score); + data.put("totalQuestions", exam.getQuestions().size()); + + return new ApiResponse(true, "考试完成", data); + } + + // 保存考试结果 + private void saveExamResult(String username, Exam exam, double score) { + String userDir = baseDirectory + File.separator + username; + File dir = new File(userDir); + if (!dir.exists()) { + dir.mkdir(); + } + + String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String filename = userDir + File.separator + timestamp + "_score_" + String.format("%.1f", score) + ".txt"; + + try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) { + writer.println("考试ID: " + exam.getExamId()); + writer.println("考试时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(exam.getStartTime())); + writer.println("得分: " + String.format("%.1f", score) + "分"); + writer.println(); + + List questions = exam.getQuestions(); + List userAnswers = exam.getUserAnswers(); + + for (int i = 0; i < questions.size(); i++) { + Question q = questions.get(i); + writer.println((i + 1) + ". " + q.getQuestionText()); + List options = q.getOptions(); + for (int j = 0; j < options.size(); j++) { + String prefix = (j == q.getCorrectAnswerIndex()) ? "[正确答案] " : + (j == userAnswers.get(i)) ? "[您的答案] " : ""; + writer.println(" " + (char)('A' + j) + ". " + prefix + options.get(j)); + } + writer.println(); + } + } catch (IOException e) { + System.out.println("保存考试结果失败: " + e.getMessage()); + } + } + + // 获取对应的题目生成器 + private QuestionGenerator getQuestionGenerator(String userType) { + System.out.println("🎯 为类型 '" + userType + "' 选择题目生成器"); + switch (userType) { + case "小学": + System.out.println("使用修复后的小学题目生成器 - 支持1-5个操作数"); + return new PrimarySchoolGenerator(); + case "初中": + System.out.println("使用修复后的初中题目生成器"); + return new JuniorHighGenerator(); + case "高中": + System.out.println("使用修复后的高中题目生成器"); + return new SeniorHighGenerator(); + default: + System.out.println("未知用户类型,使用稳定生成器"); + return new StableQuestionGenerator(); + } + } + + // 退出登录 + // 在logout方法中添加更详细的日志 + public ApiResponse logout(String sessionId) { + System.out.println("=== 退出登录处理 ==="); + System.out.println("请求的sessionId: " + sessionId); + System.out.println("当前活跃会话: " + userSessions.keySet()); + + String username = userSessions.remove(sessionId); + userExams.remove(sessionId); + + System.out.println("移除的用户名: " + username); + System.out.println("移除后活跃会话: " + userSessions.keySet()); + + // 即使sessionId无效,也返回成功,确保前端可以继续流程 + if (username != null) { + System.out.println("退出登录成功 - 用户: " + username); + return new ApiResponse(true, "退出成功", null); + } else { + System.out.println("退出登录 - sessionId无效,但返回成功"); + return new ApiResponse(true, "退出成功", null); + } + } + + // 启动HTTP服务器 + public void startServer(int port) throws IOException { + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + + // 注册端点 + server.createContext("/api/register", new RegisterHandler()); + server.createContext("/api/login", new LoginHandler()); + server.createContext("/api/change-password", new ChangePasswordHandler()); + server.createContext("/api/generate-exam", new GenerateExamHandler()); + server.createContext("/api/get-question", new GetQuestionHandler()); + server.createContext("/api/submit-answer", new SubmitAnswerHandler()); + server.createContext("/api/finish-exam", new FinishExamHandler()); + server.createContext("/api/logout", new LogoutHandler()); + // 添加新的注册码相关端点 + server.createContext("/api/send-registration-code", new SendRegistrationCodeHandler()); + + server.setExecutor(null); + server.start(); + + System.out.println("数学学习系统服务器已启动,端口: " + port); + } + + // 内部HTTP处理器类 + private abstract class BaseHandler implements HttpHandler { + protected Map parseFormData(String formData) { + Map params = new HashMap<>(); + if (formData != null && !formData.isEmpty()) { + String[] pairs = formData.split("&"); + for (String pair : pairs) { + String[] keyValue = pair.split("="); + if (keyValue.length == 2) { + try { + params.put(keyValue[0], java.net.URLDecoder.decode(keyValue[1], "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + } + return params; + } + + protected void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException { + exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8"); + exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*"); + exchange.getResponseHeaders().set("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + exchange.getResponseHeaders().set("Access-Control-Allow-Headers", "Content-Type"); + + exchange.sendResponseHeaders(statusCode, response.getBytes("UTF-8").length); + OutputStream os = exchange.getResponseBody(); + os.write(response.getBytes("UTF-8")); + os.close(); + } + + protected String toJson(ApiResponse response) { + // 简化的JSON序列化,实际应用中可以使用Jackson等库 + return "{\"success\":" + response.isSuccess() + + ",\"message\":\"" + response.getMessage() + "\"" + + ",\"data\":" + objectToJson(response.getData()) + "}"; + } + + private String objectToJson(Object obj) { + if (obj == null) return "null"; + if (obj instanceof Map) { + Map map = (Map) obj; + StringBuilder sb = new StringBuilder("{"); + boolean first = true; + for (Map.Entry entry : map.entrySet()) { + if (!first) sb.append(","); + sb.append("\"").append(entry.getKey()).append("\":"); + sb.append(objectToJson(entry.getValue())); + first = false; + } + sb.append("}"); + return sb.toString(); + } else if (obj instanceof List) { + List list = (List) obj; + StringBuilder sb = new StringBuilder("["); + boolean first = true; + for (Object item : list) { + if (!first) sb.append(","); + sb.append(objectToJson(item)); + first = false; + } + sb.append("]"); + return sb.toString(); + } else if (obj instanceof String) { + return "\"" + obj.toString().replace("\"", "\\\"") + "\""; + } else { + return obj.toString(); + } + } + } + + private class RegisterHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String email = params.get("email"); + String registrationCode = params.get("registrationCode"); + String username = params.get("username"); + String password = params.get("password"); + String confirmPassword = params.get("confirmPassword"); + String userType = params.get("userType"); + + ApiResponse response = register(email, registrationCode, username, password, confirmPassword, userType); + sendResponse(exchange, 200, toJson(response)); + } + } + + private class LoginHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String username = params.get("username"); + String password = params.get("password"); + + ApiResponse response = login(username, password); + sendResponse(exchange, 200, toJson(response)); + } + } + + //处理器都正确实现 + private class GenerateExamHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + String userType = params.get("userType"); + int questionCount = Integer.parseInt(params.get("questionCount")); + + ApiResponse response = generateExam(sessionId, userType, questionCount); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "生成试卷失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class GetQuestionHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + int questionIndex = Integer.parseInt(params.get("questionIndex")); + + ApiResponse response = getQuestion(sessionId, questionIndex); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "获取题目失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class SubmitAnswerHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + int questionIndex = Integer.parseInt(params.get("questionIndex")); + int answerIndex = Integer.parseInt(params.get("answerIndex")); + + ApiResponse response = submitAnswer(sessionId, questionIndex, answerIndex); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "提交答案失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class FinishExamHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + + ApiResponse response = finishExam(sessionId); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "完成考试失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class ChangePasswordHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + String oldPassword = params.get("oldPassword"); + String newPassword = params.get("newPassword"); + String confirmPassword = params.get("confirmPassword"); + + ApiResponse response = changePassword(sessionId, oldPassword, newPassword, confirmPassword); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "修改密码失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + private class LogoutHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + Map params = parseFormData(requestBody); + + String sessionId = params.get("sessionId"); + + ApiResponse response = logout(sessionId); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + ApiResponse errorResponse = new ApiResponse(false, "退出登录失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + // 发送注册码的处理器 + private class SendRegistrationCodeHandler extends BaseHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + System.out.println("处理发送注册码请求"); + + if ("OPTIONS".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 200, ""); + return; + } + + if (!"POST".equals(exchange.getRequestMethod())) { + sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); + return; + } + + try { + String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + System.out.println("请求体: " + requestBody); + + Map params = parseFormData(requestBody); + String email = params.get("email"); + + System.out.println("解析到的邮箱: " + email); + + ApiResponse response = sendRegistrationCode(email); + System.out.println("发送响应: " + toJson(response)); + sendResponse(exchange, 200, toJson(response)); + } catch (Exception e) { + System.err.println("发送注册码时发生错误: " + e.getMessage()); + e.printStackTrace(); + ApiResponse errorResponse = new ApiResponse(false, "获取验证码失败: " + e.getMessage(), null); + sendResponse(exchange, 500, toJson(errorResponse)); + } + } + } + + + public static void main(String[] args) { + try { + Main system = new Main(); + system.startServer(8080); // 启动在8080端口 + } catch (IOException e) { + System.err.println("启动服务器失败: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..83e17f3b359761a1129f6a1fd01d4c70f4966b34 GIT binary patch literal 5985 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 options = generateOptions(correctAnswerValue, isIntegerAnswer); + String correctAnswerStr = isIntegerAnswer ? + String.valueOf((int)correctAnswerValue) : + String.format("%.2f", correctAnswerValue); + int correctIndex = options.indexOf(correctAnswerStr); + + return new Question(questionText, options, correctIndex); + } + + // 生成考虑优先级的算术题目 + private String generateArithmeticQuestion() { + int operandCount = random.nextInt(3) + 2; // 2-4个操作数 + StringBuilder question = new StringBuilder(); + List tokens = new ArrayList<>(); + + // 生成操作数 + for (int i = 0; i < operandCount; i++) { + if (i > 0) { + // 随机选择运算符,考虑优先级 + String[] availableOps; + if (i == 1 && operandCount > 2) { + // 第一个运算符倾向于用乘除,确保优先级测试 + availableOps = new String[]{"×", "÷", "+", "-"}; + } else { + availableOps = new String[]{"+", "-", "×", "÷"}; + } + String op = availableOps[random.nextInt(availableOps.length)]; + tokens.add(op); + question.append(" ").append(op).append(" "); + } + + // 生成合适的操作数 + int num; + if (tokens.size() > 0 && (tokens.get(tokens.size()-1).equals("÷"))) { + // 除法:生成能整除的数 + num = generateDivisibleNumber(); + } else { + num = random.nextInt(30) + 1; // 1-30 + } + tokens.add(String.valueOf(num)); + question.append(num); + } + question.append(" = ?"); + + return question.toString(); + } + + // 生成能整除的数(用于除法运算) + private int generateDivisibleNumber() { + int[] smallNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + return smallNumbers[random.nextInt(smallNumbers.length)]; + } + + // 计算简单运算(支持负数) + private int calculateSimpleOperation(int a, int b, String op) { + switch (op) { + case "+": return a + b; + case "-": return a - b; + case "×": return a * b; + default: return a + b; + } + } + + // 计算表达式(考虑运算优先级)- 使用自定义解析器避免ScriptEngine问题 + private double evaluateExpression(String expression) { + try { + // 移除空格 + expression = expression.replaceAll(" ", ""); + + // 使用递归下降解析器计算表达式 + return evaluate(expression); + } catch (Exception e) { + System.err.println("计算表达式失败: " + expression + ", 错误: " + e.getMessage()); + return 0; + } + } + + // 递归计算表达式 + private double evaluate(String expr) { + if (expr.isEmpty()) return 0; + + // 处理加减法 + String[] plusMinus = expr.split("(?=[+-])", 2); + if (plusMinus.length > 1) { + double left = evaluate(plusMinus[0]); + double right = evaluate(plusMinus[1].substring(1)); + return plusMinus[1].charAt(0) == '+' ? left + right : left - right; + } + + // 处理乘除法 + String[] multDiv = expr.split("(?=[×÷])", 2); + if (multDiv.length > 1) { + double left = evaluateTerm(multDiv[0]); + double right = evaluateTerm(multDiv[1].substring(1)); + return multDiv[1].charAt(0) == '×' ? left * right : left / right; + } + + // 处理基本项(数字或括号表达式) + return evaluateTerm(expr); + } + + // 计算基本项 + private double evaluateTerm(String term) { + if (term.startsWith("(") && term.endsWith(")")) { + return evaluate(term.substring(1, term.length() - 1)); + } + + // 处理平方符号 + if (term.endsWith("²")) { + double base = evaluateTerm(term.substring(0, term.length() - 1)); + return base * base; + } + + try { + return Double.parseDouble(term); + } catch (NumberFormatException e) { + System.err.println("解析数字失败: " + term); + return 0; + } + } + + private int getPerfectSquare() { + int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; + return perfectSquares[random.nextInt(perfectSquares.length)]; + } + + private List generateOptions(double correctAnswer, boolean isInteger) { + List options = new ArrayList<>(); + + String correctStr = isInteger ? + String.valueOf((int)correctAnswer) : + String.format("%.2f", correctAnswer); + options.add(correctStr); + + Set used = new HashSet<>(); + used.add(correctStr); + + // 生成3个错误选项 + while (options.size() < 4) { + double wrongValue; + String wrongStr; + + do { + // 根据正确答案的大小调整变化范围 + double range = Math.max(5, Math.abs(correctAnswer) * 0.3); + double variation = (random.nextDouble() * range) + 1; + boolean positive = random.nextBoolean(); + + wrongValue = correctAnswer + (positive ? variation : -variation); + + if (isInteger) { + wrongValue = Math.round(wrongValue); + wrongStr = String.valueOf((int)wrongValue); + } else { + wrongValue = Math.round(wrongValue * 100) / 100.0; + wrongStr = String.format("%.2f", wrongValue); + } + } while (used.contains(wrongStr) || Double.isNaN(wrongValue) || Double.isInfinite(wrongValue)); + + options.add(wrongStr); + used.add(wrongStr); + } + + Collections.shuffle(options); + return options; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..bbca5cb70b0d4c3394c1ef20aed1e7e82578c44e GIT binary patch literal 5880 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 literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java new file mode 100644 index 0000000..01a4cec --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java @@ -0,0 +1,219 @@ +package com.mathlearn.generator; + +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class PrimarySchoolGenerator implements QuestionGenerator { + private Random random = new Random(); + private String[] operators = {"+", "-", "×", "÷"}; + private int maxAttempts = 100; // 最大尝试次数,避免无限循环 + + @Override + public Question generateQuestion() { + int attempts = 0; + while (attempts < maxAttempts) { + attempts++; + try { + // 生成2-3个操作数,避免太复杂 + int operandCount = random.nextInt(2) + 2; // 2-3个操作数 + StringBuilder question = new StringBuilder(); + List operands = new ArrayList<>(); + List usedOperators = new ArrayList<>(); + + // 生成操作数和运算符,确保表达式合法 + for (int i = 0; i < operandCount; i++) { + if (i > 0) { + String op = operators[random.nextInt(operators.length)]; + question.append(" ").append(op).append(" "); + usedOperators.add(op); + } + // 生成合适的操作数范围 + int num = generateSuitableNumber(i, usedOperators, operands); + question.append(num); + operands.add(num); + } + question.append(" = ?"); + + // 验证表达式合法性 + if (!isExpressionValid(operands, usedOperators)) { + continue; // 重新生成 + } + + // 计算正确答案 + int correctAnswer = calculateAnswerWithPriority(operands, usedOperators); + + // 确保结果不为负数 + if (correctAnswer < 0) { + continue; // 重新生成 + } + + // 生成选项并获取正确答案索引 + List options = generateOptions(correctAnswer); + int correctIndex = options.indexOf(String.valueOf(correctAnswer)); + + System.out.println("✅ 成功生成小学题目: " + question.toString() + " = " + correctAnswer); + return new Question(question.toString(), options, correctIndex); + + } catch (Exception e) { + System.err.println("生成小学题目失败,尝试次数: " + attempts + ", 错误: " + e.getMessage()); + // 继续尝试 + } + } + + // 如果多次尝试都失败,返回一个简单的默认题目 + System.out.println("⚠️ 使用默认小学题目"); + return new Question("2 + 3 = ?", Arrays.asList("5", "6", "4", "7"), 0); + } + + // 生成合适的数字 + private int generateSuitableNumber(int index, List operators, List operands) { + if (index == 0) { + // 第一个操作数 + return random.nextInt(50) + 1; // 1-50 + } + + // 根据前一个运算符决定当前操作数的范围 + String lastOperator = operators.get(operators.size() - 1); + switch (lastOperator) { + case "-": + // 减法:第二个操作数不能太大,避免负数 + int previous = operands.get(operands.size() - 1); + return random.nextInt(Math.min(previous, 20)) + 1; + case "÷": + // 除法:除数要小,且要能整除 + previous = operands.get(operands.size() - 1); + List divisors = findDivisors(previous); + if (!divisors.isEmpty()) { + return divisors.get(random.nextInt(divisors.size())); + } + return random.nextInt(10) + 1; // 备选 + case "×": + // 乘法:避免结果太大 + return random.nextInt(5) + 1; // 1-5 + default: + return random.nextInt(50) + 1; // 1-50 + } + } + + // 找到能整除的数 + private List findDivisors(int number) { + List divisors = new ArrayList<>(); + for (int i = 1; i <= Math.min(number, 10); i++) { + if (number % i == 0) { + divisors.add(i); + } + } + return divisors; + } + + // 验证表达式是否合法 + private boolean isExpressionValid(List operands, List operators) { + try { + // 计算中间结果,验证每一步都合法 + int result = operands.get(0); + for (int i = 0; i < operators.size(); i++) { + String op = operators.get(i); + int next = operands.get(i + 1); + + switch (op) { + case "-": + if (result < next) return false; // 减法结果不能为负 + break; + case "÷": + if (next == 0 || result % next != 0) return false; // 除数不能为0且要能整除 + break; + } + + result = applyOperation(result, op, next); + if (result < 0) return false; // 最终结果不能为负 + } + return true; + } catch (Exception e) { + return false; + } + } + + // 考虑运算优先级的计算 + private int calculateAnswerWithPriority(List operands, List operators) { + if (operands.size() == 1) return operands.get(0); + + // 先处理所有乘除法 + List processed = new ArrayList<>(); + processed.add(operands.get(0)); + + for (int i = 0; i < operators.size(); i++) { + String op = operators.get(i); + int nextOperand = operands.get(i + 1); + + if (op.equals("×") || op.equals("÷")) { + // 执行乘除运算 + int lastIndex = processed.size() - 1; + int lastValue = (Integer) processed.get(lastIndex); + int result = applyOperation(lastValue, op, nextOperand); + processed.set(lastIndex, result); + } else { + // 加减法先保留 + processed.add(op); + processed.add(nextOperand); + } + } + + // 再处理加减法 + int result = (Integer) processed.get(0); + for (int i = 1; i < processed.size(); i += 2) { + String op = (String) processed.get(i); + int nextOperand = (Integer) processed.get(i + 1); + result = applyOperation(result, op, nextOperand); + } + + return result; + } + + // 执行单个运算 + private int applyOperation(int a, String operator, int b) { + switch (operator) { + case "+": return a + b; + case "-": return a - b; // 前面已经验证不会为负 + case "×": return a * b; + case "÷": return a / b; // 前面已经验证能整除 + default: return a; + } + } + + private List generateOptions(int correctAnswer) { + List options = new ArrayList<>(); + options.add(String.valueOf(correctAnswer)); + + Set used = new HashSet<>(); + used.add(correctAnswer); + + // 生成3个错误选项 + while (options.size() < 4) { + int variation = random.nextInt(10) + 1; + boolean add = random.nextBoolean(); + int wrongAnswer = add ? correctAnswer + variation : Math.max(0, correctAnswer - variation); + + if (!used.contains(wrongAnswer) && wrongAnswer != correctAnswer) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } + + // 防止无限循环 + if (options.size() < 4 && used.size() > 10) { + // 强制添加一些选项 + for (int i = 1; i <= 3; i++) { + int forcedOption = correctAnswer + i * 2; + if (!used.contains(forcedOption)) { + options.add(String.valueOf(forcedOption)); + used.add(forcedOption); + if (options.size() >= 4) break; + } + } + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..2bfb7d72953038e7a332fe74d3cf7ade377a5fcc GIT binary patch literal 206 zcmX^0Z`VEs1_nn4PId++Mh4B~{9OIq#FC7h)Wo7Z{q)ql)S|?a{389p($wOT%=|oe zmR%&tyPzb6g6{drcK~+Q32i4r%{FKxj{nU!YT)4s3 zj0{}C`K3k4scxA$sf-L_F#T{F^+1-fF)}bRFaur8z`zJ}04oC zL$X#M<&Z_rg6&`p4nunq%-uN;r@r7?xt>r$^DxlvP$(Jbp7f^YpWMOeIVIt&bQ|o#38&3Vo@>AexVb zzUE_}7<(8*dLqtbe5wBNyH+gDkR1pU_5u@Hs4_JFVUNMNP-MU3b7O>|RsQsgeX^6F zwZ}p0BSh?tkWr+uLAgYyLnM)kYmH~HMso?PQCnjDY1Oz%SXz}wgg40H7J1y!lP#(w Tu#NI6SFl6brjc1xunYSGAUbwI literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..4967054c76996721a92c3d694eb00a1d42016ae7 GIT binary patch literal 10033 zcmbta3wTu3wf@(<&Y8(cax%$;L;?cxNcLQhd zeb!!kt+n@Fd#$zCnKw=zd>O#`a&G`GxHWhTc;OS6*M_eT&+7_D+vYW{xi-?06!>a7 zq8-We1n$|zD>UdSq@H9)*SyQZ(bm|y05rJ$$bg|C(?Axo1*I*qb@SGRlkHuRa6CG% zEfS5y!^v2DUQ;C65sNSBXluVH1tXKVMMw}_W=W7nyjoGuF%U$qK#N9tll4)G<(XYy zT(2V}VE2TSP?qFP$#_S!O-CVRPIN?dOk|@ame4VYjbu0)ps1%Cn1ZQ-?6ydYQO)SrX3e&xP2*Z!UpyA3 z_{}mf8^xSpOSr40rz@O{TpsUeTM_Q+A09ZPg1BNy~`$0Lb^#kQ7g{|RlJ zJ~H;QNTR1JS?$NgSf-)Dz;ZMSYW_dO1c6AJY>vLCYmnl0se#MTB=D;Bpn^!9j?W6t zJbwRy_n-XYlo_qPuRT9yMnX00YRZBsXHI#4_onv-Z+>s^>EnA29N)S34~HKP;0j!+ zq1nJntP3b&Y8_WofYJc+@i_yl5$17S8;kR73o6Ii znpJ7KW*d>}Pucbs1FcG1CZ)EID<6wSqDdackxkG+**u)!LM1}Gfeu_tvEz~Mu5b(2 zrY>EE#qHsEQ{=jyNVFwVohHaA_@{`|Wni7s!bvGD99JBr<}m}^xXv;jwwgC~D-EYf z$eUfa(jjlzuw@;IBrRAz5^4+P>*(QJX3Q;L8^C(>YS^H_H;gi0b+Mi`$_|BQ*QE<; zgR3*J5ns@7qk)@nbL!X*v*NmRL|Y@hYCA_Ao76_sYq(V~b+iVri?v3&=0$qL>*l2n zYXG-klX42T3udM-ux(tOr5)x=vq#_1#}k~s`wp&-ErQG$ty4;=uTx&%!BWQ;1;(-4 zH@|ma=dtbEj&0qe<4ZP@)o-EdxXT8WrH#9L)VRL8bljUhPNC}fayq~L7HEe(?t@*A zrTFb~#;JaX-va{wj8+~kC8>_DaEB@5u>&vg+@*#+oWikLJ#s3J66vc1+EbnF&@R^T zxGe$aN>ZG+j((yIBcvAQDS_+t{YquNX5j1i7lGaqizdSzO1&ngZ^dYxUa4a*4TfTC zjegF+^LT;ghTbZkOeoiNicUD&Q_PVsa^&mwLhUF2*PhpLfQNpzjziQ}ZV6j2QMsHQ z)bR>moSo9~4Zb*gq~rDBo-!TZ93Hb@$G26Fz1r#!eb>Mn_#VwpBD^+ofn)ebj=i8D zeX@?Q_4W0|bwRlC1LfR)IKFbG9~)vh7w2Wqk0k$60SWB84M-zsw*Ujf z>&?o~ePZAwhIm}M!|_Cf-s_Y}rNuAW-y6PG(ykr@YEhY&ky1P0k!gw)a@i<1(x9}Z%e!g1WY25Uo z(|9G-^-2mdF3Xe$ppz0OkAF~`6}RI1io1Cvmx$(botvCRJY@pyQHa&G~d2RGfB z%s1pSayIp&BT*k+t8NYSVv62MUC!ZR9^L$qE)>*L#+DjTZAgt8;O$5(4=>k+mki(W z9eYmnf0bTNY7IGGsjxfT+N#OoRPMaX&)+!=DA)M|1O&H2dPft`v*y&+50 zDtHndH$;53c_Z^)Zb+lG#o;vx-@-TNTYqY{O@>@M>ztVp zM@l~`+=k-O9@+_zczsGa=!-@!Pad_sbS29=qLJl2>()f#mxrwgg0})YJV^}_%or03 zkK_ESxs*-Ga7$-HxZ5J7Nhf7Z*ILJdXhO@Gw<^8IITO^!rjE8~IN1}YY_rD+i)zLi zhx5oe&=l*5w?r=NQ0r4L&TVn7T2)?%mh)QC5K+^mc{6!6N+y!=aCbu_*&b_6=+Z-4 zGFx7IwphiEy3m~HM>p>l`)vbzt+%6FHmlyxQw^Q2F9@c+f8WE$H*Y`j$de~te)-tp zyQ-$hlvOACHyzu&i_NP^LUg%FaK?#e9(n(n9m9CX9((S@zQ>6&XUYfn?K-h{FPpmD z!Z>Z%R5?s;;|y$r;{a}_?Wg)E>9T#&7m&@eMU$<{@-SAKZmE)GqdTJ4$2ueP>~*&9 zr5A=$Hf+Sx+qW!D812m%GtKd&*Mw2v@!{e^-_KU8@4WMKfCUVf+3V+Cd5NB~n$lo`J&n)f7al)%?_<|9*8jSC;>%4}N zIRjWUhBBUE=Y>`NLjOK2ZBXSUV{x`xi;zvBO|7*e;Hk(kPlf{R6-Fqas?6Z!`b%&% zyF(d+SiuR0j0d0xuj+?4n8&Gy3=8ZFWu}9*P^JP8;+lp~ppP?{PD$2K%wQy#H-NSQ zbe<|nNpZ+KfM}I37hDr_dMD z_v5x_xi>Cr*T1FK4hDBWlmC?FWHb86VZtOA4amb)2w@F_tu9PJ4+^k}-n9=!xEqtP z1E=F*rkI|f{yl{=u$Mv7e(J!>n2B#N6?6op_%1c?M<~Nvn2UGG>wT2tcbJbq;WLa* z&K57um0UWhd{oIKRLgYK$XqOt)vQ}_9<^|xbYhWoW3hYzb#f<`$d{Q9*^Q<0C@z+L zSSGJvxpZ(Ae@Ffh1@~&mU~H4`roNxV5)F6oMQY`*@Ju}|zg9d$^!5HUBr5&IK&=c> z_tOU}Vwvf9JP|@iOLCfA%l{lfH!>E3L{b7aHcc%a_mb zlvjB?6c4bAv zWx;)llw4_z_S>X<{j#JiIAHOpN+)ac;8|1*dFDdi_Ojqr7M>pR^}`qPC0F-V>NHPf z!9fe&Fm}8n)~PZcwD7Y@)fduMxA*nKQ0>(rtzD7Ci~nazhb>AuHl=n;AgnJ7axJ-N z7Py@pETXH+g0GH%$*R=?*Ovuf8vzsB2A7uwk67T`khd@7>kDapu@)s;VOj87R)=YK z#Mr}*0zHdH+bk)wMH#?%xOwyg$})N#%jmOeZ%A`&-$8sIs0uuf9~A})Jq2_G{|*e` z=ZA1{b77!>X6vmHv-J#33-CGYqhWfLDXk-j($ri>5^iCxOkf5nE*o6E^qbPWdX+G~dE@c@uZbJGe)F$6U)t zxZmZ$4p%02x+Y?mYdUtj%JG1!8V|ba@fFu)c*wN|54$?C$JL9+T{qzg*PVFE^#Y!D z9l_Tv^Ylw(4^aqZc{J&=&62WAB5qK~f-yaGo>tGXn#`M^u^7HcxLb()$sSeu!$zd}0af9A14Q?L5yL3@SlR_S96AA$6~9l!wRduf>~V!zm__w>Km}ds<&ddRX>2QS+(t$*H9tA z^p+nlkn%p9h8Gzb4N&j*lky;HaDX2a4$?^Y_8q*9H!Q8pfstdHW-yqYZJLWT9Gl0ToWiNtapN8;go+C{ znYo7p&F-9&I~$ulIVbUw(2XntpInra*AMt?y zgwpYwjU(+QN7{DNRML7WtB;cEl+$EGGc_e9UnypQrDkTZ)J=n>-^^qgFcs?zGn=Jh z=CI5(gDkVmT$b5p-anM+r;L|=Mv3@=$dM@ONVGs1aXW0y!-wicqc>s1`p0cG6A$7e z;MqL<#j^A&#OBFJb^Q;!IB{Dm@~trY7u349n7VkI8gUdA_?5Mj4DhFsH@`ADytj}y z4G0=bgMYL9U=bTuMCk;UgZOwsQQx3oZ)vW$EtKi1H6D(a;th&7wwF4el4dgF3^0M_ z$FCU@{)W>0mf_y-IQ`#KFF&-TqWVlLp;-J1;)rz~-;`LB)ohhd_O7l;Er@sZf{8^3 zX|Am~+nb$bVgH#C%}0!L{=(7xgyGO?;uMvkDJ^xT)G#MkG6p1bd6~PM)2r~5d92z? zBS9C%MOEV4gzd%rnBsrJBX*LJ?GUCiXmqL1m^K5ChYb7#{iTT7*u9|WLHLhs;%2lL zeT{VB3b9ZoK>e-aGnvmuK4p9qry4$Q^I1uzChK0-^I7+?R`;^|S?^%IkM$4usGHV@ zrNIKrGRu}T7h@{@TlAKq;QzWsHJgaT%W!+SV8pE>ZE9=tvCrNYPR?#qt;x($IOuU z6ZfjqG-+vRmDg3_qo9R4|LTC7(dVSRp~*IDS9?g~bdQ}}L^ z&iANylkc_&J})CrA8*_Yb?iT7mkarn@To2ylr!>VM(3c++R8e%mw?hyfFfGgZgb@x zOt5rWwfx)_Mz2b8qL)=_1)N11jkL4=JWn=wUGs?#rufk%8BA{){M44oc*(?W$-y%c z#H$kGSCD-CR3_k<6wnGxWaha@a%7TB6=scCo+HzwPG&IWI8!1rORi^j_EssCZR~wO z%H&DrVPBN9HPnknbI=Ex$~9;tIZCl|V2lO?Y2 zOTFtIx!84Fmbv~c_N8z!O3lAxRUi;Ba&vfJa%cSwfm|b7y&L99UTfht{tCm$%MBRn z-$|UsUyI~RcD8YvX%;SW^ZMpeKS8i90&lyvN8D=WDIepZkD*ubnttVEOyy(>m6MrH zci}V7VyT(6EOqlzmVUF9Wx%A*G&6Frot2S;r&wj?KsnB=9K6daJ4e9E%#o?A=n(5z z(IIxQ%FU7O|HunT6NBB$DKo#{(o)gNxSykur1f!S9Flp>`{k@E&#XZy--QXYvUWTK zf38$e3v%V$D&|PeWLFg}DUZ+lCd)6rlhFPfugSXIA=sh3{UAW?qEF$STmD*9D z3kY&oXoa2wvV>{BM`c1tGs_#*ClusCt z&lY5KX17#kT5l++$X0_XxzkH$+DQU!>M~Ml6ULxDarf4(o^{PPuT)>d_|Q43K;@XP`|{iIatsoV=uo#YF%TZMrG((Gb< zH-YQKwpu3}s+On!+*TVmK*UF6E?@> zMt*3xS$uMvWXUEuLvH6ezeDCrAFaS_X?R^d_RJs)$q9v4i2wiq literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java new file mode 100644 index 0000000..97113ff --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java @@ -0,0 +1,425 @@ +package com.mathlearn.generator; + +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class SeniorHighGenerator implements QuestionGenerator { + private Random random = new Random(); + + @Override + public Question generateQuestion() { + int type = random.nextInt(6); // 六种题型 + String questionText = ""; + double correctAnswerValue = 0; + boolean isIntegerAnswer = true; + + switch (type) { + case 0: // 三角函数(特殊角,包括负角) + String[] trigFunctions = {"sin", "cos", "tan"}; + String func = trigFunctions[random.nextInt(trigFunctions.length)]; + int angle = getSpecialAngle(); + questionText = func + "(" + angle + "°) = ?"; + correctAnswerValue = calculateTrigValue(func, angle); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 1: // 平方根(包括非完全平方数的近似值) + if (random.nextBoolean()) { + // 完全平方数 + int square = getPerfectSquare(); + questionText = "√" + square + " = ?"; + correctAnswerValue = Math.sqrt(square); + } else { + // 非完全平方数的近似值 + int num = getNonPerfectSquare(); + questionText = "√" + num + " ≈ ?"; + correctAnswerValue = Math.sqrt(num); + isIntegerAnswer = false; + } + break; + + case 2: // 对数运算 + questionText = generateLogQuestion(); + correctAnswerValue = evaluateLogQuestion(questionText); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 3: // 复合表达式(考虑优先级) + ExpressionResult exprResult = generateCompositeExpression(); + questionText = exprResult.expression; + correctAnswerValue = exprResult.value; + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + + case 4: // 二次方程 + int root = random.nextInt(15) - 7; // -7到7的根 + int a = 1; + int b = -2 * root; + int c = root * root; + questionText = String.format("方程 %dx² %s %dx %s %d = 0 的一个根是?", + a, b >= 0 ? "+" : "", b, c >= 0 ? "+" : "", c); + correctAnswerValue = root; + break; + + case 5: // 带指数的复合运算 + questionText = generateExponentialExpression(); + correctAnswerValue = evaluateExponentialExpression(questionText.replace(" = ?", "")); + isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); + break; + } + + List options = generateOptions(correctAnswerValue, isIntegerAnswer); + String correctAnswerStr = isIntegerAnswer ? + String.valueOf((int)correctAnswerValue) : + String.format("%.2f", correctAnswerValue); + int correctIndex = options.indexOf(correctAnswerStr); + + return new Question(questionText, options, correctIndex); + } + + // 表达式和结果封装类 + private static class ExpressionResult { + String expression; + double value; + + ExpressionResult(String expression, double value) { + this.expression = expression; + this.value = value; + } + } + + // 生成复合表达式并同时计算结果 + private ExpressionResult generateCompositeExpression() { + // 使用预定义的简单表达式模板,确保可计算 + String[][] templates = { + {"%d + %d × %d", "先乘后加"}, + {"%d × %d + %d", "先乘后加"}, + {"%d - %d × %d", "先乘后减"}, + {"%d × %d - %d", "先乘后减"}, + {"%d + %d ÷ %d", "先除后加"}, + {"%d ÷ %d + %d", "先除后加"}, + {"%d² + %d", "先平方后加"}, + {"%d² - %d", "先平方后减"}, + {"%d × (%d + %d)", "先加后乘"}, + {"(%d + %d) × %d", "先加后乘"} + }; + + String[] template = templates[random.nextInt(templates.length)]; + String pattern = template[0]; + String description = template[1]; + + // 生成合适的数字,确保计算有效 + int a, b, c=1; + double result = 0; + + // 根据模板类型生成合适的数字 + if (pattern.contains("÷")) { + // 除法模板:确保除数不为0且能整除 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + + // 调整数字确保除法有效 + if (pattern.startsWith("%d ÷")) { + // 第一个操作数是除法:确保b能整除a + a = b * (random.nextInt(5) + 1); // a是b的倍数 + } else if (pattern.contains("÷ %d")) { + // 其他位置的除法:确保除数不为0 + b = random.nextInt(9) + 1; // 1-9 + } + } else if (pattern.contains("²")) { + // 平方模板 + a = random.nextInt(10) + 1; // 1-10 + b = random.nextInt(20) + 1; // 1-20 + result = a * a + (pattern.contains("+") ? b : -b); + } else if (pattern.contains("(")) { + // 括号模板 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + result = pattern.contains("× (") ? a * (b + c) : (a + b) * c; + } else { + // 基本四则运算 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + c = random.nextInt(10) + 1; + + // 根据运算符计算结果 + if (pattern.contains("+ %d ×")) { + result = a + b * c; // a + b × c + } else if (pattern.contains("× %d +")) { + result = a * b + c; // a × b + c + } else if (pattern.contains("- %d ×")) { + result = a - b * c; // a - b × c + } else if (pattern.contains("× %d -")) { + result = a * b - c; // a × b - c + } else if (pattern.contains("+ %d ÷")) { + result = a + (double)b / c; // a + b ÷ c + } else if (pattern.contains("÷ %d +")) { + result = (double)a / b + c; // a ÷ b + c + } + } + + // 如果还没有计算结果,使用安全的表达式计算 + if (result == 0) { + result = safeEvaluateExpression(pattern, a, b, c); + } + + String expression = String.format(pattern, a, b, c) + " = ?"; + System.out.println("生成表达式: " + expression + " [规则: " + description + "] = " + result); + + return new ExpressionResult(expression, result); + } + + // 安全的表达式计算 + private double safeEvaluateExpression(String pattern, int a, int b, int c) { + try { + if (pattern.equals("%d + %d × %d")) { + return a + b * c; + } else if (pattern.equals("%d × %d + %d")) { + return a * b + c; + } else if (pattern.equals("%d - %d × %d")) { + return a - b * c; + } else if (pattern.equals("%d × %d - %d")) { + return a * b - c; + } else if (pattern.equals("%d + %d ÷ %d")) { + return a + (double)b / c; + } else if (pattern.equals("%d ÷ %d + %d")) { + return (double)a / b + c; + } else if (pattern.equals("%d² + %d")) { + return a * a + b; + } else if (pattern.equals("%d² - %d")) { + return a * a - b; + } else if (pattern.equals("%d × (%d + %d)")) { + return a * (b + c); + } else if (pattern.equals("(%d + %d) × %d")) { + return (a + b) * c; + } + } catch (Exception e) { + System.err.println("计算表达式失败: " + String.format(pattern, a, b, c) + ", 错误: " + e.getMessage()); + } + return 0; + } + + // 获取特殊角度(包括负角) + private int getSpecialAngle() { + int[] angles = {-360, -270, -180, -135, -120, -90, -60, -45, -30, 0, + 30, 45, 60, 90, 120, 135, 180, 270, 360}; + return angles[random.nextInt(angles.length)]; + } + + // 获取非完全平方数 + private int getNonPerfectSquare() { + int[] nonSquares = {2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20}; + return nonSquares[random.nextInt(nonSquares.length)]; + } + + // 生成对数题目 + private String generateLogQuestion() { + if (random.nextBoolean()) { + // 简单对数:log₁₀ + int value = (int)Math.pow(10, random.nextInt(4)); // 1, 10, 100, 1000 + return "log₁₀" + value + " = ?"; + } else { + // 以2为底的对数 + int value = (int)Math.pow(2, random.nextInt(6) + 1); // 2,4,8,16,32,64 + return "log₂" + value + " = ?"; + } + } + + // 计算对数题目 + private double evaluateLogQuestion(String question) { + if (question.startsWith("log₁₀")) { + int value = Integer.parseInt(question.replace("log₁₀", "").replace(" = ?", "")); + return Math.log10(value); + } else if (question.startsWith("log₂")) { + int value = Integer.parseInt(question.replace("log₂", "").replace(" = ?", "")); + return Math.log(value) / Math.log(2); + } + return 0; + } + + // 生成指数表达式 + private String generateExponentialExpression() { + int base = random.nextInt(5) + 2; // 2-6 + int exponent = random.nextInt(4) + 2; // 2-5 + return base + "^" + exponent + " = ?"; + } + + // 计算指数表达式 + private double evaluateExponentialExpression(String expr) { + String cleanExpr = expr.replace(" = ?", ""); + String[] parts = cleanExpr.split("\\^"); + int base = Integer.parseInt(parts[0]); + int exponent = Integer.parseInt(parts[1]); + return Math.pow(base, exponent); + } + + private double calculateTrigValue(String function, int angle) { + // 规范化角度到0-360度 + angle = angle % 360; + if (angle < 0) angle += 360; + + // 特殊角的精确值 + switch (angle) { + case 0: + if (function.equals("sin")) return 0; + if (function.equals("cos")) return 1; + if (function.equals("tan")) return 0; + break; + case 30: + if (function.equals("sin")) return 0.5; + if (function.equals("cos")) return Math.sqrt(3)/2; + if (function.equals("tan")) return 1/Math.sqrt(3); + break; + case 45: + double sqrt2 = Math.sqrt(2); + if (function.equals("sin")) return sqrt2/2; + if (function.equals("cos")) return sqrt2/2; + if (function.equals("tan")) return 1; + break; + case 60: + if (function.equals("sin")) return Math.sqrt(3)/2; + if (function.equals("cos")) return 0.5; + if (function.equals("tan")) return Math.sqrt(3); + break; + case 90: + if (function.equals("sin")) return 1; + if (function.equals("cos")) return 0; + if (function.equals("tan")) return Double.POSITIVE_INFINITY; + break; + case 120: + if (function.equals("sin")) return Math.sqrt(3)/2; + if (function.equals("cos")) return -0.5; + if (function.equals("tan")) return -Math.sqrt(3); + break; + case 135: + double sqrt22 = Math.sqrt(2)/2; + if (function.equals("sin")) return sqrt22; + if (function.equals("cos")) return -sqrt22; + if (function.equals("tan")) return -1; + break; + case 150: + if (function.equals("sin")) return 0.5; + if (function.equals("cos")) return -Math.sqrt(3)/2; + if (function.equals("tan")) return -1/Math.sqrt(3); + break; + case 180: + if (function.equals("sin")) return 0; + if (function.equals("cos")) return -1; + if (function.equals("tan")) return 0; + break; + case 270: + if (function.equals("sin")) return -1; + if (function.equals("cos")) return 0; + if (function.equals("tan")) return Double.NEGATIVE_INFINITY; + break; + } + + // 对于非特殊角,使用近似计算 + double rad = Math.toRadians(angle); + switch (function) { + case "sin": + return Math.round(Math.sin(rad) * 100) / 100.0; + case "cos": + return Math.round(Math.cos(rad) * 100) / 100.0; + case "tan": + if (angle % 180 == 90) { + return angle % 360 == 90 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; + } + double result = Math.tan(rad); + return Math.round(result * 100) / 100.0; + default: + return 0; + } + } + + private int getPerfectSquare() { + int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; + return perfectSquares[random.nextInt(perfectSquares.length)]; + } + + private List generateOptions(double correctAnswer, boolean isInteger) { + List options = new ArrayList<>(); + + String correctStr; + if (Double.isInfinite(correctAnswer)) { + correctStr = correctAnswer > 0 ? "∞" : "-∞"; + } else if (Double.isNaN(correctAnswer)) { + correctStr = "无解"; + } else { + correctStr = isInteger ? + String.valueOf((int)correctAnswer) : + String.format("%.2f", correctAnswer); + } + options.add(correctStr); + + Set used = new HashSet<>(); + used.add(correctStr); + + // 生成3个错误选项 + int attempts = 0; + while (options.size() < 4 && attempts < 50) { + attempts++; + double wrongValue; + String wrongStr; + + // 根据正确答案调整变化范围 + double baseRange; + if (Double.isInfinite(correctAnswer) || Double.isNaN(correctAnswer)) { + baseRange = 5; + } else { + baseRange = Math.max(2, Math.abs(correctAnswer) * 0.3); + } + + double variation = (random.nextDouble() * baseRange) + 1; + boolean positive = random.nextBoolean(); + + if (Double.isInfinite(correctAnswer)) { + wrongValue = random.nextDouble() * 10 - 5; // -5到5的随机数 + } else if (Double.isNaN(correctAnswer)) { + wrongValue = random.nextDouble() * 10; // 0到10的随机数 + } else { + wrongValue = correctAnswer + (positive ? variation : -variation); + } + + if (Double.isInfinite(wrongValue)) { + wrongStr = wrongValue > 0 ? "∞" : "-∞"; + } else if (Double.isNaN(wrongValue)) { + wrongStr = "无解"; + } else if (isInteger) { + wrongValue = Math.round(wrongValue); + wrongStr = String.valueOf((int)wrongValue); + } else { + wrongValue = Math.round(wrongValue * 100) / 100.0; + wrongStr = String.format("%.2f", wrongValue); + } + + if (!used.contains(wrongStr)) { + options.add(wrongStr); + used.add(wrongStr); + } + } + + // 如果选项不够,添加一些固定选项 + while (options.size() < 4) { + String extraOption; + if (isInteger) { + int extraValue = (int)correctAnswer + options.size() * 2 + 1; + extraOption = String.valueOf(extraValue); + } else { + double extraValue = correctAnswer + options.size() * 0.5 + 0.1; + extraOption = String.format("%.2f", extraValue); + } + + if (!used.contains(extraOption)) { + options.add(extraOption); + used.add(extraOption); + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class new file mode 100644 index 0000000000000000000000000000000000000000..77c835a92fa785434db6a6547504560a530cc812 GIT binary patch literal 3453 zcmaJ@TXa-c8UFU%&Y6<~2?GO8lj4waNhX&mP{xuWR7eX%5~l4?=z!H6l9Oa$=1iD5 zL!n-Jv9+~WdsU#VP|=#&LZt{HgcjGb%e7p-)dyWZxRy&r>;o@8d8x*4pOZ-@5-qP8{r-RNU;caIDu7Lx(BOerflr4Y0fD;x#vvn~GpwO_YTtgd-xdgL$XZ!@qky-m zd6xpULR7Z1x%mBtHBiWFP~Z)s2D*ZII_9HRAl_fd$Mc3goHLE06(2G!vuN0bVmxgd z`*P-eWwT^w3)a@kJ_QvWW&)ueM~f-}Ny&VHjt~|K)E=BV+f^uAwpkPq-9d!0Siuq< zpF*Ufp<_n+NXa(y)V@%rF=3Z=wh+I!n6>P*T{Mk+GDKh0>uA8O0!#A70kf-M^&9r? ztUb(G$u=yz#IsG^&F*oRu}uy`Ne!PyRKYSGjkrx)D@{#vIafzQy<=E1U&b1bS-#*KHfc~1xe>!mk31Qs`S&u#PubSl`W<1TzwVEznh zdKqy_%o~RV{PHj*Z@^|9U6Rn7&srfOZhZ(|tk)RStva@$n|_%Bi0Q&3H6p=56&FrB z-GM_-wq!G0K5Ul?_6V$;%b!(NF~TxR3U&xAn+?f4os)~3hmCx^f<_I!xL2maeRFem z8P90aEi)oriMj)edk*)Tj`9+c59rt>@#r;+MGg1kK^+veDjpIDu8y`uS4TUecd7UyqrFCj!C|e6ehzo2APcch!w`lQWOeMvfeK(8MK=|T z#u0ilV3efy1XeWdt#VK$?Eh_=0w#@%<{37UfrcEs5>6vJ4$6#C4jH+!nHsD?3ATc= zjzbbv#b#5~ni)x(c}*E2N84r8Ha~9LzBm3#Sk{ZFy3Hc zO2MntwHgW2sq#9D$zJAUFr6K;47*&U+*Q+_pSEj56^f?LZloA3T__j(%`I7}ZiAc7 z6=kO_Y?p4NHT1t-vWvz@uW1h#21+WvFVGl`MsK|F!Ho-}(d)0A`tvg{Tt9OrDxx1h z{_@ACk6(Z7-S+l&6>m~M!OReDW{f(^w#xEH)I&r+JXTr1LsiK253fHJb$Pgq$@|)~ zr#hlS#aV&&DY@t0oJI7PpFVy4t)qV$KYQ)@7kTX3`%hdOALp6c0Di3D9NtrKURI-@ z2rPHd;b1mv9V#3!dE3eQ*us|34{f zkZTu~vGRL(&Ai0kBi{=EN8aunz1-(pg#9aAt#j5uICcplb_Gi25`q_@#k?0$_Z|rZ zzRi9<$-w0HK_#;wcfW&UE(?#r{TdP;jb$#N&ez9-=dmcp`2=nO#;}xgt!~j6miziP zRLwgBAD}7Y4aL$KU#K;m@rT;eJK7{c+f@>;>F`B-9f~KRMwBt!{tgvDicMplJ5FGwH=&Lq%5|%=UhI?WIUY57jq}Bbf-wVN*g22gBL~?v?~{Iv`0p9J9146Ww{I$xvT&-F>q z?Mr6@p@H-`2Axw3O+@Sz5AaU(H~}m&fq;3?7|IBdu!2}vjm6Y$327Se3oOM)d}{p~ zQT!IS;rCdM>!kWCA5DM9Dtv+%lek4JLaVryucAh@ixs$Cv}3hci*+K&qP`7xQeubL zg`_aiiQ|-bH?&EX{U9MCgn|3Wqkfr#ve#! z0%|Iw)G4WqTBoHteBOjV><^sAvDV9Yf|u=SJQwkW{Sn{Qk@iGDhII^2C6uso0$P1I z&^HQ&!+-?PNwl_wRY%e{Ja`pLTjgp>mC7Hf!zk9)hyA`j|8QSIt^9C~)c>y|Px{5^ zWOiDoj(T^h4)^)`68^TZe?}~Ma5XK~{o{z8{8{TbzS(+?ad1&E=zx4PlemlV--3E< zWqi9i+s=nm4+i)?%QMLyrO#hN8Yi(6XR#ZX@F0FpijS}dza#A*(T5u_@K5X$LB5m1 z7!b=aD3)VbG$HFmJ_dD?tOGK%3RvqNQ}7zY{x3eJMVI)5!`~492mGBLeAm(NBvbp8 qGkXKyRlrFwA25<>3`_-Z#n(jPJad$NUM?VBK5qC$bSH6Y+p(M literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java new file mode 100644 index 0000000..ace3ab1 --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java @@ -0,0 +1,107 @@ +package com.mathlearn.generator; +//稳定生成器 +import com.mathlearn.model.exam.Question; + +import java.util.*; + +public class StableQuestionGenerator implements QuestionGenerator { + private Random random = new Random(); + private int questionCounter = 0; + + @Override + public Question generateQuestion() { + questionCounter++; + System.out.println(" 🔧 生成第 " + questionCounter + " 道题目..."); + + try { + // 极度简化的题目生成,确保不会卡住 + int a = random.nextInt(20) + 1; + int b = random.nextInt(20) + 1; + + // 随机选择运算符 + String[] operators = {"+", "-", "×"}; + String operator = operators[random.nextInt(operators.length)]; + + String questionText; + int correctAnswer; + + switch (operator) { + case "+": + questionText = a + " + " + b + " = ?"; + correctAnswer = a + b; + break; + case "-": + // 确保减法结果不为负数 + int larger = Math.max(a, b); + int smaller = Math.min(a, b); + questionText = larger + " - " + smaller + " = ?"; + correctAnswer = larger - smaller; + break; + case "×": + // 简化乘法,避免过大数字 + a = random.nextInt(10) + 1; + b = random.nextInt(10) + 1; + questionText = a + " × " + b + " = ?"; + correctAnswer = a * b; + break; + default: + questionText = a + " + " + b + " = ?"; + correctAnswer = a + b; + } + + // 生成稳定的选项 + List options = generateStableOptions(correctAnswer); + + System.out.println(" ✅ 题目生成成功: " + questionText); + return new Question(questionText, options, 0); // 第一个选项是正确答案 + + } catch (Exception e) { + System.err.println(" 💥 题目生成过程中发生异常: " + e.getMessage()); + // 返回一个默认题目,确保不卡住 + return new Question("1 + 1 = ?", Arrays.asList("2", "3", "4", "5"), 0); + } + } + + private List generateStableOptions(int correctAnswer) { + List options = new ArrayList<>(); + options.add(String.valueOf(correctAnswer)); + + // 生成3个稳定的错误选项 + Set used = new HashSet<>(); + used.add(correctAnswer); + + int[] variations = {1, 2, 3, 5, 7, 10}; // 固定的变化量 + + for (int i = 0; i < 3 && options.size() < 4; i++) { + int variation = variations[i % variations.length]; + boolean addVariation = random.nextBoolean(); + + int wrongAnswer = addVariation ? correctAnswer + variation : correctAnswer - variation; + + // 确保不为负数且不重复 + if (wrongAnswer > 0 && !used.contains(wrongAnswer)) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } else { + // 如果生成失败,使用备选方案 + wrongAnswer = correctAnswer + (i + 1) * 2; + if (!used.contains(wrongAnswer)) { + options.add(String.valueOf(wrongAnswer)); + used.add(wrongAnswer); + } + } + } + + // 如果选项还不够,用固定值补全 + while (options.size() < 4) { + int filler = correctAnswer + options.size() * 5 + 1; + if (!used.contains(filler)) { + options.add(String.valueOf(filler)); + used.add(filler); + } + } + + Collections.shuffle(options); + return options; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class b/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class new file mode 100644 index 0000000000000000000000000000000000000000..649edee4601be6aaecd8da31c12a1cc46d167f02 GIT binary patch literal 637 zcmZXR%TB^j5QhH)g-Wg5z2Y@)pi%n(8WW>&)Dl_i=X`v=y#qMGwt)naIy4h0qy_SA`5^6%3|#xV)mBas3VYokR04W9a2yqe0-_lU zWKHCdXWeH}x+IDhe{<_m-wWKs7%ZA7p)8=?$w*F9-|h|ts@3NI=84J}tTiZeN`C^m z3olSt1HYyEx3bk?CF6zlAB)_wDPXuNy8LlhuGS_5$Np%a%-P7;H1KQ9sCNf_N1c1| zjQqrr9K_pVhZ`n%3rR+vCf^eAxr{Q`X4W8hEsKmx{5s-)jk#>SLRgg{bZc*j1#5qZ z!ZYgv%Zy9x0F^al_!!7iyF_(?6|9bxHkbvel=TAr@wYWSDrOniP+^RRPNEA>GiZ*` S`Usgt3$tjR=qB3}*!lvsuy*eN literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java b/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java new file mode 100644 index 0000000..97e218a --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java @@ -0,0 +1,17 @@ +package com.mathlearn.model.api; + +public class ApiResponse { + private boolean success; + private String message; + private Object data; + + public ApiResponse(boolean success, String message, Object data) { + this.success = success; + this.message = message; + this.data = data; + } + + public boolean isSuccess() { return success; } + public String getMessage() { return message; } + public Object getData() { return data; } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class new file mode 100644 index 0000000000000000000000000000000000000000..fa6df17e059f8094551bf8df2214194994bb812d GIT binary patch literal 2001 zcma)7ZBrXn6n<_3EQIBqP$eLsr6i#?we|%~z)~m@h0+=tq`of67Pn0{b$3&#pF7hp z{sX^s{G#8~83EB5$ItyA{)x_Lea^ChK!y zq@x)v3f*^%`$no{*qf=9jXP$+Q)tOpw&l$zgyV^P8(Pt(A)=!ly25awQcjf(?~9UY zICiRBDVn8}xn-17SGg#(eOWbK&#KriO)vSjtDaR#Em^LY*3hZYcX&AKIK~6HiJ${v z@zkTESKPE$UDKJh-LFi?)zGidd5D@fJTrp6eZUDFFX3hSbv?uJR;{vm)UPPhZ%kp( zx8RvuUMgpm@0CosTBtZorWM2V@PNPN$fjo>Wa&~Q%2n>eq~<0tFKo3%Z2({vQH`$nm1uH04_h-d4g3N+HbWKZnTTiWqOU179tmH@ISTx-ZF1J8 zZFp6OG+x+`_n=)fOaJRDJ(E@#Z@@K>@9Xu|w}w9ti9BmK#}QKKTC!~OTD81kI;+M; zi6B4}T!o{0F9XLRLsYtjkDjACeq2@Te2h;5)%VD|Fh3Ui79%ksFCem4 z_OT(K$+yB-JLIs_2aJ-rF^uvd7p}rkqqO)bJ`3!A6I661oMCl@n80pI><;Z=I)p!Q zb_cU^SCi*=u<#fy50&x@_aye{0QsoWkL=wa=_};3J4k+|o+182=wVBpM}lwg1g3G? VkEk8tztN=Bxu@(ih0lGU@h_~W##{gZ literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java new file mode 100644 index 0000000..ce3c1cd --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java @@ -0,0 +1,46 @@ +package com.mathlearn.model.exam; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class Exam { + private List questions; + private List userAnswers; + private Date startTime; + private String examId; + + public Exam(List questions) { + this.questions = questions; + this.userAnswers = new ArrayList<>(); + this.startTime = new Date(); + this.examId = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + + // 初始化用户答案列表 + for (int i = 0; i < questions.size(); i++) { + userAnswers.add(-1); // -1表示未作答 + } + } + + public List getQuestions() { return questions; } + public List getUserAnswers() { return userAnswers; } + public Date getStartTime() { return startTime; } + public String getExamId() { return examId; } + + public void setAnswer(int questionIndex, int answerIndex) { + if (questionIndex >= 0 && questionIndex < userAnswers.size()) { + userAnswers.set(questionIndex, answerIndex); + } + } + + public double calculateScore() { + int correctCount = 0; + for (int i = 0; i < questions.size(); i++) { + if (userAnswers.get(i) == questions.get(i).getCorrectAnswerIndex()) { + correctCount++; + } + } + return (double) correctCount / questions.size() * 100; + } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class new file mode 100644 index 0000000000000000000000000000000000000000..8942b24d1523223070cc269dfa50194f22c7ad42 GIT binary patch literal 842 zcmaiyU279T6o%i)*P87nX=1FOQL9CgwRG=ID3pQ_2o_1{{U#mal-*g~%xZp=7YYr6 z7ySYLDDmB7VupR8c5!fF`p%?n*Lm>TFdtr1b15eKU(0iZAsZo&@a6V=3 zxttN#7~GZ^npo*cH-%Om)UYdHMIY0&DO*_z6Qcrepr&RaYdE-zCMn}6j@jOco_>*W zUth|ZfanX9hiamIlf+WsV2#k*EPdP+c-7vFuVr@ooeP1&Dc>hh8z?Q`CE-ZM=l&>Q zL<_zs& zl*D8CR;6#Nta>|2_lAA$D#x#r=gBWXFPAP3WG?(Y-nk+A1;&cF&-(-3db9=FruzfJ zeLaWe9?ns5TXWREGcNFu=N>Zvo5~%ONw1 options; + private int correctAnswerIndex; + + public Question(String questionText, List options, int correctAnswerIndex) { + this.questionText = questionText; + this.options = options; + this.correctAnswerIndex = correctAnswerIndex; + } + + public String getQuestionText() { return questionText; } + public List getOptions() { return options; } + public int getCorrectAnswerIndex() { return correctAnswerIndex; } +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class b/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class new file mode 100644 index 0000000000000000000000000000000000000000..d02c2fae41688ff0102fee2e1b72d4ebdf28465e GIT binary patch literal 1426 zcmbV~TTc^F6ouF6oic?&TS~bUxwpe*cr~I4G58`8BgzABLpiBK+9{b%HU1|bG_f)9 z!5`p{GOj&SEe;byOp|lY?5_QtwfEUSet!E7;0OnKB#_J^Wgv}=Lh;&uXImZHZCj_8 z*Sh5^WDXtI@t-Ip8_n|xy%-oPXbg^gCPYjth^ZAaUlYjt~9x?>Ic+OytpIcl|f z1DA-Lgj~C;6=qMyH=OyNiRfE+O1F`;5IU>+i?0}Fl;{O;)02N?T;~)80%s*N8qu%4v$P29rI_sf!ET{9O+^4 z*68fZuwa!hnc%o)xN_`xO31VXI|n4#`S8Kc=MHwx2zLXV1}t-}^Xr&-Deg7%E0no2 zMAqCLqG0X~Q8ZISls@xMg%z#~yiC$lC}09p{7s{TBIYp@ARmm7r$nZyT!};0$gD=d zbz~_o5nLv?Lhu~FsvO*TdaMQT)e-!V@Fdmc-|(vVT`-e>S)B_EERwiH;xdVK5?9Dr z`&0SjQRS6?R~@3(2wX=V8?1SgHn)gc=U3Q7X{Ms7wD|?uPdtPT%LKs&*UeaIAu4TB zx)m!eMx`dD+p*GxsC0+Y281mSe%ov5W5nw&MJ6Ocq;+;Em@(;4VLS+7UHeq+#yY4* U9axm^#bc{c>;bj=ygUKx7uQVtbpQYW literal 0 HcmV?d00001 diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java b/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java new file mode 100644 index 0000000..0760366 --- /dev/null +++ b/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java @@ -0,0 +1,49 @@ +package com.mathlearn.model.user; + +// 用户账户类 +public class UserAccount { + private String username; + private String password; + private String userType; + private String email; // 添加邮箱字段 + private String registrationCode; + private boolean registered; + + public UserAccount(String username, String password, String userType) { + this.username = username; + this.password = password; + this.userType = userType; + this.registered = true; + } + + public UserAccount(String username, String password, String userType, String email) { + this.username = username; + this.password = password; + this.userType = userType; + this.email = email; + this.registered = true; + } + + public UserAccount(String email, String registrationCode) { + this.email = email; + this.registrationCode = registrationCode; + this.registered = false; + } + + public void completeRegistration(String username, String password, String userType) { + this.username = username; + this.password = password; + this.userType = userType; + this.registered = true; + } + + public String getUsername() { return username; } + public String getPassword() { return password; } + public String getUserType() { return userType; } + public String getRegistrationCode() { return registrationCode; } + public boolean isRegistered() { return registered; } + + public void setPassword(String password) { this.password = password; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } +} -- 2.34.1 From fb357ca552ddf5ac22be809a74991278263c3a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B1=AA?= <2297852620@qq.com> Date: Sat, 11 Oct 2025 19:08:36 +0800 Subject: [PATCH 15/30] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pair-programming/doc/README.md | 2 - .../src/electron-frontend/package-lock.json | 3821 ----------------- .../src/electron-frontend/package.json | 34 - .../src/electron-frontend/resources/main.js | 100 - .../electron-frontend/resources/preload.js | 129 - .../resources/renderer/login.html | 119 - .../resources/renderer/main.html | 432 -- .../resources/renderer/quiz.html | 264 -- .../resources/renderer/register.html | 260 -- .../resources/renderer/result.html | 104 - .../resources/style/common.css | 118 - .../src/electron-frontend/start-backend.bat | 6 - .../src/java-backend/math_learn/.gitignore | 30 - .../java-backend/math_learn/.idea/.gitignore | 8 - .../java-backend/math_learn/.idea/misc.xml | 6 - .../java-backend/math_learn/.idea/modules.xml | 8 - .../src/java-backend/math_learn/.idea/vcs.xml | 6 - .../java-backend/math_learn/math_learn.iml | 11 - .../2025-10-09-19-22-22_score_100.0.txt | 64 - .../src/com/mathlearn/Main$BaseHandler.class | Bin 4196 -> 0 bytes .../Main$ChangePasswordHandler.class | Bin 2465 -> 0 bytes .../mathlearn/Main$FinishExamHandler.class | Bin 2287 -> 0 bytes .../mathlearn/Main$GenerateExamHandler.class | Bin 2454 -> 0 bytes .../mathlearn/Main$GetQuestionHandler.class | Bin 2400 -> 0 bytes .../src/com/mathlearn/Main$LoginHandler.class | Bin 1669 -> 0 bytes .../com/mathlearn/Main$LogoutHandler.class | Bin 2275 -> 0 bytes .../com/mathlearn/Main$RegisterHandler.class | Bin 1894 -> 0 bytes .../Main$SendRegistrationCodeHandler.class | Bin 2772 -> 0 bytes .../mathlearn/Main$SubmitAnswerHandler.class | Bin 2443 -> 0 bytes .../math_learn/src/com/mathlearn/Main.class | Bin 16119 -> 0 bytes .../math_learn/src/com/mathlearn/Main.java | 829 ---- .../generator/JuniorHighGenerator.class | Bin 5985 -> 0 bytes .../generator/JuniorHighGenerator.java | 221 - .../generator/PrimarySchoolGenerator.class | Bin 5880 -> 0 bytes .../generator/PrimarySchoolGenerator.java | 219 - .../generator/QuestionGenerator.class | Bin 206 -> 0 bytes .../generator/QuestionGenerator.java | 8 - ...SeniorHighGenerator$ExpressionResult.class | Bin 500 -> 0 bytes .../generator/SeniorHighGenerator.class | Bin 10033 -> 0 bytes .../generator/SeniorHighGenerator.java | 425 -- .../generator/StableQuestionGenerator.class | Bin 3453 -> 0 bytes .../generator/StableQuestionGenerator.java | 107 - .../com/mathlearn/model/api/ApiResponse.class | Bin 637 -> 0 bytes .../com/mathlearn/model/api/ApiResponse.java | 17 - .../src/com/mathlearn/model/exam/Exam.class | Bin 2001 -> 0 bytes .../src/com/mathlearn/model/exam/Exam.java | 46 - .../com/mathlearn/model/exam/Question.class | Bin 842 -> 0 bytes .../com/mathlearn/model/exam/Question.java | 19 - .../mathlearn/model/user/UserAccount.class | Bin 1426 -> 0 bytes .../com/mathlearn/model/user/UserAccount.java | 49 - 50 files changed, 7462 deletions(-) delete mode 100644 pair-programming/doc/README.md delete mode 100644 pair-programming/src/electron-frontend/package-lock.json delete mode 100644 pair-programming/src/electron-frontend/package.json delete mode 100644 pair-programming/src/electron-frontend/resources/main.js delete mode 100644 pair-programming/src/electron-frontend/resources/preload.js delete mode 100644 pair-programming/src/electron-frontend/resources/renderer/login.html delete mode 100644 pair-programming/src/electron-frontend/resources/renderer/main.html delete mode 100644 pair-programming/src/electron-frontend/resources/renderer/quiz.html delete mode 100644 pair-programming/src/electron-frontend/resources/renderer/register.html delete mode 100644 pair-programming/src/electron-frontend/resources/renderer/result.html delete mode 100644 pair-programming/src/electron-frontend/resources/style/common.css delete mode 100644 pair-programming/src/electron-frontend/start-backend.bat delete mode 100644 pair-programming/src/java-backend/math_learn/.gitignore delete mode 100644 pair-programming/src/java-backend/math_learn/.idea/.gitignore delete mode 100644 pair-programming/src/java-backend/math_learn/.idea/misc.xml delete mode 100644 pair-programming/src/java-backend/math_learn/.idea/modules.xml delete mode 100644 pair-programming/src/java-backend/math_learn/.idea/vcs.xml delete mode 100644 pair-programming/src/java-backend/math_learn/math_learn.iml delete mode 100644 pair-programming/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$FinishExamHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$GetQuestionHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator$ExpressionResult.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.java delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class delete mode 100644 pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java diff --git a/pair-programming/doc/README.md b/pair-programming/doc/README.md deleted file mode 100644 index aacf4a3..0000000 --- a/pair-programming/doc/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Pair-Programming - diff --git a/pair-programming/src/electron-frontend/package-lock.json b/pair-programming/src/electron-frontend/package-lock.json deleted file mode 100644 index cc0a9c4..0000000 --- a/pair-programming/src/electron-frontend/package-lock.json +++ /dev/null @@ -1,3821 +0,0 @@ -{ - "name": "math-learning-app", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "math-learning-app", - "version": "1.0.0", - "dependencies": { - "node-fetch": "^2.7.0" - }, - "devDependencies": { - "electron": "^22.0.0", - "electron-builder": "^24.0.0" - } - }, - "node_modules/@develar/schema-utils": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", - "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", - "dev": true, - "dependencies": { - "ajv": "^6.12.0", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/@electron/asar": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", - "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", - "dev": true, - "dependencies": { - "commander": "^5.0.0", - "glob": "^7.1.6", - "minimatch": "^3.0.4" - }, - "bin": { - "asar": "bin/asar.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/@electron/asar/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@electron/asar/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@electron/get": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", - "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "global-agent": "^3.0.0" - } - }, - "node_modules/@electron/notarize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", - "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.1", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/notarize/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/notarize/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/notarize/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/osx-sign": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", - "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", - "dev": true, - "dependencies": { - "compare-version": "^0.1.2", - "debug": "^4.3.4", - "fs-extra": "^10.0.0", - "isbinaryfile": "^4.0.8", - "minimist": "^1.2.6", - "plist": "^3.0.5" - }, - "bin": { - "electron-osx-flat": "bin/electron-osx-flat.js", - "electron-osx-sign": "bin/electron-osx-sign.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@electron/osx-sign/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true, - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/@electron/osx-sign/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/osx-sign/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/universal": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", - "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", - "dev": true, - "dependencies": { - "@electron/asar": "^3.2.1", - "@malept/cross-spawn-promise": "^1.1.0", - "debug": "^4.3.1", - "dir-compare": "^3.0.0", - "fs-extra": "^9.0.1", - "minimatch": "^3.0.4", - "plist": "^3.0.4" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/@electron/universal/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/universal/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/universal/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@electron/universal/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@malept/flatpak-bundler": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", - "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.0", - "lodash": "^4.17.15", - "tmp-promise": "^3.0.2" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@malept/flatpak-bundler/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "22.18.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.8.tgz", - "integrity": "sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw==", - "dev": true, - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/plist": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", - "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*", - "xmlbuilder": ">=11.0.1" - } - }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/verror": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", - "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", - "dev": true, - "optional": true - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", - "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/7zip-bin": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", - "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", - "dev": true - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/app-builder-bin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", - "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", - "dev": true - }, - "node_modules/app-builder-lib": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", - "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", - "dev": true, - "dependencies": { - "@develar/schema-utils": "~2.6.5", - "@electron/notarize": "2.2.1", - "@electron/osx-sign": "1.0.5", - "@electron/universal": "1.5.1", - "@malept/flatpak-bundler": "^0.4.0", - "@types/fs-extra": "9.0.13", - "async-exit-hook": "^2.0.1", - "bluebird-lst": "^1.0.9", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", - "chromium-pickle-js": "^0.2.0", - "debug": "^4.3.4", - "ejs": "^3.1.8", - "electron-publish": "24.13.1", - "form-data": "^4.0.0", - "fs-extra": "^10.1.0", - "hosted-git-info": "^4.1.0", - "is-ci": "^3.0.0", - "isbinaryfile": "^5.0.0", - "js-yaml": "^4.1.0", - "lazy-val": "^1.0.5", - "minimatch": "^5.1.1", - "read-config-file": "6.3.2", - "sanitize-filename": "^1.6.3", - "semver": "^7.3.8", - "tar": "^6.1.12", - "temp-file": "^3.4.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "dmg-builder": "24.13.3", - "electron-builder-squirrel-windows": "24.13.3" - } - }, - "node_modules/app-builder-lib/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/app-builder-lib/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/app-builder-lib/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/app-builder-lib/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/archiver": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", - "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", - "dev": true, - "peer": true, - "dependencies": { - "archiver-utils": "^2.1.0", - "async": "^3.2.4", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.1.2", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "dev": true, - "peer": true, - "dependencies": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "peer": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/archiver-utils/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "peer": true - }, - "node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true - }, - "node_modules/async-exit-hook": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "peer": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bluebird-lst": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", - "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", - "dev": true, - "dependencies": { - "bluebird": "^3.5.5" - } - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "optional": true - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/builder-util": { - "version": "24.13.1", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", - "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", - "dev": true, - "dependencies": { - "@types/debug": "^4.1.6", - "7zip-bin": "~5.2.0", - "app-builder-bin": "4.0.0", - "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.2.4", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "debug": "^4.3.4", - "fs-extra": "^10.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-ci": "^3.0.0", - "js-yaml": "^4.1.0", - "source-map-support": "^0.5.19", - "stat-mode": "^1.0.0", - "temp-file": "^3.4.0" - } - }, - "node_modules/builder-util-runtime": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", - "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/builder-util/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/builder-util/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/builder-util/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chromium-pickle-js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", - "dev": true - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "optional": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/compare-version": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", - "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/compress-commons": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", - "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", - "dev": true, - "peer": true, - "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/config-file-ts": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", - "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", - "dev": true, - "dependencies": { - "glob": "^10.3.10", - "typescript": "^5.3.3" - } - }, - "node_modules/config-file-ts/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "node_modules/crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.1.0" - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "peer": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/crc32-stream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", - "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", - "dev": true, - "peer": true, - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "optional": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "optional": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "optional": true - }, - "node_modules/dir-compare": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", - "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0", - "minimatch": "^3.0.4" - } - }, - "node_modules/dir-compare/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/dir-compare/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/dmg-builder": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", - "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", - "dev": true, - "dependencies": { - "app-builder-lib": "24.13.3", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", - "fs-extra": "^10.1.0", - "iconv-lite": "^0.6.2", - "js-yaml": "^4.1.0" - }, - "optionalDependencies": { - "dmg-license": "^1.0.11" - } - }, - "node_modules/dmg-builder/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dmg-builder/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/dmg-builder/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/dmg-license": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", - "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "@types/plist": "^3.0.1", - "@types/verror": "^1.10.3", - "ajv": "^6.10.0", - "crc": "^3.8.0", - "iconv-corefoundation": "^1.1.7", - "plist": "^3.0.4", - "smart-buffer": "^4.0.2", - "verror": "^1.10.0" - }, - "bin": { - "dmg-license": "bin/dmg-license.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", - "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron": { - "version": "22.3.27", - "resolved": "https://registry.npmjs.org/electron/-/electron-22.3.27.tgz", - "integrity": "sha512-7Rht21vHqj4ZFRnKuZdFqZFsvMBCmDqmjetiMqPtF+TmTBiGne1mnstVXOA/SRGhN2Qy5gY5bznJKpiqogjM8A==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@electron/get": "^2.0.0", - "@types/node": "^16.11.26", - "extract-zip": "^2.0.1" - }, - "bin": { - "electron": "cli.js" - }, - "engines": { - "node": ">= 12.20.55" - } - }, - "node_modules/electron-builder": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", - "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", - "dev": true, - "dependencies": { - "app-builder-lib": "24.13.3", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", - "chalk": "^4.1.2", - "dmg-builder": "24.13.3", - "fs-extra": "^10.1.0", - "is-ci": "^3.0.0", - "lazy-val": "^1.0.5", - "read-config-file": "6.3.2", - "simple-update-notifier": "2.0.0", - "yargs": "^17.6.2" - }, - "bin": { - "electron-builder": "cli.js", - "install-app-deps": "install-app-deps.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/electron-builder-squirrel-windows": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", - "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", - "dev": true, - "peer": true, - "dependencies": { - "app-builder-lib": "24.13.3", - "archiver": "^5.3.1", - "builder-util": "24.13.1", - "fs-extra": "^10.1.0" - } - }, - "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "peer": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-builder-squirrel-windows/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-builder/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-builder/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-builder/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-publish": { - "version": "24.13.1", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", - "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", - "dev": true, - "dependencies": { - "@types/fs-extra": "^9.0.11", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", - "chalk": "^4.1.2", - "fs-extra": "^10.1.0", - "lazy-val": "^1.0.5", - "mime": "^2.5.2" - } - }, - "node_modules/electron-publish/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-publish/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-publish/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron/node_modules/@types/node": { - "version": "16.18.126", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", - "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "optional": true - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extsprintf": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", - "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "optional": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, - "peer": true - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/global-agent/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "optional": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "optional": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/iconv-corefoundation": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", - "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "cli-truncate": "^2.1.0", - "node-addon-api": "^1.6.3" - }, - "engines": { - "node": "^8.11.2 || >=10" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "peer": true - }, - "node_modules/isbinaryfile": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", - "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", - "dev": true, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jake": { - "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", - "dev": true, - "dependencies": { - "async": "^3.2.6", - "filelist": "^1.0.4", - "picocolors": "^1.1.1" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "optional": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/lazy-val": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", - "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", - "dev": true - }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "peer": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "peer": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "peer": true - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true, - "peer": true - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "dev": true, - "peer": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true, - "peer": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, - "peer": true - }, - "node_modules/lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "dev": true, - "peer": true - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/node-addon-api": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", - "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", - "dev": true, - "optional": true - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/plist": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", - "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "peer": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-config-file": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", - "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", - "dev": true, - "dependencies": { - "config-file-ts": "^0.2.4", - "dotenv": "^9.0.2", - "dotenv-expand": "^5.1.0", - "js-yaml": "^4.1.0", - "json5": "^2.2.0", - "lazy-val": "^1.0.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "dev": true, - "peer": true, - "dependencies": { - "minimatch": "^5.1.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peer": true - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "dev": true, - "dependencies": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "dev": true - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "optional": true - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "optional": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "optional": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "optional": true - }, - "node_modules/stat-mode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", - "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "peer": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "dependencies": { - "debug": "^4.1.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "peer": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/temp-file": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", - "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", - "dev": true, - "dependencies": { - "async-exit-hook": "^2.0.1", - "fs-extra": "^10.0.0" - } - }, - "node_modules/temp-file/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/temp-file/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/temp-file/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", - "dev": true, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/tmp-promise": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", - "dev": true, - "dependencies": { - "tmp": "^0.2.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", - "dev": true, - "dependencies": { - "utf8-byte-length": "^1.0.1" - } - }, - "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/utf8-byte-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "peer": true - }, - "node_modules/verror": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", - "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", - "dev": true, - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/zip-stream": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", - "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", - "dev": true, - "peer": true, - "dependencies": { - "archiver-utils": "^3.0.4", - "compress-commons": "^4.1.2", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/zip-stream/node_modules/archiver-utils": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", - "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", - "dev": true, - "peer": true, - "dependencies": { - "glob": "^7.2.3", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - } - } -} diff --git a/pair-programming/src/electron-frontend/package.json b/pair-programming/src/electron-frontend/package.json deleted file mode 100644 index 85b1de1..0000000 --- a/pair-programming/src/electron-frontend/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "math-learning-app", - "version": "1.0.0", - "description": "小初高数学学习软件", - "main": "src/main.js", - "scripts": { - "start": "electron .", - "dev": "electron . --dev", - "build": "electron-builder" - }, - "devDependencies": { - "electron": "^22.0.0", - "electron-builder": "^24.0.0" - }, - "build": { - "appId": "com.mathlearning.app", - "productName": "数学学习系统", - "directories": { - "output": "dist" - }, - "files": [ - "src/**/*", - "styles/**/*", - "assets/**/*" - ], - "win": { - "target": "nsis", - "icon": "assets/icon.ico" - } - }, - "dependencies": { - "node-fetch": "^2.7.0" - } -} diff --git a/pair-programming/src/electron-frontend/resources/main.js b/pair-programming/src/electron-frontend/resources/main.js deleted file mode 100644 index 688dacc..0000000 --- a/pair-programming/src/electron-frontend/resources/main.js +++ /dev/null @@ -1,100 +0,0 @@ -const fetch = require('node-fetch'); -const { app, BrowserWindow, Menu, ipcMain } = require('electron'); -const path = require('path'); - -let mainWindow; - -function createWindow() { - mainWindow = new BrowserWindow({ - width: 1200, - height: 800, - webPreferences: { - nodeIntegration: false, - contextIsolation: true, - preload: path.join(__dirname, 'preload.js'), // 确保路径正确 - webSecurity: false // 开发时可以关闭,避免CORS问题 - }, - icon: path.join(__dirname, 'assets/icon.png') // 可选 - }); - - // 加载登录页面 - mainWindow.loadFile(path.join(__dirname, 'renderer/login.html')); - - // 开发时打开开发者工具 - mainWindow.webContents.openDevTools(); -} - -function createMenu() { - const template = [ - { - label: '文件', - submenu: [ - { - label: '退出', - click: () => app.quit() - } - ] - }, - { - label: '查看', - submenu: [ - { role: 'reload' }, - { role: 'toggleDevTools' } - ] - } - ]; - - const menu = Menu.buildFromTemplate(template); - Menu.setApplicationMenu(menu); -} - -// API 基础URL -const API_BASE_URL = 'http://localhost:8080/api'; - -// 处理API请求 -ipcMain.handle('api-request', async (event, { endpoint, method = 'POST', data = {} }) => { - try { - const url = `${API_BASE_URL}${endpoint}`; - const formData = new URLSearchParams(); - - for (const [key, value] of Object.entries(data)) { - formData.append(key, value); - } - - const response = await fetch(url, { - method: method, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: formData - }); - - const result = await response.json(); - return result; - } catch (error) { - return { - success: false, - message: `网络错误: ${error.message}`, - data: null - }; - } -}); - -// 页面导航 -ipcMain.handle('navigate-to', (event, page) => { - mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`)); -}); - -app.whenReady().then(createWindow); - -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } -}); - -app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } -}); \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/preload.js b/pair-programming/src/electron-frontend/resources/preload.js deleted file mode 100644 index 5f08f7e..0000000 --- a/pair-programming/src/electron-frontend/resources/preload.js +++ /dev/null @@ -1,129 +0,0 @@ -const { contextBridge, ipcRenderer } = require('electron'); - -// 统一的会话管理器 -const SessionManager = { - // 获取当前用户会话(强制从存储读取) - getCurrentUser() { - try { - const session = localStorage.getItem('userSession'); - return session ? JSON.parse(session) : null; - } catch (error) { - console.error('获取用户会话失败:', error); - return null; - } - }, - - // 获取当前考试会话 - getCurrentExam() { - try { - const exam = localStorage.getItem('currentExam'); - return exam ? JSON.parse(exam) : null; - } catch (error) { - console.error('获取考试会话失败:', error); - return null; - } - }, - - // 清除所有会话 - clearAllSessions() { - localStorage.removeItem('userSession'); - localStorage.removeItem('currentExam'); - localStorage.removeItem('examResult'); - console.log('所有会话已清除'); - }, - - // 验证会话是否有效 - validateUserSession() { - const user = this.getCurrentUser(); - if (!user || !user.sessionId) { - return false; - } - - // 可以添加更多验证逻辑,比如检查过期时间等 - return true; - }, - - // 刷新用户会话(在修改密码等操作后) - refreshUserSession(updatedUserData) { - if (updatedUserData) { - localStorage.setItem('userSession', JSON.stringify(updatedUserData)); - } - } - -}; - -// 暴露安全的API给渲染进程 -contextBridge.exposeInMainWorld('electronAPI', { - // 页面导航 - navigateTo: (page) => ipcRenderer.invoke('navigate-to', page), - - // 存储会话数据 - setSession: (key, value) => { - localStorage.setItem(key, JSON.stringify(value)); - }, - - getSession: (key) => { - const item = localStorage.getItem(key); - return item ? JSON.parse(item) : null; - }, - - removeSession: (key) => { - localStorage.removeItem(key); - }, - - // 新增:获取当前会话状态 - getSessionState: () => { - return SessionManager.validateSession(); - }, - - // 新增:强制清除所有会话 - clearAllSessions: () => { - SessionManager.clearAllSessions(); - }, - // 新增会话验证方法 - validateSession: () => { - return SessionManager.validateUserSession(); - }, - - // 新增会话刷新方法 - refreshSession: (userData) => { - SessionManager.refreshUserSession(userData); - } -}); - -// 直接在渲染进程中暴露 API 调用函数 -contextBridge.exposeInMainWorld('api', { - request: async (endpoint, method = 'POST', data = {}) => { - try { - console.log('API Request:', endpoint, method, data); - - const url = `http://localhost:8080/api${endpoint}`; - const formData = new URLSearchParams(); - - for (const [key, value] of Object.entries(data)) { - formData.append(key, value); - } - - const response = await fetch(url, { - method: method, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: formData - }); - - const result = await response.json(); - console.log('API Response:', result); - return result; - } catch (error) { - console.error('API Error:', error); - return { - success: false, - message: `网络错误: ${error.message}`, - data: null - }; - } - } -}); - -console.log('Preload script loaded successfully'); \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/login.html b/pair-programming/src/electron-frontend/resources/renderer/login.html deleted file mode 100644 index 7d51f60..0000000 --- a/pair-programming/src/electron-frontend/resources/renderer/login.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - 数学试卷自动生成系统 - 登录 - - - - - - - - - - - \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/main.html b/pair-programming/src/electron-frontend/resources/renderer/main.html deleted file mode 100644 index 37435c4..0000000 --- a/pair-programming/src/electron-frontend/resources/renderer/main.html +++ /dev/null @@ -1,432 +0,0 @@ - - - - - - 数学学习系统 - 主页 - - - - - -
-

数学学习系统

- - - -
- - - -
- - - -
- - -
-
- - - - - \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/quiz.html b/pair-programming/src/electron-frontend/resources/renderer/quiz.html deleted file mode 100644 index bc7962d..0000000 --- a/pair-programming/src/electron-frontend/resources/renderer/quiz.html +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - 数学学习系统 - 答题 - - - - - -
-
- -
- -
- -
- -
- -
- - -
- - - - - \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/register.html b/pair-programming/src/electron-frontend/resources/renderer/register.html deleted file mode 100644 index dbffcca..0000000 --- a/pair-programming/src/electron-frontend/resources/renderer/register.html +++ /dev/null @@ -1,260 +0,0 @@ - - - - - - 数学学习系统 - 注册 - - - - - -
-

用户注册

- -
-
- -
- -
-
- - -
- -
- -
- -
-
- -
-
- -
-
- -
- -
- - -
-
- - - - - \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/renderer/result.html b/pair-programming/src/electron-frontend/resources/renderer/result.html deleted file mode 100644 index a229fd5..0000000 --- a/pair-programming/src/electron-frontend/resources/renderer/result.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - 数学学习系统 - 成绩 - - - - - -
-

考试完成

-
- -
-

- -
- - -
-
- - - - - \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/resources/style/common.css b/pair-programming/src/electron-frontend/resources/style/common.css deleted file mode 100644 index 19382d9..0000000 --- a/pair-programming/src/electron-frontend/resources/style/common.css +++ /dev/null @@ -1,118 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - min-height: 100vh; - padding: 20px; -} - -.message { - padding: 10px; - margin-top: 15px; - border-radius: 5px; - text-align: center; -} - -.message.success { - background: #d4edda; - color: #155724; - border: 1px solid #c3e6cb; -} - -.message.error { - background: #f8d7da; - color: #721c24; - border: 1px solid #f5c6cb; -} - -.message.info { - background: #d1ecf1; - color: #0c5460; - border: 1px solid #bee5eb; -} - -/* 基础按钮样式 */ -.btn { - padding: 10px 20px; - border: none; - border-radius: 6px; - font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: all 0.3s ease; - position: relative; - overflow: hidden; -} - -/* 按钮交互效果 */ -.btn:hover { - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); -} - -.btn:active { - transform: translateY(0); - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); -} - -/* 主按钮 - 用于主要操作 */ -.btn-primary { - background: #007acc; - color: white; -} - -.btn-primary:hover { - background: #005fa3; -} - -/* 次要按钮 - 用于辅助操作 */ -.btn-secondary { - background: #6c757d; - color: white; -} - -.btn-secondary:hover { - background: #5a6268; -} - -/* 成功按钮 - 用于提交、确认等操作 */ -.btn-success { - background: #28a745; - color: white; -} - -.btn-success:hover { - background: #218838; -} - -/* 危险按钮 - 用于删除、退出等操作 */ -.btn-danger { - background: #dc3545; - color: white; -} - -.btn-danger:hover { - background: #c82333; -} - -/* 禁用状态 */ -.btn:disabled { - opacity: 0.7; - cursor: not-allowed; - transform: none; - box-shadow: none; -} - -/* 图标按钮样式(如果需要) */ -.btn-icon-left i { - margin-right: 8px; -} - -.btn-icon-right i { - margin-left: 8px; -} \ No newline at end of file diff --git a/pair-programming/src/electron-frontend/start-backend.bat b/pair-programming/src/electron-frontend/start-backend.bat deleted file mode 100644 index 81b488e..0000000 --- a/pair-programming/src/electron-frontend/start-backend.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -echo 启动数学学习系统后端服务器... -cd java-backend -javac math_question.java -java math_question -pause \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/.gitignore b/pair-programming/src/java-backend/math_learn/.gitignore deleted file mode 100644 index 13275f1..0000000 --- a/pair-programming/src/java-backend/math_learn/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -### IntelliJ IDEA ### -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ -.kotlin - -### Eclipse ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ - -### Mac OS ### -.DS_Store \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/.idea/.gitignore b/pair-programming/src/java-backend/math_learn/.idea/.gitignore deleted file mode 100644 index 35410ca..0000000 --- a/pair-programming/src/java-backend/math_learn/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 默认忽略的文件 -/shelf/ -/workspace.xml -# 基于编辑器的 HTTP 客户端请求 -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/pair-programming/src/java-backend/math_learn/.idea/misc.xml b/pair-programming/src/java-backend/math_learn/.idea/misc.xml deleted file mode 100644 index 6f29fee..0000000 --- a/pair-programming/src/java-backend/math_learn/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/.idea/modules.xml b/pair-programming/src/java-backend/math_learn/.idea/modules.xml deleted file mode 100644 index 422d56a..0000000 --- a/pair-programming/src/java-backend/math_learn/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/.idea/vcs.xml b/pair-programming/src/java-backend/math_learn/.idea/vcs.xml deleted file mode 100644 index c2365ab..0000000 --- a/pair-programming/src/java-backend/math_learn/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/math_learn.iml b/pair-programming/src/java-backend/math_learn/math_learn.iml deleted file mode 100644 index c90834f..0000000 --- a/pair-programming/src/java-backend/math_learn/math_learn.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt b/pair-programming/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt deleted file mode 100644 index 67cd00c..0000000 --- a/pair-programming/src/java-backend/math_learn/math_questions/张三1/2025-10-09-19-22-22_score_100.0.txt +++ /dev/null @@ -1,64 +0,0 @@ -考试ID: 20251009192152 -考试时间: 2025-10-09 19:21:52 -得分: 100.0分 - -1. 20 ÷ 5 - 3 = ? - A. 9 - B. 0 - C. 3 - D. [正确答案] 1 - -2. 10 ÷ 5 = ? - A. 12 - B. 1 - C. 0 - D. [正确答案] 2 - -3. 7 - 7 + 27 = ? - A. 34 - B. [正确答案] 27 - C. 18 - D. 23 - -4. 48 - 18 = ? - A. 33 - B. [正确答案] 30 - C. 28 - D. 39 - -5. 10 - 9 = ? - A. [正确答案] 1 - B. 10 - C. 3 - D. 0 - -6. 2 × 4 × 1 = ? - A. 0 - B. 12 - C. 4 - D. [正确答案] 8 - -7. 45 + 46 × 1 = ? - A. [正确答案] 91 - B. 101 - C. 88 - D. 89 - -8. 4 × 1 + 39 = ? - A. 40 - B. 45 - C. 41 - D. [正确答案] 43 - -9. 28 ÷ 1 = ? - A. [正确答案] 28 - B. 33 - C. 35 - D. 23 - -10. 47 × 5 = ? - A. 226 - B. 243 - C. [正确答案] 235 - D. 228 - diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class deleted file mode 100644 index 353bdc304f1b1484376f7bff793065ae0e3c0462..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4196 zcmai1dw3LA760AI?#^U0Kp05E@=TVH=Cxf*YlK~(l8``X9>@kFk5-4xm<-vS+0M-J zkYZ~s)(6%{s}{71wSsS{+NFRZ_$XSn+SY1))<-{I{e1l4AELGK+?idn%P#HrC9`+W zoO{l>=lss^+(? zm7y#<2}ey%j#z3^3!)Pd5!cFy;#CYwlV&<u|{{> zrV(!>PnNAYtMldR!fQmVkg*amhQ%-Mg%V3UE5oBGu?4_vm9UCo!P;a}v+W3v%`#Jw zwW*Z3H!^JLza(my_*?rowr%BlLo$Z3 ziRxZdvTk#Xx@#WQtAL*2tV3X=lxS)?9>iuOM2yJTf~^d5D=ASY?X`4=u;6dq(al|L z#_MHl;}G*FQ>IP8+JT)SZkBNiZ*&(}Y1NrXX{u#J)6`?BsG8BEYcqNwe1>Y>PGsFm z@a=Dup<)+9kYXRC>Zlxha|>a+{FARD*B+Ch;Z4LJq`gjc)GJlB{Od^#B z({x;es%|uQs|0J+7)x;)kWH83M$C-_Ooo=?lH^SmH)lQ|g^1ITVS@U+A+1ho1S|sh zsP0VA%63%4q57_D-CmB!a!CdI5-2pEkxivU5Y`*q8Wm-vJFBOtEhX$B=pG2d#y(Eo zRQ9^!16*zbPE`kF+=hb$Kx$5Fe}ebW>_W0#9w$+}2Djr55pR`oC*D@VY3>GzFkz{V zNzv7p?CsCX$-p7JUBulo-obI9xRJZ&3o2B?3Dq9b_BmYlT{7Oy%jz>oAmTj*x^}k^ zk2d%6XeGRt4%*2N`hFQ7z`exZ#46Mq43SDFF3WO0W5iJ(Bun8M9L9%b+|OMH2vIj_ z`?>L>-1tYXuz6J&Oxt{bK?ujV(T~eG#*Oke->RmvM1c>I!-L%VLozA1Q5p?bV{Do#mm962)g2$Dy%=vJ z2J-a~TM&f}=!Q0wP4CjI5p`FJB()y#Zc;5Ztr5VerDkOK;OH~0w8sHUi_cveW&uHQ z+T{*JLX&G)#05fGg_{HsR6-v&R3~eZ_x@Kly{bGR<&rfNfLu)D3~?_PuP}(?{pH4Z zzJix0zb)dsg@&O^LjUmPH-u^@PiZT!OngOhj#t0~xk{K>E2;JAyd2e>J+I|xB?u2` zwzI*ssbzmeUCseeT3M=Iw`n@IW2u?T^YbaX(Hscd-UtZCSZ6rx@qRcKX5r5881XuZ z4@&q6jd>Ey3gD+f{0z^E_&EpWFA7&8mkV`ck2$GDy|Q}@+@~gqornkTFRor*(Tl@F zq}@DVnv>Z~aew6TQAWLA@AA6{sR_qDM`o62zVy4E=_oSv@J$w)rifreq%Z zUA`0X9K*6{)-Q>p^Z+7$M`P~gRS6B=X?=|}9tCRiQ#8Q*wDRLLJ;q;d00n;UDQo$)7NX{TcJwUvNG9D_#3u zKo9#HM%h2Ho&6m<**~DtyK(j}e1k$Bf^Q1TAc~j}Q6r*B#CiH-bjT^(fa)^2t92es zM9U=vrYLvxqba|a?0u8|1$>JV@@;&_OApOJAE^PGC?y@rb;|WQyxLvHmDPpijmp}> zvPZd&FBe9Xc{%i+JCs8|X%F%QdZHX&7xLvWI$fU@RMYAIjT&|d_3S@rV*f=a`yW=a zmvAGS!bYm;u)y#bMd72|U8Lvt@Hnk_(PQ+D7rma`Y^VP>w9_M*!}uAbfs^#cLxDni z5d8290R#mRb+i`v4a>8`o`U7Jf7ZFfyJ=t*qO-FEB$9Xgjo`tqTUeNZIl@dV5@w-Ms6~%3 zn~I`96XqZ*%*8&T4hMvK+$l8RZebqo5kk0En2!g91vn-w#93hxE((kBl&}QP2#t7F zXu@+s7|#n!@q*Bd7ljrV(i;&JIi>?HE~!q0X`AqR2zZgN4_`tDL1hY!(<;Y{R2GX6 zE}@oG8mQpkchB+z{LuY;0zanDnRL2msOV3+&!_QAlFg^$Pv8ms$|ukTs0qIgRO2`J JEq;&C{{g`EdAa}q diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class deleted file mode 100644 index b5329c7850143c7fe0bb18926c3368b7b2f43bb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2465 zcmb7GU2qds6#niu&2G~LN}#Plh0+F0Qqtfr&>+$jY71>zNhp@8uuU$_(#>wz-Lw=$ z#}{9G)fsVc#s?kW)H)aj7|}<^cW2ZY^+Em||7V=>&GGCeX;T_uoKAP|J$uf%=X~co z=jO|Qu3Q7qhnJfmph1L3MkBlop^TA_Hp_(-}8@hL&k=AL6Hq+_Fcw zoinl&dMG@6Qkhj^8l@OZ*`}&bQ|N7I7jd7A05*`>oeGpXc~LZrp*2)vK00-hXY6?R zsDuX?;3H%=%GiVs2HE0z_7JxUhHi0&csa*=L>wQgabAhd!J(7EGd7w^O9&FMXFIuR z8fIs2XE~`3-LN|pO*7_rw)30=)K(b}A;hqHDgT6#op+$FWUm^rA-zzv=@72u34jQ? zMQoE1MGwO|7l7qDloF|C`!p>vZ*xMz6ADizny?)Yi+DuFqj-#Avumi6C6&Oms5U8^ z*rS+PqLi~IyT-%mfnz%vHk5O%Rjw$x^?1VJ(GG@9p~=L5Ylg=i(09q`MVw((!8v5W zF!TEqTOpRz7ORS9*;&z6H6nW^++64aEgB9gG5q1n)~)lQP|GzoM*wOMO8(FT!l!6-TE2vdQQ;7sTBjXTK&Rj4KSccB9>&{ND zZ(FAWMI5fu&TUNUVP3GQA|j4dx_xOz)%EH_8WS>(I@7^NRT`m+D%0FgL+?2m&*KGR ze_om4{f3@V>?5k3qm@PMbU3-Jpv#G}d`^txxWh~0Rw#7zuJ~4IF;1P*PY_a_hgF>? zi}@*Trj;p;BrW9z9#c#u&uwl}BwiX_G;JOKZXND5F~a136*XCAhR9rT>sv(65^=JM ztJBV-i(d$&luz8kQ`0A~9Ub*q^!tIOi^>(l|UYI^uutgLdz-JkPZuhtds`{)k!z%-~T!R56V;d$- zr8jH2TTv{ZSH3K);ILuL6btdY0=~>JJzwB;)F*2^R0~uis<`N?d@yjFDBH3f>{i(!Ca6`0p>_!3F>3iuf&8%--;KIpV8mo1hO{N(g_9*d;tZ64_S5&SccT`!e3 z^awvs6VrrIGd%5W ze9~%vBfs6O({YZyiG36(#>wzy(x4Y zXPn{12Osc(8TDDmH=Q~d22jQy4>F9u{|B7@0nYfwcsALzTUy1*WcTjfbH01dcfND> z-h*3r01RTO844Oy1T-|Fi6N4+iiskZ1w(M#OpJ5gjHGo_cM8Lod2xiBc|+I?O|qan zk%J67#x^=6LkOZ-MMy&nG=|+9O(H4oh&8k$bb>s}&=K7XE;bXyRt9xqa(Z+klMSH_ z+f;-#Y{w3U9v9syn+a3ML_x}uBkVZh6JcTI3*0uaoR({E)+RI+I5~F6REa?!zi$p*iy($i9=tDol z_9_AEZ73x&%?}zzYDo%WA`p$urkZgOPpf!F!?SpfVQ+yoCqZb+WL}yd~ZW)_#Nk6P%07-@|CHK&@WfzZg$w?*t zV%7Pqft96hkkCuXAYNiDO>#*SbJonP%UhQof`)p*yt6|KB561=1*21|NfV8ob$S2c`b+-+0q zgkzaixc}q3NkgcZsH>pbC)84+B#9suuX)Y4HZC@eD1;2M8m8T54H0SML@=KhVVXZP z8cyML5@V4sh#||&ad}FY1zI^I7D*CW$L}f+4|gRcJ&7}}OlBFP(KEgRcs{@R^JdwS*vX4L|S)GYj#I)znd^aFhk>O#BxY?Z7Iu=jfJ1s3nU0d?6m$D4F*qC1qEI7{nBS`r4sIlSfhKJXAf2yf}F zptXXXA7N{}cN^}8AFtramS%;(axn zWeT$&1}tiArJ6~KzBN$3hNgUjcI6H_l<&}^e2+fm2lOjH;+S$5Y2_ZW%1=0}{0u|+ z9hUM7O3JUeqWp%d${*mwLJI;N?SH#-H`9eV+6d55Il2m3D>#q&>U|gmx(Dgq0{wMd Yq^DhIAd6wxbPdwo2`G?Q#AS5;1NY~EkN^Mx diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class deleted file mode 100644 index 293b2db69ca5858fbbb3a0309b84f1f33122d2cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2454 zcmah~-E$LF6#w0AnoZLMN`Thl2c->=q_n{=ga(l&P#SETN=kuNh1=wsY@6(c-J8;a zh#xP$FoQEPqrUipX+_^bm8+EjQnw8P7=KVuf7MK1FN!7U>?$#o-mS{TCOQk+`h#c^(A3&LXX%Dip| z4>9bVXm*MD;X{WCzlKg|3@!m~bXWl&SoGs)Cc+K(=5 zR}s*#13MW89CW*EL=7RMc_~Y_u$F}t9jD=`l}w%+Il<7C6Y{LMQWmzH6f$pS>FA;G z#3Enj(E^!7)6&w7938zIJu05l(2L#Vw%LF}Clp?=8FqzS?x}@Ek&&_RoDVNBz)!rs zq+t*G7&KcL*|WkfnTAa#iPd6!#))G|7kK?_4iEhdp6OJ2#)lvgd%a&+mTC2m^w)yw zGfdgX3kCD4$oAiGh}y5=0748~H{y?**;R+?di1&(O&X=Lq)h}b5&;nmsyL`&2*V6J zssuc3Lm`oAcC=84uS!8octYX%cn1#QWfiYzconZP?5#Q)bmmf=~4^rIR^5M$UQ^8IjO{* ztOlPou(H$(B=u6vhc_8IY+>8FX(Y3qcnc>~jB1D@L5S6W8paH5#3)sa8@C|>SL*6Z zKAd9kl}Va2t0m#XX~L_Dk#6FuQgBYg zEY3R(!aQS}2E)y(y~$4sV85Eq_kPKGGa`3cI$B3|F9!O(%uv`&T-Qw?RCXXQ`*wv zrP@ht9~?#g`Q^8Ne17}!4|g8jT7PtR?eYEZM*7$`FP8ndiWL>B4&m1rf*Z=#jb(F5 z)H`o22V*=VO^e#oS8id}4Qu<=ZVfv)VVX3bR#AT+@@AROt!orJ6#u?ikl4kn&NI1j*3sHt^dC%38EG|`l#T1Bxcst z<=o#iQs_r_E*+6v;bVde$1d9x=LtS&sk)x-V-cT+hPvdqP5(a~g#hNcWK!^_Z zy}*{i3bs|S>uYR{3~tA7f#)lDaV@a7zWhyfncWEtILi;weUU!ws~~(2(RI8&897+N zk*T4;v7d2V!LR5Z@eBn{KAE%+1;!eapD=#d8@UhG>*;OZ<*i_9M6GTa=~XM3A^h(V zoP3D6i){q@?gLz+VAheDA|v)!WTAdihtrpHFJLA0P% zMo7VCY+>ke(CxAw*SUxngfMMx&2uY0OvA$$as^eNk3>h# zs`F~RNG9>Durz&^TyIB*j7Jo7Vk>Q1Z9t(DidwW8+9ICqV>4%YP9&nI19*%9L85h= zg6-&HP;9Q}C%A1Ix=o%WYB4^<<3!p6?)v8N(9Pf*AInY#5GG*)<2vw%1u^~dQ>YvRGZVj z#^aNzGy52})?)P~(bX9K-g=bn?F~qf-v)`xOiz!LY$}4ow+W>5wW^Qi(TN zbv|ogWuX;G>1HB;=NX!8ZrddFbiNrc;-HK{1xXAMVl|+;F+&3}%CO6eTNi;Rb?#CC zhY6u7KL=aS^9w;7!LW?9f}?nep>;)RX1eSs_IHco)_b)sl^9Pt*%^3g@mkvNgQ|T-#BU;I>Y|e6}$f4 zbt+B9iMqV11xU5ZO{dAoIOSILN+VhqHHaxpD|p%I0zry0Lzz=&d5AjOs|wEGHBxy= zo#R7>o>RpMO%!NklL`fC?}5bC3H2n-T?*nPW*q(H7$T9=YYjXr_4H3sMGO&z44XzY zosX7FGu)a~XNpcAsuk+EYN;hIxJ91$sYOv&b?~cscvxqM68;7%rraEf)`bn;XU~>V ztn=!W?b!V297ktE~>WxX_>XOIF~bx zB>K^fO3ysada84vIoA6lSgdy$@{(f?PES9*AzjAnG;X9JVKB_1P}|G45TZ<PT$5W z>7P^__u9?*M(X>3>vdG{KdIsoy(I??ea`bI<{tK|Aoz?&V diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class deleted file mode 100644 index b1499eaa7a2c365b58418106b69d1c58ca13a056..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1669 zcma)6ZBr9h6n^d{$%e2XMh(Tbih*iggtc#0iM0|m5C};m0Tq1dlH4I{H@oTXjn=XK z8U4`y3!OGj+nG*3cKV?|snfHYfQ!(nvom|&&Uwx`&w2UlpI?6muz*Ly;22U6QV~Xk z;cUZhYi(V&OrblLwx%1_Ov&CgtYzJ5n!;g-$d=*GTw*v`IxL%uA&OxIF%=_F8O|IQ znaS&}c#U?=unc*fVIp-DTzWH#F$SeltrsihS`6bjt{|@B1Wqzcd+2W0(kvmhmXsY= zI8TJ5Ez|baH;tBV?FxqRT_M-S*InVtH6dGelUz@wOON#@x@MAyR+Ell?UL&WOelCq z#UxIX+M5CtI-%&M%Wx_cP_OJf77dw8Z$kuH0`INnf%Tp>b!~zNHL7P zjz4cVpLtXdqBm@Gd1KYS6&I?*RUOBnL6tc2k&|-Z8X=jXqg z9?>e4_eHY9aI9olqTFro2&b;^m|nN_%dx6EM5GiB^>+22-XzYcWEx*l zY6h?|>SxiB1~rm`yTRhD?7uL?YIfIYh=So+8}^3RoR>RFK$*IK*>)*!YSFTUvuILA zyaHAaPPdW3bix#|7Ns%C#>c(sNIOm+4L15$=``)1fssu1XRu866_gjAIBwHFLM!+Z z)@dK6EnzU!P#@_2O^6CTeH$Om_He9+Q$JuVlRb_<+HTyn3?Op$d z#65cWpojEJXs__;TIOO8SIV>TYro(+#~(<{hi2n9_YdLBPhgXw$#4&a`G{{IGa2cj zeZK?ou6 ki3B$N9m5?A;hvAXg>8Rb!hKrfK37Y4Kx>q`;9-dW3x(CM9{>OV diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class deleted file mode 100644 index b371211d0f671fa22e3e2d6b0c31649100c335c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2275 zcma)8-*XdH6#njR+D+3fEdg4K3ZX5Sq_n}`&>+&3))w2el2U{!xJ|Cj(#_sw_omQs zoMFZXU-f|*@ma^`Iv7S69UmS44@P}w2AxsHv&p92(kf1;d+**o=ey^8_dDn2m&f;h z1Tc!VHYiXvM0B*El_60Sl}yEuWs4iGotZIAdth2Di>jP7?2^S@hE`cNy@6v4d#AS> zXJd$>O+!paJ9LHv+f4>?hQ~M2PMWqUPcif)cY;eTM6ruOo1L4Vn#~tt=)!IdaUFZG zm!aQB_o{Zr<}y>3(($;v%H7N)O~-E(%Z9zo8M>CaJjbt9xhH41EQ=C_o=i<&HCBy` zMJAbobWMAiLhnY8hG%s2Vn4Y(X+WtHieY&S`;sB|*`=$zD6^?cQ9Q?h7%_T4$3Y|* zbdTGmbKG-;?NKDzMvhO3I6D;r4`TCq=wpb?%@*dP7$9Ol>f^2}+`f^%Mp6k|$b?~8 z;yN$&ee4r;M8^wAGVI#SKPO6SKGi|?rpQd$PF2z-+^7%%X$)#Os$&Sl414MXY_*}3 z$h0(SS-CaIiHS%uwU}$eF}$eZB^@v06^27~N1Ht92wacOrXWc@hFcnIypvzc`T2<} z#~JoFat#{?M)mV}&DYWE3CL&@qB6Lx7Koop0uFtmBx^Gsn+mD=$pPHPy|k;51v))Q(PGpNKU!;vsQWIUZel$}-J75{e{wY~gl;hbJqNlAgmQUm}YP$>gOF`GHSprFlXNB-$~ekfC$h zw0XW-S>o=zv1IwJqESn8hHF%~BEg z`1Ibdx9>mr;nst%)_=S6^+p#;mK$zcp#5&>!7*^n8!r z`s?pNdwTFYu=LWSQs)`A<1qJ$jaaoPRQgsNm4UQVaCu%!B zQ#)V~3+;&XbU*U@Z9ah|T8PkAMS60YEBFx0^>G|!8l&`Wh5k)kqqqG~$zmKXJ)<;w M5d{*fxPjh(0H+~#Z~y=R diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class deleted file mode 100644 index de3d7545570ca66b33dd37bd23a31ede7ed7914c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1894 zcmb_cZC4vr5Pt3@WH({U%eD;$wWR@TUK$o{t3W7)KqFKjNK&*#ZI|RWY~Ad}-AyZc z{Ok{~e$ap5$9gpQa*oH39)Fa_*-c0z;L#7BoU?c4W@hfpGtbN)fByU{fF;x-;OLVO zQqYeuL!x5WwYu)@n?iRiZ9_M#$!$?HTu(Twx>YrW!w~lN4R>;y;oSO3^IQ}%A`+qs z2B0upIB7DO*In^E+Pq;I-U7pD^0aWN9T|fRQgN%iR@^K_F^mxjs)DmP$1veXcbk@G z2~XSiyoM{B$HLK8Nxbz*WnZ^yf?>EOylwGuQ@GxS@b>L0rJhW!KhhuTnn@;F$#V>= zMybazD&YkMag34MaRVxyqUff}a6Z}NUfg>mDqb#iPsU3Oh!Un36kNnOgW?LSx-Hy> zZMl?5u3h85WSm>;3Es)g$05NG+A5aHGA0Sw&l19MY$q|7XcskZ+1|Krn)VY>O?>VH zby>lyNHPpQuRm{B4}7RQ)f=|9W;L1~JtFiv0gy&U!W9KsOfj4d0QkENl|-i1CDY6w zc!H1!B~!ck2&VCxgx3{Z#WjXYfulv9)B?w)-jqCIkM2~L+dBF6-zgXF&oGR&Ywb1e z7zO=!!{^bP3>TBT`G2-d?f9V2Dwso#;Y`DSv|u~+72VT`CB4l$!m}N$=@}-`ypfY} zgK`pe-7p7m6N?g-6y&i?(Sl-*3>o?eO@_<8F^>q))3(l)j9Ww`Cm10|_YB)wwyQ$M zTMTlO$ZF|z($+|8=&t+3cB(SoW*Dm2)Iu7N7hKQnwEeY=^*hYy#Jvm}z z+>HmC_IyS|1s@K%?hM_GrjH5}Q)^glYu!DE~ePZ8sZHr;{_y#!L z_ms&c8v3{raO;L8Hkf*23I~J zrgXwaX}ySs-%wY=gWg#wcK>0Bmh7fe5e374E#j}!DW6T$o=sXttF}u_Qr0X>ILjur z+MlPP6Z>|cXJ2BRfRkx=v*BTXWs}6|N2`{;?~yhU=)gca^8;8qa|r2~Z;re44busp z!99}uNu(GIyLi9t%f=v4B;ZH&Os0jQ7S4Z-!E|N>zpF2{@bWYDQs?@c;F^7o+_%&qt zbxiRYEb>_tcn&2#j|cn)>U;s8@|*aAFXAcB<6FLrL%xC!C}IeFG=>iYiQzu_pa<{l Wp%R=$ROwU$+=~!&$~2!3L;NpiIqwqy diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class deleted file mode 100644 index e2419eb2144be39a18e68480ebca674f5a1a14d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2772 zcma)8+jA3D82_DY+D+31O1KsfN*gfgg@DMdMU)mwi@ixofmX$Ba%{IvcEj!lsEAxd zMCDSXTpv&r2ge7n2;-R=~cE`A^tD#0&QT<`AMtATo#V~c*R5Z0li}E^IjmEgn zkZX1;hJPi)?1rgZtGw_aPlQ)OJ|u?4Q&s%cvXOzdQBf6h6T`efHn?D09;Rc4hyn>S z;bSQ1k@w4?n5=e%!hMFx;|zk9G#TbJ*ei+_YS9(d44XQa<5eEaW>`3K^TcTX$&qvC z$B!O+^wakvCr^)leQfN`(4)cQUd+Wj5%VP!VgbXfEFcVG!h(#cbV|TE#xcMoaaUEa z&4Wdx)ZEfq-`o`TVlkG8D3Y)g#SA4@1dOB_Qn?xGHqC^=_5EBA)zNh8!ALiG!pW^J zZtmdwlH4#Gx!J8nDZGK;)U&+sW0{EM5?)4Nax`pXC_RKC$Bd^;ZSL&h5wj}T?m;O7 zyi^0_5-PBQK{D)Y8wpJ{$dW224==E|s(z|%Rvf4-+%3)FRu5jGLx~}QPmBo%z zMXF{N$+4JrfJciDTY-92!Wyh)nEu57YAxDll|$NlN@%^BNKPcwi}lzbqEbQ?HfH22 zLx)_V+($RZV%2>nr%1R1!H()YY{Kgz-jJvVsu`BriB<`nQlJ}@o3Ke0F6+@6=bQHB z>};*wyPjcz<7=jJT8YZtk1bZMZ)I2#=%{|SX0Xji{kKg*9qP%wxZKNYG&LfdyA-pV zW(FN^(xJ<o}k8PCI@+3R$}>h z3p+%FCA4BEq1lm{P^9*v)I4R@L^WlYl@|HHu+59z*dwA{LI>Vv@J;0as&1$1CUXqK zhODMf28a_I#X@pI32ja&JGfK0lnEE!m9Q7@SrnyhH#BNjg8M&vvoxBI;I@f~Oq7`2 z@YJt7VG*K5N?gMG79$B%<6d;4TY_RWyqDtD$PGj8;ywsgG&&KJ5C_>a!zL1{v`BBO zE=Q={gg~%OL?X=-Pk1=1lRmgDJPn3ba+H-opgki8#CaAUWk@Cx)kaNVkvLhH202+!t!bup6(t-?4G%u19(VZruU{@y z7BLS#A;KHG_3fkU{UfJ-9KCj8{P^wB+k^Jfr{uN6{UaC7j0_Lh!q12Tp1KeoT~3i? zbl|J;fvaP8?$~NyFw7r2J2Z0c()bUj$L<`Xdt>D0;Ml$IXmv&|&UkSa=S1{dZGE1> zZ}*N}D~h^b>*d5MR!*EwuazUFrW3hc$*l6UqT`!$%NqU$P3ui2GE+GoqaiFf8g^_}pKC{EVwy#3hDhQ~b~7mWV5KIXqvL ziqMGxil`GkM4hal!1`mMnTsC!yPz>iUnTZ8kY8GMAFQ-&2;!inj{P*|(i=hn4$wS@ zri8(85Pi;G){#d1^Dd_OW~DI4x3DaQmr^LXis_|gGx5+DOrdPh7fOq-*-WG4-6`y< z%prMcVNMF~3`2I-tg{^v9drxp2sui4UBl?H6=>f30NNhG5$+?0hoCo+&Ft^e3PQ5% zBVX6zI&KgHx$JPX)87t+S?~yRFk6_5#lk!+5f-3KSco;kBCHjPP$w)!t5AY=!H+Is zIZPpdBSH}ULMg5bD{(_8!#6@X289aT7gpe*5W*kADttg8&WC%++<(v`qH{G4k-$wR zd`RO*GjF?D3>Mp0dZ!@g-?3AP#lWg>r#L54{K6E?mTA HTt(r3RPG%8 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class deleted file mode 100644 index bf68e842f2a3edcb45e524bc6754792a6e045a86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2443 zcmah~ZF3V<6n^eD?WXBMOQ5Yqh0+F0Qrh4fLW4+Cs13GFC8a>C;x@T9OOxHOdsC>0 zFZji8G6T-|GULk#!{~@(u>^$~$B&M`L(w1LjNcs3ZZ>3Tqf92d_ntlXx%WKhIp_ZR z&+VT84B_2oNNAAZQ_zSeh8-EB5G$x6m*=Xf$HrAn52Z_U1x*a;)){V&s(LohO@=0s z)2z@ghD~E@m&60`qgh5kK?@XyEo)su3Dx2?w0)YciTweF+Iv25=5Jiidi`z0%Tsfwct*q{Gk!e6 zfB^BjMZs2dGbk3>uf?A*vP(AAZuFWFOX|gvpiQ`1AOfQ3ld)4l zKL!{!It1MBLm`oCb|{}uED26b_`;FdL^F2baT!l2coI)BY;zXsw31R_T9li#AoZwb zcDOR9b&W@-Mo#Ww*j$O#>+Cu?`Pgmi=oyBs;n~E0dq$>h()TJDM4Vw=(cW~#FbfA& zp^{3x$*S^M0V@eDPf{<&{dkt4+2WR^8G16?g6D8R#*l&ph6&LLsOrqnK#WqwcyX&D z@TAT)`EiI49QoPUdX}FJ;CYP7NGdpt7Z^6wl$O*5pSP>b?*u{9Rbs22Kk3IfLyPLv zrVEL9896_2PxVG|aJ$fqI(PM3E7de@XtSZEUk>&ZATGV1gMXf4k%8rDi3Z`+) zZVAR=%g`D2t}f#GYwHxBj1yJGIWRgOKmbWH)wAZtsKia8vfS?l1j zR24BzMKVkjGPI6qI-e*N=D0bf&gIF{R;k@d)l>^yaFb5bL|uy-t&Q*G;X%zJLip>b zzA_7>V;44Xk3CBUrKMKMse50Dq_j~oGkip|cWbsA{(!9p(%uBM%2C52?X@KgLs-I8 ziZeRK1`sKS{y!ZQ+G>MXdYw7Y679PQ7VWzQdD(WyJUyG}4e1l)XxvCc!eG#FsO<~!&(K_9l45xIfbEj&FQ z-C4$-iT>ceAF*G;&*&KR^#>1DCqH0hcVmBW%sX$2u7Gv<+8f)O%9t3Gon50{av4*! z#WjS+?_lOc1L3}O8z(8ATgXh16ZA?{Q69!HQJI0@2a} zUuVbP$jUh0jXW8Av}J*w28|^YaoTyOVA9)9-%9kiaE@l1(Lf$4yg^Stz0dn3yotAQ H0bTzBRRXMe diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/Main.class deleted file mode 100644 index cd98b8c74bfc37346a2cc9babaadc4b24ae200e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16119 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 accounts; - private Map pendingRegistrations; // 待完成注册的用户 - private Map userExams; // 用户当前试卷 - private Map userSessions; // 用户会话 - private String baseDirectory = "math_questions"; - private Random random = new Random(); - - public Main() { - initializeAccounts(); - pendingRegistrations = new HashMap<>(); - userExams = new HashMap<>(); - userSessions = new HashMap<>(); - createBaseDirectory(); - } - - // 初始化预设账户 - private void initializeAccounts() { - accounts = new HashMap<>(); - - // 小学账号 - accounts.put("张三1", new UserAccount("张三1", "Abc123", "小学")); - accounts.put("张三2", new UserAccount("张三2", "Abc123", "小学")); - accounts.put("张三3", new UserAccount("张三3", "Abc123", "小学")); - - // 初中账号 - accounts.put("李四1", new UserAccount("李四1", "Abc123", "初中")); - accounts.put("李四2", new UserAccount("李四2", "Abc123", "初中")); - accounts.put("李四3", new UserAccount("李四3", "Abc123", "初中")); - - // 高中账号 - accounts.put("王五1", new UserAccount("王五1", "Abc123", "高中")); - accounts.put("王五2", new UserAccount("王五2", "Abc123", "高中")); - accounts.put("王五3", new UserAccount("王五3", "Abc123", "高中")); - } - - // 创建基础目录 - private void createBaseDirectory() { - File dir = new File(baseDirectory); - if (!dir.exists()) { - dir.mkdir(); - } - } - - // 生成注册码 - public String generateRegistrationCode(String email) { - String code = "REG" + random.nextInt(10000); - pendingRegistrations.put(email, new UserAccount(email, code)); - return code; - } - - // 用户注册 - 修改以保存邮箱 - public ApiResponse register(String email, String registrationCode, String username, String password, String confirmPassword, String userType) { - System.out.println("处理注册请求: " + username + ", 邮箱: " + email); - - // 验证注册码 - if (!pendingRegistrations.containsKey(email) || - !pendingRegistrations.get(email).getRegistrationCode().equals(registrationCode)) { - return new ApiResponse(false, "无效的注册码", null); - } - - // 验证用户名是否已存在 - if (accounts.containsKey(username)) { - return new ApiResponse(false, "用户名已存在", null); - } - - // 验证密码 - if (!password.equals(confirmPassword)) { - return new ApiResponse(false, "两次输入的密码不匹配", null); - } - - if (!isValidPassword(password)) { - return new ApiResponse(false, "密码必须为6-10位,且包含大小写字母和数字", null); - } - - // 验证用户类型 - if (!userType.equals("小学") && !userType.equals("初中") && !userType.equals("高中")) { - return new ApiResponse(false, "无效的用户类型", null); - } - - // 创建用户账户并保存邮箱 - UserAccount newAccount = new UserAccount(username, password, userType, email); - accounts.put(username, newAccount); - pendingRegistrations.remove(email); - - System.out.println("注册成功: " + username); - return new ApiResponse(true, "注册成功", null); - } - // 在math_question类中添加发送注册码的方法 - public ApiResponse sendRegistrationCode(String email) { - System.out.println("收到发送注册码请求,邮箱: " + email); - - // 验证邮箱格式 - if (!isValidEmail(email)) { - return new ApiResponse(false, "无效的邮箱格式", null); - } - - // 检查邮箱是否已注册 - for (UserAccount account : accounts.values()) { - if (email.equals(account.getEmail())) { - return new ApiResponse(false, "该邮箱已被注册", null); - } - } - - // 生成注册码 - String code = generateRegistrationCode(email); - - // 模拟发送邮件 - System.out.println("=== 邮件发送模拟 ==="); - System.out.println("收件人: " + email); - System.out.println("验证码: " + code); - System.out.println("=== 邮件发送完成 ==="); - - Map data = new HashMap<>(); - data.put("email", email); - // 注意:实际生产中不应该返回验证码,这里仅用于演示和测试 - data.put("debugCode", code); - - return new ApiResponse(true, "验证码已发送到您的邮箱", data); - } - - // 验证邮箱格式 - private boolean isValidEmail(String email) { - if (email == null) return false; - String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; - return email.matches(emailRegex); - } - - - - - // 验证密码格式 - private boolean isValidPassword(String password) { - if (password.length() < 6 || password.length() > 10) { - return false; - } - - boolean hasUpper = false; - boolean hasLower = false; - boolean hasDigit = false; - - for (char c : password.toCharArray()) { - if (Character.isUpperCase(c)) hasUpper = true; - if (Character.isLowerCase(c)) hasLower = true; - if (Character.isDigit(c)) hasDigit = true; - } - - return hasUpper && hasLower && hasDigit; - } - - // 用户登录 - public ApiResponse login(String username, String password) { - UserAccount account = accounts.get(username); - if (account != null && account.getPassword().equals(password)) { - // 生成会话ID - String sessionId = generateSessionId(); - userSessions.put(sessionId, username); - - Map data = new HashMap<>(); - data.put("sessionId", sessionId); - data.put("userType", account.getUserType()); - data.put("username", username); - - return new ApiResponse(true, "登录成功", data); - } - return new ApiResponse(false, "用户名或密码错误", null); - } - - // 生成会话ID - private String generateSessionId() { - return "SESS" + System.currentTimeMillis() + random.nextInt(1000); - } - - // 验证会话 - private String validateSession(String sessionId) { - return userSessions.get(sessionId); - } - - // 修改密码 - public ApiResponse changePassword(String sessionId, String oldPassword, String newPassword, String confirmPassword) { - String username = validateSession(sessionId); - if (username == null) { - return new ApiResponse(false, "会话无效或已过期", null); - } - - UserAccount account = accounts.get(username); - if (!account.getPassword().equals(oldPassword)) { - return new ApiResponse(false, "原密码错误", null); - } - - if (!newPassword.equals(confirmPassword)) { - return new ApiResponse(false, "两次输入的新密码不匹配", null); - } - - if (!isValidPassword(newPassword)) { - return new ApiResponse(false, "新密码必须为6-10位,且包含大小写字母和数字", null); - } - - account.setPassword(newPassword); - return new ApiResponse(true, "密码修改成功", null); - } - - // 生成试卷 - 添加详细日志 - public ApiResponse generateExam(String sessionId, String userType, int questionCount) { - System.out.println("🚀 === 开始生成试卷 ==="); - System.out.println("📅 时间: " + new Date()); - System.out.println("👤 用户: " + validateSession(sessionId)); - System.out.println("🎯 类型: " + userType); - System.out.println("📊 数量: " + questionCount); - - try { - String username = validateSession(sessionId); - if (username == null) { - System.out.println("❌ 会话验证失败"); - return new ApiResponse(false, "会话无效或已过期", null); - } - - if (questionCount < 10 || questionCount > 30) { - return new ApiResponse(false, "题目数量应在10-30之间", null); - } - - // 获取题目生成器 - QuestionGenerator generator = getQuestionGenerator(userType); - if (generator == null) { - return new ApiResponse(false, "无效的用户类型", null); - } - - System.out.println("✅ 开始生成题目..."); - - // 完全移除去重逻辑,先保证能生成题目 - List questions = new ArrayList<>(); - - for (int i = 0; i < questionCount; i++) { - System.out.println("🔄 尝试生成第 " + (i + 1) + " 题..."); - - try { - Question question = generator.generateQuestion(); - if (question == null) { - System.out.println("❌ 第 " + (i + 1) + " 题生成返回了null"); - continue; - } - - questions.add(question); - System.out.println("✅ 第 " + (i + 1) + " 题: " + question.getQuestionText()); - System.out.println(" 选项: " + question.getOptions()); - System.out.println(" 答案: " + question.getCorrectAnswerIndex()); - - } catch (Exception e) { - System.err.println("💥 生成第 " + (i + 1) + " 题时发生异常: " + e.getMessage()); - e.printStackTrace(); - // 继续生成下一题,不要因为一题失败就停止 - } - - // 添加小延迟,避免快速循环问题 - Thread.sleep(50); - } - - if (questions.isEmpty()) { - System.err.println("💥 严重错误:一道题目都没有生成成功!"); - return new ApiResponse(false, "无法生成任何题目,请检查系统配置", null); - } - - System.out.println("🎉 题目生成完成,共 " + questions.size() + " 题"); - - // 创建试卷 - Exam exam = new Exam(questions); - userExams.put(sessionId, exam); - - // 返回第一题 - Map data = new HashMap<>(); - data.put("examId", exam.getExamId()); - data.put("totalQuestions", questions.size()); // 使用实际生成的数量 - data.put("currentQuestion", 0); - data.put("question", questions.get(0).getQuestionText()); - data.put("options", questions.get(0).getOptions()); - - System.out.println("✅ === 试卷生成成功 ==="); - return new ApiResponse(true, "试卷生成成功", data); - - } catch (Exception e) { - System.err.println("💥 生成试卷时发生严重异常: " + e.getMessage()); - e.printStackTrace(); - return new ApiResponse(false, "系统错误: " + e.getMessage(), null); - } - } - - - - // 获取题目 - public ApiResponse getQuestion(String sessionId, int questionIndex) { - String username = validateSession(sessionId); - if (username == null) { - return new ApiResponse(false, "会话无效或已过期", null); - } - - Exam exam = userExams.get(sessionId); - if (exam == null) { - return new ApiResponse(false, "没有进行中的考试", null); - } - - List questions = exam.getQuestions(); - if (questionIndex < 0 || questionIndex >= questions.size()) { - return new ApiResponse(false, "无效的题目索引", null); - } - - Question question = questions.get(questionIndex); - - Map data = new HashMap<>(); - data.put("examId", exam.getExamId()); - data.put("totalQuestions", questions.size()); - data.put("currentQuestion", questionIndex); - data.put("question", question.getQuestionText()); - data.put("options", question.getOptions()); - data.put("userAnswer", exam.getUserAnswers().get(questionIndex)); - - return new ApiResponse(true, "获取题目成功", data); - } - - // 提交答案 - public ApiResponse submitAnswer(String sessionId, int questionIndex, int answerIndex) { - String username = validateSession(sessionId); - if (username == null) { - return new ApiResponse(false, "会话无效或已过期", null); - } - - Exam exam = userExams.get(sessionId); - if (exam == null) { - return new ApiResponse(false, "没有进行中的考试", null); - } - - exam.setAnswer(questionIndex, answerIndex); - - Map data = new HashMap<>(); - data.put("currentQuestion", questionIndex); - - return new ApiResponse(true, "答案提交成功", data); - } - - // 完成考试 - public ApiResponse finishExam(String sessionId) { - String username = validateSession(sessionId); - if (username == null) { - return new ApiResponse(false, "会话无效或已过期", null); - } - - Exam exam = userExams.get(sessionId); - if (exam == null) { - return new ApiResponse(false, "没有进行中的考试", null); - } - - double score = exam.calculateScore(); - - // 保存考试记录 - saveExamResult(username, exam, score); - - // 移除当前考试 - userExams.remove(sessionId); - - Map data = new HashMap<>(); - data.put("score", score); - data.put("totalQuestions", exam.getQuestions().size()); - - return new ApiResponse(true, "考试完成", data); - } - - // 保存考试结果 - private void saveExamResult(String username, Exam exam, double score) { - String userDir = baseDirectory + File.separator + username; - File dir = new File(userDir); - if (!dir.exists()) { - dir.mkdir(); - } - - String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); - String filename = userDir + File.separator + timestamp + "_score_" + String.format("%.1f", score) + ".txt"; - - try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) { - writer.println("考试ID: " + exam.getExamId()); - writer.println("考试时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(exam.getStartTime())); - writer.println("得分: " + String.format("%.1f", score) + "分"); - writer.println(); - - List questions = exam.getQuestions(); - List userAnswers = exam.getUserAnswers(); - - for (int i = 0; i < questions.size(); i++) { - Question q = questions.get(i); - writer.println((i + 1) + ". " + q.getQuestionText()); - List options = q.getOptions(); - for (int j = 0; j < options.size(); j++) { - String prefix = (j == q.getCorrectAnswerIndex()) ? "[正确答案] " : - (j == userAnswers.get(i)) ? "[您的答案] " : ""; - writer.println(" " + (char)('A' + j) + ". " + prefix + options.get(j)); - } - writer.println(); - } - } catch (IOException e) { - System.out.println("保存考试结果失败: " + e.getMessage()); - } - } - - // 获取对应的题目生成器 - private QuestionGenerator getQuestionGenerator(String userType) { - System.out.println("🎯 为类型 '" + userType + "' 选择题目生成器"); - switch (userType) { - case "小学": - System.out.println("使用修复后的小学题目生成器 - 支持1-5个操作数"); - return new PrimarySchoolGenerator(); - case "初中": - System.out.println("使用修复后的初中题目生成器"); - return new JuniorHighGenerator(); - case "高中": - System.out.println("使用修复后的高中题目生成器"); - return new SeniorHighGenerator(); - default: - System.out.println("未知用户类型,使用稳定生成器"); - return new StableQuestionGenerator(); - } - } - - // 退出登录 - // 在logout方法中添加更详细的日志 - public ApiResponse logout(String sessionId) { - System.out.println("=== 退出登录处理 ==="); - System.out.println("请求的sessionId: " + sessionId); - System.out.println("当前活跃会话: " + userSessions.keySet()); - - String username = userSessions.remove(sessionId); - userExams.remove(sessionId); - - System.out.println("移除的用户名: " + username); - System.out.println("移除后活跃会话: " + userSessions.keySet()); - - // 即使sessionId无效,也返回成功,确保前端可以继续流程 - if (username != null) { - System.out.println("退出登录成功 - 用户: " + username); - return new ApiResponse(true, "退出成功", null); - } else { - System.out.println("退出登录 - sessionId无效,但返回成功"); - return new ApiResponse(true, "退出成功", null); - } - } - - // 启动HTTP服务器 - public void startServer(int port) throws IOException { - HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); - - // 注册端点 - server.createContext("/api/register", new RegisterHandler()); - server.createContext("/api/login", new LoginHandler()); - server.createContext("/api/change-password", new ChangePasswordHandler()); - server.createContext("/api/generate-exam", new GenerateExamHandler()); - server.createContext("/api/get-question", new GetQuestionHandler()); - server.createContext("/api/submit-answer", new SubmitAnswerHandler()); - server.createContext("/api/finish-exam", new FinishExamHandler()); - server.createContext("/api/logout", new LogoutHandler()); - // 添加新的注册码相关端点 - server.createContext("/api/send-registration-code", new SendRegistrationCodeHandler()); - - server.setExecutor(null); - server.start(); - - System.out.println("数学学习系统服务器已启动,端口: " + port); - } - - // 内部HTTP处理器类 - private abstract class BaseHandler implements HttpHandler { - protected Map parseFormData(String formData) { - Map params = new HashMap<>(); - if (formData != null && !formData.isEmpty()) { - String[] pairs = formData.split("&"); - for (String pair : pairs) { - String[] keyValue = pair.split("="); - if (keyValue.length == 2) { - try { - params.put(keyValue[0], java.net.URLDecoder.decode(keyValue[1], "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - } - } - return params; - } - - protected void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException { - exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8"); - exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*"); - exchange.getResponseHeaders().set("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); - exchange.getResponseHeaders().set("Access-Control-Allow-Headers", "Content-Type"); - - exchange.sendResponseHeaders(statusCode, response.getBytes("UTF-8").length); - OutputStream os = exchange.getResponseBody(); - os.write(response.getBytes("UTF-8")); - os.close(); - } - - protected String toJson(ApiResponse response) { - // 简化的JSON序列化,实际应用中可以使用Jackson等库 - return "{\"success\":" + response.isSuccess() + - ",\"message\":\"" + response.getMessage() + "\"" + - ",\"data\":" + objectToJson(response.getData()) + "}"; - } - - private String objectToJson(Object obj) { - if (obj == null) return "null"; - if (obj instanceof Map) { - Map map = (Map) obj; - StringBuilder sb = new StringBuilder("{"); - boolean first = true; - for (Map.Entry entry : map.entrySet()) { - if (!first) sb.append(","); - sb.append("\"").append(entry.getKey()).append("\":"); - sb.append(objectToJson(entry.getValue())); - first = false; - } - sb.append("}"); - return sb.toString(); - } else if (obj instanceof List) { - List list = (List) obj; - StringBuilder sb = new StringBuilder("["); - boolean first = true; - for (Object item : list) { - if (!first) sb.append(","); - sb.append(objectToJson(item)); - first = false; - } - sb.append("]"); - return sb.toString(); - } else if (obj instanceof String) { - return "\"" + obj.toString().replace("\"", "\\\"") + "\""; - } else { - return obj.toString(); - } - } - } - - private class RegisterHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - Map params = parseFormData(requestBody); - - String email = params.get("email"); - String registrationCode = params.get("registrationCode"); - String username = params.get("username"); - String password = params.get("password"); - String confirmPassword = params.get("confirmPassword"); - String userType = params.get("userType"); - - ApiResponse response = register(email, registrationCode, username, password, confirmPassword, userType); - sendResponse(exchange, 200, toJson(response)); - } - } - - private class LoginHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - Map params = parseFormData(requestBody); - - String username = params.get("username"); - String password = params.get("password"); - - ApiResponse response = login(username, password); - sendResponse(exchange, 200, toJson(response)); - } - } - - //处理器都正确实现 - private class GenerateExamHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - try { - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - Map params = parseFormData(requestBody); - - String sessionId = params.get("sessionId"); - String userType = params.get("userType"); - int questionCount = Integer.parseInt(params.get("questionCount")); - - ApiResponse response = generateExam(sessionId, userType, questionCount); - sendResponse(exchange, 200, toJson(response)); - } catch (Exception e) { - ApiResponse errorResponse = new ApiResponse(false, "生成试卷失败: " + e.getMessage(), null); - sendResponse(exchange, 500, toJson(errorResponse)); - } - } - } - - private class GetQuestionHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - try { - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - Map params = parseFormData(requestBody); - - String sessionId = params.get("sessionId"); - int questionIndex = Integer.parseInt(params.get("questionIndex")); - - ApiResponse response = getQuestion(sessionId, questionIndex); - sendResponse(exchange, 200, toJson(response)); - } catch (Exception e) { - ApiResponse errorResponse = new ApiResponse(false, "获取题目失败: " + e.getMessage(), null); - sendResponse(exchange, 500, toJson(errorResponse)); - } - } - } - - private class SubmitAnswerHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - try { - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - Map params = parseFormData(requestBody); - - String sessionId = params.get("sessionId"); - int questionIndex = Integer.parseInt(params.get("questionIndex")); - int answerIndex = Integer.parseInt(params.get("answerIndex")); - - ApiResponse response = submitAnswer(sessionId, questionIndex, answerIndex); - sendResponse(exchange, 200, toJson(response)); - } catch (Exception e) { - ApiResponse errorResponse = new ApiResponse(false, "提交答案失败: " + e.getMessage(), null); - sendResponse(exchange, 500, toJson(errorResponse)); - } - } - } - - private class FinishExamHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - try { - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - Map params = parseFormData(requestBody); - - String sessionId = params.get("sessionId"); - - ApiResponse response = finishExam(sessionId); - sendResponse(exchange, 200, toJson(response)); - } catch (Exception e) { - ApiResponse errorResponse = new ApiResponse(false, "完成考试失败: " + e.getMessage(), null); - sendResponse(exchange, 500, toJson(errorResponse)); - } - } - } - - private class ChangePasswordHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - try { - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - Map params = parseFormData(requestBody); - - String sessionId = params.get("sessionId"); - String oldPassword = params.get("oldPassword"); - String newPassword = params.get("newPassword"); - String confirmPassword = params.get("confirmPassword"); - - ApiResponse response = changePassword(sessionId, oldPassword, newPassword, confirmPassword); - sendResponse(exchange, 200, toJson(response)); - } catch (Exception e) { - ApiResponse errorResponse = new ApiResponse(false, "修改密码失败: " + e.getMessage(), null); - sendResponse(exchange, 500, toJson(errorResponse)); - } - } - } - - private class LogoutHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - try { - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - Map params = parseFormData(requestBody); - - String sessionId = params.get("sessionId"); - - ApiResponse response = logout(sessionId); - sendResponse(exchange, 200, toJson(response)); - } catch (Exception e) { - ApiResponse errorResponse = new ApiResponse(false, "退出登录失败: " + e.getMessage(), null); - sendResponse(exchange, 500, toJson(errorResponse)); - } - } - } - // 发送注册码的处理器 - private class SendRegistrationCodeHandler extends BaseHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - System.out.println("处理发送注册码请求"); - - if ("OPTIONS".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 200, ""); - return; - } - - if (!"POST".equals(exchange.getRequestMethod())) { - sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); - return; - } - - try { - String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); - System.out.println("请求体: " + requestBody); - - Map params = parseFormData(requestBody); - String email = params.get("email"); - - System.out.println("解析到的邮箱: " + email); - - ApiResponse response = sendRegistrationCode(email); - System.out.println("发送响应: " + toJson(response)); - sendResponse(exchange, 200, toJson(response)); - } catch (Exception e) { - System.err.println("发送注册码时发生错误: " + e.getMessage()); - e.printStackTrace(); - ApiResponse errorResponse = new ApiResponse(false, "获取验证码失败: " + e.getMessage(), null); - sendResponse(exchange, 500, toJson(errorResponse)); - } - } - } - - - public static void main(String[] args) { - try { - Main system = new Main(); - system.startServer(8080); // 启动在8080端口 - } catch (IOException e) { - System.err.println("启动服务器失败: " + e.getMessage()); - } - } -} \ No newline at end of file diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class deleted file mode 100644 index 83e17f3b359761a1129f6a1fd01d4c70f4966b34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5985 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 options = generateOptions(correctAnswerValue, isIntegerAnswer); - String correctAnswerStr = isIntegerAnswer ? - String.valueOf((int)correctAnswerValue) : - String.format("%.2f", correctAnswerValue); - int correctIndex = options.indexOf(correctAnswerStr); - - return new Question(questionText, options, correctIndex); - } - - // 生成考虑优先级的算术题目 - private String generateArithmeticQuestion() { - int operandCount = random.nextInt(3) + 2; // 2-4个操作数 - StringBuilder question = new StringBuilder(); - List tokens = new ArrayList<>(); - - // 生成操作数 - for (int i = 0; i < operandCount; i++) { - if (i > 0) { - // 随机选择运算符,考虑优先级 - String[] availableOps; - if (i == 1 && operandCount > 2) { - // 第一个运算符倾向于用乘除,确保优先级测试 - availableOps = new String[]{"×", "÷", "+", "-"}; - } else { - availableOps = new String[]{"+", "-", "×", "÷"}; - } - String op = availableOps[random.nextInt(availableOps.length)]; - tokens.add(op); - question.append(" ").append(op).append(" "); - } - - // 生成合适的操作数 - int num; - if (tokens.size() > 0 && (tokens.get(tokens.size()-1).equals("÷"))) { - // 除法:生成能整除的数 - num = generateDivisibleNumber(); - } else { - num = random.nextInt(30) + 1; // 1-30 - } - tokens.add(String.valueOf(num)); - question.append(num); - } - question.append(" = ?"); - - return question.toString(); - } - - // 生成能整除的数(用于除法运算) - private int generateDivisibleNumber() { - int[] smallNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - return smallNumbers[random.nextInt(smallNumbers.length)]; - } - - // 计算简单运算(支持负数) - private int calculateSimpleOperation(int a, int b, String op) { - switch (op) { - case "+": return a + b; - case "-": return a - b; - case "×": return a * b; - default: return a + b; - } - } - - // 计算表达式(考虑运算优先级)- 使用自定义解析器避免ScriptEngine问题 - private double evaluateExpression(String expression) { - try { - // 移除空格 - expression = expression.replaceAll(" ", ""); - - // 使用递归下降解析器计算表达式 - return evaluate(expression); - } catch (Exception e) { - System.err.println("计算表达式失败: " + expression + ", 错误: " + e.getMessage()); - return 0; - } - } - - // 递归计算表达式 - private double evaluate(String expr) { - if (expr.isEmpty()) return 0; - - // 处理加减法 - String[] plusMinus = expr.split("(?=[+-])", 2); - if (plusMinus.length > 1) { - double left = evaluate(plusMinus[0]); - double right = evaluate(plusMinus[1].substring(1)); - return plusMinus[1].charAt(0) == '+' ? left + right : left - right; - } - - // 处理乘除法 - String[] multDiv = expr.split("(?=[×÷])", 2); - if (multDiv.length > 1) { - double left = evaluateTerm(multDiv[0]); - double right = evaluateTerm(multDiv[1].substring(1)); - return multDiv[1].charAt(0) == '×' ? left * right : left / right; - } - - // 处理基本项(数字或括号表达式) - return evaluateTerm(expr); - } - - // 计算基本项 - private double evaluateTerm(String term) { - if (term.startsWith("(") && term.endsWith(")")) { - return evaluate(term.substring(1, term.length() - 1)); - } - - // 处理平方符号 - if (term.endsWith("²")) { - double base = evaluateTerm(term.substring(0, term.length() - 1)); - return base * base; - } - - try { - return Double.parseDouble(term); - } catch (NumberFormatException e) { - System.err.println("解析数字失败: " + term); - return 0; - } - } - - private int getPerfectSquare() { - int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; - return perfectSquares[random.nextInt(perfectSquares.length)]; - } - - private List generateOptions(double correctAnswer, boolean isInteger) { - List options = new ArrayList<>(); - - String correctStr = isInteger ? - String.valueOf((int)correctAnswer) : - String.format("%.2f", correctAnswer); - options.add(correctStr); - - Set used = new HashSet<>(); - used.add(correctStr); - - // 生成3个错误选项 - while (options.size() < 4) { - double wrongValue; - String wrongStr; - - do { - // 根据正确答案的大小调整变化范围 - double range = Math.max(5, Math.abs(correctAnswer) * 0.3); - double variation = (random.nextDouble() * range) + 1; - boolean positive = random.nextBoolean(); - - wrongValue = correctAnswer + (positive ? variation : -variation); - - if (isInteger) { - wrongValue = Math.round(wrongValue); - wrongStr = String.valueOf((int)wrongValue); - } else { - wrongValue = Math.round(wrongValue * 100) / 100.0; - wrongStr = String.format("%.2f", wrongValue); - } - } while (used.contains(wrongStr) || Double.isNaN(wrongValue) || Double.isInfinite(wrongValue)); - - options.add(wrongStr); - used.add(wrongStr); - } - - Collections.shuffle(options); - return options; - } -} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class deleted file mode 100644 index bbca5cb70b0d4c3394c1ef20aed1e7e82578c44e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5880 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 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java deleted file mode 100644 index 01a4cec..0000000 --- a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.java +++ /dev/null @@ -1,219 +0,0 @@ -package com.mathlearn.generator; - -import com.mathlearn.model.exam.Question; - -import java.util.*; - -public class PrimarySchoolGenerator implements QuestionGenerator { - private Random random = new Random(); - private String[] operators = {"+", "-", "×", "÷"}; - private int maxAttempts = 100; // 最大尝试次数,避免无限循环 - - @Override - public Question generateQuestion() { - int attempts = 0; - while (attempts < maxAttempts) { - attempts++; - try { - // 生成2-3个操作数,避免太复杂 - int operandCount = random.nextInt(2) + 2; // 2-3个操作数 - StringBuilder question = new StringBuilder(); - List operands = new ArrayList<>(); - List usedOperators = new ArrayList<>(); - - // 生成操作数和运算符,确保表达式合法 - for (int i = 0; i < operandCount; i++) { - if (i > 0) { - String op = operators[random.nextInt(operators.length)]; - question.append(" ").append(op).append(" "); - usedOperators.add(op); - } - // 生成合适的操作数范围 - int num = generateSuitableNumber(i, usedOperators, operands); - question.append(num); - operands.add(num); - } - question.append(" = ?"); - - // 验证表达式合法性 - if (!isExpressionValid(operands, usedOperators)) { - continue; // 重新生成 - } - - // 计算正确答案 - int correctAnswer = calculateAnswerWithPriority(operands, usedOperators); - - // 确保结果不为负数 - if (correctAnswer < 0) { - continue; // 重新生成 - } - - // 生成选项并获取正确答案索引 - List options = generateOptions(correctAnswer); - int correctIndex = options.indexOf(String.valueOf(correctAnswer)); - - System.out.println("✅ 成功生成小学题目: " + question.toString() + " = " + correctAnswer); - return new Question(question.toString(), options, correctIndex); - - } catch (Exception e) { - System.err.println("生成小学题目失败,尝试次数: " + attempts + ", 错误: " + e.getMessage()); - // 继续尝试 - } - } - - // 如果多次尝试都失败,返回一个简单的默认题目 - System.out.println("⚠️ 使用默认小学题目"); - return new Question("2 + 3 = ?", Arrays.asList("5", "6", "4", "7"), 0); - } - - // 生成合适的数字 - private int generateSuitableNumber(int index, List operators, List operands) { - if (index == 0) { - // 第一个操作数 - return random.nextInt(50) + 1; // 1-50 - } - - // 根据前一个运算符决定当前操作数的范围 - String lastOperator = operators.get(operators.size() - 1); - switch (lastOperator) { - case "-": - // 减法:第二个操作数不能太大,避免负数 - int previous = operands.get(operands.size() - 1); - return random.nextInt(Math.min(previous, 20)) + 1; - case "÷": - // 除法:除数要小,且要能整除 - previous = operands.get(operands.size() - 1); - List divisors = findDivisors(previous); - if (!divisors.isEmpty()) { - return divisors.get(random.nextInt(divisors.size())); - } - return random.nextInt(10) + 1; // 备选 - case "×": - // 乘法:避免结果太大 - return random.nextInt(5) + 1; // 1-5 - default: - return random.nextInt(50) + 1; // 1-50 - } - } - - // 找到能整除的数 - private List findDivisors(int number) { - List divisors = new ArrayList<>(); - for (int i = 1; i <= Math.min(number, 10); i++) { - if (number % i == 0) { - divisors.add(i); - } - } - return divisors; - } - - // 验证表达式是否合法 - private boolean isExpressionValid(List operands, List operators) { - try { - // 计算中间结果,验证每一步都合法 - int result = operands.get(0); - for (int i = 0; i < operators.size(); i++) { - String op = operators.get(i); - int next = operands.get(i + 1); - - switch (op) { - case "-": - if (result < next) return false; // 减法结果不能为负 - break; - case "÷": - if (next == 0 || result % next != 0) return false; // 除数不能为0且要能整除 - break; - } - - result = applyOperation(result, op, next); - if (result < 0) return false; // 最终结果不能为负 - } - return true; - } catch (Exception e) { - return false; - } - } - - // 考虑运算优先级的计算 - private int calculateAnswerWithPriority(List operands, List operators) { - if (operands.size() == 1) return operands.get(0); - - // 先处理所有乘除法 - List processed = new ArrayList<>(); - processed.add(operands.get(0)); - - for (int i = 0; i < operators.size(); i++) { - String op = operators.get(i); - int nextOperand = operands.get(i + 1); - - if (op.equals("×") || op.equals("÷")) { - // 执行乘除运算 - int lastIndex = processed.size() - 1; - int lastValue = (Integer) processed.get(lastIndex); - int result = applyOperation(lastValue, op, nextOperand); - processed.set(lastIndex, result); - } else { - // 加减法先保留 - processed.add(op); - processed.add(nextOperand); - } - } - - // 再处理加减法 - int result = (Integer) processed.get(0); - for (int i = 1; i < processed.size(); i += 2) { - String op = (String) processed.get(i); - int nextOperand = (Integer) processed.get(i + 1); - result = applyOperation(result, op, nextOperand); - } - - return result; - } - - // 执行单个运算 - private int applyOperation(int a, String operator, int b) { - switch (operator) { - case "+": return a + b; - case "-": return a - b; // 前面已经验证不会为负 - case "×": return a * b; - case "÷": return a / b; // 前面已经验证能整除 - default: return a; - } - } - - private List generateOptions(int correctAnswer) { - List options = new ArrayList<>(); - options.add(String.valueOf(correctAnswer)); - - Set used = new HashSet<>(); - used.add(correctAnswer); - - // 生成3个错误选项 - while (options.size() < 4) { - int variation = random.nextInt(10) + 1; - boolean add = random.nextBoolean(); - int wrongAnswer = add ? correctAnswer + variation : Math.max(0, correctAnswer - variation); - - if (!used.contains(wrongAnswer) && wrongAnswer != correctAnswer) { - options.add(String.valueOf(wrongAnswer)); - used.add(wrongAnswer); - } - - // 防止无限循环 - if (options.size() < 4 && used.size() > 10) { - // 强制添加一些选项 - for (int i = 1; i <= 3; i++) { - int forcedOption = correctAnswer + i * 2; - if (!used.contains(forcedOption)) { - options.add(String.valueOf(forcedOption)); - used.add(forcedOption); - if (options.size() >= 4) break; - } - } - } - } - - Collections.shuffle(options); - return options; - } -} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class deleted file mode 100644 index 2bfb7d72953038e7a332fe74d3cf7ade377a5fcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206 zcmX^0Z`VEs1_nn4PId++Mh4B~{9OIq#FC7h)Wo7Z{q)ql)S|?a{389p($wOT%=|oe zmR%&tyPzb6g6{drcK~+Q32i4r%{FKxj{nU!YT)4s3 zj0{}C`K3k4scxA$sf-L_F#T{F^+1-fF)}bRFaur8z`zJ}04oC zL$X#M<&Z_rg6&`p4nunq%-uN;r@r7?xt>r$^DxlvP$(Jbp7f^YpWMOeIVIt&bQ|o#38&3Vo@>AexVb zzUE_}7<(8*dLqtbe5wBNyH+gDkR1pU_5u@Hs4_JFVUNMNP-MU3b7O>|RsQsgeX^6F zwZ}p0BSh?tkWr+uLAgYyLnM)kYmH~HMso?PQCnjDY1Oz%SXz}wgg40H7J1y!lP#(w Tu#NI6SFl6brjc1xunYSGAUbwI diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class deleted file mode 100644 index 4967054c76996721a92c3d694eb00a1d42016ae7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10033 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 diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java deleted file mode 100644 index 97113ff..0000000 --- a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.java +++ /dev/null @@ -1,425 +0,0 @@ -package com.mathlearn.generator; - -import com.mathlearn.model.exam.Question; - -import java.util.*; - -public class SeniorHighGenerator implements QuestionGenerator { - private Random random = new Random(); - - @Override - public Question generateQuestion() { - int type = random.nextInt(6); // 六种题型 - String questionText = ""; - double correctAnswerValue = 0; - boolean isIntegerAnswer = true; - - switch (type) { - case 0: // 三角函数(特殊角,包括负角) - String[] trigFunctions = {"sin", "cos", "tan"}; - String func = trigFunctions[random.nextInt(trigFunctions.length)]; - int angle = getSpecialAngle(); - questionText = func + "(" + angle + "°) = ?"; - correctAnswerValue = calculateTrigValue(func, angle); - isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); - break; - - case 1: // 平方根(包括非完全平方数的近似值) - if (random.nextBoolean()) { - // 完全平方数 - int square = getPerfectSquare(); - questionText = "√" + square + " = ?"; - correctAnswerValue = Math.sqrt(square); - } else { - // 非完全平方数的近似值 - int num = getNonPerfectSquare(); - questionText = "√" + num + " ≈ ?"; - correctAnswerValue = Math.sqrt(num); - isIntegerAnswer = false; - } - break; - - case 2: // 对数运算 - questionText = generateLogQuestion(); - correctAnswerValue = evaluateLogQuestion(questionText); - isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); - break; - - case 3: // 复合表达式(考虑优先级) - ExpressionResult exprResult = generateCompositeExpression(); - questionText = exprResult.expression; - correctAnswerValue = exprResult.value; - isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); - break; - - case 4: // 二次方程 - int root = random.nextInt(15) - 7; // -7到7的根 - int a = 1; - int b = -2 * root; - int c = root * root; - questionText = String.format("方程 %dx² %s %dx %s %d = 0 的一个根是?", - a, b >= 0 ? "+" : "", b, c >= 0 ? "+" : "", c); - correctAnswerValue = root; - break; - - case 5: // 带指数的复合运算 - questionText = generateExponentialExpression(); - correctAnswerValue = evaluateExponentialExpression(questionText.replace(" = ?", "")); - isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); - break; - } - - List options = generateOptions(correctAnswerValue, isIntegerAnswer); - String correctAnswerStr = isIntegerAnswer ? - String.valueOf((int)correctAnswerValue) : - String.format("%.2f", correctAnswerValue); - int correctIndex = options.indexOf(correctAnswerStr); - - return new Question(questionText, options, correctIndex); - } - - // 表达式和结果封装类 - private static class ExpressionResult { - String expression; - double value; - - ExpressionResult(String expression, double value) { - this.expression = expression; - this.value = value; - } - } - - // 生成复合表达式并同时计算结果 - private ExpressionResult generateCompositeExpression() { - // 使用预定义的简单表达式模板,确保可计算 - String[][] templates = { - {"%d + %d × %d", "先乘后加"}, - {"%d × %d + %d", "先乘后加"}, - {"%d - %d × %d", "先乘后减"}, - {"%d × %d - %d", "先乘后减"}, - {"%d + %d ÷ %d", "先除后加"}, - {"%d ÷ %d + %d", "先除后加"}, - {"%d² + %d", "先平方后加"}, - {"%d² - %d", "先平方后减"}, - {"%d × (%d + %d)", "先加后乘"}, - {"(%d + %d) × %d", "先加后乘"} - }; - - String[] template = templates[random.nextInt(templates.length)]; - String pattern = template[0]; - String description = template[1]; - - // 生成合适的数字,确保计算有效 - int a, b, c=1; - double result = 0; - - // 根据模板类型生成合适的数字 - if (pattern.contains("÷")) { - // 除法模板:确保除数不为0且能整除 - a = random.nextInt(10) + 1; - b = random.nextInt(10) + 1; - c = random.nextInt(10) + 1; - - // 调整数字确保除法有效 - if (pattern.startsWith("%d ÷")) { - // 第一个操作数是除法:确保b能整除a - a = b * (random.nextInt(5) + 1); // a是b的倍数 - } else if (pattern.contains("÷ %d")) { - // 其他位置的除法:确保除数不为0 - b = random.nextInt(9) + 1; // 1-9 - } - } else if (pattern.contains("²")) { - // 平方模板 - a = random.nextInt(10) + 1; // 1-10 - b = random.nextInt(20) + 1; // 1-20 - result = a * a + (pattern.contains("+") ? b : -b); - } else if (pattern.contains("(")) { - // 括号模板 - a = random.nextInt(10) + 1; - b = random.nextInt(10) + 1; - c = random.nextInt(10) + 1; - result = pattern.contains("× (") ? a * (b + c) : (a + b) * c; - } else { - // 基本四则运算 - a = random.nextInt(10) + 1; - b = random.nextInt(10) + 1; - c = random.nextInt(10) + 1; - - // 根据运算符计算结果 - if (pattern.contains("+ %d ×")) { - result = a + b * c; // a + b × c - } else if (pattern.contains("× %d +")) { - result = a * b + c; // a × b + c - } else if (pattern.contains("- %d ×")) { - result = a - b * c; // a - b × c - } else if (pattern.contains("× %d -")) { - result = a * b - c; // a × b - c - } else if (pattern.contains("+ %d ÷")) { - result = a + (double)b / c; // a + b ÷ c - } else if (pattern.contains("÷ %d +")) { - result = (double)a / b + c; // a ÷ b + c - } - } - - // 如果还没有计算结果,使用安全的表达式计算 - if (result == 0) { - result = safeEvaluateExpression(pattern, a, b, c); - } - - String expression = String.format(pattern, a, b, c) + " = ?"; - System.out.println("生成表达式: " + expression + " [规则: " + description + "] = " + result); - - return new ExpressionResult(expression, result); - } - - // 安全的表达式计算 - private double safeEvaluateExpression(String pattern, int a, int b, int c) { - try { - if (pattern.equals("%d + %d × %d")) { - return a + b * c; - } else if (pattern.equals("%d × %d + %d")) { - return a * b + c; - } else if (pattern.equals("%d - %d × %d")) { - return a - b * c; - } else if (pattern.equals("%d × %d - %d")) { - return a * b - c; - } else if (pattern.equals("%d + %d ÷ %d")) { - return a + (double)b / c; - } else if (pattern.equals("%d ÷ %d + %d")) { - return (double)a / b + c; - } else if (pattern.equals("%d² + %d")) { - return a * a + b; - } else if (pattern.equals("%d² - %d")) { - return a * a - b; - } else if (pattern.equals("%d × (%d + %d)")) { - return a * (b + c); - } else if (pattern.equals("(%d + %d) × %d")) { - return (a + b) * c; - } - } catch (Exception e) { - System.err.println("计算表达式失败: " + String.format(pattern, a, b, c) + ", 错误: " + e.getMessage()); - } - return 0; - } - - // 获取特殊角度(包括负角) - private int getSpecialAngle() { - int[] angles = {-360, -270, -180, -135, -120, -90, -60, -45, -30, 0, - 30, 45, 60, 90, 120, 135, 180, 270, 360}; - return angles[random.nextInt(angles.length)]; - } - - // 获取非完全平方数 - private int getNonPerfectSquare() { - int[] nonSquares = {2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20}; - return nonSquares[random.nextInt(nonSquares.length)]; - } - - // 生成对数题目 - private String generateLogQuestion() { - if (random.nextBoolean()) { - // 简单对数:log₁₀ - int value = (int)Math.pow(10, random.nextInt(4)); // 1, 10, 100, 1000 - return "log₁₀" + value + " = ?"; - } else { - // 以2为底的对数 - int value = (int)Math.pow(2, random.nextInt(6) + 1); // 2,4,8,16,32,64 - return "log₂" + value + " = ?"; - } - } - - // 计算对数题目 - private double evaluateLogQuestion(String question) { - if (question.startsWith("log₁₀")) { - int value = Integer.parseInt(question.replace("log₁₀", "").replace(" = ?", "")); - return Math.log10(value); - } else if (question.startsWith("log₂")) { - int value = Integer.parseInt(question.replace("log₂", "").replace(" = ?", "")); - return Math.log(value) / Math.log(2); - } - return 0; - } - - // 生成指数表达式 - private String generateExponentialExpression() { - int base = random.nextInt(5) + 2; // 2-6 - int exponent = random.nextInt(4) + 2; // 2-5 - return base + "^" + exponent + " = ?"; - } - - // 计算指数表达式 - private double evaluateExponentialExpression(String expr) { - String cleanExpr = expr.replace(" = ?", ""); - String[] parts = cleanExpr.split("\\^"); - int base = Integer.parseInt(parts[0]); - int exponent = Integer.parseInt(parts[1]); - return Math.pow(base, exponent); - } - - private double calculateTrigValue(String function, int angle) { - // 规范化角度到0-360度 - angle = angle % 360; - if (angle < 0) angle += 360; - - // 特殊角的精确值 - switch (angle) { - case 0: - if (function.equals("sin")) return 0; - if (function.equals("cos")) return 1; - if (function.equals("tan")) return 0; - break; - case 30: - if (function.equals("sin")) return 0.5; - if (function.equals("cos")) return Math.sqrt(3)/2; - if (function.equals("tan")) return 1/Math.sqrt(3); - break; - case 45: - double sqrt2 = Math.sqrt(2); - if (function.equals("sin")) return sqrt2/2; - if (function.equals("cos")) return sqrt2/2; - if (function.equals("tan")) return 1; - break; - case 60: - if (function.equals("sin")) return Math.sqrt(3)/2; - if (function.equals("cos")) return 0.5; - if (function.equals("tan")) return Math.sqrt(3); - break; - case 90: - if (function.equals("sin")) return 1; - if (function.equals("cos")) return 0; - if (function.equals("tan")) return Double.POSITIVE_INFINITY; - break; - case 120: - if (function.equals("sin")) return Math.sqrt(3)/2; - if (function.equals("cos")) return -0.5; - if (function.equals("tan")) return -Math.sqrt(3); - break; - case 135: - double sqrt22 = Math.sqrt(2)/2; - if (function.equals("sin")) return sqrt22; - if (function.equals("cos")) return -sqrt22; - if (function.equals("tan")) return -1; - break; - case 150: - if (function.equals("sin")) return 0.5; - if (function.equals("cos")) return -Math.sqrt(3)/2; - if (function.equals("tan")) return -1/Math.sqrt(3); - break; - case 180: - if (function.equals("sin")) return 0; - if (function.equals("cos")) return -1; - if (function.equals("tan")) return 0; - break; - case 270: - if (function.equals("sin")) return -1; - if (function.equals("cos")) return 0; - if (function.equals("tan")) return Double.NEGATIVE_INFINITY; - break; - } - - // 对于非特殊角,使用近似计算 - double rad = Math.toRadians(angle); - switch (function) { - case "sin": - return Math.round(Math.sin(rad) * 100) / 100.0; - case "cos": - return Math.round(Math.cos(rad) * 100) / 100.0; - case "tan": - if (angle % 180 == 90) { - return angle % 360 == 90 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; - } - double result = Math.tan(rad); - return Math.round(result * 100) / 100.0; - default: - return 0; - } - } - - private int getPerfectSquare() { - int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; - return perfectSquares[random.nextInt(perfectSquares.length)]; - } - - private List generateOptions(double correctAnswer, boolean isInteger) { - List options = new ArrayList<>(); - - String correctStr; - if (Double.isInfinite(correctAnswer)) { - correctStr = correctAnswer > 0 ? "∞" : "-∞"; - } else if (Double.isNaN(correctAnswer)) { - correctStr = "无解"; - } else { - correctStr = isInteger ? - String.valueOf((int)correctAnswer) : - String.format("%.2f", correctAnswer); - } - options.add(correctStr); - - Set used = new HashSet<>(); - used.add(correctStr); - - // 生成3个错误选项 - int attempts = 0; - while (options.size() < 4 && attempts < 50) { - attempts++; - double wrongValue; - String wrongStr; - - // 根据正确答案调整变化范围 - double baseRange; - if (Double.isInfinite(correctAnswer) || Double.isNaN(correctAnswer)) { - baseRange = 5; - } else { - baseRange = Math.max(2, Math.abs(correctAnswer) * 0.3); - } - - double variation = (random.nextDouble() * baseRange) + 1; - boolean positive = random.nextBoolean(); - - if (Double.isInfinite(correctAnswer)) { - wrongValue = random.nextDouble() * 10 - 5; // -5到5的随机数 - } else if (Double.isNaN(correctAnswer)) { - wrongValue = random.nextDouble() * 10; // 0到10的随机数 - } else { - wrongValue = correctAnswer + (positive ? variation : -variation); - } - - if (Double.isInfinite(wrongValue)) { - wrongStr = wrongValue > 0 ? "∞" : "-∞"; - } else if (Double.isNaN(wrongValue)) { - wrongStr = "无解"; - } else if (isInteger) { - wrongValue = Math.round(wrongValue); - wrongStr = String.valueOf((int)wrongValue); - } else { - wrongValue = Math.round(wrongValue * 100) / 100.0; - wrongStr = String.format("%.2f", wrongValue); - } - - if (!used.contains(wrongStr)) { - options.add(wrongStr); - used.add(wrongStr); - } - } - - // 如果选项不够,添加一些固定选项 - while (options.size() < 4) { - String extraOption; - if (isInteger) { - int extraValue = (int)correctAnswer + options.size() * 2 + 1; - extraOption = String.valueOf(extraValue); - } else { - double extraValue = correctAnswer + options.size() * 0.5 + 0.1; - extraOption = String.format("%.2f", extraValue); - } - - if (!used.contains(extraOption)) { - options.add(extraOption); - used.add(extraOption); - } - } - - Collections.shuffle(options); - return options; - } -} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class deleted file mode 100644 index 77c835a92fa785434db6a6547504560a530cc812..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3453 zcmaJ@TXa-c8UFU%&Y6<~2?GO8lj4waNhX&mP{xuWR7eX%5~l4?=z!H6l9Oa$=1iD5 zL!n-Jv9+~WdsU#VP|=#&LZt{HgcjGb%e7p-)dyWZxRy&r>;o@8d8x*4pOZ-@5-qP8{r-RNU;caIDu7Lx(BOerflr4Y0fD;x#vvn~GpwO_YTtgd-xdgL$XZ!@qky-m zd6xpULR7Z1x%mBtHBiWFP~Z)s2D*ZII_9HRAl_fd$Mc3goHLE06(2G!vuN0bVmxgd z`*P-eWwT^w3)a@kJ_QvWW&)ueM~f-}Ny&VHjt~|K)E=BV+f^uAwpkPq-9d!0Siuq< zpF*Ufp<_n+NXa(y)V@%rF=3Z=wh+I!n6>P*T{Mk+GDKh0>uA8O0!#A70kf-M^&9r? ztUb(G$u=yz#IsG^&F*oRu}uy`Ne!PyRKYSGjkrx)D@{#vIafzQy<=E1U&b1bS-#*KHfc~1xe>!mk31Qs`S&u#PubSl`W<1TzwVEznh zdKqy_%o~RV{PHj*Z@^|9U6Rn7&srfOZhZ(|tk)RStva@$n|_%Bi0Q&3H6p=56&FrB z-GM_-wq!G0K5Ul?_6V$;%b!(NF~TxR3U&xAn+?f4os)~3hmCx^f<_I!xL2maeRFem z8P90aEi)oriMj)edk*)Tj`9+c59rt>@#r;+MGg1kK^+veDjpIDu8y`uS4TUecd7UyqrFCj!C|e6ehzo2APcch!w`lQWOeMvfeK(8MK=|T z#u0ilV3efy1XeWdt#VK$?Eh_=0w#@%<{37UfrcEs5>6vJ4$6#C4jH+!nHsD?3ATc= zjzbbv#b#5~ni)x(c}*E2N84r8Ha~9LzBm3#Sk{ZFy3Hc zO2MntwHgW2sq#9D$zJAUFr6K;47*&U+*Q+_pSEj56^f?LZloA3T__j(%`I7}ZiAc7 z6=kO_Y?p4NHT1t-vWvz@uW1h#21+WvFVGl`MsK|F!Ho-}(d)0A`tvg{Tt9OrDxx1h z{_@ACk6(Z7-S+l&6>m~M!OReDW{f(^w#xEH)I&r+JXTr1LsiK253fHJb$Pgq$@|)~ zr#hlS#aV&&DY@t0oJI7PpFVy4t)qV$KYQ)@7kTX3`%hdOALp6c0Di3D9NtrKURI-@ z2rPHd;b1mv9V#3!dE3eQ*us|34{f zkZTu~vGRL(&Ai0kBi{=EN8aunz1-(pg#9aAt#j5uICcplb_Gi25`q_@#k?0$_Z|rZ zzRi9<$-w0HK_#;wcfW&UE(?#r{TdP;jb$#N&ez9-=dmcp`2=nO#;}xgt!~j6miziP zRLwgBAD}7Y4aL$KU#K;m@rT;eJK7{c+f@>;>F`B-9f~KRMwBt!{tgvDicMplJ5FGwH=&Lq%5|%=UhI?WIUY57jq}Bbf-wVN*g22gBL~?v?~{Iv`0p9J9146Ww{I$xvT&-F>q z?Mr6@p@H-`2Axw3O+@Sz5AaU(H~}m&fq;3?7|IBdu!2}vjm6Y$327Se3oOM)d}{p~ zQT!IS;rCdM>!kWCA5DM9Dtv+%lek4JLaVryucAh@ixs$Cv}3hci*+K&qP`7xQeubL zg`_aiiQ|-bH?&EX{U9MCgn|3Wqkfr#ve#! z0%|Iw)G4WqTBoHteBOjV><^sAvDV9Yf|u=SJQwkW{Sn{Qk@iGDhII^2C6uso0$P1I z&^HQ&!+-?PNwl_wRY%e{Ja`pLTjgp>mC7Hf!zk9)hyA`j|8QSIt^9C~)c>y|Px{5^ zWOiDoj(T^h4)^)`68^TZe?}~Ma5XK~{o{z8{8{TbzS(+?ad1&E=zx4PlemlV--3E< zWqi9i+s=nm4+i)?%QMLyrO#hN8Yi(6XR#ZX@F0FpijS}dza#A*(T5u_@K5X$LB5m1 z7!b=aD3)VbG$HFmJ_dD?tOGK%3RvqNQ}7zY{x3eJMVI)5!`~492mGBLeAm(NBvbp8 qGkXKyRlrFwA25<>3`_-Z#n(jPJad$NUM?VBK5qC$bSH6Y+p(M diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java deleted file mode 100644 index ace3ab1..0000000 --- a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.mathlearn.generator; -//稳定生成器 -import com.mathlearn.model.exam.Question; - -import java.util.*; - -public class StableQuestionGenerator implements QuestionGenerator { - private Random random = new Random(); - private int questionCounter = 0; - - @Override - public Question generateQuestion() { - questionCounter++; - System.out.println(" 🔧 生成第 " + questionCounter + " 道题目..."); - - try { - // 极度简化的题目生成,确保不会卡住 - int a = random.nextInt(20) + 1; - int b = random.nextInt(20) + 1; - - // 随机选择运算符 - String[] operators = {"+", "-", "×"}; - String operator = operators[random.nextInt(operators.length)]; - - String questionText; - int correctAnswer; - - switch (operator) { - case "+": - questionText = a + " + " + b + " = ?"; - correctAnswer = a + b; - break; - case "-": - // 确保减法结果不为负数 - int larger = Math.max(a, b); - int smaller = Math.min(a, b); - questionText = larger + " - " + smaller + " = ?"; - correctAnswer = larger - smaller; - break; - case "×": - // 简化乘法,避免过大数字 - a = random.nextInt(10) + 1; - b = random.nextInt(10) + 1; - questionText = a + " × " + b + " = ?"; - correctAnswer = a * b; - break; - default: - questionText = a + " + " + b + " = ?"; - correctAnswer = a + b; - } - - // 生成稳定的选项 - List options = generateStableOptions(correctAnswer); - - System.out.println(" ✅ 题目生成成功: " + questionText); - return new Question(questionText, options, 0); // 第一个选项是正确答案 - - } catch (Exception e) { - System.err.println(" 💥 题目生成过程中发生异常: " + e.getMessage()); - // 返回一个默认题目,确保不卡住 - return new Question("1 + 1 = ?", Arrays.asList("2", "3", "4", "5"), 0); - } - } - - private List generateStableOptions(int correctAnswer) { - List options = new ArrayList<>(); - options.add(String.valueOf(correctAnswer)); - - // 生成3个稳定的错误选项 - Set used = new HashSet<>(); - used.add(correctAnswer); - - int[] variations = {1, 2, 3, 5, 7, 10}; // 固定的变化量 - - for (int i = 0; i < 3 && options.size() < 4; i++) { - int variation = variations[i % variations.length]; - boolean addVariation = random.nextBoolean(); - - int wrongAnswer = addVariation ? correctAnswer + variation : correctAnswer - variation; - - // 确保不为负数且不重复 - if (wrongAnswer > 0 && !used.contains(wrongAnswer)) { - options.add(String.valueOf(wrongAnswer)); - used.add(wrongAnswer); - } else { - // 如果生成失败,使用备选方案 - wrongAnswer = correctAnswer + (i + 1) * 2; - if (!used.contains(wrongAnswer)) { - options.add(String.valueOf(wrongAnswer)); - used.add(wrongAnswer); - } - } - } - - // 如果选项还不够,用固定值补全 - while (options.size() < 4) { - int filler = correctAnswer + options.size() * 5 + 1; - if (!used.contains(filler)) { - options.add(String.valueOf(filler)); - used.add(filler); - } - } - - Collections.shuffle(options); - return options; - } -} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class deleted file mode 100644 index 649edee4601be6aaecd8da31c12a1cc46d167f02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 637 zcmZXR%TB^j5QhH)g-Wg5z2Y@)pi%n(8WW>&)Dl_i=X`v=y#qMGwt)naIy4h0qy_SA`5^6%3|#xV)mBas3VYokR04W9a2yqe0-_lU zWKHCdXWeH}x+IDhe{<_m-wWKs7%ZA7p)8=?$w*F9-|h|ts@3NI=84J}tTiZeN`C^m z3olSt1HYyEx3bk?CF6zlAB)_wDPXuNy8LlhuGS_5$Np%a%-P7;H1KQ9sCNf_N1c1| zjQqrr9K_pVhZ`n%3rR+vCf^eAxr{Q`X4W8hEsKmx{5s-)jk#>SLRgg{bZc*j1#5qZ z!ZYgv%Zy9x0F^al_!!7iyF_(?6|9bxHkbvel=TAr@wYWSDrOniP+^RRPNEA>GiZ*` S`Usgt3$tjR=qB3}*!lvsuy*eN diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java deleted file mode 100644 index 97e218a..0000000 --- a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.mathlearn.model.api; - -public class ApiResponse { - private boolean success; - private String message; - private Object data; - - public ApiResponse(boolean success, String message, Object data) { - this.success = success; - this.message = message; - this.data = data; - } - - public boolean isSuccess() { return success; } - public String getMessage() { return message; } - public Object getData() { return data; } -} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class deleted file mode 100644 index fa6df17e059f8094551bf8df2214194994bb812d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2001 zcma)7ZBrXn6n<_3EQIBqP$eLsr6i#?we|%~z)~m@h0+=tq`of67Pn0{b$3&#pF7hp z{sX^s{G#8~83EB5$ItyA{)x_Lea^ChK!y zq@x)v3f*^%`$no{*qf=9jXP$+Q)tOpw&l$zgyV^P8(Pt(A)=!ly25awQcjf(?~9UY zICiRBDVn8}xn-17SGg#(eOWbK&#KriO)vSjtDaR#Em^LY*3hZYcX&AKIK~6HiJ${v z@zkTESKPE$UDKJh-LFi?)zGidd5D@fJTrp6eZUDFFX3hSbv?uJR;{vm)UPPhZ%kp( zx8RvuUMgpm@0CosTBtZorWM2V@PNPN$fjo>Wa&~Q%2n>eq~<0tFKo3%Z2({vQH`$nm1uH04_h-d4g3N+HbWKZnTTiWqOU179tmH@ISTx-ZF1J8 zZFp6OG+x+`_n=)fOaJRDJ(E@#Z@@K>@9Xu|w}w9ti9BmK#}QKKTC!~OTD81kI;+M; zi6B4}T!o{0F9XLRLsYtjkDjACeq2@Te2h;5)%VD|Fh3Ui79%ksFCem4 z_OT(K$+yB-JLIs_2aJ-rF^uvd7p}rkqqO)bJ`3!A6I661oMCl@n80pI><;Z=I)p!Q zb_cU^SCi*=u<#fy50&x@_aye{0QsoWkL=wa=_};3J4k+|o+182=wVBpM}lwg1g3G? VkEk8tztN=Bxu@(ih0lGU@h_~W##{gZ diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java deleted file mode 100644 index ce3c1cd..0000000 --- a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.mathlearn.model.exam; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -public class Exam { - private List questions; - private List userAnswers; - private Date startTime; - private String examId; - - public Exam(List questions) { - this.questions = questions; - this.userAnswers = new ArrayList<>(); - this.startTime = new Date(); - this.examId = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); - - // 初始化用户答案列表 - for (int i = 0; i < questions.size(); i++) { - userAnswers.add(-1); // -1表示未作答 - } - } - - public List getQuestions() { return questions; } - public List getUserAnswers() { return userAnswers; } - public Date getStartTime() { return startTime; } - public String getExamId() { return examId; } - - public void setAnswer(int questionIndex, int answerIndex) { - if (questionIndex >= 0 && questionIndex < userAnswers.size()) { - userAnswers.set(questionIndex, answerIndex); - } - } - - public double calculateScore() { - int correctCount = 0; - for (int i = 0; i < questions.size(); i++) { - if (userAnswers.get(i) == questions.get(i).getCorrectAnswerIndex()) { - correctCount++; - } - } - return (double) correctCount / questions.size() * 100; - } -} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class deleted file mode 100644 index 8942b24d1523223070cc269dfa50194f22c7ad42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 842 zcmaiyU279T6o%i)*P87nX=1FOQL9CgwRG=ID3pQ_2o_1{{U#mal-*g~%xZp=7YYr6 z7ySYLDDmB7VupR8c5!fF`p%?n*Lm>TFdtr1b15eKU(0iZAsZo&@a6V=3 zxttN#7~GZ^npo*cH-%Om)UYdHMIY0&DO*_z6Qcrepr&RaYdE-zCMn}6j@jOco_>*W zUth|ZfanX9hiamIlf+WsV2#k*EPdP+c-7vFuVr@ooeP1&Dc>hh8z?Q`CE-ZM=l&>Q zL<_zs& zl*D8CR;6#Nta>|2_lAA$D#x#r=gBWXFPAP3WG?(Y-nk+A1;&cF&-(-3db9=FruzfJ zeLaWe9?ns5TXWREGcNFu=N>Zvo5~%ONw1 options; - private int correctAnswerIndex; - - public Question(String questionText, List options, int correctAnswerIndex) { - this.questionText = questionText; - this.options = options; - this.correctAnswerIndex = correctAnswerIndex; - } - - public String getQuestionText() { return questionText; } - public List getOptions() { return options; } - public int getCorrectAnswerIndex() { return correctAnswerIndex; } -} diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class deleted file mode 100644 index d02c2fae41688ff0102fee2e1b72d4ebdf28465e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1426 zcmbV~TTc^F6ouF6oic?&TS~bUxwpe*cr~I4G58`8BgzABLpiBK+9{b%HU1|bG_f)9 z!5`p{GOj&SEe;byOp|lY?5_QtwfEUSet!E7;0OnKB#_J^Wgv}=Lh;&uXImZHZCj_8 z*Sh5^WDXtI@t-Ip8_n|xy%-oPXbg^gCPYjth^ZAaUlYjt~9x?>Ic+OytpIcl|f z1DA-Lgj~C;6=qMyH=OyNiRfE+O1F`;5IU>+i?0}Fl;{O;)02N?T;~)80%s*N8qu%4v$P29rI_sf!ET{9O+^4 z*68fZuwa!hnc%o)xN_`xO31VXI|n4#`S8Kc=MHwx2zLXV1}t-}^Xr&-Deg7%E0no2 zMAqCLqG0X~Q8ZISls@xMg%z#~yiC$lC}09p{7s{TBIYp@ARmm7r$nZyT!};0$gD=d zbz~_o5nLv?Lhu~FsvO*TdaMQT)e-!V@Fdmc-|(vVT`-e>S)B_EERwiH;xdVK5?9Dr z`&0SjQRS6?R~@3(2wX=V8?1SgHn)gc=U3Q7X{Ms7wD|?uPdtPT%LKs&*UeaIAu4TB zx)m!eMx`dD+p*GxsC0+Y281mSe%ov5W5nw&MJ6Ocq;+;Em@(;4VLS+7UHeq+#yY4* U9axm^#bc{c>;bj=ygUKx7uQVtbpQYW diff --git a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java b/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java deleted file mode 100644 index 0760366..0000000 --- a/pair-programming/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.mathlearn.model.user; - -// 用户账户类 -public class UserAccount { - private String username; - private String password; - private String userType; - private String email; // 添加邮箱字段 - private String registrationCode; - private boolean registered; - - public UserAccount(String username, String password, String userType) { - this.username = username; - this.password = password; - this.userType = userType; - this.registered = true; - } - - public UserAccount(String username, String password, String userType, String email) { - this.username = username; - this.password = password; - this.userType = userType; - this.email = email; - this.registered = true; - } - - public UserAccount(String email, String registrationCode) { - this.email = email; - this.registrationCode = registrationCode; - this.registered = false; - } - - public void completeRegistration(String username, String password, String userType) { - this.username = username; - this.password = password; - this.userType = userType; - this.registered = true; - } - - public String getUsername() { return username; } - public String getPassword() { return password; } - public String getUserType() { return userType; } - public String getRegistrationCode() { return registrationCode; } - public boolean isRegistered() { return registered; } - - public void setPassword(String password) { this.password = password; } - public String getEmail() { return email; } - public void setEmail(String email) { this.email = email; } -} -- 2.34.1 From a8eef1a637f797bd3cc66c6a6b76544dca0d6190 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 19:35:11 +0800 Subject: [PATCH 16/30] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=BB=E7=95=8C?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/style/main.css | 389 ++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 src/electron-frontend/resources/style/main.css diff --git a/src/electron-frontend/resources/style/main.css b/src/electron-frontend/resources/style/main.css new file mode 100644 index 0000000..35e99e9 --- /dev/null +++ b/src/electron-frontend/resources/style/main.css @@ -0,0 +1,389 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + --primary-color: #4f46e5; + --primary-dark: #4338ca; + --success-color: #10b981; + --warning-color: #f59e0b; + --danger-color: #ef4444; + --info-color: #3b82f6; + --light-bg: #f8fafc; + --dark-text: #1e293b; + --light-text: #64748b; + --border-color: #e2e8f0; + --shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); + --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + padding: 20px; + line-height: 1.6; + color: var(--dark-text); +} + +/* 容器样式 */ +.container { + max-width: 1200px; + margin: 0 auto; +} + +/* 卡片样式 */ +.card { + background: white; + border-radius: 16px; + box-shadow: var(--shadow); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.card-header { + padding: 24px; + border-bottom: 1px solid var(--border-color); +} + +.card-body { + padding: 24px; +} + +/* 按钮样式 */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 12px 24px; + border: none; + border-radius: 12px; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + text-decoration: none; + position: relative; + overflow: hidden; +} + +.btn::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); + transition: left 0.5s; +} + +.btn:hover::before { + left: 100%; +} + +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--primary-dark)); + color: white; + box-shadow: 0 4px 14px 0 rgba(79, 70, 229, 0.4); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px 0 rgba(79, 70, 229, 0.5); +} + +.btn-success { + background: linear-gradient(135deg, var(--success-color), #059669); + color: white; + box-shadow: 0 4px 14px 0 rgba(16, 185, 129, 0.4); +} + +.btn-success:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px 0 rgba(16, 185, 129, 0.5); +} + +.btn-warning { + background: linear-gradient(135deg, var(--warning-color), #d97706); + color: white; + box-shadow: 0 4px 14px 0 rgba(245, 158, 11, 0.4); +} + +.btn-warning:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px 0 rgba(245, 158, 11, 0.5); +} + +.btn-danger { + background: linear-gradient(135deg, var(--danger-color), #dc2626); + color: white; + box-shadow: 0 4px 14px 0 rgba(239, 68, 68, 0.4); +} + +.btn-danger:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px 0 rgba(239, 68, 68, 0.5); +} + +.btn-secondary { + background: #64748b; + color: white; +} + +.btn-secondary:hover { + background: #475569; + transform: translateY(-1px); +} + +/* 输入框样式 */ +.form-group { + margin-bottom: 20px; +} + +.form-label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: var(--dark-text); +} + +.form-control { + width: 100%; + padding: 14px 16px; + border: 2px solid var(--border-color); + border-radius: 12px; + font-size: 16px; + transition: all 0.3s ease; + background: white; + color: var(--dark-text); +} + +.form-control:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); + transform: translateY(-1px); +} + +/* 消息样式 */ +.message { + padding: 16px; + margin-top: 20px; + border-radius: 12px; + text-align: center; + font-weight: 500; + animation: slideIn 0.3s ease-out; +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-10px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.message.success { + background: #d1fae5; + color: #065f46; + border: 1px solid #a7f3d0; +} + +.message.error { + background: #fee2e2; + color: #991b1b; + border: 1px solid #fecaca; +} + +.message.info { + background: #dbeafe; + color: #1e40af; + border: 1px solid #bfdbfe; +} + +/* 用户信息卡片 */ +.user-card { + background: linear-gradient(135deg, #f8fafc, #e2e8f0); + padding: 24px; + border-radius: 16px; + border-left: 4px solid var(--primary-color); + margin-bottom: 30px; +} + +.user-card h3 { + margin-bottom: 8px; + color: var(--dark-text); +} + +.user-card p { + color: var(--light-text); + margin-bottom: 4px; +} + +/* 按钮组 */ +.btn-group { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 16px; + margin-bottom: 30px; +} + +/* 模态框样式 */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + backdrop-filter: blur(4px); + animation: fadeIn 0.3s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.modal-content { + background: white; + padding: 32px; + border-radius: 20px; + box-shadow: var(--shadow-lg); + max-width: 500px; + width: 90%; + animation: scaleIn 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +@keyframes scaleIn { + from { + opacity: 0; + transform: scale(0.9); + } + + to { + opacity: 1; + transform: scale(1); + } +} + +/* 标题样式 */ +.page-title { + font-size: 2.5rem; + font-weight: 700; + text-align: center; + margin-bottom: 30px; + background: linear-gradient(135deg, var(--primary-color), #7c3aed); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.section-title { + font-size: 1.5rem; + font-weight: 600; + margin-bottom: 20px; + color: var(--dark-text); +} + +/* 输入框修复 */ +input[type="text"], +input[type="password"], +input[type="number"], +input[type="email"], +select { + -webkit-appearance: none !important; + appearance: none !important; + border: 2px solid var(--border-color) !important; + background-color: white !important; + box-shadow: none !important; + outline: none !important; + transform: translateZ(0); + backface-visibility: hidden; + perspective: 1000; +} + +input:focus, +select:focus { + border-color: var(--primary-color) !important; + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important; + outline: none !important; +} + +/* 加载动画 */ +.loading { + display: inline-block; + width: 20px; + height: 20px; + border: 3px solid rgba(255, 255, 255, .3); + border-radius: 50%; + border-top-color: #fff; + animation: spin 1s ease-in-out infinite; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +/* 响应式设计 */ +@media (max-width: 768px) { + body { + padding: 10px; + } + + .btn-group { + grid-template-columns: 1fr; + } + + .page-title { + font-size: 2rem; + } + + .modal-content { + padding: 24px; + margin: 20px; + } +} + +/* 特殊效果 */ +.glass-effect { + background: rgba(255, 255, 255, 0.25); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.18); +} + +.pulse { + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0% { + box-shadow: 0 0 0 0 rgba(79, 70, 229, 0.4); + } + + 70% { + box-shadow: 0 0 0 10px rgba(79, 70, 229, 0); + } + + 100% { + box-shadow: 0 0 0 0 rgba(79, 70, 229, 0); + } +} \ No newline at end of file -- 2.34.1 From 6a04981a99b14c8dbbe2c4007907f42c8f92d365 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 19:37:30 +0800 Subject: [PATCH 17/30] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=BB=E7=95=8C?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/renderer/main.html | 680 ++++++++++-------- 1 file changed, 369 insertions(+), 311 deletions(-) diff --git a/src/electron-frontend/resources/renderer/main.html b/src/electron-frontend/resources/renderer/main.html index 2e778f3..0728ad2 100644 --- a/src/electron-frontend/resources/renderer/main.html +++ b/src/electron-frontend/resources/renderer/main.html @@ -4,101 +4,274 @@ 数学学习系统 - 主页 - + -
-

数学学习系统

+
+
+ +
+

数学学习系统

+

开启您的数学学习之旅

+
- + +
+
+ +
+ +
-
- - - -
- + +
+
+
📚
+

选择题目类型

+
+ +
+ + + +
+
-
- - + + + + +
+ + +
@@ -116,17 +289,22 @@ } // 显示用户信息 - document.getElementById('userInfo').innerHTML = ` - 用户名: ${currentUser.username}
- 用户类型: ${currentUser.userType} - `; + document.getElementById('userName').textContent = currentUser.username; + document.getElementById('userType').textContent = `${currentUser.userType} 用户`; + document.getElementById('userAvatar').textContent = currentUser.username.charAt(0).toUpperCase(); // 绑定题目类型按钮事件 - document.querySelectorAll('.btn-group button').forEach(btn => { + document.querySelectorAll('.level-btn').forEach(btn => { btn.addEventListener('click', (e) => { - selectedType = e.target.dataset.type; + selectedType = e.currentTarget.dataset.type; document.getElementById('selectedType').textContent = selectedType; document.getElementById('examSettings').style.display = 'block'; + + // 滚动到考试设置区域 + document.getElementById('examSettings').scrollIntoView({ + behavior: 'smooth', + block: 'center' + }); }); }); @@ -147,20 +325,30 @@ if (changePasswordBtn) { changePasswordBtn.addEventListener('click', showChangePasswordModal); } + + // 初始化统计数据(模拟数据) + initializeStats(); }); + function initializeStats() { + // 这里可以连接后端获取真实数据,目前使用模拟数据 + document.getElementById('totalQuestions').textContent = '128'; + document.getElementById('correctRate').textContent = '87%'; + document.getElementById('studyDays').textContent = '15'; + } + async function startExam() { console.log('=== 开始答题流程开始 ==='); const questionCount = parseInt(document.getElementById('questionCount').value); if (!selectedType) { - alert('请先选择题目类型'); + showNotification('请先选择题目类型', 'error'); return; } if (isNaN(questionCount) || questionCount < 10 || questionCount > 30) { - alert('题目数量应在10-30之间'); + showNotification('题目数量应在10-30之间', 'error'); return; } @@ -170,126 +358,101 @@ console.log('当前用户会话:', latestUser); if (!latestUser || !latestUser.sessionId) { - alert('用户会话已过期,请重新登录'); + showNotification('用户会话已过期,请重新登录', 'error'); await window.electronAPI.navigateTo('login'); return; } - console.log('开始生成试卷请求:', { + // 显示加载状态 + const startExamBtn = document.getElementById('startExam'); + const startExamText = document.getElementById('startExamText'); + const startExamLoading = document.getElementById('startExamLoading'); + + startExamText.style.display = 'none'; + startExamLoading.style.display = 'inline-block'; + startExamBtn.disabled = true; + + const result = await window.api.request('/generate-exam', 'POST', { sessionId: latestUser.sessionId, userType: selectedType, questionCount: questionCount }); - // 显示加载状态 - const startExamBtn = document.getElementById('startExam'); - const originalText = startExamBtn.textContent; - startExamBtn.textContent = '生成中...'; - startExamBtn.disabled = true; + console.log('生成试卷API响应:', result); - console.log('发送生成试卷请求...'); + if (result.success) { + // 保存考试信息 + const examData = { + examId: result.data.examId, + totalQuestions: result.data.totalQuestions, + currentQuestion: result.data.currentQuestion || 0, + userType: selectedType, + firstQuestion: { + question: result.data.question, + options: result.data.options + } + }; - // 添加超时控制 - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 15000); // 15秒超时 + console.log('保存考试数据:', examData); + window.electronAPI.setSession('currentExam', examData); - try { - const result = await window.api.request('/generate-exam', 'POST', { - sessionId: latestUser.sessionId, - userType: selectedType, - questionCount: questionCount - }); + showNotification('试卷生成成功!正在跳转...', 'success'); - clearTimeout(timeoutId); - console.log('生成试卷API响应:', result); - - if (result.success) { - // 保存考试信息 - 确保包含所有必要字段 - const examData = { - examId: result.data.examId, - totalQuestions: result.data.totalQuestions, - currentQuestion: result.data.currentQuestion || 0, - userType: selectedType, - // 保存第一题的详细信息,确保跳转后能立即显示 - firstQuestion: { - question: result.data.question, - options: result.data.options - } - }; - - console.log('保存考试数据:', examData); - window.electronAPI.setSession('currentExam', examData); - - // 确保数据保存完成后再跳转 - setTimeout(async () => { - console.log('考试数据已保存,准备跳转到答题页面'); - await window.electronAPI.navigateTo('quiz'); - }, 100); - } else { - alert('生成试卷失败: ' + result.message); - // 如果是会话问题,清除会话 - if (result.message.includes('会话') || result.message.includes('登录')) { - window.electronAPI.removeSession('userSession'); - await window.electronAPI.navigateTo('login'); - } + setTimeout(async () => { + await window.electronAPI.navigateTo('quiz'); + }, 1000); + } else { + showNotification('生成试卷失败: ' + result.message, 'error'); + if (result.message.includes('会话') || result.message.includes('登录')) { + window.electronAPI.removeSession('userSession'); + await window.electronAPI.navigateTo('login'); } - } catch (fetchError) { - clearTimeout(timeoutId); - throw fetchError; } } catch (error) { console.error('生成试卷错误:', error); - - if (error.name === 'AbortError') { - alert('请求超时!请检查:\n1. 后端Java程序是否运行\n2. 网络连接是否正常\n3. 端口8080是否被占用'); - } else { - alert('生成试卷时发生错误: ' + error.message); - } + showNotification('生成试卷时发生错误: ' + error.message, 'error'); } finally { // 恢复按钮状态 const startExamBtn = document.getElementById('startExam'); + const startExamText = document.getElementById('startExamText'); + const startExamLoading = document.getElementById('startExamLoading'); + if (startExamBtn) { - startExamBtn.textContent = '开始答题'; + startExamText.style.display = 'inline-block'; + startExamLoading.style.display = 'none'; startExamBtn.disabled = false; } } - - console.log('=== 开始答题流程结束 ==='); } - // 网络连接测试函数 - async function testBackendConnectivity() { - try { - console.log('测试后端连接...'); - - // 使用更简单的请求测试连接 - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 3000); - - const response = await fetch('http://localhost:8080/api/login', { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: 'username=test&password=test', - signal: controller.signal - }); - - clearTimeout(timeoutId); - - return { - connected: true, - status: response.status - }; - } catch (error) { - console.error('网络连接测试失败:', error); - return { - connected: false, - error: error.message - }; + // 显示通知函数 + function showNotification(message, type) { + // 移除现有通知 + const existingNotification = document.querySelector('.notification'); + if (existingNotification) { + existingNotification.remove(); } + + const notification = document.createElement('div'); + notification.className = `message ${type} notification`; + notification.textContent = message; + notification.style.position = 'fixed'; + notification.style.top = '20px'; + notification.style.right = '20px'; + notification.style.zIndex = '1001'; + notification.style.maxWidth = '300px'; + + document.body.appendChild(notification); + + // 3秒后自动移除 + setTimeout(() => { + notification.style.opacity = '0'; + notification.style.transform = 'translateX(100%)'; + setTimeout(() => notification.remove(), 300); + }, 3000); } + async function logout() { if (confirm('确定要退出登录吗?')) { try { @@ -302,152 +465,68 @@ } catch (error) { console.error('退出登录API错误:', error); } finally { - // 清除所有本地存储 window.electronAPI.removeSession('userSession'); window.electronAPI.removeSession('currentExam'); window.electronAPI.removeSession('examResult'); - - console.log('本地会话已清除,跳转到登录页面'); - - // 简单直接地导航到登录页面 await window.electronAPI.navigateTo('login'); } } } - // 显示修改密码模态框 + // 显示修改密码模态框(使用新的样式) function showChangePasswordModal() { - // 创建修改密码模态框 const modalHtml = ` -
-
-

修改密码

-
- -
-
- -
-
- + -
- - -
-
-
-
- `; + `; - // 添加模态框到页面 document.body.insertAdjacentHTML('beforeend', modalHtml); - // 绑定模态框事件 - 阻止内容区域点击事件冒泡 - const modalContent = document.getElementById('passwordModalContent'); - modalContent.addEventListener('click', function (e) { - e.stopPropagation(); - }); - - // 绑定按钮事件 + // 绑定事件 document.getElementById('confirmChangePassword').addEventListener('click', changePassword); document.getElementById('cancelChangePassword').addEventListener('click', closePasswordModal); - // 点击模态框背景关闭 + // 点击背景关闭 document.getElementById('passwordModal').addEventListener('click', function (e) { if (e.target === this) { closePasswordModal(); } }); - - // 修复模态框输入框的焦点问题 - repairModalInputs(); - } - - // 专门修复模态框输入框的函数 - function repairModalInputs() { - console.log('修复模态框输入框'); - - // 多重修复策略 - function aggressiveModalRepair() { - const modalInputs = [ - document.getElementById('oldPassword'), - document.getElementById('newPassword'), - document.getElementById('confirmPassword') - ]; - - modalInputs.forEach((input, index) => { - if (!input) return; - - // 完全重置样式 - input.style.cssText = ''; - input.style.border = '1px solid #ddd'; - input.style.background = 'white'; - input.style.color = '#000'; - input.style.opacity = '1'; - input.style.visibility = 'visible'; - input.style.display = 'block'; - input.style.width = '100%'; - input.style.padding = '10px'; - input.style.borderRadius = '5px'; - input.style.fontSize = '16px'; - input.style.webkitAppearance = 'none'; - input.style.appearance = 'none'; - - // 确保可交互 - input.readOnly = false; - input.disabled = false; - input.tabIndex = index + 1; - - // 添加事件监听器确保可聚焦 - input.addEventListener('mousedown', function (e) { - this.focus(); - e.stopPropagation(); - }); - - input.addEventListener('click', function (e) { - this.focus(); - e.stopPropagation(); - }); - }); - - // 特别聚焦第一个输入框 - const oldPasswordInput = document.getElementById('oldPassword'); - if (oldPasswordInput) { - setTimeout(() => { - oldPasswordInput.focus(); - oldPasswordInput.select(); - }, 300); - } - } - - // 立即执行修复 - aggressiveModalRepair(); - - // 多重延迟修复 - setTimeout(aggressiveModalRepair, 100); - setTimeout(aggressiveModalRepair, 500); - setTimeout(aggressiveModalRepair, 1000); - - // 监听模态框内的鼠标移动,持续修复 - let repairCount = 0; - const modal = document.getElementById('passwordModal'); - if (modal) { - modal.addEventListener('mousemove', () => { - if (repairCount < 3) { - setTimeout(aggressiveModalRepair, repairCount * 200); - repairCount++; - } - }); - } } - - // 关闭修改密码模态框 function closePasswordModal() { const modal = document.getElementById('passwordModal'); if (modal) { - modal.remove(); + modal.style.opacity = '0'; + setTimeout(() => modal.remove(), 300); } } @@ -457,30 +536,23 @@ const confirmPassword = document.getElementById('confirmPassword').value; const messageEl = document.getElementById('passwordMessage'); - // 清空之前的消息 messageEl.textContent = ''; - messageEl.style.color = ''; + messageEl.className = ''; if (!oldPassword || !newPassword || !confirmPassword) { - messageEl.textContent = '请填写所有字段'; - messageEl.style.color = 'red'; + showMessage('请填写所有字段', 'error', messageEl); return; } if (newPassword !== confirmPassword) { - messageEl.textContent = '两次输入的新密码不一致'; - messageEl.style.color = 'red'; + showMessage('两次输入的新密码不一致', 'error', messageEl); return; } try { - // 重新获取最新用户会话 const latestUser = window.electronAPI.getSession('userSession'); - console.log('修改密码,用户信息:', latestUser); - if (!latestUser || !latestUser.sessionId) { - messageEl.textContent = '用户会话已过期,请重新登录'; - messageEl.style.color = 'red'; + showMessage('用户会话已过期,请重新登录', 'error', messageEl); setTimeout(() => { closePasswordModal(); window.electronAPI.navigateTo('login'); @@ -495,37 +567,23 @@ confirmPassword: confirmPassword }); - console.log('修改密码响应:', result); - if (result.success) { - messageEl.textContent = '密码修改成功'; - messageEl.style.color = 'green'; - - // 更新本地会话中的密码信息(如果需要) - // 注意:这里只更新本地显示,实际密码已在后端更新 - + showMessage('密码修改成功', 'success', messageEl); setTimeout(() => { closePasswordModal(); - }, 2000); + }, 1500); } else { - messageEl.textContent = result.message; - messageEl.style.color = 'red'; - - // 如果是会话问题,清除会话 - if (result.message.includes('会话') || result.message.includes('登录')) { - window.electronAPI.removeSession('userSession'); - setTimeout(() => { - closePasswordModal(); - window.electronAPI.navigateTo('login'); - }, 2000); - } + showMessage(result.message, 'error', messageEl); } } catch (error) { - console.error('修改密码错误:', error); - messageEl.textContent = '修改密码时发生错误: ' + error.message; - messageEl.style.color = 'red'; + showMessage('修改密码时发生错误: ' + error.message, 'error', messageEl); } } + + function showMessage(message, type, element) { + element.textContent = message; + element.className = `message ${type}`; + } -- 2.34.1 From 23f3d777ec5ff75f02bd013a6789e102785da0d6 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 20:28:22 +0800 Subject: [PATCH 18/30] pom.xml --- .../math_learn/.idea/compiler.xml | 13 ++++++++ .../math_learn/.idea/encodings.xml | 7 ++++ .../math_learn/.idea/jarRepositories.xml | 20 +++++++++++ src/java-backend/math_learn/.idea/modules.xml | 8 ----- src/java-backend/math_learn/pom.xml | 33 +++++++++++++++++++ 5 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 src/java-backend/math_learn/.idea/compiler.xml create mode 100644 src/java-backend/math_learn/.idea/encodings.xml create mode 100644 src/java-backend/math_learn/.idea/jarRepositories.xml delete mode 100644 src/java-backend/math_learn/.idea/modules.xml create mode 100644 src/java-backend/math_learn/pom.xml diff --git a/src/java-backend/math_learn/.idea/compiler.xml b/src/java-backend/math_learn/.idea/compiler.xml new file mode 100644 index 0000000..01d8ea0 --- /dev/null +++ b/src/java-backend/math_learn/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/encodings.xml b/src/java-backend/math_learn/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/src/java-backend/math_learn/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/jarRepositories.xml b/src/java-backend/math_learn/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/src/java-backend/math_learn/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml deleted file mode 100644 index 422d56a..0000000 --- a/src/java-backend/math_learn/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/pom.xml b/src/java-backend/math_learn/pom.xml new file mode 100644 index 0000000..7cdff2f --- /dev/null +++ b/src/java-backend/math_learn/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.mathlearn + math-learning-system + 1.0.0 + + + 8 + 8 + UTF-8 + + + + + + com.sun.mail + javax.mail + 1.6.2 + + + + + javax.activation + activation + 1.1.1 + + + \ No newline at end of file -- 2.34.1 From 522d0b636af966ffd795d4cc65b569c1dffc7cdb Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 20:29:51 +0800 Subject: [PATCH 19/30] =?UTF-8?q?=E9=82=AE=E7=AE=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../math_learn/src/com/mathlearn/Main.java | 103 ++++++++++++++++-- 1 file changed, 91 insertions(+), 12 deletions(-) diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main.java b/src/java-backend/math_learn/src/com/mathlearn/Main.java index d4ece29..eb6ab90 100644 --- a/src/java-backend/math_learn/src/com/mathlearn/Main.java +++ b/src/java-backend/math_learn/src/com/mathlearn/Main.java @@ -12,6 +12,9 @@ import java.io.*; import java.net.InetSocketAddress; import java.text.SimpleDateFormat; import java.util.*; +import javax.mail.*; +import javax.mail.internet.*; +import java.util.Properties; // 主系统类 - 改造为->HTTP服务器 public class Main { @@ -22,6 +25,13 @@ public class Main { private String baseDirectory = "math_questions"; private Random random = new Random(); + // 邮件配置 - 请修改为你的QQ邮箱信息 + private static final String EMAIL_HOST = "smtp.qq.com"; + private static final String EMAIL_PORT = "587"; + private static final String EMAIL_USERNAME = "2944528150@qq.com"; // 你的QQ邮箱 + private static final String EMAIL_PASSWORD = "your-authorization-code"; // QQ邮箱授权码,不是密码 + private static final String EMAIL_FROM = "2944528150@qq.com"; // 发件人邮箱 + public Main() { initializeAccounts(); pendingRegistrations = new HashMap<>(); @@ -116,23 +126,24 @@ public class Main { if (email.equals(account.getEmail())) { return new ApiResponse(false, "该邮箱已被注册", null); } -} + } // 生成注册码 String code = generateRegistrationCode(email); - // 模拟发送邮件 - System.out.println("=== 邮件发送模拟 ==="); - System.out.println("收件人: " + email); - System.out.println("验证码: " + code); - System.out.println("=== 邮件发送完成 ==="); + // 发送邮件 + boolean emailSent = sendEmail(email, "数学学习系统 - 注册验证码", + buildEmailContent(code)); - Map data = new HashMap<>(); - data.put("email", email); - // 注意:实际生产中不应该返回验证码,这里仅用于演示和测试 - data.put("debugCode", code); - - return new ApiResponse(true, "验证码已发送到您的邮箱", data); + if (emailSent) { + Map data = new HashMap<>(); + data.put("email", email); + // 实际生产环境中不应该返回验证码,这里仅用于测试 + data.put("debugCode", code); + return new ApiResponse(true, "验证码已发送到您的邮箱", data); + } else { + return new ApiResponse(false, "邮件发送失败,请检查邮箱地址或稍后重试", null); + } } // 验证邮箱格式 @@ -143,7 +154,75 @@ public class Main { } + // 构建邮件内容 + private String buildEmailContent(String code) { + return "" + + "" + + "" + + "" + + "" + + "" + + "" + + "
" + + "

数学学习系统 - 注册验证码

" + + "

您好!

" + + "

您正在注册数学学习系统账号,验证码为:

" + + "
" + code + "
" + + "

验证码有效期15分钟,请尽快完成注册。

" + + "

如非本人操作,请忽略此邮件。

" + + "
" + + "

数学学习系统团队

" + + "

此为系统邮件,请勿回复

" + + "
" + + "
" + + "" + + ""; + } + // 发送邮件方法 + private boolean sendEmail(String toEmail, String subject, String content) { + try { + // 配置邮件服务器属性 + Properties props = new Properties(); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "true"); + props.put("mail.smtp.host", EMAIL_HOST); + props.put("mail.smtp.port", EMAIL_PORT); + props.put("mail.smtp.ssl.trust", EMAIL_HOST); + + // 创建会话 + Session session = Session.getInstance(props, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(EMAIL_USERNAME, EMAIL_PASSWORD); + } + }); + // 创建邮件 + Message message = new MimeMessage(session); + message.setFrom(new InternetAddress(EMAIL_FROM)); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); + message.setSubject(subject); + + // 设置邮件内容为HTML格式 + message.setContent(content, "text/html; charset=utf-8"); + + // 发送邮件 + Transport.send(message); + + System.out.println("邮件发送成功 - 收件人: " + toEmail); + return true; + + } catch (Exception e) { + System.err.println("邮件发送失败: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } // 验证密码格式 private boolean isValidPassword(String password) { -- 2.34.1 From ee98a6cd533e2d7f72f94afa0d4e12bced17e681 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 21:10:42 +0800 Subject: [PATCH 20/30] =?UTF-8?q?=E9=82=AE=E7=AE=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/java-backend/math_learn/src/com/mathlearn/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main.java b/src/java-backend/math_learn/src/com/mathlearn/Main.java index d4ece29..453cc90 100644 --- a/src/java-backend/math_learn/src/com/mathlearn/Main.java +++ b/src/java-backend/math_learn/src/com/mathlearn/Main.java @@ -116,7 +116,7 @@ public class Main { if (email.equals(account.getEmail())) { return new ApiResponse(false, "该邮箱已被注册", null); } -} + } // 生成注册码 String code = generateRegistrationCode(email); -- 2.34.1 From 25f0387c826d998ec06307b65fea8e8fb5b33a79 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 21:35:22 +0800 Subject: [PATCH 21/30] deletecompiler --- src/java-backend/math_learn/.idea/.name | 1 + src/java-backend/math_learn/.idea/compiler.xml | 8 ++++++++ src/java-backend/math_learn/.idea/modules.xml | 8 -------- 3 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 src/java-backend/math_learn/.idea/.name create mode 100644 src/java-backend/math_learn/.idea/compiler.xml delete mode 100644 src/java-backend/math_learn/.idea/modules.xml diff --git a/src/java-backend/math_learn/.idea/.name b/src/java-backend/math_learn/.idea/.name new file mode 100644 index 0000000..002da1d --- /dev/null +++ b/src/java-backend/math_learn/.idea/.name @@ -0,0 +1 @@ +Main.java \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/compiler.xml b/src/java-backend/math_learn/.idea/compiler.xml new file mode 100644 index 0000000..5f31e91 --- /dev/null +++ b/src/java-backend/math_learn/.idea/compiler.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml deleted file mode 100644 index 422d56a..0000000 --- a/src/java-backend/math_learn/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file -- 2.34.1 From 82811e241872fc2d706312f6198e36777a071c49 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 22:06:47 +0800 Subject: [PATCH 22/30] =?UTF-8?q?=E7=9C=9F=E5=AE=9E=E9=82=AE=E7=AE=B1?= =?UTF-8?q?=E5=8F=91=E9=80=81=E9=AA=8C=E8=AF=81=E7=A0=81-QQ=E9=82=AE?= =?UTF-8?q?=E7=AE=B1=E6=8E=88=E6=9D=83=E7=A0=81=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/java-backend/math_learn/.idea/modules.xml | 8 ++++++++ src/java-backend/math_learn/math-learning-system.iml | 8 ++++++++ src/java-backend/math_learn/src/com/mathlearn/Main.java | 4 ++-- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/java-backend/math_learn/.idea/modules.xml create mode 100644 src/java-backend/math_learn/math-learning-system.iml diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml new file mode 100644 index 0000000..d2bf936 --- /dev/null +++ b/src/java-backend/math_learn/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/math-learning-system.iml b/src/java-backend/math_learn/math-learning-system.iml new file mode 100644 index 0000000..abe781f --- /dev/null +++ b/src/java-backend/math_learn/math-learning-system.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main.java b/src/java-backend/math_learn/src/com/mathlearn/Main.java index eb6ab90..7d330cf 100644 --- a/src/java-backend/math_learn/src/com/mathlearn/Main.java +++ b/src/java-backend/math_learn/src/com/mathlearn/Main.java @@ -28,8 +28,8 @@ public class Main { // 邮件配置 - 请修改为你的QQ邮箱信息 private static final String EMAIL_HOST = "smtp.qq.com"; private static final String EMAIL_PORT = "587"; - private static final String EMAIL_USERNAME = "2944528150@qq.com"; // 你的QQ邮箱 - private static final String EMAIL_PASSWORD = "your-authorization-code"; // QQ邮箱授权码,不是密码 + private static final String EMAIL_USERNAME = "2944528150@qq.com"; // QQ邮箱 + private static final String EMAIL_PASSWORD = "kxfeaqqfyxysdhfh"; // QQ邮箱授权码,不是密码 private static final String EMAIL_FROM = "2944528150@qq.com"; // 发件人邮箱 public Main() { -- 2.34.1 From d8f4c37190bd31e8f62e58cdd49aa61ee67ebf54 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 22:34:45 +0800 Subject: [PATCH 23/30] =?UTF-8?q?maven=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/java-backend/math_learn/pom.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/java-backend/math_learn/pom.xml b/src/java-backend/math_learn/pom.xml index 7cdff2f..f031ea9 100644 --- a/src/java-backend/math_learn/pom.xml +++ b/src/java-backend/math_learn/pom.xml @@ -30,4 +30,16 @@ 1.1.1 + + + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + + + \ No newline at end of file -- 2.34.1 From 4cbc3e0951e2c6ebe856307257b28bbccb2c258d Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 22:50:59 +0800 Subject: [PATCH 24/30] commit --- src/java-backend/math_learn/.idea/compiler.xml | 4 +++- src/java-backend/math_learn/.idea/misc.xml | 1 + src/java-backend/math_learn/.idea/modules.xml | 8 -------- 3 files changed, 4 insertions(+), 9 deletions(-) delete mode 100644 src/java-backend/math_learn/.idea/modules.xml diff --git a/src/java-backend/math_learn/.idea/compiler.xml b/src/java-backend/math_learn/.idea/compiler.xml index 01d8ea0..40b3a64 100644 --- a/src/java-backend/math_learn/.idea/compiler.xml +++ b/src/java-backend/math_learn/.idea/compiler.xml @@ -6,8 +6,10 @@ - + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/misc.xml b/src/java-backend/math_learn/.idea/misc.xml index 6f29fee..5cd9a10 100644 --- a/src/java-backend/math_learn/.idea/misc.xml +++ b/src/java-backend/math_learn/.idea/misc.xml @@ -1,5 +1,6 @@ + diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml deleted file mode 100644 index d2bf936..0000000 --- a/src/java-backend/math_learn/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file -- 2.34.1 From cfac8d930b522bc06c4d87129a8bd182d707830a Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sat, 11 Oct 2025 23:48:28 +0800 Subject: [PATCH 25/30] =?UTF-8?q?=E8=A7=A3=E5=86=B3compiler,misc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/electron-frontend/package.json | 27 ++++++++++++++++--- .../math_learn/.idea/compiler.xml | 9 +------ src/java-backend/math_learn/.idea/misc.xml | 2 +- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/electron-frontend/package.json b/src/electron-frontend/package.json index fef080d..8a20168 100644 --- a/src/electron-frontend/package.json +++ b/src/electron-frontend/package.json @@ -6,7 +6,8 @@ "scripts": { "start": "electron .", "dev": "electron . --dev", - "build": "electron-builder" + "build": "electron-builder", + "dist": "electron-builder --publish=never" }, "devDependencies": { "electron": "^22.3.27", @@ -21,11 +22,29 @@ "files": [ "resources/**/*", "!resources/node_modules", - "package.json" + "!**/*.map", + "!**/*.log" ], "win": { - "target": "nsis" - } + "target": [ + { + "target": "nsis", + "arch": [ + "x64" + ] + } + ], + "icon": "resources/icon.ico" + }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true, + "createDesktopShortcut": true, + "createStartMenuShortcut": true, + "shortcutName": "数学学习系统" + }, + "compression": "maximum", + "asar": true }, "dependencies": { "node-fetch": "^2.7.0" diff --git a/src/java-backend/math_learn/.idea/compiler.xml b/src/java-backend/math_learn/.idea/compiler.xml index 40b3a64..5f31e91 100644 --- a/src/java-backend/math_learn/.idea/compiler.xml +++ b/src/java-backend/math_learn/.idea/compiler.xml @@ -1,15 +1,8 @@ - - - - - - - - + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/misc.xml b/src/java-backend/math_learn/.idea/misc.xml index 5cd9a10..b2eea27 100644 --- a/src/java-backend/math_learn/.idea/misc.xml +++ b/src/java-backend/math_learn/.idea/misc.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file -- 2.34.1 From 52f3ec6a5a11e148495d552ffefcdb64502b46ca Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sun, 12 Oct 2025 10:44:03 +0800 Subject: [PATCH 26/30] compiler --- .../.idea/artifacts/math_learning_system_jar.xml | 15 +++++++++++++++ src/java-backend/math_learn/.idea/compiler.xml | 2 +- src/java-backend/math_learn/.idea/modules.xml | 8 -------- src/java-backend/math_learn/META-INF/MANIFEST.MF | 4 ++++ 4 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml delete mode 100644 src/java-backend/math_learn/.idea/modules.xml create mode 100644 src/java-backend/math_learn/META-INF/MANIFEST.MF diff --git a/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml b/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml new file mode 100644 index 0000000..7089bb3 --- /dev/null +++ b/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml @@ -0,0 +1,15 @@ + + + $PROJECT_DIR$/../../../../../../electronPro/MATHLEARN/backend + + + + + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/compiler.xml b/src/java-backend/math_learn/.idea/compiler.xml index 01d8ea0..1f3d83c 100644 --- a/src/java-backend/math_learn/.idea/compiler.xml +++ b/src/java-backend/math_learn/.idea/compiler.xml @@ -6,7 +6,7 @@ - + diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml deleted file mode 100644 index d2bf936..0000000 --- a/src/java-backend/math_learn/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/META-INF/MANIFEST.MF b/src/java-backend/math_learn/META-INF/MANIFEST.MF new file mode 100644 index 0000000..952f743 --- /dev/null +++ b/src/java-backend/math_learn/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Main-Class: com.mathlearn.Main +Class-Path: activation-1.1.1.jar javax.mail-1.6.2.jar + -- 2.34.1 From 55ae4d389bc9d8f495f62d617bb9642fc0ea7827 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sun, 12 Oct 2025 10:49:20 +0800 Subject: [PATCH 27/30] misc --- src/java-backend/math_learn/.idea/misc.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/java-backend/math_learn/.idea/misc.xml b/src/java-backend/math_learn/.idea/misc.xml index 6f29fee..fdc35ea 100644 --- a/src/java-backend/math_learn/.idea/misc.xml +++ b/src/java-backend/math_learn/.idea/misc.xml @@ -1,5 +1,13 @@ + + + + -- 2.34.1 From b5087c37c26e1de9616a53bb4cbf60d53fb35acb Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sun, 12 Oct 2025 15:37:19 +0800 Subject: [PATCH 28/30] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/README.md | 204 ++++++++++++++++++ src/java-backend/math_learn/.idea/modules.xml | 8 + 2 files changed, 212 insertions(+) create mode 100644 src/java-backend/math_learn/.idea/modules.xml diff --git a/doc/README.md b/doc/README.md index aacf4a3..27198ab 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,2 +1,206 @@ # Pair-Programming +## **项目概述** + +数学学习系统是一个面向小初高学生的数学学习软件,旨在通过生成针对性的数学题目帮助学生进行练习和巩固数学知识。该系统采用前后端分离架构,前端基于 Electron 构建桌面应用,后端使用 Java 提供 API 服务。 + +## **项目结构** + +pair-programming/ + +├── src/ + +│ ├── electron-frontend/ # Electron前端 + +│ │ ├── resources/ + +│ │ │ ├── renderer/ # 渲染进程页面 + +│ │ │ │ ├── main.html # 主页面 + +│ │ │ │ ├── login.html # 登录页面 + +│ │ │ │ └── result.html # 结果页面 + +│ │ │ │ └── quiz.html # 答题页面 + +│ │ │ │ └── register.html # 注册页面 + +│ │ │ ├── main.js # 主进程代码 + +│ │ │ └── preload.js # 预加载脚本 + +│ │ ├── package.json # 前端依赖配置 + +│ │ └── package-lock.json # 依赖版本锁定文件 + +│ └── java-backend/ # Java后端 + +│ └── math\_learn/ # 数学学习系统后端代码 + +│ ├── .idea/ # IntelliJ IDEA配置 + +│ ├── src/ # 源代码 + +│ │ └── com/mathlearn/ + +│ │ ├── Main.java # 主程序入口 + +│ │ └── generator/ # 题目生成业务 + +| | | └── QuestionGenerator # 题目生成器接口 + +│ │ | └── SeniorHighGenerator.java # 高中题目生成器 + +| | └──model/ # 实体类 + +| | ├── api/ # API响应类 + +| | ├── exam/ # 题目试卷类 + +| | └── user/ # 用户类 + +│ └── .gitignore # Git忽略文件 + +└──doc/ #说明文档 + + └── README.md + +## **功能说明** + +**核心功能** + +1.用户认证:支持用户注册、登录、退出、修改密码功能 + +2.题目生成:根据用户选择的学段(小学、初中、高中)生成相应难度的数学题目 + +3.答题系统:提供交互式答题界面 + +4.成绩评估:答题完成后计算并展示得分和评价 + + + +## **题目生成** + +系统根据不同学段生成相应难度的题目: + +高中阶段包含对数等高级数学题目 + +题目数量可在 10-30 之间选择 + +生成过程包含详细日志记录,便于调试和跟踪 + + + +## **技术栈** + +前端技术 + +Electron:用于构建跨平台桌面应用 + +HTML/CSS:页面结构和样式 + +JavaScript:交互逻辑 + +node-fetch:网络请求 + +后端技术 + +Java:后端服务开发 + +JDK 21:Java 开发环境 + + + +## **环境配置与运行** + +后端运行: + +1.确保安装 JDK 21 + +2.在 IDE(如 IntelliJ IDEA)中打开math\_learn项目 + +3.运行com.mathlearn.Main主类启动后端服务 + + + +## **API 接口说明** + +生成试卷 + +端点:/generate-exam + +方法:POST + +参数: + +  sessionId:用户会话 ID + +  userType:用户类型(小学 / 初中 / 高中) + +  questionCount:题目数量(10-30) + +返回:包含试卷信息和第一题的 JSON 响应 + + + +## **退出登录** + +端点:/logout + +方法:POST + +参数: + +sessionId:用户会话 ID + +返回:退出结果 + + + +## **注意事项** + +确保后端服务在本地 8080 端口运行,否则前端无法正常获取数据 + +题目生成可能需要一定时间,系统设置了 15 秒超时控制 + +若遇到连接问题,请检查: + +1.后端 Java 程序是否运行 + +2.网络连接是否正常 + +3.端口 8080 是否被占用 + + + +## **使用教程** + +1.后端启动 + +两种路径: + + 1)安装mathlearn\_setup.exe安装包,根据指示完成下载 + + 确保端口8080未被占用 + + backend目录有jar和exe两种方式启动后端服务器 + + 2)在 IDE(如 IntelliJ IDEA,或其他编程软件)中打开math\_learn项目 + + 确保端口8080未被占用 + + 运行com.mathlearn.Main主类启动后端服务 + +2.前端运行: + +安装mathlearn\_setup.exe安装包,根据指示完成下载 + +3.根据邮箱注册自己的账号并完成登录 + +4\.根据用户类型选择不同的题目类型,并输入所需题目数量(10-30题) + +5\.完成答题并查看所得分数 + +6\.安装目录下backend/math_questions文件夹里存储用户答题数据 + diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml new file mode 100644 index 0000000..d2bf936 --- /dev/null +++ b/src/java-backend/math_learn/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file -- 2.34.1 From 2851c2a426e508da2a205959ac38e2b28f6b03bb Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sun, 12 Oct 2025 15:43:10 +0800 Subject: [PATCH 29/30] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/README.md b/doc/README.md index 27198ab..6fa1bee 100644 --- a/doc/README.md +++ b/doc/README.md @@ -46,19 +46,19 @@ pair-programming/ │ │ ├── Main.java # 主程序入口 -│ │ └── generator/ # 题目生成业务 +│ │ ├── generator/ # 题目生成业务 -| | | └── QuestionGenerator # 题目生成器接口 +│ │ │ ├── QuestionGenerator # 题目生成器接口 -│ │ | └── SeniorHighGenerator.java # 高中题目生成器 +│ │ │ └── SeniorHighGenerator.java # 高中题目生成器 -| | └──model/ # 实体类 +│ │ └──model/ # 实体类 -| | ├── api/ # API响应类 +│ │ ├── api/ # API响应类 -| | ├── exam/ # 题目试卷类 +│ │ ├── exam/ # 题目试卷类 -| | └── user/ # 用户类 +│ │ └── user/ # 用户类 │ └── .gitignore # Git忽略文件 -- 2.34.1 From d4103654d79d42752b14e6d5feeb6fcd175fbea7 Mon Sep 17 00:00:00 2001 From: jiazhuo <2944528150@qq.com> Date: Sun, 12 Oct 2025 15:46:08 +0800 Subject: [PATCH 30/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.idea/artifacts/math_learning_system_jar.xml | 14 ++++++-------- src/java-backend/math_learn/META-INF/MANIFEST.MF | 1 - 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml b/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml index 7089bb3..49743a9 100644 --- a/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml +++ b/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml @@ -1,15 +1,13 @@ $PROJECT_DIR$/../../../../../../electronPro/MATHLEARN/backend - - - - - - + + + - - + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/META-INF/MANIFEST.MF b/src/java-backend/math_learn/META-INF/MANIFEST.MF index 952f743..0054b90 100644 --- a/src/java-backend/math_learn/META-INF/MANIFEST.MF +++ b/src/java-backend/math_learn/META-INF/MANIFEST.MF @@ -1,4 +1,3 @@ Manifest-Version: 1.0 Main-Class: com.mathlearn.Main -Class-Path: activation-1.1.1.jar javax.mail-1.6.2.jar -- 2.34.1