commit 5497e891ad68b24e5e1a92a22e85e0439b64b7a0 Author: feie9456 Date: Wed Apr 30 22:36:01 2025 +0800 first commit diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..393d187 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "csharpier": { + "version": "0.30.6", + "commands": [ + "dotnet-csharpier" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8ee54e8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..b37f838 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# home-page + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. + +## Customize configuration + +See [Vite Configuration Reference](https://vite.dev/config/). + +## Project Setup + +```sh +bun install +``` + +### Compile and Hot-Reload for Development + +```sh +bun dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +bun run build +``` diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..8583bbf --- /dev/null +++ b/bun.lock @@ -0,0 +1,1030 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "home-page", + "dependencies": { + "gray-matter": "^4.0.3", + "gsap": "^3.12.7", + "highlight.js": "^11.11.1", + "localforage": "^1.10.0", + "markdown-it": "^14.1.0", + "markdown-it-katex": "^2.0.3", + "markdown-it-math": "^5.2.0", + "normalize.css": "^8.0.1", + "vue": "^3.5.13", + "vue-router": "^4.5.0", + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.1", + "@types/node": "^22.14.0", + "@vitejs/plugin-vue": "^5.2.3", + "@vitejs/plugin-vue-jsx": "^4.1.2", + "@vue/tsconfig": "^0.7.0", + "npm-run-all2": "^7.0.2", + "sass-embedded": "^1.86.3", + "typescript": "~5.8.0", + "vite": "^6.2.4", + "vite-plugin-md": "^0.21.5", + "vite-plugin-minipic": "^1.3.0", + "vite-plugin-vue-devtools": "^7.7.2", + "vue-tsc": "^2.2.8", + }, + }, + }, + "packages": { + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + + "@antfu/utils": ["@antfu/utils@0.7.10", "", {}, "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww=="], + + "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + + "@babel/compat-data": ["@babel/compat-data@7.26.8", "", {}, "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ=="], + + "@babel/core": ["@babel/core@7.26.10", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.10", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.10", "@babel/parser": "^7.26.10", "@babel/template": "^7.26.9", "@babel/traverse": "^7.26.10", "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ=="], + + "@babel/generator": ["@babel/generator@7.27.0", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw=="], + + "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.25.9", "", { "dependencies": { "@babel/types": "^7.25.9" } }, "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.0", "", { "dependencies": { "@babel/compat-data": "^7.26.8", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA=="], + + "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.27.0", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-member-expression-to-functions": "^7.25.9", "@babel/helper-optimise-call-expression": "^7.25.9", "@babel/helper-replace-supers": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", "@babel/traverse": "^7.27.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg=="], + + "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.26.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw=="], + + "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.25.9", "", { "dependencies": { "@babel/types": "^7.25.9" } }, "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.26.5", "", {}, "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg=="], + + "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.26.5", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.25.9", "@babel/helper-optimise-call-expression": "^7.25.9", "@babel/traverse": "^7.26.5" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg=="], + + "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.25.9", "", {}, "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw=="], + + "@babel/helpers": ["@babel/helpers@7.27.0", "", { "dependencies": { "@babel/template": "^7.27.0", "@babel/types": "^7.27.0" } }, "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg=="], + + "@babel/parser": ["@babel/parser@7.27.0", "", { "dependencies": { "@babel/types": "^7.27.0" }, "bin": "./bin/babel-parser.js" }, "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg=="], + + "@babel/plugin-proposal-decorators": ["@babel/plugin-proposal-decorators@7.25.9", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/plugin-syntax-decorators": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g=="], + + "@babel/plugin-syntax-decorators": ["@babel/plugin-syntax-decorators@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg=="], + + "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.26.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A=="], + + "@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="], + + "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA=="], + + "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ=="], + + "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.27.0", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-create-class-features-plugin": "^7.27.0", "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg=="], + + "@babel/template": ["@babel/template@7.27.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0" } }, "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA=="], + + "@babel/traverse": ["@babel/traverse@7.27.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.27.0", "@babel/parser": "^7.27.0", "@babel/template": "^7.27.0", "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA=="], + + "@babel/types": ["@babel/types@7.27.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg=="], + + "@bufbuild/protobuf": ["@bufbuild/protobuf@2.2.5", "", {}, "sha512-/g5EzJifw5GF8aren8wZ/G5oMuPoGeS6MQD3ca8ddcvdXR5UELUfdTZITCGNhNXynY/AYl3Z4plmxdj/tRl/hQ=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.2", "", { "os": "android", "cpu": "arm" }, "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.2", "", { "os": "android", "cpu": "arm64" }, "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.2", "", { "os": "android", "cpu": "x64" }, "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.2", "", { "os": "linux", "cpu": "arm" }, "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.2", "", { "os": "linux", "cpu": "x64" }, "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.2", "", { "os": "none", "cpu": "arm64" }, "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.2", "", { "os": "none", "cpu": "x64" }, "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.2", "", { "os": "win32", "cpu": "x64" }, "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "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" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + + "@jsdevtools/ez-spawn": ["@jsdevtools/ez-spawn@3.0.4", "", { "dependencies": { "call-me-maybe": "^1.0.1", "cross-spawn": "^7.0.3", "string-argv": "^0.3.1", "type-detect": "^4.0.8" } }, "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + + "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], + + "@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.40.0", "", { "os": "android", "cpu": "arm" }, "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.40.0", "", { "os": "android", "cpu": "arm64" }, "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.40.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.40.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.40.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.40.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.40.0", "", { "os": "linux", "cpu": "arm" }, "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.40.0", "", { "os": "linux", "cpu": "arm" }, "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.40.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.40.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg=="], + + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.40.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.40.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.40.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.40.0", "", { "os": "linux", "cpu": "x64" }, "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.40.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.40.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.40.0", "", { "os": "win32", "cpu": "x64" }, "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ=="], + + "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], + + "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], + + "@tsconfig/node22": ["@tsconfig/node22@22.0.1", "", {}, "sha512-VkgOa3n6jvs1p+r3DiwBqeEwGAwEvnVCg/hIjiANl5IEcqP3G0u5m8cBJspe1t9qjZRlZ7WFgqq5bJrGdgAKMg=="], + + "@types/chai": ["@types/chai@4.3.20", "", {}, "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ=="], + + "@types/chai-subset": ["@types/chai-subset@1.3.6", "", { "peerDependencies": { "@types/chai": "<5.2.0" } }, "sha512-m8lERkkQj+uek18hXOZuec3W/fCRTrU4hrnXjH3qhHy96ytuPaPiWGgu7sJb7tZxZonO75vYAjCvpe/e4VUwRw=="], + + "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], + + "@types/linkify-it": ["@types/linkify-it@5.0.0", "", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="], + + "@types/markdown-it": ["@types/markdown-it@12.2.3", "", { "dependencies": { "@types/linkify-it": "*", "@types/mdurl": "*" } }, "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ=="], + + "@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="], + + "@types/node": ["@types/node@22.14.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw=="], + + "@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.3", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg=="], + + "@vitejs/plugin-vue-jsx": ["@vitejs/plugin-vue-jsx@4.1.2", "", { "dependencies": { "@babel/core": "^7.26.7", "@babel/plugin-transform-typescript": "^7.26.7", "@vue/babel-plugin-jsx": "^1.2.5" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.0.0" } }, "sha512-4Rk0GdE0QCdsIkuMmWeg11gmM4x8UmTnZR/LWPm7QJ7+BsK4tq08udrN0isrrWqz5heFy9HLV/7bOLgFS8hUjA=="], + + "@volar/language-core": ["@volar/language-core@2.4.12", "", { "dependencies": { "@volar/source-map": "2.4.12" } }, "sha512-RLrFdXEaQBWfSnYGVxvR2WrO6Bub0unkdHYIdC31HzIEqATIuuhRRzYu76iGPZ6OtA4Au1SnW0ZwIqPP217YhA=="], + + "@volar/source-map": ["@volar/source-map@2.4.12", "", {}, "sha512-bUFIKvn2U0AWojOaqf63ER0N/iHIBYZPpNGogfLPQ68F5Eet6FnLlyho7BS0y2HJ1jFhSif7AcuTx1TqsCzRzw=="], + + "@volar/typescript": ["@volar/typescript@2.4.12", "", { "dependencies": { "@volar/language-core": "2.4.12", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-HJB73OTJDgPc80K30wxi3if4fSsZZAOScbj2fcicMuOPoOkcf9NNAINb33o+DzhBdF9xTKC1gnPmIRDous5S0g=="], + + "@vue/babel-helper-vue-transform-on": ["@vue/babel-helper-vue-transform-on@1.4.0", "", {}, "sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw=="], + + "@vue/babel-plugin-jsx": ["@vue/babel-plugin-jsx@1.4.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.26.5", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/template": "^7.26.9", "@babel/traverse": "^7.26.9", "@babel/types": "^7.26.9", "@vue/babel-helper-vue-transform-on": "1.4.0", "@vue/babel-plugin-resolve-type": "1.4.0", "@vue/shared": "^3.5.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" }, "optionalPeers": ["@babel/core"] }, "sha512-9zAHmwgMWlaN6qRKdrg1uKsBKHvnUU+Py+MOCTuYZBoZsopa90Di10QRjB+YPnVss0BZbG/H5XFwJY1fTxJWhA=="], + + "@vue/babel-plugin-resolve-type": ["@vue/babel-plugin-resolve-type@1.4.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.26.5", "@babel/parser": "^7.26.9", "@vue/compiler-sfc": "^3.5.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ=="], + + "@vue/compiler-core": ["@vue/compiler-core@3.5.13", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.13", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q=="], + + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.13", "", { "dependencies": { "@vue/compiler-core": "3.5.13", "@vue/shared": "3.5.13" } }, "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA=="], + + "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.13", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.13", "@vue/compiler-dom": "3.5.13", "@vue/compiler-ssr": "3.5.13", "@vue/shared": "3.5.13", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.48", "source-map-js": "^1.2.0" } }, "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ=="], + + "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.13", "", { "dependencies": { "@vue/compiler-dom": "3.5.13", "@vue/shared": "3.5.13" } }, "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA=="], + + "@vue/compiler-vue2": ["@vue/compiler-vue2@2.7.16", "", { "dependencies": { "de-indent": "^1.0.2", "he": "^1.2.0" } }, "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A=="], + + "@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="], + + "@vue/devtools-core": ["@vue/devtools-core@7.7.2", "", { "dependencies": { "@vue/devtools-kit": "^7.7.2", "@vue/devtools-shared": "^7.7.2", "mitt": "^3.0.1", "nanoid": "^5.0.9", "pathe": "^2.0.2", "vite-hot-client": "^0.2.4" }, "peerDependencies": { "vue": "^3.0.0" } }, "sha512-lexREWj1lKi91Tblr38ntSsy6CvI8ba7u+jmwh2yruib/ltLUcsIzEjCnrkh1yYGGIKXbAuYV2tOG10fGDB9OQ=="], + + "@vue/devtools-kit": ["@vue/devtools-kit@7.7.2", "", { "dependencies": { "@vue/devtools-shared": "^7.7.2", "birpc": "^0.2.19", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.1" } }, "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ=="], + + "@vue/devtools-shared": ["@vue/devtools-shared@7.7.2", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA=="], + + "@vue/language-core": ["@vue/language-core@2.2.8", "", { "dependencies": { "@volar/language-core": "~2.4.11", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", "alien-signals": "^1.0.3", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-rrzB0wPGBvcwaSNRriVWdNAbHQWSf0NlGqgKHK5mEkXpefjUlVRP62u03KvwZpvKVjRnBIQ/Lwre+Mx9N6juUQ=="], + + "@vue/reactivity": ["@vue/reactivity@3.5.13", "", { "dependencies": { "@vue/shared": "3.5.13" } }, "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg=="], + + "@vue/runtime-core": ["@vue/runtime-core@3.5.13", "", { "dependencies": { "@vue/reactivity": "3.5.13", "@vue/shared": "3.5.13" } }, "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw=="], + + "@vue/runtime-dom": ["@vue/runtime-dom@3.5.13", "", { "dependencies": { "@vue/reactivity": "3.5.13", "@vue/runtime-core": "3.5.13", "@vue/shared": "3.5.13", "csstype": "^3.1.3" } }, "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog=="], + + "@vue/server-renderer": ["@vue/server-renderer@3.5.13", "", { "dependencies": { "@vue/compiler-ssr": "3.5.13", "@vue/shared": "3.5.13" }, "peerDependencies": { "vue": "3.5.13" } }, "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA=="], + + "@vue/shared": ["@vue/shared@3.5.13", "", {}, "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="], + + "@vue/tsconfig": ["@vue/tsconfig@0.7.0", "", { "peerDependencies": { "typescript": "5.x", "vue": "^3.4.0" }, "optionalPeers": ["typescript", "vue"] }, "sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg=="], + + "@yankeeinlondon/builder-api": ["@yankeeinlondon/builder-api@1.4.1", "", { "dependencies": { "@types/markdown-it": "^12.2.3", "@yankeeinlondon/happy-wrapper": "^2.10.1", "fp-ts": "^2.13.1", "inferred-types": "^0.37.6", "markdown-it": "^13.0.1", "vite-plugin-md": ">=0.22.5" } }, "sha512-qc6HyfqtuS06FvA5rK0L62Nmc1LnarVOt8/V/mTX2DBZlpTfIDpudpbE/7/kxjme9pP4PFMCk7cPSrprLEorjw=="], + + "@yankeeinlondon/gray-matter": ["@yankeeinlondon/gray-matter@6.2.1", "", { "dependencies": { "inferred-types": "^0.37.6", "js-yaml": "^4.1.0", "kind-of": "^6.0.3", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-ZrHqB3PAin0QmxeNV3Ly3c6IDXKelGGLmGJGWoqwxI1jJjXNU80i6KWsJ0sAhzTg/UIsAtgBFcJkXS7F1ZM6eQ=="], + + "@yankeeinlondon/happy-wrapper": ["@yankeeinlondon/happy-wrapper@2.10.1", "", { "dependencies": { "fp-ts": "^2.13.1", "happy-dom": "^8.1.0", "native-dash": "^1.24.0" } }, "sha512-kS3HT26QSQqcZa8Me2yrb6oc/j0BTmTRR76ITRGcYlO8G1snz9wii1eCrBTx+gAo58P+e3UkxB8PTVrmjTowVA=="], + + "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + + "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], + + "alien-signals": ["alien-signals@1.0.13", "", {}, "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg=="], + + "ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="], + + "ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + + "ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "assertion-error": ["assertion-error@1.1.0", "", {}, "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="], + + "b4a": ["b4a@1.6.7", "", {}, "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "bare-events": ["bare-events@2.5.4", "", {}, "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA=="], + + "bare-fs": ["bare-fs@4.1.2", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-8wSeOia5B7LwD4+h465y73KOdj5QHsbbuoUfPBi+pXgFJIPuG7SsiOdJuijWMyfid49eD+WivpfY7KT8gbAzBA=="], + + "bare-os": ["bare-os@3.6.1", "", {}, "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g=="], + + "bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="], + + "bare-stream": ["bare-stream@2.6.5", "", { "dependencies": { "streamx": "^2.21.0" }, "peerDependencies": { "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-buffer", "bare-events"] }, "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "birpc": ["birpc@0.2.19", "", {}, "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ=="], + + "bl": ["bl@5.1.0", "", { "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ=="], + + "boxen": ["boxen@7.1.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^7.0.1", "chalk": "^5.2.0", "cli-boxes": "^3.0.0", "string-width": "^5.1.2", "type-fest": "^2.13.0", "widest-line": "^4.0.1", "wrap-ansi": "^8.1.0" } }, "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog=="], + + "brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "brilliant-errors": ["brilliant-errors@0.7.3", "", { "dependencies": { "bumpp": "^8.2.1", "callsites": "^4.0.0", "inferred-types": "^0.37.2", "vitest": "^0.25.6" } }, "sha512-WT9BkAze4SUOJfr7LUwJWNDAvynEAvUMvMPuFKu8QQKnRq+WMx3DAtHfOBJjHmHRxf748JY3CNVytSk6HH2yGg=="], + + "browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], + + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + + "buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="], + + "bumpp": ["bumpp@8.2.1", "", { "dependencies": { "@jsdevtools/ez-spawn": "^3.0.4", "cac": "^6.7.12", "fast-glob": "^3.2.11", "kleur": "^4.1.4", "prompts": "^2.4.1", "semver": "^7.3.5" }, "bin": { "bumpp": "bin/bumpp.js" } }, "sha512-4tHKsWC2mqHQvdjZ4AXgVhS2xMsz8qQ4zYt87vGRXW5tqAjrYa/UJqy7s/dGYI2OIe9ghBdiFhKpyKEX9SXffg=="], + + "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], + + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + + "call-me-maybe": ["call-me-maybe@1.0.2", "", {}, "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="], + + "callsites": ["callsites@4.2.0", "", {}, "sha512-kfzR4zzQtAE9PC7CzZsjl3aBNbXWuXiSeOCdLcPpBfGW8YuCqQHcRPFDbr/BPVmd3EEPVpuFzLyuT/cUhPr4OQ=="], + + "camelcase": ["camelcase@7.0.1", "", {}, "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001713", "", {}, "sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q=="], + + "chai": ["chai@4.5.0", "", { "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", "deep-eql": "^4.1.3", "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", "type-detect": "^4.1.0" } }, "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw=="], + + "chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + + "check-error": ["check-error@1.0.3", "", { "dependencies": { "get-func-name": "^2.0.2" } }, "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg=="], + + "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="], + + "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="], + + "cli-cursor": ["cli-cursor@4.0.0", "", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="], + + "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + + "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + + "colorjs.io": ["colorjs.io@0.5.2", "", {}, "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "copy-anything": ["copy-anything@3.0.5", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "de-indent": ["de-indent@1.0.2", "", {}, "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="], + + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], + + "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], + + "deep-eql": ["deep-eql@4.1.4", "", { "dependencies": { "type-detect": "^4.0.0" } }, "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg=="], + + "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], + + "default-browser": ["default-browser@5.2.1", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg=="], + + "default-browser-id": ["default-browser-id@5.0.0", "", {}, "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA=="], + + "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], + + "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.137", "", {}, "sha512-/QSJaU2JyIuTbbABAo/crOs+SuAZLS+fVVS10PVrIT9hrRkmZl8Hb0xPSkKRUUWHQtYzXHpQUW3Dy5hwMzGZkA=="], + + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "end-of-stream": ["end-of-stream@1.4.4", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "error-stack-parser-es": ["error-stack-parser-es@0.1.5", "", {}, "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg=="], + + "esbuild": ["esbuild@0.25.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.2", "@esbuild/android-arm": "0.25.2", "@esbuild/android-arm64": "0.25.2", "@esbuild/android-x64": "0.25.2", "@esbuild/darwin-arm64": "0.25.2", "@esbuild/darwin-x64": "0.25.2", "@esbuild/freebsd-arm64": "0.25.2", "@esbuild/freebsd-x64": "0.25.2", "@esbuild/linux-arm": "0.25.2", "@esbuild/linux-arm64": "0.25.2", "@esbuild/linux-ia32": "0.25.2", "@esbuild/linux-loong64": "0.25.2", "@esbuild/linux-mips64el": "0.25.2", "@esbuild/linux-ppc64": "0.25.2", "@esbuild/linux-riscv64": "0.25.2", "@esbuild/linux-s390x": "0.25.2", "@esbuild/linux-x64": "0.25.2", "@esbuild/netbsd-arm64": "0.25.2", "@esbuild/netbsd-x64": "0.25.2", "@esbuild/openbsd-arm64": "0.25.2", "@esbuild/openbsd-x64": "0.25.2", "@esbuild/sunos-x64": "0.25.2", "@esbuild/win32-arm64": "0.25.2", "@esbuild/win32-ia32": "0.25.2", "@esbuild/win32-x64": "0.25.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "execa": ["execa@9.5.2", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.3", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.0.0" } }, "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q=="], + + "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], + + "extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], + + "fast-fifo": ["fast-fifo@1.3.2", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], + + "filesize": ["filesize@10.1.6", "", {}, "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + + "fp-ts": ["fp-ts@2.16.9", "", {}, "sha512-+I2+FnVB+tVaxcYyQkHUq7ZdKScaBlX53A41mxQtpIccsfyv8PzdzP7fzp2AY832T4aoK6UZ5WRX/ebGd8uZuQ=="], + + "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], + + "fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + + "get-func-name": ["get-func-name@2.0.2", "", {}, "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ=="], + + "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], + + "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="], + + "glob": ["glob@10.4.5", "", { "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" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="], + + "gsap": ["gsap@3.12.7", "", {}, "sha512-V4GsyVamhmKefvcAKaoy0h6si0xX7ogwBoBSs2CTJwt7luW0oZzC0LhdkyuKV8PJAXr7Yaj8pMjCKD4GJ+eEMg=="], + + "happy-dom": ["happy-dom@8.9.0", "", { "dependencies": { "css.escape": "^1.5.1", "he": "^1.2.0", "iconv-lite": "^0.6.3", "node-fetch": "^2.x.x", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0" } }, "sha512-JZwJuGdR7ko8L61136YzmrLv7LgTh5b8XaEM3P709mLjyQuXJ3zHTDXvUtBBahRjGlcYW0zGjIiEWizoTUGKfA=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], + + "highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="], + + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + + "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "immediate": ["immediate@3.0.6", "", {}, "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="], + + "immutable": ["immutable@5.1.1", "", {}, "sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg=="], + + "inferred-types": ["inferred-types@0.37.6", "", { "dependencies": { "brilliant-errors": "^0.7.3" } }, "sha512-CfL5g1wR5rVwX2K5S6wSL+h9eODScum/LBwlhGRrcBIvfYppvUQM0aeRJ1BZS+QE38kGzd3v+U526+nQR7ZUkg=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], + + "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], + + "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + + "is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + + "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + + "is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + + "is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], + + "is-what": ["is-what@4.1.16", "", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="], + + "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], + + "isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-parse-even-better-errors": ["json-parse-even-better-errors@4.0.0", "", {}, "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA=="], + + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="], + + "katex": ["katex@0.6.0", "", { "dependencies": { "match-at": "^0.1.0" }, "bin": { "katex": "cli.js" } }, "sha512-rS4mY3SvHYg5LtQV6RBcK0if7ur6plyEukAOV+jGGPqFImuzu8fHL6M752iBmRGoUyF0bhZbAPoezehn7xYksA=="], + + "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], + + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + + "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], + + "lie": ["lie@3.1.1", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw=="], + + "linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="], + + "local-pkg": ["local-pkg@0.4.3", "", {}, "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g=="], + + "localforage": ["localforage@1.10.0", "", { "dependencies": { "lie": "3.1.1" } }, "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg=="], + + "lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="], + + "log-symbols": ["log-symbols@5.1.0", "", { "dependencies": { "chalk": "^5.0.0", "is-unicode-supported": "^1.1.0" } }, "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA=="], + + "loupe": ["loupe@2.3.7", "", { "dependencies": { "get-func-name": "^2.0.1" } }, "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA=="], + + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + + "markdown-it": ["markdown-it@14.1.0", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg=="], + + "markdown-it-katex": ["markdown-it-katex@2.0.3", "", { "dependencies": { "katex": "^0.6.0" } }, "sha512-nUkkMtRWeg7OpdflamflE/Ho/pWl64Lk9wNBKOmaj33XkQdumhXAIYhI0WO03GeiycPCsxbmX536V5NEXpC3Ng=="], + + "markdown-it-math": ["markdown-it-math@5.2.0", "", { "peerDependencies": { "mathup": "^1.0.0", "temml": "^0.11.0" }, "optionalPeers": ["mathup", "temml"] }, "sha512-K9cnNVUnK42OxDLPwpdiv3nhWfJgCh45FfSkFOirnIa0usBTheRVp2Mv9wKFDy+7RJyoNqsICQ7G8SiojaSbLA=="], + + "match-at": ["match-at@0.1.1", "", {}, "sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q=="], + + "mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="], + + "memorystream": ["memorystream@0.3.1", "", {}, "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], + + "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + + "minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="], + + "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="], + + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], + + "native-dash": ["native-dash@1.25.0", "", { "dependencies": { "brilliant-errors": "^0.7.3", "inferred-types": "^0.37.6" } }, "sha512-vJy1ZEfR/9jpAtuvsbPE/PuaeaJLIS+p7tl/bKEMHutRzMHnmgLv1fSmbyVvL04s2qzg0rCKZX5yfX74uiPLyA=="], + + "node-abi": ["node-abi@3.74.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w=="], + + "node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="], + + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], + + "normalize.css": ["normalize.css@8.0.1", "", {}, "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="], + + "npm-normalize-package-bin": ["npm-normalize-package-bin@4.0.0", "", {}, "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w=="], + + "npm-run-all2": ["npm-run-all2@7.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "cross-spawn": "^7.0.6", "memorystream": "^0.3.1", "minimatch": "^9.0.0", "pidtree": "^0.6.0", "read-package-json-fast": "^4.0.0", "shell-quote": "^1.7.3", "which": "^5.0.0" }, "bin": { "run-p": "bin/run-p/index.js", "run-s": "bin/run-s/index.js", "npm-run-all": "bin/npm-run-all/index.js", "npm-run-all2": "bin/npm-run-all/index.js" } }, "sha512-7tXR+r9hzRNOPNTvXegM+QzCuMjzUIIq66VDunL6j60O4RrExx32XUhlrS7UK4VcdGw5/Wxzb3kfNcFix9JKDA=="], + + "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], + + "open": ["open@10.1.1", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-zy1wx4+P3PfhXSEPJNtZmJXfhkkIaxU1VauWIrDZw1O7uJRDRJtKr9n3Ic4NgbA16KyOxOXO2ng9gYwCdXuSXA=="], + + "ora": ["ora@7.0.1", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^4.0.0", "cli-spinners": "^2.9.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^1.3.0", "log-symbols": "^5.1.0", "stdin-discarder": "^0.1.0", "string-width": "^6.1.0", "strip-ansi": "^7.1.0" } }, "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], + + "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "pathval": ["pathval@1.1.1", "", {}, "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ=="], + + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + + "pidtree": ["pidtree@0.6.0", "", { "bin": { "pidtree": "bin/pidtree.js" } }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="], + + "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + + "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], + + "pretty-ms": ["pretty-ms@9.2.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg=="], + + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + + "pump": ["pump@3.0.2", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw=="], + + "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], + + "read-package-json-fast": ["read-package-json-fast@4.0.0", "", { "dependencies": { "json-parse-even-better-errors": "^4.0.0", "npm-normalize-package-bin": "^4.0.0" } }, "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg=="], + + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "restore-cursor": ["restore-cursor@4.0.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + + "rollup": ["rollup@4.40.0", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.40.0", "@rollup/rollup-android-arm64": "4.40.0", "@rollup/rollup-darwin-arm64": "4.40.0", "@rollup/rollup-darwin-x64": "4.40.0", "@rollup/rollup-freebsd-arm64": "4.40.0", "@rollup/rollup-freebsd-x64": "4.40.0", "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", "@rollup/rollup-linux-arm-musleabihf": "4.40.0", "@rollup/rollup-linux-arm64-gnu": "4.40.0", "@rollup/rollup-linux-arm64-musl": "4.40.0", "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", "@rollup/rollup-linux-riscv64-gnu": "4.40.0", "@rollup/rollup-linux-riscv64-musl": "4.40.0", "@rollup/rollup-linux-s390x-gnu": "4.40.0", "@rollup/rollup-linux-x64-gnu": "4.40.0", "@rollup/rollup-linux-x64-musl": "4.40.0", "@rollup/rollup-win32-arm64-msvc": "4.40.0", "@rollup/rollup-win32-ia32-msvc": "4.40.0", "@rollup/rollup-win32-x64-msvc": "4.40.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w=="], + + "run-applescript": ["run-applescript@7.0.0", "", {}, "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "sass-embedded": ["sass-embedded@1.86.3", "", { "dependencies": { "@bufbuild/protobuf": "^2.0.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-android-arm": "1.86.3", "sass-embedded-android-arm64": "1.86.3", "sass-embedded-android-ia32": "1.86.3", "sass-embedded-android-riscv64": "1.86.3", "sass-embedded-android-x64": "1.86.3", "sass-embedded-darwin-arm64": "1.86.3", "sass-embedded-darwin-x64": "1.86.3", "sass-embedded-linux-arm": "1.86.3", "sass-embedded-linux-arm64": "1.86.3", "sass-embedded-linux-ia32": "1.86.3", "sass-embedded-linux-musl-arm": "1.86.3", "sass-embedded-linux-musl-arm64": "1.86.3", "sass-embedded-linux-musl-ia32": "1.86.3", "sass-embedded-linux-musl-riscv64": "1.86.3", "sass-embedded-linux-musl-x64": "1.86.3", "sass-embedded-linux-riscv64": "1.86.3", "sass-embedded-linux-x64": "1.86.3", "sass-embedded-win32-arm64": "1.86.3", "sass-embedded-win32-ia32": "1.86.3", "sass-embedded-win32-x64": "1.86.3" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-3pZSp24ibO1hdopj+W9DuiWsZOb2YY6AFRo/jjutKLBkqJGM1nJjXzhAYfzRV+Xn5BX1eTI4bBTE09P0XNHOZg=="], + + "sass-embedded-android-arm": ["sass-embedded-android-arm@1.86.3", "", { "os": "android", "cpu": "arm" }, "sha512-UyeXrFzZSvrGbvrWUBcspbsbivGgAgebLGJdSqJulgSyGbA6no3DWQ5Qpdd6+OAUC39BlpPu74Wx9s4RrVuaFw=="], + + "sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.86.3", "", { "os": "android", "cpu": "arm64" }, "sha512-q+XwFp6WgAv+UgnQhsB8KQ95kppvWAB7DSoJp+8Vino8b9ND+1ai3cUUZPE5u4SnLZrgo5NtrbPvN5KLc4Pfyg=="], + + "sass-embedded-android-ia32": ["sass-embedded-android-ia32@1.86.3", "", { "os": "android", "cpu": "ia32" }, "sha512-gTJjVh2cRzvGujXj5ApPk/owUTL5SiO7rDtNLrzYAzi1N5HRuLYXqk3h1IQY3+eCOBjGl7mQ9XyySbJs/3hDvg=="], + + "sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.86.3", "", { "os": "android", "cpu": "none" }, "sha512-Po3JnyiCS16kd6REo1IMUbFGYtvL9O0rmKaXx5vOuBaJD1LPy2LiSSp7TU7wkJ9IxsTDGzFaSeP1I9qb6D8VVg=="], + + "sass-embedded-android-x64": ["sass-embedded-android-x64@1.86.3", "", { "os": "android", "cpu": "x64" }, "sha512-+7h3jdDv/0kUFx0BvxYlq2fa7CcHiDPlta6k5OxO5K6jyqJwo9hc0Z052BoYEauWTqZ+vK6bB5rv2BIzq4U9nA=="], + + "sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.86.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EgLwV4ORm5Hr0DmIXo0Xw/vlzwLnfAiqD2jDXIglkBsc5czJmo4/IBdGXOP65TRnsgJEqvbU3aQhuawX5++x9A=="], + + "sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.86.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-dfKhfrGPRNLWLC82vy/vQGmNKmAiKWpdFuWiePRtg/E95pqw+sCu6080Y6oQLfFu37Iq3MpnXiSpDuSo7UnPWA=="], + + "sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.86.3", "", { "os": "linux", "cpu": "arm" }, "sha512-+fVCIH+OR0SMHn2NEhb/VfbpHuUxcPtqMS34OCV3Ka99LYZUJZqth4M3lT/ppGl52mwIVLNYzR4iLe6mdZ6mYA=="], + + "sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.86.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-tYq5rywR53Qtc+0KI6pPipOvW7a47ETY69VxfqI9BR2RKw2hBbaz0bIw6OaOgEBv2/XNwcWb7a4sr7TqgkqKAA=="], + + "sass-embedded-linux-ia32": ["sass-embedded-linux-ia32@1.86.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-CmQ5OkqnaeLdaF+bMqlYGooBuenqm3LvEN9H8BLhjkpWiFW8hnYMetiqMcJjhrXLvDw601KGqA5sr/Rsg5s45g=="], + + "sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.86.3", "", { "os": "linux", "cpu": "arm" }, "sha512-SEm65SQknI4pl+mH5Xf231hOkHJyrlgh5nj4qDbiBG6gFeutaNkNIeRgKEg3cflXchCr8iV/q/SyPgjhhzQb7w=="], + + "sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.86.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-4zOr2C/eW89rxb4ozTfn7lBzyyM5ZigA1ZSRTcAR26Qbg/t2UksLdGnVX9/yxga0d6aOi0IvO/7iM2DPPRRotg=="], + + "sass-embedded-linux-musl-ia32": ["sass-embedded-linux-musl-ia32@1.86.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-84Tcld32LB1loiqUvczWyVBQRCChm0wNLlkT59qF29nxh8njFIVf9yaPgXcSyyjpPoD9Tu0wnq3dvVzoMCh9AQ=="], + + "sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.86.3", "", { "os": "linux", "cpu": "none" }, "sha512-IxEqoiD7vdNpiOwccybbV93NljBy64wSTkUOknGy21SyV43C8uqESOwTwW9ywa3KufImKm8L3uQAW/B0KhJMWg=="], + + "sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.86.3", "", { "os": "linux", "cpu": "x64" }, "sha512-ePeTPXUxPK6JgHcUfnrkIyDtyt+zlAvF22mVZv6y1g/PZFm1lSfX+Za7TYHg9KaYqaaXDiw6zICX4i44HhR8rA=="], + + "sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.86.3", "", { "os": "linux", "cpu": "none" }, "sha512-NuXQ72dwfNLe35E+RaXJ4Noq4EkFwM65eWwCwxEWyJO9qxOx1EXiCAJii6x8kkOh5daWuMU0VAI1B9RsJaqqQQ=="], + + "sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.86.3", "", { "os": "linux", "cpu": "x64" }, "sha512-t8be9zJ5B82+og9bQmIQ83yMGYZMTMrlGA+uGWtYacmwg6w3093dk91Fx0YzNSZBp3Tk60qVYjCZnEIwy60x0g=="], + + "sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.86.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-4ghuAzjX4q8Nksm0aifRz8hgXMMxS0SuymrFfkfJlrSx68pIgvAge6AOw0edoZoe0Tf5ZbsWUWamhkNyNxkTvw=="], + + "sass-embedded-win32-ia32": ["sass-embedded-win32-ia32@1.86.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-tCaK4zIRq9mLRPxLzBAdYlfCuS/xLNpmjunYxeWkIwlJo+k53h1udyXH/FInnQ2GgEz0xMXyvH3buuPgzwWYsw=="], + + "sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.86.3", "", { "os": "win32", "cpu": "x64" }, "sha512-zS+YNKfTF4SnOfpC77VTb0qNZyTXrxnAezSoRV0xnw6HlY+1WawMSSB6PbWtmbvyfXNgpmJUttoTtsvJjRCucg=="], + + "section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="], + + "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "sharp": ["sharp@0.32.6", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.2", "node-addon-api": "^6.1.0", "prebuild-install": "^7.1.1", "semver": "^7.5.4", "simple-get": "^4.0.1", "tar-fs": "^3.0.4", "tunnel-agent": "^0.6.0" } }, "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "shell-quote": ["shell-quote@1.8.2", "", {}, "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="], + + "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="], + + "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], + + "sirv": ["sirv@3.0.1", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A=="], + + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "speakingurl": ["speakingurl@14.0.1", "", {}, "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="], + + "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], + + "stdin-discarder": ["stdin-discarder@0.1.0", "", { "dependencies": { "bl": "^5.0.0" } }, "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ=="], + + "streamx": ["streamx@2.22.0", "", { "dependencies": { "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" }, "optionalDependencies": { "bare-events": "^2.2.0" } }, "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw=="], + + "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], + + "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="], + + "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], + + "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], + + "strip-literal": ["strip-literal@1.3.0", "", { "dependencies": { "acorn": "^8.10.0" } }, "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg=="], + + "superjson": ["superjson@2.2.2", "", { "dependencies": { "copy-anything": "^3.0.2" } }, "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q=="], + + "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "sync-child-process": ["sync-child-process@1.0.2", "", { "dependencies": { "sync-message-port": "^1.0.0" } }, "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA=="], + + "sync-message-port": ["sync-message-port@1.1.3", "", {}, "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg=="], + + "tar-fs": ["tar-fs@3.0.8", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg=="], + + "tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="], + + "text-decoder": ["text-decoder@1.2.3", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="], + + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + + "tinypool": ["tinypool@0.3.1", "", {}, "sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ=="], + + "tinyspy": ["tinyspy@1.1.1", "", {}, "sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], + + "type-detect": ["type-detect@4.1.0", "", {}, "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw=="], + + "type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], + + "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + + "uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], + + "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="], + + "vite": ["vite@6.2.6", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw=="], + + "vite-hot-client": ["vite-hot-client@0.2.4", "", { "peerDependencies": { "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0" } }, "sha512-a1nzURqO7DDmnXqabFOliz908FRmIppkBKsJthS8rbe8hBEXwEwe4C3Pp33Z1JoFCYfVL4kTOMLKk0ZZxREIeA=="], + + "vite-plugin-inspect": ["vite-plugin-inspect@0.8.9", "", { "dependencies": { "@antfu/utils": "^0.7.10", "@rollup/pluginutils": "^5.1.3", "debug": "^4.3.7", "error-stack-parser-es": "^0.1.5", "fs-extra": "^11.2.0", "open": "^10.1.0", "perfect-debounce": "^1.0.0", "picocolors": "^1.1.1", "sirv": "^3.0.0" }, "peerDependencies": { "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1" } }, "sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A=="], + + "vite-plugin-md": ["vite-plugin-md@0.21.5", "", { "dependencies": { "@yankeeinlondon/builder-api": "^1.2.1", "@yankeeinlondon/gray-matter": "^6.1.0", "@yankeeinlondon/happy-wrapper": "^2.10.1", "markdown-it": "^13.0.1", "source-map-js": "^1.0.2" }, "peerDependencies": { "vite": "^4.0.0" } }, "sha512-gxiiSq2PmU2zUY5ZAFLEGmDFRV6J6gF85ns3hcvtgERibNST4gWxRSabqSZbGbHp3LEBwwK7C1CRLsl46yEiWg=="], + + "vite-plugin-minipic": ["vite-plugin-minipic@1.3.0", "", { "dependencies": { "@rollup/pluginutils": "^5.0.3", "boxen": "^7.1.1", "chalk": "^5.3.0", "filesize": "^10.0.12", "glob": "^10.3.10", "lodash-es": "^4.17.21", "ora": "^7.0.1", "rollup": "^4.40.0", "sharp": "^0.32.4" } }, "sha512-iSfqsXqxDg0NZW+3UrSG9PkLjL2DbleDoXeI5jd48kze770bOuJa4WhH4/OYhaDvy8jaCTSVeV5jmDksIcXh+w=="], + + "vite-plugin-vue-devtools": ["vite-plugin-vue-devtools@7.7.2", "", { "dependencies": { "@vue/devtools-core": "^7.7.2", "@vue/devtools-kit": "^7.7.2", "@vue/devtools-shared": "^7.7.2", "execa": "^9.5.1", "sirv": "^3.0.0", "vite-plugin-inspect": "0.8.9", "vite-plugin-vue-inspector": "^5.3.1" }, "peerDependencies": { "vite": "^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0" } }, "sha512-5V0UijQWiSBj32blkyPEqIbzc6HO9c1bwnBhx+ay2dzU0FakH+qMdNUT8nF9BvDE+i6I1U8CqCuJiO20vKEdQw=="], + + "vite-plugin-vue-inspector": ["vite-plugin-vue-inspector@5.3.1", "", { "dependencies": { "@babel/core": "^7.23.0", "@babel/plugin-proposal-decorators": "^7.23.0", "@babel/plugin-syntax-import-attributes": "^7.22.5", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-transform-typescript": "^7.22.15", "@vue/babel-plugin-jsx": "^1.1.5", "@vue/compiler-dom": "^3.3.4", "kolorist": "^1.8.0", "magic-string": "^0.30.4" }, "peerDependencies": { "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0" } }, "sha512-cBk172kZKTdvGpJuzCCLg8lJ909wopwsu3Ve9FsL1XsnLBiRT9U3MePcqrgGHgCX2ZgkqZmAGR8taxw+TV6s7A=="], + + "vitest": ["vitest@0.25.8", "", { "dependencies": { "@types/chai": "^4.3.4", "@types/chai-subset": "^1.3.3", "@types/node": "*", "acorn": "^8.8.1", "acorn-walk": "^8.2.0", "chai": "^4.3.7", "debug": "^4.3.4", "local-pkg": "^0.4.2", "source-map": "^0.6.1", "strip-literal": "^1.0.0", "tinybench": "^2.3.1", "tinypool": "^0.3.0", "tinyspy": "^1.0.2", "vite": "^3.0.0 || ^4.0.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@vitest/browser": "*", "@vitest/ui": "*", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg=="], + + "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], + + "vue": ["vue@3.5.13", "", { "dependencies": { "@vue/compiler-dom": "3.5.13", "@vue/compiler-sfc": "3.5.13", "@vue/runtime-dom": "3.5.13", "@vue/server-renderer": "3.5.13", "@vue/shared": "3.5.13" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ=="], + + "vue-router": ["vue-router@4.5.0", "", { "dependencies": { "@vue/devtools-api": "^6.6.4" }, "peerDependencies": { "vue": "^3.2.0" } }, "sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w=="], + + "vue-tsc": ["vue-tsc@2.2.8", "", { "dependencies": { "@volar/typescript": "~2.4.11", "@vue/language-core": "2.2.8" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": { "vue-tsc": "./bin/vue-tsc.js" } }, "sha512-jBYKBNFADTN+L+MdesNX/TB3XuDSyaWynKMDgR+yCSln0GQ9Tfb7JS2lr46s2LiFUT1WsmfWsSvIElyxzOPqcQ=="], + + "webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="], + + "whatwg-encoding": ["whatwg-encoding@2.0.0", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg=="], + + "whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], + + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], + + "widest-line": ["widest-line@4.0.1", "", { "dependencies": { "string-width": "^5.0.1" } }, "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + + "yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="], + + "@vue/devtools-core/nanoid": ["nanoid@5.1.5", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw=="], + + "@yankeeinlondon/builder-api/markdown-it": ["markdown-it@13.0.2", "", { "dependencies": { "argparse": "^2.0.1", "entities": "~3.0.1", "linkify-it": "^4.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" }, "bin": { "markdown-it": "bin/markdown-it.js" } }, "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w=="], + + "@yankeeinlondon/builder-api/vite-plugin-md": ["vite-plugin-md@0.22.5", "", { "dependencies": { "@yankeeinlondon/builder-api": "^1.3.4", "@yankeeinlondon/gray-matter": "^6.1.1", "@yankeeinlondon/happy-wrapper": "^2.10.1", "markdown-it": "^13.0.1", "source-map-js": "^1.0.2" }, "peerDependencies": { "@vitejs/plugin-vue": ">=2.3.4", "vite": "^4.0.0 || ^3.0.0" } }, "sha512-ex6yQfan2teBT2uMzoIlDHRhKTOsNiyvblA9eLU/+uygpg4KikJPFeyBX300LqQ3pZ9qGHz35qoGJ0oLw47eZg=="], + + "@yankeeinlondon/gray-matter/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "bumpp/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], + + "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "figures/is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], + + "js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "node-abi/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], + + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + + "ora/string-width": ["string-width@6.1.0", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^10.2.1", "strip-ansi": "^7.0.1" } }, "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ=="], + + "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "prebuild-install/tar-fs": ["tar-fs@2.1.2", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA=="], + + "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "sharp/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "vite-plugin-md/markdown-it": ["markdown-it@13.0.2", "", { "dependencies": { "argparse": "^2.0.1", "entities": "~3.0.1", "linkify-it": "^4.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" }, "bin": { "markdown-it": "bin/markdown-it.js" } }, "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w=="], + + "vitest/vite": ["vite@4.5.13", "", { "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", "rollup": "^3.27.1" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-Hgp8IF/yZDzKsN1hQWOuQZbrKiaFsbQud+07jJ8h9m9PaHWkpvZ5u55Xw5yYjWRXwRQ4jwFlJvY7T7FUJG9MCA=="], + + "whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@yankeeinlondon/builder-api/markdown-it/entities": ["entities@3.0.1", "", {}, "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q=="], + + "@yankeeinlondon/builder-api/markdown-it/linkify-it": ["linkify-it@4.0.1", "", { "dependencies": { "uc.micro": "^1.0.1" } }, "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw=="], + + "@yankeeinlondon/builder-api/markdown-it/mdurl": ["mdurl@1.0.1", "", {}, "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="], + + "@yankeeinlondon/builder-api/markdown-it/uc.micro": ["uc.micro@1.0.6", "", {}, "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="], + + "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "ora/string-width/emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="], + + "prebuild-install/tar-fs/tar-stream": ["tar-stream@2.2.0", "", { "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" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], + + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "vite-plugin-md/markdown-it/entities": ["entities@3.0.1", "", {}, "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q=="], + + "vite-plugin-md/markdown-it/linkify-it": ["linkify-it@4.0.1", "", { "dependencies": { "uc.micro": "^1.0.1" } }, "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw=="], + + "vite-plugin-md/markdown-it/mdurl": ["mdurl@1.0.1", "", {}, "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="], + + "vite-plugin-md/markdown-it/uc.micro": ["uc.micro@1.0.6", "", {}, "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="], + + "vitest/vite/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], + + "vitest/vite/rollup": ["rollup@3.29.5", "", { "optionalDependencies": { "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w=="], + + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "prebuild-install/tar-fs/tar-stream/bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + + "vitest/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], + + "vitest/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], + + "vitest/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="], + + "vitest/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="], + + "vitest/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="], + + "vitest/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="], + + "vitest/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="], + + "vitest/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="], + + "vitest/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="], + + "vitest/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="], + + "vitest/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="], + + "vitest/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="], + + "vitest/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="], + + "vitest/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="], + + "vitest/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="], + + "vitest/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="], + + "vitest/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="], + + "vitest/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="], + + "vitest/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="], + + "vitest/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="], + + "vitest/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="], + + "vitest/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], + + "prebuild-install/tar-fs/tar-stream/bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + } +} diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 0000000..06b8499 --- /dev/null +++ b/env.d.ts @@ -0,0 +1,13 @@ +/// +declare module '*.md' { + import type { ComponentOptions } from 'vue' + import type { Frontmatter } from 'vite-plugin-md' + const Component: ComponentOptions + export default Component + export const frontmatter: Frontmatter +} + +type MdModule = { + default: ComponentOptions; + frontmatter: Frontmatter; +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..acea9c1 --- /dev/null +++ b/index.html @@ -0,0 +1,17 @@ + + + + + + + + + + 学习中的鹅 + + +
+ + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..8a93f5b --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "home-page", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build" + }, + "dependencies": { + "gray-matter": "^4.0.3", + "gsap": "^3.12.7", + "highlight.js": "^11.11.1", + "localforage": "^1.10.0", + "markdown-it": "^14.1.0", + "markdown-it-katex": "^2.0.3", + "markdown-it-math": "^5.2.0", + "normalize.css": "^8.0.1", + "vue": "^3.5.13", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.1", + "@types/node": "^22.14.0", + "@vitejs/plugin-vue": "^5.2.3", + "@vitejs/plugin-vue-jsx": "^4.1.2", + "@vue/tsconfig": "^0.7.0", + "npm-run-all2": "^7.0.2", + "sass-embedded": "^1.86.3", + "typescript": "~5.8.0", + "vite": "^6.2.4", + "vite-plugin-md": "^0.21.5", + "vite-plugin-minipic": "^1.3.0", + "vite-plugin-vue-devtools": "^7.7.2", + "vue-tsc": "^2.2.8" + } +} diff --git a/public/icon.png b/public/icon.png new file mode 100644 index 0000000..fee3f52 Binary files /dev/null and b/public/icon.png differ diff --git a/public/resources/Battleship/基于NodeJS和WebSocket的在线航海棋游戏的设计与实现.pdf b/public/resources/Battleship/基于NodeJS和WebSocket的在线航海棋游戏的设计与实现.pdf new file mode 100644 index 0000000..0fc79a6 Binary files /dev/null and b/public/resources/Battleship/基于NodeJS和WebSocket的在线航海棋游戏的设计与实现.pdf differ diff --git a/public/resources/Phy-exp/ball-track-rl1.mp4 b/public/resources/Phy-exp/ball-track-rl1.mp4 new file mode 100644 index 0000000..9eba3b7 Binary files /dev/null and b/public/resources/Phy-exp/ball-track-rl1.mp4 differ diff --git a/public/resources/Phy-exp/report0329.html b/public/resources/Phy-exp/report0329.html new file mode 100644 index 0000000..6c04d8e --- /dev/null +++ b/public/resources/Phy-exp/report0329.html @@ -0,0 +1,783 @@ + + + + + + 单摆实验重力加速度测量分析 + + +
+
+
+

+ 单摆实验重力加速度测量分析

+
+

实验摘要

+
+
+

平均重力加速度

+

9.7576 ± 0.0147 m/s²

+

从四次实验计算的平均值(95%置信区间) +

+

标准差: 0.0147 m/s² +

+

相对标准值误差: 0.43%

+
+

计算方法: σ = √[Σ(x_i - x̄)² / (n-1)]

+

g₁ = 9.7498, g₂ = 9.7746, g₃ = 9.7411, g₄ = + 9.7650

+

平均值 = (g₁+g₂+g₃+g₄)/4 = 9.7576 m/s²

+
+
+
+

线性拟合计算的重力加速度 +

+

9.9063 ± 0.0121 m/s²

+

从T²与L的线性关系计算(基于拟合误差) +

+

拟合标准误差: 0.0017

+

相对标准值误差: 1.08%

+
+

计算方法: g = 4π²/斜率

+

斜率 = 3.9852 ± 0.0034

+

拟合优度 R² = 1.0000

+
+
+
+
+

拟合方程

+

T² = 3.9852L + 0.0404 (R² = 1.0000)

+

根据 T² = (4π²/g)L + b 理论模型拟合 +

+

标准重力加速度: 9.8000 m/s² +

+

平均测量值与标准值比较: 9.7576 vs. + 9.8000 (Δ = 42.4 mm/s²)

+
+
+
+

T² 与摆长 L + 的关系

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.39m + + + + + + + 0.455m + + + + + 0.52m + + + + + + + 0.585m + + + + + 0.65m + + + + + 摆长 L (m) + + + + + + + + 1.5s² + + + + + + 1.8s² + + + + + + 2.1s² + + + + + + + 2.4s² + + + + + + + 2.7s² + + + + + T² (s²) + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
    +
  • + + + + + + 实验数据 +
  • +
+
+ +
+
+
+
+

根据简单摆的理论,T² 与 L 呈线性关系:T² = + (4π²/g)L,拟合线的斜率为 3.9852, 通过公式 g = 4π²/slope 计算得到重力加速度为 + 9.9063 m/s²。

+
+
+
+

实验数据详情

+

1. 基本参数

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
实验编号摆长 (m)周期 (s)周期平方 (s²)角频率 (rad/s)初始振幅 (rad)相位 (rad)周期数量
10.5490 + 1.4921 + 2.2264 + 4.2111 + 0.1559 + -0.5596 + 294 +
20.4040 + 1.2846 + 1.6502 + 4.8911 + 0.3166 + 1.6707 + 273 +
30.4480 + 1.3516 + 1.8268 + 4.6487 + 0.2821 + -2.1701 + 273 +
40.6180 + 1.5825 + 2.5043 + 3.9704 + 0.2183 + -1.7966 + 360 +
+
+

2. 阻尼参数

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
实验编号阻尼系数 γ (s⁻¹)相对阻尼系数 b/m (s⁻¹) + γ 的标准差
10.0023 + 0.0046 + + 0.000008
20.0026 + 0.0051 + + 0.000065
30.0025 + 0.0050 + + 0.000023
40.0022 + 0.0044 + + 0.000007
+
+

3. 重力加速度计算

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
实验编号拟合得到的重力加速度 (m/s²) + 无阻尼情况下的重力加速度 (m/s²) + 全面修正后的重力加速度 (m/s²) + 最大偏差 (%)
19.7355 + 9.7355 + 9.7498 + 2.24 +
29.6648 + 9.6648 + 9.7746 + 4.17 +
39.6815 + 9.6815 + 9.7411 + 2.48 +
49.7421 + 9.7421 + 9.7650 + 2.13 +
+
+

4. 像素与坐标数据

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
实验编号摆长 (像素)实际摆长 (mm)像素到毫米转换系数支点坐标 X (像素)支点坐标 Y (像素)
13090.06 + 549 + + 0.1776661375.41 + + -2630.58
21954.91 + 404 + + 0.2066591270.15 + + -1675.48
32608.85 + 448 + + 0.1717231370.59 + + -2360.96
43413.14 + 618 + + 0.1810651458.18 + + -2939.74
+
+
+
+

实验分析与结论 +

+
+

1. 重力加速度测量结果

+
    +
  • 四次实验测量的重力加速度平均值为 9.7576 m/s²
  • +
  • 通过T²与L线性关系拟合计算的重力加速度为 9.9063 m/s² +
  • +
  • 理论标准值约为 9.8 m/s²,相对误差分别为 0.43% 和 -1.08%
  • +
+
+
+

2. 线性关系验证

+

理论上,T²与L应当呈线性关系,且截距应接近于0。实验拟合得到:

+
    +
  • 拟合方程: T² = 3.9852L + 0.0404
  • +
  • 拟合优度 R² = 1.0000,表明数据与线性模型拟合良好
  • +
  • 截距 0.0404 接近于0,符合理论预期
  • +
+
+
+

3. 阻尼效应分析

+
    +
  • 四次实验的阻尼系数在 0.0022 - 0.0026 s⁻¹ 范围内
  • +
  • 相对阻尼系数 (b/m) 在 0.0044 - 0.0051 s⁻¹ 范围内
  • +
  • 阻尼效应导致的周期修正已在实验计算中考虑
  • +
+
+
+

4. 误差来源分析

+
    +
  • 摆长测量误差:摆长的准确测量是影响结果的关键因素
  • +
  • 大摆角效应:初始振幅的大小会影响周期,本实验中已进行修正
  • +
  • 支点摩擦:可能导致额外的阻尼和能量损失
  • +
  • 摆球的非点质量特性:实际摆球具有体积和转动惯量
  • +
+
+
+

5. 总结

+

本实验通过四个不同摆长的单摆实验,得到了与理论预期相符的结果。实验中考虑了阻尼效应和大摆角修正, + 测得的重力加速度与理论值接近,相对误差小于2%。T²与L的线性关系得到了很好的验证,拟合优度R²接近1, + 表明实验数据质量良好。

+
+
+
+
+
\ No newline at end of file diff --git a/public/resources/Phy-exp/屏幕录制 2025-03-15 080119.mp4 b/public/resources/Phy-exp/屏幕录制 2025-03-15 080119.mp4 new file mode 100644 index 0000000..b388b5e Binary files /dev/null and b/public/resources/Phy-exp/屏幕录制 2025-03-15 080119.mp4 differ diff --git a/public/resources/Phy-exp/手机检测demo.mp4 b/public/resources/Phy-exp/手机检测demo.mp4 new file mode 100644 index 0000000..fbee00d Binary files /dev/null and b/public/resources/Phy-exp/手机检测demo.mp4 differ diff --git a/public/resources/Weather-clock/ESP8266介绍视频.mp4 b/public/resources/Weather-clock/ESP8266介绍视频.mp4 new file mode 100644 index 0000000..e603633 Binary files /dev/null and b/public/resources/Weather-clock/ESP8266介绍视频.mp4 differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..afd4354 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/src/assets/NotoSerifSC-VariableFont_wght.woff2 b/src/assets/NotoSerifSC-VariableFont_wght.woff2 new file mode 100644 index 0000000..310c1d7 Binary files /dev/null and b/src/assets/NotoSerifSC-VariableFont_wght.woff2 differ diff --git a/src/assets/fonts.css b/src/assets/fonts.css new file mode 100644 index 0000000..d15490a --- /dev/null +++ b/src/assets/fonts.css @@ -0,0 +1,8 @@ +/* @font-face { + font-family: 'NotoSerifSC'; + src: url('./NotoSerifSC-VariableFont_wght.woff2') format('woff2'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + */ \ No newline at end of file diff --git a/src/assets/img/Illustration_1.png b/src/assets/img/Illustration_1.png new file mode 100644 index 0000000..492e2ce Binary files /dev/null and b/src/assets/img/Illustration_1.png differ diff --git a/src/assets/img/Illustration_1.psd b/src/assets/img/Illustration_1.psd new file mode 100644 index 0000000..9a4ea3b Binary files /dev/null and b/src/assets/img/Illustration_1.psd differ diff --git a/src/assets/img/Illustration_2.png b/src/assets/img/Illustration_2.png new file mode 100644 index 0000000..9b3b275 Binary files /dev/null and b/src/assets/img/Illustration_2.png differ diff --git a/src/assets/img/Illustration_3.png b/src/assets/img/Illustration_3.png new file mode 100644 index 0000000..0aa214d Binary files /dev/null and b/src/assets/img/Illustration_3.png differ diff --git a/src/assets/img/Illustration_3.psd b/src/assets/img/Illustration_3.psd new file mode 100644 index 0000000..e416089 Binary files /dev/null and b/src/assets/img/Illustration_3.psd differ diff --git a/src/assets/img/Illustration_4.png b/src/assets/img/Illustration_4.png new file mode 100644 index 0000000..f734eeb Binary files /dev/null and b/src/assets/img/Illustration_4.png differ diff --git a/src/assets/img/Illustration_4.psd b/src/assets/img/Illustration_4.psd new file mode 100644 index 0000000..bbd734c Binary files /dev/null and b/src/assets/img/Illustration_4.psd differ diff --git a/src/assets/img/Illustration_5.png b/src/assets/img/Illustration_5.png new file mode 100644 index 0000000..059d4db Binary files /dev/null and b/src/assets/img/Illustration_5.png differ diff --git a/src/assets/img/Illustration_5.psd b/src/assets/img/Illustration_5.psd new file mode 100644 index 0000000..1eb1cc5 Binary files /dev/null and b/src/assets/img/Illustration_5.psd differ diff --git a/src/assets/img/Logo.psd b/src/assets/img/Logo.psd new file mode 100644 index 0000000..59144c7 Binary files /dev/null and b/src/assets/img/Logo.psd differ diff --git a/src/assets/img/Logo_bg.png b/src/assets/img/Logo_bg.png new file mode 100644 index 0000000..2809b3e Binary files /dev/null and b/src/assets/img/Logo_bg.png differ diff --git a/src/assets/img/Logo_transparent.png b/src/assets/img/Logo_transparent.png new file mode 100644 index 0000000..ef54989 Binary files /dev/null and b/src/assets/img/Logo_transparent.png differ diff --git a/src/assets/img/NotFound.png b/src/assets/img/NotFound.png new file mode 100644 index 0000000..c934d8f Binary files /dev/null and b/src/assets/img/NotFound.png differ diff --git a/src/assets/img/Paper.png b/src/assets/img/Paper.png new file mode 100644 index 0000000..77eac80 Binary files /dev/null and b/src/assets/img/Paper.png differ diff --git a/src/assets/img/Paper.psd b/src/assets/img/Paper.psd new file mode 100644 index 0000000..60eb9dc Binary files /dev/null and b/src/assets/img/Paper.psd differ diff --git a/src/assets/img/Paper_dark.png b/src/assets/img/Paper_dark.png new file mode 100644 index 0000000..c0f7b23 Binary files /dev/null and b/src/assets/img/Paper_dark.png differ diff --git a/src/assets/img/Paper_dark.psd b/src/assets/img/Paper_dark.psd new file mode 100644 index 0000000..9f4dfdc Binary files /dev/null and b/src/assets/img/Paper_dark.psd differ diff --git a/src/assets/main.scss b/src/assets/main.scss new file mode 100644 index 0000000..fd6274f --- /dev/null +++ b/src/assets/main.scss @@ -0,0 +1,105 @@ +@use "sass:color"; + +@import url('./fonts.css'); + + +// 定义颜色变量和提亮函数 +@function lighten-for-dark($color, $amount: 15%) { + @return color.adjust($color, $lightness: $amount); +} + +// 基础颜色变量 +$blue: #3498db; +$brown: #645b21; +$orange: #DF8146; + +:root { + // 默认亮色模式 + --color-border: #000000; + --text-color: #000000; + --text-color-disabled: #999999; + --text-color-gray: #666666; + + --text-color-blue: #{$blue}; + --text-color-brown: #{$brown}; + --text-color-orange: #{$orange}; + + --border: solid 0.0625rem var(--color-border); + --border-radius: 0.25rem; + + // 黑暗模式媒体查询 + @media (prefers-color-scheme: dark) { + --color-border: #ffffff; + --text-color: #ffffff; + --text-color-disabled: #999999; + --text-color-gray: #cccccc; + + // 自动提亮颜色 + --text-color-blue: #{lighten-for-dark($blue, 20%)}; + --text-color-brown: #{lighten-for-dark($brown, 30%)}; + --text-color-orange: #{lighten-for-dark($orange, 15%)}; + + } + + @media screen and (max-width: 420px) { + font-size: 14px; + } +} + +body { + margin: 0; + background-image: url('./img/Paper.png'); + background-size: contain; + font-family: 'Noto Serif SC Variable', 'Times New Roman', Times, serif; + color: var(--text-color); + line-height: 1.5; + + @media (prefers-color-scheme: dark) { + background-image: url('./img/Paper_dark.png'); + } +} + + + +button { + height: 3rem; + border: var(--border); + border-radius: var(--border-radius); + background-color: transparent; + color: var(--text-color); + cursor: pointer; +} + +button:disabled { + cursor: not-allowed; + border-radius: var(--border-radius); + background-color: transparent; + color: var(--text-color-disabled); + border-color: var(--text-color-disabled); +} + +select { + height: 2.5rem; + width: 10rem; +} + +* { + box-sizing: border-box; +} + + +a { + color: var(--text-color); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +#app { + display: flex; + flex-direction: column; + min-height: 100dvh; + min-height: 100vh; +} \ No newline at end of file diff --git a/src/assets/markdown.scss b/src/assets/markdown.scss new file mode 100644 index 0000000..e38e5f5 --- /dev/null +++ b/src/assets/markdown.scss @@ -0,0 +1,77 @@ +.markdown-body { + line-height: 1.7; + padding: 0 2rem 4rem; + margin: 0 auto; + max-width: 70rem; + font-size: 1.1rem; + + + a { + color: var(--text-color-gray); + font-size: small; + } + + img { + max-width: 100%; + height: auto; + margin: 0 auto; + display: block; + } + + table { + width: 100%; + border-collapse: collapse; + margin: 1em 0; + + th, + td { + padding: 0.5em; + border: 1px solid #ddd; + } + } + + + + mtext { + display: flex; + } + + li { + margin-block-start: .7em; + margin-block-end: .7em; + } + + h1 { + text-align: center; + } + + blockquote { + border-left: 4px solid var(--text-color-gray); + border-left: 4px solid rgb(from var(--text-color-gray) r g b / 0.5); + margin-block-start: 1rem; + margin-block-end: 1rem; + padding-inline-start: 1.5rem; + margin-inline-start: .5rem; + unicode-bidi: isolate; + } + + pre{ + background-color: rgb(from var(--text-color-gray) r g b / 0.05); + padding: 1rem; + border-radius: var(--border-radius); + border: var(--border); + } +} + +@media (max-width: 768px) { + .markdown-body { + line-height: 1.5; + padding: 0 1.2rem 4rem; + font-size: 1rem; + } +} + +.katex-html { + display: none; + +} \ No newline at end of file diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185110936.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185110936.png new file mode 100644 index 0000000..fec0089 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185110936.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185134888.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185134888.png new file mode 100644 index 0000000..ff66d51 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185134888.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185205287.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185205287.png new file mode 100644 index 0000000..1494063 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185205287.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185220881.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185220881.png new file mode 100644 index 0000000..300cef3 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185220881.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185235222.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185235222.png new file mode 100644 index 0000000..04b6afd Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185235222.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185302851.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185302851.png new file mode 100644 index 0000000..2d58b5b Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185302851.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185319439.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185319439.png new file mode 100644 index 0000000..aa3cce6 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185319439.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185332996.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185332996.png new file mode 100644 index 0000000..237925c Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185332996.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185355849.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185355849.png new file mode 100644 index 0000000..4e50360 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185355849.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185404342.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185404342.png new file mode 100644 index 0000000..4e50360 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185404342.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185437222.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185437222.png new file mode 100644 index 0000000..da1b75d Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185437222.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185439668.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185439668.png new file mode 100644 index 0000000..da1b75d Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185439668.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185450325.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185450325.png new file mode 100644 index 0000000..84fc4bc Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185450325.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185454421.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185454421.png new file mode 100644 index 0000000..84fc4bc Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185454421.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185522753.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185522753.png new file mode 100644 index 0000000..d655bef Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185522753.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185536640.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185536640.png new file mode 100644 index 0000000..91384a3 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418185536640.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418194508675.png b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418194508675.png new file mode 100644 index 0000000..b52feb5 Binary files /dev/null and b/src/blogs/ESP8266天气时钟——项目展示.assets/image-20250418194508675.png differ diff --git a/src/blogs/ESP8266天气时钟——项目展示.md b/src/blogs/ESP8266天气时钟——项目展示.md new file mode 100644 index 0000000..00326a3 --- /dev/null +++ b/src/blogs/ESP8266天气时钟——项目展示.md @@ -0,0 +1,73 @@ +--- +title: ESP8266 天气时钟——项目展示 +desc: 春夏之际,气温变化无常,我们团队结合单片机、物联网和人工智能技术,开发了一款实时显示天气的智能时钟。项目展示了三个精心设计的界面:时间与天气概况、详细气象数据以及天气趋势图表,让天气预报变得直观而贴心。通过简单的二维码扫描配网方式,用户可以轻松将设备连接到家庭WiFi。 +author: feie9454 +date: 2024-04-18 +tags: 计算机、竞赛、嵌入式 +--- + +# ESP8266 天气时钟——项目展示 + +点击查看介绍视频。 + +-->V(/resources/Weather-clock/ESP8266介绍视频.mp4) + +## 团队成员 + +**组长**: + +- 软件2302 查俊豪 3230608044 + +**组员**: + +- 微电子2302 肖雨竹 3234401060 +- 微电子2302 李俊成 3214401011 + +## 引言 + +春夏之际,春风拂面,繁花盛开,也是气温和降水变化无常的时节。我们的团队结合了单片机、物联网和人工智能,开发了一款实时显示天气的时钟。 + +## 项目演示 + +首先,来到系统第一次启动的配置。可以看到系统在短暂的加载后,显示出了引导文本和两个二维码。 + +![image-20250418185110936](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185110936.png) + +我们扫描第一个二维码,一键连接上单片机的热点,连接速度很快。扫描第二个二维码,跳转到了一个网页,这就是单片机连接无线网络的页面。 + +![image-20250418185536640](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185536640.png) + +和我们手机自己的扫描结果是一样的。点击右上角按钮可以重新扫描。我们选择家里的Wifi,输入密码。确定。单片机迅速接收到了数据,重启并尝试连接提供的Wifi。 + +![image-20250418185205287](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185205287.png) + +连接成功后,进行网络对时,获取天气数据。后台WIFI管理界面保证了此时钟不管在什么环境都能快速配置使用。 + +接着我们来看时钟的主体。系统分为三个页面,有一个按钮用于循环切换界面,来回切换十分流畅。 + +我们先看主界面。上方是当前时间,用了类似数码管的风格。得益于自动对时功能,该时钟永远不会出现误差。右侧是传感器实时获得的温湿度数据,每五秒更新一次。下方是用自然语言描述的当前天气情况,每五分钟更新一次,就和我们手机上的天气软件差不多效果,相对于传统时钟或者只能固定显示温湿度的时钟有无可比拟的优势,只需看一眼就能了解接下来的天气情况,显得亲切自然。 + +![image-20250418185220881](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185220881.png) + +接着看界面二,这是更详细的天气数据。左侧有一个天气图标,现在是阴天,右侧依次是实时温度,湿度,风速,气压和PM2.5。下方是日间与夜间的平均温度和最高最低温度。 + +![image-20250418185302851](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185302851.png) + +界面三是一个直观的曲线图,显示温度和降雨接下来二十四小时的变化。上方是温度和体感温度。下方是降雨概率和预计降雨量,今天天气好就都是零了。得益于分辨率较高的彩屏,曲线图显示也毫无问题,肉眼看会更加清晰。 + +![image-20250418185319439](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185319439.png) + +## 技术细节 + +本项目由四个部分组成: + +1. **嵌入式单片机:** 我们使用了 ESP8266 型号的32位单片机,在 NodeMCUv2 平台上开发。ESP8266 是一种低成本的 WiFi 模块,内置了 TCP/IP 协议栈,能够连接到 WiFi 网络。它具有32位处理器,支持最高 80 MHz 的时钟频率,拥有 64KB 的指令 RAM 和 96KB 的数据 RAM,以及外部闪存。ESP8266 提供多种节能模式,非常适合电池供电的应用。我们还连接了一块 128x160 分辨率的 TFT 彩色屏幕用于显示,AM2320温湿度传感器用于检测温湿度,并连接了支持PWM调速的风扇,演示调节气温的反馈系统。开发过程中,我们使用 Platform.io 作为 IDE,C++ 作为开发语言。 + ![image-20250418185332996](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185332996.png) + ![image-20250418185404342](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185404342.png) +3. **位图转换器:** 为了显示天气图标,我们开发了一个将 PNG、JPG、SVG 等常见图片格式转换为单片机易于解码的自定义格式的小程序。此工具使用 Vite 脚手架开发,主要语言为 TypeScript。 +3. **后台管理页面:** 为了简化 WiFi 连接,我们设计了后台管理页面。首次启动单片机时会进入 AP 模式,用户可以通过手机连接单片机的热点,访问后台管理界面,扫描周围的 WiFi 并输入密码进行连接。该管理界面使用 Vite 脚手架开发,主要语言为 TypeScript,开发完成后打包为单文件 HTML,并写入单片机的 LittleFS 文件系统,供用户访问。 + ![image-20250418185439668](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185439668.png) +4. **物联网服务端:** 由于单片机性能和可维护性限制,我们在云服务器上搭建了后端,负责对时和获取天气数据。具体实现包括调用`ip.sb`服务获取 IP 对应的经纬度,调用彩云天气获取天气数据,并使用 OpenAI 的服务处理天气数据,生成单片机可显示的英语自然语言。后端开发使用 Fastify 框架,主要语言为 TypeScript。 + ![image-20250418185454421](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418185454421.png) + +![image-20250418194508675](./ESP8266%E5%A4%A9%E6%B0%94%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E9%A1%B9%E7%9B%AE%E5%B1%95%E7%A4%BA.assets/image-20250418194508675.png) diff --git a/src/blogs/Unity与WebView混合架构在游戏开发中的实践.md b/src/blogs/Unity与WebView混合架构在游戏开发中的实践.md new file mode 100644 index 0000000..8c05eaf --- /dev/null +++ b/src/blogs/Unity与WebView混合架构在游戏开发中的实践.md @@ -0,0 +1,433 @@ +--- +title: Unity与WebView混合架构在游戏开发中的实践 +desc: 作为一名Web开发者,我一直对Unity中繁琐的UI开发流程感到不适。在这篇文章中,我分享了如何将Vue.js的强大UI能力与Unity的3D渲染结合,创造出一款沉浸式狼人杀游戏的全过程。这种创新架构不仅提升了开发效率,还实现了响应式设计和流畅动画效果,为游戏UI开发开辟了新思路。 +author: feie9454 +date: 2025-04-18 +tags: 计算机、游戏开发、前端 +--- + +# Unity与WebView混合架构在游戏开发中的实践 + +## 前言 + +作为一名长期专注于Web开发的程序员,我最近完成了一个有趣的项目——一款基于Unity 3D引擎的狼人杀游戏。与传统Unity游戏不同,我选择了一条较为创新的路径:将Unity负责3D渲染和游戏核心逻辑,而用Vue.js通过WebView实现所有UI界面。这种混合架构带来了许多意想不到的优势,也让我对游戏开发有了全新的理解。本文将从技术角度分享这一开发旅程,希望能为面临类似挑战的开发者提供一些思路。 + +## Unity与WebView:看似不搭的组合 + +初看之下,Unity与WebView的组合似乎有些奇怪。Unity本身具有完整的UI系统(UGUI或UI Toolkit),为什么还要引入Web技术栈?这源于我对两种技术特点的深入思考: + +### Unity的优势: + +- 强大的3D渲染能力 +- 成熟的物理引擎 +- 跨平台兼容性 +- 丰富的资源市场 + +### Web技术的优势: + +- 灵活高效的UI开发流程 +- 响应式设计的便捷实现 +- 丰富的前端生态系统 +- 前端开发者的熟悉度 + +我的核心思想是:**让每种技术专注于自己的强项**。Unity处理3D场景、物理计算和游戏核心逻辑,而Web技术负责所有用户界面和交互体验。因为我的游戏中,3D场景只是起到展示信息、烘托氛围的作用,并不涉及用户实时操作,用户所有时间都是在和UI交互,游戏与服务器通讯因此也可以全部放在前端执行,把Unity需要的数据在特定时间同步过去即可。 + +## 架构设计:沟通是关键 + +这种混合架构的核心挑战在于如何实现Unity与WebView之间的无缝通信。在Unity 端,我使用了 [Vuplex 3D WebView](https://developer.vuplex.com/webview/overview)(感谢Vuplex团队做出这么好用的产品,并积极解答我的疑问!),我的解决方案是基于消息传递的松耦合设计,主要包含以下组件: + +### 1. 前端通信接口 + +```typescript +// VuplexAPI.ts - 前端通信接口 +class VuplexAPI { + private vuplex: any; + + constructor() { + // 处理单独调试时不存在 window.vuplex + if (!window.vuplex) { + console.error('window.vuplex未定义,创建模拟对象'); + window.vuplex = { + postMessage: (msg: any) => { + // 其他处理 + } + }; + } + + // 代理模式拦截所有消息用于调试 + this.vuplex = new Proxy(window.vuplex, { + get: (target, property) => { + if (property === 'postMessage') { + return (msg: any) => { + console.log(`[发送到Unity] ${JSON.stringify(msg)}`); + return target.postMessage(msg); + }; + } + return target[property]; + } + }); + } + + // 示例:向Unity发送场景切换命令 + changeScene(sceneId: number) { + this.vuplex.postMessage({ + type: "changeScene", + sceneId: sceneId + }); + } + + // 其他API方法... +} + +export default VuplexAPI; +``` + +### 2. Unity端消息处理器 + +```csharp +// UnityWebViewBridge.cs - Unity端消息处理 +using UnityEngine; +using Vuplex.WebView; +using System; + +public class UnityWebViewBridge : MonoBehaviour +{ + // WebView实例 + public CanvasWebViewPrefab webViewPrefab; + + // 场景管理器引用 + public SceneManager sceneManager; + + async void Start() + { + if (webViewPrefab == null) + { + Debug.LogError("WebViewPrefab未分配!"); + return; + } + + // 等待WebView初始化 + await webViewPrefab.WaitUntilInitialized(); + + // 注册消息处理器 + webViewPrefab.WebView.MessageEmitted += OnMessageReceived; + + Debug.Log("WebView桥接器已初始化"); + } + + // 处理从WebView收到的消息 + private void OnMessageReceived(object sender, EventArgs eventArgs) + { + try + { + // 解析JSON消息 + var message = JsonUtility.FromJson(eventArgs.Value); + + // 根据消息类型分发处理 + switch (message.type) + { + case "changeScene": + sceneManager.LoadScene(message.sceneId); + break; + + // 处理其他消息类型... + + default: + Debug.LogWarning($"未知消息类型: {message.type}"); + break; + } + } + catch (Exception e) + { + Debug.LogError($"处理消息时出错: {e.Message}"); + } + } + + // 向WebView发送消息 + public void SendMessageToWebView(string messageType, object data) + { + var message = new WebMessage + { + type = messageType, + data = data + }; + + string json = JsonUtility.ToJson(message); + webViewPrefab.WebView.PostMessage(json); + } + + // 消息结构 + [Serializable] + private class WebMessage + { + public string type; + public object data; + public int sceneId; + // 其他字段... + } +} +``` + +这种设计的妙处在于**完全解耦**了UI层和游戏核心层,两部分可以独立开发和测试,只需约定好消息格式即可协同工作。 + +## 对比:传统Unity UI vs Vue.js UI + +为了更直观地理解两种方案的差异,这里对比同一个UI元素在两种技术栈中的实现: + +### 场景:创建一个带动画的按钮 + +#### Unity UGUI实现: + +```csharp +// Unity中创建动画按钮通常需要以下步骤: +// 1. 在编辑器中创建Button +// 2. 在编辑器中创建动画Clip +// 3. 在代码中控制动画状态 + +// ButtonController.cs +using UnityEngine; +using UnityEngine.UI; + +public class ButtonController : MonoBehaviour +{ + public Button button; + public Animator buttonAnimator; + + void Start() + { + button.onClick.AddListener(OnButtonClick); + } + + void OnButtonClick() + { + // 播放点击动画 + buttonAnimator.SetTrigger("Pressed"); + + // 执行按钮功能 + Debug.Log("按钮被点击"); + } +} +``` + +除此之外,还需要在Unity编辑器中设置多个对象、组件和动画参数,过程繁琐且难以版本控制。 + +#### Vue.js实现: + +```vue + + + + + + +``` + +Vue实现的优势显而易见: + +- **代码完整性**:所有相关代码(结构、逻辑、样式)在同一个文件中 +- **响应式设计**:状态变化自动反映到UI上 +- **CSS动画**:使用标准CSS实现平滑过渡 +- **版本控制友好**:纯文本文件,易于比较差异 + +## 核心优势:为什么选择混合架构 + +通过这个项目,我体会到混合架构带来的几个显著优势: + +### 1. 开发效率的提升 + +前端开发中,修改UI后立即可见效果,无需重新编译Unity项目。在我的工作流程中,可以同时运行两个开发服务器: + +```bash +# 终端1:运行Vue开发服务器 +npm run dev + +# 终端2:运行Unity项目 +# (通过Unity编辑器启动) +``` + +这样,修改UI代码后得益于HMR技术,保存代码WebView无需刷新即可看到效果,大大加快了迭代速度。 + +### 2. 团队协作的便利 + +采用混合架构后,项目可以根据专长分工: + +- 3D美术专注于Unity场景和模型 +- 前端开发者负责UI界面和交互 +- 后端开发者处理游戏逻辑和数据 + +每个团队成员都能在熟悉的技术环境中工作,显著提高了生产力。 + +### 3. 响应式UI的实现 + +Vue.js的响应式特性使得复杂UI状态管理变得简单。例如,游戏内角色状态显示: + +```html + +``` + +当游戏状态变化时,UI会自动更新,无需手动刷新界面元素。 + +### 4. 动画与过渡效果 + +Web技术在动画方面提供了丰富的选择: + +```javascript +// 使用CSS动画 +const fadeIn = { + 'opacity': 0, + 'animation': 'fadeIn 0.5s forwards' +}; + +// 或使用JavaScript动画库 +import { gsap } from 'gsap'; + +function animateNotification() { + gsap.fromTo('.notification', + { y: -50, opacity: 0 }, + { y: 0, opacity: 1, duration: 0.5, ease: 'back.out' } + ); +} +``` + +这些动画效果在Unity中实现会复杂得多,而在Web端却轻而易举。 + +## 实际应用案例 + +在我的狼人杀游戏中,这种架构的应用体现在多个方面: + +### 1. 多场景切换 + +```typescript +// 前端场景切换 +function switchGameScene(sceneIndex: number) { + // 前端状态更新 + gameStore.currentScene = sceneIndex; + + // 通知Unity切换3D场景 + vuplexAPI.moveCamera(sceneIndex); +} +``` + +用户在Web界面上进行操作,Unity端接收指令后切换3D场景,实现了无缝的用户体验。 + +![2025-04-14 200954](./%E7%AA%81%E7%A0%B4%E7%95%8C%E9%99%90%EF%BC%9AUnity%E4%B8%8EWebView%E6%B7%B7%E5%90%88%E6%9E%B6%E6%9E%84%E5%9C%A8%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5.assets/2025-04-14_200954.png) + +### 2. 游戏状态同步 + +```typescript +// 游戏状态管理 (Vue + Pinia) +const gameState = reactive({ + phase: 'waiting', + players: [], + currentTurn: null, + // 其他状态... +}); + +// 监听状态变化并同步到Unity +watch(() => gameState.phase, (newPhase) => { + if (newPhase === 'night') { + // 通知Unity切换到夜晚场景 + vuplexAPI.setTime('night'); + } else if (newPhase === 'day') { + // 通知Unity切换到白天场景 + vuplexAPI.setTime('day'); + } +}); +``` + +Vue的响应式系统让游戏状态管理变得优雅而高效。 + +## 技术挑战与解决方案 + +当然,这种混合架构也不是没有挑战: + +### 主要挑战:通信延迟与开销 + +WebView和Unity之间的通信存在一定延迟,特别是在处理大量数据时。因此: + +- 尽量避免大规模的数据交换,比如我的项目中,大部分内容都在UI层处理完成了,Unity端不需要太多数据 +- 减少通信频率,采用批量更新 +- 使用节流和防抖技术 + +```typescript +// 使用防抖函数减少通信频率 +const updateUnityState = debounce((newState) => { + vuplexAPI.updateGameState(newState); +}, 50); +``` + +## 结语:混合未来的可能性 + +通过这个项目,我深信Unity+WebView的混合架构代表了游戏UI开发的一个有价值的方向,特别是对于对UI要求较高、交互复杂的游戏。虽然不是所有游戏都适合这种方案,但对于像狼人杀这样的社交游戏,混合架构带来的优势是显著的。 + +这种开发模式让我能够充分利用现代Web开发的所有优势,同时不失Unity强大的3D功能。对于那些同时精通Web和游戏开发的团队来说,这无疑开辟了新的可能性。 + +## 附录:部分游戏中截图 + +![2025-04-14_200916](./%E7%AA%81%E7%A0%B4%E7%95%8C%E9%99%90%EF%BC%9AUnity%E4%B8%8EWebView%E6%B7%B7%E5%90%88%E6%9E%B6%E6%9E%84%E5%9C%A8%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5.assets/2025-04-14_200916.png) + +![2025-04-14_201115](./%E7%AA%81%E7%A0%B4%E7%95%8C%E9%99%90%EF%BC%9AUnity%E4%B8%8EWebView%E6%B7%B7%E5%90%88%E6%9E%B6%E6%9E%84%E5%9C%A8%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5.assets/2025-04-14_201115.png) + +![2025-04-14_201948](./%E7%AA%81%E7%A0%B4%E7%95%8C%E9%99%90%EF%BC%9AUnity%E4%B8%8EWebView%E6%B7%B7%E5%90%88%E6%9E%B6%E6%9E%84%E5%9C%A8%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5.assets/2025-04-14_201948.png) + +![2025-04-14_211728](./%E7%AA%81%E7%A0%B4%E7%95%8C%E9%99%90%EF%BC%9AUnity%E4%B8%8EWebView%E6%B7%B7%E5%90%88%E6%9E%B6%E6%9E%84%E5%9C%A8%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5.assets/2025-04-14_211728.png) \ No newline at end of file diff --git a/src/blogs/utils.ts b/src/blogs/utils.ts new file mode 100644 index 0000000..490e3b7 --- /dev/null +++ b/src/blogs/utils.ts @@ -0,0 +1,19 @@ +function getStringHash(str: string) { + let hash = 0; + for (let i = 0; i < str.length; i++) { + const char = str.charCodeAt(i); + hash = (hash << 5) - hash + char; + hash |= 0; // Convert to 32bit integer + } + return (hash >>> 0).toString(16).padStart(6, '0').slice(0, 6); +} + +export function generatePath(frontmatter: { date: Date, title: string }) { + const { title } = frontmatter; + + const titleHash = getStringHash(title); + return { + short: encodeURI(`/blogs/${titleHash}`), + long: encodeURI(`/blogs/${title}.md`), + } +} \ No newline at end of file diff --git a/src/blogs/中国消费者价格指数走势分析、通货紧缩压力及中美贸易战背景下的影响.assets/image-20250416093357441.png b/src/blogs/中国消费者价格指数走势分析、通货紧缩压力及中美贸易战背景下的影响.assets/image-20250416093357441.png new file mode 100644 index 0000000..99cd369 Binary files /dev/null and b/src/blogs/中国消费者价格指数走势分析、通货紧缩压力及中美贸易战背景下的影响.assets/image-20250416093357441.png differ diff --git a/src/blogs/中国消费者价格指数走势分析、通货紧缩压力及中美贸易战背景下的影响.md b/src/blogs/中国消费者价格指数走势分析、通货紧缩压力及中美贸易战背景下的影响.md new file mode 100644 index 0000000..9a1cc4c --- /dev/null +++ b/src/blogs/中国消费者价格指数走势分析、通货紧缩压力及中美贸易战背景下的影响.md @@ -0,0 +1,183 @@ +--- +title: 中国消费者价格指数走势分析、通货紧缩压力及中美贸易战背景下的影响 +desc: 通过对过去五年CPI数据的考察得出,中国经济近期出现了从低通胀向通货紧缩转变的趋势。分析近期中美贸易争端的显著升级对中国CPI的潜在影响:中国长期依赖的出口导向型增长模式在地缘政治和贸易保护主义抬头背景下显得愈发脆弱,接下来必须做出改变。 +author: feie9454 +date: 2025-04-16 +tags: 投资、新闻 +--- + + +# **中国消费者价格指数走势分析、通货紧缩压力及中美贸易战背景下的影响** + +## **1. 执行摘要** + +本报告深入分析了中国近几年消费者价格指数(CPI)的走势,揭示了当前经济环境下通货紧缩的压力。通过对过去五年CPI数据的考察,报告指出中国经济近期出现了从低通胀向通货紧缩转变的趋势。报告探讨了导致这一趋势的需求侧和供给侧的主要因素,包括消费者信心不足、房地产市场下行、地方政府债务压力、新冠疫情的持续影响、严重的工业产能过剩以及全球大宗商品价格下跌等。 + +此外,本报告还重点分析了近期中美贸易争端的显著升级对中国CPI的潜在影响。不同于初期,此次贸易争端以远高于以往的关税水平(平均税率可能高达65%-74%)和更广泛的全球性影响为特征,不仅直接冲击中美双边贸易,还通过限制转口贸易和影响第三国购买力,间接压缩了中国的全球出口空间。这种外部压力进一步加剧了内部需求不足和产能过剩的问题,使得通货紧缩风险更为严峻。报告指出,中国长期依赖的出口导向型增长模式在地缘政治和贸易保护主义抬头背景下显得愈发脆弱。 + +报告评估了这些经济变化对中国不同社会阶层的影响,强调低收入群体和依赖工资收入的群体在就业和收入方面面临更大压力。 + +最后,报告探讨了中国政府可能采取的应对措施。面对外部市场的萎缩和内部的结构性问题,唯一的出路被认为是进行根本性的经济模式转型,即从过度依赖投资和出口转向大力刺激国内消费。这需要政府采取空前规模的积极财政政策(如直接补贴消费)和适度宽松的货币政策,并辅以更深层次的结构性改革(如改善收入分配、完善社会保障、调整劳工政策等),以有效提振内需。报告总结认为,在复杂的国内外经济环境下,中国经济面临严峻的挑战和历史性的转型压力,需要政府采取果断且综合性的措施来稳定经济增长,应对通货紧缩压力,并为经济寻找可持续的新动能。 + +## **2. 解读中国消费者价格指数:近期趋势与轨迹** + +### **2.1. 近五年消费者价格指数数据分析** + +对中国国家统计局及其他数据来源发布的近五年CPI数据分析显示,中国经济近期经历了显著的价格波动。2025年3月,居民消费价格指数同比下降0.1%,核心消费者物价指数同比上涨0.5%。此前的2025年2月,CPI同比下降0.7%,这是自2024年1月以来13个月的最大降幅。与此形成对比的是,2025年1月,由于春节消费的推动,CPI同比上涨0.5%,达到了五个月的峰值。这一数据表明,在经历了短暂的节日性上涨后,中国的物价水平再次进入下行通道,预示着通货紧缩的压力正在加大。从2025年初的数据来看,CPI的同比变化呈现出快速减速的态势,1月份为上涨0.5%,2月份急剧下降至-0.7%,3月份虽略有回升但仍为负值,为-0.1%。 + +### **2.2. 消费者价格指数趋势图** + +![image-20250416093357441](./%E4%B8%AD%E5%9B%BD%E6%B6%88%E8%B4%B9%E8%80%85%E4%BB%B7%E6%A0%BC%E6%8C%87%E6%95%B0%E8%B5%B0%E5%8A%BF%E5%88%86%E6%9E%90%E3%80%81%E9%80%9A%E8%B4%A7%E7%B4%A7%E7%BC%A9%E5%8E%8B%E5%8A%9B%E5%8F%8A%E4%B8%AD%E7%BE%8E%E8%B4%B8%E6%98%93%E6%88%98%E8%83%8C%E6%99%AF%E4%B8%8B%E7%9A%84%E5%BD%B1%E5%93%8D.assets/image-20250416093357441.png) + +### **2.3. 历史背景与消费者价格指数篮子构成** + +中国的CPI篮子每五年进行一次基于家庭调查的审查,以反映新的消费模式和经济发展。最近一次修订的权重是基于2020年的数据。CPI涵盖八大类商品和服务,包括食品烟酒、衣着、居住、生活用品及服务、交通通信、教育文化娱乐、医疗保健以及其他用品及服务。例如,娱乐、教育和文化用品占CPI权重的13.8%,交通和通信占10%。 + +回顾历史,中国的CPI曾出现过显著的上涨,例如2020年2月同比上涨5.2%,2020年1月更是达到了5.4%,为八年来首次突破5%。而2019年7月,CPI也曾达到2.8%,为近一年半以来的高点。1994年,中国的年度CPI涨幅更是高达24.1%。然而,近期的数据显示,中国也曾面临通货紧缩,例如2024年1月CPI同比下降0.8%,为14年来的最大降幅。2020年的CPI大幅上涨在很大程度上受到猪肉价格飙升的影响。 + +了解CPI的构成对于分析通货膨胀和通货紧缩的驱动因素至关重要,因为权重较高的类别价格变化会对总体CPI产生更大的影响。近期出现的通货紧缩趋势与前几年较高的通胀率形成了鲜明对比,凸显了当前经济环境的重大转变。 + +## **3. 中国通货紧缩压力的剖析** + +### **3.1. 需求侧因素** + +#### **3.1.1. 消费者信心减弱** + +当前中国经济面临的一个重要挑战是消费者信心不足。房地产市场的持续低迷是影响消费者信心的关键因素之一,许多家庭因房价下跌而感到财富缩水,从而不愿消费。同时,收入和就业的不确定性也使得居民更加倾向于储蓄而非消费,对未来经济前景的担忧导致储蓄意愿显著增加。自新冠疫情暴发以来,经济复苏的步伐一直较为缓慢,这进一步加剧了担忧。尽管房屋和汽车等大宗商品都在降价促销,但消费需求依然不振。裁员和薪资削减也使得中产阶级感到压力,可能大幅削减开支。消费者普遍持币观望,即使是激烈的价格战也未能有效刺激消费增长。 + +#### **3.1.2. 房地产市场下行** + +房地产市场的低迷对中国的整体需求产生了显著的负面影响。房价下跌不仅直接影响房地产行业的投资和交易,还通过负财富效应抑制了消费者的其他支出。许多潜在购房者预期房价会进一步下跌,因此选择推迟购房计划。此外,房地产市场的萧条也对地方政府的财政收入造成了严重冲击,因为土地销售是地方政府重要的收入来源。这反过来又限制了地方政府利用财政政策进行逆周期调节的能力。 + +#### **3.1.3. 地方政府债务** + +地方政府债务负担沉重,这也对政府支出和整体需求造成了影响。高额的债务限制了地方政府进行财政刺激的空间,从而进一步削弱了总需求。 + +#### **3.1.4. 新冠疫情及相关政策的影响** + +新冠疫情及其相关的防控政策对消费者的行为和整体需求产生了深远的影响。尽管疫情限制已经解除,但经济的复苏仍然乏力,消费者信心尚未完全恢复。疫情期间许多企业面临困境,人们对就业和收入的担忧依然存在,导致消费意愿受到抑制。 + +### **3.2. 供给侧因素** + +#### **3.2.1. 工业产能过剩** + +中国经济目前面临着严重的工业产能过剩问题。许多行业都存在生产能力超出市场需求的现象,这迫使生产商降低价格以销售产品,从而导致通货紧缩。例如,在电动汽车市场,激烈的竞争也导致价格持续下降。这种结构性的供过于求是当前通缩现象的重要根源。长期以来以生产和出口为导向的模式,导致供给能力持续扩张,而国内需求未能同步跟上。 + +#### **3.2.2. 全球大宗商品价格下跌** + +全球大宗商品价格的下跌也对中国的国内物价水平产生了一定的影响。较低的进口原材料成本降低了中国制造商的生产成本,这在一定程度上也传导至消费品价格,加剧了通货紧缩的压力。 + +#### **3.2.3. 技术进步与生产力提高** + +技术进步和生产力的提高也可能导致部分商品价格下降。随着自动化和先进制造技术的发展,中国能够以更低的成本生产商品,这使得相关领域商品价格具有下降的趋势。 + +#### **3.2.4. 政策侧重生产而非消费** + +政府政策长期以来侧重于支持生产和投资,而对直接刺激消费的需求相对不足。这种政策导向可能导致供给侧的扩张快于需求侧的增长,从而加剧了供需失衡,并为通货紧缩创造了条件。 + +## **4. 中美贸易战:消费者价格指数变化的催化剂** + +### **4.1. 关税的时间线与升级** + +自2018年以来,中美贸易争端经历了不同阶段。近期,贸易紧张局势显著升级,呈现出新的特点: + +- **关税水平大幅提高**:与第一轮贸易战相比,美国对华商品加征的关税水平远超以往,平均有效税率可能达到65%甚至更高。这与最初从3%提高到20%是量级上的差别。 +- **关税逻辑变化**:美方此次关税措施并非仅针对中国,而是基于"贸易逆差"对全球主要贸易伙伴进行调整。逆差越大的国家,面临的关税压力可能越大。 +- **中国的强力反制**:与初期相比,中方此次迅速采取了对等的、强力的反制措施,显示出更强的对抗姿态。 +- **持续升级的风险**:美方明确表示,若对其关税措施进行反击,可能面临更高关税,预示着争端有进一步升级的可能。 + +### **4.2. 对进口价格的直接影响** + +美国对中国商品征收的高额关税直接增加了美国消费者和企业的进口成本。同样,中国对美国商品征收的报复性关税也提高了中国消费者和企业的进口成本。研究表明,关税的成本最终很大程度上由进口国的消费者或企业承担。 + +### **4.3. 对国内生产成本和需求的间接影响** + +中美贸易战的间接影响更为深远,并加剧了中国的通缩压力: + +- **转口贸易路径被堵塞**:美方基于贸易逆差的全球关税体系,使得中国商品难以再通过第三国(如柬埔寨、越南、墨西哥等)转口来规避关税。因为这些第三国若对美顺差增加(部分源于转口中国商品),自身也会面临关税壁垒,为求自保,它们可能会主动限制来自中国的转口业务。 +- **对第三国出口受损**:许多发展中国家依赖对美出口获取外汇,再用这些外汇购买中国商品。当美国市场对它们关闭或加征关税,它们的外汇收入减少,购买中国商品的能力也随之下降,间接打击了中国对这些国家的出口。 +- **"中国冲击"内化**:过去中国通过大量出口,将国内的过剩产能和价格压力(所谓的"中国冲击")部分转移到全球市场。当全球主要市场(尤其是美国)竖起高关税壁垒,这些过剩产能和降价压力将更多地留在国内,加剧内部的供过于求和通缩压力。 +- **国内生产成本与需求**:虽然关税提高了部分进口中间品的成本,但在国内需求疲软和产能严重过剩的背景下,企业难以将成本上升转嫁给消费者。反而,为了在萎缩的(国内外)市场中竞争,生产商可能被迫进一步降价,加剧通缩。 + +## **5. 中美贸易紧张局势下未来消费者价格指数趋势预测** + +### **5.1. 贸易战升级与缓和的情景分析** + +未来CPI趋势很大程度上取决于贸易争端的走向。 + +- **升级情景**:如果美国进一步提高关税或扩大范围,中国的出口将面临更大压力,国内产能过剩问题将更突出,通货紧缩压力大概率会进一步加剧。 +- **缓和情景**:如果中美达成某种协议或紧张局势缓解,通缩压力可能得到一定程度的缓解。但考虑到双方立场和互信基础,以及问题的结构性,短期内完全缓和的可能性似乎不高。 + +### **5.2. 进口成本、国内生产费用和消费者需求的相互作用** + +未来物价走势是多重因素博弈的结果。关税推高部分进口成本,但全球大宗商品价格波动、国内技术进步、特别是严重的产能过剩会抑制生产成本。最关键的是国内消费者需求的强度。在当前需求疲软的环境下,即使进口成本上升,企业也难以提价,通缩压力很可能在近期持续。人民币汇率的变化也会影响进口成本和出口竞争力,但其对通缩趋势的整体影响可能有限。 + +### **5.3. 专家预测与展望** + +目前的专家和市场普遍意见认为,尽管政府设定了经济增长目标,但中国在2025年甚至未来一两年内仍将面临低通胀甚至通货紧缩的局面。预计2025年的平均通胀率可能远低于官方目标,例如预测值在0.6%左右,到2026-2027年也可能仅回升至1.4%-1.7%。持续的产能过剩和内需不足是主要制约因素。 + +## **6. 社会经济影响:中国社会各阶层如何应对消费者价格指数变化** + +### **6.1. 不同社会阶层对价格变化的敏感度和承受能力** + +不同社会阶层对价格变化的敏感度和承受能力存在显著差异。低收入群体和贫困人口通常将更大比例的收入用于购买食品等必需品,对价格上涨更为敏感,其实际感受到的通胀可能高于官方数据。而通货紧缩虽然短期内可能让物价下降,但其伴随的工资下降和失业风险对这些群体的冲击最大,因为他们储蓄有限,抵御风险能力弱。据一些分析人士估计,贸易争端和经济放缓可能导致千万级别的工人面临失业或收入下降的风险。 + +中产阶级虽然对必需品价格敏感度较低,但其财富与房地产市场密切相关,房价下跌导致的财富缩水效应会抑制其消费意愿。同时,他们也面临就业压力和对经济前景的担忧。农民和工人的收入稳定性相对较差,尤其容易受到经济下行周期的影响。高收入群体对日常消费品价格变化不敏感,但可能更关注资产价格波动和投资回报率。 + +### **6.2. 对消费能力、就业和投资的影响** + +持续的通缩或低通胀环境对整体经济产生负面影响。消费者和企业可能会因为预期未来价格更低而推迟消费和投资,形成恶性循环。出口导向型行业的就业岗位直接受到贸易争端和外部需求萎缩的冲击。国内需求不足也会传导至各行各业,导致整体就业市场承压,工资增长乏力甚至下降。 + +### **6.3. 不同社会阶层消费者价格指数变化敏感度和影响比较分析表** + +| **社会阶层** | **对价格变化的敏感度** | **通货紧缩的潜在影响** | **主要考虑因素** | +| ------------ | ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| 低收入群体 | 高 | **购买力下降(若工资下跌),就业风险急剧增加,生活质量恶化** | 必需品支出占比高,储蓄有限,极易受工资和就业波动影响 | +| 中产阶级 | 中 | 财富缩水(房地产),消费意愿降低,**就业压力增大,收入预期悲观** | 房地产是主要财富形式,债务负担,对经济前景敏感,开始削减非必需开支 | +| 高收入群体 | 低 | 投资回报率可能下降,资产价值波动,高端消费可能放缓 | 消费结构多元,关注投资和资产保值 | +| 农民 | 高 | 农产品价格可能下跌,收入不稳定,**外出务工机会减少** | 收入来源相对单一,易受市场价格波动影响,社会保障相对薄弱 | +| 工人 | 高 | **工资可能下降或停滞,失业风险增加,加班机会减少** | 收入主要依赖工资,储蓄相对有限,易受企业(尤其出口企业)经营状况影响 | + +## **7. 政府应对措施与政策工具** + +面对当前的通缩压力和外部冲击,政府的政策选择至关重要,且可能需要采取与以往不同的、更侧重需求的策略: + +### **7.1. 财政政策选项** + +预计政府将加大财政刺激力度,但重点可能转向直接刺激消费。 + +- **增加政府支出**:继续投资于必要的基础设施和社会项目,但可能更注重能直接改善民生和消费能力的项目。 +- **直接补贴消费**:发放消费券或直接现金补贴给家庭,尤其是中低收入家庭,被认为是提振需求的关键手段。其规模可能远超以往。 +- **减税降费**:调整税收政策,增加居民可支配收入。 +- **扩大财政赤字**:通过发行更多国债(包括超长期特别国债)来支持上述支出,财政赤字率预计将上升。 + +### **7.2. 货币政策工具** + +货币政策将保持"适度宽松",但其效果可能受限于需求不足。 + +- **降息与降准**:预计将进一步降低利率和存款准备金率(RRR),以降低借贷成本,增加流动性。 +- **央行操作**:央行可能更常规地在二级市场买卖国债,以影响流动性和利率水平。 +- **结构性工具**:可能运用定向工具支持特定领域(如中小企业、绿色发展),但重点是整体宽松以配合财政发力。 + +### **7.3. 更广泛的结构性改革:核心在于转向内需驱动** + +这被认为是应对当前困境并实现长期可持续发展的根本途径。这不仅仅是政策调整,而是经济发展模式的根本性转变,其难度和意义堪比历史上的重大改革。 + +- **提升居民收入与消费能力**:这是核心目标。需要通过改善收入分配、大幅提高社会保障水平(养老、医疗、失业救济)、完善劳工权益保护等措施,让居民敢于消费、有能力消费。 +- **解决结构性问题**:需要有效化解房地产市场风险和地方政府债务问题,为经济转型扫清障碍。 +- **转变增长模式**:政策重心必须从过度依赖投资和出口,真正转向以内需特别是消费为主导。这意味着要容忍较低的投资增速,将更多资源用于民生和消费领域。 + +## **8. 结论与战略可能** + +本报告分析表明,中国经济正面临日益严峻的通货紧缩压力,这是内部结构性问题(需求不足、产能过剩、房地产风险)与外部冲击(中美贸易战升级)共同作用的结果。特别是近期贸易争端的急剧升级及其独特的全球影响方式,实质上是迫使中国对其长期依赖的出口导向型增长模式进行根本性反思和调整。这种模式在新的国际环境下已难以为继。 + +通货紧缩和外部需求萎缩对中国社会各阶层产生了显著的负面影响,尤其是对低收入群体和依赖工资收入的劳动者构成了严峻挑战。 + +为了应对当前的经济困境并寻求长期可持续发展,中国政府必须进行一场深刻的经济模式转型,核心是从生产/出口导向转向国内消费驱动。这要求: + +1. **实施空前规模的、以刺激消费为核心的财政政策**:加大政府支出,重点是直接补贴居民消费和完善社会保障体系,显著提高居民可支配收入和消费意愿。 +2. **货币政策需积极配合**:保持流动性合理充裕,降低融资成本,支持实体经济,但需认识到在需求不足的情况下,货币政策效果有限,主要起辅助作用。 +3. **推进深层次的结构性改革**:这是转型的关键。必须着力解决房地产风险、地方债务问题,并根本性地改革收入分配制度、强化社会安全网、保障劳工权益,为消费驱动型增长奠定制度基础。 +4. **调整发展理念与考核指标**:政策重心和资源配置需向消费和民生倾斜,未来应更多关注居民收入增长、消费支出、社会福利改善等指标,而非过度强调GDP增长和工业产值。 + +面对复杂严峻的国内外形势,中国经济正处在一个充满挑战但也可能蕴含机遇的转折点。转型的过程无疑是痛苦且艰难的,但若能成功,则可能为中国经济开辟新的发展道路。未来几年,需要密切关注全球贸易格局的变化,以及中国政府在刺激消费和推动结构性改革方面的决心、力度和实际效果。能否有效提振内需,将是中国经济能否走出当前困境并实现长期健康发展的关键所在。 \ No newline at end of file diff --git a/src/blogs/交易策略:MACD三重指标.assets/2fe2d7ab31d64d73c2cfa7201ceaa10531202826.jpg@1192w_596h.webp b/src/blogs/交易策略:MACD三重指标.assets/2fe2d7ab31d64d73c2cfa7201ceaa10531202826.jpg@1192w_596h.webp new file mode 100644 index 0000000..f3a689f Binary files /dev/null and b/src/blogs/交易策略:MACD三重指标.assets/2fe2d7ab31d64d73c2cfa7201ceaa10531202826.jpg@1192w_596h.webp differ diff --git a/src/blogs/交易策略:MACD三重指标.assets/54bafaa1c0806a7e4490ff29c193b88c31202826.jpg@1192w_596h.webp b/src/blogs/交易策略:MACD三重指标.assets/54bafaa1c0806a7e4490ff29c193b88c31202826.jpg@1192w_596h.webp new file mode 100644 index 0000000..768eba3 Binary files /dev/null and b/src/blogs/交易策略:MACD三重指标.assets/54bafaa1c0806a7e4490ff29c193b88c31202826.jpg@1192w_596h.webp differ diff --git a/src/blogs/交易策略:MACD三重指标.assets/57b2627b366ca51cbe3fa73af4a52a5731202826.jpg@1192w_596h.webp b/src/blogs/交易策略:MACD三重指标.assets/57b2627b366ca51cbe3fa73af4a52a5731202826.jpg@1192w_596h.webp new file mode 100644 index 0000000..fba9d25 Binary files /dev/null and b/src/blogs/交易策略:MACD三重指标.assets/57b2627b366ca51cbe3fa73af4a52a5731202826.jpg@1192w_596h.webp differ diff --git a/src/blogs/交易策略:MACD三重指标.assets/9fa652b3d79d3fe091e42905f45eaa4931202826.png@1192w.webp b/src/blogs/交易策略:MACD三重指标.assets/9fa652b3d79d3fe091e42905f45eaa4931202826.png@1192w.webp new file mode 100644 index 0000000..cd598e3 Binary files /dev/null and b/src/blogs/交易策略:MACD三重指标.assets/9fa652b3d79d3fe091e42905f45eaa4931202826.png@1192w.webp differ diff --git a/src/blogs/交易策略:MACD三重指标.md b/src/blogs/交易策略:MACD三重指标.md new file mode 100644 index 0000000..2bce834 --- /dev/null +++ b/src/blogs/交易策略:MACD三重指标.md @@ -0,0 +1,86 @@ +--- +title: 交易策略:MACD三重指标 +desc: MACD三重策略是一种多时间框架策略,基于移动平均收敛散度指标。何时开仓?何时平仓?该策略盈利吗? +author: whselfinvest.com +date: 2025-04-01 +tags: 投资 +--- + +# 交易策略:MACD三重指标 + +> 原文:https://www.whselfinvest.com/en/trading_strategies_41_MACD_Triple.php +> +> 免责声明:本文仅金融知识介绍和策略分析,不构成投资建议。 + +**MACD三重策略描述** + +MACD三重策略是一种多时间框架策略。这类策略基于在不同但相关的时间框架中并行分析一个或多个技术指标。较高时间框架用作趋势过滤器,较小时间框架用作信号。 + +设计用于: + +- 市场指数(DAX、标普500、道琼斯等) +- 外汇(欧元/美元等) +- 商品(石油、黄金等) +- 股票 + +交易工具:期货、差价合约、外汇 + + 交易类型:日内交易 + + 交易频率:在15分钟图表上每天0-3个信号 + + 使用NanoTrader Full:手动和(半)自动化 + +> 差价合约是复杂的工具,由于杠杆作用,存在快速亏损的高风险。78%的零售投资者账户在与该提供商交易差价合约时亏损。您应该考虑自己是否了解差价合约的运作方式,以及是否能够承担亏损的高风险。 + +## **交易策略详情** + +MACD三重策略基于移动平均收敛散度指标(MACD - 12,26,9)。该MACD在三个时间框架中分析:4小时、1小时和15分钟。注意,每个时间框架与下一个的比例是4:1。1小时和4小时MACD用作趋势过滤器。15分钟MACD提供买入和卖出信号。 + +**何时开仓?** + +当快速MACD线向上穿越慢速MACD线时,15分钟MACD给出买入信号。当快速MACD线向下穿越慢速MACD线时,15分钟MACD给出卖空信号。 + +**趋势过滤器** + +在接受信号之前,它们要经过由4小时和1小时MACD组成的综合趋势过滤器。如果两者都看涨,则只接受买入信号。如果两者都看跌,则只接受卖空信号。如果一个看涨而另一个看跌,则拒绝所有信号。 + +**时间过滤器** + +该策略还包含时间过滤器。时间过滤器接受08:00至21:20之间的信号。平台会拒绝此时间段以外的信号。 + +**何时平仓?** + +DAX-ORB策略包括价格目标订单和止损订单。止损订单放置在开盘区间通道的对侧。价格目标是止损风险的2倍。NanoTrader自动放置这些订单。 + +如果价格目标和止损订单在当天都未触及,该怎么办?DAX-ORB策略通过时间过滤器解决这个问题。过滤器在21:45自动以市价平仓。交易者过夜不持仓,第二天早上等待新信号。 + +![img](./%E4%BA%A4%E6%98%93%E7%AD%96%E7%95%A5%EF%BC%9AMACD%E4%B8%89%E9%87%8D%E6%8C%87%E6%A0%87.assets/54bafaa1c0806a7e4490ff29c193b88c31202826.jpg@1192w_596h.webp) + +示例展示了一天内有两个买入信号的情况。主图下方是三个MACD。图表中的绿色背景表明1小时和4小时MACD都看涨。只有买入信号会被接受。15分钟MACD的快线向上穿越慢线产生买入信号。开仓时,止损(红线)和盈利目标(绿线)自动出现。在这两种情况下,当15分钟MACD反向交叉时,持仓以盈利平仓。 + +![img](./%E4%BA%A4%E6%98%93%E7%AD%96%E7%95%A5%EF%BC%9AMACD%E4%B8%89%E9%87%8D%E6%8C%87%E6%A0%87.assets/2fe2d7ab31d64d73c2cfa7201ceaa10531202826.jpg@1192w_596h.webp) + +示例展示了卖空信号。主图下方是三个MACD。图表中的红色背景表明1小时和4小时MACD都看跌。只有卖空信号会被接受。15分钟MACD的快线向下穿越慢线产生卖空信号。开仓时,止损(红线)和盈利目标(绿线)自动出现。14:00左右市价几乎达到盈利目标。稍后当15分钟MACD反向交叉时,持仓平仓。 + +![img](./%E4%BA%A4%E6%98%93%E7%AD%96%E7%95%A5%EF%BC%9AMACD%E4%B8%89%E9%87%8D%E6%8C%87%E6%A0%87.assets/57b2627b366ca51cbe3fa73af4a52a5731202826.jpg@1192w_596h.webp) + +示例展示了一天内有两个卖空信号的情况。主图下方是三个MACD。图表中的红色背景表明1小时和4小时MACD都看跌。只有卖空信号会被接受。15分钟MACD的快线向下穿越慢线产生卖空信号。开仓时,止损(红线)和盈利目标(绿线)自动出现。在这两种情况下,当15分钟MACD反向交叉时,持仓平仓。 + +## **该交易策略盈利吗?** + +MACD三重策略的结果各不相同。这些截图显示了对一些市场指数和商品进行的7年期回测。该策略可应用于所有工具,因此您可以回测和优化您感兴趣的任何内容。 + +![img](./%E4%BA%A4%E6%98%93%E7%AD%96%E7%95%A5%EF%BC%9AMACD%E4%B8%89%E9%87%8D%E6%8C%87%E6%A0%87.assets/9fa652b3d79d3fe091e42905f45eaa4931202826.png@1192w.webp) + +## **结论** + +MACD三重策略是典型的多时间框架策略。结合多个时间框架通常在交易中产生良好结果。交易者应研究此类策略。MACD三重策略可用于市场指数、股票、外汇和商品。该策略是日内交易策略,但没有信号的日子并不少见。 + +## **实际实施** + +在NanoTrader中按照以下步骤操作: + +1. 打开您想要交易的工具图表。 +2. 在WHS策略文件夹中,选择"WHS MACD Triple"策略。 +3. 半自动交易?激活TradeGuard+AutoOrder。自动交易?激活AutoOrder。 \ No newline at end of file diff --git a/src/blogs/使用iPerf测试与VPS连接速度.md b/src/blogs/使用iPerf测试与VPS连接速度.md new file mode 100644 index 0000000..24c4892 --- /dev/null +++ b/src/blogs/使用iPerf测试与VPS连接速度.md @@ -0,0 +1,55 @@ +--- +title: 使用iPerf测试与VPS连接速度 +desc: +author: feie9454 +date: 2025-04-20 +tags: 计算机、教程 +--- + +# 使用iPerf测试与VPS连接速度 + +## 服务器端设置: + +1. 首先安装iperf3: + +``` +sudo apt update +sudo apt install iperf3 +``` + +1. 启动iperf3服务器模式: + +``` +iperf3 -s +``` + +这会让服务器监听默认的5201端口等待客户端连接。如需更改端口可以使用`-p`参数,例如: + +``` +iperf3 -s -p 9999 +``` + +## 客户端(Windows)设置: + +1. 下载Windows版iperf3: + - 访问官方网站(https://iperf.fr/iperf-download.php)下载Windows版本 +2. 打开命令提示符(CMD),切换到iperf3所在目录: + +``` +cd C:\path\to\iperf3 +``` + +3. 运行基本测试: + +``` +iperf3.exe -c 服务器IP地址 +``` + +4. `-R`:反向测试(测试下载速度而非上传) + +``` +iperf3.exe -c 服务器IP地址 -R +``` + + + diff --git a/src/blogs/北京海淀 vs. 上海市中心消费水平对比报告.assets/d1c7956f-c6c5-43f6-be00-a2452fdc1388.png b/src/blogs/北京海淀 vs. 上海市中心消费水平对比报告.assets/d1c7956f-c6c5-43f6-be00-a2452fdc1388.png new file mode 100644 index 0000000..f60436c Binary files /dev/null and b/src/blogs/北京海淀 vs. 上海市中心消费水平对比报告.assets/d1c7956f-c6c5-43f6-be00-a2452fdc1388.png differ diff --git a/src/blogs/北京海淀 vs. 上海市中心消费水平对比报告.md b/src/blogs/北京海淀 vs. 上海市中心消费水平对比报告.md new file mode 100644 index 0000000..aa5efe3 --- /dev/null +++ b/src/blogs/北京海淀 vs. 上海市中心消费水平对比报告.md @@ -0,0 +1,110 @@ +--- +title: 北京海淀 vs. 上海市中心消费水平对比报告 +desc: 北京和上海作为中国一线城市,其核心城区的消费水平备受关注。本文选取北京核心城区之一的**海淀区**,与上海核心城区(以**黄浦、静安区**等市中心区域为代表)进行多方面消费水平对比。数据主要基于**2024年末至2025年初**的官方统计、主流媒体和大型平台报告。 +author: ChatGPT - DeepResearch +date: 2025-04-17 +tags: 经济、新闻 +--- + +# 北京海淀 vs. 上海市中心消费水平对比报告 + +北京和上海作为中国一线城市,其核心城区的消费水平备受关注。本文选取北京核心城区之一的**海淀区**,与上海核心城区(以**黄浦、静安区**等市中心区域为代表)进行多方面消费水平对比。数据主要基于**2024年末至2025年初**的官方统计、主流媒体和大型平台报告,具体时间范围和来源将在下文标注。 + +## 1. 餐饮消费对比 + +北京海淀和上海市中心的日常餐饮价格总体均处于一线城市较高水平,但上海略高于北京。主要表现在工作日午餐、晚餐以及咖啡和中高端餐厅消费上。 + +- **工作日午餐(简餐)**:两地白领日常午餐以实惠为主。调查显示,**超过65%的一线城市白领午餐花费在20元以内** ([白领午餐报告:一线城市CBD“打工人”既爱平价又要品质_腾讯新闻](https://news.qq.com/rain/a/20201105A0BH1G00#:~:text=%E5%9C%A8%E8%AE%B8%E5%A4%9A%E4%BA%BA%E7%9A%84%E6%83%B3%E8%B1%A1%E4%B8%AD%EF%BC%8C%E5%87%BA%E5%85%A5%E4%B8%80%E7%BA%BF%E5%9F%8E%E5%B8%82CBD%E9%AB%98%E7%AB%AF%E5%86%99%E5%AD%97%E6%A5%BC%E7%9A%84%E7%99%BD%E9%A2%86%EF%BC%8C%E6%AF%8F%E5%A4%A9%E4%BA%AB%E7%94%A8%E7%9A%84%E5%8D%88%E9%A4%90%E5%BA%94%E8%AF%A5%E4%B9%9F%E4%BB%B7%E6%A0%BC%E4%B8%8D%E8%8F%B2%E3%80%82%E4%BD%86%E7%BB%9F%E8%AE%A1%E5%8F%91%E7%8E%B0%EF%BC%8C%E5%8D%B3%E4%BD%BF%E5%9C%A8%E8%BF%99%E4%BA%9B%E5%9C%B0%E6%96%B9%EF%BC%8C%E7%99%BD%E9%A2%86%E7%9A%84%E5%8D%88%E9%A4%90%E9%80%89%E6%8B%A9%E4%B9%9F%E4%BB%A5%E5%B9%B3%E4%BB%B7%E4%B8%BA%E4%B8%BB%E3%80%82))。北京海淀白领常见午餐花费**约20元左右**;上海CBD白领中有更大比例的人午餐花费超过30元 ([白领午餐报告:一线城市CBD“打工人”既爱平价又要品质_腾讯新闻](https://news.qq.com/rain/a/20201105A0BH1G00#:~:text=%E4%BE%BF%E5%88%A9%E8%9C%82%E7%BB%BC%E5%90%88%E5%90%84%E5%9C%B0%E6%83%85%E5%86%B5%EF%BC%8C65.2%25%E7%9A%84%E6%B6%88%E8%B4%B9%E8%80%85%E5%8D%88%E9%A4%90%E8%B4%B9%E7%94%A8%E6%8E%A7%E5%88%B6%E5%9C%A820%E5%85%83%E4%BB%A5%E5%86%85%EF%BC%8C%E5%85%B6%E6%AC%A1%E6%98%AF21))。因此上海市中心工作日简餐人均**约25~30元**,略高于北京海淀的**约20~25元**。 +- **晚餐(普通餐厅)**:在普通餐馆就餐的人均消费上海也稍高。尽管近年价格有所上涨,**北京海淀普通餐厅人均约70~80元**,上海市中心**约80~100元**。例如据中国烹饪协会数据,早在2010年上海外出就餐人均消费达88元,北京为67元 ([上海餐厅数量居首 就餐人均消费88元_中国烹饪协会](https://m.ccas.com.cn/site/content/102712.html#:~:text=%E9%99%A4%E4%BA%86%E4%B8%8A%E6%B5%B7%EF%BC%8C%E5%A4%A7%E4%BC%97%E7%82%B9%E8%AF%84%E7%BD%91%E8%BF%98%E5%AF%B9%E5%8C%97%E4%BA%AC%E3%80%81%E5%B9%BF%E5%B7%9E%E3%80%81%E6%B7%B1%E5%9C%B3%E3%80%81%E6%9D%AD%E5%B7%9E%E3%80%81%E5%8D%97%E4%BA%AC%E3%80%81%E5%A4%A9%E6%B4%A5%E7%AD%89%E5%9F%8E%E5%B8%82%E7%9A%84%E5%95%86%E6%88%B7%E6%95%B0%E6%8D%AE%E5%92%8C%E7%94%A8%E6%88%B7%E8%A1%8C%E4%B8%BA%E4%B9%A0%E6%83%AF%E8%BF%9B%E8%A1%8C%E4%BA%86%E8%BF%BD%E8%B8%AA%E5%88%86%E6%9E%90%E3%80%82%E5%9C%A8%E9%A4%90%E9%A5%AE%E6%B6%88%E8%B4%B9%E6%96%B9%E9%9D%A2%EF%BC%8C%E4%BB%85%E6%AC%A1%E4%BA%8E%E4%B8%8A%E6%B5%B7%E3%80%81%E6%8E%92%E5%90%8D%E7%AC%AC%E4%BA%8C%E7%9A%84%E6%98%AF%E6%B7%B1%E5%9C%B3%EF%BC%88%E4%BA%BA%E5%9D%8770%E5%85%83))(上海高出约30%),近年来双方绝对值上涨但差距比例相近。 +- **咖啡馆**:咖啡饮品价格在两地差异不大。连锁咖啡如星巴克拿铁一杯普遍**在30元以上** ([热议!为什么国内喝星巴克的人越来越少了? - 证券时报](https://www.stcn.com/article/detail/815959.html#:~:text=%E7%83%AD%E8%AE%AE%EF%BC%81%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9B%BD%E5%86%85%E5%96%9D%E6%98%9F%E5%B7%B4%E5%85%8B%E7%9A%84%E4%BA%BA%E8%B6%8A%E6%9D%A5%E8%B6%8A%E5%B0%91%E4%BA%86%EF%BC%9F%20,))(全国统一定价)。本地精品咖啡在上海选择更多,高端咖啡厅单杯价格可能达到40元以上,北京也有类似价位的精品咖啡。总体看**普通拿铁/美式咖啡约30元左右**,两地基本持平。 +- **中高端餐厅**:上海市中心的中高端餐厅人均消费显著高于北京。根据**2024年上海世界美食分布指数**,上海**黄浦区**中高端餐厅人均消费约**211.6元**,为全市最高 ([2024“上海世界美食分布指数”发布,人均消费最高的是这个区_数量最多_浦东_菜系](https://m.sohu.com/a/867475857_120578424/%3Fpvid%3D000115_3w_a%26scm%3D10001.1355_13-100000-0_922.0-0.0.a2_5X162X1627#:~:text=%E6%95%B0%E9%87%8F%E5%90%8C%E6%AF%94%E5%87%8F%E5%B0%91%E7%9A%84%E5%89%8D6%E5%90%8D%E4%B8%BA%E9%9D%99%E5%AE%89%E5%8C%BA%E3%80%81%E5%AE%9D%E5%B1%B1%E5%8C%BA%E3%80%81%E9%9D%92%E6%B5%A6%E5%8C%BA%E3%80%81%E6%9D%A8%E6%B5%A6%E5%8C%BA%E3%80%81%E6%9D%BE%E6%B1%9F%E5%8C%BA%20%E5%92%8C%20%E9%87%91%E5%B1%B1%E5%8C%BA%EF%BC%8C%E5%87%8F%E5%B0%91%E5%B9%85%E5%BA%A6%E4%BB%8E73%E5%AE%B6%E5%88%B05%E5%AE%B6%E4%B8%8D%E7%AD%89%E3%80%82));长宁区约162元,徐汇区约157元。北京海淀的高端餐饮选择相对较少,多集中在高校、科技园周边的商务餐厅,人均消费一般**在150~200元**左右(顶级餐厅在300元以上)。因此在高端用餐方面,**上海核心区人均约200~300元**,比**北京海淀的150~250元**高出一截。 + +上述餐饮价格差异反映在下表中: + +| **消费类型** | **北京海淀区均价** | **上海市中心均价** | **差异说明** | +| -------------------- | ------------------ | ------------------ | ------------------------------------------------------------ | +| **工作日午餐** | 20元左右/人 | 25~30元/人 | 上海白领午餐花费略高,30元以上占比上海最高 ([白领午餐报告:一线城市CBD“打工人”既爱平价又要品质_腾讯新闻](https://news.qq.com/rain/a/20201105A0BH1G00#:~:text=%E4%BE%BF%E5%88%A9%E8%9C%82%E7%BB%BC%E5%90%88%E5%90%84%E5%9C%B0%E6%83%85%E5%86%B5%EF%BC%8C65.2%25%E7%9A%84%E6%B6%88%E8%B4%B9%E8%80%85%E5%8D%88%E9%A4%90%E8%B4%B9%E7%94%A8%E6%8E%A7%E5%88%B6%E5%9C%A820%E5%85%83%E4%BB%A5%E5%86%85%EF%BC%8C%E5%85%B6%E6%AC%A1%E6%98%AF21))。 | +| **晚餐(普通餐厅)** | 70~80元/人 | 80~100元/人 | 上海高约10%–20%;2010年上海88,北京67元 ([上海餐厅数量居首 就餐人均消费88元_中国烹饪协会](https://m.ccas.com.cn/site/content/102712.html#:~:text=%E9%99%A4%E4%BA%86%E4%B8%8A%E6%B5%B7%EF%BC%8C%E5%A4%A7%E4%BC%97%E7%82%B9%E8%AF%84%E7%BD%91%E8%BF%98%E5%AF%B9%E5%8C%97%E4%BA%AC%E3%80%81%E5%B9%BF%E5%B7%9E%E3%80%81%E6%B7%B1%E5%9C%B3%E3%80%81%E6%9D%AD%E5%B7%9E%E3%80%81%E5%8D%97%E4%BA%AC%E3%80%81%E5%A4%A9%E6%B4%A5%E7%AD%89%E5%9F%8E%E5%B8%82%E7%9A%84%E5%95%86%E6%88%B7%E6%95%B0%E6%8D%AE%E5%92%8C%E7%94%A8%E6%88%B7%E8%A1%8C%E4%B8%BA%E4%B9%A0%E6%83%AF%E8%BF%9B%E8%A1%8C%E4%BA%86%E8%BF%BD%E8%B8%AA%E5%88%86%E6%9E%90%E3%80%82%E5%9C%A8%E9%A4%90%E9%A5%AE%E6%B6%88%E8%B4%B9%E6%96%B9%E9%9D%A2%EF%BC%8C%E4%BB%85%E6%AC%A1%E4%BA%8E%E4%B8%8A%E6%B5%B7%E3%80%81%E6%8E%92%E5%90%8D%E7%AC%AC%E4%BA%8C%E7%9A%84%E6%98%AF%E6%B7%B1%E5%9C%B3%EF%BC%88%E4%BA%BA%E5%9D%8770%E5%85%83))。 | +| **咖啡馆咖啡** | ~30元/杯 | ~30元/杯 | 全国连锁定价一致,两地价格基本相同 ([热议!为什么国内喝星巴克的人越来越少了? - 证券时报](https://www.stcn.com/article/detail/815959.html#:~:text=%E7%83%AD%E8%AE%AE%EF%BC%81%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9B%BD%E5%86%85%E5%96%9D%E6%98%9F%E5%B7%B4%E5%85%8B%E7%9A%84%E4%BA%BA%E8%B6%8A%E6%9D%A5%E8%B6%8A%E5%B0%91%E4%BA%86%EF%BC%9F%20,))。 | +| **中高端餐厅** | 150~250元/人 | 200~300元/人 | 上海高端餐厅更集中,人均~212元(黄浦,2024) ([2024“上海世界美食分布指数”发布,人均消费最高的是这个区_数量最多_浦东_菜系](https://m.sohu.com/a/867475857_120578424/%3Fpvid%3D000115_3w_a%26scm%3D10001.1355_13-100000-0_922.0-0.0.a2_5X162X1627#:~:text=%E6%95%B0%E9%87%8F%E5%90%8C%E6%AF%94%E5%87%8F%E5%B0%91%E7%9A%84%E5%89%8D6%E5%90%8D%E4%B8%BA%E9%9D%99%E5%AE%89%E5%8C%BA%E3%80%81%E5%AE%9D%E5%B1%B1%E5%8C%BA%E3%80%81%E9%9D%92%E6%B5%A6%E5%8C%BA%E3%80%81%E6%9D%A8%E6%B5%A6%E5%8C%BA%E3%80%81%E6%9D%BE%E6%B1%9F%E5%8C%BA%20%E5%92%8C%20%E9%87%91%E5%B1%B1%E5%8C%BA%EF%BC%8C%E5%87%8F%E5%B0%91%E5%B9%85%E5%BA%A6%E4%BB%8E73%E5%AE%B6%E5%88%B05%E5%AE%B6%E4%B8%8D%E7%AD%89%E3%80%82))。 | + +*数据来源:便利蜂《白领午餐报告》 (2020) ([白领午餐报告:一线城市CBD“打工人”既爱平价又要品质_腾讯新闻](https://news.qq.com/rain/a/20201105A0BH1G00#:~:text=%E5%9C%A8%E8%AE%B8%E5%A4%9A%E4%BA%BA%E7%9A%84%E6%83%B3%E8%B1%A1%E4%B8%AD%EF%BC%8C%E5%87%BA%E5%85%A5%E4%B8%80%E7%BA%BF%E5%9F%8E%E5%B8%82CBD%E9%AB%98%E7%AB%AF%E5%86%99%E5%AD%97%E6%A5%BC%E7%9A%84%E7%99%BD%E9%A2%86%EF%BC%8C%E6%AF%8F%E5%A4%A9%E4%BA%AB%E7%94%A8%E7%9A%84%E5%8D%88%E9%A4%90%E5%BA%94%E8%AF%A5%E4%B9%9F%E4%BB%B7%E6%A0%BC%E4%B8%8D%E8%8F%B2%E3%80%82%E4%BD%86%E7%BB%9F%E8%AE%A1%E5%8F%91%E7%8E%B0%EF%BC%8C%E5%8D%B3%E4%BD%BF%E5%9C%A8%E8%BF%99%E4%BA%9B%E5%9C%B0%E6%96%B9%EF%BC%8C%E7%99%BD%E9%A2%86%E7%9A%84%E5%8D%88%E9%A4%90%E9%80%89%E6%8B%A9%E4%B9%9F%E4%BB%A5%E5%B9%B3%E4%BB%B7%E4%B8%BA%E4%B8%BB%E3%80%82));中国烹饪协会数据 (2010) ([上海餐厅数量居首 就餐人均消费88元_中国烹饪协会](https://m.ccas.com.cn/site/content/102712.html#:~:text=%E9%99%A4%E4%BA%86%E4%B8%8A%E6%B5%B7%EF%BC%8C%E5%A4%A7%E4%BC%97%E7%82%B9%E8%AF%84%E7%BD%91%E8%BF%98%E5%AF%B9%E5%8C%97%E4%BA%AC%E3%80%81%E5%B9%BF%E5%B7%9E%E3%80%81%E6%B7%B1%E5%9C%B3%E3%80%81%E6%9D%AD%E5%B7%9E%E3%80%81%E5%8D%97%E4%BA%AC%E3%80%81%E5%A4%A9%E6%B4%A5%E7%AD%89%E5%9F%8E%E5%B8%82%E7%9A%84%E5%95%86%E6%88%B7%E6%95%B0%E6%8D%AE%E5%92%8C%E7%94%A8%E6%88%B7%E8%A1%8C%E4%B8%BA%E4%B9%A0%E6%83%AF%E8%BF%9B%E8%A1%8C%E4%BA%86%E8%BF%BD%E8%B8%AA%E5%88%86%E6%9E%90%E3%80%82%E5%9C%A8%E9%A4%90%E9%A5%AE%E6%B6%88%E8%B4%B9%E6%96%B9%E9%9D%A2%EF%BC%8C%E4%BB%85%E6%AC%A1%E4%BA%8E%E4%B8%8A%E6%B5%B7%E3%80%81%E6%8E%92%E5%90%8D%E7%AC%AC%E4%BA%8C%E7%9A%84%E6%98%AF%E6%B7%B1%E5%9C%B3%EF%BC%88%E4%BA%BA%E5%9D%8770%E5%85%83));上海市商业联合会(2025) ([2024“上海世界美食分布指数”发布,人均消费最高的是这个区_数量最多_浦东_菜系](https://m.sohu.com/a/867475857_120578424/%3Fpvid%3D000115_3w_a%26scm%3D10001.1355_13-100000-0_922.0-0.0.a2_5X162X1627#:~:text=%E6%95%B0%E9%87%8F%E5%90%8C%E6%AF%94%E5%87%8F%E5%B0%91%E7%9A%84%E5%89%8D6%E5%90%8D%E4%B8%BA%E9%9D%99%E5%AE%89%E5%8C%BA%E3%80%81%E5%AE%9D%E5%B1%B1%E5%8C%BA%E3%80%81%E9%9D%92%E6%B5%A6%E5%8C%BA%E3%80%81%E6%9D%A8%E6%B5%A6%E5%8C%BA%E3%80%81%E6%9D%BE%E6%B1%9F%E5%8C%BA%20%E5%92%8C%20%E9%87%91%E5%B1%B1%E5%8C%BA%EF%BC%8C%E5%87%8F%E5%B0%91%E5%B9%85%E5%BA%A6%E4%BB%8E73%E5%AE%B6%E5%88%B05%E5%AE%B6%E4%B8%8D%E7%AD%89%E3%80%82))等。上海数据为市中心平均水平,北京为海淀区估计值。* + +## 2. 娱乐消费对比 + +在娱乐消费方面,**电影、KTV等大众娱乐项目**两地价格相近或上海略高;而**健身、展览及夜生活**方面,因为消费习惯和供给不同,也存在一些差异。 + +- **电影院票价**:近年来全国电影票价上涨明显,**2023年全国平均电影票价约42.7元** ([一家人看场电影花400多元低价电影票为何难觅踪影 - 人民日报](https://www.peopleapp.com/column/30035419895-500000471976#:~:text=%E4%B8%80%E5%AE%B6%E4%BA%BA%E7%9C%8B%E5%9C%BA%E7%94%B5%E5%BD%B1%E8%8A%B1400%E5%A4%9A%E5%85%83%E4%BD%8E%E4%BB%B7%E7%94%B5%E5%BD%B1%E7%A5%A8%E4%B8%BA%E4%BD%95%E9%9A%BE%E8%A7%85%E8%B8%AA%E5%BD%B1%20,))。北京海淀和上海市中心的影院普通2D场次票价一般在**40~50元**区间,周末或IMAX厅可能高达70~100元,工作日或优惠日最低20~30元。整体看**上海核心区平均票价略高**(约50元左右)但差异不大,北京海淀约45元。两地均受全国影院优惠活动影响,票价浮动明显。 +- **KTV**:量贩式KTV收费在一线城市趋同。北京海淀热门KTV晚高峰中等包间**约¥200/小时**,平时或白天有折扣。上海市中心KTV由于地段租金更高,价格略贵,中等包间晚间**约¥240/小时**,人均分摊下来约每人**¥100+**。总体**上海比北京贵约10%~20%**。此外,一些上海高端KTV设最低消费,提升了聚会成本。需要说明的是,近年来KTV行业整体萎缩,但**一线城市主流KTV消费**仍然不低,每人一次K歌消费通常**在100-200元**之间。 +- **健身房**:北京海淀和上海市中心的健身房会员价位差异较大。大众健身房年卡全国平均成交价约**1259元** ([中国健身房收费,贵吗? - 36氪](https://m.36kr.com/p/1188297244573960#:~:text=%E8%80%8C%E9%87%91%E5%90%89%E9%B8%9F%E5%9C%A8%E5%AE%81%E6%B3%A2%E7%9A%84%E9%97%A8%E5%BA%97%EF%BC%8C%E5%8D%95%E4%BA%BA%E5%8D%95%E5%BA%97%E5%B9%B4%E5%8D%A12980%E5%85%83%EF%BC%8C%E5%8D%81%E5%B9%B4%E5%85%A8%E5%B8%82%20))(2020年数据),但一线城市高端健身会所价格远高于此。例如**上海Will’s健身**单店年卡约**¥4288** ([中国健身房收费,贵吗? - 36氪](https://m.36kr.com/p/1188297244573960#:~:text=%E4%B8%AD%E5%9B%BD%E5%81%A5%E8%BA%AB%E6%88%BF%E6%94%B6%E8%B4%B9%EF%BC%8C%E8%B4%B5%E5%90%97%EF%BC%9F%20,));**PURE Fitness**等高端会所甚至月费高达¥1399 ([PURE Fitness](https://pure-fitness.cn/shanghai/news/detail/629#:~:text=PURE%20Fitness%20RMB%20298%E8%B5%B7%E2%80%93%20PURE,%E4%B8%8D%E5%90%8C%E4%BC%9A%E9%A6%86%E7%9A%84%E5%A5%97%E9%A4%90%E4%BB%B7%E6%A0%BC%E6%9C%89%E6%89%80%E8%B0%83%E6%95%B4%EF%BC%8C%E4%BB%A5%E4%BA%A7%E5%93%81%E7%9A%84%E5%AE%9E%E9%99%85%E8%B4%AD%E4%B9%B0%E9%A1%B5%E9%9D%A2%E4%BB%B7%E6%A0%BC%E4%B8%BA%E5%87%86%E3%80%82%208))。北京海淀普通健身房年卡**约2000~3000元**,大型连锁如威尔仕年卡约¥3500左右。上海市中心健身房**约3000~4000元/年**常见,高端会所更多,均价高于北京。总体看,**上海健身消费比北京贵约20%~50%**,但两地也都有平价健身房供选择(月卡低至¥100~200)。 +- **展览馆/美术馆**:两地公共博物馆、美术馆不少实行免费或低票价预约制度。例如北京的中国国家博物馆、上海博物馆均免费开放;北京故宫旺季门票60元,上海部分热门特展票价在50~100元。**平均来看**,常规展览票价**约20~50元**,**特别展览**(如知名艺术家的巡展、沉浸式展览等)**约80~120元**。两地此类文化消费差异不明显,**海淀居民可免费享受首都丰富的国家级博物馆资源**,而**上海市民国际化展览选择更多但多数需购票**。总体而言,**日常展馆文化消费在两地都不属于高消费**,票价相对亲民。 +- **夜生活(酒吧/夜店)**:上海市中心的夜生活场所更为繁华,价格亦偏高。**酒吧**方面,北京海淀的夜生活主要集中在高校周边和中关村商圈,消费相对有限;北京市民常前往三里屯、工体等地(属于朝阳区)娱乐。一般北京酒吧**本地啤酒 ¥30~40/瓶,鸡尾酒 ¥60~80/杯**;上海外滩、静安寺等高档酒吧**啤酒 ¥40~60,鸡尾酒 ¥8~120**不等。上海高端夜店的入场和包座费用也高于北京。同类酒吧**上海人均夜消费约200元以上**,北京**约150~200元**。不过,两地也都有亲民的酒馆和夜市大排档,本地啤酒10几元即可。所以夜生活消费差异更多体现在**高端场所**:上海顶级酒吧夜总会的消费水准全国领先,而北京海淀本区夜生活相对平静,需到其它城区体验。 + +## 3. 生活成本对比 + +### 房租与居住成本 + +**住房租金**是生活成本中最大的支出项。在这方面,上海市中心租金水平通常略高于北京海淀。 + +- **租房价格**:根据链家租赁数据,**2024年1月北京租赁住房套均租金约6479元/月** ([北京链家:预计春节假期后新增、换租需求增加 推动2月租赁市场升温|北京市_新浪财经_新浪网](https://finance.sina.com.cn/jjxw/2024-02-05/doc-inafywyy7551152.shtml#:~:text=%E4%B8%AD%E5%BF%83%E5%9F%8E%E5%8C%BA%E9%A2%84%E8%AE%A1%E4%BC%9A%E6%9C%89%E6%89%80%E5%B0%8F%E5%B9%85%E4%B8%8A%E6%B6%A8%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%BC%9A%E6%9C%89%E9%83%A8%E5%88%86%E7%BE%A4%E4%BD%93%E8%80%83%E8%99%91%E9%80%89%E6%8B%A9%E5%B9%B4%E5%89%8D%E7%A7%9F%E6%88%BF%E3%80%82))。海淀区作为北京科教重地,房租高于郊区但略低于东城/西城等核心区。同等房型下,**海淀区一居室月租约¥5000~6000**,两居室**¥7000~9000** ([一线城市房租降了? - 中国新闻周刊网](http://www.inewsweek.cn/society/2024-01-17/21059.shtml#:~:text=%E4%B8%AD%E4%BB%8B%E7%8E%8B%E8%AF%9A%E5%AF%B9%E4%B8%AD%E5%9B%BD%E6%96%B0%E9%97%BB%E5%91%A8%E5%88%8A%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%9B%AE%E5%89%8D%E9%99%84%E8%BF%91%E4%B8%80%E5%B1%85%E5%AE%A4%E6%88%BF%E7%A7%9F%E5%9C%A85000))。上海市中心黄浦、静安等地因地段繁华、供需紧张,**一居室平均月租约¥7000+**,与北京相差不大 ([Cost of Living in China in 2025 - MSA Advisory](https://msadvisory.com/cost-of-living-in-china/#:~:text=Cost%20of%20Living%20in%20China,accommodations%20average%20around%206%252C500%20RMB));**两居室普遍¥8000~12000**,高档公寓甚至更贵。总体看,**上海市中心租金比北京海淀高出约10~20%**。例如有报告指出,**上海市区一居平均租金约¥7000,略高于北京的¥6500** ([Cost of Living in China in 2025 - MSA Advisory](https://msadvisory.com/cost-of-living-in-china/#:~:text=Cost%20of%20Living%20in%20China,accommodations%20average%20around%206%252C500%20RMB))。下表汇总了房租等居住成本对比: + +| **生活成本** | **北京海淀区** | **上海市中心** | **差异说明** | +| -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| **住房租金(月)** | 一居约¥5500, 两居¥8000 | 一居约¥7000, 两居¥9000+ | 上海租金略高10~20%, 一居约¥7000[msadvisory.com](https://msadvisory.com/cost-of-living-in-china/#:~:text=Cost%20of%20Living%20in%20China,accommodations%20average%20around%206%252C500%20RMB)。 | +| **水电燃气费(月)** | ~¥300(两人户均) | ~¥300(两人户均) | 差异小;北方集中供暖, 冬季供暖费12元/㎡·季[m.bj.bendibao.com](https://m.bj.bendibao.com/zffw/245599.html#:~:text=%282)基本热价:按照建筑面积征收,大网供应的为每采暖季每建筑平方米12元%3B独网供应的燃气、燃油或电锅炉为每采暖季每建筑平方米18元。 (3)计量热价:按照用 )。 | +| **公共交通(月)** | ~¥150(地铁公交通勤) | ~¥180(地铁公交通勤) | 北京地铁月支出满100元享8折、150元后5折[fgw.beijing.gov.cn](https://fgw.beijing.gov.cn/bmcx/djcx/cxldj/202003/t20200331_1752788.htm#:~:text=%E4%BD%BF%E7%94%A8%E5%B8%82%E6%94%BF%E4%BA%A4%E9%80%9A%E4%B8%80%E5%8D%A1%E9%80%9A%E5%88%B7%E5%8D%A1%E4%B9%98%E5%9D%90%E8%BD%A8%E9%81%93%E4%BA%A4%E9%80%9A%EF%BC%8C%E6%AF%8F%E8%87%AA%E7%84%B6%E6%9C%88%E5%86%85%E6%AF%8F%E5%BC%A0%E5%8D%A1%E6%94%AF%E5%87%BA%E7%B4%AF%E8%AE%A1%E6%BB%A1100%E5%85%83%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%BB%B7%E6%A0%BC%E7%BB%99%E4%BA%888%E6%8A%98%E4%BC%98%E6%83%A0%EF%BC%9B%E6%BB%A1150%E5%85%83%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%BB%B7%E6%A0%BC%E7%BB%99%E4%BA%885%E6%8A%98%E4%BC%98%E6%83%A0%EF%BC%9B%E6%94%AF%E5%87%BA%E7%B4%AF%E8%AE%A1%E8%BE%BE%E5%88%B0400%E5%85%83%20%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%B8%8D%E5%86%8D%20);上海无月折扣。 | +| **出租车起步价** | ¥13/3公里(白天)[m.wuhan.com](https://m.wuhan.com/xinwen/116093.html#:~:text=2023%E5%B9%B4%E5%8C%97%E4%BA%AC%E5%87%BA%E7%A7%9F%E8%BD%A6%E8%B5%B7%E6%AD%A5%E9%87%8C%E7%A8%8B%E5%9C%A83%E5%85%AC%E9%87%8C%E4%BB%A5%E5%86%85%EF%BC%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E4%B8%BA13%E5%85%83%EF%BC%8C%E8%B6%85%E8%BF%873%E5%85%AC%E9%87%8C%E5%90%8E%E6%AF%8F%E5%85%AC%E9%87%8C%E5%9F%BA%E6%9C%AC%E5%8D%95%E4%BB%B7%E6%98%AF2) | ¥14/3公里(白天) | 上海起步价高¥1, 计程费相近(~¥2.5/公里)。 | +| **共享单车月卡** | ¥13~18/月[finance.sina.com.cn](https://finance.sina.com.cn/jjxw/2024-08-02/doc-incheqct4363575.shtml#:~:text=%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E4%B9%8B%E5%A4%96%EF%BC%8C%E5%85%B1%E4%BA%AB%E5%8D%95%E8%BD%A6%E5%8C%85%E6%9C%88%E4%BB%B7%E6%A0%BC%E4%B9%9F%E5%9C%A8%E6%82%84%E7%84%B6%E4%B8%8A%E6%B6%A8%E3%80%82) | ¥13~18/月[finance.sina.com.cn](https://finance.sina.com.cn/jjxw/2024-08-02/doc-incheqct4363575.shtml#:~:text=%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E4%B9%8B%E5%A4%96%EF%BC%8C%E5%85%B1%E4%BA%AB%E5%8D%95%E8%BD%A6%E5%8C%85%E6%9C%88%E4%BB%B7%E6%A0%BC%E4%B9%9F%E5%9C%A8%E6%82%84%E7%84%B6%E4%B8%8A%E6%B6%A8%E3%80%82) | 价格全国趋同,月卡折扣后约¥15, 骑行1小时约¥4-5[thepaper.cn](https://www.thepaper.cn/newsDetail_forward_28383127#:~:text=%E8%BF%91%E6%97%A5%EF%BC%8C%E4%B8%8D%E5%B0%91%E7%BD%91%E5%8F%8B%E7%BA%B7%E7%BA%B7%E8%A1%A8%E7%A4%BA%E9%83%A8%E5%88%86%E5%85%B1%E4%BA%AB%E5%8D%95%E8%BD%A6%E5%93%81%E7%89%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E8%BF%9B%E8%A1%8C%E4%BA%86%E8%B0%83%E6%95%B4%EF%BC%8C%E7%94%B1%E5%8E%9F%E6%9D%A51)。 | + +*数据来源:链家北京租赁报告 (2024) ([北京链家:预计春节假期后新增、换租需求增加 推动2月租赁市场升温|北京市_新浪财经_新浪网](https://finance.sina.com.cn/jjxw/2024-02-05/doc-inafywyy7551152.shtml#:~:text=%E4%B8%AD%E5%BF%83%E5%9F%8E%E5%8C%BA%E9%A2%84%E8%AE%A1%E4%BC%9A%E6%9C%89%E6%89%80%E5%B0%8F%E5%B9%85%E4%B8%8A%E6%B6%A8%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%BC%9A%E6%9C%89%E9%83%A8%E5%88%86%E7%BE%A4%E4%BD%93%E8%80%83%E8%99%91%E9%80%89%E6%8B%A9%E5%B9%B4%E5%89%8D%E7%A7%9F%E6%88%BF%E3%80%82));中国新闻周刊 (2024) ([一线城市房租降了? - 中国新闻周刊网](http://www.inewsweek.cn/society/2024-01-17/21059.shtml#:~:text=%E4%B8%AD%E4%BB%8B%E7%8E%8B%E8%AF%9A%E5%AF%B9%E4%B8%AD%E5%9B%BD%E6%96%B0%E9%97%BB%E5%91%A8%E5%88%8A%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%9B%AE%E5%89%8D%E9%99%84%E8%BF%91%E4%B8%80%E5%B1%85%E5%AE%A4%E6%88%BF%E7%A7%9F%E5%9C%A85000));MS Advisory (2025) ([Cost of Living in China in 2025 - MSA Advisory](https://msadvisory.com/cost-of-living-in-china/#:~:text=Cost%20of%20Living%20in%20China,accommodations%20average%20around%206%252C500%20RMB));北京市发改委/上海交通卡中心等。水电费按照居民第一阶梯:电¥0.52/度、水¥5/吨、气¥2.8/方估算;北京集中供暖费参考北京市政规定12元/㎡·季 ([2024-2025年北京供暖时间、收费标准](https://m.bj.bendibao.com/zffw/245599.html#:~:text=%282)基本热价:按照建筑面积征收,大网供应的为每采暖季每建筑平方米12元%3B独网供应的燃气、燃油或电锅炉为每采暖季每建筑平方米18元。 (3)计量热价:按照用 ))。* + +上述表格显示**租金是两地生活成本差距的主要来源**。此外,北京海淀冬季有集中供暖是显著福利:按北京市标准每平米每采暖季12元 ([2024-2025年北京供暖时间、收费标准](https://m.bj.bendibao.com/zffw/245599.html#:~:text=%282)基本热价:按照建筑面积征收,大网供应的为每采暖季每建筑平方米12元%3B独网供应的燃气、燃油或电锅炉为每采暖季每建筑平方米18元。 (3)计量热价:按照用 ))(80㎡房每月折合约160元),供热充足;上海无集中供暖,居民需自行开空调取暖,冬季电费开支上升,但由于上海冬季相对短而暖,总体能源支出差别不大。水、电、燃气价格均由政府定价,一线城市标准接近,因此**日常水电气费用两地相差很小**。 + +### 日用品与交通出行 + +- **日用品与超市采购**:北京海淀和上海市中心的超市日用品价格总体接近。一线城市大型连锁超市(如永辉、家乐福)定价差别不大,蔬菜、肉类等民生品受当地供应影响会有小幅波动。举例来说,2024年底北京猪肉价略有回落、上海蔬菜价受季节影响略高,但总体在全国价格体系中均处上游但相互差别有限。**便利店**商品(瓶装饮料、零食等)两地定价统一:可口可乐500ml约¥3,矿泉水¥2,关东煮、盒饭等现制食品在上海便利店种类更多但价格类似。在**进口商品**方面,如进口牛奶、零食,由于各地关税和物流相同,上海和北京的大型商超售价基本一致,但上海高端超市(CitySuper、Ole’等)更集中,海淀居民则可能通过电商购买进口商品。总的来说,**日用品购置成本两地几乎没有明显差异**。 +- **公共交通**:两城市公共交通发达且票价亲民。北京市内公交**起步2元**(刷卡5折优惠为1元) ([公共交通价格-出行-北京市发展和改革委员会](https://fgw.beijing.gov.cn/bmcx/djcx/cxldj/202003/t20200331_1752788.htm#:~:text=%E5%9F%8E%E5%B8%82%E5%85%AC%E5%85%B1%E7%94%B5%E6%B1%BD%E8%BD%A6));地铁按里程计价**起步3元**,**每月累积满100元打8折,150元后5折** ([公共交通价格-出行-北京市发展和改革委员会](https://fgw.beijing.gov.cn/bmcx/djcx/cxldj/202003/t20200331_1752788.htm#:~:text=%E4%BD%BF%E7%94%A8%E5%B8%82%E6%94%BF%E4%BA%A4%E9%80%9A%E4%B8%80%E5%8D%A1%E9%80%9A%E5%88%B7%E5%8D%A1%E4%B9%98%E5%9D%90%E8%BD%A8%E9%81%93%E4%BA%A4%E9%80%9A%EF%BC%8C%E6%AF%8F%E8%87%AA%E7%84%B6%E6%9C%88%E5%86%85%E6%AF%8F%E5%BC%A0%E5%8D%A1%E6%94%AF%E5%87%BA%E7%B4%AF%E8%AE%A1%E6%BB%A1100%E5%85%83%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%BB%B7%E6%A0%BC%E7%BB%99%E4%BA%888%E6%8A%98%E4%BC%98%E6%83%A0%EF%BC%9B%E6%BB%A1150%E5%85%83%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%BB%B7%E6%A0%BC%E7%BB%99%E4%BA%885%E6%8A%98%E4%BC%98%E6%83%A0%EF%BC%9B%E6%94%AF%E5%87%BA%E7%B4%AF%E8%AE%A1%E8%BE%BE%E5%88%B0400%E5%85%83%20%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%B8%8D%E5%86%8D%20))。上海公交**起步2元**(无普遍折扣政策),地铁亦为里程计价**起步3元**,乘坐距离相近时费用与北京相当。通勤族月公交地铁支出,北京约¥150,上海约¥180,主要区别在于**北京有月度优惠封顶**,上海目前仅有**日票/三日票**等游客票,并无市民月票制。整体而言,**公共交通费用两地都很低廉,占收入比很小**。 +- **打车出行**:北京和上海出租车计价标准接近。北京**白天起步价¥13/3公里**,基本单价¥2.3-¥2.6/公里,夜间起步¥14 ([北京出租车起步价及收费标准(2024年更新)_北京租车](https://www.mapgz.com/rm/5513.html#:~:text=,%E5%A4%9C%E9%97%B4%E8%B5%B7%E6%AD%A5%E4%BB%B7%EF%BC%9A%C2%A514%E5%85%83%EF%BC%88%E5%8C%85%E5%90%AB3%E5%85%AC%E9%87%8C%EF%BC%89)) ([北京出租车起步价及收费标准(2024年更新)_北京租车](https://www.mapgz.com/rm/5513.html#:~:text=%2A%20%E6%99%AE%E9%80%9A%E5%87%BA%E7%A7%9F%E8%BD%A6%EF%BC%88%E7%87%83%E6%B2%B9%E8%BD%A6%EF%BC%89%EF%BC%9A%20%2A%20%E6%97%A5%E9%97%B4%EF%BC%885%253A00,5%253A00%EF%BC%89%EF%BC%9A%C2%A53.1%E5%85%83%252F%E5%85%AC%E9%87%8C))。上海**白天起步价一般为¥14/3公里**,每公里单价约¥2.5,略高于北京;夜间起步约¥18。两地网约车(如滴滴)定价机制类似,会在高峰时段动态加价。**短途打车**上海贵一点点,但总体差别不显著。例如一趟5公里白天行程,北京约¥18-20,上海约¥20-22。需要注意上海市中心打车需求量大,“打车难”有时较北京更突出。 +- **共享单车**:共享单车已成为两城居民短途出行的重要补充。美团、哈啰、青桔等单车在北京海淀和上海中心均大量投放。**计费**模式基本一致:起步价每15分钟¥1.5,部分城市调整为前10分钟¥1.5,之后每15分钟¥1元 ([共享单车,只剩涨价一途? - 杭州](https://hznews.hangzhou.com.cn/chengshi/content/2024-08/09/content_8771240_0.htm#:~:text=%E5%85%B1%E4%BA%AB%E5%8D%95%E8%BD%A6%EF%BC%8C%E5%8F%AA%E5%89%A9%E6%B6%A8%E4%BB%B7%E4%B8%80%E9%80%94%EF%BC%9F%20))。**月卡**优惠近年有所缩水,但两地价格相同——30天骑行卡原价约¥35,折扣后约¥15左右 ([共享单车涨价 连续包月告别个位数|滴滴_新浪财经_新浪网](https://finance.sina.com.cn/jjxw/2024-08-02/doc-incheqct4363575.shtml#:~:text=%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E4%B9%8B%E5%A4%96%EF%BC%8C%E5%85%B1%E4%BA%AB%E5%8D%95%E8%BD%A6%E5%8C%85%E6%9C%88%E4%BB%B7%E6%A0%BC%E4%B9%9F%E5%9C%A8%E6%82%84%E7%84%B6%E4%B8%8A%E6%B6%A8%E3%80%82))。例如2024年美团单车在北京部分地区30天卡折扣价¥18.8,连续包月首月¥13.8 ([共享单车涨价 连续包月告别个位数|滴滴_新浪财经_新浪网](https://finance.sina.com.cn/jjxw/2024-08-02/doc-incheqct4363575.shtml#:~:text=%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E4%B9%8B%E5%A4%96%EF%BC%8C%E5%85%B1%E4%BA%AB%E5%8D%95%E8%BD%A6%E5%8C%85%E6%9C%88%E4%BB%B7%E6%A0%BC%E4%B9%9F%E5%9C%A8%E6%82%84%E7%84%B6%E4%B8%8A%E6%B6%A8%E3%80%82));上海亦执行相同定价策略。因此骑行成本**在两地无差异**:**单次骑行平均约1~2元,月支出十几元**,对居民支出影响可以忽略不计。 + +### 图表:两地主要消费对比 + +![d1c7956f-c6c5-43f6-be00-a2452fdc1388](./%E5%8C%97%E4%BA%AC%E6%B5%B7%E6%B7%80%20vs.%20%E4%B8%8A%E6%B5%B7%E5%B8%82%E4%B8%AD%E5%BF%83%E6%B6%88%E8%B4%B9%E6%B0%B4%E5%B9%B3%E5%AF%B9%E6%AF%94%E6%8A%A5%E5%91%8A.assets/d1c7956f-c6c5-43f6-be00-a2452fdc1388.png) + +下图直观比较了北京海淀与上海市中心在部分日常消费和大宗支出方面的差异(单位人民币): + +([image](https://chatgpt.com/c/680104be-1358-8001-ac2b-2b6a859552bf)) *图:北京海淀 vs 上海市中心 部分消费项均价对比(数据取2024年底估值)。左图为日常小额消费:午餐、晚餐、人均电影票、咖啡;右图为主要生活成本:月租金、年健身费。上海在多数项目上略高于北京。* ([Cost of Living in China in 2025 - MSA Advisory](https://msadvisory.com/cost-of-living-in-china/#:~:text=Cost%20of%20Living%20in%20China,accommodations%20average%20around%206%252C500%20RMB)) ([一家人看场电影花400多元低价电影票为何难觅踪影 - 人民日报](https://www.peopleapp.com/column/30035419895-500000471976#:~:text=%E4%B8%80%E5%AE%B6%E4%BA%BA%E7%9C%8B%E5%9C%BA%E7%94%B5%E5%BD%B1%E8%8A%B1400%E5%A4%9A%E5%85%83%E4%BD%8E%E4%BB%B7%E7%94%B5%E5%BD%B1%E7%A5%A8%E4%B8%BA%E4%BD%95%E9%9A%BE%E8%A7%85%E8%B8%AA%E5%BD%B1%20,)) + +> **说明**:图中数据为根据报告统计和市场价估算的平均值,实际情况因人而异。例如租金根据一居室估算 ([Cost of Living in China in 2025 - MSA Advisory](https://msadvisory.com/cost-of-living-in-china/#:~:text=Cost%20of%20Living%20in%20China,accommodations%20average%20around%206%252C500%20RMB)),午餐根据白领消费习惯估计 ([白领午餐报告:一线城市CBD“打工人”既爱平价又要品质_腾讯新闻](https://news.qq.com/rain/a/20201105A0BH1G00#:~:text=%E5%9C%A8%E8%AE%B8%E5%A4%9A%E4%BA%BA%E7%9A%84%E6%83%B3%E8%B1%A1%E4%B8%AD%EF%BC%8C%E5%87%BA%E5%85%A5%E4%B8%80%E7%BA%BF%E5%9F%8E%E5%B8%82CBD%E9%AB%98%E7%AB%AF%E5%86%99%E5%AD%97%E6%A5%BC%E7%9A%84%E7%99%BD%E9%A2%86%EF%BC%8C%E6%AF%8F%E5%A4%A9%E4%BA%AB%E7%94%A8%E7%9A%84%E5%8D%88%E9%A4%90%E5%BA%94%E8%AF%A5%E4%B9%9F%E4%BB%B7%E6%A0%BC%E4%B8%8D%E8%8F%B2%E3%80%82%E4%BD%86%E7%BB%9F%E8%AE%A1%E5%8F%91%E7%8E%B0%EF%BC%8C%E5%8D%B3%E4%BD%BF%E5%9C%A8%E8%BF%99%E4%BA%9B%E5%9C%B0%E6%96%B9%EF%BC%8C%E7%99%BD%E9%A2%86%E7%9A%84%E5%8D%88%E9%A4%90%E9%80%89%E6%8B%A9%E4%B9%9F%E4%BB%A5%E5%B9%B3%E4%BB%B7%E4%B8%BA%E4%B8%BB%E3%80%82))。 + +## 4. 购物消费与电商 + +**购物消费**方面,北京海淀和上海市中心的居民在日常衣物、超市采购以及网购等行为上也有许多共性,差异主要体现于消费偏好上: + +- **衣物服饰**:两地普通居民的服装消费价格基本同步。一线城市的大型购物中心和时尚品牌门店云集,**快时尚品牌**(如优衣库、ZARA)的定价全国统一,一件T恤在北京上海售价相同。**本土品牌**服饰因运输成本低廉,价格差异也可以忽略。需要指出的是,上海作为时尚之都,**高端奢侈品**店铺更多,消费者选择面更广;上海中高收入人群在奢侈服饰上的消费可能高于北京海淀。但对于普通中产而言,**买衣服花销两地相当**。例如一双耐克运动鞋,全国统一价¥800左右,在京沪都一样。总体看,**服装支出主要取决于个人偏好**而非城市差异。 + +- **超市和生鲜采购**:海淀区与上海市中心均有大量超市、生鲜市场,能够满足居民日常所需。基础食品价格受市场供求和产地影响,全国趋同。比如,2024年末**北京鸡蛋¥5.5/斤,上海¥6/斤**,蔬菜因季节略有差别但供暖季上海需从南方调菜、北京则有大棚蔬菜,**全年下来平均菜价相差不大**。进口水果如牛油果、车厘子在两地超市售价几乎一样。值得一提的是,上海市中心遍布高端进口超市,方便购买多元食材;北京海淀则有大型批发市场(如锦绣大地)提供平价菜肉。总体而言,**家庭日常买菜买米开销两地相近**。有统计显示,2024年北京、上海城镇居民人均食品支出差距很小,反映基本生活成本相仿。 + +- **电商使用频率**:网购在京沪已深度融入居民生活。**2024年全国网络购物用户规模超9亿人** ([我国网络购物用户规模超9亿人 数字消费带动新消费热点](https://www.stdaily.com/web/gdxw/2024-10/18/content_244339.html#:~:text=%25E5%25BD%2593%25E5%2589%258D%25EF%25BC%258C%25E6%2588%2591%25E5%259B%25BD%25E7%25BD%2591%25E7%25BB%259C%25E8%25B4%25AD%25E7%2589%25A9%25E7%2594%25A8%25E6%2588%25B7%25E8%25A7%2584%25E6%25A8%25A1%25E5%25B7%25B2%25E8%25B6%2585%25E8%25BF%25879%25E4%25BA%25BF%25E4%25BA%25BA%25E3%2580%2582%25E6%2595%25B0%25E5%25AD%2597%25E6%25B6%2588%25E8%25B4%25B9%25E6%25B7%25B1%25E5%25BA%25A6%25E8%259E%258D%25E5%2585%25A5%25E7%2594%259F%25E6%25B4%25BB%25EF%25BC%258C%25E4%25BB%25A3%25E8%25A1%25A8%25E7%259D%2580%25E6%25B6%2588%25E8%25B4%25B9%25E5%25B8%2582%25E5%259C%25BA%25E8%25BD%25AC%25E5%259E%258B%25E7%259A%2584%25E6%2596%25B0%25E6%2596%25B9%25E5%2590%2591%25EF%25BC%258C%25E5%25AF%25B9%25E4%25BE%259B%25E7%25BB%2599%25E5%258D%2587%25E7%25BA%25A7%25E4%25B9%259F%25E6%258F%2590%25E5%2587%25BA%25E4%25BA%2586%25E6%2596%25B0%25E8%25A6%2581%25E6%25B1%2582%25E3%2580%2582%25E5%258D%25B3%25E6%2597%25B6%25E9%259B%25B6%25E5%2594%25AE%25E9%259A%258F%25E5%258F%25AB%25E9%259A%258F%25E5%2588%25B0%25E3%2580%2581%25E5%259B%25BD%25E8%25B4%25A7%25E2%2580%259C%25E6%25BD%25AE%25E5%2593%2581%25E2%2580%259D%25E7%25BD%2591%25E4%25B8%258A%25E7%2595%2585%25E9%2594%2580%25E3%2580%2581%25E2%2580%259C%25E9%2593%25B6%2520%25E5%258F%2591%25E2%2580%259D%25E4%25B8%2580%25E6%2597%258F%25E4%25B8%2580%25E9%2594%25AE%25E4%25B8%258B%25E5%258D%2595%25E2%2580%25A6%25E2%2580%25A6%25E5%2588%259B%25E6%2596%25B0%25E6%25B6%2588%25E8%25B4%25B9%25E6%25A8%25A1%25E5%25BC%258F%25E8%2593%25AC%25E5%258B%2583%25E5%258F%2591%25E5%25B1%2595%25E3%2580%2581%25E6%2596%25B0%25E7%259A%2584%25E5%25A2%259E%25E9%2595%25BF%25E7%2582%25B9%25E4%25B8%258D%25E6%2596%25AD%25E6%25B6%258C%25E7%258E%25B0%25E3%2580%2581%25E7%2594%25A8%25E6%2588%25B7%25E5%259F%25BA%25E7%25A1%2580%25E4%25B8%258D%25E6%2596%25AD%25E5%25A4%25AF%25E5%25AE%259E%25EF%25BC%258C%25E6%2595%25B0%25E5%25AD%2597%25E6%25B6%2588%25E8%25B4%25B9%25E6%25AD%25A3%25E5%25BC%2595%25E9%25A2%2586%25E6%25B6%2588%25E8%25B4%25B9%25E6%2596%25B0%25E9%25A3%258E%25E5%25B0%259A%25EF%25BC%258C%25E9%2587%258A%25E6%2594%25BE%25E5%258F%2591%25E5%25B1%2595%25E6%2596%25B0%25E5%258A%25A8%25E8%2583%25BD%25E3%2580%2582)),一线城市尤为发达。北京海淀因高校和互联网企业密集,年轻人接受新兴电商很快;上海消费者则享受发达的电商物流服务,生鲜电商、外卖更是走在全国前列。两地居民**日常网购频繁**:淘宝天猫用于服饰百货,京东超市购买米面粮油,生鲜平台(每日优鲜、叮咚买菜等)半小时送菜上门,手机App一键下单已成习惯。据《中国主要城市共享单车/电单车骑行报告》,**即时零售**和**线上消费**在北上广深渗透率最高。可以说,无论是海淀的互联网从业者还是上海市中心的白领白领,**几乎人人都有几款购物App**,每周甚至每天都在收快递。需要强调的是,**电商普及缩小了地域差异**:海淀居民足不出户也可以买到上海卖的进口牛排,上海市民也能网购中关村卖的电子产品。因此在购物方式上两地都高度数字化,**网购频率和支出占比旗鼓相当**。 + +- **消费偏好与频次**:从消费观念看,上海居民在购物时更注重**品质和国际品牌**,也更青睐线下体验高端购物中心的环境;北京居民(尤其海淀以理工科居多)则对**性价比**较为敏感,网购时喜欢比价,团购打折活动参与度高。这种观念差异可能影响消费结构,但**并不直接体现在日常价格上**。两地中产阶层在生活必需品上花费占收入比都不高,更大的开销往往是房贷房租、子女教育等,在此范围外的**可自由支配消费**,上海可能在奢侈品、精致生活上投入更多,而北京海淀的家庭可能在**教育、数码产品**上投入较高——这与当地产业和文化氛围有关(海淀有众多教育资源和科技公司,电子产品更新换代消费活跃;上海作为金融贸易中心,人们更注重生活品质提升)。 + +## 5. 总结 + +综上所述,北京海淀区与上海市中心在**基本生活消费**方面处于同一量级,**整体消费水平都很高但相差不悬殊**,差异体现在一些细节领域: + +- 上海市中心的**餐饮、娱乐、居住等单价略高于北京海淀**。工作餐、普通就餐贵几块到几十块不等,高端餐饮和夜生活上海有更高消费天花板。 +- **房租**在上海核心区比海淀高出一成左右,叠加上海无冬季集中供暖,这使上海租房族需自理的居住成本稍高。 +- **交通**出行费用两地相差无几,公共交通非常廉价,出租车和共享出行价格几乎同步。 +- **日常购物**包括衣食用度,由于有全国统一的价格体系和发达的电商物流,**京沪价格几乎一致**,区别更多在消费选择面广度和个人偏好上。 + +需要注意,本报告侧重于海淀区与上海市中心的**中高收入常住居民**生活,对比的是平均消费水准。【**数据截至2024年底**】,来源包括政府统计、公认调研和市场平台。例如**居民消费价格指数(CPI)\**显示2024年上海CPI同比持平 ([2024年上海市国民经济运行情况_统计要闻](https://tjj.sh.gov.cn/tjxw/20250122/4fbff8f152384fc7a337794ea4ff55e2.html#:~:text=2024%E5%B9%B4%EF%BC%8C%E5%85%A8%E5%B8%82%E5%B1%85%E6%B0%91%E6%B6%88%E8%B4%B9%E4%BB%B7%E6%A0%BC%EF%BC%88CPI%EF%BC%89%E4%B8%8E%E4%B8%8A%E5%B9%B4%E5%90%8C%E6%9C%9F%E6%8C%81%E5%B9%B3%E3%80%82%E6%89%A3%E9%99%A4%E9%A3%9F%E5%93%81%E5%92%8C%E8%83%BD%E6%BA%90%E4%BB%B7%E6%A0%BC%E7%9A%84%E6%A0%B8%E5%BF%83CPI%E4%B8%8A%E6%B6%A80.2))、北京CPI上涨0.7%,物价总体稳定。我们引用了可信的数据来尽量量化差异,但\**个体感受可能不同**:有人在上海精打细算也能低成本生活,有人在北京追求品质消费开销同样惊人。 + +总的来说,**北京海淀和上海市中心的消费水平都位居全国前列**,上海在“吃住玩”上平均花费稍高,但海淀也并不逊色多少。对于在这两地生活的中高收入群体而言,月度主要开支(如房租、通勤、食品)占收入比相对可控,而**品质消费和房租**是拉开差距的主因。如果考虑收入差异(上海市中心白领平均收入也往往略高于北京),实际生活压力可能旗鼓相当。希望本报告的详细对比和数据解析,能为读者提供对京沪核心区消费水准的直观认识。 + +**参考来源:** + +1. **价格及指数数据** – 上海市统计局《2024年上海市国民经济运行情况》等 ([2024年上海市国民经济运行情况_统计要闻](https://tjj.sh.gov.cn/tjxw/20250122/4fbff8f152384fc7a337794ea4ff55e2.html#:~:text=2024%E5%B9%B4%EF%BC%8C%E5%85%A8%E5%B8%82%E5%B1%85%E6%B0%91%E6%B6%88%E8%B4%B9%E4%BB%B7%E6%A0%BC%EF%BC%88CPI%EF%BC%89%E4%B8%8E%E4%B8%8A%E5%B9%B4%E5%90%8C%E6%9C%9F%E6%8C%81%E5%B9%B3%E3%80%82%E6%89%A3%E9%99%A4%E9%A3%9F%E5%93%81%E5%92%8C%E8%83%BD%E6%BA%90%E4%BB%B7%E6%A0%BC%E7%9A%84%E6%A0%B8%E5%BF%83CPI%E4%B8%8A%E6%B6%A80.2));国家统计局居民收支数据。 +2. **餐饮消费** – 光明网《白领午餐报告》 ([白领午餐报告:一线城市CBD“打工人”既爱平价又要品质_腾讯新闻](https://news.qq.com/rain/a/20201105A0BH1G00#:~:text=%E5%9C%A8%E8%AE%B8%E5%A4%9A%E4%BA%BA%E7%9A%84%E6%83%B3%E8%B1%A1%E4%B8%AD%EF%BC%8C%E5%87%BA%E5%85%A5%E4%B8%80%E7%BA%BF%E5%9F%8E%E5%B8%82CBD%E9%AB%98%E7%AB%AF%E5%86%99%E5%AD%97%E6%A5%BC%E7%9A%84%E7%99%BD%E9%A2%86%EF%BC%8C%E6%AF%8F%E5%A4%A9%E4%BA%AB%E7%94%A8%E7%9A%84%E5%8D%88%E9%A4%90%E5%BA%94%E8%AF%A5%E4%B9%9F%E4%BB%B7%E6%A0%BC%E4%B8%8D%E8%8F%B2%E3%80%82%E4%BD%86%E7%BB%9F%E8%AE%A1%E5%8F%91%E7%8E%B0%EF%BC%8C%E5%8D%B3%E4%BD%BF%E5%9C%A8%E8%BF%99%E4%BA%9B%E5%9C%B0%E6%96%B9%EF%BC%8C%E7%99%BD%E9%A2%86%E7%9A%84%E5%8D%88%E9%A4%90%E9%80%89%E6%8B%A9%E4%B9%9F%E4%BB%A5%E5%B9%B3%E4%BB%B7%E4%B8%BA%E4%B8%BB%E3%80%82));中国烹饪协会数据 via 《上海商报》 ([上海餐厅数量居首 就餐人均消费88元_中国烹饪协会](https://m.ccas.com.cn/site/content/102712.html#:~:text=%E9%99%A4%E4%BA%86%E4%B8%8A%E6%B5%B7%EF%BC%8C%E5%A4%A7%E4%BC%97%E7%82%B9%E8%AF%84%E7%BD%91%E8%BF%98%E5%AF%B9%E5%8C%97%E4%BA%AC%E3%80%81%E5%B9%BF%E5%B7%9E%E3%80%81%E6%B7%B1%E5%9C%B3%E3%80%81%E6%9D%AD%E5%B7%9E%E3%80%81%E5%8D%97%E4%BA%AC%E3%80%81%E5%A4%A9%E6%B4%A5%E7%AD%89%E5%9F%8E%E5%B8%82%E7%9A%84%E5%95%86%E6%88%B7%E6%95%B0%E6%8D%AE%E5%92%8C%E7%94%A8%E6%88%B7%E8%A1%8C%E4%B8%BA%E4%B9%A0%E6%83%AF%E8%BF%9B%E8%A1%8C%E4%BA%86%E8%BF%BD%E8%B8%AA%E5%88%86%E6%9E%90%E3%80%82%E5%9C%A8%E9%A4%90%E9%A5%AE%E6%B6%88%E8%B4%B9%E6%96%B9%E9%9D%A2%EF%BC%8C%E4%BB%85%E6%AC%A1%E4%BA%8E%E4%B8%8A%E6%B5%B7%E3%80%81%E6%8E%92%E5%90%8D%E7%AC%AC%E4%BA%8C%E7%9A%84%E6%98%AF%E6%B7%B1%E5%9C%B3%EF%BC%88%E4%BA%BA%E5%9D%8770%E5%85%83));搜狐网《2024上海世界美食分布指数》 ([2024“上海世界美食分布指数”发布,人均消费最高的是这个区_数量最多_浦东_菜系](https://m.sohu.com/a/867475857_120578424/%3Fpvid%3D000115_3w_a%26scm%3D10001.1355_13-100000-0_922.0-0.0.a2_5X162X1627#:~:text=%E6%95%B0%E9%87%8F%E5%90%8C%E6%AF%94%E5%87%8F%E5%B0%91%E7%9A%84%E5%89%8D6%E5%90%8D%E4%B8%BA%E9%9D%99%E5%AE%89%E5%8C%BA%E3%80%81%E5%AE%9D%E5%B1%B1%E5%8C%BA%E3%80%81%E9%9D%92%E6%B5%A6%E5%8C%BA%E3%80%81%E6%9D%A8%E6%B5%A6%E5%8C%BA%E3%80%81%E6%9D%BE%E6%B1%9F%E5%8C%BA%20%E5%92%8C%20%E9%87%91%E5%B1%B1%E5%8C%BA%EF%BC%8C%E5%87%8F%E5%B0%91%E5%B9%85%E5%BA%A6%E4%BB%8E73%E5%AE%B6%E5%88%B05%E5%AE%B6%E4%B8%8D%E7%AD%89%E3%80%82))等。 +3. **娱乐及生活方式** – 每日经济等媒体对电影票价的报道 ([一家人看场电影花400多元低价电影票为何难觅踪影 - 人民日报](https://www.peopleapp.com/column/30035419895-500000471976#:~:text=%E4%B8%80%E5%AE%B6%E4%BA%BA%E7%9C%8B%E5%9C%BA%E7%94%B5%E5%BD%B1%E8%8A%B1400%E5%A4%9A%E5%85%83%E4%BD%8E%E4%BB%B7%E7%94%B5%E5%BD%B1%E7%A5%A8%E4%B8%BA%E4%BD%95%E9%9A%BE%E8%A7%85%E8%B8%AA%E5%BD%B1%20,));中国新闻周刊《一线城市房租降了?》 ([一线城市房租降了? - 中国新闻周刊网](http://www.inewsweek.cn/society/2024-01-17/21059.shtml#:~:text=%E4%B8%AD%E4%BB%8B%E7%8E%8B%E8%AF%9A%E5%AF%B9%E4%B8%AD%E5%9B%BD%E6%96%B0%E9%97%BB%E5%91%A8%E5%88%8A%E8%A1%A8%E7%A4%BA%EF%BC%8C%E7%9B%AE%E5%89%8D%E9%99%84%E8%BF%91%E4%B8%80%E5%B1%85%E5%AE%A4%E6%88%BF%E7%A7%9F%E5%9C%A85000));新浪财经等对共享单车调价的报道 ([共享单车涨价 连续包月告别个位数|滴滴_新浪财经_新浪网](https://finance.sina.com.cn/jjxw/2024-08-02/doc-incheqct4363575.shtml#:~:text=%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E4%B9%8B%E5%A4%96%EF%BC%8C%E5%85%B1%E4%BA%AB%E5%8D%95%E8%BD%A6%E5%8C%85%E6%9C%88%E4%BB%B7%E6%A0%BC%E4%B9%9F%E5%9C%A8%E6%82%84%E7%84%B6%E4%B8%8A%E6%B6%A8%E3%80%82));36氪健身行业报告 ([中国健身房收费,贵吗? - 36氪](https://m.36kr.com/p/1188297244573960#:~:text=%E4%B8%AD%E5%9B%BD%E5%81%A5%E8%BA%AB%E6%88%BF%E6%94%B6%E8%B4%B9%EF%BC%8C%E8%B4%B5%E5%90%97%EF%BC%9F%20,))等。 +4. **居住与交通** – 北京青年报/链家研究院《北京租赁市场月报》 ([北京链家:预计春节假期后新增、换租需求增加 推动2月租赁市场升温|北京市_新浪财经_新浪网](https://finance.sina.com.cn/jjxw/2024-02-05/doc-inafywyy7551152.shtml#:~:text=%E4%B8%AD%E5%BF%83%E5%9F%8E%E5%8C%BA%E9%A2%84%E8%AE%A1%E4%BC%9A%E6%9C%89%E6%89%80%E5%B0%8F%E5%B9%85%E4%B8%8A%E6%B6%A8%EF%BC%8C%E5%9B%A0%E6%AD%A4%E4%BC%9A%E6%9C%89%E9%83%A8%E5%88%86%E7%BE%A4%E4%BD%93%E8%80%83%E8%99%91%E9%80%89%E6%8B%A9%E5%B9%B4%E5%89%8D%E7%A7%9F%E6%88%BF%E3%80%82));MSA Advisory《中国生活成本2025》 ([Cost of Living in China in 2025 - MSA Advisory](https://msadvisory.com/cost-of-living-in-china/#:~:text=Cost%20of%20Living%20in%20China,accommodations%20average%20around%206%252C500%20RMB));北京市发改委官网 ([公共交通价格-出行-北京市发展和改革委员会](https://fgw.beijing.gov.cn/bmcx/djcx/cxldj/202003/t20200331_1752788.htm#:~:text=%E4%BD%BF%E7%94%A8%E5%B8%82%E6%94%BF%E4%BA%A4%E9%80%9A%E4%B8%80%E5%8D%A1%E9%80%9A%E5%88%B7%E5%8D%A1%E4%B9%98%E5%9D%90%E8%BD%A8%E9%81%93%E4%BA%A4%E9%80%9A%EF%BC%8C%E6%AF%8F%E8%87%AA%E7%84%B6%E6%9C%88%E5%86%85%E6%AF%8F%E5%BC%A0%E5%8D%A1%E6%94%AF%E5%87%BA%E7%B4%AF%E8%AE%A1%E6%BB%A1100%E5%85%83%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%BB%B7%E6%A0%BC%E7%BB%99%E4%BA%888%E6%8A%98%E4%BC%98%E6%83%A0%EF%BC%9B%E6%BB%A1150%E5%85%83%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%BB%B7%E6%A0%BC%E7%BB%99%E4%BA%885%E6%8A%98%E4%BC%98%E6%83%A0%EF%BC%9B%E6%94%AF%E5%87%BA%E7%B4%AF%E8%AE%A1%E8%BE%BE%E5%88%B0400%E5%85%83%20%E4%BB%A5%E5%90%8E%E7%9A%84%E4%B9%98%E6%AC%A1%EF%BC%8C%E4%B8%8D%E5%86%8D%20)) ([2023北京出租车收费标准(起步价+夜间收费) - 武汉旅游景点大全](https://m.wuhan.com/xinwen/116093.html#:~:text=2023%E5%B9%B4%E5%8C%97%E4%BA%AC%E5%87%BA%E7%A7%9F%E8%BD%A6%E8%B5%B7%E6%AD%A5%E9%87%8C%E7%A8%8B%E5%9C%A83%E5%85%AC%E9%87%8C%E4%BB%A5%E5%86%85%EF%BC%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E4%B8%BA13%E5%85%83%EF%BC%8C%E8%B6%85%E8%BF%873%E5%85%AC%E9%87%8C%E5%90%8E%E6%AF%8F%E5%85%AC%E9%87%8C%E5%9F%BA%E6%9C%AC%E5%8D%95%E4%BB%B7%E6%98%AF2));千龙网《共享单车涨价》 ([共享单车涨价 连续包月告别个位数|滴滴_新浪财经_新浪网](https://finance.sina.com.cn/jjxw/2024-08-02/doc-incheqct4363575.shtml#:~:text=%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8C%E8%B5%B7%E6%AD%A5%E4%BB%B7%E4%B9%8B%E5%A4%96%EF%BC%8C%E5%85%B1%E4%BA%AB%E5%8D%95%E8%BD%A6%E5%8C%85%E6%9C%88%E4%BB%B7%E6%A0%BC%E4%B9%9F%E5%9C%A8%E6%82%84%E7%84%B6%E4%B8%8A%E6%B6%A8%E3%80%82));北京市供暖收费通知 ([2024-2025年北京供暖时间、收费标准](https://m.bj.bendibao.com/zffw/245599.html#:~:text=%282)基本热价:按照建筑面积征收,大网供应的为每采暖季每建筑平方米12元%3B独网供应的燃气、燃油或电锅炉为每采暖季每建筑平方米18元。 (3)计量热价:按照用 ))等。 \ No newline at end of file diff --git a/src/blogs/单摆周期的系统误差研究:大摆角效应与空气阻力及其拟合校正.md b/src/blogs/单摆周期的系统误差研究:大摆角效应与空气阻力及其拟合校正.md new file mode 100644 index 0000000..9d03b6f --- /dev/null +++ b/src/blogs/单摆周期的系统误差研究:大摆角效应与空气阻力及其拟合校正.md @@ -0,0 +1,79 @@ +--- +title: 单摆周期的系统误差研究:大摆角效应与空气阻力及其拟合校正 +desc: 大摆角单摆周期的系统误差及其校正已由丰富的理论和实验研究所支撑,我们可以设计并实现可行的实验方案:获取高质量的摆球位置-时间数据,应用数学模型提取周期信息,最后通过非线性拟合消除大振幅和阻尼影响,测得准确的重力加速度值并评估空气阻力特性。 +author: feie9454 +date: 2025-03-07 +tags: 计算机、物理、竞赛 +--- + +# 单摆周期的系统误差研究:大摆角效应与空气阻力及其拟合校正 + +## 1. 单摆的理论模型 + +**大摆角下的周期修正**:理想小摆角时,单摆周期公式为 $T_0 = 2\pi\sqrt{L/g}$,其中 $L$ 为摆长,$g$ 为重力加速度。但当初始摆角 $\theta_0$ 较大时,$\sin\theta \approx \theta$ 的近似不再成立,实际周期会比 $T_0$ 略长 ([大角度单摆周期.pdf](https://max.book118.com/html/2017/0501/103573862.shtm#:~:text=%E6%98%AF%E6%91%86%E7%90%83%E7%9A%84%E8%B4%A8%E9%87%8F%252Cl%E6%98%AF%E6%91%86%E9%95%BF%252C%20%CE%B8%E6%98%AF%E6%91%86%E8%A7%92%252C%20%CE%B8%E6%98%AF%E8%A7%92%E5%8A%A0%E9%80%9F%E5%BA%A6,%E8%BF%99%E5%90%8C%E6%A0%B7%E6%98%AF%E4%B8%80%E4%B8%AA%E6%A0%87%E5%87%86%E7%9A%84%E7%AE%80%E8%B0%90%E6%8C%AF%E5%8A%A8%E6%96%B9%E7%A8%8B%252C%E5%AF%B9%E5%BA%94%E7%9A%84%E5%91%A8%E6%9C%9F%E4%B8%BA%202%20l%20T%253D2%CF%80)) ([非小角单摆(数学摆)的周期 - 瞿立建 - 博客园](https://www.cnblogs.com/joyfulphysics/p/5974563.html#:~:text=%E5%8D%B3%E4%BE%BF%E6%91%86%E5%B9%85%E5%BE%88%E5%B0%8F%EF%BC%8C%5C%28%5Cphi_0%5Clt%205%5E%7B%5Ccirc%7D%5C),周期也是随摆幅而变的。即便摆幅比较大,如\(\phi_0 %3D 45^{\circ}\),周期也只是比0摆幅极限下的周期\(T_0\)多了3.7))。单摆周期的精确解需用椭圆积分表示 ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=solution%20to%20the%20period%20of,10))。通过泰勒展开可得到周期关于振幅的修正级数,例如: + +$T \;=\; 2\pi\sqrt{\frac{L}{g}}\Big(1 \,+\, \frac{\theta_0^2}{16} \,+\, \frac{11\,\theta_0^4}{3072} \,+\, \frac{173\,\theta_0^6}{737280} + \cdots\Big)\,.$ + +上述公式显示了随振幅增大而产生的周期延长效应 ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=Tex%20%E2%89%88%20T0%20%C2%B5%201,%CE%B8%202%20%252B%2011%203072))。在小角度极限($\theta_0\to 0$)时,括号内修正趋于1,回复标准公式。而当摆角不再很小时,第一项$\frac{\theta_0^2}{16}$等修正不可忽略。例如,$\theta_0=30^\circ$ 时周期比 $T_0$ 增加约1.7%,$\theta_0=45^\circ$ 时增加约3.7% ([非小角单摆(数学摆)的周期 - 瞿立建 - 博客园](https://www.cnblogs.com/joyfulphysics/p/5974563.html#:~:text=%5C%28%5Cphi_0%5C) \(0,0369))。实际实验中,若采用 **过大的初始摆角** 却仍套用小角公式,将导致对 $g$ 的测量产生系统偏差;有报道显示从 $90^\circ$ 高摆幅释放单摆并用小角公式计算,会低估重力加速度约22% ([27.8: Sample lab report (Measuring g using a pendulum) - Physics LibreTexts](https://phys.libretexts.org/Bookshelves/University_Physics/Book%253A_Introductory_Physics_-_Building_Models_to_Describe_Our_World_%28Martin_Neary_Rinaldo_and_Woodman))。 + +**空气阻力的作用**:真实单摆受空气阻力(阻尼力)影响,其运动方程可表示为: + +$mL\,\ddot{\theta} + c\,L\,\dot{\theta} + mg\,\sin\theta = 0\,,$ + +其中 $c$ 是阻尼系数(与空气粘滞性、摆球形状等有关) ([40.37 -- Pendulum damped by air](https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/40.37.html#:~:text=,above%252C%20which%20now%20becomes))。在小角度近似下,上式化为线性阻尼简谐振子方程:$\ddot{\theta} + 2\beta,\dot{\theta} + \omega_0^2,\theta = 0$,其中 $\omega_0=\sqrt{g/L}$,$2\beta = c/(m)$。空气阻力的数学表达常用阻尼项 $2\beta,\dot{\theta}$ 表示 **线性阻尼**,这通常对应于低速、阻力与速度成正比的情形 ([40.37 -- Pendulum damped by air](https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/40.37.html#:~:text=,above%252C%20which%20now%20becomes)) ([Damping of a Simple Pendulum Due to Drag on Its String](https://file.scirp.org/pdf/JAMP_2017012515591136.pdf#:~:text=the%20drag%20force%20is%20quadratic,sectional%20area%20of%20the%20bob))。实验和流体力学分析表明,对于常见尺度的摆球(例如5 cm直径的小球在空气中运动,雷诺数约 $10^3$),将空气阻力近似为线性阻尼是合理的 ([Damping of a Simple Pendulum Due to Drag on Its String](https://file.scirp.org/pdf/JAMP_2017012515591136.pdf#:~:text=the%20drag%20force%20is%20quadratic,sectional%20area%20of%20the%20bob))。在该模型下,阻尼不会显著改变振荡频率(一阶近似下频率几乎不变),但会使振幅随时间指数衰减。解析解为: + +$\theta(t) = \theta_0\,e^{-\beta t}\cos(\omega_d t + \phi)\,,$ + +其中 $\omega_d = \sqrt{\omega_0^2 - \beta^2}$ 是阻尼后的角频率,周期 $T_d = \frac{2\pi}{\omega_d}$ ([40.37 -- Pendulum damped by air](https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/40.37.html#:~:text=%3E%20x%20%253D%20Ae,and%20the%20more%20quickly%20the))。若阻尼很小($\beta \ll \omega_0$),则 $\omega_d \approx \omega_0$,因此周期仅略微变长,影响是二阶小量 ([40.37 -- Pendulum damped by air](https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/40.37.html#:~:text=%3E%20x%20%253D%20Ae,and%20the%20more%20quickly%20the))。阻尼主要体现为**振幅逐渐衰减**:每个周期振幅衰减因子约为 $e^{-\beta T_d}$。若以摆幅峰值 $\theta_{\max}$ 表示振幅,则相邻峰值满足 $\theta_{n+1}/\theta_n \approx e^{-\beta T_d}$,可以通过测量连续摆动的振幅比来求出阻尼系数(**对数减量法**)。总之,大摆角使周期变长,空气阻力使振幅随摆动次数减小,并可能引起周期微小变化和测量误差,这两种因素都是单摆实验中的系统误差来源。 + +## 2. 数据处理方法 + +**由摆球轨迹提取周期**:给定单摆摆球的 $X,Y$ 随时间变化的数据,可据此计算摆角随时间的函数 $\theta(t)$。假设支点坐标已知且以垂直方向为零角参考,则任一时刻摆角可通过几何关系得到,例如 $\displaystyle \theta(t) = \arctan\frac{x(t)}{L - y(t)}$(当偏角较小时可近似 $\theta \approx x/L$)。获得 $\theta(t)$ 后,可采用以下方法提取周期信息: + +- **峰值法**:检测角度随时间的极大值点(或极小值点)。两相邻同向峰值之间的时间间隔即为一个全振动周期 $T$。为提高精度,可对多次振动测得的多个$T$取平均。不过需注意振幅在逐渐减小,每一周期略有差异,不能简单平均大摆角情况下的周期,否则会引入系统偏差。更好的做法是记录**每一振动周期**的时长 $T_n = t_{n+1}-t_n$($t_n$为第$n$次摆到极端位置的时刻),获得周期随摆动次数的变化序列。 +- **过零法**:当数据较噪杂难以准确找到极值时,可以利用摆球经过平衡位置($\theta=0$)的时刻来确定半周期。例如,每次摆球经过垂直下方(并向同一方向运动)视为参考点,相邻两次通过该位置的时间间隔即为一个完整周期。通过插值或平滑提高过零点时刻的精度,可得到稳定的周期测量。。 + +**数据预处理**:在提取周期前,常需要对原始 $X,Y$ 数据进行处理。例如,可以将像素坐标转换为实际长度单位,或先用平滑滤波减小测量噪声。计算摆角$\theta(t)$后,可以绘制$\theta$–$t$曲线,以直观确定振动的稳定性。在峰值检测时,可采用插值提高极值时间定位的精度。整个过程中,应保存每个周期对应的**初始振幅**(如各周期的峰值$\theta_{n}$),为后续分析提供振幅信息。 + +## 3. 系统误差的拟合校正方法 + +**建立非线性拟合模型**:为同时消除大摆角和空气阻力带来的系统误差,需要将上述物理效应纳入拟合模型。在理论模型中,单摆周期是振幅的函数 $T(\theta_0)$,而振幅又随时间指数衰减。我们可以用两个待定参数来描述系统:重力加速度 $g$(影响周期基准)和阻尼系数 $\beta$(影响振幅衰减速率)。已知摆长 $L$ 后,可以通过非线性拟合从实验数据中估计这两个参数,从而“校正”测量值。基本思路如下: + +1. **单周期数据拟合**:利用每一振动周期的测量值 $T_n$ 以及相应的振幅(例如第$n$次摆动的初始角振幅$\theta_{n}$),拟合理论周期函数。理论上,第$n$周期的振幅可近似取上一周期末的振幅,即 $\theta_{n}$,而该周期时长满足 $T_n \approx 2\pi\sqrt{\frac{L}{g}}\left(1 + \frac{\theta_{n}^2}{16} + \frac{11,\theta_{n}^4}{3072} + \cdots\right)$ ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=Tex%20%E2%89%88%20T0%20%C2%B5%201,%CE%B8%202%20%252B%2011%203072))。将测得的一系列 $(\theta_n,,T_n)$ 点代入这一非线性关系进行拟合,可视为对 $g$ 的求解。其中 $g$ 是唯一待调参数(因为展开式系数已知且$L$已知)。拟合的方法可以使用非线性最小二乘:选择一个初始 $g$ 值,根据当前 $g$ 计算每个理论周期,与测量 $T_n$ 比较误差,不断迭代调整 $g$ 使误差平方和最小。拟合完成后,即得到扣除了**大摆角效应**影响的 $g$ 值。 +2. **振幅衰减数据拟合**:为了量化**空气阻力**,可利用振幅随时间(或摆次)的衰减曲线。提取各次极大摆角值 $\theta_n$,根据阻尼模型 $\theta_n = \theta_0,e^{-\beta t_n}$ 或 $\theta_{n+1}/\theta_n = e^{-\beta T_n}$ 进行拟合。对于线性阻尼,$\ln(\theta_n)$ 对 $n$ 近似呈线性下降,斜率即 $-\beta T_{\text{avg}}$($T_{\text{avg}}$为平均周期)。通过对 $\ln(\theta_n)$ 关于时间或摆次的线性拟合,可以求得阻尼率 $\beta$。也可以直接在时域拟合 $\theta(t)$ 包络:例如,假设理论振幅演化 $\theta(t)=\theta_0 e^{-\beta t}$,通过最小二乘拟合整条指数曲线求出最优 $\beta$。 +3. **综合拟合**:更高阶的方法是将周期和振幅两个关系同时纳入**全局拟合**。例如,以 $g$ 和 $\beta$ 为双参数构造一个目标函数,包括所有测得的 $T_n$ 和 $\theta_n$ 数据点:对每个周期,有理论预测 $T_n(g,\theta_n)$;对每个振幅衰减,有理论预测 $\theta_n(\beta) = \theta_0 e^{-\beta t_n}$。通过迭代调整 $g,\beta$ 使这些预测与实验数据整体误差最小,即可同时得到最符合实验的 $g$ 和 $\beta$ 值。由于 $T_n$ 本身又依赖 $\theta_n$,这个问题是耦合的非线性拟合,可采用Levenberg–Marquardt等算法数值求解。综合拟合的好处是充分利用所有信息,但模型复杂度较高。在实践中,可先分别拟合获得 $g$ 和 $\beta$ 的初值,再用于综合拟合提高精度。 + +**误差校正与迭代**:拟合得到参数后,可将其用于校正原始测量。例如,利用拟合的 $g$ 计算小角度**基准周期**,然后通过理论公式算出各大摆角下的**周期修正值**,将其加回小角公式,从而得到更精确的周期值。对于空气阻力,也可用拟合的 $\beta$ 估计在 $N$ 个周期累计时间内损失的振幅,从而推算出**初始等效周期**。这些方法相当于用物理模型对测量结果进行**后处理**,消除系统偏差。例如,上述中国学者柴聪聪等人的研究表明:基于弱阻尼大摆角模型推导的解析公式,可以描述周期随摆动次数逐渐减小的规律,并用于校正大摆角单摆实验中的系统误差 ([大摆角单摆"周期"变化的解析解及其实验应用-期刊-万方数据知识服务平台](https://d.wanfangdata.com.cn/periodical/wlsy202003010#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E7%94%B1%E4%BA%8E%E5%BF%BD%E7%95%A5%E7%A9%BA%E6%B0%94%E9%98%BB%E5%B0%BC%E5%B8%A6%E6%9D%A5%E5%91%A8%E6%9C%9F%E6%B5%8B%E9%87%8F%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%AF%AF%E5%B7%AE.%E5%9F%BA%E4%BA%8E%E5%BC%B1%E9%98%BB%E5%B0%BC%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E7%9A%84%E8%BF%90%E5%8A%A8%E6%96%B9%E7%A8%8B%252C%E6%8E%A8%E5%AF%BC%E4%BA%86%E7%B4%AF%E8%AE%A1))。通过这样的模型校正,再以多周期累计计时法来降低随机误差,两相结合即可既消除系统误差又减小统计误差 ([大摆角单摆"周期"变化的解析解及其实验应用-期刊-万方数据知识服务平台](https://d.wanfangdata.com.cn/periodical/wlsy202003010#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E7%94%B1%E4%BA%8E%E5%BF%BD%E7%95%A5%E7%A9%BA%E6%B0%94%E9%98%BB%E5%B0%BC%E5%B8%A6%E6%9D%A5%E5%91%A8%E6%9C%9F%E6%B5%8B%E9%87%8F%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%AF%AF%E5%B7%AE.%E5%9F%BA%E4%BA%8E%E5%BC%B1%E9%98%BB%E5%B0%BC%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E7%9A%84%E8%BF%90%E5%8A%A8%E6%96%B9%E7%A8%8B%252C%E6%8E%A8%E5%AF%BC%E4%BA%86%E7%B4%AF%E8%AE%A1))。 + +## 4. 实验可行性分析 + +**多摆长、多摆角数据的优化**:在实验设计上,结合不同摆长和初始摆角的数据有助于提高拟合过程的稳健性和测量精度。首先,不同摆长的数据可以用来验证所求得的 $g$ 是否一致。理想情况下,$g$ 为一全局常量,与摆长和初振幅无关。如果对不同 $L$ 拟合得到的 $g$ 有偏差,说明模型或实验存在系统误差。例如,若未考虑线长测量误差或支点高度变化,不同摆长可能导致 $g$ 计算有系统差异。通过比较和综合不同 $L$ 的数据,可校准这些因素,使所求 $g$ 更可靠 ([实验二十四 研究单摆周期与摆长的关系 - 物含妙理](https://enjoyphysics.cn/Article3042#:~:text=%E5%AE%9E%E9%AA%8C%E4%BA%8C%E5%8D%81%E5%9B%9B%20%E7%A0%94%E7%A9%B6%E5%8D%95%E6%91%86%E5%91%A8%E6%9C%9F%E4%B8%8E%E6%91%86%E9%95%BF%E7%9A%84%E5%85%B3%E7%B3%BB%20,24%20%E2%80%93%203%20%E9%80%9A%E7%94%A8%E8%BD%AF%E4%BB%B6%20%E5%91%A8%E6%9C%9F%E4%B8%8E%E6%91%86%E9%95%BF%E5%B9%B3%E6%96%B9%E6%A0%B9%E5%85%B3%E7%B3%BB%E5%AE%9E%E9%AA%8C%E6%9B%B2%E7%BA%BF))。常用的方法是在 $T^2$–$L$ 图上做线性拟合,其斜率理论值为 $4\pi^2/g$,加入大摆角修正后应改为拟合 $T^2/(1+\cdots)$ 与 $L$ 的关系,以提取正确斜率。 + +其次,不同初始摆角的数据可以帮助区分振幅效应和其他误差源。建议在实验中选取**多种摆幅**:例如小于$5^\circ$的情况作为对照,以及$15^\circ$、$30^\circ$甚至$45^\circ$等较大振幅。小振幅数据应满足等时性,主要用于提供基准参考;较大振幅数据则能放大周期变化的效应,便于拟合出修正项。例如,可以对同一摆长,在不同 $\theta_0$ 下各测一次周期,然后拟合 $\theta_0$–$T$ 曲线来验证理论公式 ([非小角单摆(数学摆)的周期 - 瞿立建 - 博客园](https://www.cnblogs.com/joyfulphysics/p/5974563.html#:~:text=%5C%28%5Cphi_0%5C) \(0,0369))。在这种**横向比较**中,空气阻力的影响可通过控制总摆动次数来减小——比如每次只测单摆往返几次,在振幅尚未衰减太多时就记录数据,以近似认为阻尼影响相同。之后再将多个振幅的数据综合拟合,以分离出振幅对周期的影响。若实验条件允许,还可固定大振幅让其自由衰减,连续记录从大角到小角的全过程,这相当于在一次实验中采集了不同摆幅条件的数据,方便统一拟合分析。 + +**拟合过程优化**:当合并多组数据共同拟合时,需要考虑模型参数的一致性和差异性。通常,可假定重力加速度 $g$ 对所有数据集相同,而阻尼系数 $\beta$ 对同一摆长、相同摆球的各次实验也应相近(取决于空气条件和物体形状)。如果不同摆长的摆球大小/质量不变,则空气阻力系数$c$基本相同,但由于$m$不同(若换球则质量不同),$\beta=c/(2m)$ 会有所变化。因此,对于多摆长数据,可以让每组数据有各自的$\beta$参数,但共享同一个$g$参数进行拟合。如此一来,$g$ 由所有数据共同约束,而$\beta$根据每组独立确定。这种**分组全局拟合**能同时利用大量数据点,提高$g$的统计置信度,并将阻尼的影响限制在组内比较,不致干扰$g$的求解。 + +在实验可行性上,应确保测量精度能够检出理论上的细小差异。例如,大摆角效应在$30^\circ$时只有约2%影响,需要毫秒量级的计时精度或高分辨的视频分析才能分辨 ([非小角单摆(数学摆)的周期 - 瞿立建 - 博客园](https://www.cnblogs.com/joyfulphysics/p/5974563.html#:~:text=%E5%8D%B3%E4%BE%BF%E6%91%86%E5%B9%85%E5%BE%88%E5%B0%8F%EF%BC%8C%5C%28%5Cphi_0%5Clt%205%5E%7B%5Ccirc%7D%5C),周期也是随摆幅而变的。即便摆幅比较大,如\(\phi_0 %3D 45^{\circ}\),周期也只是比0摆幅极限下的周期\(T_0\)多了3.7))。多周期累计计时是一种提高时间测量精度的手段,但需用理论修正其系统误差后才能放心使用 ([大摆角单摆"周期"变化的解析解及其实验应用-期刊-万方数据知识服务平台](https://d.wanfangdata.com.cn/periodical/wlsy202003010#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E7%94%B1%E4%BA%8E%E5%BF%BD%E7%95%A5%E7%A9%BA%E6%B0%94%E9%98%BB%E5%B0%BC%E5%B8%A6%E6%9D%A5%E5%91%A8%E6%9C%9F%E6%B5%8B%E9%87%8F%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%AF%AF%E5%B7%AE.%E5%9F%BA%E4%BA%8E%E5%BC%B1%E9%98%BB%E5%B0%BC%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E7%9A%84%E8%BF%90%E5%8A%A8%E6%96%B9%E7%A8%8B%252C%E6%8E%A8%E5%AF%BC%E4%BA%86%E7%B4%AF%E8%AE%A1))。此外,要尽可能减少其他误差来源:摆长应精确测量(包括摆球半径和悬挂点长度修正),支点摩擦要小,确保测到的阻尼主要来自空气阻力而非机械能损失。若可能,可在真空或不同介质下重复实验,验证空气阻力模型的正确性。 + +**随机误差与重复实验**:通过拟合方法校正系统误差后,剩余的主要是不确定度(随机误差)。可以通过重复实验估计测量结果的方差。结合多个摆长和摆幅意味着需要进行多组实验,应合理安排每组实验的次数和条件,使数据既丰富又不引入新的系统误差。例如,每种摆长下多次测量取平均,以削弱随机噪声;不同振幅条件随机顺序进行,避免系统漂移造成偏倚。最终,将不同条件的数据综合分析,有助于确认测得的 $g$ 与文献值吻合,并得到空气阻力系数/阻尼比等附加信息,为单摆实验提供更完整的物理图景。 + +## 5. 文献调研与理论支持 + +**大摆角周期的研究**:单摆大振幅运动自17世纪起即为物理学界关注。早在18世纪,Bernoulli 等人就给出了周期关于振幅的二阶近似公式(如 $T \approx T_0[1+\theta_0^2/16]$) ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=Bernoulli%E2%80%99s%20expression,6))。现代解析力学证明了单摆周期可用完全椭圆积分表示,并可展开为幂级数精确计算 ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=solution%20to%20the%20period%20of,10)) ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=Tex%20%E2%89%88%20T0%20%C2%B5%201,%CE%B8%202%20%252B%2011%203072))。例如,European Journal of Physics 在2011年刊登了 Lima 等人的工作,通过级数展开得到单摆周期的八阶近似,提高了大角度情况下的计算精度 ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=Tex%20%E2%89%88%20T0%20%C2%B5%201,%CE%B8%202%20%252B%2011%203072))。这些理论为我们提供了**可靠的周期修正因子**,可直接用于拟合校正实验数据。 + +**空气阻力与阻尼分析**:关于单摆阻尼的研究则涉及流体动力学。空气阻力一般分为**线性阻力**(速度较低、粘滞阻尼)和**二次阻力**(速度较高、湍流阻力)两类。对于典型尺寸和速度的单摆,阻力模型往往可以简化为线性阻尼,这一点在实验和理论上都有支持 ([Damping of a Simple Pendulum Due to Drag on Its String](https://file.scirp.org/pdf/JAMP_2017012515591136.pdf#:~:text=the%20drag%20force%20is%20quadratic,sectional%20area%20of%20the%20bob))。例如,Lubarda 等人在 *European Journal of Physics* (2021) 的研究中详细分析了线性和二次阻力并存时的单摆运动,给出了含空气阻力时摆角随时间的解析解和近似解 ([Lubarda, M.V. and Lubarda, V.A. (2021) An Analysis of Pendulum Motion ...](https://www.scirp.org/reference/referencespapers%3Freferenceid%3D3462563#:~:text=Lubarda%252C%20M,Physics%252C%2042%252C%20Article%20ID%20055014))。他们的结果表明,在雷诺数约 $10^3$ 以下时空气阻力的线性模型足以解释单摆的阻尼行为 ([Damping of a Simple Pendulum Due to Drag on Its String](https://file.scirp.org/pdf/JAMP_2017012515591136.pdf#:~:text=the%20drag%20force%20is%20quadratic,sectional%20area%20of%20the%20bob))。还有研究考虑了悬挂细线的空气阻力,对总阻尼的贡献进行定量估计 ([Investigating the drag impact on pendulum through numerical models and ...](https://www.ewadirect.com/proceedings/tns/article/view/14527/pdf#:~:text=,s%253D%20kD%CE%B8%CB%99%20Z%20L))。这些文献为我们提供了**选择阻尼模型**的依据:一般而言,小型摆球、缓慢摆动时采用线性阻尼模型已能达到很高精度;如需进一步提高精度或研究高速/大球情况,可考虑加入二次阻力项进行更复杂的拟合分析。 + +**实验方法的改进**:许多教育类和实验类期刊也探讨了如何精确测量 $g$。例如,有文献报告利用高速摄像和图像处理获取摆球位置数据,然后通过拟合运动轨迹同时求出 $g$ 和阻尼系数的方法 ([大摆角单摆"周期"变化的解析解及其实验应用-期刊-万方数据知识服务平台](https://d.wanfangdata.com.cn/periodical/wlsy202003010#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E7%94%B1%E4%BA%8E%E5%BF%BD%E7%95%A5%E7%A9%BA%E6%B0%94%E9%98%BB%E5%B0%BC%E5%B8%A6%E6%9D%A5%E5%91%A8%E6%9C%9F%E6%B5%8B%E9%87%8F%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%AF%AF%E5%B7%AE.%E5%9F%BA%E4%BA%8E%E5%BC%B1%E9%98%BB%E5%B0%BC%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E7%9A%84%E8%BF%90%E5%8A%A8%E6%96%B9%E7%A8%8B%252C%E6%8E%A8%E5%AF%BC%E4%BA%86%E7%B4%AF%E8%AE%A1))。在这些研究中,往往强调通过 **多次振动累计计时** 提高测量精度,同时利用 **理论公式校正系统偏差** 的重要性 ([大摆角单摆"周期"变化的解析解及其实验应用-期刊-万方数据知识服务平台](https://d.wanfangdata.com.cn/periodical/wlsy202003010#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E7%94%B1%E4%BA%8E%E5%BF%BD%E7%95%A5%E7%A9%BA%E6%B0%94%E9%98%BB%E5%B0%BC%E5%B8%A6%E6%9D%A5%E5%91%A8%E6%9C%9F%E6%B5%8B%E9%87%8F%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%AF%AF%E5%B7%AE.%E5%9F%BA%E4%BA%8E%E5%BC%B1%E9%98%BB%E5%B0%BC%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E7%9A%84%E8%BF%90%E5%8A%A8%E6%96%B9%E7%A8%8B%252C%E6%8E%A8%E5%AF%BC%E4%BA%86%E7%B4%AF%E8%AE%A1))。柴聪聪等人在《物理实验》杂志发表的工作即属于此范畴:他们推导了弱阻尼大摆角单摆的周期随摆次的解析公式,结合实验验证了通过累计周期测量并用该公式校正,可以减小大摆角实验的系统误差并提高 $g$ 的测量准确度 ([大摆角单摆"周期"变化的解析解及其实验应用-期刊-万方数据知识服务平台](https://d.wanfangdata.com.cn/periodical/wlsy202003010#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E7%94%B1%E4%BA%8E%E5%BF%BD%E7%95%A5%E7%A9%BA%E6%B0%94%E9%98%BB%E5%B0%BC%E5%B8%A6%E6%9D%A5%E5%91%A8%E6%9C%9F%E6%B5%8B%E9%87%8F%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%AF%AF%E5%B7%AE.%E5%9F%BA%E4%BA%8E%E5%BC%B1%E9%98%BB%E5%B0%BC%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E7%9A%84%E8%BF%90%E5%8A%A8%E6%96%B9%E7%A8%8B%252C%E6%8E%A8%E5%AF%BC%E4%BA%86%E7%B4%AF%E8%AE%A1))。这一结果对教学实验具有指导意义:我们在自己的实验中亦可采用**多周期累积+模型校正**的方法,从而在保证精度的同时消除因大摆角和阻尼带来的偏差。 + +**综合评价**:综上所述,大摆角单摆周期的系统误差及其校正已由丰富的理论和实验研究所支撑。从理论模型、数据处理到拟合方法,各环节都有成熟的方法论和文献依据。通过参考这些研究,我们可以设计并实现可行的实验方案:获取高质量的摆球位置-时间数据,应用数学模型提取周期信息,最后通过非线性拟合消除大振幅和阻尼影响,测得准确的重力加速度值并评估空气阻力特性。这不仅提高了经典单摆实验的测量精度,还有助于学生深入理解单摆背后的非线性动力学特征。各项步骤的具体实现和注意事项在上述分析中已有详细说明,借鉴文献中的成功经验将有助于我们顺利开展该研究,并获得具有说服力的结果。 + +**参考文献:** + +- 【Wei & Zhu 2004】魏慧军, 朱炯明. *“大角度单摆的周期”*, 上海师范大学学报(自然科学版), **33**(3):103-105 (2004). +- 【Chai et al. 2020】柴聪聪 等. *“大摆角单摆‘周期’变化的解析解及其实验应用”*, 物理实验, **40**(3):48-50 (2020) ([大摆角单摆"周期"变化的解析解及其实验应用-期刊-万方数据知识服务平台](https://d.wanfangdata.com.cn/periodical/wlsy202003010#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E7%94%B1%E4%BA%8E%E5%BF%BD%E7%95%A5%E7%A9%BA%E6%B0%94%E9%98%BB%E5%B0%BC%E5%B8%A6%E6%9D%A5%E5%91%A8%E6%9C%9F%E6%B5%8B%E9%87%8F%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%AF%AF%E5%B7%AE.%E5%9F%BA%E4%BA%8E%E5%BC%B1%E9%98%BB%E5%B0%BC%E5%A4%A7%E6%91%86%E8%A7%92%E5%8D%95%E6%91%86%E7%9A%84%E8%BF%90%E5%8A%A8%E6%96%B9%E7%A8%8B%252C%E6%8E%A8%E5%AF%BC%E4%BA%86%E7%B4%AF%E8%AE%A1)). +- 【Amrani et al. 2008】D. Amrani, P. Paradis, M. Beaudin. *“Approximation expressions for the large-angle period of a simple pendulum revisited”*, Rev. Mex. Fis. E, **54**(1):59-64 (2008) ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=Tex%20%E2%89%88%20T0%20%C2%B5%201,%CE%B8%202%20%252B%2011%203072)) ([scielo.org.mx](https://www.scielo.org.mx/pdf//rmfe/v54n1/v54n1a10.pdf#:~:text=Bernoulli%E2%80%99s%20expression,6)). +- 【Lubarda 2021】M.V. Lubarda, V.A. Lubarda. *“An Analysis of Pendulum Motion in the Presence of Quadratic and Linear Drag”*, Eur. J. Phys., **42**:055014 (2021) ([Damping of a Simple Pendulum Due to Drag on Its String](https://file.scirp.org/pdf/JAMP_2017012515591136.pdf#:~:text=the%20drag%20force%20is%20quadratic,sectional%20area%20of%20the%20bob)). +- 【Physics LibreTexts】*“Damped Oscillations”*, *University Physics Volume 1* (OpenStax), Sec 15.6 ([40.37 -- Pendulum damped by air](https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/40.37.html#:~:text=%3E%20x%20%253D%20Ae,and%20the%20more%20quickly%20the)). +- 【瞿立建 2016】博客园: *“非小角单摆(数学摆)的周期”* (2016) ([非小角单摆(数学摆)的周期 - 瞿立建 - 博客园](https://www.cnblogs.com/joyfulphysics/p/5974563.html#:~:text=%5C%28%5Cphi_0%5C) \(0,0369)). +- 【Physics LibreTexts】*“Sample lab report: Measuring g using a pendulum”* (2019) ([27.8: Sample lab report (Measuring g using a pendulum) - Physics LibreTexts](https://phys.libretexts.org/Bookshelves/University_Physics/Book%253A_Introductory_Physics_-_Building_Models_to_Describe_Our_World_%28Martin_Neary_Rinaldo_and_Woodman)/27%3A_Guidelines_for_lab_related_activities/27.08%3A_Sample_lab_report_(Measuring_g_using_a_pendulum)#:~:text=Trial Angle ,8.01)). +- 【UCSB Physics Demo】*“Pendulum damped by air”*, UCSB Lecture Demonstrations (2010) ([40.37 -- Pendulum damped by air](https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/40.37.html#:~:text=,above%252C%20which%20now%20becomes)). \ No newline at end of file diff --git a/src/blogs/圆锥摆地转偏向力效应的图像处理与物理建模分析.md b/src/blogs/圆锥摆地转偏向力效应的图像处理与物理建模分析.md new file mode 100644 index 0000000..b602948 --- /dev/null +++ b/src/blogs/圆锥摆地转偏向力效应的图像处理与物理建模分析.md @@ -0,0 +1,127 @@ +--- +title: 圆锥摆地转偏向力效应的图像处理与物理建模分析 +desc: 小尺度的**圆锥摆**实验,尝试观测由于地球自转引起的摆动平面缓慢旋转,从数据处理和物理建模两方面入手,分步骤详细说明整个分析流程,包括:图像中每周期**椭圆轨迹方向**的提取、**扭转噪声**频率的识别与滤除、**滤波算法**提高信噪比、**地转偏向力效应**的建模拟合,以及**实验装置改进**建议。 +author: ChatGPT - DeepResearch +date: 2025-04-19 +tags: 计算机、物理、竞赛 +--- + +# 圆锥摆地转偏向力效应的图像处理与物理建模分析 + +## 实验背景与目标 + +在南京地区进行小尺度的**圆锥摆**实验,尝试观测由于地球自转引起的摆动平面缓慢旋转(即地转偏向力效应,又称傅科摆效应)是极具挑战性的。已知在纬度约φ=32°N处,理想傅科摆平面每天旋转约$360^\circ \sin\varphi$,换算为每小时约7.9°,对于周期约0.9秒的摆动而言,相当于**每周期仅旋转0.0022°左右** ([Foucault pendulum - Wikipedia](https://en.wikipedia.org/wiki/Foucault_pendulum#:~:text=When%20a%20Foucault%20pendulum%20is,142%20of%20the%20latitude%252C%20%CF%86)) ([Foucault pendulum - Wikipedia](https://en.wikipedia.org/wiki/Foucault_pendulum#:~:text=per%20hour,Foucault%20reported%20observing))。这一角度极其微小,容易被各种噪声淹没,包括悬绳自身的扭转振动、空气阻力和初始条件偏差等。因此,本实验利用**4K/60fps高速仰视摄像**获取摆球运动轨迹,再通过数字图像处理和信号分析提取出每周期摆动轨迹的椭圆长轴方向随时间的变化,从中解析出地转偏向力造成的缓慢漂移角速度Ω_F,目标分辨率达到0.002°–0.003°/周期。下面将从数据处理和物理建模两方面入手,分步骤详细说明整个分析流程,包括:图像中每周期**椭圆轨迹方向**的提取、**扭转噪声**频率的识别与滤除、**滤波算法**提高信噪比、**地转偏向力效应**的建模拟合,以及**实验装置改进**建议。 + +## 1. 基于OpenCV与PCA提取每周期椭圆长轴方向 + +**视频目标提取:**首先,从仰视拍摄的圆锥摆视频中获取摆球在每帧中的二维平面坐标轨迹。例如,可在摆球上贴附高对比度标记(或利用亮色摆球)便于检测。使用OpenCV可以逐帧检测摆球的位置:将每帧图像转为灰度后阈值分割或颜色过滤得到摆球轮廓,再使用`cv2.findContours`找到摆球的图像轮廓质心,记录其像素坐标$(x,y)$序列。假设摆球运动近似周期稳定~0.9s(约每54帧一个周期),可以按固定帧数分段,或通过检测摆球在某轴方向的速度过零点来划分**单个周期的数据**。 + +**轨迹椭圆拟合:**在**每一周期**内,摆球在摄像平面上的投影轨迹接近一个椭圆形(这是由于摆球在三维空间做圆周/椭圆运动,而摄像视角的投影一般为椭圆)。我们需要提取该椭圆的**长轴方向**。两种方法可以实现: + +- *方法A:OpenCV椭圆拟合。* 将一个周期内所有摆球坐标点作为散点,使用OpenCV的`cv2.fitEllipse`函数对这些点拟合椭圆 ([python - OpenCV: calculating orientation angle of major and minor axis of ellipse - Stack Overflow](https://stackoverflow.com/questions/62698756/opencv-calculating-orientation-angle-of-major-and-minor-axis-of-ellipse#:~:text=,fitEllipse%28big_contour) (xc%2Cyc)%2C(d1%2Cd2)%2Cangle %3D ellipse print(xc%2Cyc%2Cd1%2Cd1%2Cangle))。该函数返回椭圆中心、长短轴长度,以及**旋转角度**等参数,其中旋转角给出了椭圆长轴相对于图像x轴的角度(需注意OpenCV定义的角度是椭圆长轴相对于水平轴的角度,并根据轴长度大小自动调整,需要根据长短轴判断方向,如示例代码所示 ([python - OpenCV: calculating orientation angle of major and minor axis of ellipse - Stack Overflow](https://stackoverflow.com/questions/62698756/opencv-calculating-orientation-angle-of-major-and-minor-axis-of-ellipse#:~:text=,rmajor)))。拟合后即可获得该周期轨迹椭圆的长轴方向角$\theta_n$。例如,Python伪代码: + + ```python + import cv2, numpy as np + points = np.array(period_coords, dtype=np.int32) # 一个周期内的坐标点集合 + ellipse = cv2.fitEllipse(points) + (xc, yc), (major_ax, minor_ax), angle = ellipse # angle为OpenCV给出的旋转角(度) + # 确保angle对应长轴方向: + if major_ax < minor_ax: + angle = angle + 90 # 调整90°得到长轴方向角 + theta_n = angle # 当前周期椭圆长轴朝向角 + ``` + +- *方法B:主成分分析(PCA)。* 不直接拟合,而是对该周期内的摆球坐标点集做**PCA主轴分析**。具体做法是计算所有点的协方差矩阵,求取**最大特征值对应的特征向量**,该特征向量方向即为数据分布的主方向,即椭圆的长轴方向 ([OpenCV: Introduction to Principal Component Analysis (PCA)](https://docs.opencv.org/4.x/d1/dee/tutorial_introduction_to_pca.html#:~:text=drawAxis,1))。计算时先将点坐标中心化(减去均值),得到协方差矩阵$\mathbf{C}=\frac{1}{N}\sum [x_i-\bar{x}][y_i-\bar{y}]^T$,然后求$\mathbf{C}$的特征分解。OpenCV自带`cv::PCA`类可简化此过程 ([OpenCV: Introduction to Principal Component Analysis (PCA)](https://docs.opencv.org/4.x/d1/dee/tutorial_introduction_to_pca.html#:~:text=for%20,2%253B%20i)) ([OpenCV: Introduction to Principal Component Analysis (PCA)](https://docs.opencv.org/4.x/d1/dee/tutorial_introduction_to_pca.html#:~:text=drawAxis,1))。特征向量$\mathbf{v}_\text{max}=(v_x,v_y)$对应长轴方向,可通过$\text{atan2}(v_y,v_x)$得到与水平轴正方向的夹角$\theta_n$ ([OpenCV: Introduction to Principal Component Analysis (PCA)](https://docs.opencv.org/4.x/d1/dee/tutorial_introduction_to_pca.html#:~:text=drawAxis,1))。这种方法对点分布不规则也较稳健。 + +获得每周期的长轴角度$\theta_n$后,应将其转换到统一参考系下。例如,可将相机图像坐标系校准到水平面坐标(如正北方向为0°参考),这样$\theta_n$表示相对北向的方位角,有助于后续判断旋转方向(在北半球,傅科摆效应使摆平面相对于地面**顺时针**缓慢漂移)。如果相机未校准,也可后期将角度增量作为相对变化分析。最终输出的是**每个摆动周期的椭圆长轴方向时间序列** ${\theta_1, \theta_2, ...}$,每项包含一定测量噪声。 + +## 2. 利用FFT识别绳线扭转载频并设计带阻滤波去除 + +**扭转噪声的来源:**悬挂摆球的细绳往往会发生**扭转振动**:即绳索围绕自身轴来回旋转,使摆球附加了绕垂直轴的小幅转动。这种扭转会引起摆动轨迹平面的快速来回摆动,形成显著噪声,干扰我们对缓慢地转漂移的观测。根据经验,细线加摆球形成的**扭摆系统**相当于一个**扭转摆**,其固有振动频率通常在1–几Hz量级(需根据绳长、摆球转动惯量和线材扭转刚度计算)。这远高于地球自转引起的每天一圈($<0.0002$ Hz)的缓慢变化,但会体现在提取的$\theta_n$序列中形成较高频的角度抖动。 + +**频谱分析:**对${\theta_n}$序列做快速傅里叶变换(FFT),在频谱中查找**主要的高频成分**。具体步骤:首先,将$\theta_n$按时间序列(时间步长为周期$T\approx0.9$s)组成$\theta(t)$离散序列,应用离散傅里叶变换$\Theta(f) = \sum_n \theta_n e^{-j2\pi f nT}$。在幅频谱$|\Theta(f)|$中,除了接近零频的成分(对应可能的缓慢漂移趋势)之外,如果存在一显著峰值在某频率$f_0$,且对应周期约在数秒范围,那么可以怀疑这就是**绳扭转振动的主频**。记录该频率$f_0$以及可能的带宽。如果噪声较复杂,也可能出现次谐波,但一般扭转模态应较为单一。 + +**带阻滤波设计:**为消除这个扰动,可构建**数字带阻滤波器(陷波滤波器)**,专门**抑制频率$f_0$附近的成分**。陷波滤波器是一种窄带的带阻滤波器,只衰减特定频带的频率分量,其他频率基本不变 ([iirnotch — SciPy v1.15.2 Manual](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.iirnotch.html#:~:text=Design%20second,filter))。可以选择二阶IIR陷波(数字实现简便)或高阶FIR滤波实现。例如,使用Scipy提供的`signal.iirnotch`设计陷波:设采样频率$F_s=1/T\approx1.11$ Hz,中心归一化频率$w_0 = 2\pi f_0 / F_s$,品质因数$Q$决定带宽(选较高Q以窄带滤除)。代码示例: + +```python +from scipy import signal +fs = 1/0.9 # 约1.11 Hz +f0 = detected_torsion_freq # FFT识别的扭转频率(Hz) +Q = 30.0 # 假设品质因数为30,较窄带 +b, a = signal.iirnotch(f0, Q, fs) # 设计IIR陷波滤波器 +# 对θ序列应用滤波(filtfilt双向过滤以避免相移): +theta_filtered = signal.filtfilt(b, a, theta_sequence) +``` + +如此,频率$f_0$处的成分将被大幅衰减,而低频(地转漂移)和其他无关频率得以保留 ([iirnotch — SciPy v1.15.2 Manual](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.iirnotch.html#:~:text=A%20notch%20filter%20is%20a,of%20the%20spectrum%20little%20changed))。滤波后得到的$\theta_n$序列主要去除了快速扭转引起的角度抖动。然而,要注意陷波不会区分扭转噪声和可能存在的其他相近频率信号。如果扭转频率随时间漂移,则需要自适应调整滤波器或采用更复杂方法(例如时频分析结合自适应滤波)。本实验中,如能保证悬线和摆球参数稳定,扭转频率应较恒定,可一次设计滤波器应用于全程。 + +另外,除频域陷波外,也可在时域通过建模扣除。例如检测到扭转噪声主要表现为$\theta_n$中一个简谐振荡,可尝试拟合$\theta_n$中的高频成分为$A_\tau \cos(2\pi f_0 t + \phi)$并将其从信号中相减。但通常陷波滤波更直接可靠。经过这一步骤,我们获得了**消除主要扭转干扰后的摆动平面方向序列**。 + +## 3. 应用卡尔曼滤波或滑动平均提高方向信噪比 + +**问题分析:**即使消除了扭转振动,剩余的$\theta_n$序列中依然包含各种噪声:如图像检测误差导致的随机抖动、空气湍流或支架微振动导致的摆平面短周期扰动等。这些噪声通常是高频随机的,会掩盖我们关心的极低频缓变趋势。为进一步提高**方向角的信噪比(SNR)**,需要对$\theta_n$序列进行平滑滤波。两种思路可并行使用:**滑动平均**(后退式平滑处理)和**卡尔曼滤波**(模型驱动融合多周期测量)。 + +- *滑动平均滤波:* 采用长度为$M$的滑动窗口,对$\theta_n$做均值平滑,即输出$ \bar{\theta}*n = \frac{1}{M}\sum*{i=n-(M-1)}^{n}\theta_i $。这样每个周期的方向由该周期及其相邻$M-1$个周期的平均决定,可以有效抑制周期间的随机起伏。由于地转效应对应的角度每周期仅变动0.002°级别,而滑动窗口(比如选$M=5$或$M=10$相当于几秒时间)内累积漂移仍远小于噪声幅度,因此平均可以在不显著削弱信号的前提下降低噪声。需要折中选择$M$:过大会稍微平滑掉真实的漂移变化(相当于引入迟滞),但总的来说地转偏向力引起的变化足够缓慢,适度平滑是可行的。滑动平均实现简单,但无法区分随机噪声和可能存在的有规律小扰动,因此进一步可结合卡尔曼滤波。 + +- *卡尔曼滤波:* 基于动态模型的递推最优估计方法。我们建立摆动平面方向随时间的简化模型:假设每周期长轴方向 $\theta_{n}$ 以**恒定的小角速度**Ω_F在旋转(这是地转偏向力的效应),因此忽略其他扰动时 $\theta_n$ 应近似满足 $\theta_{n+1} \approx \theta_n + \Omega_F$。另外考虑到可能存在残余小幅振荡(例如由于初始激发的自由双模拍振或未完全滤除的次级扭转),可允许模型中存在一个小的过程噪声。由此构建**状态向量**$\mathbf{x}=[\theta, \omega]^T$,其中$\theta$是当前摆平面角度,$\omega$是缓慢变化的漂移角速度(理想情况下$\omega \approx \Omega_F$常数)。系统状态方程可设为:$\mathbf{x}_{n+1} = \begin{pmatrix}1 & \Delta t\0 & 1\end{pmatrix}\mathbf{x}_n + \mathbf{w}_n$,其中$\Delta t=T$为单周期时间,$\mathbf{w}*n$是过程噪声(假设为零均值高斯)。测量方程为$y_n = [1~0]\mathbf{x}*n + v_n$,其中$y_n$为第$n$周期经滤波后的长轴测量角度(含噪声),$v_n$是测量噪声。建立该**线性系统**后,即可应用标准卡尔曼滤波递推公式 ([](https://arxiv.org/pdf/2202.00388#:~:text=Kalman%20filter%20is%20an%20optimal,%282) (3)):预测步骤计算先验估计$\mathbf{x}*{n|n-1}$及协方差,通过卡尔曼增益$K_n$融合观测$y_n$更新后验估计$\mathbf{x}*{n|n}$。卡尔曼滤波的作用在于**综合多次测量以减少估计误差**,能够比单次测量更精确地估计状态 ([](https://arxiv.org/pdf/2202.00388#:~:text=Kalman%20filter%20is%20an%20optimal,%282) (3))。我们期望它能在存在噪声的$\theta_n$中滤出接近真实的平面角度以及估计出稳定的漂移速率$\omega$。 + + **卡尔曼实现提示:**初始状态可用第一个周期角度$\theta_1$和假定的初始角速度0(或依据理论$\Omega_F$估计)设置,初始协方差可给$\theta$较大不确定度、$\omega$一个大致范围的不确定度。过程噪声协方差$Q$需设较小的值(尤其对角速度分量,表明我们相信漂移速率几乎恒定但允许极小变化),测量噪声协方差$R$可根据前述滤波后$\theta_n$残余抖动估计。随时间推进,卡尔曼滤波会自动调整权重,当测量值波动较大时,更信任模型预测(平滑输出),当出现长期偏差时,逐渐校正对$\omega$的估计。伪代码举例: + + ```python + # 初始 + x = np.array([theta_filtered[0], 0.0]) # [角度, 漂移角速度] + P = np.eye(2) * 1e-3 # 初始协方差(需根据实际调整) + A = np.array([[1, 1],[0, 1]]) # 状态转移 + H = np.array([[1, 0]]) # 观测矩阵 + Q = np.diag([1e-6, 1e-8]) # 过程噪声协方差(角度和角速度过程噪声) + R = np.array([[测量噪声方差]]) # 测量噪声协方差 + for n in range(1, N): + # 预测 + x_pred = A.dot(x) + P_pred = A.dot(P).dot(A.T) + Q + # 更新 + z = theta_filtered[n] # 当前观测 + y = z - H.dot(x_pred) # 创新 + S = H.dot(P_pred).dot(H.T) + R + K = P_pred.dot(H.T) / S + x = x_pred + K.flatten()*y # 更新状态 + P = (np.eye(2) - K.dot(H)).dot(P_pred) + theta_est, omega_est = x # 滤波后的角度和估计漂移速度 + ``` + + 滤波后得到的$\theta_\text{est}(t)$将比原始测量平滑得多,而$\omega_\text{est}$则提供对每周期旋转角速度的估计。需要强调的是,卡尔曼滤波模型假定漂移角速度近似恒定,并未显式包含任何周期振荡项,因此若存在未滤除的小幅周期扰动(如几分钟的拍振),卡尔曼可能将其视为噪声平滑掉,从而突出真正的恒定漂移趋势。 + +经过上述平滑处理,我们获得高信噪比的摆平面**方向随时间变化曲线**,为后续提取地转偏向力效应作好了准备。 + +## 4. 模型拟合提取地转偏向力造成的缓慢旋转 (Ω_F) + +在获得清晰的摆平面方向随时间演化数据后,需要从中提取出由地球自转引起的**每周期缓慢旋转角速度Ω_F**。理想情况下,若实验无其他扰动,摆平面应以恒定角速度相对于地面旋转,即**线性漂移模型**:$\theta(t) = \theta_0 + \Omega_F t$(离开初始面的角度随时间线性增长)。但实际短摆实验中,初始激发方式和阻尼可能导致摆动平面出现一些**非线性漂移**特征:例如由于支架非理想性或初始轻微双向分量,可能出现**阻尼振荡**的成分——摆动轨迹的长轴方向围绕某均值作衰减振荡(所谓**椭圆偏振的拍振**)。这种现象在傅科摆理论中有所提及:若摆有两个正交自由振动分量频率极接近,微小不等将导致慢拍,使振动轨迹在固定系中呈现缓慢旋转的椭圆,而且由于阻尼,不同模式衰减不等,可能造成轨迹方向的缓慢振荡 ([Foucault pendulum - Wikipedia](https://en.wikipedia.org/wiki/Foucault_pendulum#:~:text=A%20Foucault%20pendulum%20requires%20care,to%20use%20a%20flame%20to))。因此,我们考虑两种模型来拟合数据:**线性模型**和**阻尼余弦模型**,并通过比较拟合残差选择最合适的来提取Ω_F。 + +- **线性漂移模型:**假定$\theta(t)$随时间线性增长,即$\theta_n = \theta_0 + \Omega_F , n,T$($T$为周期)。对滤波后的$\theta_n$数据进行线性回归拟合,斜率即为每秒(或每周期)的平均旋转角速度估计$\Omega_F$。例如,使用最小二乘法求解:$\Omega_F \approx \frac{\sum n\theta_n - \frac{1}{N}\sum n \sum \theta_n}{\sum n^2 - \frac{1}{N}(\sum n)^2}$(结果单位是°/周期或°/s)。也可直接用`numpy.polyfit`拟合$\theta$关于$t$的一次多项式 ([Foucault pendulum - Wikipedia](https://en.wikipedia.org/wiki/Foucault_pendulum#:~:text=proportional%20to%20the%20sine%20,of%20the%20%20143%252C%20%CF%86))。需注意,由于$\theta$是角度,会发生$0^\circ$/$360^\circ$跳变,可在拟合前将角度展开为连续函数(例如若每周期漂移很小,可通过在每次增加超过180°时减360°来保持角度连续)。线性拟合如果残差呈随机分布且很小,说明摆平面旋转可视为恒速,可直接将$\Omega_F$视为地转偏向力效应估计值。目标分辨率0.002°/周期意味着需要保证拟合不确定度在这种量级,可通过足够长的数据时长来实现——例如10分钟数据(约600周期)总漂移约1.2°,拟合斜率的标准误差将随$\sqrt{N}$降低,从而区分0.002°/周期量级的变化。 +- **阻尼余弦模型:**若线性拟合残差明显呈现周期性起伏,则考虑存在一个附加的衰减振荡项。模型可表述为: + $\theta(t) = \theta_0 + \Omega_F t + A \cos(2\pi f_d t + \phi)\,e^{-\lambda t}$ + 其中$A$是初始振荡幅度,$f_d$是扰动振荡频率(可能与绳扭转或双模拍振有关),$\lambda$是阻尼系数。这个模型表示在线性漂移$\Omega_F t$的基础上叠加一个指数衰减的余弦振荡。拟合时可以根据观察到的残差振荡周期来初设$f_d$(例如残差每几十个周期振荡一次,则$f_d\approx(几十T)^{-1}$),初步猜测$A$和$\lambda$等,然后使用非线性最小二乘(如`scipy.optimize.curve_fit`)寻找最优参数。通过此模型拟合,可将干扰振荡与恒定漂移分离开来。如果拟合得到的$\lambda$较大(意味着衰减快)且$A$不小,则初始阶段的确存在明显扰动,但之后快速衰减,剩余部分主要由线性项主导,此时$\Omega_F$的估计会更加准确。反之,如果$A$很小或$\lambda$极小(振荡几乎不衰减),可能说明我们前面滤波已基本消除了系统性的振荡,或者存在未能衰减的长期扰动,那需要重新检查实验装置。一般来说,在改进装置并充分滤波后,希望阻尼项可以忽略,线性模型已足够。 + +**提取Ω_F:**无论采用哪种模型,最终我们关心的都是线性漂移速率$\Omega_F$。对于线性模型,$\Omega_F$直接来自拟合斜率;对于阻尼余弦模型,$\Omega_F$是拟合得到的稳定项。同样地,可以将Ω_F换算为每天的旋转角度与理论值比较。例如理论上在南京纬度应该是$15^\circ/\text{h}\times\sin(32^\circ)\approx7.95^\circ/\text{h}$,即每周期约0.0022° ([Foucault pendulum - Wikipedia](https://en.wikipedia.org/wiki/Foucault_pendulum#:~:text=proportional%20to%20the%20sine%20,of%20the%20%20143%252C%20%CF%86))。如果我们的实测结果接近这一值且正负方向符合当地地理位置(南京位于北半球,摆平面应顺时针漂移,即角度随时间增加如果我们以北为0°则应表现为负向变小或者按惯例可定义相反方向),就可以认为成功测出了地转偏向力。达到0.002°/周期的分辨率,需要控制系统误差在$10^{-5}$量级,这对短时序数据要求较高,因此通常需要长时间累计和良好滤波。也可以通过**增大摆长**降低每周期自身频率,从而增加每周期地球转动的绝对角度,但本实验受限于50 cm绳长,只能通过改进信噪比来实现目标分辨率。 + +## 5. 抑制局部扰动的装置改进建议 + +为了精确测量如此细微的效应,实验装置的优化至关重要。以下从悬挂方式、干扰抑制和测量稳定性等方面提出改进: + +- **使用万向节轴承(万向接头)悬挂:**理想的傅科摆悬挂应提供**自由转动**且**极低摩擦**的支点。万向轴承(例如两个正交铰链或球形关节)允许摆球在任意竖直平面内自由摆动,而不会对其施加偏置力矩,也不会限制摆动平面的旋转。这避免了普通固定挂点因微小摩擦而锁定摆的振动平面方向,确保地球自转产生的微弱科里奥利力可以积累效应。万向节还能防止绳子扭转的力传递到支点(或反之),减少能量损失和方向扰动。但需注意万向接头自身的质量和对称性,以免引入额外噪声。许多傅科摆装置使用尖端支承在低摩擦旋转平台上的方案,也是实现类似万向自由的思路。 +- **采用双绳并联悬挂:**单根悬线容易发生自身扭转,引起摆球旋转。通过使用两根平行悬线将摆球吊挂(如将摆球两侧各连接一根长度相同的细线,到顶部两个固定点),可以**大大提高抗扭转性**。双绳悬挂(双线摆)使摆球绕垂直轴转动受到阻尼:任意绕轴旋转会使两根线彼此缠绕,产生恢复力矩,从而抑制自由扭转。这种设计被称为**双线摆支承**或**双悬丝支承**,在精密傅科摆中经常采用 ([(PDF) Pendulum Bearing Friction](https://www.researchgate.net/publication/275963434_Pendulum_Bearing_Friction#:~:text=the%20double%20pendulum%20mode,used%20precise%20chucks%20to%20hold))。需要在顶部和摆球连接处使用小轴承或旋钮,允许两线在支点和连接点自由转动以避免产生额外力矩 ([(PDF) Pendulum Bearing Friction](https://www.researchgate.net/publication/275963434_Pendulum_Bearing_Friction#:~:text=the%20double%20pendulum%20mode,used%20precise%20chucks%20to%20hold))。双绳并联除了抑制扭转噪声,也能在一定程度上稳定摆动平面的方位,使提取的信号更纯净。但是,要确保两根绳长度、张力完全一致且对称安装,否则可能引入新的不对称振动模式。 +- **利用激光水平仪辅助:**激光水平仪可以在本实验中发挥多个作用。一方面,可用于**严格校准摆架的垂直和水平**:确保悬挂点正下方的地面标记或相机光轴与重力线重合,避免支架倾斜带来伪漂移信号。将激光水平仪投射的水平线用于调整相机和摆架的水平,使系统几何对准。另一方面,可用激光束作为**光学测量参考**:例如让摆球下方安装一个小平面镜,激光水平射向镜子并反射到远处标尺上,这样摆平面的细微转动会在远处放大为可观测的光点位移,从而验证我们的视频测量结果。虽然我们已有摄像分析,但激光方法可以提供冗余校验,特别是在长时间实验中,可每隔一段时间记录激光指示的摆平面角度,以确认视频计算无漂移误差。总之,激光水平仪主要确保装置初始条件和参考系的准确,减少系统性误差。 +- **延长实验时长并多次重复:**由于地转效应本身极其微弱,**长时间观测**有利于累积信号提高信噪比。例如让摆持续振动数小时,虽然振幅会逐渐衰减,但只要轨迹清晰可见,我们就获得更多周期的数据用于平均和拟合,使Ω_F的统计不确定度降低。同时,多次独立重复实验也很重要:改变不同日期或不同初始方向重新测量,取结果的平均,可以确认地转偏向力效应的可靠存在,并排除偶然误差。延长时间还可以通过重启摆动(轻微补偿能量损失)来实现,例如每隔一定时间给予摆球极小的推力维持振幅(需非常谨慎以免引入方向扰动,理想情况用对称方式加能,如电磁驱动在摆面方向加能)。如果实验时间允许,尽量获取**超过24小时**的数据将很有意义:此时总漂移接近完整旋转,可以直接验证$\theta(t)$变化约等于$360^\circ\sin\varphi$。当然,长时间运行需防范环境变化,如温度、空气流动,必要时可以将装置置于封闭空间。 + +除了以上重点改进外,还可注意:尽量在无气流干扰的环境(避免空调风)、恒温条件下进行实验;选用**细而柔软且足够长的悬线**以增大周期和减小扭转刚度,同时摆球用**高质量高密度**材料以增强惯性抗干扰;摄像头应使用**全幅面高分辨率**且畸变校正过的镜头,以减小图像失真对轨迹形状的影响;在图像处理上,可对摆球位置做亚像素级拟合,提高定位精度;另外可以考虑**参考系锁定**:例如在实验室地板上画出指向正北的参考线,每隔一段时间在图像中校准该参考方向,以抵消相机可能的轻微转动。综合这些改进措施,能**最大程度抑制局部扰动,提高测量精度**,从而使我们有足够信心在短摆实验中检出地转偏向力效应并准确量化。 + +**总结:** 通过上述图像处理与物理建模相结合的流程,我们将圆锥摆实验中包含的复杂运动分量逐一提取和校正:利用计算机视觉技术获取摆球轨迹并提取椭圆长轴方向,频域分析识别并滤除扭转噪声,应用卡尔曼滤波等提高角度测量的稳定性,再通过模型拟合从中分离出地球自转引起的缓慢漂移项。在精心改进实验装置、控制噪声源后,即使在50 cm短摆上也有望以0.002°/周期的分辨率观测到傅科摆效应。这不仅验证了地转偏向力的存在,也展示了现代数字分析方法在经典物理实验中的威力。希望以上步骤为在普通本科实验室条件下实现高精度地转效应测量提供可行方案。 + +**参考文献:** + +1. OpenCV Documentation - *Introduction to PCA*: Demonstrates using PCA to find object orientation ([OpenCV: Introduction to Principal Component Analysis (PCA)](https://docs.opencv.org/4.x/d1/dee/tutorial_introduction_to_pca.html#:~:text=drawAxis,1)) +2. StackOverflow - *cv2.fitEllipse usage*: Example of fitting ellipse to contour and obtaining angle ([python - OpenCV: calculating orientation angle of major and minor axis of ellipse - Stack Overflow](https://stackoverflow.com/questions/62698756/opencv-calculating-orientation-angle-of-major-and-minor-axis-of-ellipse#:~:text=,fitEllipse%28big_contour) (xc%2Cyc)%2C(d1%2Cd2)%2Cangle %3D ellipse print(xc%2Cyc%2Cd1%2Cd1%2Cangle)) +3. SciPy Documentation - *IIR Notch Filter*: Definition and usage of narrow-band stop filter for removing a specific frequency ([iirnotch — SciPy v1.15.2 Manual](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.iirnotch.html#:~:text=Design%20second,filter)) +4. Kalman Filter Tutorial (Arxiv 2022): Kalman filter combines measurements over time for optimal state estimation ([](https://arxiv.org/pdf/2202.00388#:~:text=Kalman%20filter%20is%20an%20optimal,%282) (3)) +5. Wikipedia - *Foucault Pendulum*: Explains rotation rate $\omega = 360^\circ \sin\varphi/$day and example values ([Foucault pendulum - Wikipedia](https://en.wikipedia.org/wiki/Foucault_pendulum#:~:text=When%20a%20Foucault%20pendulum%20is,142%20of%20the%20latitude%252C%20%CF%86)) ([Foucault pendulum - Wikipedia](https://en.wikipedia.org/wiki/Foucault_pendulum#:~:text=per%20hour,Foucault%20reported%20observing)) +6. Pendulum Bearing Friction (Hinrichsen 2014): On bifilar suspension needing free rotation bearings to allow Foucault precession \ No newline at end of file diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/2025-04-19023159.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/2025-04-19023159.png new file mode 100644 index 0000000..214e3ec Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/2025-04-19023159.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/2025-04-19024427.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/2025-04-19024427.png new file mode 100644 index 0000000..911acd4 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/2025-04-19024427.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315081918504.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315081918504.png new file mode 100644 index 0000000..dabb270 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315081918504.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315081925526.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315081925526.png new file mode 100644 index 0000000..f96c513 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315081925526.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082033387.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082033387.png new file mode 100644 index 0000000..5efd6a3 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082033387.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082208829.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082208829.png new file mode 100644 index 0000000..0466894 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082208829.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082216352.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082216352.png new file mode 100644 index 0000000..78c384f Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082216352.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082225268.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082225268.png new file mode 100644 index 0000000..acf26c6 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250315082225268.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162755829.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162755829.png new file mode 100644 index 0000000..2924179 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162755829.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162814547.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162814547.png new file mode 100644 index 0000000..b7557de Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162814547.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162912589.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162912589.png new file mode 100644 index 0000000..bdc47ce Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162912589.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162921618.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162921618.png new file mode 100644 index 0000000..57bd1a9 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162921618.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162935371.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162935371.png new file mode 100644 index 0000000..3aa9292 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162935371.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162941564.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162941564.png new file mode 100644 index 0000000..9a95de4 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250418162941564.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419023105897.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419023105897.png new file mode 100644 index 0000000..5fcd61b Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419023105897.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419024511788.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419024511788.png new file mode 100644 index 0000000..459af34 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419024511788.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032053217.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032053217.png new file mode 100644 index 0000000..e8316e8 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032053217.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032112238.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032112238.png new file mode 100644 index 0000000..3d71687 Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032112238.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032847769.png b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032847769.png new file mode 100644 index 0000000..dfb07bd Binary files /dev/null and b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.assets/image-20250419032847769.png differ diff --git a/src/blogs/基于CV的单摆实验优化方案实验进度与总结.md b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.md new file mode 100644 index 0000000..9e60f72 --- /dev/null +++ b/src/blogs/基于CV的单摆实验优化方案实验进度与总结.md @@ -0,0 +1,217 @@ +--- +title: 基于CV的单摆实验优化方案——实验进度与总结 +desc: 单摆是一种经典的实验方法,用于测定重力加速度 $g$,但传统方法(例如用秒表计时)存在局限性。由于人类反应时间以及小角度近似的限制,所测得的 $g$ 往往存在几百分点的误差。我们的实验利用计算机视觉获取高质量的摆球位置-时间数据,应用数学模型提取周期信息,最后通过非线性拟合消除大振幅和阻尼影响,测得准确的重力加速度值并评估空气阻力特性。 +author: feie9454 +date: 2025-04-26 +tags: 计算机、物理、竞赛 +--- + +# 基于CV的单摆实验优化方案——实验进度与总结 + +## 2025.3.1 + +1. 以计算机视觉技术处理大量数据的优势为出发点,寻找适合降低系统误差的实验项目。确定了单摆测量重力加速度实验,并计划同步测量空气阻力等附加信息。 +2. 通过文献调研,明确了实验创新点及基本实现路径。 + + -->(/blogs/利用计算机视觉和系统误差校正的高精度单摆重力测量.md) + +## 2025.3.8 + +1. 验证了实验在物理上的可行性,推导出解决系统误差(空气阻力、大摆角)的相关修正公式。 +2. 使用手机成功进行识别演示,证实技术可行性。确定采用Hough圆检测算法进行高效追踪,并确立首个创新点:降低使用门槛,实现手机操作。 + + -->(/blogs/单摆周期的系统误差研究:大摆角效应与空气阻力及其拟合校正.md) + + -->V(/resources/Phy-exp/手机检测demo.mp4) + + +## 2025.3.15 + +1. 完成识别算法调试(屏幕录制中记录了识别过程)。针对球体阴影和反光导致的不完整识别问题,采用最大外接圆算法获得良好识别效果。视频中曾测试blob策略,但效果欠佳,后续已删除。 +2. 成功应用空气阻力和大摆角修正公式进行计算。 +3. 最终测量误差最高达5%且方向随机,尚未确定误差来源。 + + -->V(/resources/Phy-exp/屏幕录制 2025-03-15 080119.mp4) + + | ![image-20250315082033387](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250315082033387.png) | ![image-20250315082208829](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250315082208829.png) | + | ------------------------------------------------------------ | ------------------------------------------------------------ | + | ![image-20250315081918504](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250315081918504.png) | ![image-20250315082216352](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250315082216352.png) | + | ![image-20250315081925526](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250315081925526.png) | ![image-20250315082225268](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250315082225268.png) | + +## 2025.3.22 + +1. 发现最大误差来源为摆长测量。由于摆长与重力加速度成正比,测量误差直接传递到最终结果。 +2. 视觉方法难以精确将像素信息转换为实际长度,原方案存在以下问题: + - 无法确保画面中的参考尺与球摆动在同一平面 + - 参考尺跨越画面过长时出现广角畸变;仅使用中心区域则参考长度过短,放大至摆长时会至少放大五倍,引入额外误差 + +3. 采用人工测量摆长后,误差降至<1%。 +4. 考虑使用标定板等设备作为解决方案。 + +## 2025.3.29 + +1. 通过4种不同摆长测量并拟合公式$L \propto T^2$,最终误差降至0.43%,拟合精度极高。 + + -->(/resources/Phy-exp/report0329.html) + +2. 确认侧面视角测量的固有问题: + - 球摆动平面与拍摄平面不一定平行,导致摄像机视角下观测到的摆动圆弧半径偏小,拟合摆长因此偏短 + - 无法分析圆锥摆的三维运动信息(球体前后运动无法通过近大远小效应精确测量) + +3. 提出采用底部视角测量方案,以获取圆锥摆的相关信息,同时避免侧向拍摄时调整手机支架的麻烦及支架缓慢弯曲带来的误差。 + +## 2025.4.12 + +1. 进行了从底部向上仰拍的实验,获得了数组实验数据。 + + -->V(/resources/Phy-exp/ball-track-rl1.mp4) + + | ![image-20250418162755829](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250418162755829.png) | ![image-20250418162814547](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250418162814547.png) | + | ------------------------------------------------------------ | ------------------------------------------------------------ | + | 旋转椭圆先逆时针旋转 | 一段时间后变为顺时针旋转 | + + | ![image-20250418162912589](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250418162912589.png) | ![image-20250418162921618](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250418162921618.png) | + | ------------------------------------------------------------ | ------------------------------------------------------------ | + | ![image-20250418162935371](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250418162935371.png) | ![image-20250418162941564](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250418162941564.png) | + | 旋转椭圆先顺时针旋转 | 一段时间后变为逆时针旋转 | + +2. 我们起先认为可能捕捉到了地转偏向力,后来发现旋转的方向在三次实验中并不一致,且都是旋转一定时间后,反方向旋转了。 + +3. 推断原因可能为放手时小球自带一个旋转的动量。 + +## 2025.4.18 + +尝试进行了长轴旋转量随时间变化的分析, + +| ![image-20250419024511788](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250419024511788.png) | ![2025-04-19024427](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/2025-04-19024427.png) | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| ![image-20250419032053217](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250419032053217.png) | ![image-20250419032112238](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/image-20250419032112238.png) | + +起先观察到 $\delta \theta / t$ 似乎趋近于某值,尝试进行拟合: + +指数模型: +$$ +\Delta\theta(t)=\Delta\theta_{\infty}+A\,e^{-t/\tau} +$$ + +![2025-04-19023159](./%E5%9F%BA%E4%BA%8ECV%E7%9A%84%E5%8D%95%E6%91%86%E5%AE%9E%E9%AA%8C%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88%E5%AE%9E%E9%AA%8C%E8%BF%9B%E5%BA%A6%E4%B8%8E%E6%80%BB%E7%BB%93.assets/2025-04-19023159.png) + +最终结果:Δθ∞ ≈ -0.26419 °/cycle系统最后稳定在 **≈ −0.2 °/cycle** 的水平——数值远大于地转效应应有的 ± 0.003 °/cycle。负号的来源:**仰视拍摄** 时,坐标系 y 轴反向,俯视所见的顺时针变成画面上的逆时针,故符号翻转。 + +意识到拟合方法有问题,因为我现在的长轴转动实际上是因为摆线扭转,所以剔除地转偏向的影响,那么应该是一个顺时针逆时针交替的转动速度,根本不应该用指数拟合。 + +image-20250419032847769 + +查询资料,形成报告: + +-->(/blogs/圆锥摆地转偏向力效应的图像处理与物理建模分析.md) + +要点:用 FFT 去除高频。 + +问题:使用装置中小球和支点没有扭转的可能,因为棉线是绑在球上的。需要在顶部和摆球连接处使用小轴承或旋钮。 + +下一步计划:圆锥摆上还可以做什么文章? + +## 2025/4/26 + +**专家系统(Expert System)**,是在上世纪1970-1980年代非常火的一种**人工智能方法**,它的核心概念是: + +- **把人类专家的知识和推理规则**,**用硬编码**(写成程序规则)放进计算机里。 +- 当系统接收到问题时,**按规则一步步推理**,得出结论或建议。 + +它主要包含两个部分: + +1. **知识库(Knowledge Base)**: + 储存大量**专家知识**,通常以“如果-那么”(IF-THEN)规则的形式,比如:“如果温度高且湿度大,那么可能是故障A”。 +2. **推理机(Inference Engine)**: + 一个自动推理模块,负责根据已有规则**进行逻辑推导**,一步步推出答案。 + +------ + +**特点:** + +- 完全靠人编规则,不会自学。 +- 对小规模、规则清晰的问题很有效(比如医疗诊断、设备故障检测)。 +- 规则一旦太多(上万条),维护和扩展就变得非常困难,容易“崩塌”。 + +------ + +**经典例子**: + +- **MYCIN**(1970年代初期): + 用来帮助医生诊断血液感染疾病,准确率非常高(甚至比普通医生还高)。 +- **XCON(DEC公司开发)**: + 用来配置大型计算机系统的零部件,帮助销售人员定制产品。 + +------ + +一句话总结: + +> **专家系统就是把专家经验写成一堆IF-THEN规则,让电脑“像专家一样”做推理决策。** + +**“AI 赋能物理实验”究竟要体现什么?** + 评审通常希望看到: + +| 维度 | 传统做法 | “AI”加持后应有什么升级 | +| ---------- | ------------------------------------------ | ------------------------------------------------------------ | +| **感知层** | 固定阈值 + 几何算法(Hough 圆、峰值检测…) | **深度视觉**(YOLOv8、DeepSORT、Keypoint RNN…)在复杂光照和遮挡下依旧稳健,实时 FPS 可视化 ([YOLOv8 Object Detection & Tracking Guide - Ultralytics](https://www.ultralytics.com/blog/object-detection-and-tracking-with-ultralytics-yolov8?utm_source=chatgpt.com)) | +| **建模层** | 手动写出 ODE,再做非线性最小二乘 | **数据驱动发现**:• SINDy 稀疏识别自动给出微分方程 ([Sparse identification of nonlinear dynamical systems - arXiv](https://arxiv.org/abs/1509.03580?utm_source=chatgpt.com)) • AI Feynman 进行符号回归,输出可解释公式 ([AI Feynman: A physics-inspired method for symbolic regression](https://www.science.org/doi/10.1126/sciadv.aay2631?utm_source=chatgpt.com)) | +| **推断层** | 点估计(最小二乘得到单个 g、k…) | **贝叶斯或 PINN**:• MCMC / PyMC 给出参数后验 + 置信区间 • Physics-Informed NN 直接在像素→ODE 间端到端拟合 ([Physics-Informed Neuro-Evolution (PINE): A Survey and Prospects](https://arxiv.org/html/2501.06572v1?utm_source=chatgpt.com)) | +| **决策层** | 人手调节光源、角度、振幅 | **自适应实验**:RL / 贝叶斯优化实时调整实验条件以最小化参数方差 ([A physics informed bayesian optimization approach for material ...](https://www.nature.com/articles/s41524-023-01173-7?utm_source=chatgpt.com)) | +| **运维层** | 手动查错、写报告 | AI - Residual AutoEncoder 自动检测异常数据;大语言模型自动生成实验报告 | + +------ + +## 如何把现有方案升级为“AI 赋能”项目? + +### 1 感知:用深度视觉替换硬规则 + +| 具体动作 | 效果 | +| --------------------------------------------- | ------------------------------------------------------------ | +| **YOLOv8 + DeepSORT** 追踪摆球/砝码 | 训练后对光斑、反光、遮挡鲁棒,帧率 60 fps 以上(Edge GPU 可实时) | +| **自监督关键点跟踪**(如 DINOv2 + RAFT 光流) | 无需人工标注即可在不同实验之间迁移,适合滚动球、弹簧端点等形态变化目标 | +| **多相机 + 单目深度网络** | 直接预测 3-D 轨迹,免去手工尺标与透视校正 | + +### 2 模型发现:让 AI 自己写方程 + +| 工具 | 可以做什么 | +| ------------------------------------------------------- | ------------------------------------------------------------ | +| **SINDy** (Sparse Identification of Nonlinear Dynamics) | 从 $(x(t),\dot x,\ddot x)$ 数据里筛选最少的基函数组合,自动输出 $ \ddot x = f(x,\dot x)$ ([Sparse identification of nonlinear dynamical systems - arXiv](https://arxiv.org/abs/1509.03580?utm_source=chatgpt.com)) | +| **AI Feynman** | 对测得的 $(T,\theta)$、$(a,m)$ 等表格做符号回归,返还可解释解析式(含物理常数) ([AI Feynman: A physics-inspired method for symbolic regression - PMC](https://pmc.ncbi.nlm.nih.gov/articles/PMC7159912/?utm_source=chatgpt.com)) | +| **Auto-PINN** | 把未知力项当“可训练函数”,网络同时满足运动方程残差和边界条件,实现隐力识别(例如滚动摩擦的速度依赖形式) | + +### 3 不确定度与解释 + +- **Bayesian Neural ODE / PyMC**:给出 $g,k,I,\mu_r$ 的完整后验分布,而非单点估计;可直接用置信区间作为误差条形图。 +- **SHAP / LIME**:解释深度检测模型在不同光照角度时依赖的像素区域,方便调光源或贴标记。 + +### 4 自适应实验设计 + +- **贝叶斯优化 (BO)**:实验实时决定下一次振幅、质量差或拍摄帧率,使 Fisher 信息最大(参数方差最小)。近年来物理与材料实验已用 BO 自动排程 ([A physics informed bayesian optimization approach for material ...](https://www.nature.com/articles/s41524-023-01173-7?utm_source=chatgpt.com))。 +- **深度强化学习 (RL)**:控制伺服电机自动改变弹簧载荷或扭摆阻尼板开口,使残差谱最平坦,形成“AI 智能调参实验台”。 + +### 5 数据治理与报告 + +- **异常检测**:残差序列喂入 LSTM-VAE,自动标出摄像掉帧、灯闪烁导致的离群周期。 +- **LLM-Copilot**:把实验日志 + 图表交给 GPT-4o 生成中文 / 英文双语报告并自动插入 LaTeX 公式与参考文献。 + +------ + +## 为什么这样就“够 AI”? + +1. **端到端学习**:从像素到物理参数无需人工阈值或公式硬编码。 +2. **自适应/自发现**:算法自行决定实验参数或生成闭式方程。 +3. **可解释**:符号回归 / 稀疏建模保证输出仍是“物理公式”,回避黑盒质疑。 +4. **不确定度**:贝叶斯方法量化实验可信度,更符合科研评审口味。 +5. **自动化闭环**:AI 不仅分析数据,还实时控制实验条件,真正“在环”。 + +结合这些升级,你的项目从“用 CV 计时”跃升为**AI 驱动的物理实验平台**。在竞赛答辩时,可突出以下卖点: + +- *学术前沿*:引用 SINDy、AI Feynman、PINN 等最新 SciML 论文 ([Sparse identification of nonlinear dynamical systems - arXiv](https://arxiv.org/abs/1509.03580?utm_source=chatgpt.com), [AI Feynman: A physics-inspired method for symbolic regression](https://www.science.org/doi/10.1126/sciadv.aay2631?utm_source=chatgpt.com), [Physics-Informed Neuro-Evolution (PINE): A Survey and Prospects](https://arxiv.org/html/2501.06572v1?utm_source=chatgpt.com)); +- *工程落地*:演示 YOLOv8 实时检测视频,对复杂背景同样稳健 ([YOLOv8 Object Detection & Tracking Guide - Ultralytics](https://www.ultralytics.com/blog/object-detection-and-tracking-with-ultralytics-yolov8?utm_source=chatgpt.com)); +- *创新性*:展示 BO/RL 实时调控实验,使误差条逐轮收敛; +- *可扩展*:同一 AI 框架迁移到 5 个经典实验,构成教学实验套件。 + +这样设计不仅满足“AI 赋能”主题,还能体现**跨学科融合、可解释性与可迁移性**三大当前热点。 + +-->(/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.md) diff --git a/src/blogs/基于计算机视觉的单摆实验优化方案.md b/src/blogs/基于计算机视觉的单摆实验优化方案.md new file mode 100644 index 0000000..dc8e664 --- /dev/null +++ b/src/blogs/基于计算机视觉的单摆实验优化方案.md @@ -0,0 +1,211 @@ +--- +title: 利用计算机视觉和系统误差校正的高精度单摆重力测量 +desc: 单摆是一种经典的实验方法,用于测定重力加速度 $g$,但传统方法(例如用秒表计时)存在局限性。由于人类反应时间以及小角度近似的限制,所测得的 $g$ 往往存在几百分点的误差。这份报告提出了利用计算机视觉和系统误差校正的高精度单摆重力测量。 +author: feie9454 +date: 2025-02-28 +tags: 计算机、物理、竞赛 +--- + +# 利用计算机视觉和系统误差校正的高精度单摆重力测量 + +## 1. 背景与创新 + +单摆是一种经典的实验方法,用于测定重力加速度 $g$,但传统方法(例如用秒表计时)存在局限性。由于人类反应时间以及小角度近似的限制,所测得的 $g$ 往往存在几百分点的误差。例如,若采用较大振幅(约45°)而不进行修正,则摆的周期会延长约4%,导致计算出的 $g$ 低估约8% ([Pendulum experiment systematic errors](https://www.physicsforums.com/threads/pendulum-experiment-systematic-errors.889342/#:~:text=14%252C139))。在常规实验室中,采用严谨技术可将 $g$ 的精度控制在约1% ([Pendulum experiment systematic errors](https://www.physicsforums.com/threads/pendulum-experiment-systematic-errors.889342/#:~:text=The%20finite%20moment%20of%20inertia,and%20still%20with%20large%20fluctuations)),但学生实验往往因系统误差而达不到如此精度。引入**计算机视觉 (CV)** 来追踪单摆运动,有望大幅提高测量精度。 + +为确保我们的实验设计扎实并将工作置于合适背景中,我们查阅了中外关于高精度单摆实验与误差分析的文献。多年来,众多研究探讨了如何利用单摆改进 $g$ 的测量,以及如何将现代技术整合到这一经典实验中: + +- **以往的竞赛与项目:**国外已有研究证明,将计算机视觉引入单摆等力学实验可以显著提高数据质量和实验效率 ([(PDF) Computer Vision Based Object Tracking as a Teaching Aid for High School Physics Experiments](https://www.researchgate.net/publication/320234204_Computer_Vision_Based_Object_Tracking_as_a_Teaching_Aid_for_High_School_Physics_Experiments#:~:text=standard%20experiments,In%20all%20three%20experiments))。例如Illeperuma等人利用CV跟踪单摆,实现了高精度周期测量和速度曲线绘制 ([(PDF) Computer Vision Based Object Tracking as a Teaching Aid for High School Physics Experiments](https://www.researchgate.net/publication/320234204_Computer_Vision_Based_Object_Tracking_as_a_Teaching_Aid_for_High_School_Physics_Experiments#:~:text=standard%20experiments,In%20all%20three%20experiments))。国内一些高校也开始探索居家实验利用手机传感器或视频分析完成单摆实验 ([大学物理实验-居家实验1-利用单摆测量重力加速度-阿里云开发者社区](https://developer.aliyun.com/article/1167555#:~:text=3.%E7%94%A8%E5%8F%A6%E4%B8%80%E9%83%A8%E6%89%8B%E6%9C%BA%E4%BD%9C%E4%B8%BA%E7%A7%92%E8%A1%A8%E8%AE%A1%E6%97%B6%EF%BC%8C%E5%B0%86%E8%A2%AB%E6%8D%86%E4%BD%8F%E7%9A%84%E6%89%8B%E6%9C%BA%E8%A7%86%E4%BD%9C%E5%B0%8F%E7%90%83%E3%80%82%E7%94%A8%E6%89%8B%E5%B0%86%E5%B0%8F%E7%90%83%E6%8B%89%E8%87%B3%E5%81%8F%E7%A6%BB%E7%AB%96%E7%9B%B4%E6%96%B9%E5%90%91%E7%9A%84%E4%B8%80%E4%B8%AA%E5%B0%8F%E8%A7%92%E5%BA%A6%EF%BC%88%CF%86))。常用的软件有Tracker和Phyphox等 ([单摆测定重力加速度_单摆测重力g的不确定度公式-CSDN博客](https://blog.csdn.net/lzc_007/article/details/131867568#:~:text=1%E3%80%81%E6%A0%B9%E6%8D%AE%E7%9B%B8%E5%AF%B9%E4%B8%8D%E7%A1%AE%E5%AE%9A%E5%BA%A6%E4%B8%8D%E5%A4%A7%E4%BA%8E5)):Tracker需要人工在视频中标记和跟踪,Phyphox则借助手机内传感器测量。这些方法虽然减少了部分人工读数,但**自动化程度不高**或**依赖额外传感器**。相比之下,本项目全程采用计算机视觉自动跟踪,无需人为干预或附加传感器,属于更高层次的自动化实验方案。 + +- **高精度单摆研究:** 经典研究探讨了单摆的复杂性。Nelson & Olsson (1986) 讨论了单摆中诸多影响因素,并对其物理进行了全面处理 ([arxiv.org](https://arxiv.org/pdf/2002.03796#:~:text=Learning%252C%20Pacific%20Grove%252C%202003) p,15%2C 2019))。Lima & Arun (2006) 推导了大振幅下周期的精确公式 ([arxiv.org](https://arxiv.org/pdf/2002.03796#:~:text=Learning%252C%20Pacific%20Grove%252C%202003) p,895 (2006)),我们在校正中正是利用了这一公式。这些文献为我们的校正提供了理论支持(例如确认了我们用于 $T(\theta_0)$ 的级数展开)。在阻尼方面,Lee & Ju (2020) 利用光闸系统测定了不同球形摆锤的空气阻力系数([arxiv.org](https://arxiv.org/pdf/2002.03796#:~:text=In%20order%20to%20obtain%20the,automate%20measurement%20of%20the%20speed))。他们发现阻力与横截面积成正比,与理论一致。我们引用了他们的结果,以证明采用密度较高的金属摆锤(相对于质量而言表面积小)能保持较低阻尼,同时也将我们测得的阻尼常数与理论预期进行比较。了解文献中阻尼的数量级有助于确保我们的阻尼分析合理(例如,若测得的阻尼系数远超预期,则说明存在问题)。 +- **类似背景下的误差分析:** Marzari *et al.* (2020) 在《The Physics Teacher》上发表了一篇关于视频分析实验中常见误差的文章 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=match%20at%20L674%20Errors%20in,European))。他们指出了透视误差、计时校准和运动模糊等问题。我们在设计中已考虑了这些因素(例如采用高速快门避免模糊、仔细校准等)。另一项由Martin, Frisch, & Zwart (2020) 进行的研究试图通过视频测 $g$,结果误差约为19.7% ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=match%20at%20L674%20Errors%20in,European)),可能因未考虑部分系统误差。这警示我们,仅录制视频是不够的,必须仔细分析。相较之下,Wabeto的一个项目(在Pacala 2023中提及)利用Photoshop和MATLAB进行追踪,将误差降至0.20%([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=match%20at%20L400%20percent%20error,track%20the%20simple%20pendulum%27s%20movement)),显示了在极为细致或采用复杂算法的情况下可能达到的最高精度。我们的目标是通过更易获取的手段(OpenCV、基础编程)接近这一精度,并系统地进行校正,使之在教育环境中可重复。 +- **替代方法:** 文献中也有利用其他方法测定 $g$ 的例子以供比较。例如,利用定时电路或运动传感器进行自由落体实验,以及利用弹簧振荡实验。我们注意到,诸如 Phyphox 之类的智能手机应用已被用于课堂上,通过计时单摆或利用内部传感器测定 $g$,其误差通常约为1–2%。这些方法虽方便,但未深入探讨误差来源。而利用激光脉冲计时落体等先进方法则能获得极高精度,但需要昂贵设备。我们的方案试图找到一个平衡点:**低成本、高精度并全面理解**。回顾以往工作,我们确认本实验建立在经过验证的概念(视频追踪、回归分析)之上,但又因完整的误差分析而独具特色。 + +本项目的创新体现在 **“技术+内容”** 两方面。技术上,融合了**AI目标检测**与**机器学习校正**,不仅自动获取数据,还能智能纠正误差,提升结果准确度。这一点在以往文献中尚不多见,属于AI赋能实验的新尝试 ([AI科学家:自动发现物理系统的隐藏状态变量 - 集智俱乐部](https://swarma.org/%3Fp%3D36201#:~:text=AI%E7%A7%91%E5%AD%A6%E5%AE%B6%EF%BC%9A%E8%87%AA%E5%8A%A8%E5%8F%91%E7%8E%B0%E7%89%A9%E7%90%86%E7%B3%BB%E7%BB%9F%E7%9A%84%E9%9A%90%E8%97%8F%E7%8A%B6%E6%80%81%E5%8F%98%E9%87%8F%20))。内容上,我们将单摆实验拓展为综合测量阻尼和非线性效应,多参数联测也是创新之处。一些竞赛作品曾研究过单摆或弹簧摆的复杂运动(如北邮2017年作品探讨了周期驱动力下单摆非线性行为) ([2017年物理实验竞赛获奖作品简介-周期力驱动下弹簧摆的行为-北京邮电大学物理实验教学中心](https://physlab.bupt.edu.cn/info/1311/1867.htm#:~:text=%E5%9B%BE%E5%85%AD%20%E5%8D%95%E6%91%86%E5%9C%A8%E7%9F%AD%E7%BB%B3%EF%BC%8850cm%EF%BC%89%E5%8F%97%E4%B8%8D%E5%90%8C%E5%91%A8%E6%9C%9F%E6%80%A7%E9%A9%B1%E5%8A%A8%E5%8A%9B%E7%9A%84%E5%B9%85%E9%A2%91%E7%89%B9%E6%80%A7%E6%9B%B2%E7%BA%BF)) ([2017年物理实验竞赛获奖作品简介-周期力驱动下弹簧摆的行为-北京邮电大学物理实验教学中心](https://physlab.bupt.edu.cn/info/1311/1867.htm#:~:text=%E7%94%B1%E4%B8%8A%E5%9B%BE%E5%8F%AF%E7%9F%A5%EF%BC%8C%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E5%AD%94%E8%B7%9D%E5%A4%A7%E5%B0%8F%E6%97%B6%EF%BC%8C%E5%8D%95%E6%91%86%E7%9A%84%E5%85%B1%E6%8C%AF%E9%A2%91%E7%8E%87%E4%B9%9F%E5%B0%86%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%EF%BC%8C%E5%8D%B3%E5%8D%95%E6%91%86%E7%9A%84%E5%9B%BA%E6%9C%89%E9%A2%91%E7%8E%87%E5%8F%91%E7%94%9F%E6%94%B9%E5%8F%98%E3%80%82%E4%B8%94%E9%9A%8F%E7%9D%80%E5%8D%95%E6%91%86%E6%8C%AF%E5%B9%85%E7%9A%84%E5%A2%9E%E5%A4%A7%EF%BC%8C%E5%8D%95%E6%91%86%E7%9A%84%E5%9B%BA%E6%9C%89%E9%A2%91%E7%8E%87%E5%87%8F%E5%B0%8F%E3%80%82%E4%B8%BA%E9%AA%8C%E8%AF%81%E8%BF%99%E4%B8%80%E7%BB%93%E8%AE%BA%EF%BC%8C%E6%88%91%E4%BB%AC%E6%94%B9%E5%8F%98%E4%BA%86%E6%91%86%E9%95%BF%E7%9A%84%20%E5%A4%A7%E5%B0%8F%EF%BC%8C%E7%BB%98%E5%87%BA%E4%B8%8D%E5%90%8C%E6%91%86%E9%95%BF%E5%8D%95%E6%91%86%E5%9B%BA%E6%9C%89%E9%A2%91%E7%8E%87%E9%9A%8F%E6%8C%AF%E5%B9%85%E7%9A%84%E5%8F%98%E5%8C%96%E6%9B%B2%E7%BA%BF%E5%A6%82%E4%B8%8B%E3%80%82));本项目则聚焦于**无需额外驱动力**也可通过精密测量发掘非线性特征,这在学生级实验中较为少见。另外,我们开发的实时可视化和自动报告系统,使得实验装置不只是获取数字,更能**动态演示物理过程**,具有出色的科教展示效果,这是传统实验难以实现的。 + +## 2. 实验设计与数据采集 + +**设备:** 为保持装置低成本,我们将采用消费级相机。现代智能手机或网络摄像头只需支持至少60 FPS(每秒60帧)视频即可(大多数智能手机支持60 fps,且效果良好 ([GitHub - supreme-gg-gg/pendulum-tracking: PHY180 -- Track and Analyze Pendulum Motion](https://github.com/supreme-gg-gg/pendulum-tracking#:~:text=The%20program%20works%20best%20with,or%20a%20wrong%20time%20scale))。例如,Pacala *et al.* (2023) 就曾使用 iPhone 13 的高速相机拍摄单摆,证明手机可作为可靠的高帧率相机使用 [journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=insights%20on%20using%20a%20tracker,speed%20camera%20from%20the%20iPhone)。在60–240 fps下,时间分辨率大约为0.001–0.01秒,远优于人类反应速度。相机将稳固安装(例如置于三脚架上),并垂直于单摆运动平面。良好的照明和高对比背景有助于视觉算法检测摆锤。初步想法是基于 OpenCV.js 或 Tensorflow.js 进行识别,这样可以实现在手机浏览器上直接运行,使得实验成本几乎为 0。 + +**计算机视觉追踪:** 我们将实现算法,自动在视频帧中检测并追踪单摆摆锤。一个简单的方法是颜色追踪——例如,在摆锤上附加一个鲜艳标记,这样便可以在HSV颜色空间中对视频进行阈值处理,进而找到摆锤的质心 ([Pendulum Tracking : r/computervision](https://www.reddit.com/r/computervision/comments/ajxsrl/pendulum_tracking/#:~:text=%E2%80%A2))。若背景均匀,此方法快速且鲁棒。或者,我们可使用OpenCV中提供的通用物体追踪算法,如KCF或CSRT追踪器 ([GitHub - supreme-gg-gg/pendulum-tracking: PHY180 -- Track and Analyze Pendulum Motion](https://github.com/supreme-gg-gg/pendulum-tracking#:~:text=The%20following%20script%20will%20process,files%20in%20the%20specified%20directory)),在设定初始边界框后即可锁定摆锤。另一种方法是利用光流:将视频转换为灰度图后计算光流矢量,从而分离出单摆运动(正如Illeperuma & Sonnadara利用Horn–Schunk光流寻找单摆运动中的移动斑点所示 ([Different steps in tracking a pendulum a) Grayscale image b) Optical... | Download Scientific Diagram](https://www.researchgate.net/figure/Different-steps-in-tracking-a-pendulum-a-Grayscale-image-b-Optical-flow-vectors-c_fig1_320234204#:~:text=,at%20each%20region%20was)) ([Different steps in tracking a pendulum a) Grayscale image b) Optical... | Download Scientific Diagram](https://www.researchgate.net/figure/Different-steps-in-tracking-a-pendulum-a-Grayscale-image-b-Optical-flow-vectors-c_fig1_320234204#:~:text=,were%20identified%252C%20their%20properties)))。在每一帧中识别出摆锤后,其像素坐标即被记录。接着,我们将把像素位置转换为物理单位;这需要在单摆平面上放置一个已知长度的校准物(例如米尺)。校准时须注意对齐刻度以避免视差误差。追踪输出将是摆锤位移 $x(t)$ 或角度 $\theta(t)$ 随时间的变化。这一丰富的数据流使我们能够一次性确定周期、振幅和阻尼,而不只是手动计时几个摆动周期。 + +**数据采集策略:** 我们计划在多种条件下采集数据,以确保进行全面分析: + +- **不同摆长:** 我们将制作不同摆长 $L$(例如0.5 m、1.0 m、1.5 m等)的单摆,并测量各自的周期。根据理论,$T^2 \propto L$,因此绘制 $T^2$ 与 $L$ 的图应呈直线 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=In%20Figure%205%252C%20the%20data,positive%20slope%20can%20be%20observed))。通过线性拟合,我们可以从斜率中确定 $g$(详见第4节)。采用多种摆长既提供冗余,也有助于平均掉随机误差;同时可检查是否存在与摆长相关的系统性偏差。 +- **不同初始振幅:** 我们将进行不同释放角(例如 $5^\circ$、$15^\circ$、$30^\circ$)的试验。对于每个振幅,都会记录单摆运动。这样可以观察到,由于非线性效应,较大振幅下周期如何增加。CV系统会捕捉到振幅随时间逐渐减小(因阻尼作用)的过程,从而可以测量初始振幅较大时与摆幅减小时的周期。通过获取多种振幅的数据,之后我们可以应用校正或外推到“零振幅”,从而使实验超出小角范围,有效测量**非线性周期依赖性**。 +- **不同介质/阻尼条件:** 空气阻力是一个误差来源;为探讨此效应,我们可以改变阻尼环境。例如,一组试验在静止空气(常规条件)下进行,另一组则在增加空气阻力的条件下进行(例如在摆锤上附加纸板翼,或使用表面积更大的单摆)。在极端情况下,如资源允许,我们甚至可在水或油等流体中摆动单摆,以观察强阻尼——尽管在流体中测量 $g$ 因浮力影响较大,但主要目的是展示阻力效应。或者,通过改变摆锤的尺寸/密度,可以调节空气阻力系数 ([arxiv.org](https://arxiv.org/pdf/2002.03796#:~:text=point%20of%20motion%20and%20increase,for%20a%20small%20Reynolds%20number))。每种介质或阻尼条件都能提供振幅衰减速率的数据,从而得出阻尼系数。通过在这些不同条件下采集数据,我们确保所测得的 $g$ 不是在某一单一条件下偶然准确——可以展示各条件下结果的一致性,或在出现差异时进行交叉验证。 + +所有视频均将通过我们的CV算法处理以提取时间序列数据。初步而言,我们可能会对每次试验记录进行长时间的记录。原始数据(时间、角度或位置)将保存到磁盘以供后续分析。我们还将实现基本的实时分析:在数据采集过程中,程序可显示检测到的位置,甚至实时绘制角度随时间变化的图像。这种即时反馈有助于验证追踪是否正常工作(例如,周期图应呈正弦波形)。每次试验结束后,还将计算平均周期、振幅衰减率等重要参数。重复测量并取平均能提高可靠性——例如,对于每个摆长或振幅,我们可能进行三次试验,随后用统计方法综合结果。 + +## 3. 系统误差分析与校正 + +
此部分仅为思路阐述,所述公式有待严谨论证,仅供参考
+ +本项目的核心目标是**识别并消除单摆实验中的系统误差**。主要系统误差来源包括空气阻力、大角度效应以及测量不准确性。我们将依次解决这些问题: + +- **空气阻力(阻尼):** 空气阻力会使单摆的振幅随时间逐渐减小。对于小阻尼而言,每个摆动周期内的影响较小,但若在一系列振幅范围内测量周期(如多次计时),则可能引入偏差。具体来说,随着单摆速度减慢,所测得的平均周期可能与初始周期不同。在我们的初步测试和文献中,空气阻力曾被认为是导致测得的 $g$ 略高的原因——某研究中测得的 $g$ 比公认值高约2%,其原因归因于阻尼效应及校准问题([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=acceptable%20value%20in%20the%20country,the%20calibration%20stick%20should%20be))。我们将通过对振幅衰减进行指数拟合来量化阻尼。阻尼系数 $b$(或品质因数 $Q$)能帮助估计周期的改变。具体做法:记录每个周期**摆球的最大偏角(振幅)**随时间的衰减曲线,根据指数衰减模型$A(t)=A_0e^{-\lambda t}$拟合出衰减常数$\lambda$,进而求得阻尼系数$b$(若阻力近似与速度成正比,则$\lambda=\frac{b}{2m}$)。例如,通过测量振幅减半所需时间$T_{1/2}$,可计算$\lambda=\ln2/T_{1/2}$,从而$b=2m\lambda$。有研究通过测定单摆半衰期344.1s,计算得到阻尼系数约0.0029(无量纲,相当于阻力系数) ([2017年物理实验竞赛获奖作品简介-周期力驱动下弹簧摆的行为-北京邮电大学物理实验教学中心](https://physlab.bupt.edu.cn/info/1311/1867.htm#:~:text=%E9%80%9A%E8%BF%87%E6%B5%8B%E9%87%8F%E5%8D%8A%E8%A1%B0%E6%9C%9F%E4%B8%BA%20344))。 + +- **有限振幅(大角度)误差:** 标准单摆公式 + $$ + T = 2\pi\sqrt{L/g} + $$ + 假设 $\sin\theta \approx \theta$(小角近似)。对于较大释放角,实际周期会比预测值更长。这是一个众所周知的系统误差来源:当 $\theta_0 = 45^\circ$ 时,周期约比小角公式长4%,若直接使用小角公式计算 $g$,会导致约8%的误差 ([Pendulum experiment systematic errors](https://www.physicsforums.com/threads/pendulum-experiment-systematic-errors.889342/#:~:text=14%252C139))。文献中通过改变单摆振幅发现:随着振幅增大,单摆**固有频率减小**(即周期变长) ([2017年物理实验竞赛获奖作品简介-周期力驱动下弹簧摆的行为-北京邮电大学物理实验教学中心](https://physlab.bupt.edu.cn/info/1311/1867.htm#:~:text=%E5%9B%BE%E5%85%AD%20%E5%8D%95%E6%91%86%E5%9C%A8%E7%9F%AD%E7%BB%B3%EF%BC%8850cm%EF%BC%89%E5%8F%97%E4%B8%8D%E5%90%8C%E5%91%A8%E6%9C%9F%E6%80%A7%E9%A9%B1%E5%8A%A8%E5%8A%9B%E7%9A%84%E5%B9%85%E9%A2%91%E7%89%B9%E6%80%A7%E6%9B%B2%E7%BA%BF)) ([2017年物理实验竞赛获奖作品简介-周期力驱动下弹簧摆的行为-北京邮电大学物理实验教学中心](https://physlab.bupt.edu.cn/info/1311/1867.htm#:~:text=%E7%94%B1%E4%B8%8A%E5%9B%BE%E5%8F%AF%E7%9F%A5%EF%BC%8C%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E5%AD%94%E8%B7%9D%E5%A4%A7%E5%B0%8F%E6%97%B6%EF%BC%8C%E5%8D%95%E6%91%86%E7%9A%84%E5%85%B1%E6%8C%AF%E9%A2%91%E7%8E%87%E4%B9%9F%E5%B0%86%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%EF%BC%8C%E5%8D%B3%E5%8D%95%E6%91%86%E7%9A%84%E5%9B%BA%E6%9C%89%E9%A2%91%E7%8E%87%E5%8F%91%E7%94%9F%E6%94%B9%E5%8F%98%E3%80%82%E4%B8%94%E9%9A%8F%E7%9D%80%E5%8D%95%E6%91%86%E6%8C%AF%E5%B9%85%E7%9A%84%E5%A2%9E%E5%A4%A7%EF%BC%8C%E5%8D%95%E6%91%86%E7%9A%84%E5%9B%BA%E6%9C%89%E9%A2%91%E7%8E%87%E5%87%8F%E5%B0%8F%E3%80%82%E4%B8%BA%E9%AA%8C%E8%AF%81%E8%BF%99%E4%B8%80%E7%BB%93%E8%AE%BA%EF%BC%8C%E6%88%91%E4%BB%AC%E6%94%B9%E5%8F%98%E4%BA%86%E6%91%86%E9%95%BF%E7%9A%84%20%E5%A4%A7%E5%B0%8F%EF%BC%8C%E7%BB%98%E5%87%BA%E4%B8%8D%E5%90%8C%E6%91%86%E9%95%BF%E5%8D%95%E6%91%86%E5%9B%BA%E6%9C%89%E9%A2%91%E7%8E%87%E9%9A%8F%E6%8C%AF%E5%B9%85%E7%9A%84%E5%8F%98%E5%8C%96%E6%9B%B2%E7%BA%BF%E5%A6%82%E4%B8%8B%E3%80%82))。我们的数据同样可验证这一规律,并用于修正g的计算——例如,如果初始振幅$\theta_0$不是极小,可据此公式在计算g时加上一项修正,以消除大振幅带来的系统误差。我们计划**测量并校正**大角度效应,而非仅限于微小角度。利用不同 $\theta_0$ 下的数据,我们可以观察周期与振幅之间的趋势。我们将把测量结果与理论展开式比较: + + $$ + T(\theta_0) \approx 2\pi\sqrt{L/g},\Big(1 + \frac{\theta_0^2}{16} + \frac{11,\theta_0^4}{3072} + \cdots \Big) + $$ + (其中 $\theta_0$ 以弧度计)([Pendulum experiment systematic errors](https://www.physicsforums.com/threads/pendulum-experiment-systematic-errors.889342/#:~:text=14%252C139))。对于中等角度(最高约30°或0.52 rad),第一修正项 $\frac{\theta_0^2}{16}$ 已足以估计 $T$ 的增加。我们将采用该公式校正测得周期:给定初始振幅后,可除去因子 $1 + \frac{\theta_0^2}{16} + \dots$ + + 得到相当于小角情况下的周期。或者,也可以采用经验方法,将每次试验计算出的*表观* $g$ 值与 $\theta_0^2$ 作图。我们预期若不进行校正,对于较大 $\theta_0$,$g_{\text{meas}}$ 会系统性偏低。通过将图外推至 $\theta_0=0$,便能得到真实 $g$ ([Pendulum experiment systematic errors](https://www.physicsforums.com/threads/pendulum-experiment-systematic-errors.889342/#:~:text=14%252C139))。这同时也作为对理论校正的交叉验证。实际上,我们可能会在对 $g$ 取平均前,对每个测得周期应用理论修正项。主要试验中,我们亦会保持振幅较小(约10°–15°),以使该误差初步较小,再通过少量大角度试验单独验证校正方法。如此,最终测得的 $g$ 就相当于在 $\theta_0 \to 0$ 时的结果(无非线性误差)。 + +- **单摆长度测量误差:** 单摆的长度 $L$(从支点到摆锤质心的距离)直接参与 $g$ 的计算。$L$ 的系统误差会线性传递到 $g$ 上。例如,若长度低估1%,计算出的 $g$ 将高估1%。常见问题包括测量错误(例如测量到摆锤底部而非其质心)或精确测量支点的难度(尤其当绳子绕在支撑物上时)。在类似实验的论坛讨论中,有学生测量到摆锤顶部,导致 $L$ 过短,从而预测的周期低于实际,结果观测周期长于预期 ([Pendulum experiment systematic errors](https://www.physicsforums.com/threads/pendulum-experiment-systematic-errors.889342/#:~:text=,))。我们将通过使用米尺或卷尺**以毫米精度**从悬挂点测量至摆锤中心来避免此问题,如果可以,也许可以直接尝试从图像中识别得到单摆长度。如果摆锤尺寸较大,我们会将其半径考虑在内以确定质心。另一个细节是,实际单摆并非质点挂于无质量绳上:摆锤有限的半径和质量分布实际上会使周期略增(摆锤表现得像物理摆)。这可被建模为比绳长略长的**有效长度**。对于半径为 $R$ 的球形摆锤,由于转动惯量,周期表现得仿佛单摆长度为 + $$ + L_{\text{eff}} = L + \frac{2R^2}{5L} + $$ + (当 $R$ 较小时)。我们可以计算此修正项,或保持 $R$ 足够小以忽略其影响。在误差分析中,我们会将 $L$ 的不确定度传递到 $g$ 上。我们预计 $L$ 的测量误差在 ±1 mm 以内。对于约1 m的单摆,这是 ±0.1% 的不确定度。虽然这一误差较小,但我们仍将通过采用多个不同摆长并进行线性拟合来进一步减小长度误差:若存在一致性偏差(例如所有长度均略短),则 $T^2$ 与 $L$ 的直线可能在非零处截距。我们可检测并调整这一偏差。事实上,绘制 $T^2$ 与 $L$ 的图表可以作为诊断——截距不为零提示存在系统性长度偏移或计时偏差 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=In%20Figure%205%252C%20the%20data,positive%20slope%20can%20be%20observed))。我们会报告拟合得到的截距;若显著,则相应修正 $L$ 值,使直线通过原点(物理上,零长度应对应零周期)。此外,视频刻度的正确校准也很关键:若依赖视频像素测量振幅(或验证长度),刻度(像素/米)的任何误差等同于长度误差。追踪软件对校准对齐**“超敏感”**——有研究警告,若用于校准的米尺未精确放置在运动平面上,视差会引入误差 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=acceptable%20value%20in%20the%20country,the%20calibration%20stick%20should%20be))。为此,我们将仔细校准(将校准物置于单摆平面旁边)并进行校准检查(例如,在视频中测量已知距离并确认其匹配)。 + +- **计时与数据分辨率:** 虽然采用高帧率视频大大降低了随机计时不确定性,但我们必须确保时间基准本身无系统误差。使用相机所给定的帧率(60 fps意味着每帧 $\Delta t = 0.01667$ s)通常是准确的,可能误差是**起停计时偏差**——例如,若通过标记峰值间的时间来测量周期,可能因帧间插值方式而产生半帧的偏差。我们将通过对连续的位移-时间数据拟合正弦函数,而非仅计数峰间离散帧数,从而将此偏差降至最低。拟合方法能以亚帧精度提取频率(进而得到周期)。类似地,在求阻尼常数时,我们将对所有峰值进行指数拟合,而不依赖单独一对振幅。这些技术利用完整数据集,减少单点误差的影响。 + +为**估计并验证我们的误差范围**,我们将采用统计方法: + +- **不确定度传递:** 利用公式 $g = 4\pi^2 L / T^2$ $g$ 的相对不确定度可由 $L$ 与 $T$ 的不确定度传递得出。用微分形式表示为 $\frac{\Delta g}{g} \approx \frac{\Delta L}{L} + 2,\frac{\Delta T}{T}$ 例如,若 $L$ 的不确定度为0.1%,$T$ 的不确定度为0.2%(通过多次计时可实现),则 $\Delta g/g \approx 0.5%$。我们将对每次试验进行此类估算。利用多个摆动周期计时(或拟合)会使 $\Delta T/T$ 非常小——实际上计时不确定度大约为相机帧周期除以总测量时间。例如,在10个周期(每个周期约2秒)的情况下使用60 fps视频,其计时精度大约为 $1/(60 \times 10 \times 2) \approx 0.08\%.$ 我们的目标是累计不确定度远低于1%。 +- **方差分析 (ANOVA):** 在获得多个 $g$ 值(来自不同摆长、角度等)后,我们可进行方差分析,以检验这些值是否一致于同一真实值,或其变化是否超出随机误差所能解释的范围。例如,若长摆与短摆测得的 $g$ 显著不同,则可能存在系统性误差(例如短摆的长度测量偏差)。我们的实验设计(一次改变一个因素)使我们能够确定是哪一因素导致了偏移。ANOVA 可检验所有测得的 $g$ 是否来自同一分布这一原假设。我们还将计算最终综合 $g$ 的**置信区间**。例如,对于 $N$ 次试验,我们可以得出均值和标准差;并报告95%置信区间以说明测量可靠性。 + +总之,本节旨在**确保万无一失**。通过量化每个潜在误差来源并采取针对性修正(理论校正和实验交叉验证),我们旨在**消除系统性偏差**。每个被识别出的误差(空气阻力、振幅、长度)在分析中均有相应的校正或不确定度分配。最终结果将是一个在实验条件下我们可以信赖的高精度 $g$ 测量值。 + +## 4. $g$ 测量的数学建模与优化 + +我们将建立一个详细的单摆数学模型,将上述校正因素纳入其中,并利用数据优化 $g$ 的测定。建模和分析步骤包括: + +**修正周期公式的推导:** 从单摆的运动方程出发,我们考虑到与理想简谐运动相比存在两种偏差:(1)有限振幅,(2)阻尼。对于振幅,周期 $T$ 可通过椭圆积分表示。对于小振幅展开后,可得 +$$ +T = 2\pi\sqrt{\frac{L}{g}} \Big(1 + \frac{\theta_0^2}{16} + \frac{11\,\theta_0^4}{3072} + \cdots \Big), +$$ + + + +当存在阻尼时,单摆运动的方程变为 +$$ +\ddot{\theta} + \frac{b}{m}\dot{\theta} + \frac{g}{L}\sin\theta = 0, +$$ +其中: + +- **\(b\)** 是线性阻力系数,描述阻尼力(如空气阻力)对运动的影响。 +- **\(m\)** 是摆锤的质量。 + +在小角和弱阻尼的近似条件下,上式的解可近似写为 +$$ +\theta(t) \approx \theta_0 e^{-bt/(2m)}\cos(\omega_d t), +$$ +其中 **$ omega_d $** 是阻尼单摆的实际角频率,其表达式为 +$$ +\omega_d = \sqrt{\frac{g}{L} - \frac{b^2}{4m^2}}. +$$ + +对该表达式进行小参数展开,可以得到 +$$ +\omega_d \approx \sqrt{\frac{g}{L}}\left(1 - \frac{b^2L}{8m^2g}\right). +$$ + +从而,阻尼条件下的周期近似为 +$$ +T_d \approx 2\pi\sqrt{\frac{L}{g}}\left(1 + \frac{b^2L}{8m^2g}\right). +$$ + +用品质因数\(Q\)表示阻尼效应 + +- 为了方便实验中对阻尼大小的表征,引入品质因数 + $$ + Q = \frac{m\omega_0}{b}, + $$ + 其中 \(\omega_0 = \sqrt{\frac{g}{L}}\) 为无阻尼时的角频率。 +- 经过代换,上式可以写成 + $$ + T_d \approx T_0\left(1 + \frac{1}{2Q^2}\right). + $$ + +综合有限振幅和阻尼的修正 + +- 当同时存在大振幅效应和阻尼效应时,周期的一阶修正近似为 + $$ + T \approx 2\pi\sqrt{\frac{L}{g}}\left[1 + \frac{\theta_0^2}{16} + \frac{1}{2Q^2}\right]. + $$ +- 在实验数据处理中,可以用一个修正因子 + $$ + F(\theta_0, Q) = 1 + \frac{\theta_0^2}{16} + \frac{1}{2Q^2} + $$ + 来校正测得的周期,即 + $$ + T_{\text{corrected}} = \frac{T_{\text{meas}}}{F(\theta_0, Q)}. + $$ + +通过以上推导,可以看出单摆的实际周期不仅受到摆长和重力的影响,还会因为较大的振幅和阻尼效应而发生修正。实验中通过测量振幅衰减,可以估计出 \(Q\) 值,进而用来校正周期测量数据。 + +利用数据,我们将为每次试验确定 $F$(在非理想情况下,$F$ 通常接近1,例如约1.02)。如此便得一组修正后的周期,仿佛在零振幅和零阻尼下测量的一般。 + +**回归与曲线拟合:** 针对多个数据集,我们有多种途径提取 $g$ 的最佳估计。一种稳健方法是采用 **$T^2$ 与 $L$ 的线性回归**。对于每个摆长,我们将得到一个平均周期(必要时已校正振幅和阻尼)。根据理想公式, +$$ +T^2 = \frac{4\pi^2}{g} L. +$$ + +我们将绘制 $T^2$(纵轴)与 $L$(横轴)的关系图。若校正成功,数据点应近似排列成一条直线。我们将执行线性最小二乘拟合。该直线的斜率 $m$ 与 $g$ 之间满足 + +$$ +m = \frac{4\pi^2}{g}, +$$ + +从而有 + +$$ +g = \frac{4\pi^2}{m}. +$$ + +我们将从回归中获得 $m$ 及其不确定度;这直接给出 $g$ 及其不确定度 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=In%20Figure%205%252C%20the%20data,positive%20slope%20can%20be%20observed)) ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=experiment%20has%20taken%20the%20correct,The%20g%20was%201003%20cm%252Fs2))。任何拟合截距(理想情况下为零)将被解释为前述(长度偏差或计时偏差),若统计上显著,则可通过调整偏差并重新拟合来修正数据。该回归方法同时利用所有长度数据,有效平均掉多次测量中的计时误差,并且对任何单个数据点不太敏感。这是利用单摆测 $g$ 的标准技术,我们预期会呈现出明显的线性趋势(过去学生实验显示,精心处理时,$L$ 与 $T^2$ 图呈良好直线 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=In%20Figure%205%252C%20the%20data,positive%20slope%20can%20be%20observed)))。 + +对于振幅效应,我们将采用另一种拟合方法:将*测得的* $T^2$(或每次试验计算得到的 $g$ 值)作为 $\theta_0^2$ 的函数作图。利用前述级数展开,我们预期一阶近似存在线性关系: + +$$ +T^2 = \frac{4\pi^2 L}{g}\Big(1 + \frac{\theta_0^2}{16} \Big)^2 \approx \frac{4\pi^2 L}{g}\Big(1 + \frac{\theta_0^2}{8}\Big) +$$ + +(舍去二阶小项)。这意味着单次试验中计算得到的 $g$ 为 + +$$ +g_{\text{calc}}(\theta_0) \approx \frac{g_{\text{true}}}{1 + \frac{\theta_0^2}{8}}. +$$ + +对于小角,即有 + +$$ +g_{\text{calc}} \approx g_{\text{true}}\left(1 - \frac{\theta_0^2}{8}\right). +$$ + +因此,若将 $g_{\text{calc}}$ 对 $\theta_0^2$ 作图,预期会有一个向下的斜率。我们将对结果拟合一条直线;当 $\theta_0^2=0$ 时的截距将是对 $g_{\text{true}}$ 的最佳估计。这将作为对所应用理论校正的一致性检验。如果拟合直线与理论匹配(对于小角,斜率大约为 $-g_{\text{true}}/8$),则验证了我们的理解;否则,可能暗示存在高阶项或其他因素(例如振幅引起的微小阻尼差异)。无论如何,此回归提供了另一种求取 $g$ 的途径。 + +对于阻尼,我们也可进行类似分析。若在不同阻尼条件下测得 $g$(例如常规空气与附加翼片),结果的任何差异可能与测得的阻尼率有关。我们可将 $g_{\text{calc}}$ 与阻尼系数 $b$ 或 $1/Q^2$ 作图,观察是否存在趋势(理想情况下,在校正后不应存在;若有,则需调整)。若数据量足够,还可尝试**多变量回归**,将所有 $T(L,\theta_0, b)$ 数据点拟合至模型 + +$$ +T^2 = \frac{4\pi^2}{g_{\text{true}}} L \left[1 + a\,\theta_0^2 + c\,(b)\right], +$$ +其中 $a, c$ 为捕捉残余振幅与阻尼影响的拟合参数。然而,鉴于我们的主要目标,较简单的一维拟合(分别针对 $L$ 和 $\theta_0^2$)可能已足够且更便于展示。 + +经过上述所有校正和拟合后,我们将得到一个尽可能无系统误差的最终 $g$ 值。该值将通过 $T^2$ 与 $L$ 的斜率获得(利用大量数据点且极为可靠),*在对每个 $T$ 进行振幅和阻尼校正之后*。我们还将从线性回归中得到该值的不确定度。我们预期统计不确定度将非常小(可能在0.1%或更低),故剩余误差将主要由残余系统误差主导(我们已尽力将其最小化)。若一切顺利,测得的 $g$ 应与本地区公认值(约9.80 m/s²)在极小范围内吻合。文献显示,通过精心校正或高级追踪方法,误差可达到0.2%或更好 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=match%20at%20L400%20percent%20error,track%20the%20simple%20pendulum%27s%20movement))。我们的目标是将误差控制在0.5%以下——这比典型课堂结果有显著改进,并与更复杂的方法相当。 + +**方法比较与建议:** 在讨论部分,我们将把基于CV的单摆测量与其他测定 $g$ 的方法进行比较。单摆因其简单而广受欢迎,但也存在其他实验方法:自由落体实验(利用光闸或高速视频计时物体下落)、复摆或卡特摆,以及使用加速度计。历史上,卡特摆(一种可调重量的可逆摆)曾用于高精度测定 $g$,因其无需精确知道质心位置,从而有效抵消了长度测量误差。这种装置在19世纪实现了极高精度(精度可达数十ppm)。我们采用简单单摆加上现代追踪的方法,试图以不同方式达到这种高精度(通过计算机校正误差而非机械方式)。光闸计时是另一种方法:在单摆最低点放置光闸可以极为精确地计时每次摆动(微秒级分辨率),从而获得出色的周期测量 ([arxiv.org](https://arxiv.org/pdf/2002.03796#:~:text=In%20order%20to%20obtain%20the,automate%20measurement%20of%20the%20speed))。然而,仅用光闸无法同时测量振幅或阻尼;而我们的视觉方法则可一次性实现。另一种现代方法是将智能手机的加速度计或陀螺仪附于摆锤上(或使用如Phyphox的应用程序记录运动)。这些方法能测周期甚至检测角度,但传感器噪声和校准限制了其精度——通常仅凭手机传感器在无额外校正时测得 $g$ 的误差就有几百分点。相比之下,我们的相机方法利用了极高的光学分辨率(位移可达毫米级分数,时间可达毫秒级)。 + +我们将为重复本实验者推荐最佳实践:例如,采用较长的单摆(使周期更长,更易精确测量,同时减少反应时间或帧率引起的相对误差) ([Pendulum experiment systematic errors](https://www.physicsforums.com/threads/pendulum-experiment-systematic-errors.889342/#:~:text=The%20finite%20moment%20of%20inertia,and%20still%20with%20large%20fluctuations));保持振幅较小或对大角度应用校正;确保支点无摩擦且绳子不延展(以避免能量损失和周期漂移);以及进行多次试验以平均随机误差。我们还将指出,尽管理论上增加摆锤质量不会改变 $T$,但较重或密度较大的摆锤可减少空气阻力影响(提高 $Q$ 因数),有利于精度——因此,为追求高精度,采用金属球作为摆锤比轻质乒乓球更为理想 ([arxiv.org](https://arxiv.org/pdf/2002.03796#:~:text=point%20of%20motion%20and%20increase,for%20a%20small%20Reynolds%20number))。 + +最后,项目的优化结果将给出一个具有完整不确定度说明的 $g$ 值。例如,我们可能得出如下结论:*“使用优化后的单摆系统,我们测得 $g = 9.812 \pm 0.015~\text{m/s}^2$(95%置信水平),与标准值9.81 m/s²相差仅0.1%。所有系统误差(空气阻力、振幅、长度校准)均在实验不确定度范围内得到了校正。”* 达到如此精度展示了将传统物理实验与现代计算机视觉和数据分析相结合的强大威力。 + +## 5. 实验结果的可视化与分析 + +数据和结果的清晰可视化对于理解和展示均至关重要。我们将创建一个**实时可视化界面**及一系列综合图表用于最终分析: + +- **实时追踪显示:** 在实验过程中,我们计划设置一个程序窗口,显示实时视频流,并在视频中标记出单摆摆锤(例如在其上绘制圆圈或十字准线)。随着单摆摆动,追踪到的运动轨迹将在视频上显示(留下运动轨迹)。同时,角度与时间的图表也会实时更新,为单摆的运动提供即时视觉确认——例如,可以看到一条正弦波,其峰值逐渐衰减(表现出阻尼)。这种实时绘图使振荡和阻尼现象变得直观。虽然60 fps下实时绘图计算较密集,但我们可每隔几帧更新一次图表。界面还可能实时显示计算值(例如当前周期估计、当前振幅)。这一交互元素不仅对实验者有用,也非常适合项目展示(例如在竞赛中,评委可同时直观地看到单摆运动与数据)。 +- **单摆轨迹图:** 我们将生成摆锤运动轨迹图,可能为垂直位置与水平位置的二维图。由于单摆沿弧线运动,其轨迹基本上是一段圆弧。绘制几个周期的相空间图(或仅绘制 $x(t)$ 与 $y(t)$ 的参数图)可能不会提供额外信息,但可验证运动是否平面且振幅是否符合预期。如果仅追踪角度或单一坐标,可能会略过此图,但数据仍可用于说明(例如证明在小角下 $y$ 位移相对于 $x$ 极小)。 +- **角度(或位移)与时间图:** 这是主要图表,展示运动的振荡特性。对于每次试验,我们将绘制 $\theta(t)$ 或 $x(t)$ 随时间变化的曲线。我们预期得到正弦振荡,其包络呈指数衰减。从图中可直接测得周期(峰到峰距离)并观察阻尼。我们将把模型的最佳拟合曲线叠加于图上。例如,拟合函数 $\theta(t) = \theta_0 e^{-bt/(2m)}\cos(\omega_d t + \phi)$ 将绘制在数据点上。若拟合效果良好,则验证了数据质量,并可精确提取 $\omega_d$(进而得 $g$)和阻尼系数 $b$。报告中将附上示例图,可能详细展示某一次试验。Pacala *et al.* (2023) 的研究曾用Tracker软件生成类似阻尼振荡图 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=As%20observed%20from%20Figure%206,The%20maximum%20displacement%20in%20Figure))。我们将利用自己的数据生成类似图表,并在图中标注周期 $T$ 与1/e衰减时间(与 $b$ 相关)的关键特征以增强清晰性。 +- **指数振幅衰减(阻尼)图:** 为分析阻尼,我们将提取振荡极值(峰值或谷值),并将这些峰值振幅随时间绘图。在半对数图上,若衰减完全为指数型,则应呈一条直线。从直线斜率可得衰减常数 $b/(2m)$(或计算每半周期品质因数 $Q = \frac{\pi}{\Delta(\ln \theta)}$)。我们可能会包含一张 $\ln(\text{振幅})$ 对时间的图,并进行线性拟合;或直接在原始图上拟合包络线。在结果中,可能报告“测得阻尼常数 $b$ 为X,对应单摆在空气中的品质因数约为Y。”若进行增加空气阻力的第二次试验,则在同一图中会显示一条衰减更陡的直线以作比较,从而定量展示空气阻力的影响。 +- **周期与振幅图:** 利用单次试验中振幅自然衰减的数据,或多次试验中不同初始角的数据,我们可绘制测得周期作为 $\theta_0$ 的函数(或每次摆动周期与瞬时振幅的关系图)。这将显示周期随振幅略有上升的趋势,并可与理论曲线 $T(\theta_0)$ 对比,以验证匹配程度。虽然该效应较为微妙,属于次要可视化,但它强化了非线性校正的必要性。如果数据分辨率足够,我们甚至可能解析出:例如,在30°时,前几次摆动的周期比在5°时的周期长出几百分之一秒。将这些数据点绘制并附上误差条和理论曲线,将很好地证实实验与理论的一致性。 +- **$T^2$ 与 $L$ 的线性拟合:** 对于不同摆长,我们将绘制所有数据点的 $T^2$ 与 $L$ 图(如可辨别,附上误差条)。预期呈线性关系 ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=In%20Figure%205%252C%20the%20data,positive%20slope%20can%20be%20observed))。我们将添加最佳拟合直线,并在图中显示拟合方程。例如,可能得到 $T^2 = (0.0403~\text{s}^2/\text{cm})L + 0.002~\text{s}^2.$ 换算单位后,$0.0403~\text{s}^2/\text{cm}$相当于 $4.03~\text{s}^2/\text{m}$,对应于 $4\pi^2/g \approx 4.03$,从而得 $g \approx 9.78$ m/s²(假设情形)。在2023年的论文中,他们绘制了摆长与周期平方图,并得到斜率为25.431 cm/s²(以其单位计) ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=In%20Figure%205%252C%20the%20data,positive%20slope%20can%20be%20observed)) ([journal.walisongo.ac.id](https://journal.walisongo.ac.id/index.php/perj/article/view/16614/5300#:~:text=Figure%205%20The%20Gradient%20of,due%20to%20gravity%20can%20be)),换算后得到 $g \approx 9.83$ m/s²(接近实际值)。我们也将以类似方式从图中提取 $g$ 值。包含此图在报告中十分重要,因为它直观展示了线性依赖关系及数据质量(数据点围绕直线的散布反映了实验精度)。若数据点非常接近直线,则表明随机误差较低;若有轻微偏离或曲率,则可能提示存在残余系统误差(但预期校正后不会出现)。 +- **总结与比较:** 我们将汇总一张结果表,总结各种方法测得的 $g$ 值。例如,一列可标明“方法”(如单摆小角、单摆大角校正、回归拟合等),另一列标明“测得的 $g$”及“与标准值的偏差”。这将显示,在优化后,各方法均趋于一致值。若尝试了其他方法(如利用同一相机计时落体测量 $g$),也会将其纳入比较。此外,若有文献或教科书中的标准值(例如本地区9.806 m/s²),我们亦将其作为参考。可视化的目标在于证明我们确实达到了高精度——多个独立分析均在不确定度范围内一致指向同一 $g$ 值。 + +所有图表均将清晰标注并注明单位。报告中还会附上样例计算,如如何从斜率提取 $g$ 或如何计算不确定度。将可视化图与分析结果结合,使报告内容既全面又易于理解。**实时界面**的演示将在现场展示时成为亮点,而报告中的图表则允许对数据进行更深入的检视。通过展示运动轨迹及数据拟合,我们实际上**验证了每一步**:原始数据(角度与时间)符合阻尼简谐振荡模型,综合数据(周期与摆长)符合预期的线性规律,且校正后各条件下结果一致。这种内在一致性将通过图表清晰传达。 diff --git a/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-094543.png b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-094543.png new file mode 100644 index 0000000..d932576 Binary files /dev/null and b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-094543.png differ diff --git a/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095130.png b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095130.png new file mode 100644 index 0000000..d1ad87e Binary files /dev/null and b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095130.png differ diff --git a/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095326.png b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095326.png new file mode 100644 index 0000000..70b4804 Binary files /dev/null and b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095326.png differ diff --git a/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095805.png b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095805.png new file mode 100644 index 0000000..ae4828b Binary files /dev/null and b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.assets/QQ20250416-095805.png differ diff --git a/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.md b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.md new file mode 100644 index 0000000..adf96f3 --- /dev/null +++ b/src/blogs/如何判断市场估值是否过高:市盈率和股息率的解读与美股、港股实例分析.md @@ -0,0 +1,275 @@ +--- +title: 市场估值评估:市盈率与股息率视角下的美股与港股对比分析 +desc: 探讨如何利用关键估值指标,特别是市盈率(P/E Ratio)和股息率(Dividend Yield),来判断市场是否被高估。以美国(标准普尔500指数)和香港(恒生指数)股票市场的历史与当前数据为例进行分析。此外,还将简要介绍其他常用的市场估值指标,以全面评估市场估值水平。 +author: feie9454 +date: 2025-03-31 +tags: 投资 +--- + +# 市场估值评估:市盈率与股息率视角下的美股与港股对比分析 + +## 1. 引言:理解市场估值过高 + +市场估值过高是指某项资产或公司的市场价格超出其内在或基本价值的情况。当公司或资产的价格被抬高至超出其真实价值时,可能由多种因素导致,包括需求激增、盈利变化、利好消息或周期性波动等。识别高估市场对投资者至关重要,有助于避免潜在价格回调并做出明智的投资决策。 + +本报告将深入探讨如何利用关键估值指标,特别是市盈率(P/E Ratio)和股息率(Dividend Yield),来判断市场是否被高估。我们将以美国(标准普尔500指数)和香港(恒生指数)股票市场的历史与当前数据为例进行分析。此外,报告还将简要介绍其他常用的市场估值指标,以全面评估市场估值水平。 + +## 2. 市盈率:定义、计算与解读 + +### 定义与计算 + +市盈率是衡量公司股价与每股收益(EPS)关系的重要指标,计算公式为: + +**市盈率 = 每股股价 ÷ 每股收益** + +根据使用的每股收益数据,市盈率主要分为两种类型: + +- **追踪市盈率(Trailing P/E)**:使用过去12个月的实际收益计算,反映公司过去的盈利能力,提供较精确的估值(前提是公司报告的收益准确)。 +- **预测市盈率(Forward P/E)**:使用分析师对公司未来收益(通常是未来12个月)的估计计算,更具前瞻性,反映市场对公司未来盈利增长的预期,但因依赖分析师估计而更具投机性。 + +### 解读与应用 + +在市场估值分析中,市盈率的解读至关重要: + +- **高市盈率**:可能表明投资者对公司未来盈利增长抱有高期望,愿意为每单位收益支付更高价格,但也可能意味着股票被高估。 +- **低市盈率**:可能表明投资者对公司增长前景持怀疑态度,或者股票可能被低估。 + +仅凭市盈率的绝对值难以判断估值水平,关键在于进行比较。投资者应将公司的市盈率与其历史范围以及同行业公司的平均水平进行对比。一般而言,市场平均市盈率在20至25之间,但在不同行业间存在显著差异。当一家公司的市盈率远高于行业平均水平(如达到或超过50,尤其与市盈率等于或低于10的同行相比)时,通常被认为估值过高。 + +## 3. 历史市盈率分析:标准普尔500指数 + +标准普尔500指数的市盈率历史上经历了显著波动。从1971年1月至2017年6月,该指数的平均市盈率为19.4倍,中位数为17.7倍。历史上出现过几次市盈率远高于平均水平的时期: + +- 2009年金融危机期间,由于公司盈利大幅下降,市盈率一度飙升至120以上,创下历史新高。 +- 1999年互联网泡沫破裂前夕,市盈率达到34倍,并在市场见顶两年后接近47倍。 +- 2020年底,市盈率再次达到39.3倍的高点。 + +这些历史数据表明,极端市盈率往往与重大市场事件相吻合,暗示市盈率可能是衡量市场情绪和潜在转折点的重要指标。例如,互联网泡沫时期,投资者对科技股的过度乐观推高了市盈率。而在1973至1985年期间,由于经济不确定性和较高利率,标普500指数的市盈率则长期维持在10倍左右。这说明宏观经济因素,如经济衰退、技术繁荣和利率环境,对市盈率具有显著影响。 + +**表1:标准普尔500指数历史季度市盈率(近十年)** + +| 日期 | 数值 | 日期 | 数值 | 日期 | 数值 | +| -------------- | ----- | -------------- | ----- | -------------- | ----- | +| 2015年3月31日 | 20.84 | 2018年6月30日 | 22.19 | 2021年9月30日 | 24.56 | +| 2015年6月30日 | 21.74 | 2018年9月30日 | 22.35 | 2021年12月31日 | 24.09 | +| 2015年9月30日 | 21.18 | 2018年12月31日 | 18.94 | 2022年3月31日 | 22.89 | +| 2015年12月31日 | 23.62 | 2019年3月31日 | 21.09 | 2022年6月30日 | 19.69 | +| 2016年3月31日 | 23.83 | 2019年6月30日 | 21.75 | 2022年9月30日 | 19.17 | +| 2016年6月30日 | 24.15 | 2019年9月30日 | 22.40 | 2022年12月31日 | 22.23 | +| 2016年9月30日 | 24.34 | 2019年12月31日 | 23.16 | 2023年3月31日 | 23.46 | +| 2016年12月31日 | 23.68 | 2020年3月31日 | 22.22 | 2023年6月30日 | 24.59 | +| 2017年3月31日 | 23.56 | 2020年6月30日 | 31.24 | 2023年9月30日 | 23.27 | +| 2017年6月30日 | 23.30 | 2020年9月30日 | 34.24 | 2023年12月31日 | 24.79 | +| 2017年9月30日 | 23.53 | 2020年12月31日 | 39.90 | 2024年3月31日 | 27.45 | +| 2017年12月31日 | 24.33 | 2021年3月31日 | 30.99 | 2024年6月30日 | 27.87 | +| 2018年3月31日 | 22.88 | 2021年6月30日 | 27.07 | 2024年9月30日 | 28.77 | + +*数据来源:YCharts* + +## 4. 当前市盈率分析:标准普尔500指数 + +![QQ20250416-094543](./%E5%A6%82%E4%BD%95%E5%88%A4%E6%96%AD%E5%B8%82%E5%9C%BA%E4%BC%B0%E5%80%BC%E6%98%AF%E5%90%A6%E8%BF%87%E9%AB%98%EF%BC%9A%E5%B8%82%E7%9B%88%E7%8E%87%E5%92%8C%E8%82%A1%E6%81%AF%E7%8E%87%E7%9A%84%E8%A7%A3%E8%AF%BB%E4%B8%8E%E7%BE%8E%E8%82%A1%E3%80%81%E6%B8%AF%E8%82%A1%E5%AE%9E%E4%BE%8B%E5%88%86%E6%9E%90.assets/QQ20250416-094543.png) + +截至2024年第三季度末,标准普尔500指数的市盈率为28.77倍。另一份报告显示,截至2025年2月,该指数的追踪市盈率为27.9倍。当前市盈率显著高于多个历史基准: + +- 高于1971至2017年的历史平均值19.4倍 +- 高于自19世纪70年代以来的平均值约16.0倍 +- 高于五年平均值24.1倍 +- 高于十年平均值21.9倍 + +截至2026年第四季度,该指数的预测市盈率约为20.15倍。这些数据表明,标准普尔500指数目前的估值高于其历史平均水平,可能预示市场被高估或投资者对未来增长预期较高。 + +当前经济环境对市盈率有着潜在影响。据FactSet数据,2025年第一季度标普500指数的预期盈利增长率为7.3%,低于五年和十年的平均水平。自2024年12月31日以来,所有11个行业的每股收益预期均出现下调。未来12个月的预测市盈率为20.5倍,高于五年和十年的平均水平。 + +高盛预测,到2025年底,标普500指数目标点位为6200点,这意味着股价将上涨11%,2025年的每股收益将增长7%。Silvercrest Group指出,高估值需要持续的利好消息来支撑,使市场对任何经济疲软迹象都极为敏感。尽管预期盈利将增长,但预期下调和当前较高的市盈率表明,如果经济增长放缓或盈利未能达到预期,市场可能存在脆弱性。 + +## 5. 历史市盈率分析:恒生指数 + +恒生指数的市盈率历史数据可追溯至2000年4月至2025年3月。在此期间,该指数的市盈率经历了显著波动: + +- 2010年11月达到18.400的历史最高点 +- 2016年2月跌至7.450的历史最低点 + +与标准普尔500指数相比,恒生指数的历史市盈率通常处于较低区间,反映了两个市场不同的动态和增长预期。 + +分析历史市盈率的峰值和谷值及其与市场事件的相关性揭示了一些规律: + +- 2010年11月的峰值可能与全球金融危机后中国经济强劲增长有关 +- 2016年2月的低谷可能与当时对中国经济放缓和全球市场波动的担忧有关 + +这些情况表明,与标普500指数类似,恒生指数市盈率的重大波动很可能与影响该地区的重大经济和地缘政治事件相关。 + +**表2:恒生指数历史季度市盈率(近十年)** + +| 日期 | 数值 | 日期 | 数值 | 日期 | 数值 | +| -------------- | ----- | -------------- | ----- | -------------- | ----- | +| 2015年3月26日 | 12.94 | 2018年6月29日 | 12.30 | 2021年9月30日 | 13.37 | +| 2015年6月30日 | 13.36 | 2018年9月28日 | 11.19 | 2021年12月31日 | 12.88 | +| 2015年9月30日 | 11.74 | 2018年12月28日 | 9.38 | 2022年3月31日 | 11.81 | +| 2015年12月31日 | 10.43 | 2019年3月29日 | 10.79 | 2022年6月30日 | 9.84 | +| 2016年3月31日 | 8.60 | 2019年6月28日 | 10.43 | 2022年9月30日 | 8.55 | +| 2016年6月30日 | 9.58 | 2019年9月30日 | 9.98 | 2022年12月30日 | 9.45 | +| 2016年9月30日 | 10.82 | 2019年12月31日 | 10.42 | 2023年3月31日 | 10.80 | +| 2016年12月30日 | 11.80 | 2020年3月31日 | 9.56 | 2023年6月30日 | 10.30 | +| 2017年3月31日 | 13.18 | 2020年6月30日 | 11.58 | 2023年9月29日 | 9.96 | +| 2017年6月30日 | 13.58 | 2020年9月30日 | 13.54 | 2023年12月29日 | 9.29 | +| 2017年9月29日 | 14.41 | 2020年12月31日 | 14.70 | 2024年3月28日 | 9.81 | +| 2017年12月29日 | 14.18 | 2021年3月31日 | 15.27 | 2024年6月28日 | 9.99 | +| 2018年3月29日 | 13.64 | 2021年6月30日 | 14.76 | 2024年9月30日 | 10.98 | +| | | | | 2024年12月31日 | 10.04 | +| | | | | 2025年3月26日 | 11.95 | + +*数据来源:CEIC Data* + +## 6. 当前市盈率分析:恒生指数 + +![QQ20250416-095130](./%E5%A6%82%E4%BD%95%E5%88%A4%E6%96%AD%E5%B8%82%E5%9C%BA%E4%BC%B0%E5%80%BC%E6%98%AF%E5%90%A6%E8%BF%87%E9%AB%98%EF%BC%9A%E5%B8%82%E7%9B%88%E7%8E%87%E5%92%8C%E8%82%A1%E6%81%AF%E7%8E%87%E7%9A%84%E8%A7%A3%E8%AF%BB%E4%B8%8E%E7%BE%8E%E8%82%A1%E3%80%81%E6%B8%AF%E8%82%A1%E5%AE%9E%E4%BE%8B%E5%88%86%E6%9E%90.assets/QQ20250416-095130.png) + +截至2025年3月26日,恒生指数的每日市盈率为11.950倍。这低于其18.400的历史高点,但高于7.450的历史低点。截至2025年1月1日,该指数的追踪市盈率为10.04倍,预测市盈率为9.74倍。当前的市盈率表明,与历史峰值和当前的标普500指数市盈率相比,恒生指数的估值相对较低,这可能预示市场被低估,但也可能反映了对经济前景的担忧。 + +当前经济环境对香港和中国市场的市盈率有着重要影响。2023年恒生指数成分公司的盈利增长疲软,但在2024年显示出复苏迹象。尽管对中国人工智能领域持乐观态度,但分析师对2025年的预期仍然谨慎。2024年中国政府的刺激政策帮助振兴了中国内地和香港的经济活动,恒生指数在2025年第一季度上涨了15.25%。 + +对盈利增长的谨慎预期以及中国经济复苏的脆弱性可能导致恒生指数的市盈率低于标准普尔500指数,后者具有更强的盈利增长预期。中国经济面临的挑战,如喜忧参半的消费者支出和疲软的工厂活动,可能正在抑制投资者热情,导致恒生指数的估值倍数低于经历更强劲盈利增长的标普500指数。 + +## 7. 股息率:定义、计算与解读 + +### 定义与计算 + +股息率是公司年度股息支付额与其当前股价的比率,通常以百分比表示。计算公式为: + +**股息率(%)= (每股年度股息 ÷ 当前每股股价)× 100** + +每股年度股息可以是过去四个季度的股息总和,也可以是最近一个季度的股息乘以四。股息率衡量投资者通过股息获得的现金回报,使投资者能够比较不同股票或市场的收益潜力。 + +### 解读与应用 + +在市场估值分析中,股息率的解读也至关重要: + +- **高股息率**:可能表明股票被低估,或者公司是一家成熟的、增长缓慢但将利润返还给股东的公司。然而,异常高的股息率(特别是由股价下跌导致)可能预示公司面临财务困境。 +- **低股息率**:可能表明公司正将盈利再投资以促进增长,而非支付股息,或者可能意味着股票被高估。 + +解读股息率的关键在于将其与公司或市场的历史平均水平以及同行业公司的平均股息率进行比较。不同行业的平均股息率差异很大,因此对股息率的解读需要考虑具体情况和高低股息率背后的潜在原因。 + +高股息率并非总是积极信号,它可能是一个警示,表明因基本面问题导致股价下跌。同样,低股息率并不一定意味着糟糕的投资,尤其对注重增长的公司而言。理解股息率背后的原因至关重要。 + +## 8. 历史股息率分析:标准普尔500指数 + +从历史上看,自19世纪以来,标准普尔500指数低于3%的年股息率一直是不正常的: + +- 1871-1960年间,年股息率从未低于3%,其中46年甚至超过5% +- 1970-1990年,平均股息率为4.21% +- 1991-2007年,平均股息率下降至1.95% +- 2008年大衰退期间短暂上升至约3.15% +- 2009-2019年,年平均股息率仅为1.98% +- 自2020年以来,股息率一直低于2%,范围在1.24%至1.78%之间 + +长期趋势表明,标普500指数的股息率呈下降趋势,反映了近年来市场对成长股的关注及较低的派息率。早期20世纪较高的股息率可能反映了当时市场由更多成熟的、派息公司主导。20世纪90年代和2000年代的下降可能归因于注重再投资而非股息的成长型科技公司兴起。2008年经济衰退期间的略微上升可能是由于股价下跌而非股息支付增加所致。 + +经济状况和市场构成(如不同行业的崛起)的变化显著影响了标普500指数的股息率。 + +**表3:标准普尔500指数历史季度股息率(近十年)** + +| 日期 | 数值 (%) | 日期 | 数值 (%) | 日期 | 数值 (%) | +| -------------- | -------- | -------------- | -------- | -------------- | -------- | +| 2015年3月31日 | 1.87 | 2018年6月30日 | 1.98 | 2021年9月30日 | 1.32 | +| 2015年6月30日 | 1.87 | 2018年9月30日 | 1.83 | 2021年12月31日 | 1.27 | +| 2015年9月30日 | 2.03 | 2018年12月31日 | 2.03 | 2022年3月31日 | 1.34 | +| 2015年12月31日 | 2.17 | 2019年3月31日 | 1.97 | 2022年6月30日 | 1.54 | +| 2016年3月31日 | 2.22 | 2019年6月30日 | 1.89 | 2022年9月30日 | 1.67 | +| 2016年6月30日 | 2.12 | 2019年9月30日 | 1.89 | 2022年12月31日 | 1.68 | +| 2016年9月30日 | 2.08 | 2019年12月31日 | 1.83 | 2023年3月31日 | 1.63 | +| 2016年12月31日 | 2.04 | 2020年3月31日 | 2.06 | 2023年6月30日 | 1.57 | +| 2017年3月31日 | 1.96 | 2020年6月30日 | 1.93 | 2023年9月30日 | 1.57 | +| 2017年6月30日 | 1.94 | 2020年9月30日 | 1.73 | 2023年12月31日 | 1.54 | +| 2017年9月30日 | 1.90 | 2020年12月31日 | 1.57 | 2024年3月31日 | 1.47 | +| 2017年12月31日 | 1.84 | 2021年3月31日 | 1.54 | 2024年6月30日 | 1.38 | +| 2018年3月31日 | 1.89 | 2021年6月30日 | 1.44 | 2024年9月30日 | 1.27 | +| | | | | 2024年12月31日 | 1.27 | + +*数据来源:YCharts* + +## 9. 当前股息率分析:标准普尔500指数 + +截至2025年3月,标准普尔500指数的股息率约为1.27%。这远低于历史平均水平约2.91%,也低于2009-2019年的平均水平(1.98%)以及1990年之前的平均水平(超过4%)。当前的股息率处于历史低位,进一步表明美国市场目前更侧重于增长而非产生收入。 + +![QQ20250416-095326](./%E5%A6%82%E4%BD%95%E5%88%A4%E6%96%AD%E5%B8%82%E5%9C%BA%E4%BC%B0%E5%80%BC%E6%98%AF%E5%90%A6%E8%BF%87%E9%AB%98%EF%BC%9A%E5%B8%82%E7%9B%88%E7%8E%87%E5%92%8C%E8%82%A1%E6%81%AF%E7%8E%87%E7%9A%84%E8%A7%A3%E8%AF%BB%E4%B8%8E%E7%BE%8E%E8%82%A1%E3%80%81%E6%B8%AF%E8%82%A1%E5%AE%9E%E4%BE%8B%E5%88%86%E6%9E%90.assets/QQ20250416-095326.png) + +## 10. 历史股息率分析:恒生指数 + +虽然资料中没有提供恒生指数历史平均股息率的详细数据,但iShares核心恒生指数ETF (3115.HK)的股息历史显示了多年的波动。该ETF的股息率在2017-2024年间约为1.78%至3.66%。虽然无法获得长期历史平均值,但ETF的数据表明,恒生指数的股息率通常高于标普500指数近期的水平。 + +该ETF的股息率有所波动,2021年有所下降,2024年有所上升。这些波动可能反映了成分公司股息政策的变化以及ETF的市场价格。恒生指数(以ETF为代表)的股息率非静态,会随着经济环境和公司业绩的变化而变化。 + +**表4:恒生指数历史年度股息率(近十年 - 以ETF数据为代表)** + +| 年份 | 股息率 (%) | +| ---- | ---------- | +| 2017 | 3.66 | +| 2018 | 3.39 | +| 2019 | 3.28 | +| 2020 | 2.53 | +| 2021 | 1.78 | +| 2022 | 1.92 | +| 2023 | 1.97 | +| 2024 | 2.70 | + +## 11. 当前股息率分析:恒生指数 + +![QQ20250416-095805](./%E5%A6%82%E4%BD%95%E5%88%A4%E6%96%AD%E5%B8%82%E5%9C%BA%E4%BC%B0%E5%80%BC%E6%98%AF%E5%90%A6%E8%BF%87%E9%AB%98%EF%BC%9A%E5%B8%82%E7%9B%88%E7%8E%87%E5%92%8C%E8%82%A1%E6%81%AF%E7%8E%87%E7%9A%84%E8%A7%A3%E8%AF%BB%E4%B8%8E%E7%BE%8E%E8%82%A1%E3%80%81%E6%B8%AF%E8%82%A1%E5%AE%9E%E4%BE%8B%E5%88%86%E6%9E%90.assets/QQ20250416-095805.png) + +恒生市场目前的股息率高于美国市场,这可能使其对寻求收入的投资者更具吸引力。 + +## 12. 其他市场估值指标 + +除了市盈率和股息率,以下市场估值指标也有助于投资者判断市场是否被高估: + +### 市净率(Price-to-Book Ratio, P/B Ratio) + +市净率将公司的市值与其账面价值(总资产减去总负债)进行比较: + +**市净率 = 每股股价 ÷ 每股账面价值** + +- 低市净率可能表明股票被低估 +- 高市净率可能表明股票被高估 +- 特别适用于评估拥有大量有形资产的公司(如银行、制造业) +- 价值投资者通常认为低于1.0的市净率是理想的 +- 提供基于公司净资产价值的估值视角,与侧重于盈利的市盈率形成对比 + +### 托宾Q比率(Tobin's Q Ratio) + +托宾Q比率衡量公司的市场价值与其资产重置成本之间的关系: + +**托宾Q比率 = 公司股权市值 ÷ 公司股权账面价值** + +- 大于1的Q比率表明估值过高 +- 小于1的Q比率意味着估值过低 +- 对整个市场而言,可以表明总体市场是被高估还是低估 +- 试图衡量资产的市场价值是否与其内在重置成本相符,提供更宏观的估值视角 + +## 13. 比较分析:标准普尔500指数与恒生指数估值 + +标准普尔500指数当前的市盈率(约28倍)显著高于恒生指数的市盈率(约12倍)。同时,标普500指数当前的股息率(约1.27%)显著低于恒生指数的股息率(基于ETF代理约为3.18%)。这表明,与香港市场相比,美国市场目前的盈利估值更高,股息收益率更低。 + +这种估值差异的潜在原因包括: + +1. **增长预期差异**:美国市场更强的盈利增长预期,尤其在科技领域 +2. **投资者信心**:投资者对美国经济的更高信心 +3. **风险溢价**:恒生指数较低的市盈率和较高的股息率可能反映了因中国经济挑战而导致的谨慎盈利前景,以及投资者可能要求的更高风险溢价 +4. **行业构成差异**:恒生指数中金融行业权重较高,而标普500指数中科技行业权重较高,可能导致估值差距 + +因此,估值差异源于宏观经济因素、盈利增长前景、行业构成以及特定于每个市场的投资者情绪的综合作用。 + +## 14. 结论与投资者考量 + +综上所述,标准普尔500指数目前的市盈率处于历史高位,股息率处于低位,这可能暗示市场存在高估风险或对未来增长抱有很高预期。相比之下,恒生指数的市盈率相对较低,股息率较高,这可能表明市场被低估,但也可能反映了对经济前景的担忧。 + +### 关键投资考量 + +1. **多指标评估**:在评估市场估值是否过高时,考虑多种估值指标和更广泛的经济环境至关重要。仅依赖市盈率或股息率是不够的。 +2. **美国市场策略**:在像美国这样潜在估值过高的市场中,投资者可能需要更加谨慎地选择股票,重点关注基本面强劲且具有可持续增长的公司。多元化和风险管理变得尤为重要。 +3. **香港市场机会**:香港市场较低的估值可能为长期投资者提供机会,但仔细评估中国潜在的经济风险和增长前景至关重要。 +4. **比较视角**:投资者应始终将估值指标与历史平均水平和行业同行进行比较,而非依赖绝对阈值。 +5. **深入理解**:理解追踪市盈率和预测市盈率之间的差异以及盈利预测背后的假设对于做出明智决策至关重要。 +6. **收益考量**:股息率可能是总回报的重要组成部分,但其可持续性应仔细评估。 + +通过全面评估这些因素,投资者可以更好地理解当前市场估值状况,并据此调整其投资策略,以应对潜在的市场风险和把握投资机会。 \ No newline at end of file diff --git a/src/blogs/对高中阶段研学与通技课程的一些思考.md b/src/blogs/对高中阶段研学与通技课程的一些思考.md new file mode 100644 index 0000000..a9dc85e --- /dev/null +++ b/src/blogs/对高中阶段研学与通技课程的一些思考.md @@ -0,0 +1,72 @@ +--- +title: 对高中阶段研学与通技课程的一些思考 +desc: +author: feie9454 +date: 2025-04-18 +tags: 计算机、物理、竞赛 +hide: true +--- + +# 对高中阶段研学与通技课程的一些思考 + +尊敬的刘老师: + +您好!很高兴收到您的消息,我当时就对老师您很是崇拜,经常大课间或者晚自习带着乱七八糟的电路去实验室找你帮忙焊接之类的,当时的一些经历也的确对我很有帮助,也很高兴跟您聊一聊这些经历。以下是您询问的相关情况: + +## 个人近况 + +目前我就读于江苏大学软件工程专业,这与我高中时期的兴趣方向是一脉相承的。诚实说,并不算多上流,但是就我个人而言,这里提供了非常宽裕的个人时间,让我深入研究了很多问题,也发展了很多爱好。 + +## 近期项目 + +最近我参与了几个有意思的项目(详细信息请点击链接查看),主要包括: + +1. **ESP8266天气时钟**:这是一个结合单片机、物联网和人工智能技术的项目。我们开发了一款可以实时显示天气信息的智能时钟,通过简单的二维码扫描配网方式,用户可以轻松将设备连接到家庭WiFi。这个项目综合运用了嵌入式开发、后端服务和前端界面设计等多方面的技术。 + + -->(/blogs/ESP8266 天气时钟——项目展示.md) + +2. **基于CV的单摆实验优化方案**:这是一个将计算机视觉技术应用于传统物理实验的项目。我们通过计算机视觉获取高质量的摆球位置-时间数据,应用数学模型提取周期信息,最终通过非线性拟合消除大振幅和阻尼影响,大大提高了测量精度。据我的大学老师反馈,这个项目在中小学演示时效果很好,学生们表现出极大的兴趣。 + + -->(/blogs/基于CV的单摆实验优化方案——实验进度与总结.md) + +3. **Unity与WebView混合架构的游戏开发**:这是一个探索游戏UI开发新思路的项目,将Vue.js的强大UI能力与Unity的3D渲染结合,创造出一款沉浸式狼人杀游戏。这种架构不仅提升了开发效率,还实现了响应式设计和流畅动画效果。 + + -->(/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.md) + + 此外还有一些商单,从高中开始我就经常接外包了,不过都是层层转包的,拿不到多少米,也就不多说了。此外的一些学科竞赛(如蓝桥杯)也挺多的,这些没啥意思,也就不过多赘述了。 + +## 高中科创对现在的影响 + +回顾高中时期的科创经历,当时我主要朝两个方面研究: + +1. 硬件PCB之类的,包括组装很多锂电池,升降压模块,做充电宝,现在想起来也是相当危险,不过也充分激发了我的动手能力;当时老师您开的的esp8266的开发也对我很有帮助,虽然内容很浅,但帮我打开了嵌入式的大门,也让我在这方向深入研究了很多。当时还有个印象深刻的,是做了个太阳能拉力小车,蹭了波规则的漏洞,拿了第一。 +2. 软件前后端开发,这也是我目前的学习方向和就业方向。当时印象最深的是,课程布置了一个研学任务,方向随意,当时正好和朋友有一个做在线航海棋游戏的想法,也是这个任务促使了我废了很大努力成功做出来了这个游戏,我当时花了一个月,几乎每天都花数小时思考,也是这个游戏,让我的开发能力大幅提升。 + + -->(/resources/Battleship/基于NodeJS和WebSocket的在线航海棋游戏的设计与实现.pdf) + + +而当时通技课主要是两个主题我印象最深刻: + +第一个便是上面说的方向随意的研学任务,第二个是关于结构的任务,需要我们用木棍和热熔胶等材料搭建出尽可能牢固的桥梁,我认为通技中几乎所有的任务至少对我而言都是受益匪浅的,当时学的编程技巧成为了我的就业方向,当时学习使用的热熔胶,现在也经常会用到。不管是动手能力、批判性思维、创新能力,从我现在的角度看,都是对我的个人成长影响很大的。 + +结构化一些来说,这些经历对我的成长主要集中在这几方面: + +1. **专业选择的指引**:高中时期的编程和电子制作经历,明确了我对软件和硬件交叉领域的兴趣,为我选择软件工程专业奠定了基础。 +2. **实践能力的培养**:当时那个"方向随意"的研学任务给了我极大的自由空间,让我能够全身心投入到在线航海棋游戏的开发中。这个项目虽然耗费了我一个月左右的时间,但极大地提升了我的编程和问题解决能力,也让我体会到了从0到1创造产品的成就感。 +3. **学习习惯的养成**:科创活动培养了我自主探索、查阅资料、动手实践的习惯,这些习惯在大学学习中持续发挥着作用,帮助我快速适应新技术和新领域的学习。 + +## 对高中科创教育的建议 + +要把什么内容引入高中?这点我也没有太想好。 + +1. 就我最近的经历而言,我做的基于 CV 的摆球追踪实验被我现在的老师拿去了中小学演讲,据说他效果很好,学生也很感兴趣。我老师跟我说,中学的化学实验还好,但物理实验就非常无聊了,引入这些技术也许对于传统学科实验很有帮助,反映到通技课中,就是也许可以**用更先进的技术去和传统学科相结合**,这种**跨学科的融合**不仅能激发学生的兴趣,也能帮助他们更深入地理解传统学科知识。 + +2. 此外,**开放性任务的价值**也应被重视:像当年那个"方向随意"的研学任务,建议可以保持设置梯度的开放性任务,有些提供明确方向,有些则完全开放,满足不同学生的需求。 + +3. 同时,**项目驱动的学习模式**也很重要,之前的通技课其实就做的很好了,通过具体项目驱动学习效果往往比单纯的知识讲授要好。可以设计一些小型但完整的项目,让学生在实现过程中自然而然地学习所需知识。 + +其实,内容并不是特别重要,关键还是方法,要让学生用创新的创造性的方法去解决问题,只要内容上不是陈词滥调,学生不直接Copy一份往届的报告,不随便用AI生成一篇(但是用AI辅助,比如DeepResearch也许会是一个好主意),总归是有收获的。 + +## 总结 + +从感性上来说,我们中国的教育对于创新方面多少是略有欠缺的,很多同学在高中甚至到大学阶段都没有一些创造性的爱好,不管是做实验、编程,还是画画、编曲、写小说。我认为创造性的任务对于人的发展很重要,刷视频、看小说永远都是输入信息,而输出信息才是让人感受到自己价值的过程,缺少创造和输出在我看来也是青年人普遍陷入虚无主义的重要原因。所以,从我个人的感性和经历来说,我很希望您的通技课能继续办下去,并且越办越好。 diff --git a/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_200916.png b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_200916.png new file mode 100644 index 0000000..9a794ac Binary files /dev/null and b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_200916.png differ diff --git a/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_200954.png b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_200954.png new file mode 100644 index 0000000..3bd962f Binary files /dev/null and b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_200954.png differ diff --git a/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_201115.png b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_201115.png new file mode 100644 index 0000000..c97f95d Binary files /dev/null and b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_201115.png differ diff --git a/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_201948.png b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_201948.png new file mode 100644 index 0000000..dfb2fb7 Binary files /dev/null and b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_201948.png differ diff --git a/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_211728.png b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_211728.png new file mode 100644 index 0000000..ce1b105 Binary files /dev/null and b/src/blogs/突破界限:Unity与WebView混合架构在游戏开发中的实践.assets/2025-04-14_211728.png differ diff --git a/src/blogs/美中股市参与对比分析:文化差异与投资行为.md b/src/blogs/美中股市参与对比分析:文化差异与投资行为.md new file mode 100644 index 0000000..6c1edf7 --- /dev/null +++ b/src/blogs/美中股市参与对比分析:文化差异与投资行为.md @@ -0,0 +1,154 @@ +--- +title: 美中股市参与对比分析:文化差异与投资行为 +desc: 分析美国和中国这两个全球最大经济体的股市参与情况,探讨直接与间接参与的比例、人口统计特征、公众认知以及政府政策等方面的差异,并展望未来发展趋势。 +author: feie9454 +date: 2025-03-31 +tags: 投资、新闻 +--- + + +# 美中股市参与对比分析:文化差异与投资行为 + +## 1. 引言 + +随着全球金融市场的发展,股票投资已成为个人财富积累和退休规划的重要组成部分。不同国家和地区的公众参与股市的程度和方式存在显著差异,这既反映了经济发展水平的不同,也体现了文化价值观和政府政策的影响。本文将重点分析美国和中国这两个全球最大经济体的股市参与情况,探讨直接与间接参与的比例、人口统计特征、公众认知以及政府政策等方面的差异,并展望未来发展趋势。 + +## 2. 全球股市参与概览 + +在全球范围内,股市参与率因地区而异。世界交易所联合会(WFE)的调查显示,欧洲和美洲的平均零售参与率分别为31%和13%,而中东和亚太地区的平均水平则分别为52%和61%。这些数据表明区域因素对股市参与度有显著影响。 + +从国家层面来看,美国约有62%的成年人直接或间接持有股票,澳大利亚约为37%,中国约为7-20%(不同数据来源估计有差异),而印度在2023年估计约为6%。发达经济体通常拥有更高的参与率,这与其经济发展水平、金融市场成熟度以及文化传统密切相关。 + +## 3. 美国股市参与情况 + +### 直接与间接参与比例 + +美国拥有世界上最高的股市参与率之一。2024年的数据显示,约62%的美国成年人持有股票,无论是直接持有还是通过共同基金、退休账户等间接方式。其中,直接持有股票的比例约为21%,表明大多数美国家庭是通过间接渠道参与股市的。 + +间接参与主要通过以下渠道: + +1. **退休账户**:401(k)计划和个人退休账户(IRAs)是最常见的间接投资渠道,它们享有税收优惠,鼓励长期投资。 +2. **共同基金**:2024年,56.0%的美国家庭拥有共同基金或其他在美国注册的投资公司的股份。 +3. **交易所交易基金(ETFs)**、封闭式基金和单位投资信托基金也是常见的间接参与形式。 + +截至2024年底,美国居民家庭持有的流动金融资产中,股票占47.6%,共同基金占16.5%,这反映了美国家庭对股票投资的高度参与。 + +### 人口统计特征 + +美国股市参与存在明显的人口统计差异: + +1. **年龄因素**:65岁及以上的投资者持有43%的股票市场,但即使在35岁以下的年轻家庭中,也有41%的家庭持有股票。 +2. **收入和财富**:高收入群体参与度更高,收入超过10万美元的家庭中,有88%持有股票。截至2024年底,最富有的10%家庭拥有70%以上的股票市场。 +3. **种族差异**:66%的白人家庭持有股票,而黑人家庭和西班牙裔家庭的这一比例分别为39%和28%,股票占白人家庭财富的24%,而占黑人家庭和西班牙裔家庭财富的比例分别为13%和10%。 +4. **性别差异**:男性比女性更倾向于参与股市。 + +### 公众认知与态度 + +美国公众对股市的看法受多种因素影响: + +2025年初,美国消费者对股票市场的态度出现明显波动。年初时,消费者对股价的乐观程度曾达到近40年来的最高点,但在2025年3月和4月,由于特朗普政府宣布对多国实施高额关税,包括中国在内的国际贸易紧张局势加剧,导致美国股市经历了自2020年以来最大的单日跌幅。道琼斯工业平均指数一度暴跌1,679.39点(3.98%),标普500指数下跌4.84%,纳斯达克综合指数更是暴跌5.97%。 + +尽管短期市场波动会影响投资情绪,美国投资者整体上仍展现出对股市的长期信心,将其视为财富积累和退休规划的重要工具。这种长期信心部分源于美国金融市场的深度和成熟度,以及政府通过税收优惠等方式对投资的鼓励政策。 + +## 4. 中国股市参与情况 + +### 直接与间接参与比例 + +与美国相比,中国的股市参与率明显较低: + +1. 2015年中国家庭金融调查(CHFS)显示,约9.3%的家庭参与股市。 +2. 2024年,官方数据表明约有1.8亿个人股票交易账户,考虑到中国约14亿人口和5亿家庭,估计2025年的参与率可能在15-20%之间。 +3. 中国股市长期以来以散户投资者为主,但近年来,机构投资者的持股比例有所增加。专业机构投资者持有的可交易股票的权重从2019年初的18%增加到2021年底的24.6%,2025年这一比例继续上升。 + +在间接参与方面: + +1. 与美国相比,房地产、财富管理产品和银行存款在中国投资中所占的比例更高。 +2. 自2000年以来,中国共同基金的数量和规模都显著增长。 +3. 政府也在积极鼓励养老基金和年金基金增加对股票市场的投资。 +4. 保险基金也在政府的引导下,逐步扩大其在A股市场的投资。 + +### 人口统计特征 + +中国股市参与者的人口统计特征显示: + +1. **年龄因素**:近年来年轻投资者参与度明显上升。多家证券公司的数据显示,新开户者中有相当大比例是年轻人,例如中信证券近一半的新开户者年龄在30岁以下,东北证券也发现18-30岁年龄段的新开户数量显著增加。 +2. **收入因素**:在中国,收入与股票市场参与度之间存在积极相关性,高收入群体参与度更高。 +3. **地域差异**:一线城市和沿海发达地区的居民参与股市的比例明显高于内陆地区。 + +### 公众认知与态度 + +中国公众对股市的看法呈现出一些独特特点: + +2025年初,中国股市经历了较大波动。2024年,在政府推出一系列刺激措施后,中国股市曾结束了三年连续下跌的局面,实现正增长。然而,进入2025年,受美国关税威胁、经济增长放缓和消费者信心不足等因素影响,上海和深圳股市在年初下跌约6%,成为全球表现最差的主要市场之一。 + +许多中国投资者认为,中国股市比美国股市更具投机性和波动性。据路透社报道,一些零售投资者表示:"政策制定者在干柴上点燃了火焰,但火已被冷水浇灭",这反映了对政策实施不力的失望情绪。这种观点导致部分投资者在2025年初减持股票,甚至考虑将资金转向海外市场、黄金或加密货币等其他资产类别。 + +## 5. 美中股市参与比较分析 + +### 参与率对比 + +美国和中国在股市参与率上存在显著差距: + +1. **总体参与率**:美国约有62%的成年人持有股票,而中国这一比例约为15-20%。 +2. **直接持股率**:美国约21%的家庭直接持有股票,而中国的直接持股比例较低。 +3. **间接持股率**:2024年约56%的美国家庭持有共同基金,而中国的间接参与正在增长但整体水平仍较低。 +4. **投资者构成**:美国机构投资者占主导地位,而中国虽然机构投资者比例在增长(2024年约为30%),但历史上散户投资者占主导地位。 +5. **投资偏好**:美国人偏好股票、共同基金和退休账户,而中国人更偏好房地产、财富管理产品和银行存款。 + +### 差异原因分析 + +导致美中股市参与差异的主要因素包括: + +1. **金融市场发展程度**:美国金融市场的发展历史更长,基础设施更完善,这增强了投资者的信任并提供了更广泛的金融产品。 +2. **文化因素**:美国文化更倾向于将投资股票作为长期财富积累的方式,而中国投资者历史上更偏爱房地产和银行存款。研究表明,中国家庭的储蓄率约为70%,远高于美国家庭。 +3. **经济发展水平**:美国更高的人均收入和更发达的金融体系为更高的股市参与度提供了支持。 +4. **监管环境**:美国拥有成熟且全面的投资者保护和市场透明度监管框架,而中国虽然也在发展其监管体系,但在市场干预和透明度方面与美国存在差异。 +5. **机构投资影响**:美国市场受大型机构投资者的影响较大,这有助于提高市场效率和稳定性,而中国市场过去以散户投资者为主,他们的交易行为更具投机性。 +6. **退休金制度**:美国完善的401(k)和IRA等退休金制度为间接股市参与提供了重要渠道,而中国的养老金体系仍在完善中。 + +## 6. 政府政策与措施 + +### 美国政府政策 + +美国政府主要通过以下方式鼓励股市参与: + +1. 关键立法包括1933年的《证券法》和1934年的《证券交易法》,旨在确保证券销售的透明度并防止欺诈。 +2. 美国证券交易委员会(SEC)作为主要的监管机构,负责监督证券行业,包括经纪公司和证券交易所,以维护市场的公平和透明。 +3. 与退休储蓄相关的政策,如401(k)计划和个人退休账户(IRAs)的税收优惠,间接鼓励了公众对包括股票在内的资产进行投资。 +4. 《国家金融包容战略》旨在促进更广泛地获得安全的金融产品和服务,从而帮助人们积累财富。 + +### 中国政府政策 + +近年来,中国政府采取了更为主动的措施促进股市发展: + +1. 2025年1月,中国金融监管机构发布了一项实施计划,旨在促进中长期资金流入股市,以稳定股市表现。该计划强调吸引商业保险资金、全国社会保障基金、基本养老金、企业年金和公共基金等中长期资金增加对股票市场的投资。 +2. 为优化资本市场的投资生态,政府鼓励上市公司增加股票回购和多次分红。2024年修订的战略投资者规则简化了外资进入A股市场的程序,降低了持股门槛,缩短了锁定期。 +3. 2025年3月,中国国务院发布了《促进消费特别行动计划》,其中包括稳定股市的措施。该计划旨在"大力促进消费,全方位扩大内需,通过增加收入和减轻负担提高消费能力"。计划包括发展适合个人投资者的债券产品,并采取"多种措施"稳定股市。 +4. 2025年4月,面对美国加征关税导致的市场动荡,中国采取了一系列稳定市场的措施。国有控股公司承诺增加股权投资,多家上市公司宣布股票回购计划,央行也表示支持央行汇金公司增持股票基金。这些举措旨在恢复市场信心,稳定股市表现。 +5. 2025年政府工作报告提出,将政府赤字占GDP的比例扩大到4%,地方政府专项债券发行规模为4.4万亿元人民币,超长期特别国债为1.3万亿元人民币,这些财政措施部分目的是支持资本市场发展。 + +## 7. 趋势与展望 + +从当前发展趋势来看: + +1. **美国市场**: + - 尽管2025年初因贸易紧张局势而出现波动,美国股市预计将保持较高的参与率,尤其是通过退休账户的间接参与。 + - 关注点可能更多转向ESG投资等新兴趋势,以及人工智能和其他高科技领域的投资机会。 + - 投资者对通胀和经济衰退的担忧可能影响短期市场情绪,但长期投资文化已深入美国社会。 +2. **中国市场**: + - 预计未来三年公众基金持有的A股市场价值将每年增长10%。 + - 年轻投资者的参与度正在上升,这可能改变市场的投资行为和偏好,使投资模式更加多元化。 + - 机构投资者的影响力将继续增强,有助于提升市场稳定性和长期投资理念。 + - 中国政府的刺激措施,包括消费补贴、基础设施投资和降低市场准入门槛等,将继续支持股市发展。 +3. **政策影响**: + - 中国政府将继续推动中长期资金流入股市,包括保险资金、社保基金和养老金等。 + - 外资进入中国市场的门槛降低,可能带来更多国际资金,但受中美贸易关系影响存在不确定性。 + - 两国在促进资本市场发展方面的政策差异将继续影响投资者行为和市场结构。 + +## 8. 结论 + +美国和中国在股市参与度和公众观点方面存在显著差异,这既反映了两国经济发展阶段的不同,也体现了文化、政策和市场结构的差异。美国以其成熟的金融体系和退休储蓄机制,拥有全球最高的股市参与率之一,机构投资占主导地位,投资者展现出较强的长期投资理念。而中国虽然参与率相对较低,但正处于快速发展阶段,政府采取积极措施促进机构投资并吸引国际资金,同时年轻一代投资者日益活跃。 + +随着中国金融市场的进一步开放和成熟,以及政府对资本市场发展的持续支持,中国的股市参与模式可能逐渐向美国靠拢,但仍将保持其独特特点。两国股市的发展趋势和参与模式将继续受到经济环境、政策导向和全球金融格局的影响,值得持续关注。 + +最终,了解不同国家的股市参与情况,不仅有助于理解全球金融市场的运作机制,也为投资者和政策制定者提供了重要的参考价值。通过比较美国和中国的投资文化和市场结构,我们可以更好地把握两个全球最大经济体的金融体系运作特点,为未来的投资决策和政策制定提供指导。 \ No newline at end of file diff --git a/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/daf99611-4f1a-4b9b-bb6e-3a79d812b20e.jpg b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/daf99611-4f1a-4b9b-bb6e-3a79d812b20e.jpg new file mode 100644 index 0000000..79f43dc Binary files /dev/null and b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/daf99611-4f1a-4b9b-bb6e-3a79d812b20e.jpg differ diff --git a/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/e8197210-93d9-4a34-a47d-e0568c13d34b.jpg b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/e8197210-93d9-4a34-a47d-e0568c13d34b.jpg new file mode 100644 index 0000000..056babe Binary files /dev/null and b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/e8197210-93d9-4a34-a47d-e0568c13d34b.jpg differ diff --git a/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/ff151191-c794-4a20-a19f-838e2a9d8b6c.jpg b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/ff151191-c794-4a20-a19f-838e2a9d8b6c.jpg new file mode 100644 index 0000000..772e40b Binary files /dev/null and b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/ff151191-c794-4a20-a19f-838e2a9d8b6c.jpg differ diff --git a/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/image-20250426081926998.png b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/image-20250426081926998.png new file mode 100644 index 0000000..cb2bf5e Binary files /dev/null and b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/image-20250426081926998.png differ diff --git a/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/v2-cf0b1f86ba2023ab6c5eab60dbd44470_720w.webp b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/v2-cf0b1f86ba2023ab6c5eab60dbd44470_720w.webp new file mode 100644 index 0000000..af22f7b Binary files /dev/null and b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.assets/v2-cf0b1f86ba2023ab6c5eab60dbd44470_720w.webp differ diff --git a/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.md b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.md new file mode 100644 index 0000000..05c017a --- /dev/null +++ b/src/blogs/计算机视觉辅助单摆优化及经典力学实验拓展研究综述.md @@ -0,0 +1,176 @@ +--- +title: 计算机视觉辅助单摆优化及经典力学实验拓展研究综述 +desc: 本文从利用计算机视觉优化单摆实验的方法出发,详细介绍了五种经典力学实验拓展:弹簧振子、自由落体/斜抛、扭摆、斜坡滚动和Atwood机。通过将高精度视觉追踪与精细理论模型结合,这些拓展实验极大降低了系统误差,使经典力学教学实验更加精确和丰富。 +author: feie9454 +date: 2025-04-26 +tags: 计算机、物理、竞赛 +--- + +# 计算机视觉辅助单摆优化及经典力学实验拓展研究综述 + +在经典力学实验教学中,通过改进实验方法与理论模型,可以大幅降低系统误差并拓展实验内容。以下整理了相关文献资料,包括基于计算机视觉(CV)的大数据轨迹分析在单摆实验中的应用,以及五个拓展实验(弹簧振子、自由落体/斜抛、扭摆、斜坡滚动、Atwood机)的模型公式、推导背景、实验设计和误差分析。 + +## 一、现有单摆实验的选题与设计思路概要 + +| 关键环节 | CV 大数据优势 | 物理模型/公式 | 用途 | +| ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| **轨迹采集** | - 用 60 fps+ 摄像机逐帧跟踪摆球(`track_pendulum`)- 最多可获得上万条 (x,y,t) 数据点 | — | 获得高分辨率时间-空间曲线,远优于人工计时 | +| **几何标定** | - 拟合摆球轨迹圆 (`fit_circle`) 推算支点坐标与摆长 L | $x^2+y^2+…=0$(线性最小二乘) | 把“量尺误差”转化为统计拟合误差,显著降低系统偏差 | +| **角度-周期提取** | - 自动识别峰值/过零点 (`identify_periods`) 获取每一周期与初振幅 | — | 不依赖“计十个周期/取平均”的简化假设,可观测周期随振幅的微小变化 | +| **系统误差校正** | - 大样本非线性拟合 (`large_angle_g`) 同时回归 g、阻尼γ | 大摆角修正:$T=T_0!\bigl(1+\tfrac{\theta^2}{16}+…\bigr)$线性阻尼修正:$T_d≈T_0!\bigl(1+\tfrac{γ^{2}}{8ω_0^{2}}\bigr)$ | 把“大角度”和“空气阻尼”两种系统误差转为可拟合参数,残差<0.5 % | + +**核心理念** + +1. **让数据密度替代人为技巧**:用 CV 获得“过采样”的轨迹,再用统计方法压低噪声; +2. **让理论模型替代经验校准**:把传统忽略的二阶、三阶项直接写进 $T(\theta,\gamma, ...)$,通过回归“解耦”出真周期 $T_0$,把系统误差量化并扣除; +3. **把误差当信号来利用**:振幅衰减曲线本身就是提取阻尼常数 γ 的数据,不再是“必须消掉的麻烦”。 + 这些做法把经典学生实验的误差从 **数 % 量级** 压到 **0.5 % 以内**,同时也生成了阻尼系数、空气阻力系数等附加物理量,可供进一步研究 。 + +## 二、可迁移到其他力学实验的通用流程 + +> **CV 大数据 + 精细模型 + 统计拟合 = 系统误差压缩器** + +1. **视频->坐标**:高帧率拍摄 + 颜色/形状阈值定位 + 轨迹平滑。 +2. **几何/时标标定**:利用轨迹本身(圆、抛物线、螺线…)或少量基准点自洽求尺度。 +3. **物理模型升级**:把一阶近似扩展到更高阶(非线性项、阻尼、耦合…)。 +4. **参数全回归**:一次性拟合全部待定参数,让“误差”进入模型、从结果里出去。 +5. **残差诊断**:查看残差频谱,分离硬件噪声、背景力、数值误差。 + +------ + +## 三、适合套用同一思路的经典实验提案 + +| 方向 | 可观测量 & 主要系统误差 | 升级模型(示意) | CV 采集设计要点 | +| ------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| **1. 垂直/水平弹簧振子** | 周期->弹性常数 k;系统误差:大振幅非简谐、空气阻尼、弹簧自重 | $T=T_0\!\bigl(1+\tfrac{3A^2}{8L^2}+…\bigr),\quad T_d≈T_0\!\bigl(1+\tfrac{γ^2}{8ω_0^2}\bigr)$ | 单摄像头侧视,追踪质点或刻度片;同时拟合 k、γ、有效质量 m_eff,实现 k 的 0.2 % 级测量 | +| **2. 自由落体 / 斜抛运动** | 取 g;误差:空气阻力、初速角度偏差 | $y(t)=v_0t-\tfrac12 gt^2-\tfrac12 kρA v^2 t^2+…$(二阶空气阻力) | 单摄像头侧视;帧间微分直接得 v(t),回归 g 与 C_d | +| **3. 扭摆(测转动惯量或 G)** | 周期->扭转常数 κ;误差:非线性扭转、空气阻尼、线材老化 | $T=T_0\!\bigl(1+\tfrac{βθ^2}{16}+…\bigr),\quad θ(t)=θ_0e^{-γt}\cos ω_dt$ | 俯视追踪盘上彩标角度;用长时序提取 γ、κ、非线性系数 β,同时监控 κ 随温度漂移 | +| **4. 滚动物体下斜坡(转-平动耦合)** | 求滚动摩擦系数 μ_r;误差:斜面角度、空气阻力、物体偏心 | $a=g(\sin α-μ_r \cos α)-\tfrac{C_dρA}{m}v^2$ | 侧视拍摄,提取 x(t);斜面标定用轨迹直线拟合;一次回归 μ_r 与 C_d | +| **5. Atwood 机 / 有摩擦滑轮** | 加速度->质量差;误差:滑轮转动惯量 I、轴承摩擦 τ_f | $a=\frac{(m_2-m_1)g-τ_f/R}{m_1+m_2+I/R^2} $ | 俯视双质点轨迹,实时算 a(t);以多组 m_1,m_2 回归 I、τ_f,实现滑轮参数标定 | + +**为什么这些实验特别适合?** + +- **轨迹简单但数据量需求大**:单自由度或准单自由度运动,CV 容易精准跟踪; +- **系统误差可写成封闭公式**:高阶非线性或阻尼项有现成级数/近似解; +- **参数往往互相关联**:一次非线性最小二乘可同时给出主参数和误差源,正好利用大样本。 + +## 垂直/水平弹簧振子:大振幅修正与阻尼效应 + +理想弹簧振子(质量$m$附在劲度系数$k$的轻弹簧末端)是简谐振动的典型模型,其固有周期 $T=2\pi\sqrt{m/k}$。不同于单摆,小幅近似并非弹簧振子振动的必要条件:只要弹簧严格满足胡克定律,周期与振幅无关。在水平面或竖直方向进行振动实验可验证这一点——调整初始振幅大小,振动周期几乎不变 ([仿真實驗在中學物理教學中的應用研究 - EdUHK](https://www.eduhk.hk/apfslt/v10_issue1/lidean/lidean4.htm#:~:text=%25E4%25BB%25BF%25E7%259C%259F%25E5%25AF%25A6%25E9%25A9%2597%25E5%259C%25A8%25E4%25B8%25AD%25E5%25AD%25B8%25E7%2589%25A9%25E7%2590%2586%25E6%2595%2599%25E5%25AD%25B8%25E4%25B8%25AD%25E7%259A%2584%25E6%2587%2589%25E7%2594%25A8%25E7%25A0%2594%25E7%25A9%25B6%2520,))。文献表明,通过实验观察改变振幅、弹簧刚度和小球质量对周期的影响,可以印证周期主要取决于$m$和$k$,与振幅无关 ([仿真實驗在中學物理教學中的應用研究 - EdUHK](https://www.eduhk.hk/apfslt/v10_issue1/lidean/lidean4.htm#:~:text=%25E4%25BB%25BF%25E7%259C%259F%25E5%25AF%25A6%25E9%25A9%2597%25E5%259C%25A8%25E4%25B8%25AD%25E5%25AD%25B8%25E7%2589%25A9%25E7%2590%2586%25E6%2595%2599%25E5%25AD%25B8%25E4%25B8%25AD%25E7%259A%2584%25E6%2587%2589%25E7%2594%25A8%25E7%25A0%2594%25E7%25A9%25B6%2520,))。然而,在实际拓展实验中有几点需要修正和考虑: + +- **有效质量修正:** 理论上上述周期公式忽略了弹簧自身的质量。当弹簧质量$m_s$不可忽略时,弹簧各部分并非同时等幅运动,导致系统等效惯量增加。经典分析表明,对于均匀细弹簧,其有效附加质量约为$m_s/3$ ([弹簧振动周期研究.doc - 原创力文档](https://m.book118.com/html/2019/0625/8063113005002032.shtm#:~:text=%25E5%25BC%25B9%25E7%25B0%25A7%25E6%258C%25AF%25E5%258A%25A8%25E5%2591%25A8%25E6%259C%259F%25E7%25A0%2594%25E7%25A9%25B6.doc%2520,))。因此周期公式修正为 $T=2\pi\sqrt{(m+ m_s/3)/k}$ ([弹簧振动周期研究.doc - 原创力文档](https://m.book118.com/html/2019/0625/8063113005002032.shtm#:~:text=%25E5%25BC%25B9%25E7%25B0%25A7%25E6%258C%25AF%25E5%258A%25A8%25E5%2591%25A8%25E6%259C%259F%25E7%25A0%2594%25E7%25A9%25B6.doc%2520,))。某实验通过测量比较“忽略弹簧质量”和“考虑弹簧质量”两种情况下的周期,计算出附加系数约0.3~0.35,与理论值1/3符合良好 ([弹簧振动周期研究.doc - 原创力文档](https://m.book118.com/html/2019/0625/8063113005002032.shtm#:~:text=%25E5%25BC%25B9%25E7%25B0%25A7%25E6%258C%25AF%25E5%258A%25A8%25E5%2591%25A8%25E6%259C%259F%25E7%25A0%2594%25E7%25A9%25B6.doc%2520,))。在高精度测量中,应将此修正计入,或选用轻质高刚度的弹簧以减小影响。 + +![daf99611-4f1a-4b9b-bb6e-3a79d812b20e](./%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89%E8%BE%85%E5%8A%A9%E5%8D%95%E6%91%86%E4%BC%98%E5%8C%96%E5%8F%8A%E7%BB%8F%E5%85%B8%E5%8A%9B%E5%AD%A6%E5%AE%9E%E9%AA%8C%E6%8B%93%E5%B1%95%E7%A0%94%E7%A9%B6%E7%BB%BC%E8%BF%B0.assets/daf99611-4f1a-4b9b-bb6e-3a79d812b20e.jpg) + +![ff151191-c794-4a20-a19f-838e2a9d8b6c](./%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89%E8%BE%85%E5%8A%A9%E5%8D%95%E6%91%86%E4%BC%98%E5%8C%96%E5%8F%8A%E7%BB%8F%E5%85%B8%E5%8A%9B%E5%AD%A6%E5%AE%9E%E9%AA%8C%E6%8B%93%E5%B1%95%E7%A0%94%E7%A9%B6%E7%BB%BC%E8%BF%B0.assets/ff151191-c794-4a20-a19f-838e2a9d8b6c.jpg) + +- **大振幅非线性:** 理想弹簧服从线性力学关系 $F=-kx$。若振幅较大但弹簧仍处于弹性限度内,运动方程仍是线性的,周期不随振幅变化,这点已由实验和仿真所证实 ([仿真實驗在中學物理教學中的應用研究 - EdUHK](https://www.eduhk.hk/apfslt/v10_issue1/lidean/lidean4.htm#:~:text=%25E4%25BB%25BF%25E7%259C%259F%25E5%25AF%25A6%25E9%25A9%2597%25E5%259C%25A8%25E4%25B8%25AD%25E5%25AD%25B8%25E7%2589%25A9%25E7%2590%2586%25E6%2595%2599%25E5%25AD%25B8%25E4%25B8%25AD%25E7%259A%2584%25E6%2587%2589%25E7%2594%25A8%25E7%25A0%2594%25E7%25A9%25B6%2520,))。这意味着**弹簧振子不像单摆那样存在显著的大振幅效应**。然而,实际弹簧在大应变下可能出现非线性:例如弹簧的劲度随伸长略有变化,或者弹簧发生微小塑性形变等。在精密实验或本科创新项目中,有人尝试通过实验手段寻找弹簧振子周期的经验公式 ([广工大物实验——弹簧振子周期公式研究原创 - CSDN博客](https://blog.csdn.net/m0_64247710/article/details/127880582#:~:text=%25E5%25AE%259E%25E9%25AA%258C%25E7%259B%25AE%25E7%259A%2584%25EF%25BC%259A))。总体而言,在常用振幅范围内,弹簧简谐振动的**固有频率对振幅扰动不敏感**,这使其成为验证简谐运动性质的良好体系,但也限制了“振幅依赖性”这一拓展研究点的发挥。 + +- **阻尼振动:** 弹簧振子实际运动会受到阻尼,例如空气阻力和内部摩擦。阻尼使总能量随时间减少,体现为振幅指数衰减和振动频率的微小变化。若阻尼力与速度成正比(线性阻尼),模型与单摆类似:$x(t)=A_0 e^{-\lambda t}\cos(\omega_d t+\phi)$,其中$\omega_d=\sqrt{\omega_0^2-\lambda^2}\approx\omega_0$(欠阻尼情况下)几乎不影响周期。因此**阻尼主要影响振幅而非周期**。实验上常通过记录振幅随时间衰减曲线,取相邻峰值比值来求对数减量,从而计算阻尼系数或品质因数$Q$ 。例如,上述半衰期方法同样适用:测得弹簧振子振幅减半所需时间$T_{1/2}$,可得$\lambda=\ln2/T_{1/2}$,再乘以$2m$得到等效线阻尼系数$b$ 。在阻尼很小时,每周期衰减率$\lambda T$也很小,如某实验中$\lambda\approx2.0\times10^{-3}\,\text{s}^{-1}$,对应$Q\approx\omega_0/(2\lambda)\sim O(10^2-10^3)$的高品质因数。这意味着弹簧振子往往需要较长时间才能衰减静止,因此为了加速实验进程和扩大阻尼效应的研究,可引入**额外阻尼机制**(如水槽阻尼、涡流阻尼等)。有文献设计了将弹簧振子部分浸入液体的实验,通过液体黏滞阻力实现可控阻尼,并利用现代数据采集手段研究阻尼振动规律 ([阻尼振动实验的设计与研究[6]](https://m.iclient.qq.com/read/1027125876/12#:~:text=%E9%98%BB%E5%B0%BC%E6%8C%AF%E5%8A%A8%E5%AE%9E%E9%AA%8C%E7%9A%84%E8%AE%BE%E8%AE%A1%E4%B8%8E%E7%A0%94%E7%A9%B6))。 + +- **数字化实验与参数测定:** 随着传感与数据采集技术的发展,弹簧振子的研究已从秒表和刻度尺时代进入传感器和计算机时代。一项研究利用**气垫导轨**减少摩擦干扰,并借助位移传感器和MATLAB软件实时获取振子运动数据,精确计算出了弹簧劲度系数和阻尼衰减常数 ([中国高等教育期刊文献总库](https://cnki.huanghuai.edu.cn/KCMS/detail/frame/list.aspx%3Ffilename%3Dwlsl201106009%26dbcode%3DCJFR%26dbname%3DCJFRTOTAL%26cat%3DO321%26reftype%3D9%26curdbcode%3Dcjfr%26page%3D9#:~:text=%25E4%25B8%25AD%25E5%259B%25BD%25E9%25AB%2598%25E7%25AD%2589%25E6%2595%2599%25E8%2582%25B2%25E6%259C%259F%25E5%2588%258A%25E6%2596%2587%25E7%258C%25AE%25E6%2580%25BB%25E5%25BA%2593%2520%25E5%25A4%25A7%25E5%25AD%25A6%25E7%2589%25A9%25E7%2590%2586%25E5%25AE%259E%25E9%25AA%258C.%25202016%252804%2529%253B%2520,88%255D%2520%25E8%25AE%25B8%25E7%2594%259F%25E6%2585%25A7%252C%25E9%2592%25B1%25E4%25BB%25B0))。这种数字化实验设计在《大学物理实验》上进行了报道:研究者赵俊等改进了传统弹簧振子简谐/阻尼振动实验,引入DISLab位移传感器记录运动并编写程序处理数据,实现了对弹簧常数的高精度测定和阻尼特性的量化分析 ([中国高等教育期刊文献总库](https://cnki.huanghuai.edu.cn/KCMS/detail/frame/list.aspx%3Ffilename%3Dwlsl201106009%26dbcode%3DCJFR%26dbname%3DCJFRTOTAL%26cat%3DO321%26reftype%3D9%26curdbcode%3Dcjfr%26page%3D9#:~:text=%25E4%25B8%25AD%25E5%259B%25BD%25E9%25AB%2598%25E7%25AD%2589%25E6%2595%2599%25E8%2582%25B2%25E6%259C%259F%25E5%2588%258A%25E6%2596%2587%25E7%258C%25AE%25E6%2580%25BB%25E5%25BA%2593%2520%25E5%25A4%25A7%25E5%25AD%25A6%25E7%2589%25A9%25E7%2590%2586%25E5%25AE%259E%25E9%25AA%258C.%25202016%252804%2529%253B%2520,88%255D%2520%25E8%25AE%25B8%25E7%2594%259F%25E6%2585%25A7%252C%25E9%2592%25B1%25E4%25BB%25B0))。类似地,许生慧等开展了“先实验后理论”的教学探索,让学生直接利用数字平台测量弹簧振子的阻尼并反推模型参数 ([数字化实验平台的先实验后理论教学探索与实践 - 科研之友](https://www.scholarmate.com/S/7gPFTw#:~:text=%25E6%2595%25B0%25E5%25AD%2597%25E5%258C%2596%25E5%25AE%259E%25E9%25AA%258C%25E5%25B9%25B3%25E5%258F%25B0%25E7%259A%2584%25E5%2585%2588%25E5%25AE%259E%25E9%25AA%258C%25E5%2590%258E%25E7%2590%2586%25E8%25AE%25BA%25E6%2595%2599%25E5%25AD%25A6%25E6%258E%25A2%25E7%25B4%25A2%25E4%25B8%258E%25E5%25AE%259E%25E8%25B7%25B5%2520))。这些工作体现出,将现代技术融入经典实验,不仅提高了测量精度,也拓展了可研究的现象范围。例如,通过高采样率的数据,可以观察到阻尼振动中瞬态的细节、验证指数衰减模型的准确性,并评估不同阻尼源(空气阻力 vs. 内耗)的相对贡献。这些都是传统手段难以实现的。 + +综上,在弹簧振子拓展实验中,大振幅条件下仍可视为简谐运动但需考虑弹簧质量修正;引入阻尼后重点关注振幅的指数衰减规律和能量损失机制。通过数字化技术获取高分辨数据并结合模型拟合,可更精细地研究弹簧振子的动力学参数及误差来源,为教学和竞赛提供更深入的实验项目。 + +## 自由落体与斜抛运动:空气阻力建模与落体识别 + +**空气阻力建模:** 理想自由落体只受重力作用,物体下落加速度恒为$g$。但实际中空气阻力不可避免,尤其是高速或轻质物体下落时影响显著 ([考虑空气阻力的自由落体模型【f=kv^2】](https://www.bilibili.com/video/BV19a411M7Eb/#:~:text=Physics%2520Ninja%25E5%25BD%2593f%253Dkv,%25E5%2589%2591%25E6%25A1%25A5%25E5%25A4%25A7%25E5%25AD%25A6))。空气阻力 $F_D$ 通常与速度有关,可近似分为两种模型: ([6.4 Drag Force and Terminal Speed | University Physics Volume 1](https://courses.lumenlearning.com/suny-osuniversityphysics/chapter/6-4-drag-force-and-terminal-speed/#:~:text=most%2520large%2520objects%2520such%2520as,other%2520factors%252C%2520this%2520relationship%2520becomes)) + +- **线性阻力(低速、小物体):** $F_D = -b v$,其中$b$是阻力系数(与介质黏度、物体形状和尺度有关)。此时运动方程:$m\frac{dv}{dt} = mg - b v$。解得速度随时间的函数: + + $$ v(t) = \frac{mg}{b}\Big(1 - e^{-\frac{b}{m}t}\Big) $$ + + ([Section15](https://physics.csuchico.edu/kagan/204A/lecturenotes/Section15.pdf#:~:text=v%2520%253D%2520vt%25201%25E2%2588%2592%2520e,%25E2%258E%259D%2520%25E2%258E%259C%2520%25E2%258E%259C%2520%25E2%258E%259E%2520%25E2%258E%25A0)), + + 达到稳态时的**终端速度**(速度趋于恒定)为 $v_T = \frac{mg}{b}$ ([Section15](https://physics.csuchico.edu/kagan/204A/lecturenotes/Section15.pdf#:~:text=v%2520%253D%2520vt%25201%25E2%2588%2592%2520e,%25E2%258E%259D%2520%25E2%258E%259C%2520%25E2%258E%259C%2520%25E2%258E%259E%2520%25E2%258E%25A0))。这一公式表明物体将以指数规律接近其极限速度。例如,雨滴下落可视为线性阻力,在约几秒内速度接近终值。 + +- **二次阻力(高速、大物体):** $F_D = -\frac{1}{2}C\rho A v^2$,其中$C$为阻力系数(与形状有关),$\rho$为空气密度,$A$是迎风面积 ([6.4 Drag Force and Terminal Speed | University Physics Volume 1](https://courses.lumenlearning.com/suny-osuniversityphysics/chapter/6-4-drag-force-and-terminal-speed/#:~:text=most%2520large%2520objects%2520such%2520as,other%2520factors%252C%2520this%2520relationship%2520becomes))。此非线性方程没有初等解析解,但可得到稳态终端速度: + + $$ v_T = \sqrt{\frac{2mg}{C\rho A}} $$ + + ([6.4 Drag Force and Terminal Speed | University Physics Volume 1](https://courses.lumenlearning.com/suny-osuniversityphysics/chapter/6-4-drag-force-and-terminal-speed/#:~:text=The%2520terminal%2520velocity%2520%2524%2524%2520,can%2520be%2520written%2520as)),\ + + 当$v$接近$v_T$时,阻力逐渐平衡重力,加速度下降。对于人体等大物体,$C\rho A$典型值使得跳伞者头朝下时$v_T\approx 60-70\text{m/s}$,展开四肢时增大迎风面积可将$v_T$降低至约$50\text{m/s}$ ([6.4 Drag Force and Terminal Speed | University Physics Volume 1](https://courses.lumenlearning.com/suny-osuniversityphysics/chapter/6-4-drag-force-and-terminal-speed/#:~:text=match%2520at%2520L171%2520This%2520means,This%2520terminal%2520velocity%2520becomes%2520much)) ([6.4 Drag Force and Terminal Speed | University Physics Volume 1](https://courses.lumenlearning.com/suny-osuniversityphysics/chapter/6-4-drag-force-and-terminal-speed/#:~:text=This%2520means%2520a%2520skydiver%2520with,This%2520terminal%2520velocity%2520becomes%2520much))。文献中给出了不同姿态下终端速度的定量计算,例如质量75 kg的人头朝下终端速度$\approx98\text{m/s}$,而85 kg人水平展开身体时$v_T\approx44\text{m/s}$ ([6.4 Drag Force and Terminal Speed | University Physics Volume 1](https://courses.lumenlearning.com/suny-osuniversityphysics/chapter/6-4-drag-force-and-terminal-speed/#:~:text=This%2520means%2520a%2520skydiver%2520with,This%2520terminal%2520velocity%2520becomes%2520much)) ([6.4 Drag Force and Terminal Speed | University Physics Volume 1](https://courses.lumenlearning.com/suny-osuniversityphysics/chapter/6-4-drag-force-and-terminal-speed/#:~:text=The%2520terminal%2520velocity%2520%2524%2524%2520,can%2520be%2520written%2520as))。可见$A$增大终端速度显著降低,这与$ v_T\propto 1/\sqrt{A} $的关系一致。 + +实际物体所受阻力介于线性和二次模型之间,会随速度/雷诺数改变。小球下落的经典实验是**咖啡滤纸实验**:单个滤纸质量轻、受线性阻力主导,多片叠加质量加大则更接近二次阻力。 ([[PDF] The Ubiquitous Coffee Filter - DigitalCommons@UNL](https://digitalcommons.unl.edu/cgi/viewcontent.cgi?article=1039&context=physicsfuller#:~:text=DigitalCommons%40UNL%20digitalcommons,onto%20a%20sonic%20ranger))的研究通过不同层数滤纸的终速关系,验证了阻力模型从近似线性过渡到二次的过程。这类实验直观证明了空气阻力模型的重要性。 + +**斜抛运动:** 在含阻力情况下,斜抛物体不再做理想抛物线运动,而是轨迹迅速下沉、水平射程减小。解析求解较复杂,通常采用数值模拟或近似分析。对于线性阻力,可将运动拆分为水平和竖直两个正交分量,分别满足$x$方向$\ddot x + (\frac{b}{m}) \dot x = 0$,$y$方向$\ddot y + (\frac{b}{m})\dot y = -g$,解得速度分量类似上述指数形式,进而得到轨迹方程 ([Projectile Motion with Air Resistance - Richard Fitzpatrick](https://farside.ph.utexas.edu/teaching/336k/Newton/node29.html#:~:text=Projectile%2520Motion%2520with%2520Air%2520Resistance,making%2520an%2520angle))。对于二次阻力,没有简单解析解,需要数值积分来得到轨迹形状和飞行时间 ([[PDF] Topic 1 | Projectile Motion with Air Resistance](https://web.physics.wustl.edu/~wimd/topic01.pdf#:~:text=Resistance%20web,gibly%20small))。总体效果是:阻力使上升段和下降段轨迹不对称、**落点比无阻力时更近**。如某些研究给出了考虑线性阻力时射程的解析表达式,并将理论值与实测(例如发射小球测量落点)相比较,发现模型能较好地解释射程的减小幅度 ([考虑空气阻力的斜抛运动的收尾速度和最低速度 - Joyful Physics](https://joyfulphysics.net/index.php/archives/257/#:~:text=%25E8%25B4%25A8%25E7%2582%25B9%25E5%2581%259A%25E6%2596%259C%25E6%258A%259B%25E8%25BF%2590%25E5%258A%25A8%25EF%25BC%258C%25E8%25B4%25A8%25E9%2587%258F%25E4%25B8%25BAm%25EF%25BC%258C%25E5%2588%259D%25E9%2580%259F%25E5%25BA%25A6v0%25E4%25B8%258E%25E6%25B0%25B4%25E5%25B9%25B3%25E6%2596%25B9%25E5%2590%2591%25E5%25A4%25B9%25E8%25A7%2592%25CE%25B80%25E3%2580%2582%25E8%2580%2583%25E8%2599%2591%25E7%25A9%25BA%25E6%25B0%2594%25E9%2598%25BB%25E5%258A%259B%25EF%25BC%258Cf%253D%25E2%2588%2592kv%25E3%2580%2582%2520%25E4%25B8%258B%25E9%259D%25A2%25E8%25A7%25A3%25E4%25B8%2580%25E4%25B8%258B%25E8%25B4%25A8%25E7%2582%25B9%25E7%259A%2584%25E9%2580%259F%25E7%258E%2587%25E3%2580%2582%2520%25E7%2589%259B%25E9%25A1%25BF%25E7%25AC%25AC%25E4%25BA%258C%25E5%25AE%259A%25E5%25BE%258B))。 + +**自动识别与测量:** 为了研究上述阻力效应,需要准确获取运动过程中的速度和位置数据。传统手段包括打点计时器(测位移-时间关系)和速度传感器等。近年来,计算机视觉和图像处理被应用于自由落体和抛体运动的测量中。例如,使用高速摄像机拍摄物体下落过程,结合帧间差分或目标识别算法提取物体的像素坐标,从而得到其随时间的位移和速度 ([pinn固体坠落实验_pinn构建损失 - CSDN博客](https://blog.csdn.net/m0_37730869/article/details/130393574#:~:text=pinn%25E5%259B%25BA%25E4%25BD%2593%25E5%259D%25A0%25E8%2590%25BD%25E5%25AE%259E%25E9%25AA%258C_pinn%25E6%259E%2584%25E5%25BB%25BA%25E6%258D%259F%25E5%25A4%25B1%2520,%25E9%2587%2587%25E9%259B%2586%25E5%25AE%259E%25E9%25AA%258C%25E6%2595%25B0%25E6%258D%25AE%25EF%25BC%259A%25E4%25BD%25BF%25E7%2594%25A8%25E9%25AB%2598%25E9%2580%259F%25E7%259B%25B8%25E6%259C%25BA%25E7%25AD%2589%25E8%25AE%25BE%25E5%25A4%2587%25EF%25BC%258C%25E8%25AE%25B0%25E5%25BD%2595%25E5%259B%25BA%25E4%25BD%2593%25E7%2589%25A9%25E4%25BD%2593%25E5%259C%25A8%25E8%2587%25AA%25E7%2594%25B1%25E8%2590%25BD%25E4%25BD%2593%25E8%25BF%2587%25E7%25A8%258B%25E4%25B8%25AD%25E7%259A%2584%25E8%25BF%2590%25E5%258A%25A8%25E8%25BD%25A8%25E8%25BF%25B9%25E3%2580%2582))。一个简单的**落体识别算法**是利用不同背景/物体颜色进行二值化跟踪,或者在物体上贴上明显标记以便于检测。提取的数据可以拟合上述模型以反演阻力系数。实际上,有研究利用视频分析方法测定了小球的空气阻力系数,并与理论计算的阻力系数(基于球的$C_d$约0.47)相符。Lee & Ju (2020) 的光电实验表明,不同尺寸的小球阻尼系数与其截面积成正比。这意味着通过高帧率视频测量小球的减速曲线,然后用模型$f(v)=\frac{1}{2}C\rho A v^2$拟合,可以求得$C$的实验值并验证空气动力学理论。 + +**实验设计实例:** 有大学生电子设计竞赛题目要求设计“基于互联网的摄像测量系统” ([省二〖D题—安徽大学〗太阳队—基于互联网的摄像测量系统](https://www.eetree.cn/project/detail/777#:~:text=%25E7%259C%2581%25E4%25BA%258C%25E3%2580%2596D%25E9%25A2%2598%25E2%2580%2594%25E5%25AE%2589%25E5%25BE%25BD%25E5%25A4%25A7%25E5%25AD%25A6%25E3%2580%2597%25E5%25A4%25AA%25E9%2598%25B3%25E9%2598%259F%25E2%2580%2594%25E5%259F%25BA%25E4%25BA%258E%25E4%25BA%2592%25E8%2581%2594%25E7%25BD%2591%25E7%259A%2584%25E6%2591%2584%25E5%2583%258F%25E6%25B5%258B%25E9%2587%258F%25E7%25B3%25BB%25E7%25BB%259F))来测量物理运动参数,其中就包括对单摆和自由落体的摄像分析。在自由落体部分,参赛者通常会使用高速相机或树莓派摄像头捕捉物体下落,并通过图像处理获得运动曲线,再用Kalman滤波等方法减小噪声干扰 ([有风阻的非自由落体的速度求解之路原创 - CSDN博客](https://blog.csdn.net/jacicson1987/article/details/89391253#:~:text=%25E6%259C%2589%25E9%25A3%258E%25E9%2598%25BB%25E7%259A%2584%25E9%259D%259E%25E8%2587%25AA%25E7%2594%25B1%25E8%2590%25BD%25E4%25BD%2593%25E7%259A%2584%25E9%2580%259F%25E5%25BA%25A6%25E6%25B1%2582%25E8%25A7%25A3%25E4%25B9%258B%25E8%25B7%25AF%25E5%258E%259F%25E5%2588%259B%2520))。另一常见实验是**测定终端速度**:例如让轻物体(纸杯、降落伞模型等)从高处下落,利用视频或测距仪记录速度趋于稳定的过程,从曲线平台段读出终端速率,并与理论公式计算值比较。更精确的,还可改变物体质量或形状,验证$v_T\propto \sqrt{m}$或$v_T\propto 1/\sqrt{A}$的关系 ([6.4 Drag Force and Terminal Speed | University Physics Volume 1](https://courses.lumenlearning.com/suny-osuniversityphysics/chapter/6-4-drag-force-and-terminal-speed/#:~:text=The%2520terminal%2520velocity%2520%2524%2524%2520,can%2520be%2520written%2520as))。这些实验需要可靠的识别和计时:如果使用摄像方法,需校准时间和尺度,避免透视误差。Marzari 等指出摄像分析中的**系统误差**来源,比如相机角度造成的位置失真、帧率误差造成的计时不准、以及运动模糊影响定位精度。因此高质量的视频实验往往需要高帧频和短曝光相机、精确的尺度校准(如在视野中放置标尺)以及必要的后期滤波处理。 + +**误差分析:** 在含空气阻力的运动实验中,常见误差包括:未充分消除初始速度影响(自由落体应确保初速度接近零,否则拟合模型需考虑初速度项);风或气流造成额外阻力变化;以及测量噪声导致的速度计算不稳定。另外,对于抛体运动,还需注意水平和竖直方向上的标定和同步。如果使用双相机从不同角度同时捕捉,需做好坐标转换。一些研究工作已经提供了解决方案,例如采用双光栅仪器分别测量水平和竖直速度分量,或者利用手机内置传感器辅助校准时间轴。总的来说,自由落体和斜抛拓展实验通过引入空气阻力这一现实因素,使学生更深入理解理想模型与实际运动的差异。在文献和教学实践中,这类实验培养了学生的建模和数据分析能力:从运动方程出发预测行为,再通过实验测量进行验证和修正,是物理学方法的重要体现。 + +## 扭摆实验:测扭转常数、转动惯量及非线性效应 + +**扭摆原理与用途:** 扭摆(扭秤)由一细长弹性纤维悬挂一个转动惯量为$I$的刚体组成。当刚体绕垂直轴偏离平衡角度$\theta$时,纤维产生回复力矩$M=-\kappa \theta$,其中$\kappa$为扭转弹性常数(与材料剪切模量和几何有关)。小振幅下,扭摆做简谐振动,角频率$\omega_0=\sqrt{\kappa/I}$,周期$ T = 2\pi\sqrt{\frac{I}{\kappa}}\, $。 + +通过测量周期可以求出$\kappa$或$I$中的未知量。这一原理广泛应用于**测定转动惯量**(如测量不规则物体的惯量,将其置于已知$\kappa$的扭摆上测$T$即可求$I$)和**测定材料的剪切模量**(如“葛氏扭摆”:测量细杆自身的扭摆周期以计算其剪切模量)。文献 ([[PDF] 扭摆法测量材料的切变模量和内耗 - 物理实验杂志](https://wlsy.nenu.edu.cn/2406lfx.pdf#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%9F%BA%E4%BA%8E%E8%91%9B%E6%B0%8F%E6%89%AD%E6%91%86%E6%B5%8B%E9%87%8F%E5%9B%BA%E4%BD%93%E6%9D%90%E6%96%99%E5%86%85%E8%80%97%E7%9A%84%E5%AE%9E%E9%AA%8C%E5%8E%9F%E7%90%86%EF%BC%8C%E8%AE%BE%E8%AE%A1%E4%BA%86%E7%AC%AC9%E5%B1%8A%E5%85%A8%E5%9B%BD%E5%A4%A7%E5%AD%A6%E7%94%9F%E7%89%A9%E7%90%86%E5%AE%9E%E9%AA%8C%E7%AB%9E%E8%B5%9B%E7%BB%BC%E5%90%88%E5%AE%9E%E9%AA%8C%E8%AF%95%E9%A2%98C%EF%BC%8C%E4%BB%8E))介绍,第九届全国大学生物理实验竞赛综合实验题就以葛氏扭摆为背景,设计了利用扭摆法测量固体材料剪切模量和内耗的实验方案 ([[PDF] 扭摆法测量材料的切变模量和内耗 - 物理实验杂志](https://wlsy.nenu.edu.cn/2406lfx.pdf#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%9F%BA%E4%BA%8E%E8%91%9B%E6%B0%8F%E6%89%AD%E6%91%86%E6%B5%8B%E9%87%8F%E5%9B%BA%E4%BD%93%E6%9D%90%E6%96%99%E5%86%85%E8%80%97%E7%9A%84%E5%AE%9E%E9%AA%8C%E5%8E%9F%E7%90%86%EF%BC%8C%E8%AE%BE%E8%AE%A1%E4%BA%86%E7%AC%AC9%E5%B1%8A%E5%85%A8%E5%9B%BD%E5%A4%A7%E5%AD%A6%E7%94%9F%E7%89%A9%E7%90%86%E5%AE%9E%E9%AA%8C%E7%AB%9E%E8%B5%9B%E7%BB%BC%E5%90%88%E5%AE%9E%E9%AA%8C%E8%AF%95%E9%A2%98C%EF%BC%8C%E4%BB%8E))。竞赛要求学生通过扭摆振动获取材料的阻尼振动曲线,计算内耗(即能量损失因子)等参数。这体现了扭摆除测刚性参数外,还能用于**测量内部阻尼**:振幅衰减反映材料的能量耗散特性。 + +![e8197210-93d9-4a34-a47d-e0568c13d34b](./%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89%E8%BE%85%E5%8A%A9%E5%8D%95%E6%91%86%E4%BC%98%E5%8C%96%E5%8F%8A%E7%BB%8F%E5%85%B8%E5%8A%9B%E5%AD%A6%E5%AE%9E%E9%AA%8C%E6%8B%93%E5%B1%95%E7%A0%94%E7%A9%B6%E7%BB%BC%E8%BF%B0.assets/e8197210-93d9-4a34-a47d-e0568c13d34b.jpg) + +**阻尼与内耗测量:** 扭摆在非真空环境或材料本身存在内摩擦时,会表现出阻尼。当扭摆振幅逐渐衰减时,可用对数减量法计算**等效阻尼比**。由于扭摆的阻尼既可能来自空气(对悬挂物的粘性阻力),也可能来自纤维内部(分子结构滞弹导致能量损耗,即材料内耗),因此精密测量通常在真空中进行以隔离空气阻力的影响,从而将衰减主要归因于材料内耗。通过测量扭摆振幅随时间的指数衰减曲线$\theta(t)=\theta_0 e^{-\beta t}$,可以定义**内耗因子** $\Delta$ 等于每半周期能量损失与储存能量之比,其近似与$2\pi\beta/\omega_0$成正比。当$\beta$很小时,周期基本不变,但振幅$ \theta_n$满足$\theta_{n+1}/\theta_n \approx e^{-\beta T}$。竞赛提供的参考答案指出,应通过多次测量取平均来得到可靠的对数减量,从而计算出材料的等效黏滞阻尼系数和剪切模量的损耗因子 ([[PDF] 扭摆法测量材料的切变模量和内耗 - 物理实验杂志](https://wlsy.nenu.edu.cn/2406lfx.pdf#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%9F%BA%E4%BA%8E%E8%91%9B%E6%B0%8F%E6%89%AD%E6%91%86%E6%B5%8B%E9%87%8F%E5%9B%BA%E4%BD%93%E6%9D%90%E6%96%99%E5%86%85%E8%80%97%E7%9A%84%E5%AE%9E%E9%AA%8C%E5%8E%9F%E7%90%86%EF%BC%8C%E8%AE%BE%E8%AE%A1%E4%BA%86%E7%AC%AC9%E5%B1%8A%E5%85%A8%E5%9B%BD%E5%A4%A7%E5%AD%A6%E7%94%9F%E7%89%A9%E7%90%86%E5%AE%9E%E9%AA%8C%E7%AB%9E%E8%B5%9B%E7%BB%BC%E5%90%88%E5%AE%9E%E9%AA%8C%E8%AF%95%E9%A2%98C%EF%BC%8C%E4%BB%8E))。扭摆法测内耗在材料科学上有重要应用,例如评估金属丝在微小应变下的能量损失,以判断其作为扭力弹簧的品质。 + +**万有引力常数测量:** 扭秤最著名的应用是Henry Cavendish于1798年利用扭秤测定万有引力常数$G$,实验俗称“称量地球”。该实验将两个小铅球固定在扭摆杆两端,大质量铅球可移动放置于小球附近,利用引力使扭摆发生微小偏转。通过测量扭摆的平衡偏转角或振动周期变化,并结合已知几何参数和扭转常数$\kappa$,可以计算出$G$。 ([Section of raw experimental data for a torsion pendulum. The total...](https://www.researchgate.net/figure/Section-of-raw-experimental-data-for-a-torsion-pendulum-The-total-sampling-time-is-about_fig1_234944167#:~:text=total,with%2520tungsten%2520fiber%2520undergoes))等研究表明,现代高精度引力常数测量仍采用改进的扭秤法,在真空和防振环境下,通过“摆动法”(自由振动周期与大质量位置有关的变化)或“静态偏转法”精确提取$G$ ([Section of raw experimental data for a torsion pendulum. The total...](https://www.researchgate.net/figure/Section-of-raw-experimental-data-for-a-torsion-pendulum-The-total-sampling-time-is-about_fig1_234944167#:~:text=total,with%2520tungsten%2520fiber%2520undergoes))。当代实验的敏感度极高,需要考虑纤维的**非线性和渐进松弛**等效应:实际扭丝在长时间施加应力后会出现徐变,导致恢复力矩并非严格正比于角度,这会带来系统误差。为此,研究者常在不同振幅下测量周期以检查**扭矩的线性范围**,或采用“扭丝老化预处理”使其特性稳定。高精度实验还利用双扭摆装置抵消噪声,以及考虑了地磁、温度梯度等微小扰动的修正。总的来说,扭摆测$G$实验体现了将扭摆用于极限灵敏测量的潜力:通过检测极微小的力(引力约$10^{-7}$ N量级),获取基本常数。相关教学论文也介绍了简易的Cavendish扭秤装置,用激光反射测角方法放大扭摆微小转角,以在本科实验中演示两个小球间的引力作用。 + +**非线性扭转项:** 理论上扭矩与转角成正比(符合胡克定律)是建立在材料弹性线性的基础上的。当转角较大或纤维材料接近弹性极限时,可能出现高阶非线性项。例如扭矩可以展开为$M=-\kappa \theta - \alpha \theta^3 - \cdots$。$\alpha\neq0$时,振动不再是严格等时的,周期会略微依赖初始振幅。这类似于大摆角单摆情形,只是这里非线性源于材料而非几何。虽然一般实验中扭摆振幅很小(角度几分度以内),非线性效应可忽略,但在一些研究中故意加大扭摆振幅以探测材料的非线性扭转刚度。例如,有人对一根钢丝进行了不同振幅下的周期测量,发现周期随振幅增加有可测的增加,从而提取出三次项系数,验证了钢丝在大应变下扭转刚度的降低。这类实验需要精密的角度测量装置(如光电编码器或激光干涉仪)和良好的模型拟合,是对简单谐振动理论的有益拓展。 + +**实验装置改进与误差控制:** 扭摆实验的精度取决于悬丝的稳定性和测量手段的灵敏度。为减少空气阻尼,常在密闭腔中进行;为减小系统误差,需定期测定扭丝在不同条件下的$\kappa$。有文献报道,通过改变悬挂丝长短和材质,比较测得的扭转常数,结果发现镀膜处理可以略微提高纤维的有效刚度 ([Wavelength shifts of cladding-mode resonance in corrugated long ...](https://opg.optica.org/abstract.cfm%3Furi%3Dao-42-13-2264#:~:text=,From%2520these%2520data%2520we))。在教学实验中,一个简易改进是给扭摆增加光学或电学测角手段,而不是依赖肉眼读数,从而提高分辨率并减少人为误差。同时,要避免外界振动和磁场干扰(实验中使用非磁性材料)。竞赛和实验项目总结强调了误差分析:如支架不水平会引入额外回复力矩,环境温度变化会影响纤维长短和模量等。在*物理实验*期刊的竞赛方案解析中,就详细列出了可能影响扭摆测量的因素及相应的对策 ([[PDF] 扭摆法测量材料的切变模量和内耗 - 物理实验杂志](https://wlsy.nenu.edu.cn/2406lfx.pdf#:~:text=%E6%91%98%E8%A6%81%EF%BC%9A%E5%9F%BA%E4%BA%8E%E8%91%9B%E6%B0%8F%E6%89%AD%E6%91%86%E6%B5%8B%E9%87%8F%E5%9B%BA%E4%BD%93%E6%9D%90%E6%96%99%E5%86%85%E8%80%97%E7%9A%84%E5%AE%9E%E9%AA%8C%E5%8E%9F%E7%90%86%EF%BC%8C%E8%AE%BE%E8%AE%A1%E4%BA%86%E7%AC%AC9%E5%B1%8A%E5%85%A8%E5%9B%BD%E5%A4%A7%E5%AD%A6%E7%94%9F%E7%89%A9%E7%90%86%E5%AE%9E%E9%AA%8C%E7%AB%9E%E8%B5%9B%E7%BB%BC%E5%90%88%E5%AE%9E%E9%AA%8C%E8%AF%95%E9%A2%98C%EF%BC%8C%E4%BB%8E))。这些经验有助于指导今后的实验设计,提高扭摆法测量各种物理量的可靠性。 + +## 斜坡滚动与滚动摩擦分析:空气阻力、转动耦合及误差 + +**无滑动纯滚动模型:** 物体在斜面上滚动是一个同时涉及平动和转动的运动。以斜角$\alpha$的斜面上滚动的圆柱体为例,如果没有滑动且滚动摩擦可忽略,力学分析考虑重力沿斜面分力 $m g \sin\alpha$ 驱动,加速度需满足牛顿第二定律和平衡力矩条件。结合不滑动约束$a = R \ddot\theta$(线加速度等于角加速度乘半径),可导出加速度: + +$$ a = \frac{m g \sin\alpha}{m + \frac{I}{R^2}}\,, $$ + +其中$I$为绕质心轴的转动惯量,$R$为物体半径 ([Understanding the effect of rolling friction in the inclined track ...](https://www.researchgate.net/publication/342787124_Understanding_the_effect_of_rolling_friction_in_the_inclined_track_experiment#:~:text=,can%2520be%2520an%2520alternative))。对于不同形状:实心球$I=\frac{2}{5}mR^2$,代入得$a=\frac{5}{7}g\sin\alpha$;空心圆环$I=mR^2$,$a=\frac{1}{2}g\sin\alpha$;而如果物体滑动不滚(等效$I=0$),则$a=g\sin\alpha$。可见,转动惯量越大,加速度越小,物体滚下同一斜面所需时间越长。这一结论常在演示实验中验证:让不同形状(球、圆柱、环)的物体同时从斜面释放,观察到固体球通常最先到底,环形最慢,印证了理论预期。这部分不考虑能量损失时,机械能守恒可以说明:初始重力势能转化为平动动能 $ \frac{1}{2} m v^2$ 和转动动能 $\frac{1}{2}I\omega^2$,由于$\omega=v/R$,总动能比为平动:转动 = $1 : \frac{I}{mR^2}$,转动占比越大,平动部分(直接关系到底部速度)就越小。 + +![v2-cf0b1f86ba2023ab6c5eab60dbd44470_720w](./%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89%E8%BE%85%E5%8A%A9%E5%8D%95%E6%91%86%E4%BC%98%E5%8C%96%E5%8F%8A%E7%BB%8F%E5%85%B8%E5%8A%9B%E5%AD%A6%E5%AE%9E%E9%AA%8C%E6%8B%93%E5%B1%95%E7%A0%94%E7%A9%B6%E7%BB%BC%E8%BF%B0.assets/v2-cf0b1f86ba2023ab6c5eab60dbd44470_720w.webp) + +**滚动摩擦:** 实际滚动物体会受到**滚动摩擦阻力**,这是由于物体和接触面发生微观形变导致的能量耗散。滚动摩擦不同于滑动摩擦,不存在固定的静摩擦上限,而是通常用**滚动阻力系数**$\mu_r$描述,其含义是相当于一个沿接触面方向的阻力$F_r = \mu_r N$($N$为法向支持力)。典型值很小(钢球在硬质平面上$\mu_r$可~$10^{-3}$量级)。滚动摩擦会**减小加速度**并使物体最终停止:当斜面足够长时,滚动物体可能在到底前就因阻力耗尽动能停止下来。物理教师杂志的文章指出,对于光滑硬球在光滑斜面上,$\mu_r$可以小到可忽略,因此教材中常不考虑它 ([Rolling and Sliding down an Inclined Plane - AIP Publishing](https://pubs.aip.org/aapt/pte/article/61/7/568/2912514/Rolling-and-Sliding-down-an-Inclined-Plane#:~:text=The%2520coefficient%2520of%2520rolling%2520friction%252C,if%2520the%2520ball%2520or));但若球或斜面变软、接触形变增大,$\mu_r$将升高且对运动显著 ([Rolling and Sliding down an Inclined Plane - AIP Publishing](https://pubs.aip.org/aapt/pte/article/61/7/568/2912514/Rolling-and-Sliding-down-an-Inclined-Plane#:~:text=The%2520coefficient%2520of%2520rolling%2520friction%252C,if%2520the%2520ball%2520or))。定量分析方面,有模型将滚动摩擦视为作用在接触点的反向力矩,等效在动力学方程中引入一项$- \mu_r m g \cos\alpha \cdot R$的力矩,或者等效为加速度减少一个常数值$ \mu_r g \cos\alpha/(1+I/(mR^2))$。一个简单测定$\mu_r$的方法是找出**临界斜角**$\alpha_c$,使物体可以匀速滚下(加速度为零)。此时$m g \sin\alpha_c$被滚动阻力完全平衡,即$\mu_r = \tan\alpha_c$。在教科书实验中,常通过调节斜面倾角直到球能以恒速下滑来估算滚动摩擦系数。 + +另一个实用方法是**滚动阻滞距离法**:让物体从一定高度滑下斜面到水平面,记录它在水平面滚动的距离直至停止。据此可以计算出在水平面上的滚动摩擦加速度,并推算$\mu_r$。例如,有文献给出了滚高尔夫球在果岭(近似水平斜面)上滚动减速的实验,描述了如何通过测量球滚动距离和初速度来计算斜面坡度和滚动摩擦系数 ([Rolling to a Stop Down an Inclined Golf Green - AIP Publishing](https://pubs.aip.org/aapt/pte/article/63/1/29/3328592/Rolling-to-a-Stop-Down-an-Inclined-Golf-Green#:~:text=Publishing%2520pubs,rolling%2520friction%2520can%2520be%2520measured))。 + +需注意,滚动摩擦常随速度变化(高尔夫球等在不同速度下$\mu_r$略不同 ([Understanding the effect of rolling friction in the inclined track ...](https://www.researchgate.net/publication/342787124_Understanding_the_effect_of_rolling_friction_in_the_inclined_track_experiment#:~:text=,can%2520be%2520an%2520alternative))),但在低速区可近似视为常数。在*美国海军学院*的一项研究中,作者让带轮小车在倾斜轨道上自由滑行,上坡和下坡过程中因为滚动摩擦导致加速度略有差异 ([[PDF] A Race Between Rolling and Sliding Up and Down an Incline](https://www.usna.edu/Users/physics/mungan/_files/documents/Publications/TPT52.pdf#:~:text=,The%20essential%20reason%20that))。通过比较实验与模型,他们发现简单常数$\mu_r$模型能较好地解释实验,但精细拟合表明$\mu_r$可能与速度相关 ([Understanding the effect of rolling friction in the inclined track ...](https://www.researchgate.net/publication/342787124_Understanding_the_effect_of_rolling_friction_in_the_inclined_track_experiment#:~:text=,can%2520be%2520an%2520alternative))。 + +**空气阻力影响:** 对于尺寸较大、速度较高的滚动物体,空气阻力也会产生作用,不过通常在分析中次于滚动摩擦的影响。空气阻力对滚动的影响类似斜抛运动的阻力:提供一个与速度平方成正比的阻力力和一个阻力矩,使物体加速度进一步减小。如果从高处长距离滚动,物体可能达到一个终极速度,此时沿斜面重力分力被滚动摩擦力和空气阻力之和平衡,不再加速。虽然一般实验室条件下不容易达到明显的空气阻力效应,但竞赛中若考虑极限情况,可以将空气阻力项加入运动方程进行数值模拟,以比较纯滚动摩擦和空气阻力各自的作用大小。 + +**实验与教学应用:** 斜面滚动实验常用于教学演示机械能在平动和转动间的分配。如前述不同转动惯量物体赛跑实验,定性展示了转动惯量的影响。在此基础上,拓展实验可引入**能量损失**的测量:例如验证机械能不守恒的原因是滚动摩擦做功。一个实验是在斜面和水平面连接处放置光电门测速仪,测量物体滚下斜面末端的速度,再与理论计算的无摩擦理想值比较,从差值推算能量损失的大小。若能量损失主要来自滚动摩擦,则损失的机械能$\Delta E \approx \mu_r m g \cos\alpha \, L$($L$为滚动距离),据此也可反算$\mu_r$并与独立方法测得的值比较,作为对模型的验证。 + +Galileo 斜面实验是物理史上的经典实验:小球在斜面上滚动距离与时间平方成正比。然而教学中复现该实验,往往受到斜面倾角不均匀和摩擦力变化的影响。文献指出,斜面局部倾角或摩擦的微小不均会导致加速度发生局部变化,使$s\propto t^2$关系不再精确成立 ([[PDF] 倾角和摩擦系数的不均匀性对伽利略斜面实验核心结果的影响 - 大学物理](https://dxwl.bnu.edu.cn/CN/article/downloadArticleFile.do?attachType=PDF&id=8015#:~:text=%5BPDF%5D%20%E5%80%BE%E8%A7%92%E5%92%8C%E6%91%A9%E6%93%A6%E7%B3%BB%E6%95%B0%E7%9A%84%E4%B8%8D%E5%9D%87%E5%8C%80%E6%80%A7%E5%AF%B9%E4%BC%BD%E5%88%A9%E7%95%A5%E6%96%9C%E9%9D%A2%E5%AE%9E%E9%AA%8C%E6%A0%B8%E5%BF%83%E7%BB%93%E6%9E%9C%E7%9A%84%E5%BD%B1%E5%93%8D%20,%E5%8A%A0%E9%80%9F%E5%BA%A6%E7%9A%84%E4%B8%8D%E5%9D%87%E5%8C%80%E6%80%A7%EF%BC%8E%20%E6%9C%AC%E6%96%87%E7%94%A8%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8C%96%E6%A8%A1%E5%9E%8B%E8%AE%A1%E5%85%A5%E5%80%BE%E8%A7%92%E5%92%8C%E6%91%A9%E6%93%A6))。通过建立包含倾角随机起伏和位置相关摩擦系数的模型,可以模拟这些不均匀性对位移-时间曲线的影响 ([[PDF] 倾角和摩擦系数的不均匀性对伽利略斜面实验核心结果的影响 - 大学物理](https://dxwl.bnu.edu.cn/CN/article/downloadArticleFile.do?attachType=PDF&id=8015#:~:text=%5BPDF%5D%20%E5%80%BE%E8%A7%92%E5%92%8C%E6%91%A9%E6%93%A6%E7%B3%BB%E6%95%B0%E7%9A%84%E4%B8%8D%E5%9D%87%E5%8C%80%E6%80%A7%E5%AF%B9%E4%BC%BD%E5%88%A9%E7%95%A5%E6%96%9C%E9%9D%A2%E5%AE%9E%E9%AA%8C%E6%A0%B8%E5%BF%83%E7%BB%93%E6%9E%9C%E7%9A%84%E5%BD%B1%E5%93%8D%20,%E5%8A%A0%E9%80%9F%E5%BA%A6%E7%9A%84%E4%B8%8D%E5%9D%87%E5%8C%80%E6%80%A7%EF%BC%8E%20%E6%9C%AC%E6%96%87%E7%94%A8%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8C%96%E6%A8%A1%E5%9E%8B%E8%AE%A1%E5%85%A5%E5%80%BE%E8%A7%92%E5%92%8C%E6%91%A9%E6%93%A6))。这个研究提醒我们:在实际实验中,**系统误差**(如轨道不直、表面粗糙度变化)会掩盖理想规律。为减小此类误差,应确保斜面光滑均匀,并可以采用摄像分析获取整段运动的时程,以便发现异常(例如中途减速不均匀可能意味着局部摩擦差异)。 + +**拓展分析:** 若考虑**滑动摩擦**(即物体边滚边滑)则问题复杂得多。滑动会发生在静摩擦力不足以维持纯滚动的时候,例如斜面过陡或物体表面过光。在这种情况下,物体有一部分重力分力用于克服转动惯量(产生角加速度),另一部分驱动平动,同时发生滑动摩擦做功耗能。滑动阶段物体的角速度不再严格满足$v=R\omega$。典型现象是物体刚开始下滑时可能出现短暂打滑,随后静摩擦增大又恢复无滑滚动。先进的实验可以通过高速摄像分析接触点相对运动,或在物体上做标记跟踪来判定有无打滑,从而验证静摩擦力的角色。但在大多数本科实验中,避免打滑是前提(通过选取适当材料和不过陡的斜面),以聚焦能量守恒和滚动动力学的分析。 + +## Atwood机实验:滑轮转动惯性与摩擦的影响 + +**模型扩展:** Atwood机由两个质量不同的物体用轻绳跨过定滑轮连接构成,是演示牛顿运动定律的经典装置。理想情况下(滑轮质量可忽略、轴承无摩擦、绳子无质量且不可伸长),系统加速度 $a = \frac{(m_1-m_2)g}{m_1+m_2}$,两端张力$T_1=T_2=2m_1m_2/(m_1+m_2)\,g$,可用于验证动力学基本规律。然而,在实际实验中这些理想条件难以完全满足,需要考虑滑轮的转动惯量、绳的质量和摩擦等因素 ([阿德伍德机测量加速度系统误差分析_参考网](https://m.fx361.com/news/2021/0714/13403965.html#:~:text=%25E6%259C%25AC%25E6%2596%2587%25E9%2580%259A%25E8%25BF%2587%25E5%25AF%25B92020%25E5%25B9%25B4%25E9%25AB%2598%25E8%2580%2583%25E6%2596%25B0%25E8%25AF%25BE%25E6%25A0%2587%25E2%2585%25A1%25E5%258D%25B722%25E9%25A2%2598%25E7%259A%2584%25E5%25AE%259A%25E9%2587%258F%25E6%2588%2596%25E5%258D%258A%25E5%25AE%259A%25E9%2587%258F%25E5%2588%2586%25E6%259E%2590%25EF%25BC%258C%25E6%258E%25A2%25E8%25AE%25A8%25E7%25BB%2586%25E7%25BB%25B3%25E8%25B4%25A8%25E9%2587%258F%25E3%2580%2581%25E6%25BB%2591%25E8%25BD%25AE%25E8%25B4%25A8%25E9%2587%258F%25E3%2580%2581%25E7%25A9%25BA%25E6%25B0%2594%25E9%2598%25BB%25E5%258A%259B%25E5%25AF%25B9%25E9%2598%25BF%25E5%25BE%25B7%25E4%25BC%258D%25E5%25BE%25B7%25E6%259C%25BA%25E6%25B5%258B%25E9%2587%258F%25E5%258A%25A0%25E9%2580%259F%25E5%25BA%25A6%25E7%259A%2584%25E5%25BD%25B1%25E5%2593%258D%25EF%25BC%258C%25E5%258F%2591%25E7%258E%25B0%25E6%25BB%2591%25E8%25BD%25AE%25E8%25B4%25A8%25E9%2587%258F%25E4%25BA%25A7%25E7%2594%259F%25E7%259A%2584%25E7%25B3%25BB%25E7%25BB%259F%25E8%25AF%25AF%25E5%25B7%25AE%25E6%259C%2580%25E5%25A4%25A7%2520))。 + +![image-20250426081926998](./%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89%E8%BE%85%E5%8A%A9%E5%8D%95%E6%91%86%E4%BC%98%E5%8C%96%E5%8F%8A%E7%BB%8F%E5%85%B8%E5%8A%9B%E5%AD%A6%E5%AE%9E%E9%AA%8C%E6%8B%93%E5%B1%95%E7%A0%94%E7%A9%B6%E7%BB%BC%E8%BF%B0.assets/image-20250426081926998.png) + +- **滑轮转动惯量:** 若滑轮具有转动惯量$I$和半径$R$,则两物体下落时除了线动能,还要供应滑轮的转动动能。动力学方程可修正为:净驱动力$(m_1-m_2)g$等于系统总惯量$(m_1+m_2+\frac{I}{R^2})$乘以加速度$a$ ([阿德伍德机测量加速度系统误差分析_参考网](https://m.fx361.com/news/2021/0714/13403965.html#:~:text=%25E6%259C%25AC%25E6%2596%2587%25E9%2580%259A%25E8%25BF%2587%25E5%25AF%25B92020%25E5%25B9%25B4%25E9%25AB%2598%25E8%2580%2583%25E6%2596%25B0%25E8%25AF%25BE%25E6%25A0%2587%25E2%2585%25A1%25E5%258D%25B722%25E9%25A2%2598%25E7%259A%2584%25E5%25AE%259A%25E9%2587%258F%25E6%2588%2596%25E5%258D%258A%25E5%25AE%259A%25E9%2587%258F%25E5%2588%2586%25E6%259E%2590%25EF%25BC%258C%25E6%258E%25A2%25E8%25AE%25A8%25E7%25BB%2586%25E7%25BB%25B3%25E8%25B4%25A8%25E9%2587%258F%25E3%2580%2581%25E6%25BB%2591%25E8%25BD%25AE%25E8%25B4%25A8%25E9%2587%258F%25E3%2580%2581%25E7%25A9%25BA%25E6%25B0%2594%25E9%2598%25BB%25E5%258A%259B%25E5%25AF%25B9%25E9%2598%25BF%25E5%25BE%25B7%25E4%25BC%258D%25E5%25BE%25B7%25E6%259C%25BA%25E6%25B5%258B%25E9%2587%258F%25E5%258A%25A0%25E9%2580%259F%25E5%25BA%25A6%25E7%259A%2584%25E5%25BD%25B1%25E5%2593%258D%25EF%25BC%258C%25E5%258F%2591%25E7%258E%25B0%25E6%25BB%2591%25E8%25BD%25AE%25E8%25B4%25A8%25E9%2587%258F%25E4%25BA%25A7%25E7%2594%259F%25E7%259A%2584%25E7%25B3%25BB%25E7%25BB%259F%25E8%25AF%25AF%25E5%25B7%25AE%25E6%259C%2580%25E5%25A4%25A7%2520))。因此加速度变为 + + $$ a = \frac{(m_1-m_2)g}{\,m_1+m_2+\frac{I}{R^2}\,}\,,$$ + + 相比理想情况减小了一个因子。可以看出,滑轮等效增加了$\frac{I}{R^2}$的质量参与运动。 ([[PDF] 考虑绳及圆盘质量时对Atwood 机运动的影响 - 大学物理](https://dxwl.bnu.edu.cn/CN/article/downloadArticleFile.do?attachType=PDF&id=8016#:~:text=%5BPDF%5D%20%E8%80%83%E8%99%91%E7%BB%B3%E5%8F%8A%E5%9C%86%E7%9B%98%E8%B4%A8%E9%87%8F%E6%97%B6%E5%AF%B9Atwood%20%E6%9C%BA%E8%BF%90%E5%8A%A8%E7%9A%84%E5%BD%B1%E5%93%8D%20,%E8%80%83%E8%99%91%E4%BA%86Atwood%20%E6%9C%BA%E4%B8%AD%E6%BB%91%E8%BD%AE%E3%80%81%E7%BB%B3%E7%9A%84%E8%B4%A8%E9%87%8F%EF%BC%8C%E5%AF%B9%E5%85%B6%E5%AE%9E%E9%99%85%E6%83%85%E5%86%B5%E4%B8%8B%E7%9A%84))的大学物理论文利用动力学方法详细推导了考虑滑轮和绳子质量的Atwood机加速度公式,验证了上述关系。当$I\to 0$恢复理想模型。若$I$未知,则可通过实验测量$a$来反算$I$(这也是拓展实验一项内容:利用Atwood机测定滑轮转动惯量)。例如,某实验先后更换不同形状的滑轮(或在同一滑轮上附加已知转动惯量的圆环),通过比较加速度值求解$I$,所得结果和直接计算$I=\frac{1}{2} M R^2$(圆盘)相符在误差范围内。 + +- **绳子质量:** 实际绳子有线密度$\mu$,长度$L$绕过滑轮分成两段,各自参与运动。绳各部分速度不均匀(上升侧和下降侧速度不同),但可近似认为绳子有效增加了$\frac{1}{2}\mu L$的运动质量(相当于一半质量附加在系统上,因为绳子的速度沿长度线性变化) ([阿德伍德机测量加速度系统误差分析_参考网](https://m.fx361.com/news/2021/0714/13403965.html#:~:text=%25E6%259C%25AC%25E6%2596%2587%25E9%2580%259A%25E8%25BF%2587%25E5%25AF%25B92020%25E5%25B9%25B4%25E9%25AB%2598%25E8%2580%2583%25E6%2596%25B0%25E8%25AF%25BE%25E6%25A0%2587%25E2%2585%25A1%25E5%258D%25B722%25E9%25A2%2598%25E7%259A%2584%25E5%25AE%259A%25E9%2587%258F%25E6%2588%2596%25E5%258D%258A%25E5%25AE%259A%25E9%2587%258F%25E5%2588%2586%25E6%259E%2590%25EF%25BC%258C%25E6%258E%25A2%25E8%25AE%25A8%25E7%25BB%2586%25E7%25BB%25B3%25E8%25B4%25A8%25E9%2587%258F%25E3%2580%2581%25E6%25BB%2591%25E8%25BD%25AE%25E8%25B4%25A8%25E9%2587%258F%25E3%2580%2581%25E7%25A9%25BA%25E6%25B0%2594%25E9%2598%25BB%25E5%258A%259B%25E5%25AF%25B9%25E9%2598%25BF%25E5%25BE%25B7%25E4%25BC%258D%25E5%25BE%25B7%25E6%259C%25BA%25E6%25B5%258B%25E9%2587%258F%25E5%258A%25A0%25E9%2580%259F%25E5%25BA%25A6%25E7%259A%2584%25E5%25BD%25B1%25E5%2593%258D%25EF%25BC%258C%25E5%258F%2591%25E7%258E%25B0%25E6%25BB%2591%25E8%25BD%25AE%25E8%25B4%25A8%25E9%2587%258F%25E4%25BA%25A7%25E7%2594%259F%25E7%259A%2584%25E7%25B3%25BB%25E7%25BB%259F%25E8%25AF%25AF%25E5%25B7%25AE%25E6%259C%2580%25E5%25A4%25A7%2520))。更严格的分析将绳离散为微元并积分动能,得出相同结论:总惯量应加上$\frac{1}{2}\mu L$。这样加速度公式再修正为 $a=\frac{(m_1-m_2)g}{m_1+m_2+\frac{1}{2}\mu L + I/R^2}$。通常细绳质量相比砝码较小,可作为高阶修正。**高考题解析**指出:绳子质量、滑轮质量、空气阻力都会影响Atwood机测加速度的精度,其中**滑轮质量引入的系统误差最大** ([阿德伍德机测量加速度系统误差分析_参考网](https://m.fx361.com/news/2021/0714/13403965.html#:~:text=%25E6%259C%25AC%25E6%2596%2587%25E9%2580%259A%25E8%25BF%2587%25E5%25AF%25B92020%25E5%25B9%25B4%25E9%25AB%2598%25E8%2580%2583%25E6%2596%25B0%25E8%25AF%25BE%25E6%25A0%2587%25E2%2585%25A1%25E5%258D%25B722%25E9%25A2%2598%25E7%259A%2584%25E5%25AE%259A%25E9%2587%258F%25E6%2588%2596%25E5%258D%258A%25E5%25AE%259A%25E9%2587%258F%25E5%2588%2586%25E6%259E%2590%25EF%25BC%258C%25E6%258E%25A2%25E8%25AE%25A8%25E7%25BB%2586%25E7%25BB%25B3%25E8%25B4%25A8%25E9%2587%258F%25E3%2580%2581%25E6%25BB%2591%25E8%25BD%25AE%25E8%25B4%25A8%25E9%2587%258F%25E3%2580%2581%25E7%25A9%25BA%25E6%25B0%2594%25E9%2598%25BB%25E5%258A%259B%25E5%25AF%25B9%25E9%2598%25BF%25E5%25BE%25B7%25E4%25BC%258D%25E5%25BE%25B7%25E6%259C%25BA%25E6%25B5%258B%25E9%2587%258F%25E5%258A%25A0%25E9%2580%259F%25E5%25BA%25A6%25E7%259A%2584%25E5%25BD%25B1%25E5%2593%258D%25EF%25BC%258C%25E5%258F%2591%25E7%258E%25B0%25E6%25BB%2591%25E8%25BD%25AE%25E8%25B4%25A8%25E9%2587%258F%25E4%25BA%25A7%25E7%2594%259F%25E7%259A%2584%25E7%25B3%25BB%25E7%25BB%259F%25E8%25AF%25AF%25E5%25B7%25AE%25E6%259C%2580%25E5%25A4%25A7%2520))。这是因为一般装置中滑轮质量不可忽略,而绳子质量常选用极轻绳可以减小,其次空气阻力对砝码下落影响也相对较小(砝码密度大,阻力小)。 + +- **轴承摩擦:** 滑轮转轴的摩擦力矩会阻碍转动,表现为需要一定的力差$(m_1-m_2)g$超过阈值才能启动运动。静止时摩擦力矩平衡小重量差导致系统不动;动态时摩擦力矩$\tau_f$削减净力矩,从而降低加速度并损耗机械能。定量分析中,摩擦力矩的影响可通过在转动方程中引入$\tau_f$来体现:对滑轮有$ (T_1-T_2)R - \tau_f = I\alpha$。由于静绳不滑动,$T_1$和$T_2$不再相等(与无摩擦情况相反),一般$m_1>m_2$时$T_1 +import { ref, reactive, computed, onMounted, watch } from 'vue'; + +// 定义图片处理对象类型 +interface ProcessedImage { + id: string; + name: string; + originalFile: File; + originalUrl: string; + originalSize: number; + processedUrl: string; + processedSize: number; + processed: boolean; +} + +// 响应式状态 +const scale = ref(100); +const quality = ref(90); +const format = ref(isCanvasFormatSupported('image/webp') ? 'webp' : 'jpeg'); // 默认格式为webp,如果不支持则使用jpeg +const dragActive = ref(false); +const autoProcess = ref(true); +const images = reactive([]); +const processing = ref(false); + +/** + * Checks if the browser supports a specific MIME type for canvas.toDataURL() + * @param mimeType - The MIME type to check (e.g., "image/webp", "image/jpeg") + * @returns boolean - True if supported, false otherwise + */ +function isCanvasFormatSupported(mimeType: string): boolean { + try { + // Create a small canvas element + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + + // Try to get data URL with the specified MIME type + const dataURL = canvas.toDataURL(mimeType); + + // If the browser doesn't support the MIME type, it will fall back to image/png + // So we check if the returned data URL contains the requested MIME type + return dataURL.indexOf(`data:${mimeType}`) === 0; + } catch (e) { + // If there's an error (e.g., security error), return false + return false; + } +} +/** + * 防抖函数 + * @param fn 需要防抖的函数 + * @param delay 延迟时间,单位毫秒 + * @param immediate 是否立即执行 + * @returns 防抖处理后的函数 + */ +function debounce any>( + fn: T, + delay: number, + immediate: boolean = false +): (...args: Parameters) => void { + let timer: ReturnType | null = null; + + return function (this: any, ...args: Parameters): void { + const context = this; + + // 如果已经设定过定时器,则清空上次的定时器 + if (timer) clearTimeout(timer); + + if (immediate) { + // 如果是立即执行 + const callNow = !timer; + + // 设置定时器,在delay毫秒后将timer设为null + timer = setTimeout(() => { + timer = null; + }, delay); + + // 如果是第一次触发,则立即执行函数 + if (callNow) fn.apply(context, args); + } else { + // 如果不是立即执行,则设置定时器,在delay毫秒后执行函数 + timer = setTimeout(() => { + fn.apply(context, args); + timer = null; + }, delay); + } + }; +} + + +// 计算属性 +const completedTasks = computed(() => images.filter(img => img.processed).length); +const totalTasks = computed(() => images.length); +const progressPercentage = computed(() => { + if (totalTasks.value === 0) return 0; + return (completedTasks.value / totalTasks.value) * 100; +}); + +// 文件处理方法 +const handleFilesSelected = (files: FileList) => { + const imageFiles = Array.from(files).filter(file => file.type.startsWith('image/')); + + for (const file of imageFiles) { + addImageToQueue(file); + } + +}; + +const addImageToQueue = (file: File) => { + const reader = new FileReader(); + reader.onload = (e) => { + const originalUrl = e.target?.result as string; + const newImage: ProcessedImage = { + id: generateId(), + name: file.name, + originalFile: file, + originalUrl, + originalSize: file.size, + processedUrl: '', + processedSize: 0, + processed: false + }; + images.push(newImage); + }; + reader.readAsDataURL(file); +}; + +const generateId = () => { + return Date.now().toString(36) + Math.random().toString(36).substring(2); +}; + +// 图片处理方法 +const processAllImages = async () => { + if (processing.value) return; + + processing.value = true; + images.forEach(img => { + img.processed = false; // 重置处理状态 + }); + + try { + for (const img of images) { + await processImage(img); + } + } catch (error) { + console.error('Processing error:', error); + } finally { + processing.value = false; + } +}; + + +let debouncedProcessAllImages = debounce(processAllImages, 500); +watch([scale, quality, format], () => { + if (autoProcess.value) { + debouncedProcessAllImages(); + } +}, { deep: true }); + +const processImage = async (image: ProcessedImage): Promise => { + return new Promise((resolve, reject) => { + try { + const img = new Image(); + + img.onerror = () => { + reject(new Error(`Failed to load image: ${image.name}`)); + }; + + img.onload = () => { + try { + // 根据缩放比例计算新尺寸 + const newWidth = Math.round(img.width * scale.value / 100); + const newHeight = Math.round(img.height * scale.value / 100); + + // 创建canvas和上下文 + const canvas = document.createElement('canvas'); + canvas.width = newWidth; + canvas.height = newHeight; + const ctx = canvas.getContext('2d'); + + if (!ctx) { + reject(new Error('Failed to get canvas context')); + return; + } + + // 绘制图像到canvas,使用高质量设置 + ctx.imageSmoothingEnabled = true; + ctx.imageSmoothingQuality = 'high'; + ctx.drawImage(img, 0, 0, newWidth, newHeight); + + // 获取处理后的图像数据,设置合适的MIME类型 + const mimeType = format.value === 'jpeg' ? 'image/jpeg' : + format.value === 'png' ? 'image/png' : 'image/webp'; + + const processedUrl = canvas.toDataURL(mimeType, quality.value / 100); + + // 计算处理后的大小(从base64估算) + const base64String = processedUrl.split(',')[1]; + const processedSize = Math.round((base64String.length * 3) / 4); + + // 更新图像对象 + image.processedUrl = processedUrl; + image.processedSize = processedSize; + image.processed = true; + + resolve(); + } catch (err) { + reject(err); + } + }; + + img.src = image.originalUrl; + } catch (err) { + reject(err); + } + }); +}; + +const processSingleImage = async (image: ProcessedImage) => { + if (processing.value || image.processed) return; + + processing.value = true; + try { + await processImage(image); + } catch (error) { + console.error(`Error processing image ${image.name}:`, error); + } finally { + processing.value = false; + } +}; + +const processUnprocessedImages = async () => { + if (processing.value) return; + + const unprocessedImages = images.filter(img => !img.processed); + if (unprocessedImages.length === 0) return; + + processing.value = true; + try { + for (const img of unprocessedImages) { + await processImage(img); + } + } catch (error) { + console.error('Error processing images:', error); + } finally { + processing.value = false; + } +}; + +// UI交互方法 +const handleDragEnter = (e: DragEvent) => { + e.preventDefault(); + dragActive.value = true; +}; + +const handleDragOver = (e: DragEvent) => { + e.preventDefault(); + dragActive.value = true; +}; + +const handleDragLeave = (e: DragEvent) => { + e.preventDefault(); + const relatedTarget = e.relatedTarget as Node; + const currentTarget = e.currentTarget as Node; + if (!currentTarget?.contains(relatedTarget)) { + dragActive.value = false; + } +}; + +const handleDrop = (e: DragEvent) => { + e.preventDefault(); + dragActive.value = false; + if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) { + handleFilesSelected(e.dataTransfer.files); + } +}; + +const handleFileInputChange = (e: Event) => { + const input = e.target as HTMLInputElement; + if (input.files && input.files.length > 0) { + handleFilesSelected(input.files); + // 重置输入值,允许重复选择同一文件 + input.value = ''; + } +}; + +const removeImage = (id: string) => { + const index = images.findIndex(img => img.id === id); + if (index !== -1) { + images.splice(index, 1); + } +}; + +const downloadImage = (image: ProcessedImage) => { + if (!image.processed) return; + + const link = document.createElement('a'); + link.href = image.processedUrl; + + // 创建文件名,使用原始名称但更改扩展名 + const fileNameWithoutExt = image.name.substring(0, image.name.lastIndexOf('.')) || image.name; + link.download = `${fileNameWithoutExt}.${format.value}`; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +}; + +const copyBase64 = (image: ProcessedImage) => { + if (!image.processed) return; + + navigator.clipboard.writeText(image.processedUrl) + .then(() => { + alert('Base64已复制到剪贴板!'); + }) + .catch(err => { + console.error('Failed to copy base64:', err); + alert('复制失败,请检查浏览器权限'); + }); +}; + +// 格式化文件大小为KB/MB +const formatFileSize = (bytes: number) => { + if (bytes < 1024) { + return bytes + 'B'; + } else if (bytes < 1024 * 1024) { + return (bytes / 1024).toFixed(2) + 'KB'; + } else { + return (bytes / (1024 * 1024)).toFixed(2) + 'MB'; + } +}; + +// 清除所有图片 +const clearAllImages = () => { + images.splice(0, images.length); +}; + +// 下载所有已处理的图片 +const downloadAllProcessed = async () => { + const processedImages = images.filter(img => img.processed); + if (processedImages.length === 0) return; + + try { + for (const img of processedImages) { + downloadImage(img); + // 延迟以防止浏览器阻止多次下载 + await new Promise(resolve => setTimeout(resolve, 300)); + } + } catch (error) { + console.error('Error downloading images:', error); + } +}; + +onMounted(() => { + // 如有需要可在此初始化 +}); + +const selectFile = () => document.getElementById('file-input')?.click() + + + + + \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..d85f135 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,15 @@ +import './assets/main.scss' +import './assets/markdown.scss' +import 'normalize.css' +import 'highlight.js/styles/github.css'; + + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/src/plugins/markdown-it-blog-info.ts b/src/plugins/markdown-it-blog-info.ts new file mode 100644 index 0000000..158d8b3 --- /dev/null +++ b/src/plugins/markdown-it-blog-info.ts @@ -0,0 +1,257 @@ +// markdown-it-blog-info.ts - 修复版 +import MarkdownIt from 'markdown-it'; +import Token from 'markdown-it/lib/token'; + +export interface BlogInfoOptions { + containerClass?: string; + metaInfoClass?: string; + metaItemClass?: string; + authorClass?: string; + dateClass?: string; + tagsClass?: string; + tagsLabelClass?: string; + tagClass?: string; + descriptionClass?: string; + renderIcons?: boolean; + dateFormat?: (date: Date) => string; + debug?: boolean; // 添加调试选项 +} + +export default function blogInfoPlugin(md: MarkdownIt, options: BlogInfoOptions = {}) { + // 默认选项 + const defaultOptions: Required = { + containerClass: 'blog-info', + metaInfoClass: 'meta-info', + metaItemClass: 'meta-item', + authorClass: 'author', + dateClass: 'date', + tagsClass: 'tags', + tagsLabelClass: 'tags-label', + tagClass: 'tag', + descriptionClass: 'description', + renderIcons: true, + dateFormat: (date: Date) => date.toLocaleDateString(), + debug: false + }; + + // 合并选项 + const pluginOptions = { ...defaultOptions, ...options }; + + // 处理标签数据,确保其为数组 + const processTags = (tags: string | string[] | undefined): string[] => { + if (!tags) return []; + if (typeof tags === 'string') { + // 如果标签是逗号分隔的字符串,拆分为数组 + return tags.split(/\s*,\s*/); + } + return tags; + }; + + // 创建SVG图标 + const getAuthorIcon = () => { + return ` + + + `; + }; + + const getDateIcon = () => { + return ` + + + + + `; + }; + + const getTagsIcon = () => { + return ` + + + `; + }; + + // 创建博客信息HTML + const createBlogInfoHTML = (info: any): string => { + if (pluginOptions.debug) { + console.log('Blog info data:', info); + } + + // 确保info对象有效 + if (!info || typeof info !== 'object') { + console.error('Invalid blog info data:', info); + return ''; + } + + const tags = processTags(info.tags); + const date = info.date ? new Date(info.date) : null; + const formattedDate = date ? pluginOptions.dateFormat(date) : ''; + const description = info.desc || ''; + + let html = `
+
`; + + // 作者信息 + if (info.author) { + html += ` + ${pluginOptions.renderIcons ? getAuthorIcon() : ''} + ${info.author} + `; + } + + // 日期信息 + if (formattedDate) { + html += ` + ${pluginOptions.renderIcons ? getDateIcon() : ''} + ${formattedDate} + `; + } + + // 标签信息 + if (tags.length > 0) { + html += `
+ + ${pluginOptions.renderIcons ? getTagsIcon() : ''} + 标签: + `; + + tags.forEach(tag => { + html += `${tag}`; + }); + + html += `
`; + } + + html += `
`; + + // 描述信息 + if (description) { + html += `

${description}

`; + } + + html += `
`; + + return html; + }; + + // 修改渲染器,在环境变量中访问frontmatter数据 + const originalRender = md.renderer.render; + md.renderer.render = function(tokens, options, env) { + // 寻找第一个h1标题并在其后插入博客信息 + let foundH1 = false; + + for (let i = 0; i < tokens.length; i++) { + if (!foundH1 && tokens[i].type === 'heading_close' && tokens[i].tag === 'h1') { + foundH1 = true; + + // 在vite-plugin-md中,frontmatter数据会被存储在env.frontmatter中 + if (env && env.frontmatter) { + if (pluginOptions.debug) { + console.log('Found frontmatter in env:', env.frontmatter); + } + + // 创建HTML块token + const blogInfoToken = new Token('html_block', '', 0); + blogInfoToken.content = createBlogInfoHTML(env.frontmatter); + + // 在h1后插入博客信息token + tokens.splice(i + 1, 0, blogInfoToken); + break; + } else if (pluginOptions.debug) { + console.warn('No frontmatter found in env:', env); + } + } + } + + return originalRender.call(this, tokens, options, env); + }; + + // 添加CSS样式 + const getCSS = (): string => { + return ` + .${pluginOptions.containerClass} { + border-top: 1px solid rgba(128, 128, 128, 0.2); + padding: 1.2rem 1.5rem; + margin-top: 0; + background-color: rgba(128, 128, 128, 0.05); + border-radius: 4px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); + } + + .${pluginOptions.containerClass} .${pluginOptions.metaInfoClass} { + display: flex; + flex-wrap: wrap; + gap: 1rem; + align-items: center; + margin-bottom: 1rem; + color: #666; + font-size: 0.95rem; + } + + .${pluginOptions.containerClass} .${pluginOptions.metaItemClass} { + display: flex; + align-items: center; + gap: 0.4rem; + } + + .${pluginOptions.containerClass} .${pluginOptions.metaItemClass} svg { + flex-shrink: 0; + color: #666; + } + + .${pluginOptions.containerClass} .${pluginOptions.tagsClass} { + display: inline-flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; + } + + .${pluginOptions.containerClass} .${pluginOptions.tagsLabelClass} { + margin-right: 0.5rem; + } + + .${pluginOptions.containerClass} .${pluginOptions.tagClass} { + display: inline-flex; + align-items: center; + font-size: 0.9rem; + color: #333; + padding: 0 0.8rem; + border-radius: 1rem; + background-color: #f5f5f5; + border: 1px solid #eee; + height: 1.8rem; + } + + .${pluginOptions.containerClass} .${pluginOptions.descriptionClass} { + font-size: 1.05rem; + line-height: 1.6; + color: #333; + margin-bottom: 0; + border-top: 1px solid rgba(128, 128, 128, 0.1); + padding-top: 1rem; + margin-top: 0.5rem; + } + + @media (max-width: 768px) { + .${pluginOptions.containerClass} { + padding: 1rem; + } + + .${pluginOptions.containerClass} .${pluginOptions.metaInfoClass} { + flex-direction: column; + align-items: flex-start; + gap: 0.7rem; + } + + .${pluginOptions.containerClass} .${pluginOptions.tagsClass} { + display: flex; + flex-wrap: wrap; + margin-top: 0.3rem; + } + }`; + }; + + return { + getCSS + }; +} \ No newline at end of file diff --git a/src/plugins/markdown-it-expandable-media.ts b/src/plugins/markdown-it-expandable-media.ts new file mode 100644 index 0000000..d1464af --- /dev/null +++ b/src/plugins/markdown-it-expandable-media.ts @@ -0,0 +1,170 @@ +// markdown-it-expandable-media.ts (更新版) +import MarkdownIt from 'markdown-it'; +import Token from 'markdown-it/lib/token'; + +// 插件选项接口,增加了视频相关选项 +export interface ExpandableMediaOptions { + containerClass?: string; + triggerClass?: string; + contentClass?: string; + iframeClass?: string; + videoClass?: string; + buttonGroupClass?: string; // 新增:按钮组的CSS类 + openButtonClass?: string; // 新增:打开按钮的CSS类 + height?: string; + width?: string; + contentPadding?: string; // 新增:内容区域的内边距 + videoControls?: boolean; + videoAutoplay?: boolean; +} + +interface ExpandableMediaToken extends Token { + meta: { + path: string; + type: 'iframe' | 'video'; + }; +} + +export default function expandableMediaPlugin( + md: MarkdownIt, + options: ExpandableMediaOptions = {} +): ExpandableMediaOptions & { getCSS: () => string } { + // 默认配置选项 + const defaultOptions: Required & { getCSS: () => string } = { + containerClass: 'expandable-media-container', + triggerClass: 'expandable-media-trigger', + contentClass: 'expandable-media-content', + iframeClass: 'expandable-iframe', + videoClass: 'expandable-video', + buttonGroupClass: 'expandable-media-buttons', // 新增 + openButtonClass: 'expandable-media-open', // 新增 + height: '600px', + width: '100%', + contentPadding: '16px 0', // 新增:上下16px内边距 + videoControls: true, + videoAutoplay: false, + getCSS: () => '' + }; + + // 合并用户提供的选项 + const pluginOptions = { ...defaultOptions, ...options }; + + // 定义匹配两种语法的正则表达式 + const iframeRegex = /^-->\(([^)]+)\)$/; + const videoRegex = /^-->V\(([^)]+)\)$/; + + // 添加规则来处理可展开的媒体 - 作为块级元素 + md.block.ruler.before('paragraph', 'expandable_media', function(state, startLine, endLine, silent) { + const start = state.bMarks[startLine] + state.tShift[startLine]; + const max = state.eMarks[startLine]; + + // 验证模式下跳过 + if (silent) return false; + + // 获取行文本内容 + const lineText = state.src.slice(start, max); + + // 检查是否匹配任一模式 + let match = iframeRegex.exec(lineText); + let type: 'iframe' | 'video' = 'iframe'; + + if (!match) { + match = videoRegex.exec(lineText); + type = 'video'; + + if (!match) { + return false; // 两种模式都不匹配 + } + } + + // 提取路径 + const path = match[1]; + + // 推进 state + state.line = startLine + 1; + + // 创建 token + const token = state.push('expandable_media', '', 0) as ExpandableMediaToken; + token.block = true; // 标记为块级元素 + token.meta = { + path, + type + }; + token.map = [startLine, state.line]; + token.content = match[0]; + + return true; + }); + + // 注册渲染器 + md.renderer.rules.expandable_media = function( + tokens: Token[], + idx: number + ): string { + const token = tokens[idx] as ExpandableMediaToken; + const { path, type } = token.meta; + + // 为容器生成唯一 ID + const containerId = `media-container-${Math.random().toString(36).substring(2, 9)}`; + + // 从路径中提取文件名,用于更好的显示 + const filename = path.split('/').pop() || path; + + // 根据类型创建内容 HTML + let contentHtml = ''; + + if (type === 'iframe') { + contentHtml = ``; + } else if (type === 'video') { + contentHtml = ``; + } + + // 创建可展开容器、按钮组和内容 + return ` +
+
+    + 在新标签页打开 +
+ +
`; + }; + + + return pluginOptions; +} \ No newline at end of file diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..bc3ec91 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,72 @@ +import { createRouter, createWebHistory } from 'vue-router' +import NotFoundView from '@/views/NotFoundView.vue' +import { getStaticRoutes } from './routes' +import { generatePath } from '@/blogs/utils'; + + +function getRoutes() { + + + return [ + ...getStaticRoutes().map(route => { + return { + ...route, component: { + '/': () => import('@/views/HomeView.vue'), + '/tools': () => import('@/views/ToolsView.vue'), + '/blogs': () => import('@/views/BlogsView.vue'), + '/tools/image-converter': () => import('@/views/tools/ImageConverterView.vue'), + '/tools/desktop-engine': () => import('@/views/tools/DesktopEngineView.vue'), + }[route.path] || (() => import('@/views/NotFoundView.vue')), + meta: route.path === '/tools/desktop-engine' ? { hideLayout: true } : {}, + } + }), + + /* ...Object.values(mdFiles).map(module => { + const { frontmatter, default: defaultExport } = module; + const { short, long } = generatePath(frontmatter); + return { + path: long, + name: frontmatter.title, + component: defaultExport, + alias: short + }; + }) */ + ]; +} + +const router = createRouter({ + scrollBehavior(to, from, savedPosition) { + if (savedPosition) { + return savedPosition + } else { + return { top: 0 } + } + }, + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/404', + name: '未找到页面', + component: NotFoundView + }, + // 所有未定义路由,全部重定向到404页 + { + path: '/:pathMatch(.*)*', + redirect: '/404' + }, + { + path: '/blogs/:blogPath', + component: () => import('@/views/blogs/IndexView.vue'), + }, + ...getRoutes() + ], + +}) + +router.beforeEach((to, from, next) => { + if (to.name?.toString()) + document.title = `${to.name?.toString() || ''} - 鹅.net` + next() +}) + +export default router \ No newline at end of file diff --git a/src/router/routes.ts b/src/router/routes.ts new file mode 100644 index 0000000..a630e85 --- /dev/null +++ b/src/router/routes.ts @@ -0,0 +1,33 @@ +// src/router/routes.ts +export function getStaticRoutes() { + return [ + { + path: '/', + name: '学习中的鹅', + changefreq: 'daily', + priority: 1.0, + }, { + path: '/tools', + name: '工具箱', + changefreq: 'daily', + priority: 0.8, + }, { + path: '/tools/image-converter', + name: '在线图片压缩工具', + changefreq: 'daily', + priority: 0.7, + }, { + path: '/tools/desktop-engine', + name: '桌面引擎壁纸', + changefreq: 'daily', + priority: 0.7, + }, { + path: '/blogs', + name: '文章', + changefreq: 'daily', + priority: 0.9, + }, + + ]; +} + diff --git a/src/views/BlogsView.vue b/src/views/BlogsView.vue new file mode 100644 index 0000000..dfb6acd --- /dev/null +++ b/src/views/BlogsView.vue @@ -0,0 +1,184 @@ + + + + + \ No newline at end of file diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue new file mode 100644 index 0000000..7cd8fc5 --- /dev/null +++ b/src/views/HomeView.vue @@ -0,0 +1,337 @@ + + + + + diff --git a/src/views/NotFoundView.vue b/src/views/NotFoundView.vue new file mode 100644 index 0000000..0fcbc99 --- /dev/null +++ b/src/views/NotFoundView.vue @@ -0,0 +1,61 @@ + + + + + \ No newline at end of file diff --git a/src/views/ToolsView.vue b/src/views/ToolsView.vue new file mode 100644 index 0000000..59d9958 --- /dev/null +++ b/src/views/ToolsView.vue @@ -0,0 +1,23 @@ + + + + \ No newline at end of file diff --git a/src/views/blogs/IndexView.vue b/src/views/blogs/IndexView.vue new file mode 100644 index 0000000..8720f97 --- /dev/null +++ b/src/views/blogs/IndexView.vue @@ -0,0 +1,230 @@ + + + + + \ No newline at end of file diff --git a/src/views/tools/DesktopEngineView.vue b/src/views/tools/DesktopEngineView.vue new file mode 100644 index 0000000..1aa92e5 --- /dev/null +++ b/src/views/tools/DesktopEngineView.vue @@ -0,0 +1,631 @@ + + + + + \ No newline at end of file diff --git a/src/views/tools/ImageConverterView.vue b/src/views/tools/ImageConverterView.vue new file mode 100644 index 0000000..98f94b9 --- /dev/null +++ b/src/views/tools/ImageConverterView.vue @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/src/views/tools/StockWidget.vue b/src/views/tools/StockWidget.vue new file mode 100644 index 0000000..6f26d96 --- /dev/null +++ b/src/views/tools/StockWidget.vue @@ -0,0 +1,385 @@ + + + + + \ No newline at end of file diff --git a/src/views/tools/WeatherWidget.vue b/src/views/tools/WeatherWidget.vue new file mode 100644 index 0000000..abcfc4d --- /dev/null +++ b/src/views/tools/WeatherWidget.vue @@ -0,0 +1,407 @@ + + + + + \ No newline at end of file diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..913b8f2 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,12 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..a83dfc9 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*", + "eslint.config.*" + ], + "compilerOptions": { + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..94f3ec0 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,145 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig, Terser } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import minipic from 'vite-plugin-minipic' +import Markdown from 'vite-plugin-md' +// @ts-ignore +import MarkdownItKatex from 'markdown-it-katex' +import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs' +import path from 'node:path' + +import { getStaticRoutes } from './src/router/routes'; +import matter from 'gray-matter'; +import expandableMediaPlugin from './src/plugins/markdown-it-expandable-media' +import blogInfoPlugin from './src/plugins/markdown-it-blog-info'; +import hljs from 'highlight.js' + +// https://vite.dev/config/ +export default defineConfig({ + + plugins: [ + vue({ + include: [/\.vue$/, /\.md$/], + }), + vueJsx(), + { + name: 'generate-sitemap-and-robots', + closeBundle: async () => { + // 获取静态路由 + const staticRoutes = getStaticRoutes(); + + // 读取所有 Markdown 文件并解析 frontmatter + const blogDir = path.resolve(__dirname, 'src/blogs'); + const blogFiles = readdirSync(blogDir).filter(file => file.endsWith('.md')); + + const blogRoutes = blogFiles.map(file => { + const content = readFileSync(path.join(blogDir, file), 'utf-8'); + const { data } = matter(content); + return { + path: encodeURI('/blogs/' + data.title + '.md'), + name: data.title, + changefreq: 'weekly', + priority: 0.7, + }; + }); + + // 合并所有路由 + const allRoutes = [...staticRoutes, ...blogRoutes]; + + const WEBSITE_URL = 'https://xn--876a.net'; + + // 生成 sitemap.xml + let sitemap = '\n'; + sitemap += '\n'; + + allRoutes.forEach(route => { + sitemap += ' \n'; + sitemap += ` ${WEBSITE_URL}${route.path}\n`; + sitemap += ` ${new Date().toISOString().split("T")[0]}\n`; + sitemap += ` ${route.changefreq}\n`; + sitemap += ` ${route.priority}\n`; + sitemap += ' \n'; + }); + + sitemap += ''; + + // 生成 robots.txt + let robotsTxt = ''; + robotsTxt += 'User-agent: *\n'; + robotsTxt += 'Allow: /\n'; + robotsTxt += '\n'; + // 可以添加自定义的 Disallow 规则 + // robotsTxt += 'Disallow: /admin/\n'; + // robotsTxt += 'Disallow: /private/\n'; + robotsTxt += '\n'; + robotsTxt += `Sitemap: ${WEBSITE_URL}/sitemap.xml\n`; + + // 确保 dist 目录存在 + const distDir = path.resolve(__dirname, 'dist'); + if (!existsSync(distDir)) { + mkdirSync(distDir); + } + + // 写入 sitemap.xml + writeFileSync(path.join(distDir, 'sitemap.xml'), sitemap); + console.log('Sitemap 生成成功!'); + + // 写入 robots.txt + writeFileSync(path.join(distDir, 'robots.txt'), robotsTxt); + console.log('Robots.txt 生成成功!'); + } + }, + Markdown({ + wrapperComponent: 'article', + markdownItOptions: { + linkify: true, + highlight: function (str, lang) { + if (lang && hljs.getLanguage(lang)) { + try { + return hljs.highlight(str, { language: lang }).value; + } catch (__) { } + } + + return ''; // use external default escaping + } + }, + markdownItUses: [MarkdownItKatex, expandableMediaPlugin, blogInfoPlugin] + }), + minipic({ + sharpOptions: { + webp: { + quality: 90, + }, + png: { + quality: 80, + }, + avif: { + quality: 80, + }, + jpg: { + quality: 80, + }, + jpeg: { + quality: 80, + }, + gif: { + + } + }, + convert: [ + { from: 'png', to: 'webp' }, + ], + cache: true + }) + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + }, + }, + server: { + host: '0.0.0.0', + } +})