diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..57118c3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to the Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by the Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. Please also get an ISBN
+ number for the printed version if you plan to publish a book
+ using this license. We recommend considering the
+ Apache License 2.0 for software, and the CC-BY license for
+ other creative works.
+
+ Copyright 2026 LI Meng
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index 4f476d9..2ab6c95 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-# TSZQ_KaiYuanHongMengRISC-VJuShenZhiNengKeChengGongJianZhuanQu
+计算思维程序实践共14个计算思维程序实践项目编写开源鸿蒙应用程序,为学生系统剖析了每一个实践项目的计算思维,为学生搭建了一个五级阶梯的程序实现路径,同时为学生提供了由零基础开发到最终系统实现的初始版程序和程序实现环境,供学生上机调试与研讨。
diff --git a/datafiting/README.md b/datafiting/README.md
new file mode 100644
index 0000000..14948ed
--- /dev/null
+++ b/datafiting/README.md
@@ -0,0 +1,21 @@
+# datafiting
+### 1、项目说明
+总体思路曲线拟合绘制程序项目开发的总体思路如图所示,以实现交互界面与交互控制和数据结构和数值分析算法等。程序有两个主体功能:(1)对设置的数据集和用户选择的拟合曲线类型进行拟合,并计算出拟合优度和函数表达式;(2)根据拟合得到的函数表达式进行绘制。
+ 图1.1 项目开发的总体思路图
+
+
+
+### 2、开发环境说明
+(1)系统版本:OpenHarmony 4.0 Release
+(2)SDK版本:API 10
+(3)Model类型:Stage
+(4)DevEco Studio版本:Deveco Studio 4.0 release
+(5)硬件环境:Unionpi Whale、RK3566开发板
+(6)预览器参数:(1)DeviceType:default;(2)Resolution:560-1280;(3)DPI:240;其余参数自定。
+### 3、项目主要函数调用关系图与项目输出界面演进图
+ 图3.1 项目主要函数调用关系图
+
+
+
+ 图3.2 项目输出界面演进图
+
\ No newline at end of file
diff --git a/datafiting/datafit/.gitignore b/datafiting/datafit/.gitignore
new file mode 100644
index 0000000..fbabf77
--- /dev/null
+++ b/datafiting/datafit/.gitignore
@@ -0,0 +1,11 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
\ No newline at end of file
diff --git a/datafiting/datafit/AppScope/app.json5 b/datafiting/datafit/AppScope/app.json5
new file mode 100644
index 0000000..3c45fe7
--- /dev/null
+++ b/datafiting/datafit/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.test.myapplication",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
diff --git a/datafiting/datafit/AppScope/resources/base/element/string.json b/datafiting/datafit/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000..1080233
--- /dev/null
+++ b/datafiting/datafit/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MyApplication"
+ }
+ ]
+}
diff --git a/datafiting/datafit/AppScope/resources/base/media/app_icon.png b/datafiting/datafit/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/datafiting/datafit/AppScope/resources/base/media/app_icon.png differ
diff --git a/datafiting/datafit/build-profile.json5 b/datafiting/datafit/build-profile.json5
new file mode 100644
index 0000000..1891617
--- /dev/null
+++ b/datafiting/datafit/build-profile.json5
@@ -0,0 +1,49 @@
+{
+ "app": {
+ "signingConfigs": [
+ {
+ "name": "default",
+ "material": {
+ "certpath": "C:\\Users\\nInse\\.ohos\\config\\openharmony\\auto_ohos_default_draw2_com.test.myapplication.cer",
+ "storePassword": "0000001B23074682D90DCDA10157D8187E84EC05F50638D319B2E510345811D5FEB541650A0415030813F5",
+ "keyAlias": "debugKey",
+ "keyPassword": "0000001B291E996BCAB68900B133F9F5D394B9749AFD0C20146A22CE85070C1340F65B45506D15A417CC08",
+ "profile": "C:\\Users\\nInse\\.ohos\\config\\openharmony\\auto_ohos_default_draw2_com.test.myapplication.p7b",
+ "signAlg": "SHA256withECDSA",
+ "storeFile": "C:\\Users\\nInse\\.ohos\\config\\openharmony\\auto_ohos_default_draw2_com.test.myapplication.p12"
+ }
+ }
+ ],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 10,
+ "compatibleSdkVersion": 10,
+ "runtimeOS": "OpenHarmony",
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug",
+ },
+ {
+ "name": "release"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/.gitignore b/datafiting/datafit/entry/.gitignore
new file mode 100644
index 0000000..e2713a2
--- /dev/null
+++ b/datafiting/datafit/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/datafiting/datafit/entry/build-profile.json5 b/datafiting/datafit/entry/build-profile.json5
new file mode 100644
index 0000000..197e83c
--- /dev/null
+++ b/datafiting/datafit/entry/build-profile.json5
@@ -0,0 +1,31 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ "arkOptions": {
+ // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
+ }
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": true,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/hvigorfile.ts b/datafiting/datafit/entry/hvigorfile.ts
new file mode 100644
index 0000000..c6edcd9
--- /dev/null
+++ b/datafiting/datafit/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/datafiting/datafit/entry/obfuscation-rules.txt b/datafiting/datafit/entry/obfuscation-rules.txt
new file mode 100644
index 0000000..985b2ae
--- /dev/null
+++ b/datafiting/datafit/entry/obfuscation-rules.txt
@@ -0,0 +1,18 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
\ No newline at end of file
diff --git a/datafiting/datafit/entry/oh-package.json5 b/datafiting/datafit/entry/oh-package.json5
new file mode 100644
index 0000000..225946c
--- /dev/null
+++ b/datafiting/datafit/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "license": "",
+ "devDependencies": {},
+ "author": "",
+ "name": "entry",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
diff --git a/datafiting/datafit/entry/src/main/ets/common/commonValue.ets b/datafiting/datafit/entry/src/main/ets/common/commonValue.ets
new file mode 100644
index 0000000..4de7aec
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/common/commonValue.ets
@@ -0,0 +1,30 @@
+export class COMMON_VALUE{
+ /**
+ * 字体大小(大)
+ */
+ static readonly BIG_SIZE_FONT = 20
+ /**
+ * 字体大小(小)
+ */
+ static readonly SMALL_SIZE_FONT = 15
+ /**
+ * 字体大小(超小)
+ */
+ static readonly SMALLER_SIZE_FONT = 10
+ /**
+ * 浅蓝
+ */
+ static readonly LIGHT_BLUE = '#87BAD4'
+ /**
+ * 紫色
+ */
+ static readonly PURPLE = '#BE4AD9'
+ /**
+ * 灰色
+ */
+ static readonly GREY = '#B8B8B8'
+ /**
+ * 浅白
+ */
+ static readonly LIGHT_WHITE = '#F2F2F2'
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/component/ControlBar.ets b/datafiting/datafit/entry/src/main/ets/component/ControlBar.ets
new file mode 100644
index 0000000..47c0578
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/component/ControlBar.ets
@@ -0,0 +1,221 @@
+import promptAction from '@ohos.promptAction'
+import { COMMON_VALUE } from '../common/commonValue'
+import { handle } from '../utils/algorithm/createPotGather'
+import { BoardInfo, Quadrant } from '../utils/drawBoard/BoardType'
+import { IPoint, PointType } from '../utils/drawBoard/DrawPoint'
+import { funcInfo, functionUtilIns } from '../utils/FunctionUtil'
+
+@Component
+export struct controlBar {
+ @State func:funcInfo|undefined = undefined
+
+ //TODO
+ @Prop fitFuncList:Array
+ @Prop selectFitFunc:funcInfo
+ @Prop curFuncIndex:number
+ @Link isStartFit:boolean
+ @Link isShowFunc:boolean
+ @Link quadrant:Quadrant
+ @Link points:Array
+ @Link selectFuncIndex:number
+
+ @Consume board:BoardInfo
+ @Consume isRefreshPoint:boolean
+ @Consume isRefreshFunc:boolean
+ controller:CustomDialogController = new CustomDialogController({
+ builder:addPoints({points:$points,isStartFit:$isStartFit,isShowFunc:$isShowFunc})
+ })
+ build() {
+ Column(){
+ Row({space:5}){
+
+ Row(){
+ Text('坐标轴')
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ Radio({value:"四象限",group:"Quadrant"})
+ .checked(this.quadrant == Quadrant.FOUR)
+ .onClick(()=>{
+ this.quadrant = Quadrant.FOUR
+ AppStorage.setOrCreate("quadrant",Quadrant.FOUR)
+ })
+ Text('四象限')
+ .fontSize(COMMON_VALUE.SMALLER_SIZE_FONT)
+ Radio({value:"一象限",group:"Quadrant"})
+ .checked(this.quadrant == Quadrant.ONE)
+ .onClick(()=>{
+ this.quadrant = Quadrant.ONE
+ AppStorage.setOrCreate("quadrant",Quadrant.ONE)
+ })
+ Text('一象限')
+ .fontSize(COMMON_VALUE.SMALLER_SIZE_FONT)
+ }.backgroundColor(COMMON_VALUE.GREY)
+
+ Row({space:5}){
+ Button('生成数据集')
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ .type(ButtonType.Normal)
+ .onClick(()=>{
+
+ this.isRefreshPoint = !this.isRefreshPoint
+ this.points = this.board.initMap()
+ this.board.drawAxis()
+ this.board.drawPoints()
+
+ })
+ Button('显示数据集')
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ .type(ButtonType.Normal)
+ .onClick(()=>{
+ this.isShowFunc = false
+ })
+ Button('显示数据集与曲线')
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ .type(ButtonType.Normal)
+ .onClick(()=>{
+ if(this.points.length == 0){
+ promptAction.showToast({
+ message:"还未选择样本点!"
+ })
+ return
+ }
+ if(this.selectFuncIndex != this.curFuncIndex){
+ this.isShowFunc = false
+ this.selectFuncIndex = this.curFuncIndex
+ }
+ setTimeout(()=>{
+ this.isStartFit = false
+ if (this.isShowFunc == false) {
+ this.isShowFunc = true
+ }
+ },100)
+ })
+ Button('手动输入数据集')
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ .type(ButtonType.Normal)
+ .onClick(()=>{
+ this.controller.open()
+ })
+ Button('拟合')
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ .type(ButtonType.Normal)
+ .onClick(()=>{
+ if(this.points.length == 0){
+ promptAction.showToast({
+ message:"还未选择样本点!"
+ })
+ return
+ }
+ //TODO
+ this.selectFitFunc = this.fitFuncList[this.curFuncIndex]
+
+ this.func = functionUtilIns.getFitFunc(this.selectFitFunc,this.points)
+ this.isStartFit = true
+ this.isShowFunc = false
+ setTimeout(()=>{
+ this.isShowFunc = true
+ },100)
+ this.selectFuncIndex = this.curFuncIndex
+ })
+ }
+ }
+
+ Row(){
+ Text('结果输出:')
+ Swiper(){
+ if(this.isStartFit){
+ Text('函数形式:' + this.selectFitFunc.name + "\t" + this.selectFitFunc.body)
+ .width('100%').height('100%')
+ Text('函数系数:' + this.func!.body)
+ .width('100%').height('100%')
+ Text('拟合优度R^2:' + this.func!.R!)
+ .width('100%').height('100%')
+ }
+ }.backgroundColor(COMMON_VALUE.GREY).layoutWeight(1).vertical(true).height('100%').autoPlay(false).indicator(false).loop(false)
+
+ }.width('100%').layoutWeight(1).padding(5)
+ }.backgroundColor(COMMON_VALUE.LIGHT_WHITE).width('100%').height('100%')
+ }
+}
+
+@CustomDialog
+struct addPoints{
+ controller:CustomDialogController
+ @State setNum:number = -1
+ @State num:number = 0
+ @State msg:string = ''
+ @Link points:Array
+ @Link isStartFit:boolean
+ @Link isShowFunc:boolean
+ @Consume board:BoardInfo
+ @Consume isRefreshPoint:boolean
+ @Consume isRefreshFunc:boolean
+ build(){
+ Column({space:5}){
+ Row(){
+ if(this.setNum == -1){
+ Text('设置样本点个数')
+ TextInput({text:this.num.toString()})
+ .onChange((value)=>{
+ this.num = Number(value)
+ })
+ }
+ }
+ if(this.setNum == -1){
+ Row(){
+ Button('确定')
+ .onClick(()=>{
+ if(this.num <= 0){
+ promptAction.showToast({
+ message:"必须为正整数"
+ })
+ return
+ }
+ this.points = []
+ this.setNum = this.num
+ })
+ .type(ButtonType.Normal)
+ Button('取消')
+ .onClick(()=>{
+ this.controller.close()
+ })
+ .type(ButtonType.Normal)
+ }.width('100%').justifyContent(FlexAlign.SpaceAround)
+ }else {
+ Column(){
+ if(this.setNum == 0){
+ Text('是否保存数据集')
+ }else{
+ Text("输入" + this.setNum + "个样本点,格式为X,X")
+ TextInput({text:this.msg})
+ .onChange((value)=>{
+ this.msg = value
+ })
+ }
+ Row(){
+ Button('确定')
+ .onClick(()=>{
+ if(this.setNum == 0){
+ this.isRefreshPoint = !this.isRefreshPoint
+ this.board.initMap(this.points)
+ this.board.drawAxis()
+ this.board.drawPoints()
+ this.controller.close()
+ }else{
+ let arr = this.msg.split(',')
+ this.points.push({x:Number(arr[0]),y:Number(arr[1]),pointType:PointType.CONTINUE})
+ this.msg = ''
+ this.setNum--
+ }
+ })
+ .type(ButtonType.Normal)
+ Button('取消')
+ .onClick(()=>{
+ this.controller.close()
+ })
+ .type(ButtonType.Normal)
+ }.width('100%').justifyContent(FlexAlign.SpaceAround)
+ }
+ }
+ }.padding(5)
+ }
+}
diff --git a/datafiting/datafit/entry/src/main/ets/component/FitFuncType.ets b/datafiting/datafit/entry/src/main/ets/component/FitFuncType.ets
new file mode 100644
index 0000000..01c3b44
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/component/FitFuncType.ets
@@ -0,0 +1,102 @@
+import { COMMON_VALUE } from '../common/commonValue'
+import { funcInfo } from '../utils/FunctionUtil'
+
+@Component
+export struct fitFuncType {
+ @Link fitFuncList:Array
+ @Link curFuncIndex:number
+ controller:CustomDialogController = new CustomDialogController({
+ builder:addFitFuncType({fitFuncList:$fitFuncList})
+ })
+ build() {
+ Column({space:5}){
+ Text('拟合曲线类型')
+ .height('12%')
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ List(){
+ ForEach(this.fitFuncList,(item:funcInfo,index:number)=>{
+ ListItem(){
+ funcItem({curFuncIndex:$curFuncIndex,func:item,funcIndex:index})
+ }.width('100%').height(30)
+ })
+ }.width('100%').layoutWeight(1).backgroundColor(COMMON_VALUE.LIGHT_BLUE)
+
+ Button('新增拟合曲线类型')
+ .onClick(()=>{
+ this.controller.open()
+ })
+ .type(ButtonType.Normal)
+ .backgroundColor(COMMON_VALUE.PURPLE)
+ }.width('100%').height('100%').padding({top:5,bottom:5,right:5}).backgroundColor(COMMON_VALUE.LIGHT_WHITE)
+ }
+}
+
+@Component
+struct funcItem {
+ @Link curFuncIndex:number
+ @Prop func:funcInfo
+ @Prop funcIndex:number
+ build() {
+ Row({space:5}){
+ Radio({value:this.func.name,group:"fitFunc"})
+ .width(20)
+ .height(20)
+ .checked(this.curFuncIndex == this.funcIndex)
+ .onChange((value)=>{
+ if(this.curFuncIndex == this.funcIndex){
+
+ return
+ }
+ this.curFuncIndex = this.funcIndex
+ })
+ Text(this.func.name)
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ Text(this.func.body)
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ }.width('100%').height('100%')
+ }
+}
+
+let funcList:Array = [
+ {name:"对数函数",body:"a*log(x,b)+c"},
+ {name:"指数函数",body:"a*e^(0.01x)+b"}
+]
+@CustomDialog
+struct addFitFuncType{
+ @Link fitFuncList:Array
+ controller:CustomDialogController
+ @State index:number = 0
+ @Builder item(index:number){
+ Row(){
+ Text(funcList[index].name)
+ .fontColor(this.index == index?Color.Red:Color.Black)
+ Text(funcList[index].body)
+ .fontColor(this.index == index?Color.Red:Color.Black)
+ }.width('100%').onClick(()=>{
+ this.index = index
+ })
+ }
+ build(){
+ Column({space:5}){
+
+ ForEach(funcList,(item:funcInfo,index)=>{
+ this.item(index)
+ })
+
+ Row(){
+ Button('确定')
+ .onClick(()=>{
+ this.fitFuncList.push({name:funcList[this.index].name,body:funcList[this.index].body})
+ funcList.splice(this.index,1)
+ this.controller.close()
+ })
+ .type(ButtonType.Normal)
+ Button('取消')
+ .onClick(()=>{
+ this.controller.close()
+ })
+ .type(ButtonType.Normal)
+ }.width('100%').justifyContent(FlexAlign.SpaceAround)
+ }.width('100%').padding(5)
+ }
+}
diff --git a/datafiting/datafit/entry/src/main/ets/component/Header.ets b/datafiting/datafit/entry/src/main/ets/component/Header.ets
new file mode 100644
index 0000000..8faa9a5
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/component/Header.ets
@@ -0,0 +1,65 @@
+import { COMMON_VALUE } from '../common/commonValue'
+import { BoardInfo } from '../utils/drawBoard/BoardType'
+import { IPoint, PointType } from '../utils/drawBoard/DrawPoint'
+import picker from '@ohos.file.picker';
+import fs from '@ohos.file.fs';
+import { createDocument } from '../model/createDocumentModel';
+import buffer from '@ohos.buffer';
+
+@Component
+export struct header {
+ @State filePath:string = ''
+ @Link points:Array
+ @Link isStartFit:boolean
+ @Link isShowFunc:boolean
+ @Consume board:BoardInfo
+ @Consume isRefreshPoint:boolean
+ @Consume isRefreshFunc:boolean
+ context = getContext()
+ build() {
+ Row({space:5}){
+ Text('样本数据集文件')
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ Text(this.filePath)
+ .textOverflow({overflow:TextOverflow.MARQUEE})
+ .layoutWeight(1)
+ .fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
+ .backgroundColor(COMMON_VALUE.LIGHT_BLUE)
+ .height('100%')
+ Button('装载')
+ .type(ButtonType.Normal)
+ .onClick(async ()=>{
+ this.points = []
+ let documentPicker = new picker.DocumentViewPicker()
+ let DocumentSelectOptions = new picker.DocumentSelectOptions();
+ let DocumentSelectResult: Array = await documentPicker.select(DocumentSelectOptions)
+ let uri = DocumentSelectResult[0]
+ let file = fs.openSync(uri,fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
+ //已经获取到选择的文件 进行读取操作
+ let arrayBuffer = new ArrayBuffer(8)
+ let size = 0
+ let dSize = 0
+ let str = fs.readTextSync(file.path)
+
+
+ //解析路径
+ this.filePath = file.path
+ fs.closeSync(file)
+
+ //解析文件样本点
+ let arr = str.split('\n')
+ for (let index = 0; index < arr.length; index++) {
+ this.points.push({x:Number(arr[index].split(' ')[0]),y:Number(arr[index].split(' ')[1]),pointType:PointType.CONTINUE})
+ }
+
+
+ this.isStartFit = false
+ this.isShowFunc = false
+ this.isRefreshPoint = !this.isRefreshPoint
+ this.board.initMap(this.points)
+ this.board.drawPoints()
+ this.board.drawAxis()
+ })
+ }.width('100%').height('100%').padding(5).backgroundColor(COMMON_VALUE.LIGHT_WHITE)
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/component/ImageShow.ets b/datafiting/datafit/entry/src/main/ets/component/ImageShow.ets
new file mode 100644
index 0000000..d8fc3ed
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/component/ImageShow.ets
@@ -0,0 +1,31 @@
+import { BoardInfo, CONTEXT, FIT_CONTEXT } from '../utils/drawBoard/BoardType'
+import { IPoint } from '../utils/drawBoard/DrawPoint'
+import { funcInfo, functionUtilIns } from '../utils/FunctionUtil'
+
+@Component
+export struct imageShow {
+ @Prop loop_board:string
+ @Prop loop_fit:string
+ @Prop isShowFunc:boolean
+ @Prop points:Array
+ @Prop selectFitFunc:funcInfo
+ @Consume board:BoardInfo
+ @Consume isRefreshFunc:boolean
+ build() {
+ Stack(){
+ Canvas(CONTEXT)
+ .width('100%').height(this.loop_board)
+ if(this.isShowFunc){
+ Canvas(FIT_CONTEXT)
+ .width('100%').height(this.loop_fit)
+ .onReady(()=>{
+ //获取到经过拟合后的函数
+ functionUtilIns.getFitFunc(this.selectFitFunc,this.points)
+ //解析函数 获取对应坐标点
+ let points:Array = functionUtilIns.getPoints()
+ this.board.drawFitFunc(points)
+ })
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/entryability/EntryAbility.ets b/datafiting/datafit/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000..1c7aa63
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,43 @@
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+import hilog from '@ohos.hilog';
+import UIAbility from '@ohos.app.ability.UIAbility';
+import Want from '@ohos.app.ability.Want';
+import window from '@ohos.window';
+
+export default class EntryAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
+ }
+
+ onDestroy(): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ // Main window is created, set main page for this ability
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+
+ windowStage.loadContent('pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy(): void {
+ // Main window is destroyed, release UI related resources
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
+ }
+
+ onForeground(): void {
+ // Ability has brought to foreground
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
+ }
+
+ onBackground(): void {
+ // Ability has back to background
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
+ }
+}
diff --git a/datafiting/datafit/entry/src/main/ets/model/createDocumentModel.ets b/datafiting/datafit/entry/src/main/ets/model/createDocumentModel.ets
new file mode 100644
index 0000000..d536047
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/model/createDocumentModel.ets
@@ -0,0 +1,19 @@
+import picker from '@ohos.file.picker';
+import { BusinessError } from '@ohos.base';
+import fs from '@ohos.file.fs';
+
+/**
+ * 创建一个包含样本点的文件 用于读取测试
+ */
+export let createDocument = async ()=>{
+ let documentPicker = new picker.DocumentViewPicker();
+ let uris:Array = []
+ let DocumentSaveOptions = new picker.DocumentSaveOptions();
+ DocumentSaveOptions.newFileNames = ['testPoints.txt']
+ uris = await documentPicker.save(DocumentSaveOptions)
+ let uri = uris[0]
+ let file = fs.openSync(uri, fs.OpenMode.WRITE_ONLY);
+ let writeLen = 0
+ writeLen += fs.writeSync(file.fd, '2 2\n100 100\n123 323\n200.99 199.999\n302.8 300.6\n400 400.9\n450 450');//todo必须加结束位 否则多读
+ fs.closeSync(file);
+}
diff --git a/datafiting/datafit/entry/src/main/ets/pages/Index.ets b/datafiting/datafit/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000..868cf9e
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,105 @@
+import { controlBar } from '../component/ControlBar'
+import { fitFuncType } from '../component/FitFuncType'
+import { header } from '../component/Header'
+import { imageShow } from '../component/ImageShow'
+import { createDocument } from '../model/createDocumentModel'
+import { B1Q2D, B4Q2D, BoardInfo, Quadrant } from '../utils/drawBoard/BoardType'
+import { IPoint } from '../utils/drawBoard/DrawPoint'
+import { funcInfo } from '../utils/FunctionUtil'
+
+@Entry
+@Component
+struct Index {
+ @State fitFuncList:Array = [
+ {name:"一次函数",body:"a*x+b"},
+ {name:"二次函数",body:"a*x^2+b*x+c"},
+ {name:"三次函数",body:"a*x^3+b*x^2+c*x+d"},
+ {name:"四次函数",body:"a*x^4+b*x^3+c*x^2+d*x+e"}
+ ]
+ @State curFuncIndex:number = 0
+ @State selectFuncIndex:number = 0
+ /**
+ * 是否开始拟合 点击拟合按钮改为true
+ * 响应:结果输出栏
+ */
+ @State isStartFit:boolean = false
+ /**
+ * 是否展示拟合函数 点击显示数据集与曲线改为true
+ * 响应:出现函数图像
+ */
+ @State isShowFunc:boolean = false
+
+ @State @Watch('refreshBoard')quadrant:Quadrant = Quadrant.FOUR
+
+ @Provide board:BoardInfo = B4Q2D
+ @Provide @Watch('refreshPoint')isRefreshPoint:boolean = false
+ @Provide @Watch('refreshFunc')isRefreshFunc:boolean = false
+ @State loop_board:string = '100%'
+ @State loop_fit:string = '100%'
+ @State virtualPoints:Array = []
+ @State boardPoints:Array = []
+
+ refreshPoint(){
+ if(this.loop_board == '100%'){
+ this.loop_board = '101%'
+ }else {
+ this.loop_board = '100%'
+ }
+ console.log('REFRESH point')
+ this.isStartFit = false
+ this.isShowFunc = false
+ }
+
+ refreshFunc(){
+ if(this.loop_fit == '100%'){
+ this.loop_fit = '101%'
+ }else {
+ this.loop_fit = '100%'
+ }
+ console.log('REFRESH func')
+ }
+
+ refreshBoard(){
+ console.log('REFRESH board')
+ if(this.quadrant == Quadrant.ONE){
+ this.board = B1Q2D
+ }else{
+ this.board = B4Q2D
+ }
+ if(this.virtualPoints.length != 0){
+ this.isRefreshPoint = !this.isRefreshPoint
+ this.isRefreshFunc = !this.isRefreshFunc
+ this.board.initMap(this.virtualPoints)
+ this.board.drawAxis()
+ this.board.drawPoints()
+ this.isStartFit = false
+ }
+ }
+
+ async aboutToAppear(){
+ await createDocument()
+ }
+
+
+ build() {
+ Column(){
+
+ Row(){
+ Column(){
+
+ header({points:$virtualPoints,isShowFunc:$isShowFunc,isStartFit:$isStartFit}).width('100%').height('15%')
+
+ imageShow({points:this.virtualPoints,selectFitFunc:this.fitFuncList[this.curFuncIndex],loop_board:this.loop_board,loop_fit:this.loop_fit,isShowFunc:this.isShowFunc}).width('100%').height('85%')
+
+ }.width('60%').height('100%')
+
+ fitFuncType({fitFuncList:$fitFuncList,curFuncIndex:$curFuncIndex}).width('40%').height('100%')
+
+ }.width('100%').height('75%')
+
+ //TODO
+ controlBar({points:$virtualPoints,isShowFunc:$isShowFunc,quadrant:$quadrant,isStartFit:$isStartFit,selectFitFunc:this.fitFuncList[this.selectFuncIndex],selectFuncIndex:$selectFuncIndex,curFuncIndex:this.curFuncIndex,fitFuncList:this.fitFuncList}).width('100%').layoutWeight(1)
+
+ }.width('100%').height('100%')
+ }
+}
diff --git a/datafiting/datafit/entry/src/main/ets/utils/FunctionUtil.ets b/datafiting/datafit/entry/src/main/ets/utils/FunctionUtil.ets
new file mode 100644
index 0000000..89d9d5c
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/FunctionUtil.ets
@@ -0,0 +1,49 @@
+import { IPoint, PointType } from './drawBoard/DrawPoint'
+import { handle } from './algorithm/createPotGather'
+
+export interface funcInfo {
+ /**
+ * 名称
+ */
+ name: string
+ /**
+ * 函数体
+ */
+ body: string
+ /**
+ * 拟合优度
+ */
+ R?: number
+}
+
+/**
+ * 提供函数拟合的方法
+ */
+class FunctionUtil {
+ /**
+ * 根据拟合函数类型和样本点计算出拟合函数
+ * 返回funcInfo
+ */
+ getFitFunc(fitFunc: funcInfo, points: Array) {
+ handle.fit(fitFunc.body, points);
+ let func: funcInfo = { name: "", body: handle.fitFunc, R: handle.R_squared }
+ return func
+ }
+
+ /**
+ * 根据函数返回xyMap
+ */
+ getPoints() {
+ //TODO 结合原代码
+ //用来测试的拟合函数
+ handle.compote_curveData();
+ let point: Array = handle.coordinatePoint;
+ // console.log(handle.fitFunc)
+ // for (let i = 0; i < point.length; i++) {
+ // console.log("testTag", "(" + point[i].x + ", " + point[i].y + ")");
+ // }
+ return point
+ }
+}
+
+export let functionUtilIns = new FunctionUtil()
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/utils/algorithm/createPotGather.ets b/datafiting/datafit/entry/src/main/ets/utils/algorithm/createPotGather.ets
new file mode 100644
index 0000000..67d2ca4
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/algorithm/createPotGather.ets
@@ -0,0 +1,159 @@
+import { mathjs } from './evaluate';
+import {IPoint, PointType} from "../drawBoard/DrawPoint"
+import {FitRes} from "./fittingResult"
+import { Matrix } from './least_square';
+import { Quadrant } from '../drawBoard/BoardType';
+import { Exponent } from './exponentialFit';
+import { Logarithm } from './logarithmicFit';
+
+function arrange(low: number, high: number, step: number): number[] {
+ const rangeArray: number[] = [];
+ if (step <= 0) {
+ throw new Error("Step must be greater than zero.");
+ }
+ for (let i = low; i <= high; i += step) {
+ rangeArray.push(i);
+ }
+ return rangeArray;
+}
+
+const replaceVar: Array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
+
+class CreatePointGather {
+ coordinatePoint: Array;
+ theta: number[];
+ error: number;
+ R_squared: number;
+ fitFunc: string;
+ funcFormat: string;
+ private m: number;
+
+ constructor() {
+ this.coordinatePoint = [];
+ this.theta = [];
+ this.error = 0;
+ this.R_squared = 0;
+ this.fitFunc = "";
+ this.funcFormat = "";
+ this.m = 0;
+ }
+
+ private judgeWhichM(funcFormat: string) {
+ const index = funcFormat.indexOf("^");
+ if (index === -1) {
+ this.m = 1;
+ } else {
+ this.m = Number(funcFormat[index + 1]);
+ }
+ }
+
+ private getFitFunc(funcFormat: string): void {
+ this.funcFormat = funcFormat;
+ this.fitFunc = funcFormat;
+ if (funcFormat == "a*e^(0.01x)+b") {
+ for (let i = 0; i < 2; i++) {
+ if (this.theta[i] < 0 && this.fitFunc[this.fitFunc.indexOf(replaceVar[i]) - 1] == "+") {
+ this.fitFunc = this.fitFunc.substring(0, this.fitFunc.indexOf(replaceVar[i]) - 1) + this.fitFunc.substring(this.fitFunc.indexOf(replaceVar[i]));
+ }
+ this.fitFunc = this.fitFunc.replace(replaceVar[i], this.theta[i].toFixed(4));
+ }
+ } else if (funcFormat == "a*log(x,b)+c") {
+ for (let i = 0; i < 3; i++) {
+ if (this.theta[i] < 0 && this.fitFunc[this.fitFunc.indexOf(replaceVar[i]) - 1] == "+") {
+ this.fitFunc = this.fitFunc.substring(0, this.fitFunc.indexOf(replaceVar[i]) - 1) + this.fitFunc.substring(this.fitFunc.indexOf(replaceVar[i]));
+ }
+ this.fitFunc = this.fitFunc.replace(replaceVar[i], this.theta[i].toFixed(4));
+ }
+ } else {
+ for (let i = 0; i < this.m + 1; i++) {
+ if (this.theta[i] < 0 && this.fitFunc[this.fitFunc.indexOf(replaceVar[i]) - 1] == "+") {
+ this.fitFunc = this.fitFunc.substring(0, this.fitFunc.indexOf(replaceVar[i]) - 1) + this.fitFunc.substring(this.fitFunc.indexOf(replaceVar[i]));
+ }
+ this.fitFunc = this.fitFunc.replace(replaceVar[i], this.theta[i].toFixed(4));
+ }
+ }
+ }
+
+ private calculate_function(x:number): number {
+ if (this.funcFormat == "a*e^(0.01x)+b") {
+ return Exponent.expFunc(x, this.theta[0], this.theta[1]);
+ } else if (this.funcFormat == "a*log(x,b)+c") {
+ if (x > 0) return Logarithm.logFunc(x, this.theta[0], this.theta[1], this.theta[2]);
+ else return Number.NaN;
+ }
+ return mathjs.evaluate(this.fitFunc, [{char: 'x', value: x}]);
+ }
+
+ compote_curveData(low: number = -500, high: number = 500, step: number = 1): Array {
+ if (AppStorage.get("quadrant") == Quadrant.ONE) {
+ low = 0;
+ high = 1000;
+ }
+ this.coordinatePoint = [];
+ let xValues = arrange(low, high, step);
+ let yValues: number[] = [];
+ let size = xValues.length;
+ yValues = Array(size).fill(0).map((_, index) => {
+ return this.calculate_function(xValues[index]);
+ })
+ for (let i = 0; i < size; i++) {
+ if (!Number.isNaN(yValues[i])) {
+ this.coordinatePoint.push({
+ x: xValues[i],
+ y: yValues[i],
+ pointType: PointType.CONTINUE
+ });
+ }
+ }
+ if (!this.coordinatePoint.length) {
+ this.coordinatePoint.push({
+ x: 0,
+ y: 0,
+ pointType: PointType.CONTINUE
+ })
+ }
+ return this.coordinatePoint;
+ }
+
+ private error_func(sampleData: Array): FitRes {
+ let sx: number[] = sampleData.map(value => value.x);
+ let sy: number[] = sampleData.map(value => value.y);
+ let y_predict: number[] = Array(sx.length).fill(0).map((_, index) => {
+ return this.calculate_function(sx[index]);
+ })
+ let error: number = 0;
+ for (let i = 0; i < sx.length; i++) {
+ error += (sy[i] - y_predict[i]) ** 2;
+ }
+ const mean = sy.reduce((acc, val) => acc + val, 0) / sy.length;
+ let sum: number = sy.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0);
+ let R_squared: number = 1 - (error/sum);
+ if (R_squared <= 0) R_squared = 0;
+ let fitRes: FitRes = {
+ error: error,
+ R_squared: R_squared
+ };
+ return fitRes;
+ }
+
+ fit(funcFormat: string, sampleData: Array): void {
+ let fitRes: FitRes = {};
+ if (funcFormat == "a*e^(0.01x)+b") {
+ this.theta = Exponent.gradientDescentExp(sampleData);
+ } else if (funcFormat == "a*log(x,b)+c") {
+ this.theta = Logarithm.gradientDescentLog(sampleData);
+ } else {
+ this.judgeWhichM(funcFormat);
+ fitRes = Matrix.leastSquareMethod(this.m, sampleData);
+ if (fitRes.theta) this.theta = fitRes.theta;
+ }
+ this.getFitFunc(funcFormat);
+ fitRes = this.error_func(sampleData);
+ if (fitRes.error && fitRes.R_squared) {
+ this.error = fitRes.error;
+ this.R_squared = fitRes.R_squared;
+ }
+ }
+}
+
+export let handle: CreatePointGather = new CreatePointGather();
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/utils/algorithm/evaluate.ets b/datafiting/datafit/entry/src/main/ets/utils/algorithm/evaluate.ets
new file mode 100644
index 0000000..b95bac4
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/algorithm/evaluate.ets
@@ -0,0 +1,208 @@
+interface replaceableVar {
+ char: string,
+ value: number
+}
+
+class MathExpressionParser {
+ private tokens: string[];
+ private currentTokenIndex: number;
+ private variables: replaceableVar[];
+
+ constructor() {
+ this.tokens = []
+ this.currentTokenIndex = 0
+ this.variables = []
+ }
+
+ private tokenize(expression: string): string[] {
+ const regex: RegExp = new RegExp("(\\d+\\.?\\d*|\\.\\d+|[a-zA-Z]+|\\S)", "g");
+ const originalTokens = expression.match(regex) || [];
+
+ const Tokens: string[] = [];
+ for (let i = 0; i < originalTokens.length; i++) {
+ Tokens.push(originalTokens[i]);
+ if (i < originalTokens.length - 1) {
+ const currentToken = originalTokens[i];
+ const nextToken = originalTokens[i + 1];
+ if ((this.isNumber(currentToken) && this.isVariable(nextToken)) ||
+ (this.isVariable(currentToken) && this.isVariable(nextToken)) ||
+ (currentToken === ')' && (this.isVariable(nextToken) || this.isNumber(nextToken))) ||
+ (this.isNumber(currentToken) && nextToken === '(') ||
+ (this.isVariable(currentToken) && nextToken === '(')) {
+ Tokens.push('*');
+ }
+ }
+ }
+ return Tokens;
+ }
+
+ private existInArr(token: string): number {
+ for (let i: number = 0; i < this.variables.length; i++) {
+ if (this.variables[i].char == token) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private isNumber(token: string): boolean {
+ const num = Number(token);
+ return !Number.isNaN(num) && Number.isFinite(num);
+ }
+
+ private isVariable(token: string): boolean {
+ const temp: RegExp = new RegExp("^[a-zA-Z]+$")
+ return temp.test(token) && !this.isFunction(token) && token !== "π";
+ }
+
+ private isFunction(token: string): boolean {
+ return ['pow', 'sin', 'cos', 'tan', 'ln', 'sqrt', 'log2', 'log10'].includes(token);
+ }
+
+ private getCurrentToken(): string {
+ return this.tokens[this.currentTokenIndex];
+ }
+
+ private getNextToken(): string {
+ this.currentTokenIndex++;
+ return this.getCurrentToken();
+ }
+
+ private parsePrimaryExpression(): number {
+ const token = this.getCurrentToken();
+ if (token === '(') {
+ this.getNextToken(); // consume '('
+ const result = this.parseExpression();
+ if (this.getCurrentToken() !== ')') {
+ throw new Error("Expected ')' after expression");
+ }
+ this.getNextToken(); // consume ')'
+ return result;
+ } else if (token === 'π') {
+ this.getNextToken(); // consume 'π'
+ return Math.PI;
+ } else if (this.isVariable(token)) {
+ if (this.existInArr(token) != -1) {
+ const value = this.variables[this.existInArr(token)].value;
+ this.getNextToken(); // consume variable
+ return value;
+ } else {
+ throw new Error(`Unknown variable: ${token}`);
+ }
+ } else if (this.isFunction(token)) {
+ return this.parseFunction();
+ } else {
+ const num = Number(token);
+ this.getNextToken(); // consume number
+ return num;
+ }
+ }
+
+ private parseFunction(): number {
+ const functionName = this.getCurrentToken();
+ this.getNextToken(); // consume function name
+ if (this.getCurrentToken() !== '(') {
+ throw new Error(`Expected '(' after function name ${functionName}`);
+ }
+ this.getNextToken(); // consume '('
+
+ const argument1 = this.parseExpression();
+
+ if (functionName === 'pow') {
+ if (this.getCurrentToken() !== ',') {
+ throw new Error(`Expected ',' between arguments for function ${functionName}`);
+ }
+ this.getNextToken(); // consume ','
+ const argument2 = this.parseExpression();
+ if (this.getCurrentToken() !== ')') {
+ throw new Error(`Expected ')' after arguments for function ${functionName}`);
+ }
+ this.getNextToken(); // consume ')'
+ return Math.pow(argument1, argument2);
+ }
+
+ if (this.getCurrentToken() !== ')') {
+ throw new Error(`Expected ')' after argument for function ${functionName}`);
+ }
+ this.getNextToken(); // consume ')'
+
+ switch (functionName) {
+ case 'sin':
+ return Math.sin(argument1);
+ case 'cos':
+ return Math.cos(argument1);
+ case 'tan':
+ return Math.tan(argument1);
+ case 'ln':
+ return Math.log(argument1);
+ case 'sqrt':
+ return Math.sqrt(argument1);
+ case 'log2':
+ return Math.log2(argument1);
+ case 'log10':
+ return Math.log10(argument1);
+ default:
+ throw new Error(`Unknown function: ${functionName}`);
+ }
+ }
+
+ private parseFactor(): number {
+ // 处理一元负号
+ if (this.getCurrentToken() === '-') {
+ this.getNextToken(); // consume '-'
+ return -this.parseFactor();
+ }
+ // 处理初级表达式
+ let result = this.parsePrimaryExpression();
+ // 处理乘法和除法
+ while (this.getCurrentToken() === '*' || this.getCurrentToken() === '/') {
+ const operator = this.getCurrentToken();
+ this.getNextToken(); // consume operator
+ const operand = this.parsePrimaryExpression();
+ if (operator === '*') {
+ result *= operand;
+ } else if (operator === '/') {
+ if (operand === 0) {
+ throw new Error("Division by zero");
+ }
+ result /= operand;
+ }
+ }
+ return result;
+ }
+
+ private parseExpression(): number {
+ let result = this.parseFactor();
+ while (this.getCurrentToken() === '+' || this.getCurrentToken() === '-') {
+ const operator = this.getCurrentToken();
+ this.getNextToken();
+ const operand = this.parseFactor();
+ if (operator === '+') {
+ result += operand;
+ } else if (operator === '-') {
+ result -= operand;
+ }
+ }
+ return result;
+ }
+
+ public evaluate(expression: string, variables: replaceableVar[] = []): number {
+ let temp: RegExp = new RegExp("\\s+", "g");
+ expression = expression.trim().replace(temp, "");
+ temp = new RegExp("(\\([^()]*?(?:\\([^()]*?\\)[^()]*?)*\\)|\\w+)(?:\\*\\*|\\^)(\\([^()]*?(?:\\([^()]*?\\)[^()]*?)*\\)|\\w+)", "g");
+ expression = expression.replace(temp, "pow($1, $2)");
+ this.tokens = this.tokenize(expression);
+ this.currentTokenIndex = 0;
+ this.variables = variables;
+
+ const result = this.parseExpression();
+ if (this.currentTokenIndex !== this.tokens.length) {
+ console.log("Token:" + this.tokens);
+ console.log("当前index:" + this.currentTokenIndex + " " + "当前length:" + this.tokens.length);
+ throw new Error("Unexpected token");
+ }
+ return Number(result.toFixed(4));
+ }
+}
+
+export let mathjs: MathExpressionParser = new MathExpressionParser();
diff --git a/datafiting/datafit/entry/src/main/ets/utils/algorithm/exponentialFit.ets b/datafiting/datafit/entry/src/main/ets/utils/algorithm/exponentialFit.ets
new file mode 100644
index 0000000..f307a02
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/algorithm/exponentialFit.ets
@@ -0,0 +1,48 @@
+import {IPoint} from "../drawBoard/DrawPoint"
+
+export class Exponent {
+ static expFunc(x: number, a: number, b: number): number {
+ return a * Math.exp(0.01 * x) + b;
+ }
+
+ /**
+ * 梯度下降法
+ * @param sampleData
+ * @param learningRate
+ * @param epochs
+ * @returns
+ */
+ static gradientDescentExp(sampleData: Array, learningRate: number = 0.00001, epochs: number = 100000): number[] {
+ let a = 0.001; // 初始化参数
+ let b = 0.001;
+
+ for (let epoch = 0; epoch < epochs; epoch++) {
+ let aGrad = 0;
+ let bGrad = 0;
+ const n = sampleData.length;
+ for (let i = 0; i < n; i++) {
+ const x = sampleData[i].x;
+ const y = sampleData[i].y;
+ const yPredict = Exponent.expFunc(x, a, b);
+ aGrad += -2 * (y - yPredict) * Math.exp(0.01 * x);
+ bGrad += -2 * (y - yPredict);
+ }
+
+ a -= (aGrad / n) * learningRate;
+ b -= (bGrad / n) * learningRate;
+
+ // 检查参数是否过大或过小,若是则终止训练
+ if (Number.isNaN(a) || Number.isNaN(b) || !Number.isFinite(a) || !Number.isFinite(b) || Math.abs(a) > 1e10 || Math.abs(b) > 1e10) {
+ console.error(`Parameters became unstable at epoch ${epoch + 1}`);
+ break;
+ }
+
+ // 每1000个epoch打印一次当前参数
+ if (epoch % 1000 === 0) {
+ console.log(`Epoch ${epoch + 1}, a: ${a}, b: ${b}`);
+ }
+ }
+
+ return [a, b];
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/utils/algorithm/fittingResult.ets b/datafiting/datafit/entry/src/main/ets/utils/algorithm/fittingResult.ets
new file mode 100644
index 0000000..dbff2b4
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/algorithm/fittingResult.ets
@@ -0,0 +1,9 @@
+/**
+ * 拟合结果接口类型,包含拟合的函数系数和协方差矩阵
+ */
+export interface FitRes {
+ theta?: number[];
+ covarianceMatrix?: number[][];
+ error?: number;
+ R_squared?: number;
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/utils/algorithm/least_square.ets b/datafiting/datafit/entry/src/main/ets/utils/algorithm/least_square.ets
new file mode 100644
index 0000000..f4776af
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/algorithm/least_square.ets
@@ -0,0 +1,126 @@
+import {IPoint} from "../drawBoard/DrawPoint"
+import {FitRes} from "./fittingResult"
+
+
+/**
+ * 矩阵运算工具类
+ */
+export class Matrix {
+ /**
+ * 矩阵转置
+ * @param matrix
+ * @returns
+ */
+ static transpose(matrix: number[][]): number[][] {
+ return matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));
+ }
+
+ /**
+ * 矩阵乘法
+ * @param a
+ * @param b
+ * @returns
+ */
+ static multiplyMatrices(a: number[][], b: number[][]): number[][] {
+ const result: number[][] = [];
+ for (let i = 0; i < a.length; i++) {
+ // result[i] = [];
+ result.push([]);
+ for (let j = 0; j < b[0].length; j++) {
+ let sum = 0;
+ for (let k = 0; k < b.length; k++) {
+ sum += a[i][k] * b[k][j];
+ }
+ // result[i][j] = sum;
+ result[i].push(sum);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 矩阵求逆
+ * @param matrix
+ * @returns
+ */
+ static inverseMatrix(matrix: number[][]): number[][] {
+ const size = matrix.length;
+ const augmented = matrix.map((row, i) => [
+ ...row,
+ ...Array(size).fill(0).map((_, j) => (i === j ? 1 : 0))
+ ]);
+
+ for (let i = 0; i < size; i++) {
+ let maxRow = i;
+ for (let k = i + 1; k < size; k++) {
+ if (Math.abs(augmented[k][i]) > Math.abs(augmented[maxRow][i])) {
+ maxRow = k;
+ }
+ }
+
+ let temp = augmented[i];
+ augmented[i] = augmented[maxRow];
+ augmented[maxRow] = temp;
+ // [augmented[i], augmented[maxRow]] = [augmented[maxRow], augmented[i]];
+
+ const divisor = augmented[i][i];
+ for (let j = 0; j < augmented[0].length; j++) {
+ augmented[i][j] /= divisor;
+ }
+
+ for (let k = 0; k < size; k++) {
+ if (k !== i) {
+ const factor = augmented[k][i];
+ for (let j = 0; j < augmented[0].length; j++) {
+ augmented[k][j] -= factor * augmented[i][j];
+ }
+ }
+ }
+ }
+
+ return augmented.map(row => row.slice(size));
+ }
+
+ /**
+ * 最小二乘法
+ * @param m
+ * @param sampleData
+ * @returns
+ */
+ static leastSquareMethod(m: number, sampleData: Array): FitRes {
+ const x = sampleData.map(d => d.x);
+ const y = sampleData.map(d => d.y);
+
+ const A = x.map(xi => {
+ const row: number[] = [];
+ for (let i = m; i >= 0; i--) {
+ row.push(Math.pow(xi, i));
+ }
+ return row;
+ });
+
+ const yVec = y.map(yi => [yi]);
+
+ const At = Matrix.transpose(A);
+ const AtA = Matrix.multiplyMatrices(At, A);
+ const Aty = Matrix.multiplyMatrices(At, yVec);
+
+ const invAtA = Matrix.inverseMatrix(AtA);
+ const theta = Matrix.multiplyMatrices(invAtA, Aty);
+
+ const residuals = yVec.map((yi, i) => [yi[0] - A[i].reduce((sum, aij, j) => sum + aij * theta[j][0], 0)]);
+ const residualsSquaredSum = residuals.reduce((sum, ri) => sum + ri[0] ** 2, 0);
+
+ const degreesOfFreedom = y.length - (m + 1);
+ const meanSquaredError = residualsSquaredSum / degreesOfFreedom;
+
+ const covarianceMatrix = invAtA.map(row => row.map(value => value * meanSquaredError));
+
+ const fitRes: FitRes = {
+ theta: theta.map(row => row[0]),
+ covarianceMatrix: covarianceMatrix
+ };
+
+ return fitRes;
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/utils/algorithm/logarithmicFit.ets b/datafiting/datafit/entry/src/main/ets/utils/algorithm/logarithmicFit.ets
new file mode 100644
index 0000000..29ff938
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/algorithm/logarithmicFit.ets
@@ -0,0 +1,65 @@
+import {IPoint} from "../drawBoard/DrawPoint"
+import {Matrix} from "./least_square"
+
+export class Logarithm {
+ static logFunc(x: number, a: number, b: number, c: number): number {
+ return a * Math.log(x) / Math.log(b) + c;
+ }
+
+ linearRegressionLog(sampleData: Array, base: number): number[] {
+ const A = sampleData.map((value) => [Math.log(value.x) / Math.log(base), 1]);
+ const y = sampleData.map((value) => value.y);
+
+ const At = Matrix.transpose(A);
+ const AtA = Matrix.multiplyMatrices(At, A);
+ const Aty = Matrix.multiplyMatrices(At, y.map(v => [v]));
+
+ const invAtA = Matrix.inverseMatrix(AtA);
+ const theta = Matrix.multiplyMatrices(invAtA, Aty);
+
+ const a: number = theta.map(row => row[0])[0];
+ const c: number = theta.map(row => row[0])[1];
+
+ return [ a, c ];
+ }
+
+ static gradientDescentLog(sampleData: Array, learningRate: number = 0.00001, epochs: number = 100000): number[] {
+ let a = 0.001; // 初始化参数
+ let b = 2; // 初始对数底数,需 > 0 且 ≠ 1
+ let c = 0.001;
+
+ const n = sampleData.length;
+
+ for (let epoch = 0; epoch < epochs; epoch++) {
+ let aGrad = 0;
+ let bGrad = 0;
+ let cGrad = 0;
+
+ for (let i = 0; i < n; i++) {
+ const x = sampleData[i].x;
+ const y = sampleData[i].y;
+ let yPredict = Logarithm.logFunc(x, a, b, c);
+ let logX = Math.log(x);
+ let logB = Math.log(b);
+ if (x > 0 && b > 0 && b != 1) {
+ yPredict = Logarithm.logFunc(x, a, b, c);
+ logX = Math.log(x);
+ logB = Math.log(b);
+ } else continue;
+ aGrad += -2 * (y - yPredict) * (logX / logB);
+ bGrad += -2 * (y - yPredict) * (-a * logX / (logB * logB) * (1 / b)); // 链式法则计算 b 的梯度
+ cGrad += -2 * (y - yPredict);
+ }
+
+ a -= (aGrad / n) * learningRate;
+ c -= (cGrad / n) * learningRate;
+ if (b - (bGrad / n) * learningRate <= 0) break;
+ else b -= (bGrad / n) * learningRate;
+ if (Number.isNaN(a) || Number.isNaN(b) || Number.isNaN(c)) {
+ console.error(`Parameters became NaN at epoch ${epoch + 1}`);
+ break;
+ }
+ }
+ return [ a, b, c ];
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/ets/utils/drawBoard/BoardType.ets b/datafiting/datafit/entry/src/main/ets/utils/drawBoard/BoardType.ets
new file mode 100644
index 0000000..1d0a379
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/drawBoard/BoardType.ets
@@ -0,0 +1,425 @@
+import { IPoint, PointType } from './DrawPoint';
+//标准值
+/**
+ * imageShow组件的大小(vp)
+ */
+export const I_WIDTH = 480;//3568 340
+/**
+ * imageShow组件的大小(vp)
+ */
+export const I_HEIGHT = 250;//3568 160
+/**
+ * 第一个X刻度对应的值
+ */
+const X_VALUE = 100
+/**
+ * 第一个Y刻度对应的值
+ */
+const Y_VALUE = 100
+
+export const SETTING:RenderingContextSettings = new RenderingContextSettings(true)
+export const CONTEXT:CanvasRenderingContext2D = new CanvasRenderingContext2D(SETTING)
+export const FIT_CONTEXT:CanvasRenderingContext2D = new CanvasRenderingContext2D(SETTING)
+CONTEXT.font = '10px sans-serif'
+export enum Quadrant{
+ ONE = 1,
+ FOUR = 4
+}
+
+export abstract class BoardInfo{
+ /**
+ * x刻度之间的像素距离
+ * 初始化后不允许修改
+ */
+ XGapLen:number
+ /**
+ * y刻度之间的像素距离
+ * 初始化后不允许修改
+ */
+ YGapLen:number
+ /**
+ * x刻度个数 (+)
+ * 初始化后不允许修改
+ */
+ XCount:number
+ /**
+ * y刻度个数 (+)
+ * 初始化后不允许修改
+ */
+ YCount:number
+ /**
+ * 原点的x坐标
+ * 初始化后不可修改
+ */
+ X_centre:number = 0
+ /**
+ * 原点的y坐标
+ * 初始化后不可修改
+ */
+ Y_centre:number = 0
+ /**
+ * canvas组件的margin (不包括箭头)
+ * 初始化后不可修改
+ */
+ margin:number
+ /**
+ * 显示象限
+ * 初始化后不可修改
+ */
+ quadrant:Quadrant
+ /**
+ * 画板的宽
+ * 初始化后不可修改
+ */
+ width:number
+ /**
+ * 画板的高
+ * 初始化后不可修改
+ */
+ height:number
+
+ //以下属性可修改
+
+ /**
+ * 单位X刻度对应的虚拟像素
+ * 根据倍数动态修正
+ */
+ XUnit2vp:number
+ /**
+ * 单位Y刻度对应虚拟像素
+ * 根据倍数动态修正
+ */
+ YUnit2vp:number
+ /**
+ * 第一个X刻度对应的值 (+)
+ * 根据倍数动态修正
+ */
+ XValue:number = X_VALUE
+ /**
+ * 第一个Y刻度对应的值 (+)
+ * 根据倍数动态修正
+ */
+ YValue:number = Y_VALUE
+
+ /**
+ * 虚拟点集
+ */
+ virtualPoints:Array = []
+
+ /**
+ * 拟合后得到的函数的点集
+ */
+ boardPoints:Array = []
+
+ constructor(margin:number,quadrant:Quadrant,Xgl:number,Ygl:number,XC:number,YC:number) {
+ this.margin = margin
+ this.quadrant = quadrant
+ //画板属性
+ this.width = I_WIDTH - 2 * this.margin
+ this.height = I_HEIGHT - 2 * this.margin
+ //定义单位刻度对应像素
+ this.XGapLen = Xgl
+ this.YGapLen = Ygl
+ this.XUnit2vp = Xgl/X_VALUE
+ this.YUnit2vp = Ygl/Y_VALUE
+ //定义个数
+ this.XCount = XC
+ this.YCount = YC
+ }
+
+ /**
+ * 绘制坐标轴
+ */
+ public abstract drawAxis();
+
+ /**
+ * 设置画板上的xy数对
+ * 同时根据xy数对计算出合适的
+ *
+ * 初始化点集 需要保证xy都有赋值
+ *
+ * 返回virtualPoints
+ */
+ public initMap(virtualPoints?:Array){
+ this.virtualPoints = []
+ if(virtualPoints){
+ this.virtualPoints = virtualPoints
+ }else{
+ let x = 0;
+ let y = 0
+ if(this.quadrant == Quadrant.ONE){
+ for (let index = 0; index < 20; index++) {
+ x = Math.random()*1000
+ y = Math.random()*1000
+ this.virtualPoints.push({x:x,y:y,pointType:PointType.CONTINUE})
+ }
+ }else{
+ for (let index = 0; index < 20; index++) {
+ x = ((Math.random()*2)-1)*500
+ y = ((Math.random()*2)-1)*500
+ this.virtualPoints.push({x:x,y:y,pointType:PointType.CONTINUE})
+ }
+ }
+ }
+ this.boardPoints = []
+ this.transToBoardPoints()
+
+ return this.virtualPoints
+ }
+
+
+ /**
+ * 绘制拟合函数
+ */
+ public drawFitFunc(points:Array){
+ this.transToBoardPoints(points)
+ this.drawGraph(FIT_CONTEXT,points)
+ }
+
+ /**
+ * 绘制散点图
+ */
+ public drawPoints(context:CanvasRenderingContext2D = CONTEXT,boardPoints:Array = this.boardPoints){
+ context.beginPath()
+ for (let index = 0; index < boardPoints.length; index++) {
+ context.fillRect(vp2px(boardPoints[index].x-1),vp2px(boardPoints[index].y-1),vp2px(1.5),vp2px(1.5))
+ }
+ context.stroke()
+ }
+
+ /**
+ * 绘制折线
+ */
+ public drawGraph(context:CanvasRenderingContext2D = FIT_CONTEXT,boardPoints:Array = this.boardPoints){
+ FIT_CONTEXT.strokeStyle = 'red'
+ let isMeetDisContinue = false
+ let i = 0
+ while(boardPoints[i].pointType == PointType.DISCONTINUE && i <= boardPoints.length - 1){
+ i++
+ }
+ if(i == boardPoints.length){
+ //全间断点
+ return
+ }
+ if(i != 0){
+ context.fillRect(vp2px(boardPoints[i].x - 1),vp2px(boardPoints[i].y - 1),vp2px(1.5),vp2px(1.5))
+ }
+ context.moveTo(vp2px(boardPoints[i].x),vp2px(boardPoints[i].y))
+ //间断点画圆
+ for (let index = i + 1; index < boardPoints.length ; index++) {
+ if(boardPoints[index].pointType == PointType.DISCONTINUE){
+ isMeetDisContinue = true
+ continue
+ }
+ if(isMeetDisContinue){
+ context.moveTo(vp2px(boardPoints[index].x),vp2px(boardPoints[index].y))
+ context.fillRect(vp2px(boardPoints[index].x - 1),vp2px(boardPoints[index].y - 1),vp2px(1.5),vp2px(1.5))
+ isMeetDisContinue = false
+ }else{
+ context.lineTo(vp2px(boardPoints[index].x),vp2px(boardPoints[index].y))
+ }
+ }
+ context.stroke()
+ }
+
+
+ /**
+ * 将虚拟点集(二维)转变为画布点集
+ */
+ protected transToBoardPoints(virtualPoints?:Array){
+ if(virtualPoints){
+ for (let index = 0; index < virtualPoints.length; index++) {
+ virtualPoints[index].x = this.getXPosition(virtualPoints[index].x)
+ virtualPoints[index].y = this.getYPosition(virtualPoints[index].y)
+ virtualPoints[index].pointType = virtualPoints[index].pointType
+ }
+ return
+ }
+ for (let index = 0; index < this.virtualPoints.length; index++) {
+ this.boardPoints.push({x:this.getXPosition(this.virtualPoints[index].x),y:this.getYPosition(this.virtualPoints[index].y),pointType:this.virtualPoints[index].pointType})
+ }
+ }
+
+ /**
+ * 将虚拟坐标转变为画布坐标x(二维)
+ */
+ private getXPosition(x:number){
+ return this.X_centre + this.XUnit2vp*x
+ }
+ /**
+ * 将虚拟坐标转变为画布坐标x(二维)
+ */
+ private getYPosition(y:number){
+ return this.Y_centre - this.YUnit2vp*y
+ }
+}
+
+
+class board4Q2D extends BoardInfo{
+
+ constructor() {
+ super(5,Quadrant.FOUR,43,21,5,5);//根据具体环境配置
+ this.X_centre = (2 * this.margin + this.width)/2
+ this.Y_centre = (2 * this.margin + this.height)/2
+ }
+
+ public drawAxis(){
+ CONTEXT.beginPath()
+ CONTEXT.moveTo(vp2px(this.margin),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre + 3))
+ CONTEXT.lineTo(vp2px(this.width + this.margin + 3),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre - 3))
+ CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre))
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(this.height + this.margin))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.X_centre - 3),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin - 3))
+ CONTEXT.lineTo(vp2px(this.X_centre + 3),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin))
+ CONTEXT.fill()
+ CONTEXT.fillText("0",vp2px(this.X_centre + 2),vp2px(this.Y_centre + 15))
+ let valueX = this.X_centre - this.XValue * this.XUnit2vp * (this.XCount + 1)
+ let valueY = this.Y_centre + 6
+ let value = -this.XValue * this.XCount
+ let count = 2 * this.XCount
+ //绘制X轴
+ while(--count >= 0) {
+ valueX += this.XGapLen
+ if(value == 0){
+ value += this.XValue
+ valueX += this.XGapLen
+ }
+ CONTEXT.moveTo(vp2px(valueX),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(valueX),vp2px(this.Y_centre - 5))
+ CONTEXT.fillText(value.toString(),vp2px(valueX - this.getXTextBias(value.toString()) - 6),vp2px(valueY + 7))
+ value += this.XValue
+ }
+ //绘制Y轴
+ valueX = this.X_centre
+ valueY = this.Y_centre + this.YValue * this.YUnit2vp * (this.YCount + 1)
+ value = -this.YValue * this.YCount
+ count = 2 * this.YCount
+ while(--count >= 0) {
+ valueY -= this.YGapLen
+ if(value == 0){
+ value += this.YValue
+ valueY -= this.YGapLen
+ }
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(valueY))
+ CONTEXT.lineTo(vp2px(this.X_centre + 3),vp2px(valueY))
+ CONTEXT.fillText(value.toString(),vp2px(valueX - this.getYTextBias(value.toString()) + 15),vp2px(valueY + 5))
+ value += this.YValue
+ }
+ CONTEXT.stroke()
+ }
+
+ /**
+ * 获取修正后的X刻度对应的文本的显示横向偏移量
+ */
+ private getXTextBias(value:string){
+
+ let bias = value.length
+ let flag = 1
+ if(value[0] == '-'){
+ flag = -2
+ }
+ return (bias * (bias - 1))/2 + 1 + flag * this.XGapLen/50 ;
+ }
+ /**
+ * 获取修正后的Y刻度对应的文本的显示横向偏移量
+ */
+ private getYTextBias(value:string){
+ let bias = value.length
+ if(bias == 1){
+ return 1
+ }
+ return bias * 3.5 + 1;
+ }
+
+}
+
+class board1Q2D extends BoardInfo{
+
+ constructor() {
+ super(20,Quadrant.ONE,42,20,10,10);//根据具体环境配置
+
+ this.X_centre = this.margin
+ this.Y_centre = this.margin + this.height
+ }
+
+ public drawAxis(){
+ CONTEXT.beginPath()
+ CONTEXT.moveTo(vp2px(this.margin),vp2px(this.margin + this.height))
+ CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.margin - 3),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin - 3))
+ CONTEXT.lineTo(vp2px(this.margin + 3),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin))
+ CONTEXT.fill()
+ CONTEXT.moveTo(vp2px(this.margin),vp2px(this.margin + this.height))
+ CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height))
+ CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height + 3))
+ CONTEXT.lineTo(vp2px(this.margin + this.width + 3),vp2px(this.margin + this.height))
+ CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height - 3))
+ CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height))
+ CONTEXT.fill()
+ CONTEXT.fillText("0",vp2px(this.X_centre - 10),vp2px(this.Y_centre + 10))
+ let valueX = this.X_centre
+ let valueY = this.Y_centre + 6
+ let value = this.XValue
+ let count = this.XCount
+ //x轴
+ while(--count >= 0) {
+ valueX += this.XGapLen
+ CONTEXT.moveTo(vp2px(valueX),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(valueX),vp2px(this.Y_centre - 5))
+ CONTEXT.fillText(value.toString(),vp2px(valueX-this.getXTextBias(value.toString()) - 10),vp2px(valueY + 10))
+ value += this.XValue
+ }
+ //y轴
+ valueX = this.X_centre
+ valueY = this.Y_centre
+ value = this.YValue
+ count = this.YCount
+ while(--count >= 0) {
+ valueY -= this.YGapLen
+ if(value == 0){
+ value += this.YValue
+ valueY -= this.YGapLen
+ }
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(valueY))
+ CONTEXT.lineTo(vp2px(this.X_centre + 5),vp2px(valueY))
+ CONTEXT.fillText(value.toString(),vp2px(valueX + 20 - this.getYTextBias(value.toString())),vp2px(valueY + 3))
+ value += this.YValue
+ }
+ CONTEXT.stroke()
+ }
+
+ /**
+ * 获取修正后的X刻度对应的文本的显示横向偏移量
+ */
+ private getXTextBias(value:string){
+
+ let bias = value.length
+ let flag = 1
+ if(value[0] == '-'){
+ flag = -2
+ }
+ return (bias * (bias - 1))/2 + 1 + flag * this.XGapLen/50;
+ }
+ /**
+ * 获取修正后的Y刻度对应的文本的显示横向偏移量
+ */
+ private getYTextBias(value:string){
+ let bias = value.length
+ if(bias == 1){
+ return 1
+ }
+ return bias * 3.5;
+ }
+
+}
+
+export let B4Q2D:BoardInfo = new board4Q2D()
+export let B1Q2D:BoardInfo = new board1Q2D()
diff --git a/datafiting/datafit/entry/src/main/ets/utils/drawBoard/DrawPoint.ets b/datafiting/datafit/entry/src/main/ets/utils/drawBoard/DrawPoint.ets
new file mode 100644
index 0000000..e8b9fa2
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/ets/utils/drawBoard/DrawPoint.ets
@@ -0,0 +1,15 @@
+export enum PointType{
+ DISCONTINUE = 0,
+ CONTINUE = 1
+}
+/**
+ * 虚拟点集
+ * 根据函数关系和步长、个数直接得到的点集
+ */
+export interface IPoint{
+ x:number
+
+ y:number
+
+ pointType:PointType
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/module.json5 b/datafiting/datafit/entry/src/main/module.json5
new file mode 100644
index 0000000..8a612fc
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/module.json5
@@ -0,0 +1,47 @@
+{
+ "module": {
+ "requestPermissions": [
+ {
+ "name": "ohos.permission.FILE_ACCESS_MANAGER"
+ },
+ {
+ "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
+ }
+
+ ],
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "orientation": "landscape",
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/resources/base/element/color.json b/datafiting/datafit/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/resources/base/element/string.json b/datafiting/datafit/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000..f945955
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/resources/base/media/icon.png b/datafiting/datafit/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/datafiting/datafit/entry/src/main/resources/base/media/icon.png differ
diff --git a/datafiting/datafit/entry/src/main/resources/base/media/startIcon.png b/datafiting/datafit/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000..366f764
Binary files /dev/null and b/datafiting/datafit/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/datafiting/datafit/entry/src/main/resources/base/profile/main_pages.json b/datafiting/datafit/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000..55c3f00
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/resources/en_US/element/string.json b/datafiting/datafit/entry/src/main/resources/en_US/element/string.json
new file mode 100644
index 0000000..f945955
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/resources/en_US/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/main/resources/zh_CN/element/string.json b/datafiting/datafit/entry/src/main/resources/zh_CN/element/string.json
new file mode 100644
index 0000000..597ecf9
--- /dev/null
+++ b/datafiting/datafit/entry/src/main/resources/zh_CN/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "模块描述"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/ohosTest/ets/test/Ability.test.ets b/datafiting/datafit/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000..8aa3749
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,35 @@
+import hilog from '@ohos.hilog';
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function abilityTest() {
+ describe('ActsAbilityTest', () => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ })
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ })
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ })
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ })
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ })
+ })
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/ohosTest/ets/test/List.test.ets b/datafiting/datafit/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000..794c7dc
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/ohosTest/ets/testability/TestAbility.ets b/datafiting/datafit/entry/src/ohosTest/ets/testability/TestAbility.ets
new file mode 100644
index 0000000..9484761
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/ets/testability/TestAbility.ets
@@ -0,0 +1,50 @@
+import UIAbility from '@ohos.app.ability.UIAbility';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import hilog from '@ohos.hilog';
+import { Hypium } from '@ohos/hypium';
+import testsuite from '../test/List.test';
+import window from '@ohos.window';
+import Want from '@ohos.app.ability.Want';
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+
+export default class TestAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
+ let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator;
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs;
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
+ hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
+ }
+
+ onDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
+ windowStage.loadContent('testability/pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
+ JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
+ }
+
+ onForeground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
+ }
+
+ onBackground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/ohosTest/ets/testability/pages/Index.ets b/datafiting/datafit/entry/src/ohosTest/ets/testability/pages/Index.ets
new file mode 100644
index 0000000..423b427
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/ets/testability/pages/Index.ets
@@ -0,0 +1,17 @@
+@Entry
+@Component
+struct Index {
+ @State message: string = 'Hello World';
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/datafiting/datafit/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
new file mode 100644
index 0000000..917d27a
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
@@ -0,0 +1,47 @@
+import hilog from '@ohos.hilog';
+import TestRunner from '@ohos.application.testRunner';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import Want from '@ohos.app.ability.Want';
+
+let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined
+let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined
+
+async function onAbilityCreateCallback() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
+}
+
+async function addAbilityMonitorCallback(err : Error) {
+ hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
+ }
+
+ async onRun() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ const bundleName = abilityDelegatorArguments.bundleName;
+ const testAbilityName = 'TestAbility';
+ let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ const want: Want = {
+ bundleName: bundleName,
+ abilityName: testAbilityName
+ };
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ abilityDelegator.startAbility(want, (err, data) => {
+ hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
+ hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? '');
+ })
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/ohosTest/module.json5 b/datafiting/datafit/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000..4fc9701
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "description": "$string:module_test_desc",
+ "mainElement": "TestAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:test_pages",
+ "abilities": [
+ {
+ "name": "TestAbility",
+ "srcEntry": "./ets/testability/TestAbility.ets",
+ "description": "$string:TestAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:TestAbility_label",
+ "exported": true,
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "skills": [
+ {
+ "actions": [
+ "action.system.home"
+ ],
+ "entities": [
+ "entity.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/datafiting/datafit/entry/src/ohosTest/resources/base/element/color.json b/datafiting/datafit/entry/src/ohosTest/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/ohosTest/resources/base/element/string.json b/datafiting/datafit/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000..65d8fa5
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_test_desc",
+ "value": "test ability description"
+ },
+ {
+ "name": "TestAbility_desc",
+ "value": "the test ability"
+ },
+ {
+ "name": "TestAbility_label",
+ "value": "test label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/ohosTest/resources/base/media/icon.png b/datafiting/datafit/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000..ce307a8
Binary files /dev/null and b/datafiting/datafit/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/datafiting/datafit/entry/src/ohosTest/resources/base/profile/test_pages.json b/datafiting/datafit/entry/src/ohosTest/resources/base/profile/test_pages.json
new file mode 100644
index 0000000..b7e7343
--- /dev/null
+++ b/datafiting/datafit/entry/src/ohosTest/resources/base/profile/test_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "testability/pages/Index"
+ ]
+}
diff --git a/datafiting/datafit/entry/src/test/List.test.ets b/datafiting/datafit/entry/src/test/List.test.ets
new file mode 100644
index 0000000..bb5b5c3
--- /dev/null
+++ b/datafiting/datafit/entry/src/test/List.test.ets
@@ -0,0 +1,5 @@
+import localUnitTest from './LocalUnit.test';
+
+export default function testsuite() {
+ localUnitTest();
+}
\ No newline at end of file
diff --git a/datafiting/datafit/entry/src/test/LocalUnit.test.ets b/datafiting/datafit/entry/src/test/LocalUnit.test.ets
new file mode 100644
index 0000000..ed22d4d
--- /dev/null
+++ b/datafiting/datafit/entry/src/test/LocalUnit.test.ets
@@ -0,0 +1,33 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function localUnitTest() {
+ describe('localUnitTest',() => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ });
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ });
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ });
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ });
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ });
+ });
+}
\ No newline at end of file
diff --git a/datafiting/datafit/hvigor/hvigor-config.json5 b/datafiting/datafit/hvigor/hvigor-config.json5
new file mode 100644
index 0000000..1a47490
--- /dev/null
+++ b/datafiting/datafit/hvigor/hvigor-config.json5
@@ -0,0 +1,18 @@
+{
+ "hvigorVersion": "3.0.9",
+ "dependencies": {
+ "@ohos/hvigor-ohos-plugin": "3.0.9"
+ },
+ "execution": {
+ // "daemon": true, /* Enable daemon compilation. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Default: false */
+ }
+}
diff --git a/datafiting/datafit/hvigor/hvigor-wrapper.js b/datafiting/datafit/hvigor/hvigor-wrapper.js
new file mode 100644
index 0000000..372eae8
--- /dev/null
+++ b/datafiting/datafit/hvigor/hvigor-wrapper.js
@@ -0,0 +1 @@
+"use strict";var u=require("path"),D=require("os"),e=require("fs"),t=require("crypto"),r=require("child_process"),n="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},i={},C={},F=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(C,"__esModule",{value:!0}),C.maxPathLength=C.isMac=C.isLinux=C.isWindows=void 0;const E=F(D),A="Windows_NT",o="Darwin";function a(){return E.default.type()===A}function c(){return E.default.type()===o}C.isWindows=a,C.isLinux=function(){return"Linux"===E.default.type()},C.isMac=c,C.maxPathLength=function(){return c()?1016:a()?259:4095},function(e){var t=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),r=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),i=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&t(D,u,e);return r(D,u),D};Object.defineProperty(e,"__esModule",{value:!0}),e.WORK_SPACE=e.HVIGOR_PROJECT_WRAPPER_HOME=e.HVIGOR_PROJECT_ROOT_DIR=e.HVIGOR_PROJECT_CACHES_HOME=e.HVIGOR_PNPM_STORE_PATH=e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=e.PROJECT_CACHES=e.HVIGOR_WRAPPER_TOOLS_HOME=e.HVIGOR_USER_HOME=e.DEFAULT_PACKAGE_JSON=e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME=e.PNPM=e.HVIGOR=e.NPM_TOOL=e.PNPM_TOOL=e.HVIGOR_ENGINE_PACKAGE_NAME=void 0;const F=i(D),E=i(u),A=C;e.HVIGOR_ENGINE_PACKAGE_NAME="@ohos/hvigor",e.PNPM_TOOL=(0,A.isWindows)()?"pnpm.cmd":"pnpm",e.NPM_TOOL=(0,A.isWindows)()?"npm.cmd":"npm",e.HVIGOR="hvigor",e.PNPM="pnpm",e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME="hvigor-config.json5",e.DEFAULT_PACKAGE_JSON="package.json",e.HVIGOR_USER_HOME=E.resolve(F.homedir(),".hvigor"),e.HVIGOR_WRAPPER_TOOLS_HOME=E.resolve(e.HVIGOR_USER_HOME,"wrapper","tools"),e.PROJECT_CACHES="project_caches",e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=E.resolve(e.HVIGOR_WRAPPER_TOOLS_HOME,"node_modules",".bin",e.PNPM_TOOL),e.HVIGOR_PNPM_STORE_PATH=E.resolve(e.HVIGOR_USER_HOME,"caches"),e.HVIGOR_PROJECT_CACHES_HOME=E.resolve(e.HVIGOR_USER_HOME,e.PROJECT_CACHES),e.HVIGOR_PROJECT_ROOT_DIR=process.cwd(),e.HVIGOR_PROJECT_WRAPPER_HOME=E.resolve(e.HVIGOR_PROJECT_ROOT_DIR,e.HVIGOR),e.WORK_SPACE="workspace"}(i);var s={},l={};Object.defineProperty(l,"__esModule",{value:!0}),l.logInfoPrintConsole=l.logErrorAndExit=void 0,l.logErrorAndExit=function(u){u instanceof Error?console.error(u.message):console.error(u),process.exit(-1)},l.logInfoPrintConsole=function(u){console.log(u)};var B=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),d=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),f=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&B(D,u,e);return d(D,u),D};Object.defineProperty(s,"__esModule",{value:!0});var _=s.executeBuild=void 0;const p=f(e),O=f(u),h=l;_=s.executeBuild=function(u){const D=O.resolve(u,"node_modules","@ohos","hvigor","bin","hvigor.js");try{const u=p.realpathSync(D);require(u)}catch(e){(0,h.logErrorAndExit)(`Error: ENOENT: no such file ${D},delete ${u} and retry.`)}};var P={},v={};!function(u){var D=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(u,"__esModule",{value:!0}),u.hashFile=u.hash=u.createHash=void 0;const r=D(t),i=D(e);u.createHash=(u="MD5")=>r.default.createHash(u);u.hash=(D,e)=>(0,u.createHash)(e).update(D).digest("hex");u.hashFile=(D,e)=>{if(i.default.existsSync(D))return(0,u.hash)(i.default.readFileSync(D,"utf-8"),e)}}(v);var g={},m={},R={};Object.defineProperty(R,"__esModule",{value:!0}),R.Unicode=void 0;class y{}R.Unicode=y,y.SPACE_SEPARATOR=/[\u1680\u2000-\u200A\u202F\u205F\u3000]/,y.ID_START=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/,y.ID_CONTINUE=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/,Object.defineProperty(m,"__esModule",{value:!0}),m.JudgeUtil=void 0;const I=R;m.JudgeUtil=class{static isIgnoreChar(u){return"string"==typeof u&&("\t"===u||"\v"===u||"\f"===u||" "===u||" "===u||"\ufeff"===u||"\n"===u||"\r"===u||"\u2028"===u||"\u2029"===u)}static isSpaceSeparator(u){return"string"==typeof u&&I.Unicode.SPACE_SEPARATOR.test(u)}static isIdStartChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||"$"===u||"_"===u||I.Unicode.ID_START.test(u))}static isIdContinueChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||u>="0"&&u<="9"||"$"===u||"_"===u||""===u||""===u||I.Unicode.ID_CONTINUE.test(u))}static isDigitWithoutZero(u){return/[1-9]/.test(u)}static isDigit(u){return"string"==typeof u&&/[0-9]/.test(u)}static isHexDigit(u){return"string"==typeof u&&/[0-9A-Fa-f]/.test(u)}};var N=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(g,"__esModule",{value:!0}),g.parseJsonText=g.parseJsonFile=void 0;const b=N(e),S=N(D),w=N(u),H=m;var x;!function(u){u[u.Char=0]="Char",u[u.EOF=1]="EOF",u[u.Identifier=2]="Identifier"}(x||(x={}));let M,T,V,G,j,J,W="start",U=[],L=0,$=1,k=0,K=!1,z="default",q="'",Z=1;function X(u,D=!1){T=String(u),W="start",U=[],L=0,$=1,k=0,G=void 0,K=D;do{M=Q(),nu[W]()}while("eof"!==M.type);return G}function Q(){for(z="default",j="",q="'",Z=1;;){J=Y();const u=Du[z]();if(u)return u}}function Y(){if(T[L])return String.fromCodePoint(T.codePointAt(L))}function uu(){const u=Y();return"\n"===u?($++,k=0):u?k+=u.length:k++,u&&(L+=u.length),u}g.parseJsonFile=function(u,D=!1,e="utf-8"){const t=b.default.readFileSync(w.default.resolve(u),{encoding:e});try{return X(t,D)}catch(D){if(D instanceof SyntaxError){const e=D.message.split("at");if(2===e.length)throw new Error(`${e[0].trim()}${S.default.EOL}\t at ${u}:${e[1].trim()}`)}throw new Error(`${u} is not in valid JSON/JSON5 format.`)}},g.parseJsonText=X;const Du={default(){switch(J){case"/":return uu(),void(z="comment");case void 0:return uu(),eu("eof")}if(!H.JudgeUtil.isIgnoreChar(J)&&!H.JudgeUtil.isSpaceSeparator(J))return Du[W]();uu()},start(){z="value"},beforePropertyName(){switch(J){case"$":case"_":return j=uu(),void(z="identifierName");case"\\":return uu(),void(z="identifierNameStartEscape");case"}":return eu("punctuator",uu());case'"':case"'":return q=J,uu(),void(z="string")}if(H.JudgeUtil.isIdStartChar(J))return j+=uu(),void(z="identifierName");throw Eu(x.Char,uu())},afterPropertyName(){if(":"===J)return eu("punctuator",uu());throw Eu(x.Char,uu())},beforePropertyValue(){z="value"},afterPropertyValue(){switch(J){case",":case"}":return eu("punctuator",uu())}throw Eu(x.Char,uu())},beforeArrayValue(){if("]"===J)return eu("punctuator",uu());z="value"},afterArrayValue(){switch(J){case",":case"]":return eu("punctuator",uu())}throw Eu(x.Char,uu())},end(){throw Eu(x.Char,uu())},comment(){switch(J){case"*":return uu(),void(z="multiLineComment");case"/":return uu(),void(z="singleLineComment")}throw Eu(x.Char,uu())},multiLineComment(){switch(J){case"*":return uu(),void(z="multiLineCommentAsterisk");case void 0:throw Eu(x.Char,uu())}uu()},multiLineCommentAsterisk(){switch(J){case"*":return void uu();case"/":return uu(),void(z="default");case void 0:throw Eu(x.Char,uu())}uu(),z="multiLineComment"},singleLineComment(){switch(J){case"\n":case"\r":case"\u2028":case"\u2029":return uu(),void(z="default");case void 0:return uu(),eu("eof")}uu()},value(){switch(J){case"{":case"[":return eu("punctuator",uu());case"n":return uu(),tu("ull"),eu("null",null);case"t":return uu(),tu("rue"),eu("boolean",!0);case"f":return uu(),tu("alse"),eu("boolean",!1);case"-":case"+":return"-"===uu()&&(Z=-1),void(z="numerical");case".":case"0":case"I":case"N":return void(z="numerical");case'"':case"'":return q=J,uu(),j="",void(z="string")}if(void 0===J||!H.JudgeUtil.isDigitWithoutZero(J))throw Eu(x.Char,uu());z="numerical"},numerical(){switch(J){case".":return j=uu(),void(z="decimalPointLeading");case"0":return j=uu(),void(z="zero");case"I":return uu(),tu("nfinity"),eu("numeric",Z*(1/0));case"N":return uu(),tu("aN"),eu("numeric",NaN)}if(void 0!==J&&H.JudgeUtil.isDigitWithoutZero(J))return j=uu(),void(z="decimalInteger");throw Eu(x.Char,uu())},zero(){switch(J){case".":case"e":case"E":return void(z="decimal");case"x":case"X":return j+=uu(),void(z="hexadecimal")}return eu("numeric",0)},decimalInteger(){switch(J){case".":case"e":case"E":return void(z="decimal")}if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},decimal(){switch(J){case".":j+=uu(),z="decimalFraction";break;case"e":case"E":j+=uu(),z="decimalExponent"}},decimalPointLeading(){if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalFraction");throw Eu(x.Char,uu())},decimalFraction(){switch(J){case"e":case"E":return j+=uu(),void(z="decimalExponent")}if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},decimalExponent(){switch(J){case"+":case"-":return j+=uu(),void(z="decimalExponentSign")}if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalExponentInteger");throw Eu(x.Char,uu())},decimalExponentSign(){if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalExponentInteger");throw Eu(x.Char,uu())},decimalExponentInteger(){if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},hexadecimal(){if(H.JudgeUtil.isHexDigit(J))return j+=uu(),void(z="hexadecimalInteger");throw Eu(x.Char,uu())},hexadecimalInteger(){if(!H.JudgeUtil.isHexDigit(J))return eu("numeric",Z*Number(j));j+=uu()},identifierNameStartEscape(){if("u"!==J)throw Eu(x.Char,uu());uu();const u=ru();switch(u){case"$":case"_":break;default:if(!H.JudgeUtil.isIdStartChar(u))throw Eu(x.Identifier)}j+=u,z="identifierName"},identifierName(){switch(J){case"$":case"_":case"":case"":return void(j+=uu());case"\\":return uu(),void(z="identifierNameEscape")}if(!H.JudgeUtil.isIdContinueChar(J))return eu("identifier",j);j+=uu()},identifierNameEscape(){if("u"!==J)throw Eu(x.Char,uu());uu();const u=ru();switch(u){case"$":case"_":case"":case"":break;default:if(!H.JudgeUtil.isIdContinueChar(u))throw Eu(x.Identifier)}j+=u,z="identifierName"},string(){switch(J){case"\\":return uu(),void(j+=function(){const u=Y(),D=function(){switch(Y()){case"b":return uu(),"\b";case"f":return uu(),"\f";case"n":return uu(),"\n";case"r":return uu(),"\r";case"t":return uu(),"\t";case"v":return uu(),"\v"}return}();if(D)return D;switch(u){case"0":if(uu(),H.JudgeUtil.isDigit(Y()))throw Eu(x.Char,uu());return"\0";case"x":return uu(),function(){let u="",D=Y();if(!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());if(u+=uu(),D=Y(),!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());return u+=uu(),String.fromCodePoint(parseInt(u,16))}();case"u":return uu(),ru();case"\n":case"\u2028":case"\u2029":return uu(),"";case"\r":return uu(),"\n"===Y()&&uu(),""}if(void 0===u||H.JudgeUtil.isDigitWithoutZero(u))throw Eu(x.Char,uu());return uu()}());case'"':case"'":if(J===q){const u=eu("string",j);return uu(),u}return void(j+=uu());case"\n":case"\r":case void 0:throw Eu(x.Char,uu());case"\u2028":case"\u2029":!function(u){console.warn(`JSON5: '${Fu(u)}' in strings is not valid ECMAScript; consider escaping.`)}(J)}j+=uu()}};function eu(u,D){return{type:u,value:D,line:$,column:k}}function tu(u){for(const D of u){if(Y()!==D)throw Eu(x.Char,uu());uu()}}function ru(){let u="",D=4;for(;D-- >0;){const D=Y();if(!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());u+=uu()}return String.fromCodePoint(parseInt(u,16))}const nu={start(){if("eof"===M.type)throw Eu(x.EOF);iu()},beforePropertyName(){switch(M.type){case"identifier":case"string":return V=M.value,void(W="afterPropertyName");case"punctuator":return void Cu();case"eof":throw Eu(x.EOF)}},afterPropertyName(){if("eof"===M.type)throw Eu(x.EOF);W="beforePropertyValue"},beforePropertyValue(){if("eof"===M.type)throw Eu(x.EOF);iu()},afterPropertyValue(){if("eof"===M.type)throw Eu(x.EOF);switch(M.value){case",":return void(W="beforePropertyName");case"}":Cu()}},beforeArrayValue(){if("eof"===M.type)throw Eu(x.EOF);"punctuator"!==M.type||"]"!==M.value?iu():Cu()},afterArrayValue(){if("eof"===M.type)throw Eu(x.EOF);switch(M.value){case",":return void(W="beforeArrayValue");case"]":Cu()}},end(){}};function iu(){const u=function(){let u;switch(M.type){case"punctuator":switch(M.value){case"{":u={};break;case"[":u=[]}break;case"null":case"boolean":case"numeric":case"string":u=M.value}return u}();if(K&&"object"==typeof u&&(u._line=$,u._column=k),void 0===G)G=u;else{const D=U[U.length-1];Array.isArray(D)?K&&"object"!=typeof u?D.push({value:u,_line:$,_column:k}):D.push(u):D[V]=K&&"object"!=typeof u?{value:u,_line:$,_column:k}:u}!function(u){if(u&&"object"==typeof u)U.push(u),W=Array.isArray(u)?"beforeArrayValue":"beforePropertyName";else{const u=U[U.length-1];W=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}}(u)}function Cu(){U.pop();const u=U[U.length-1];W=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}function Fu(u){const D={"'":"\\'",'"':'\\"',"\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\v":"\\v","\0":"\\0","\u2028":"\\u2028","\u2029":"\\u2029"};if(D[u])return D[u];if(u<" "){const D=u.charCodeAt(0).toString(16);return`\\x${`00${D}`.substring(D.length)}`}return u}function Eu(u,D){let e="";switch(u){case x.Char:e=void 0===D?`JSON5: invalid end of input at ${$}:${k}`:`JSON5: invalid character '${Fu(D)}' at ${$}:${k}`;break;case x.EOF:e=`JSON5: invalid end of input at ${$}:${k}`;break;case x.Identifier:k-=5,e=`JSON5: invalid identifier character at ${$}:${k}`}const t=new Au(e);return t.lineNumber=$,t.columnNumber=k,t}class Au extends SyntaxError{}var ou={},au=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),cu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),su=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&au(D,u,e);return cu(D,u),D},lu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(ou,"__esModule",{value:!0}),ou.isFileExists=ou.offlinePluginConversion=ou.executeCommand=ou.getNpmPath=ou.hasNpmPackInPaths=void 0;const Bu=r,du=lu(e),fu=su(u),_u=i,pu=l;ou.hasNpmPackInPaths=function(u,D){try{return require.resolve(u,{paths:[...D]}),!0}catch(u){return!1}},ou.getNpmPath=function(){const u=process.execPath;return fu.join(fu.dirname(u),_u.NPM_TOOL)},ou.executeCommand=function(u,D,e){0!==(0,Bu.spawnSync)(u,D,e).status&&(0,pu.logErrorAndExit)(`Error: ${u} ${D} execute failed.See above for details.`)},ou.offlinePluginConversion=function(u,D){return D.startsWith("file:")||D.endsWith(".tgz")?fu.resolve(u,_u.HVIGOR,D.replace("file:","")):D},ou.isFileExists=function(u){return du.default.existsSync(u)&&du.default.statSync(u).isFile()};var Ou=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),hu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),Pu=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&Ou(D,u,e);return hu(D,u),D},vu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(P,"__esModule",{value:!0});var gu=P.initProjectWorkSpace=void 0;const mu=Pu(e),Ru=vu(D),yu=Pu(u),Iu=v,Nu=i,bu=g,Su=l,wu=ou;let Hu,xu,Mu;function Tu(u,D,e){return void 0!==e.dependencies&&(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,D.dependencies[u])===yu.normalize(e.dependencies[u])}function Vu(){const u=yu.join(Mu,Nu.WORK_SPACE);if((0,Su.logInfoPrintConsole)("Hvigor cleaning..."),!mu.existsSync(u))return;const D=mu.readdirSync(u);if(!D||0===D.length)return;const e=yu.resolve(Mu,"node_modules","@ohos","hvigor","bin","hvigor.js");mu.existsSync(e)&&(0,wu.executeCommand)(process.argv[0],[e,"--stop-daemon"],{});try{D.forEach((D=>{mu.rmSync(yu.resolve(u,D),{recursive:!0})}))}catch(D){(0,Su.logErrorAndExit)(`The hvigor build tool cannot be installed. Please manually clear the workspace directory and synchronize the project again.\n\n Workspace Path: ${u}.`)}}gu=P.initProjectWorkSpace=function(){if(Hu=function(){const u=yu.resolve(Nu.HVIGOR_PROJECT_WRAPPER_HOME,Nu.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME);mu.existsSync(u)||(0,Su.logErrorAndExit)(`Error: Hvigor config file ${u} does not exist.`);return(0,bu.parseJsonFile)(u)}(),Mu=function(u){let D;D=function(u){let D=u.hvigorVersion;if(D.startsWith("file:")||D.endsWith(".tgz"))return!1;const e=u.dependencies,t=Object.getOwnPropertyNames(e);for(const u of t){const D=e[u];if(D.startsWith("file:")||D.endsWith(".tgz"))return!1}if(1===t.length&&"@ohos/hvigor-ohos-plugin"===t[0])return D>"2.5.0";return!1}(u)?function(u){let D=`${Nu.HVIGOR_ENGINE_PACKAGE_NAME}@${u.hvigorVersion}`;const e=u.dependencies;if(e){Object.getOwnPropertyNames(e).sort().forEach((u=>{D+=`,${u}@${e[u]}`}))}return(0,Iu.hash)(D)}(u):(0,Iu.hash)(process.cwd());return yu.resolve(Ru.default.homedir(),".hvigor","project_caches",D)}(Hu),xu=function(){const u=yu.resolve(Mu,Nu.WORK_SPACE,Nu.DEFAULT_PACKAGE_JSON);return mu.existsSync(u)?(0,bu.parseJsonFile)(u):{dependencies:{}}}(),!(0,wu.hasNpmPackInPaths)(Nu.HVIGOR_ENGINE_PACKAGE_NAME,[yu.join(Mu,Nu.WORK_SPACE)])||(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion)!==xu.dependencies[Nu.HVIGOR_ENGINE_PACKAGE_NAME]||!function(){function u(u){const D=null==u?void 0:u.dependencies;return void 0===D?0:Object.getOwnPropertyNames(D).length}const D=u(Hu),e=u(xu);if(D+1!==e)return!1;for(const u in null==Hu?void 0:Hu.dependencies)if(!(0,wu.hasNpmPackInPaths)(u,[yu.join(Mu,Nu.WORK_SPACE)])||!Tu(u,Hu,xu))return!1;return!0}()){Vu();try{!function(){(0,Su.logInfoPrintConsole)("Hvigor installing...");for(const u in Hu.dependencies)Hu.dependencies[u]&&(Hu.dependencies[u]=(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.dependencies[u]));const u={dependencies:{...Hu.dependencies}};u.dependencies[Nu.HVIGOR_ENGINE_PACKAGE_NAME]=(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion);const D=yu.join(Mu,Nu.WORK_SPACE);try{mu.mkdirSync(D,{recursive:!0});const e=yu.resolve(D,Nu.DEFAULT_PACKAGE_JSON);mu.writeFileSync(e,JSON.stringify(u))}catch(u){(0,Su.logErrorAndExit)(u)}(function(){const u=["config","set","store-dir",Nu.HVIGOR_PNPM_STORE_PATH],D={cwd:yu.join(Mu,Nu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,wu.executeCommand)(Nu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)})(),function(){const u=["install"],D={cwd:yu.join(Mu,Nu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,wu.executeCommand)(Nu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)}(),(0,Su.logInfoPrintConsole)("Hvigor install success.")}()}catch(u){Vu()}}return Mu};var Gu={};!function(t){var C=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),F=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),E=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&C(D,u,e);return F(D,u),D},A=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(t,"__esModule",{value:!0}),t.executeInstallPnpm=t.isPnpmInstalled=t.environmentHandler=t.checkNpmConifg=t.PNPM_VERSION=void 0;const o=r,a=E(e),c=A(D),s=E(u),B=i,d=l,f=ou;t.PNPM_VERSION="7.30.0",t.checkNpmConifg=function(){const u=s.resolve(B.HVIGOR_PROJECT_ROOT_DIR,".npmrc"),D=s.resolve(c.default.homedir(),".npmrc");if((0,f.isFileExists)(u)||(0,f.isFileExists)(D))return;const e=(0,f.getNpmPath)(),t=(0,o.spawnSync)(e,["config","get","prefix"],{cwd:B.HVIGOR_PROJECT_ROOT_DIR});if(0!==t.status||!t.stdout)return void(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.");const r=s.resolve(`${t.stdout}`.replace(/[\r\n]/gi,""),".npmrc");(0,f.isFileExists)(r)||(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.")},t.environmentHandler=function(){process.env["npm_config_update-notifier"]="false"},t.isPnpmInstalled=function(){return!!a.existsSync(B.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH)&&(0,f.hasNpmPackInPaths)("pnpm",[B.HVIGOR_WRAPPER_TOOLS_HOME])},t.executeInstallPnpm=function(){(0,d.logInfoPrintConsole)(`Installing pnpm@${t.PNPM_VERSION}...`);const u=(0,f.getNpmPath)();!function(){const u=s.resolve(B.HVIGOR_WRAPPER_TOOLS_HOME,B.DEFAULT_PACKAGE_JSON);try{a.existsSync(B.HVIGOR_WRAPPER_TOOLS_HOME)||a.mkdirSync(B.HVIGOR_WRAPPER_TOOLS_HOME,{recursive:!0});const D={dependencies:{}};D.dependencies[B.PNPM]=t.PNPM_VERSION,a.writeFileSync(u,JSON.stringify(D))}catch(D){(0,d.logErrorAndExit)(`Error: EPERM: operation not permitted,create ${u} failed.`)}}(),(0,f.executeCommand)(u,["install","pnpm"],{cwd:B.HVIGOR_WRAPPER_TOOLS_HOME,stdio:["inherit","inherit","inherit"],env:process.env}),(0,d.logInfoPrintConsole)("Pnpm install success.")}}(Gu),function(){Gu.checkNpmConifg(),Gu.environmentHandler(),Gu.isPnpmInstalled()||Gu.executeInstallPnpm();const D=gu();_(u.join(D,i.WORK_SPACE))}();
\ No newline at end of file
diff --git a/datafiting/datafit/hvigorfile.ts b/datafiting/datafit/hvigorfile.ts
new file mode 100644
index 0000000..f3cb9f1
--- /dev/null
+++ b/datafiting/datafit/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/datafiting/datafit/hvigorw b/datafiting/datafit/hvigorw
new file mode 100644
index 0000000..ff6a29a
--- /dev/null
+++ b/datafiting/datafit/hvigorw
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# ----------------------------------------------------------------------------
+# Hvigor startup script, version 1.0.0
+#
+# Required ENV vars:
+# ------------------
+# NODE_HOME - location of a Node home dir
+# or
+# Add /usr/local/nodejs/bin to the PATH environment variable
+# ----------------------------------------------------------------------------
+
+HVIGOR_APP_HOME="`pwd -P`"
+HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
+warn() {
+ echo ""
+ echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
+}
+
+error() {
+ echo ""
+ echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
+}
+
+fail() {
+ error "$@"
+ exit 1
+}
+
+# Determine node to start hvigor wrapper script
+if [ -n "${NODE_HOME}" ];then
+ EXECUTABLE_NODE="${NODE_HOME}/bin/node"
+ if [ ! -x "$EXECUTABLE_NODE" ];then
+ fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
+ fi
+else
+ EXECUTABLE_NODE="node"
+ which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path"
+fi
+
+# Check hvigor wrapper script
+if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then
+ fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
+fi
+
+# start hvigor-wrapper script
+exec "${EXECUTABLE_NODE}" \
+ "${HVIGOR_WRAPPER_SCRIPT}" "$@"
diff --git a/datafiting/datafit/hvigorw.bat b/datafiting/datafit/hvigorw.bat
new file mode 100644
index 0000000..d570007
--- /dev/null
+++ b/datafiting/datafit/hvigorw.bat
@@ -0,0 +1,64 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Hvigor startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
+set NODE_EXE=node.exe
+
+goto start
+
+:start
+@rem Find node.exe
+if defined NODE_HOME goto findNodeFromNodeHome
+
+%NODE_EXE% --version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
+echo.
+echo Please set the NODE_HOME variable in your environment to match the
+echo location of your NodeJs installation.
+
+goto fail
+
+:findNodeFromNodeHome
+set NODE_HOME=%NODE_HOME:"=%
+set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
+
+if exist "%NODE_EXE_PATH%" goto execute
+echo.
+echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
+echo.
+echo Please set the NODE_HOME variable in your environment to match the
+echo location of your NodeJs installation.
+
+goto fail
+
+:execute
+@rem Execute hvigor
+"%NODE_EXE%" "%WRAPPER_MODULE_PATH%" %*
+
+if "%ERRORLEVEL%" == "0" goto hvigorwEnd
+
+:fail
+exit /b 1
+
+:hvigorwEnd
+if "%OS%" == "Windows_NT" endlocal
+
+:end
diff --git a/datafiting/datafit/oh-package-lock.json5 b/datafiting/datafit/oh-package-lock.json5
new file mode 100644
index 0000000..ddc8a54
--- /dev/null
+++ b/datafiting/datafit/oh-package-lock.json5
@@ -0,0 +1,13 @@
+{
+ "lockfileVersion": 1,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hypium@1.0.11": "@ohos/hypium@1.0.11"
+ },
+ "packages": {
+ "@ohos/hypium@1.0.11": {
+ "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.11.tgz",
+ "integrity": "sha512-KawcLnv43C3QIYv1UbDnKCFX3MohtDxGuFvzlUxT/qf2DBilR56Ws6zrj90LdH6PjloJQwOPESuBQIHBACAK7w=="
+ }
+ }
+}
\ No newline at end of file
diff --git a/datafiting/datafit/oh-package.json5 b/datafiting/datafit/oh-package.json5
new file mode 100644
index 0000000..f0c54ba
--- /dev/null
+++ b/datafiting/datafit/oh-package.json5
@@ -0,0 +1,12 @@
+{
+ "license": "",
+ "devDependencies": {
+ "@ohos/hypium": "1.0.11"
+ },
+ "author": "",
+ "name": "myapplication",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
diff --git a/datafiting/figs/evolution.png b/datafiting/figs/evolution.png
new file mode 100644
index 0000000..e3bebbb
Binary files /dev/null and b/datafiting/figs/evolution.png differ
diff --git a/datafiting/figs/overall.png b/datafiting/figs/overall.png
new file mode 100644
index 0000000..8e4be16
Binary files /dev/null and b/datafiting/figs/overall.png differ
diff --git a/datafiting/figs/relation.png b/datafiting/figs/relation.png
new file mode 100644
index 0000000..c9d210a
Binary files /dev/null and b/datafiting/figs/relation.png differ
diff --git a/drawing/README.md b/drawing/README.md
new file mode 100644
index 0000000..c156d8f
--- /dev/null
+++ b/drawing/README.md
@@ -0,0 +1,18 @@
+# drawing
+### 1、项目说明
+本项目拟实现一个复杂函数计算及其曲线绘制系统,基本功能为:(1)用户能够设置自变量的步长和个数;(2)程序会根据用户设置的函数以及步长和个数信息,解析函数获取点集并执行绘制的操作(3)用户能够自定义函数并保存在可识别函数中,使其能够参与新函数的构造;(4)用户能够切换函数分别在二维和三维环境下的绘制;(5)程序会解析用户输入的函数,将多项式分成单项式并以“树”的形式呈现。
+### 2、开发环境说明
+(1)系统版本:OpenHarmony 4.0 Release
+(2)SDK版本:API 10
+(3)Model类型:Stage
+(4)DevEco Studio版本:Deveco Studio 4.0 release
+(5)硬件环境:Unionpi Whale、RK3566开发板
+(6)预览器参数:(1)DeviceType:default;(2)Resolution:560-1280;(3)DPI:240;其余参数自定。
+### 3、项目主要函数调用关系图与项目输出界面演进图
+ 图3.1 项目主要函数调用关系图
+
+
+
+ 图3.2 项目输出界面演进图
+
+
diff --git a/drawing/draw/.gitignore b/drawing/draw/.gitignore
new file mode 100644
index 0000000..fbabf77
--- /dev/null
+++ b/drawing/draw/.gitignore
@@ -0,0 +1,11 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
\ No newline at end of file
diff --git a/drawing/draw/AppScope/app.json5 b/drawing/draw/AppScope/app.json5
new file mode 100644
index 0000000..3c45fe7
--- /dev/null
+++ b/drawing/draw/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.test.myapplication",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
diff --git a/drawing/draw/AppScope/resources/base/element/string.json b/drawing/draw/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000..1080233
--- /dev/null
+++ b/drawing/draw/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MyApplication"
+ }
+ ]
+}
diff --git a/drawing/draw/AppScope/resources/base/media/app_icon.png b/drawing/draw/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/drawing/draw/AppScope/resources/base/media/app_icon.png differ
diff --git a/drawing/draw/build-profile.json5 b/drawing/draw/build-profile.json5
new file mode 100644
index 0000000..844303d
--- /dev/null
+++ b/drawing/draw/build-profile.json5
@@ -0,0 +1,49 @@
+{
+ "app": {
+ "signingConfigs": [
+ {
+ "name": "default",
+ "material": {
+ "certpath": "C:\\Users\\cyf20\\.ohos\\config\\openharmony\\auto_ohos_default_draw_com.test.myapplication.cer",
+ "storePassword": "0000001A41B8AC51384118050B5A9A22C9E132AA02BE60C9CBE187B4D7B69A17D2C070E0DF83E06DC1E4",
+ "keyAlias": "debugKey",
+ "keyPassword": "0000001A98556E0863F7805DEA1D57929A5FF99B10F6509C866A4450C6198E40C8F4F0701876AB99F565",
+ "profile": "C:\\Users\\cyf20\\.ohos\\config\\openharmony\\auto_ohos_default_draw_com.test.myapplication.p7b",
+ "signAlg": "SHA256withECDSA",
+ "storeFile": "C:\\Users\\cyf20\\.ohos\\config\\openharmony\\auto_ohos_default_draw_com.test.myapplication.p12"
+ }
+ }
+ ],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 10,
+ "compatibleSdkVersion": 10,
+ "runtimeOS": "OpenHarmony",
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug",
+ },
+ {
+ "name": "release"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/.gitignore b/drawing/draw/entry/.gitignore
new file mode 100644
index 0000000..e2713a2
--- /dev/null
+++ b/drawing/draw/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/drawing/draw/entry/build-profile.json5 b/drawing/draw/entry/build-profile.json5
new file mode 100644
index 0000000..197e83c
--- /dev/null
+++ b/drawing/draw/entry/build-profile.json5
@@ -0,0 +1,31 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ "arkOptions": {
+ // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
+ }
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": true,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/hvigorfile.ts b/drawing/draw/entry/hvigorfile.ts
new file mode 100644
index 0000000..c6edcd9
--- /dev/null
+++ b/drawing/draw/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/drawing/draw/entry/obfuscation-rules.txt b/drawing/draw/entry/obfuscation-rules.txt
new file mode 100644
index 0000000..985b2ae
--- /dev/null
+++ b/drawing/draw/entry/obfuscation-rules.txt
@@ -0,0 +1,18 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
\ No newline at end of file
diff --git a/drawing/draw/entry/oh-package.json5 b/drawing/draw/entry/oh-package.json5
new file mode 100644
index 0000000..225946c
--- /dev/null
+++ b/drawing/draw/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "license": "",
+ "devDependencies": {},
+ "author": "",
+ "name": "entry",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
diff --git a/drawing/draw/entry/src/main/ets/common/BasicFuncInfo.ets b/drawing/draw/entry/src/main/ets/common/BasicFuncInfo.ets
new file mode 100644
index 0000000..0adc218
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/common/BasicFuncInfo.ets
@@ -0,0 +1,29 @@
+@Observed
+export class basicFuncInfo{
+ /**
+ * 函数名
+ */
+ private funcName:string
+ /**
+ * 函数体
+ */
+ private funcBody:string
+
+ constructor(funcName: string, funcBody: string) {
+ this.funcName = funcName
+ this.funcBody = funcBody
+ }
+
+ setFuncName(name:string){
+ this.funcName = name
+ }
+ setFuncBody(body:string){
+ this.funcBody = body
+ }
+ getFuncName(){
+ return this.funcName
+ }
+ getFuncBody(){
+ return this.funcBody
+ }
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/ets/common/CommonValue.ets b/drawing/draw/entry/src/main/ets/common/CommonValue.ets
new file mode 100644
index 0000000..7df19f1
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/common/CommonValue.ets
@@ -0,0 +1,27 @@
+export class VALUE{
+ /**
+ * 栏颜色
+ */
+ static readonly COLOR_BAR = "#EDEDED"
+ /**
+ * 字体大小(大)
+ */
+ static readonly BIG_SIZE_FONT = 15
+ /**
+ * 字体大小(大)
+ */
+ static readonly MIDDLE_SIZE_FONT = 12
+ /**
+ * 字体大小(小)
+ */
+ static readonly SMALL_SIZE_FONT = 10
+ /**
+ * controlBar的背景色
+ */
+ static readonly COLOR_COMP_CONTROLBAR_BG = "#9490D9"
+ /**
+ * controlBar的栏颜色
+ */
+ static readonly COLOR_COMP_CONTROLBAR_BAR = "#8767F7"
+
+}
diff --git a/drawing/draw/entry/src/main/ets/component/BasicFunctionsBar.ets b/drawing/draw/entry/src/main/ets/component/BasicFunctionsBar.ets
new file mode 100644
index 0000000..55656bf
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/component/BasicFunctionsBar.ets
@@ -0,0 +1,67 @@
+import { basicFuncInfo } from '../common/BasicFuncInfo'
+import { VALUE } from '../common/CommonValue'
+
+@Component
+export struct basicFunctionsBar {
+ @Consume('basicFuncList') basicFuncList:Array
+ build() {
+ Column(){
+ Text("可识别基本函数")
+ .fontSize(VALUE.BIG_SIZE_FONT)
+ .fontColor(Color.Red)
+ .fontWeight(FontWeight.Bold)
+ Row(){
+ Row(){
+ Text('函数名')
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ }.justifyContent(FlexAlign.Center).width('28%')
+ Blank()
+ Row(){
+ Text('函数体')
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ }.justifyContent(FlexAlign.Center).width('68%')
+ }.width('100%').padding({left:5,right:5})
+ List(){
+ ForEach(this.basicFuncList,(item:basicFuncInfo)=>{
+ ListItem(){
+ basicFuncItem({basicFunc:item})
+ }
+ })
+ }.layoutWeight(1).width('100%')
+ }.width('100%').height('100%')
+ }
+}
+
+@Component
+struct basicFuncItem {
+ @ObjectLink basicFunc:basicFuncInfo
+ build() {
+ Row(){
+ Scroll(){
+ Row(){
+ Text(this.basicFunc.getFuncName())
+ .fontSize(VALUE.MIDDLE_SIZE_FONT)
+ }.justifyContent(FlexAlign.Center)
+ }.width('28%').scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off)
+ Blank()
+ Scroll(){
+ Row(){
+ Text(this.basicFunc.getFuncBody())
+ .fontSize(VALUE.MIDDLE_SIZE_FONT)
+ }.justifyContent(FlexAlign.Center)
+ }.width('68%').scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off)
+ }.width('100%').height(25)
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drawing/draw/entry/src/main/ets/component/ControlBar.ets b/drawing/draw/entry/src/main/ets/component/ControlBar.ets
new file mode 100644
index 0000000..c5dca25
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/component/ControlBar.ets
@@ -0,0 +1,317 @@
+import promptAction from '@ohos.promptAction'
+import { basicFuncInfo } from '../common/BasicFuncInfo'
+import { VALUE } from '../common/CommonValue'
+import { IBoardOption, BoardType, Dimension, Quadrant } from '../utils/drawBoard/BoardType'
+import { FuncType } from '../utils/drawBoard/drawPoint'
+import { handle } from '../utils/handleFunc/processFunc'
+
+@Component
+export struct controlBar {
+ @Link inputFuncBody:string
+
+ @Link outputState:boolean
+
+ @Link boardOption:IBoardOption
+
+ build() {
+ Column({space:5}){
+ InputFunc({funcBody:$inputFuncBody,outputState:$outputState})
+ InputPara({boardOption:$boardOption})
+ }.width('100%').height('100%').backgroundColor(VALUE.COLOR_COMP_CONTROLBAR_BG).padding({top:5,bottom:5})
+ }
+
+
+}
+
+@Component
+struct InputFunc {
+ @Consume isFuncChange:boolean
+ @Link funcBody:string
+ @Link outputState:boolean
+ @Consume('basicFuncList') basicFuncList:Array
+ @Consume dimension:Dimension
+
+ build() {
+ Row({space:10}){
+ Text('')
+ .width(15)
+ .height(30)
+ Stack(){
+ Rect().width('100%').height('100%').fill(Color.White)
+ TextInput({text:this.funcBody}).width('100%').height('100%').backgroundColor(Color.White).fontColor(Color.Black).fontSize(VALUE.SMALL_SIZE_FONT)
+ .onChange((value)=>{
+ this.funcBody = value
+ this.isFuncChange = true
+ })
+ }.height(30).backgroundColor(Color.White).layoutWeight(1)
+ Button('用户命名并新增基本函数')
+ .height(30)
+ .backgroundColor(Color.Yellow)
+ .fontColor(Color.Black)
+ .fontSize(VALUE.BIG_SIZE_FONT)
+ .width(210)
+ .type(ButtonType.Normal)
+ .onClick(()=>{
+ if(handle.isValidFunc(this.funcBody)) {
+ handle.separateFunc(this.funcBody);
+ let funcName = handle.funcHead;
+ let funcBody = handle.funcBody;
+ if (funcName && handle.getFuncType(this.dimension) != FuncType.NONE) {
+ let info: basicFuncInfo = new basicFuncInfo(funcName, funcBody)
+ this.basicFuncList.push(info)
+ }
+ else {
+ promptAction.showToast({
+ message: "不支持此函数类型或未为函数命名",
+ duration: 1500,
+ bottom: 20
+ })
+ }
+ }
+ })
+ Button('输出')
+ .height(30)
+ .backgroundColor(Color.Pink)
+ .fontColor(Color.Black)
+ .fontSize(VALUE.BIG_SIZE_FONT)
+ .width(70)
+ .type(ButtonType.Normal)
+ .onClick(()=>{
+ for (let i: number = 0; i < this.basicFuncList.length; i++) {
+ let standard: RegExp = new RegExp(`(^|[^a-zA-Z])${this.basicFuncList[i].getFuncName().replace('(', '\\(').replace(')', '\\)')}($|[^a-zA-Z])`);
+ if (standard.test(this.funcBody)) {
+ let index: number = this.funcBody.indexOf(this.basicFuncList[i].getFuncName());
+ let length: number = this.basicFuncList[i].getFuncName().length;
+ this.funcBody = this.funcBody.substring(0, index) + "(" + this.basicFuncList[i].getFuncBody() + ")" + this.funcBody.substring(index + length);
+ break;
+ }
+ }
+ if (handle.isValidFunc(this.funcBody)) {
+ if (this.dimension == Dimension.TWO) {
+ handle.getPoints2D();
+ } else {
+ handle.getPoints3D();
+ for (let i = 0; i < handle.coPot.length; i++) {
+ console.log(`(${handle.coPot[i].x}, ${handle.coPot[i].y}, ${handle.coPot[i].z})`);
+ }
+
+ }
+ this.outputState = !this.outputState;
+ }
+ })
+ }.width('100%').padding({left:10,right:10})
+ }
+}
+
+@Component
+struct InputPara {
+ @Link boardOption:IBoardOption
+ @Consume isFuncChange:boolean
+ @Consume quadrant:Quadrant
+ @Consume dimension:Dimension
+
+ @Builder xStep(){
+ Row(){
+ Text('x步长')
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ Stack(){
+ Rect().width('100%').height('100%').fill(Color.White)
+ TextInput().width('100%').height('100%').backgroundColor(Color.White).fontColor(Color.Black).fontSize(VALUE.SMALL_SIZE_FONT)
+ .onChange((value)=>{
+ if(this.dimension == Dimension.THREE && Number(value) < 1){
+ WARNING("输入的x步长过小!x步长最小为1")
+ return
+ }
+ this.boardOption.xStep = Number(value)
+ handle.xStep = this.boardOption.xStep;
+ })
+ }.height(30).backgroundColor(Color.White).layoutWeight(1)
+ }.width('100%').layoutWeight(0.5)
+ }
+
+ @Builder xNumber(){
+ Row(){
+ Text('x个数')
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ Stack(){
+ Rect().width('100%').height('100%').fill(Color.White)
+ TextInput().width('100%').height('100%').backgroundColor(Color.White).fontColor(Color.Black).fontSize(VALUE.SMALL_SIZE_FONT)
+ .onChange((value)=>{
+ this.boardOption.xNumber = Number(value)
+ handle.xCount = this.boardOption.xNumber;
+ })
+ }.height(30).backgroundColor(Color.White).layoutWeight(1)
+ }.width('100%').layoutWeight(0.5)
+ }
+
+ @Builder yStep(){
+ Row(){
+ Text('y步长')
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ Stack(){
+ Rect().width('100%').height('100%').fill(Color.White)
+ TextInput({text:this.boardOption.yStep.toString()}).width('100%').height('100%').backgroundColor(Color.White).fontColor(Color.Black).fontSize(VALUE.SMALL_SIZE_FONT)
+ .onChange((value)=>{
+ this.boardOption.yStep = Number(value)
+ handle.yStep = this.boardOption.yStep;
+ })
+ }.height(30).backgroundColor(Color.White).layoutWeight(1)
+ }.width('100%').layoutWeight(0.5)
+ }
+
+ @Builder quadrantSwitch(quadrant:Quadrant){
+ Row(){
+ Radio({value:quadrant.toString(),group:"Quadrant"})
+ .checked(this.quadrant == quadrant)
+ .onClick(()=>{
+ this.quadrant = quadrant
+ this.isFuncChange = true
+ if(quadrant == Quadrant.FOUR){
+ handle.setEdge(-10, 10);
+ }else{
+ handle.setEdge(0, 20);
+ }
+ handle.updateEdge(this.boardOption.xAmplification);
+ })
+ Text(quadrant == Quadrant.ONE?"一象限":"四象限")
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ }.width('100%').height('50%').alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Center)
+ }
+
+ @Builder dimensionSwitch(dimension:Dimension){
+ Row(){
+ Radio({value:dimension.toString(),group:"TwoDimensional"})
+ .checked(this.dimension == dimension)
+ .onClick(()=>{
+ this.boardOption = {
+ xStep:0.1,
+ xNumber:0,//
+ yStep:1,
+ yNumber:0,
+ xAmplification:1,
+ yAmplification:1,
+ zAmplification:1
+ }
+ this.dimension = dimension
+ this.quadrant = Quadrant.FOUR
+ this.isFuncChange = true
+ if(dimension == Dimension.TWO){
+ handle.setEdge(-10, 10);
+ handle.updateEdge(this.boardOption.xAmplification);
+ }else{
+ handle.setEdge(-5, 5, 10);
+ handle.updateEdge(this.boardOption.xAmplification, this.boardOption.yAmplification)
+ }
+ })
+ Text(dimension == Dimension.TWO?"二维":"三维")
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ }.width('100%').height('50%').alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Center)
+ }
+
+ @Builder xAmplification(){
+ Row(){
+ Text('x放大倍数')
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ Stack(){
+ Rect().width('100%').height('100%').fill(Color.White)
+ TextInput({text:this.boardOption.xAmplification.toString()}).width('100%').height('100%').backgroundColor(Color.White).fontColor(Color.Black).fontSize(VALUE.SMALL_SIZE_FONT)
+ .onChange((value)=>{
+ this.boardOption.xAmplification = Number(value)
+ handle.updateEdge(this.boardOption.xAmplification);
+ })
+ }.height(30).backgroundColor(Color.White).layoutWeight(1)
+ }.width('100%').layoutWeight(0.5)
+ }
+
+ @Builder yAmplification(){
+ Row(){
+ Text('y放大倍数')
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ Stack(){
+ Rect().width('100%').height('100%').fill(Color.White)
+ TextInput({text:this.boardOption.yAmplification.toString()}).width('100%').height('100%').backgroundColor(Color.White).fontColor(Color.Black).fontSize(VALUE.SMALL_SIZE_FONT)
+ .onChange((value)=>{
+ this.boardOption.yAmplification = Number(value)
+ })
+ }.height(30).backgroundColor(Color.White).layoutWeight(1)
+ }.width('100%').layoutWeight(0.5)
+ }
+
+ @Builder zAmplification(){
+ Row(){
+ Text('z放大倍数')
+ .fontSize(VALUE.SMALL_SIZE_FONT)
+ Stack(){
+ TextInput({text:this.boardOption.zAmplification.toString()}).width('100%').height('100%').backgroundColor(Color.White).fontColor(Color.Black).fontSize(VALUE.SMALL_SIZE_FONT)
+ .onChange((value)=>{
+ this.boardOption.zAmplification = Number(value)
+ })
+ .fontSize(10)
+ }.height(30).backgroundColor(Color.White).layoutWeight(1)
+ }.width('100%')
+ }
+
+
+ build() {
+ Row({space:10}){
+
+ Column({space:5}){
+ this.xStep()
+ Blank()
+ if (this.dimension == Dimension.TWO){
+ this.xNumber()
+ }else{
+ this.yStep()
+ }
+ }.width('24%').height('100%').backgroundColor(VALUE.COLOR_COMP_CONTROLBAR_BAR)
+
+ if(this.dimension == Dimension.TWO){
+ Row(){
+ Column(){
+ Text("坐标轴")
+ .fontSize(VALUE.BIG_SIZE_FONT)
+ }.height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).width('40%')
+ Column(){
+ this.quadrantSwitch(Quadrant.FOUR)
+ this.quadrantSwitch(Quadrant.ONE)
+ }.height('100%').width('60%')
+ }.width('22%').height('100%').backgroundColor(VALUE.COLOR_COMP_CONTROLBAR_BAR)
+ }else{
+ Column(){
+ this.xAmplification()
+ Blank()
+ this.yAmplification()
+ }.width('22%').height('100%').backgroundColor(VALUE.COLOR_COMP_CONTROLBAR_BAR)
+ }
+
+ Row(){
+ Column(){
+ Text("维度")
+ .fontSize(VALUE.BIG_SIZE_FONT)
+ }.height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).width('40%')
+ Column(){
+ this.dimensionSwitch(Dimension.TWO)
+ this.dimensionSwitch(Dimension.THREE)
+ }.height('100%').width('60%')
+ }.width('22%').height('100%').backgroundColor(VALUE.COLOR_COMP_CONTROLBAR_BAR)
+
+ Column({space:5}){
+ if(this.dimension == Dimension.TWO){
+ this.xAmplification()
+ Blank()
+ this.yAmplification()
+ }else{
+ this.zAmplification()
+ }
+ }.width('28%').height('100%').backgroundColor(VALUE.COLOR_COMP_CONTROLBAR_BAR)
+
+ }.width('100%').layoutWeight(1).padding({left:10,right:10})
+ }
+}
+
+let WARNING = (message:string,duration?:number)=>{
+ promptAction.showToast({
+ message:message,
+ duration:duration??2000
+ })
+}
diff --git a/drawing/draw/entry/src/main/ets/component/FunctionParsingDiagram.ets b/drawing/draw/entry/src/main/ets/component/FunctionParsingDiagram.ets
new file mode 100644
index 0000000..373d59d
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/component/FunctionParsingDiagram.ets
@@ -0,0 +1,37 @@
+import { handle } from '../utils/handleFunc/processFunc'
+
+@Component
+export struct functionParsingDiagram {
+ @Link @Watch('initNodeTree') outputState: boolean
+ @Link func: string
+ @State nodeTree: Array> = []
+
+ initNodeTree() {
+ this.nodeTree = handle.createNodeTree(this.func);
+ }
+
+ build() {
+ Column(){
+ if (this.nodeTree) {
+ ForEach(this.nodeTree, (item: string[]) => {
+ Row() {
+ ForEach(item, (node: string) => {
+ Scroll() {
+ Text(node)
+ .textAlign(TextAlign.Center)
+ .fontSize(12)
+ }
+ .scrollable(ScrollDirection.Horizontal)
+ .scrollBar(BarState.Off)
+ .layoutWeight(node.length < 8 ? 1 : 2)
+ .borderWidth(1)
+ .borderColor(Color.Black)
+ .margin(1)
+ })
+ }
+ .size({ width: "100%", height: 25 })
+ })
+ }
+ }.justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Center).width('100%').height('100%').padding(5)
+ }
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/ets/component/ImageShow.ets b/drawing/draw/entry/src/main/ets/component/ImageShow.ets
new file mode 100644
index 0000000..e07b1cc
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/component/ImageShow.ets
@@ -0,0 +1,25 @@
+import { AREA_CONTEXT, BoardInfo, CONTEXT, Dimension, } from '../utils/drawBoard/BoardType'
+
+@Component
+export struct imageShow {
+ @Prop board:BoardInfo
+ @Prop loop1:string
+ @Prop loop2:string
+ build() {
+ Stack(){
+ Canvas(CONTEXT).width("100%").height(this.loop2)
+ .onReady(()=>{
+ this.board.drawAxis()
+ if (this.board.dimension == Dimension.TWO) {
+ this.board.drawGraph()
+ }
+ })
+ Canvas(AREA_CONTEXT).width("100%").height(this.loop1)
+ .onReady(()=>{
+ if (this.board.dimension == Dimension.THREE) {
+ this.board.drawGraph()
+ }
+ })
+ }.width('100%').height('100%')
+ }
+}
diff --git a/drawing/draw/entry/src/main/ets/entryability/EntryAbility.ets b/drawing/draw/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000..83fe575
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,44 @@
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+import hilog from '@ohos.hilog';
+import UIAbility from '@ohos.app.ability.UIAbility';
+import Want from '@ohos.app.ability.Want';
+import window from '@ohos.window';
+
+
+export default class EntryAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
+ }
+
+ onDestroy(): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ // Main window is created, set main page for this ability
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+
+ windowStage.loadContent('pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy(): void {
+ // Main window is destroyed, release UI related resources
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
+ }
+
+ onForeground(): void {
+ // Ability has brought to foreground
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
+ }
+
+ onBackground(): void {
+ // Ability has back to background
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
+ }
+}
diff --git a/drawing/draw/entry/src/main/ets/pages/Index.ets b/drawing/draw/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000..38cb6d7
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,187 @@
+import { basicFuncInfo } from '../common/BasicFuncInfo';
+import { basicFunctionsBar } from '../component/BasicFunctionsBar';
+import { controlBar } from '../component/ControlBar';
+import { functionParsingDiagram } from '../component/FunctionParsingDiagram';
+import { imageShow } from '../component/ImageShow';
+import { B1Q2D, B4Q2D, B4Q3D, BoardInfo, IBoardOption, Dimension, Quadrant } from '../utils/drawBoard/BoardType';
+import { FuncType, IVirtualPoints, PointType } from '../utils/drawBoard/drawPoint';
+import { handle } from '../utils/handleFunc/processFunc'
+
+@Entry
+@Component
+struct Index {
+ @Provide('basicFuncList') basicFuncList:Array = []
+ //输入的函数
+ @State inputFunction:string = ""
+ //是否把输入的函数输出成图像
+ @State @Watch('initBoard')outputState:boolean = false
+ //函数是否更改
+ @Provide isFuncChange:boolean = false
+ @State loop1:string = '100%'
+ @State loop2:string = '100%'
+ //board
+ @State board:BoardInfo|null = null
+ @Provide quadrant:Quadrant = Quadrant.FOUR
+ @Provide dimension:Dimension = Dimension.TWO
+ //boardOption
+ //默认的option
+ @State boardOption:IBoardOption = {
+ xStep:0.1,
+ xNumber:0,//
+ yStep:1,
+ yNumber:0,
+ xAmplification:1,
+ yAmplification:1,
+ zAmplification:1
+ }
+
+ aboutToAppear() {
+ handle.setEdge(-10, 10);
+ handle.updateEdge(this.boardOption.xAmplification);
+ }
+ /**
+ * 初始化board
+ */
+ initBoard(){
+ this.createBoard()
+
+ //二维测试样例
+ //三维测试样例
+ // 1.YC y=3
+ // point.points.push({y:3,pointType:PointType.CONTINUE})
+ // point.funcType = FuncType.YC
+ //2.XC x=3
+ // point.points.push({x:3,pointType:PointType.CONTINUE})
+ // point.funcType = FuncType.XC
+ //3.ZC z=3
+ // point.points.push({z:3,pointType:PointType.CONTINUE})
+ // point.funcType = FuncType.ZC
+ //4.YX y=x^2 [-5,5]
+ // let c=-5
+ // while(c <= 5){
+ // point.points.push({x:c,y:-c*c,pointType:PointType.CONTINUE})
+ // c+=0.1;
+ // }
+ // point.funcType = FuncType.YX
+ //5.YX x=y^2
+ // let c = -5
+ // while(c <= 5){
+ // point.points.push({x:-c*c,y:c,pointType:PointType.CONTINUE})
+ // c+=1;
+ // }
+ // point.funcType = FuncType.YX
+ //6.ZX z=x^2
+ // let c=-5
+ // while(c <= 5){
+ // point.points.push({x:c,z:c*c,pointType:PointType.CONTINUE})
+ // c+=1;
+ // }
+ // point.funcType = FuncType.ZX
+ //6.ZY z=y^2
+ // let c=-5
+ // while(c <= 5){
+ // point.points.push({y:c,z:c*c,pointType:PointType.CONTINUE})
+ // c+=1;
+ // }
+ // point.funcType = FuncType.ZY
+ //7.ZXY z= x^2 + y^2 需要先调整步长 否则报错
+ // let dx = -3
+ // let dy = -3
+ // for(let index = 0;index < 6;index++){//this.boardOption.xNumber
+ // for (let index = 0; index < 6; index++) {//this.boardOption.yNumber
+ // point.points.push({x:dx,y:dy,z:-(dx*dx + dy*dy),pointType:PointType.CONTINUE})
+ // dy+=1
+ // }
+ // dx+=1;
+ // dy=-3
+ // }
+ // point.funcType = FuncType.ZXY
+ // //获取到点集
+ let point:IVirtualPoints = {
+ points: handle.coPot,
+ funcType: handle.getFuncType(this.dimension)
+ }
+ console.log('testTag','points_len:',point.points.length)
+ console.log('testTag','points_funcType:',point.funcType)
+
+
+ //初始化画板下的需要绘制的坐标点
+ if(this.isFuncChange){
+ if(this.board != null){
+ this.boardOption = this.board.initMap(point)
+ }
+ this.isFuncChange = false
+ }else{
+ if (this.board != null) {
+ this.board.setOption(this.boardOption,point)
+ }
+ }
+
+ //刷新canvas组件
+ if(this.loop1 == '100%'){
+ this.loop1 = '101%'
+ }else{
+ this.loop1 = '100%'
+ }
+ if(this.loop2 == '100%'){
+ this.loop2 = '101%'
+ }else{
+ this.loop2 = '100%'
+ }
+
+ }
+
+ build() {
+ Column(){
+
+ Row(){
+ if(this.board != null){
+ imageShow({loop1:this.loop1,loop2:this.loop2,board:this.board})
+ .width('50%')
+ .height('100%')
+ .backgroundColor('#F5F5F5')
+ }else{
+ Text('')
+ .width('50%')
+ .height('100%')
+ .backgroundColor('#F5F5F5')
+ }
+
+ functionParsingDiagram({ outputState: this.outputState, func: this.inputFunction })
+ .width('25%')
+ .height('100%')
+ .backgroundColor('#F5F5F5')
+
+ basicFunctionsBar()
+ .width('25%')
+ .height('100%')
+ .backgroundColor(Color.Pink)
+
+ }.width('100%').layoutWeight(1)
+
+ controlBar({inputFuncBody:$inputFunction,outputState:$outputState,boardOption:$boardOption}).width('100%').height('30%')
+
+ }.width('100%').height('100%')
+
+ }
+ /**
+ * 创建board
+ */
+ createBoard(){
+ if (this.dimension == Dimension.TWO){
+ if(this.quadrant == Quadrant.ONE){
+ B1Q2D.setOption(this.boardOption)
+ this.board = B1Q2D
+ }
+ if(this.quadrant == Quadrant.FOUR){
+ B4Q2D.setOption(this.boardOption)
+ this.board = B4Q2D
+ }
+ }
+
+ if(this.dimension == Dimension.THREE){
+ B4Q3D.setOption(this.boardOption)
+ this.board = B4Q3D
+ }
+ }
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/ets/utils/drawBoard/BoardType.ets b/drawing/draw/entry/src/main/ets/utils/drawBoard/BoardType.ets
new file mode 100644
index 0000000..ae8e23e
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/utils/drawBoard/BoardType.ets
@@ -0,0 +1,1016 @@
+import { handle } from '../handleFunc/processFunc';
+import { FuncType, IVirtualPoints, PointType, IBoardPoint , IPoint} from './drawPoint';
+//标准值
+/**
+ * imageShow组件的大小(vp)
+ */
+export const I_WIDTH = 284;
+/**
+ * imageShow组件的大小(vp)
+ */
+export const I_HEIGHT = 174;
+/**
+ * 第一个X刻度对应的值
+ */
+const X_VALUE = 1
+/**
+ * 第一个Y刻度对应的值
+ */
+const Y_VALUE = 1
+/**
+ * 第一个Z刻度对应的值
+ */
+const Z_VALUE = 1
+
+
+export const SETTING:RenderingContextSettings = new RenderingContextSettings(true)
+export const CONTEXT:CanvasRenderingContext2D = new CanvasRenderingContext2D(SETTING)
+export const AREA_CONTEXT:CanvasRenderingContext2D = new CanvasRenderingContext2D(SETTING)
+CONTEXT.font = '10px sans-serif'
+export enum Quadrant{
+ ONE = 1,
+ FOUR = 4
+}
+export enum Dimension{
+ TWO = 2,
+ THREE = 3
+}
+export enum BoardType{
+ TYPE_4Q2D = 42,
+ TYPE_4Q3D = 43,
+ TYPE_1Q2D = 12,
+ TYPE_1Q3D = 13
+}
+export interface IBoardOption{
+ /**
+ * x步长
+ */
+ xStep:number
+ /**
+ * 显示的x个数
+ */
+ xNumber:number
+ /**
+ * y步长
+ */
+ yStep:number
+ /**
+ * 显示的y个数
+ */
+ yNumber:number
+ /**
+ * x轴放大倍数
+ */
+ xAmplification:number
+ /**
+ * y轴放大倍数
+ */
+ yAmplification:number
+ /**
+ * z轴放大倍数
+ */
+ zAmplification:number
+}
+
+
+export abstract class BoardInfo{
+ /**
+ * 默认的Option
+ * 其中属性由用户输入或程序计算进行初始化 可修改
+ */
+ BoardOption:IBoardOption = {
+ xStep:10,
+ xNumber:10,
+ yStep:10,
+ yNumber:10,
+ xAmplification:1,
+ yAmplification:1,
+ zAmplification:1
+ }
+ /**
+ * x刻度之间的像素距离
+ * 初始化后不允许修改
+ */
+ XGapLen:number
+ /**
+ * y刻度之间的像素距离
+ * 初始化后不允许修改
+ */
+ YGapLen:number
+ /**
+ * x刻度个数 (+)
+ * 初始化后不允许修改
+ */
+ XCount:number
+ /**
+ * y刻度个数 (+)
+ * 初始化后不允许修改
+ */
+ YCount:number
+ /**
+ * 原点的x坐标
+ * 初始化后不可修改
+ */
+ X_centre:number = 0
+ /**
+ * 原点的y坐标
+ * 初始化后不可修改
+ */
+ Y_centre:number = 0
+ /**
+ * canvas组件的margin (不包括箭头)
+ * 初始化后不可修改
+ */
+ margin:number
+ /**
+ * 显示象限
+ * 初始化后不可修改
+ */
+ quadrant:Quadrant
+ /**
+ * 显示维度
+ * 初始化后不可修改
+ */
+ dimension:Dimension
+ /**
+ * 画板的宽
+ * 初始化后不可修改
+ */
+ width:number
+ /**
+ * 画板的高
+ * 初始化后不可修改
+ */
+ height:number
+
+ //以下属性可修改
+
+ /**
+ * 单位X刻度对应的虚拟像素
+ * 根据倍数动态修正
+ */
+ XUnit2vp:number
+ /**
+ * 单位Y刻度对应虚拟像素
+ * 根据倍数动态修正
+ */
+ YUnit2vp:number
+ /**
+ * 第一个X刻度对应的值 (+)
+ * 根据倍数动态修正
+ */
+ XValue:number = X_VALUE
+ /**
+ * 第一个Y刻度对应的值 (+)
+ * 根据倍数动态修正
+ */
+ YValue:number = Y_VALUE
+
+ /**
+ * 虚拟点集
+ * 必填参数为pointType、funcType
+ * xyz参数可选 依据funcType进行相应参数填写 填写规则查看枚举值说明
+ */
+ virtualPoints:IVirtualPoints = {points:[],funcType:FuncType.NONE}
+ /**
+ * 画板点集
+ * 必填参数为xy、pointType 由虚拟点集转变而来
+ */
+ boardPoints:Array = []
+
+ constructor(margin:number,quadrant:Quadrant,dimension:Dimension,Xgl:number,Ygl:number,XC:number,YC:number) {
+ this.margin = margin
+ this.quadrant = quadrant
+ this.dimension = dimension
+ //画板属性
+ this.width = I_WIDTH - 2 * this.margin
+ this.height = I_HEIGHT - 2 * this.margin
+ //定义单位刻度对应像素
+ this.XGapLen = Xgl
+ this.YGapLen = Ygl
+ this.XUnit2vp = Xgl
+ this.YUnit2vp = Ygl
+ //定义个数
+ this.XCount = XC
+ this.YCount = YC
+ }
+
+ /**
+ * 绘制坐标轴
+ */
+ public abstract drawAxis();
+
+ /**
+ * 设置画板上的xy数对
+ * 同时根据xy数对计算出合适的
+ *
+ * 初始化点集
+ * 该点集为虚拟点集
+ *
+ * 返回BoardOption
+ */
+ public initMap(virtualPoints:IVirtualPoints){
+ this.virtualPoints = virtualPoints
+ this.boardPoints = []
+ this.updateAmplification()
+ this.updateCorrectBoardInfo()
+ this.transToBoardPoints()
+ return this.BoardOption
+ }
+
+ /**
+ * 用户设置BoardOption
+ */
+ public setOption(option:IBoardOption,virtualPoints?:IVirtualPoints){
+ this.BoardOption = option
+ if(virtualPoints){
+ this.initMap(virtualPoints)
+ }
+ this.boardPoints = []
+ this.updateAmplification()
+ this.updateCorrectBoardInfo()
+ this.transToBoardPoints()
+ }
+
+ /**
+ * 绘制折线
+ */
+ public drawGraph(context:CanvasRenderingContext2D = CONTEXT,boardPoints:Array = this.boardPoints){
+ let isMeetDisContinue = false
+ let i = 0
+ while(boardPoints[i].pointType == PointType.DISCONTINUE && i <= boardPoints.length - 1){
+ i++
+ }
+ if(i == boardPoints.length){
+ //全间断点
+ return
+ }
+ if(i != 0){
+ context.fillRect(vp2px(boardPoints[i].x - 1),vp2px(boardPoints[i].y - 1),vp2px(1.5),vp2px(1.5))
+ }
+ context.moveTo(vp2px(boardPoints[i].x),vp2px(boardPoints[i].y))
+ //间断点画圆
+ for (let index = i + 1; index < boardPoints.length ; index++) {
+ if(boardPoints[index].pointType == PointType.DISCONTINUE){
+ isMeetDisContinue = true
+ continue
+ }
+ if(isMeetDisContinue){
+ context.moveTo(vp2px(boardPoints[index].x),vp2px(boardPoints[index].y))
+ context.fillRect(vp2px(boardPoints[index].x - 1),vp2px(boardPoints[index].y - 1),vp2px(1.5),vp2px(1.5))
+ isMeetDisContinue = false
+ }else{
+ context.lineTo(vp2px(boardPoints[index].x),vp2px(boardPoints[index].y))
+ }
+ }
+ context.stroke()
+ }
+
+ /**
+ * 连接两个坐标点 默认两点pointType属性均为CONTINUE
+ */
+ protected drawLine(point1:IBoardPoint,point2:IBoardPoint,context:CanvasRenderingContext2D = CONTEXT){
+ context.beginPath()
+ context.moveTo(vp2px(point1.x),vp2px(point1.y))
+ context.lineTo(vp2px(point2.x),vp2px(point2.y))
+ context.stroke()
+ }
+
+ /**
+ * 在初始化点集后根据虚拟点集修正xy倍数
+ * 只需要修正因变量的值
+ */
+ protected updateAmplification(){
+ switch (this.virtualPoints.funcType){
+ case FuncType.YC: case FuncType.YX:
+ this.updateYAmplification()
+ break;
+ case FuncType.XC:
+ this.updateXAmplification()
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * 将虚拟点集(二维)转变为画布点集
+ */
+ protected transToBoardPoints(){
+ switch (this.virtualPoints.funcType){
+ case FuncType.YC:
+ if(this.quadrant == Quadrant.ONE){
+ this.boardPoints.push({x:this.getXPosition(0),y:this.getYPosition(this.virtualPoints.points[0].y!),pointType:PointType.CONTINUE})
+ this.boardPoints.push({x:this.getXPosition(this.XCount * this.XValue),y:this.getYPosition(this.virtualPoints.points[0].y!),pointType:this.virtualPoints.points[0].pointType})
+ }else{
+ this.boardPoints.push({x:this.getXPosition(-this.XCount * this.XValue),y:this.getYPosition(this.virtualPoints.points[0].y!),pointType:this.virtualPoints.points[0].pointType})
+ this.boardPoints.push({x:this.getXPosition(this.XCount * this.XValue),y:this.getYPosition(this.virtualPoints.points[0].y!),pointType:this.virtualPoints.points[0].pointType})
+ }
+ break;
+ case FuncType.XC:
+ if(this.quadrant == Quadrant.ONE){
+ this.boardPoints.push({x:this.getXPosition(this.virtualPoints.points[0].x!),y:this.getYPosition(0),pointType:PointType.CONTINUE})
+ this.boardPoints.push({x:this.getXPosition(this.virtualPoints.points[0].x!),y:this.getYPosition(this.YCount * this.YValue),pointType:this.virtualPoints.points[0].pointType})
+ }else{
+ this.boardPoints.push({x:this.getXPosition(this.virtualPoints.points[0].x!),y:this.getYPosition(-this.YCount * this.YValue),pointType:PointType.CONTINUE})
+ this.boardPoints.push({x:this.getXPosition(this.virtualPoints.points[0].x!),y:this.getYPosition(this.YCount * this.YValue),pointType:this.virtualPoints.points[0].pointType})
+ }
+ break;
+ case FuncType.YX:
+ for (let index = 0; index < this.virtualPoints.points.length; index++) {
+ this.boardPoints.push({x:this.getXPosition(this.virtualPoints.points[index].x!),y:this.getYPosition(this.virtualPoints.points[index].y!),pointType:this.virtualPoints.points[index].pointType})
+ }
+ break
+ default :
+ break;
+ }
+
+ }
+
+ /**
+ * 更新x的放大倍数
+ */
+ protected updateXAmplification(){
+ this.BoardOption.xAmplification = 1
+ let x_max = this.virtualPoints.points[0].x!
+ let x_min = this.virtualPoints.points[0].x!
+ for (let index = 1; index < this.virtualPoints.points.length; index++) {
+ if(this.virtualPoints.points[index].pointType == PointType.DISCONTINUE){
+ continue
+ }
+ if(this.virtualPoints.points[index].x != undefined && x_max < this.virtualPoints.points[index].x!){
+ x_max = this.virtualPoints.points[index].x!
+ }
+ if(this.virtualPoints.points[index].x != undefined && x_min > this.virtualPoints.points[index].x!){
+ x_min = this.virtualPoints.points[index].x!
+ }
+ }
+ let x = 0;
+ if(!(x_min > -this.XCount && x_max < this.XCount)){
+ if(x_min < 0 && x_max < 0){
+ x = x_min
+ }else if(x_min > 0 && x_max > 0){
+ x = x_max
+ }else{
+ x = x_max > -x_min?x_max: -x_min
+ }
+ let m = Number((x/this.XCount).toFixed(0))
+ let r = x%this.XCount
+ if(r == 0){
+ this.BoardOption.xAmplification = m
+ }else if(r >= 5){
+ this.BoardOption.xAmplification = m
+ }else if(r < 5 && r > 0){
+ this.BoardOption.xAmplification = m + 1
+ }
+ }
+ }
+
+ /**
+ * 更新y的放大倍数
+ */
+ protected updateYAmplification(){
+ this.BoardOption.yAmplification = 1
+ let y_max = this.virtualPoints.points[0].y!
+ let y_min = this.virtualPoints.points[0].y!
+ for (let index = 1; index < this.virtualPoints.points.length; index++) {
+ if(this.virtualPoints.points[index].pointType == PointType.DISCONTINUE){
+ continue
+ }
+ if(y_max < this.virtualPoints.points[index].y!){
+ y_max = this.virtualPoints.points[index].y!
+ }
+ if(y_min > this.virtualPoints.points[index].y!){
+ y_min = this.virtualPoints.points[index].y!
+ }
+ }
+ let y = 0;
+ if(!(y_min > -this.YCount && y_max < this.YCount)){
+ if(y_min < 0){
+ y_min = -y_min
+ }
+ if(y_max < 0){
+ y_max = -y_max
+ }
+ if(y_max > y_min){
+ y = y_max
+ }else {
+ y = y_min
+ }
+ let m = Number((y/this.YCount).toFixed(0))
+ let r = y%this.YCount
+ if(r == 0){
+ this.BoardOption.yAmplification = m
+ }else if(r >= 5){
+ this.BoardOption.yAmplification = m
+ }else if(r < 5 && r > 0){
+ this.BoardOption.yAmplification = m + 1
+ }
+ }
+ }
+ /**
+ * 在修正完xy放大倍数后进行参数1.第一个刻度对应的值2.单位刻度对应的VP大小进行修正
+ */
+ protected updateCorrectBoardInfo(){
+ this.XValue = X_VALUE * this.BoardOption.xAmplification
+ this.XUnit2vp = Number((this.XGapLen / this.BoardOption.xAmplification).toFixed(5))
+ this.YValue = Y_VALUE * this.BoardOption.yAmplification
+ this.YUnit2vp = Number((this.YGapLen / this.BoardOption.yAmplification).toFixed(10))
+ }
+
+ /**
+ * 将虚拟坐标转变为画布坐标x(二维)
+ */
+ private getXPosition(x:number){
+ return this.X_centre + this.XUnit2vp*x
+ }
+ /**
+ * 将虚拟坐标转变为画布坐标x(二维)
+ */
+ private getYPosition(y:number){
+ return this.Y_centre - this.YUnit2vp*y
+ }
+}
+
+
+class board4Q2D extends BoardInfo{
+
+ constructor() {
+ super(5,Quadrant.FOUR,Dimension.TWO,13,10,10,8);
+ this.X_centre = (2 * this.margin + this.width)/2
+ this.Y_centre = (2 * this.margin + this.height)/2
+ }
+
+ public drawAxis(){
+ CONTEXT.beginPath()
+ CONTEXT.moveTo(vp2px(this.margin),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre + 3))
+ CONTEXT.lineTo(vp2px(this.width + this.margin + 3),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre - 3))
+ CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre))
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(this.height + this.margin))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.X_centre - 3),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin - 3))
+ CONTEXT.lineTo(vp2px(this.X_centre + 3),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin))
+ CONTEXT.fill()
+ CONTEXT.fillText("0",vp2px(this.X_centre + 2),vp2px(this.Y_centre + 6))
+ let valueX = this.X_centre - this.XValue * this.XUnit2vp * (this.XCount + 1)
+ let valueY = this.Y_centre + 6
+ let value = -this.XValue * this.XCount
+ let count = 2 * this.XCount
+ //绘制X轴
+ while(--count >= 0) {
+ valueX += this.XGapLen
+ if(value == 0){
+ value += this.XValue
+ valueX += this.XGapLen
+ }
+ CONTEXT.moveTo(vp2px(valueX),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(valueX),vp2px(this.Y_centre - 3))
+ CONTEXT.fillText(value.toString(),vp2px(valueX - this.getXTextBias(value.toString())),vp2px(valueY))
+ value += this.XValue
+ }
+ //绘制Y轴
+ valueX = this.X_centre
+ valueY = this.Y_centre + this.YValue * this.YUnit2vp * (this.YCount + 1)
+ value = -this.YValue * this.YCount
+ count = 2 * this.YCount
+ while(--count >= 0) {
+ valueY -= this.YGapLen
+ if(value == 0){
+ value += this.YValue
+ valueY -= this.YGapLen
+ }
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(valueY))
+ CONTEXT.lineTo(vp2px(this.X_centre + 3),vp2px(valueY))
+ CONTEXT.fillText(value.toString(),vp2px(valueX - 4 - this.getYTextBias(value.toString())),vp2px(valueY + 3))
+ value += this.YValue
+ }
+ CONTEXT.stroke()
+ }
+
+ /**
+ * 获取修正后的X刻度对应的文本的显示横向偏移量
+ */
+ private getXTextBias(value:string){
+
+ let bias = value.length
+ let flag = 1
+ if(value[0] == '-'){
+ flag = -2
+ }
+ return (bias * (bias - 1))/2 + 1 + flag * this.XGapLen/50;
+ }
+ /**
+ * 获取修正后的Y刻度对应的文本的显示横向偏移量
+ */
+ private getYTextBias(value:string){
+ let bias = value.length
+ if(bias == 1){
+ return 1
+ }
+ return bias * 3.5;
+ }
+
+}
+
+class board1Q2D extends BoardInfo{
+
+ constructor() {
+ super(15,Quadrant.ONE,Dimension.TWO,12.5,13,20,10);
+
+ this.X_centre = this.margin
+ this.Y_centre = this.margin + this.height
+ }
+
+ public drawAxis(){
+ CONTEXT.beginPath()
+ CONTEXT.moveTo(vp2px(this.margin),vp2px(this.margin + this.height))
+ CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.margin - 3),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin - 3))
+ CONTEXT.lineTo(vp2px(this.margin + 3),vp2px(this.margin))
+ CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin))
+ CONTEXT.fill()
+ CONTEXT.moveTo(vp2px(this.margin),vp2px(this.margin + this.height))
+ CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height))
+ CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height + 3))
+ CONTEXT.lineTo(vp2px(this.margin + this.width + 3),vp2px(this.margin + this.height))
+ CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height - 3))
+ CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height))
+ CONTEXT.fill()
+ CONTEXT.fillText("0",vp2px(this.X_centre - 5),vp2px(this.Y_centre + 5))
+ let valueX = this.X_centre
+ let valueY = this.Y_centre + 6
+ let value = this.XValue
+ let count = this.XCount
+ //x轴
+ while(--count >= 0) {
+ valueX += this.XGapLen
+ CONTEXT.moveTo(vp2px(valueX),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(valueX),vp2px(this.Y_centre - 3))
+ CONTEXT.fillText(value.toString(),vp2px(valueX-this.getXTextBias(value.toString())),vp2px(valueY))
+ value += this.XValue
+ }
+ //y轴
+ valueX = this.X_centre
+ valueY = this.Y_centre
+ value = this.YValue
+ count = this.YCount
+ while(--count >= 0) {
+ valueY -= this.YGapLen
+ if(value == 0){
+ value += this.YValue
+ valueY -= this.YGapLen
+ }
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(valueY))
+ CONTEXT.lineTo(vp2px(this.X_centre + 3),vp2px(valueY))
+ CONTEXT.fillText(value.toString(),vp2px(valueX - 4 - this.getYTextBias(value.toString())),vp2px(valueY + 3))
+ value += this.YValue
+ }
+ CONTEXT.stroke()
+ }
+
+ /**
+ * 获取修正后的X刻度对应的文本的显示横向偏移量
+ */
+ private getXTextBias(value:string){
+
+ let bias = value.length
+ let flag = 1
+ if(value[0] == '-'){
+ flag = -2
+ }
+ return (bias * (bias - 1))/2 + 1 + flag * this.XGapLen/50;
+ }
+ /**
+ * 获取修正后的Y刻度对应的文本的显示横向偏移量
+ */
+ private getYTextBias(value:string){
+ let bias = value.length
+ if(bias == 1){
+ return 1
+ }
+ return bias * 3.5;
+ }
+
+}
+
+class board4Q3D extends BoardInfo{
+ /**
+ * z刻度间的像素大小
+ */
+ ZGapLen:number
+ /**
+ * 显示的z刻度个数
+ */
+ ZCount:number
+ /**
+ * Z单位刻度的像素大小
+ */
+ ZUnit2vp:number
+ /**
+ * Z第一个刻度对应的值
+ */
+ ZValue:number
+
+ /*
+ * x负半与y正半夹角正切值
+ */
+ TAN:number
+
+ /**
+ * 二维矩阵
+ */
+ boardPoints2D:IBoardPoint[][] = []
+
+ /**
+ * 绘制曲线
+ */
+
+ constructor() {
+ super(32,Quadrant.FOUR,Dimension.THREE,11,8.5,5,10)
+ this.X_centre = (2 * this.margin + this.width)/2
+ //加15是根据画板人为预先计算得到的较理想的值
+ this.Y_centre = (2 * this.margin + this.height)/2
+ this.ZGapLen = 7
+ this.ZCount = 8
+ this.ZUnit2vp = 7
+ this.ZValue = 1
+ this.BoardOption.zAmplification = 1
+ this.TAN = this.height / this.width // margin = 32时 TAN = 0.5
+ }
+
+ public drawAxis(){
+ CONTEXT.beginPath()
+ CONTEXT.moveTo(vp2px(this.margin + 20),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin - 20),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin - 20),vp2px(this.Y_centre + 3))
+ CONTEXT.lineTo(vp2px(this.width + this.margin - 20 + 3),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.width + this.margin - 20),vp2px(this.Y_centre - 3))
+ CONTEXT.lineTo(vp2px(this.width + this.margin - 20),vp2px(this.Y_centre))
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(this.height + this.margin + 8))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin - 8))
+ CONTEXT.lineTo(vp2px(this.X_centre - 3),vp2px(this.margin - 8))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin - 3 - 8))
+ CONTEXT.lineTo(vp2px(this.X_centre + 3),vp2px(this.margin - 8))
+ CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin - 8))
+ CONTEXT.moveTo(vp2px(this.X_centre + this.width/4),vp2px(this.Y_centre - this.height/4))
+ CONTEXT.lineTo(vp2px(this.X_centre - this.width/4),vp2px(this.Y_centre + this.height/4))
+ CONTEXT.lineTo(vp2px(this.X_centre - this.width/4 - 1),vp2px(this.Y_centre + this.height/4 - 2))
+ CONTEXT.lineTo(vp2px(this.X_centre - (this.width)/4 - 3),vp2px(this.Y_centre + (this.height)/4 + 1.5))
+ CONTEXT.lineTo(vp2px(this.X_centre - this.width/4 + 1),vp2px(this.Y_centre + this.height/4 + 2))
+ CONTEXT.lineTo(vp2px(this.X_centre - this.width/4),vp2px(this.Y_centre + this.height/4))
+ CONTEXT.fill()
+ //y
+ let Count = 1
+ while(Count <= this.YCount){
+ CONTEXT.moveTo(vp2px(this.X_centre + this.YGapLen * Count),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.X_centre + this.YGapLen * Count),vp2px(this.Y_centre - 2))
+ Count ++;
+ }
+ Count = 1;
+ while(Count <= this.YCount){
+ CONTEXT.moveTo(vp2px(this.X_centre - this.YGapLen * Count),vp2px(this.Y_centre))
+ CONTEXT.lineTo(vp2px(this.X_centre - this.YGapLen * Count),vp2px(this.Y_centre + 2))
+ Count ++;
+ }
+ //z
+ Count = 1
+ while (Count <= this.ZCount) {
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(this.Y_centre - this.ZGapLen * Count))
+ CONTEXT.lineTo(vp2px(this.X_centre - 2),vp2px(this.Y_centre - this.ZGapLen * Count))
+ Count ++;
+ }
+ Count = 1
+ while (Count <= this.ZCount) {
+ CONTEXT.moveTo(vp2px(this.X_centre),vp2px(this.Y_centre + this.ZGapLen * Count))
+ CONTEXT.lineTo(vp2px(this.X_centre + 2),vp2px(this.Y_centre + this.ZGapLen * Count))
+ Count ++;
+ }
+ //x
+ Count = 1
+ while (Count <= this.XCount) {
+ CONTEXT.moveTo(vp2px(this.X_centre - (this.XGapLen * Count) * 0.8944),vp2px(this.Y_centre + (this.XGapLen * Count) * 0.4472))
+ CONTEXT.lineTo(vp2px(this.X_centre - (this.XGapLen * Count) * 0.8944 + 1),vp2px(this.Y_centre + (this.XGapLen * Count) * 0.4472 + 2))
+ Count ++;
+ }
+ Count = 1
+ while (Count <= this.XCount) {
+ CONTEXT.moveTo(vp2px(this.X_centre + (this.XGapLen * Count) * 0.8944),vp2px(this.Y_centre - (this.XGapLen * Count) * 0.4472))
+ CONTEXT.lineTo(vp2px(this.X_centre + (this.XGapLen * Count) * 0.8944 - 1),vp2px(this.Y_centre - (this.XGapLen * Count) * 0.4472 - 2))
+ Count ++;
+ }
+
+ CONTEXT.stroke()
+ }
+
+ /**
+ * 绘制曲面图
+ * @override
+ */
+ public drawGraph() {
+ AREA_CONTEXT.beginPath()
+ AREA_CONTEXT.strokeStyle = '#FF0000'
+
+
+ if(this.virtualPoints.funcType == FuncType.YC || this.virtualPoints.funcType == FuncType.ZC || this.virtualPoints.funcType == FuncType.XC){
+ super.drawGraph(AREA_CONTEXT)
+ }
+
+ if(this.virtualPoints.funcType == FuncType.YX || this.virtualPoints.funcType == FuncType.ZX || this.virtualPoints.funcType == FuncType.ZY){
+ let len = this.virtualPoints.points.length
+ let pointsSide1 = this.boardPoints.slice(0,len)
+ super.drawGraph(AREA_CONTEXT,pointsSide1)
+ let pointsSide2 = this.boardPoints.slice(len)
+ super.drawGraph(AREA_CONTEXT,pointsSide2)
+
+ //端点处连接
+ super.drawLine(pointsSide1[0],pointsSide2[0],AREA_CONTEXT)
+ super.drawLine(pointsSide1[len - 1],pointsSide2[len - 1],AREA_CONTEXT)
+
+ }
+
+ if(this.virtualPoints.funcType == FuncType.ZXY){
+ //绘制y轴方向
+ for (let index = 0; index < this.BoardOption.xNumber; index++) {
+ super.drawGraph(AREA_CONTEXT,this.boardPoints2D[index])
+ }
+ //绘制x轴方向
+ for (let index1 = 0; index1 < this.BoardOption.yNumber; index1++) {
+ let arr:Array = []
+ for (let index2 = 0; index2 < this.BoardOption.xNumber; index2++) {
+ arr.push(this.boardPoints2D[index2][index1])
+ }
+ super.drawGraph(AREA_CONTEXT,arr)
+ }
+ }
+ }
+
+ /**
+ * 新增对funcType为其他情况的判断修正
+ * @override
+ */
+ protected updateAmplification(){
+
+ super.updateAmplification()
+
+ switch (this.virtualPoints.funcType){
+ case FuncType.ZC:
+ this.updateZAmplification()
+ this.updateYAmplification()
+ this.updateXAmplification()
+ break;
+ case FuncType.ZX:
+ this.updateZAmplification()
+ this.updateYAmplification()
+ break;
+ case FuncType.ZY:
+ this.updateZAmplification()
+ this.updateXAmplification()
+ break;
+ case FuncType.ZXY:
+ this.updateZAmplification()
+ break;
+ default :
+ break;
+ }
+
+ }
+
+ /**
+ * 新增对z的参数修正
+ * @override
+ */
+ protected updateCorrectBoardInfo(){
+
+ super.updateCorrectBoardInfo()
+ this.ZValue = Z_VALUE * this.BoardOption.zAmplification
+ this.ZUnit2vp = Number((this.ZGapLen / this.BoardOption.zAmplification).toFixed(5))
+ }
+
+ /**
+ * 将虚拟点集(三维)转变为画布点集
+ * @override
+ */
+ protected transToBoardPoints(){
+ switch (this.virtualPoints.funcType){
+ case FuncType.YC:
+ //4个点
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.XValue * this.XCount,this.virtualPoints.points[0].y!),
+ y:this.getYPositionByXYZ(this.XValue * this.XCount,-this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.XValue * this.XCount,this.virtualPoints.points[0].y!),
+ y:this.getYPositionByXYZ(this.XValue * this.XCount,this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(-this.XValue * this.XCount,this.virtualPoints.points[0].y!),
+ y:this.getYPositionByXYZ(-this.XValue * this.XCount,this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(-this.XValue * this.XCount,this.virtualPoints.points[0].y!),
+ y:this.getYPositionByXYZ(-this.XValue * this.XCount,-this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.XValue * this.XCount,this.virtualPoints.points[0].y!),
+ y:this.getYPositionByXYZ(this.XValue * this.XCount,-this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ break;
+ case FuncType.XC:
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[0].x!,this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[0].x!,-this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[0].x!,this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[0].x!,this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[0].x!,-this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[0].x!,this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[0].x!,-this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[0].x!,-this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[0].x!,this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[0].x!,-this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ break;
+ case FuncType.YX:
+ for (let index = 0; index < this.virtualPoints.points.length; index++) {
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[index].x!,this.virtualPoints.points[index].y!),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[index].x!,-this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[index].pointType
+ })
+ }
+ for (let index = 0; index < this.virtualPoints.points.length; index++) {
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[index].x!,this.virtualPoints.points[index].y!),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[index].x!,this.ZValue * this.ZCount),
+ pointType:this.virtualPoints.points[index].pointType
+ })
+ }
+ break;
+ case FuncType.ZC:
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.XValue * this.XCount,this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.XValue * this.XCount,this.virtualPoints.points[0].z!),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(-this.XValue * this.XCount,this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(-this.XValue * this.XCount,this.virtualPoints.points[0].z!),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(-this.XValue * this.XCount,-this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(-this.XValue * this.XCount,this.virtualPoints.points[0].z!),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.XValue * this.XCount,-this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.XValue * this.XCount,this.virtualPoints.points[0].z!),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.XValue * this.XCount,this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.XValue * this.XCount,this.virtualPoints.points[0].z!),
+ pointType:this.virtualPoints.points[0].pointType
+ })
+ break;
+ case FuncType.ZX:
+ for (let index = 0; index < this.virtualPoints.points.length; index++) {
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[index].x!,this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[index].x!,this.virtualPoints.points[index].z!),
+ pointType:this.virtualPoints.points[index].pointType
+ })
+ }
+ for (let index = 0; index < this.virtualPoints.points.length; index++) {
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.virtualPoints.points[index].x!,-this.YValue * this.YCount),
+ y:this.getYPositionByXYZ(this.virtualPoints.points[index].x!,this.virtualPoints.points[index].z!),
+ pointType:this.virtualPoints.points[index].pointType
+ })
+ }
+ break;
+ case FuncType.ZY:
+ for (let index = 0; index < this.virtualPoints.points.length; index++) {
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(this.XValue * this.XCount,this.virtualPoints.points[index].y!),
+ y:this.getYPositionByXYZ(this.XValue * this.XCount,this.virtualPoints.points[index].z!),
+ pointType:this.virtualPoints.points[index].pointType
+ })
+ }
+ for (let index = 0; index < this.virtualPoints.points.length; index++) {
+ this.boardPoints.push({
+ x:this.getXPositionByXYZ(-this.XValue * this.XCount,this.virtualPoints.points[index].y!),
+ y:this.getYPositionByXYZ(-this.XValue * this.XCount,this.virtualPoints.points[index].z!),
+ pointType:this.virtualPoints.points[index].pointType
+ })
+ }
+ break;
+ case FuncType.ZXY:
+ for (let index = 0; index < this.virtualPoints.points.length; index++) {
+ this.boardPoints.push({x:this.getXPositionByXYZ(this.virtualPoints.points[index].x!,this.virtualPoints.points[index].y!),y:this.getYPositionByXYZ(this.virtualPoints.points[index].x!,this.virtualPoints.points[index].z!),pointType:this.virtualPoints.points[index].pointType})
+ }
+ this.transTo2DArray()
+ default :
+ break;
+ }
+ }
+
+ /**
+ * 修正z的放大倍数
+ */
+ private updateZAmplification(){
+ this.BoardOption.zAmplification = 1
+ let z_max = this.virtualPoints.points[0].z!
+ let z_min = this.virtualPoints.points[0].z!
+ for (let index = 1; index < this.virtualPoints.points.length; index++) {
+ if(this.virtualPoints.points[index].pointType == PointType.DISCONTINUE){
+ continue
+ }
+ if(z_max < this.virtualPoints.points[index].z!){
+ z_max = this.virtualPoints.points[index].z!
+ }
+ if(z_min > this.virtualPoints.points[index].z!){
+ z_min = this.virtualPoints.points[index].z!
+ }
+ }
+ let z = 0;
+ if(!(z_min > -this.ZCount && z_max < this.ZCount)) {
+ if (z_min < 0 && z_max < 0) {
+ z = z_min
+ } else if (z_min > 0 && z_max > 0) {
+ z = z_max
+ } else {
+ z = z_max > -z_min ? z_max : -z_min
+ }
+ let m = Number((z/this.ZCount).toFixed(0))
+ let r = z%this.ZCount
+ if(r == 0){
+ this.BoardOption.zAmplification = m
+ }else if(r >= 5){
+ this.BoardOption.zAmplification = m
+ }else if(r < 5 && r > 0){
+ this.BoardOption.zAmplification = m + 1
+ }
+ }
+ }
+
+ /**
+ * 根据虚拟点集的坐标计算出画板坐标系下的x坐标
+ */
+ private getXPositionByXYZ(x:number,y:number){
+ return this.X_centre + this.YUnit2vp * y - 0.8944 * this.XUnit2vp * x
+ }
+
+ /**
+ * 根据虚拟点集的坐标计算出画板坐标系下的x坐标
+ */
+ private getYPositionByXYZ(x:number,z:number){
+ return this.Y_centre + this.XUnit2vp * x / 2.236 - this.ZUnit2vp * z
+ }
+
+ /**
+ * 将画板点集按照x个数、y个数转变为二维数组的格式
+ */
+ private transTo2DArray(){
+ this.boardPoints2D = []
+ let i = 0;
+ this.BoardOption.xNumber = handle.row;
+ this.BoardOption.yNumber = handle.col;
+ console.log(handle.row + " " + handle.col)
+ for (let index1 = 0; index1 < this.BoardOption.xNumber; index1++) {
+ this.boardPoints2D.push([])
+ for (let index2 = 0; index2 < this.BoardOption.yNumber; index2++) {
+ this.boardPoints2D[index1].push({x:this.boardPoints[i].x,y:this.boardPoints[i].y,pointType:this.boardPoints[i].pointType})
+ i++;
+ }
+ }
+ }
+
+}
+
+export let B4Q2D:BoardInfo = new board4Q2D()
+export let B4Q3D:BoardInfo = new board4Q3D()
+export let B1Q2D:BoardInfo = new board1Q2D()
diff --git a/drawing/draw/entry/src/main/ets/utils/drawBoard/drawPoint.ets b/drawing/draw/entry/src/main/ets/utils/drawBoard/drawPoint.ets
new file mode 100644
index 0000000..e382a77
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/utils/drawBoard/drawPoint.ets
@@ -0,0 +1,79 @@
+export enum PointType{
+ DISCONTINUE = 0,
+ CONTINUE = 1,
+}
+export enum FuncType{
+
+ /**
+ * 未选择
+ */
+ NONE = -1,
+ /**
+ * y = c型
+ * 为此枚举值时 只能填y的值且其为c的值 且虚拟点集长度为1 pointType字段必为CONTINUE
+ */
+ YC = 0,
+ /**
+ * x = c型
+ * 为此枚举值时 只能填x的值且其为c的值 且虚拟点集长度为1 pointType字段必为CONTINUE
+ */
+ XC = 1,
+ /*
+ * y = f(x)型
+ * 为此枚举值时 虚拟点集中只能填xy的值
+ */
+ YX = 2,
+ /**
+ * z = c型
+ * 为此枚举值时 只能填z的值且其为c的值 且虚拟点集长度为1 pointType字段必为CONTINUE
+ */
+ ZC = 3,
+ /**
+ * z = f(x)型
+ * 为此枚举值时 虚拟点集中只能填zx的值
+ */
+ ZX = 4,
+ /**
+ * z = f(y)型
+ * 为此枚举值时 虚拟点集中只能填zy的值
+ */
+ ZY = 5,
+ /**
+ * z = f(x,y)型
+ * 为此枚举值时 虚拟点集中只能填zxy的值
+ * 且必须为边界值
+ *
+ */
+ ZXY = 6
+}
+/**
+ * 虚拟点集
+ * 根据函数关系和步长、个数直接得到的点集
+ */
+export interface IPoint{
+ x?:number
+
+ y?:number
+
+ z?:number
+
+ pointType:PointType
+}
+export interface IVirtualPoints{
+
+ points:Array
+
+ funcType:FuncType
+
+}
+/**
+ * 画板点集
+ * 以屏幕左上角为原点的平面坐标系下的点集
+ */
+export interface IBoardPoint{
+ x:number
+
+ y:number
+
+ pointType:PointType
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/ets/utils/handleFunc/analysis.ets b/drawing/draw/entry/src/main/ets/utils/handleFunc/analysis.ets
new file mode 100644
index 0000000..76f4dcd
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/utils/handleFunc/analysis.ets
@@ -0,0 +1,361 @@
+interface replaceableVar {
+ char: string,
+ value: number
+}
+
+class MathExpressionParser {
+ private tokens: string[];
+ private currentTokenIndex: number;
+ private variables: replaceableVar[];
+ private nodeTree: string[][];
+ private exp: string;
+ private currentExpIndex: number;
+ private layer: number;
+
+ constructor() {
+ this.tokens = []
+ this.currentTokenIndex = 0
+ this.variables = []
+ // this.nodeTree = new Array(50).fill([])
+ this.nodeTree = [];
+ for (let i = 0; i < 50; i++) {
+ this.nodeTree.push([]);
+ }
+ this.exp = ""
+ this.currentExpIndex = 0
+ this.layer = 0
+ }
+
+ private tokenize(expression: string): string[] {
+ const regex: RegExp = new RegExp("(\\d+\\.?\\d*|\\.\\d+|[a-zA-Z]+|\\S)", "g");
+ const originalTokens = expression.match(regex) || [];
+
+ const Tokens: string[] = [];
+ for (let i = 0; i < originalTokens.length; i++) {
+ Tokens.push(originalTokens[i]);
+ if (i < originalTokens.length - 1) {
+ const currentToken = originalTokens[i];
+ const nextToken = originalTokens[i + 1];
+ if ((this.isNumber(currentToken) && this.isVariable(nextToken)) ||
+ (this.isVariable(currentToken) && this.isVariable(nextToken)) ||
+ (currentToken === ')' && (this.isVariable(nextToken) || this.isNumber(nextToken))) ||
+ (this.isNumber(currentToken) && nextToken === '(') ||
+ (this.isVariable(currentToken) && nextToken === '(')) {
+ Tokens.push('*');
+ }
+ }
+ }
+ return Tokens;
+ }
+
+ private existInArr(token: string): number {
+ for (let i: number = 0; i < this.variables.length; i++) {
+ if (this.variables[i].char == token) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private isNumber(token: string): boolean {
+ const num = Number(token);
+ return !Number.isNaN(num) && Number.isFinite(num);
+ }
+
+ private isVariable(token: string): boolean {
+ const temp: RegExp = new RegExp("^[a-zA-Z]+$")
+ return temp.test(token) && !this.isFunction(token) && token !== "π";
+ }
+
+ private isFunction(token: string): boolean {
+ return ['pow', 'sin', 'cos', 'tan', 'ln', 'sqrt', 'log2', 'log10'].includes(token);
+ }
+
+ private getCurrentToken(): string {
+ return this.tokens[this.currentTokenIndex];
+ }
+
+ private getNextToken(): string {
+ this.currentTokenIndex++;
+ return this.getCurrentToken();
+ }
+
+ private parsePrimaryExpression(): number {
+ const token = this.getCurrentToken();
+ if (token === '(') {
+ this.getNextToken(); // consume '('
+ const result = this.parseExpression();
+ if (this.getCurrentToken() !== ')') {
+ throw new Error("Expected ')' after expression");
+ }
+ this.getNextToken(); // consume ')'
+ return result;
+ } else if (token === 'π') {
+ this.getNextToken(); // consume 'π'
+ return Math.PI;
+ } else if (this.isVariable(token)) {
+ if (this.existInArr(token) != -1) {
+ const value = this.variables[this.existInArr(token)].value;
+ this.getNextToken(); // consume variable
+ return value;
+ } else {
+ throw new Error(`Unknown variable: ${token}`);
+ }
+ } else if (this.isFunction(token)) {
+ return this.parseFunction();
+ } else {
+ const num = Number(token);
+ this.getNextToken(); // consume number
+ return num;
+ }
+ }
+
+ private parseFunction(): number {
+ const functionName = this.getCurrentToken();
+ this.getNextToken(); // consume function name
+ if (this.getCurrentToken() !== '(') {
+ throw new Error(`Expected '(' after function name ${functionName}`);
+ }
+ this.getNextToken(); // consume '('
+
+ const argument1 = this.parseExpression();
+
+ if (functionName === 'pow') {
+ if (this.getCurrentToken() !== ',') {
+ throw new Error(`Expected ',' between arguments for function ${functionName}`);
+ }
+ this.getNextToken(); // consume ','
+ const argument2 = this.parseExpression();
+ if (this.getCurrentToken() !== ')') {
+ throw new Error(`Expected ')' after arguments for function ${functionName}`);
+ }
+ this.getNextToken(); // consume ')'
+ return Math.pow(argument1, argument2);
+ }
+
+ if (this.getCurrentToken() !== ')') {
+ throw new Error(`Expected ')' after argument for function ${functionName}`);
+ }
+ this.getNextToken(); // consume ')'
+
+ switch (functionName) {
+ case 'sin':
+ return Math.sin(argument1);
+ case 'cos':
+ return Math.cos(argument1);
+ case 'tan':
+ return Math.tan(argument1);
+ case 'ln':
+ return Math.log(argument1);
+ case 'sqrt':
+ return Math.sqrt(argument1);
+ case 'log2':
+ return Math.log2(argument1);
+ case 'log10':
+ return Math.log10(argument1);
+ default:
+ throw new Error(`Unknown function: ${functionName}`);
+ }
+ }
+
+ private parseFactor(): number {
+ // 处理一元负号
+ if (this.getCurrentToken() === '-') {
+ this.getNextToken(); // consume '-'
+ return -this.parseFactor();
+ }
+ // 处理初级表达式
+ let result = this.parsePrimaryExpression();
+ // 处理乘法和除法
+ while (this.getCurrentToken() === '*' || this.getCurrentToken() === '/') {
+ const operator = this.getCurrentToken();
+ this.getNextToken(); // consume operator
+ const operand = this.parsePrimaryExpression();
+ if (operator === '*') {
+ result *= operand;
+ } else if (operator === '/') {
+ if (operand === 0) {
+ throw new Error("Division by zero");
+ }
+ result /= operand;
+ }
+ }
+ return result;
+ }
+
+ private parseExpression(): number {
+ let result = this.parseFactor();
+ while (this.getCurrentToken() === '+' || this.getCurrentToken() === '-') {
+ const operator = this.getCurrentToken();
+ this.getNextToken();
+ const operand = this.parseFactor();
+ if (operator === '+') {
+ result += operand;
+ } else if (operator === '-') {
+ result -= operand;
+ }
+ }
+ return result;
+ }
+
+ public evaluate(expression: string, variables: replaceableVar[] = []): number {
+ this.tokens = this.tokenize(expression);
+ this.currentTokenIndex = 0;
+ this.variables = variables;
+
+ const result = this.parseExpression();
+ if (this.currentTokenIndex !== this.tokens.length) {
+ console.log("Token:" + this.tokens);
+ console.log("当前index:" + this.currentTokenIndex + " " + "当前length:" + this.tokens.length);
+ throw new Error("Unexpected token");
+ }
+ return Number(result.toFixed(4));
+ }
+
+ private getCurrentChar(): string {
+ return this.exp[this.currentExpIndex];
+ }
+
+ private getNextChar(): string {
+ this.currentExpIndex++;
+ return this.getCurrentChar();
+ }
+
+ private recursivePartitioning(expression: string) {
+ this.exp = "";
+ this.tokens = [];
+ this.tokens = this.tokenize(expression);
+ for (let i = 0; i < this.tokens.length; i++) {
+ this.exp += this.tokens[i];
+ }
+ console.log(this.exp + "----" + this.layer)
+ let temp: RegExp = new RegExp("^\\-?[a-zA-Z0-9]+$");
+ if (temp.test(this.exp)) return;
+ this.currentExpIndex = 0;
+ let parenthesizedForms: Array = [];
+ let leftIndex: number = 0;
+ let rightIndex: number = 0;
+ let char: string = "$";
+ while (this.currentExpIndex < this.exp.length) {
+ if (this.getCurrentChar() == '(') {
+ parenthesizedForms.push("");
+ let count: number = parenthesizedForms.length - 1;
+ let leftCount: number = 1;
+ let rightCount: number = 0;
+ this.getNextChar();
+ leftIndex = this.currentExpIndex;
+ let sign: number = 0;
+ while (true) {
+ if (this.getCurrentChar() == '(') leftCount++;
+ if (this.getCurrentChar() == ')') rightCount++;
+ if (leftCount == rightCount) {
+ rightIndex = this.currentExpIndex;
+ break;
+ }
+ parenthesizedForms[count] += this.getCurrentChar();
+ this.getNextChar();
+ sign++;
+ if (sign > 1000) {
+ console.log("leftCount: " + leftCount + " " + "rightCount: " + rightCount);
+ this.exp = "";
+ this.tokens = [];
+ this.nodeTree = [];
+ this.layer = 0;
+ this.currentExpIndex = 0;
+ throw new Error("The number of brackets does not match");
+ }
+ }
+ let repeatNum: number = parenthesizedForms[count].length - count.toString().length;
+ if (repeatNum >= 0) {
+ this.exp = this.exp.substring(0, leftIndex) + count.toString() + char.repeat(repeatNum) + this.exp.substring(rightIndex);
+ } else {
+ throw new Error("Functions with so many parentheses are not supported");
+ }
+ leftIndex = rightIndex = 0;
+ }
+ this.getNextChar();
+ }
+ let nail: number = this.nodeTree[this.layer].length;
+ let symbolParts: RegExpMatchArray | null = null;
+ let includesAS: RegExp = new RegExp("(?<=\\d|[a-zA-Z]|\\))[+-](?=\\d|[a-zA-Z]|\\()", "g");
+ let includesMD: RegExp = new RegExp("(?<=\\d|[a-zA-Z]|\\))[*/](?=\\d|[a-zA-Z]|\\()", "g");
+ let includesPow: RegExp = new RegExp("(?<=\\d|[a-zA-Z]|\\))(?:[*]{2}|[\\^])(?=\\d|[a-zA-Z]|\\()", "g");
+ if (includesAS.test(this.exp)) {
+ this.nodeTree[this.layer] = this.nodeTree[this.layer].concat(this.exp.split(includesAS));
+ symbolParts = this.exp.match(includesAS);
+ } else if (includesMD.test(this.exp)) {
+ this.nodeTree[this.layer] = this.nodeTree[this.layer].concat(this.exp.split(includesMD));
+ } else if (includesPow.test(this.exp)) {
+ this.nodeTree[this.layer] = this.nodeTree[this.layer].concat(this.exp.split(includesPow));
+ } else {
+ if (this.exp[0] != "(") {
+ let label = 0;
+ for (let i = 0; i < this.exp.length; i++) {
+ if (this.exp[i] == "(") {
+ label = i;
+ break;
+ }
+ }
+ this.exp = this.exp.substring(label);
+ }
+ this.nodeTree[this.layer].push(this.exp);
+ }
+
+ if (symbolParts) {
+ symbolParts.forEach((match, index) => {
+ if (match == "-") {
+ this.nodeTree[this.layer][index + 1] = "-".concat(this.nodeTree[this.layer][index + 1]);
+ }
+ })
+ }
+
+ // for (let i = nail; i < this.nodeTree[this.layer].length; i++) {
+ // console.log(this.nodeTree[this.layer][i]);
+ // }
+
+ // for (let i: number = 0; i < parenthesizedForms.length; i++) {
+ // console.log("需替换字符" + parenthesizedForms[i] + ":" + i + " " + this.layer)
+ // }
+
+ for (let i = nail; i < this.nodeTree[this.layer].length; i++) {
+ for (let j = 0; j < this.nodeTree[this.layer][i].length; j++) {
+ if (this.nodeTree[this.layer][i][j] == "(") {
+ let standard: RegExp = new RegExp("(?<=\\d|[a-zA-Z]|\\))([+-]|[*/]|[*]{2}|[\\^])(?=\\d|[a-zA-Z]|\\()", "g");
+ let flag: Boolean = false;
+ if (j == 0 && !standard.test(this.nodeTree[this.layer][i])) {
+ flag = true;
+ }
+ let start = j + 1;
+ let storeIndex = Number(this.nodeTree[this.layer][i][start]);
+ this.nodeTree[this.layer][i] = this.nodeTree[this.layer][i].substring(0, start) + parenthesizedForms[storeIndex] + this.nodeTree[this.layer][i].substring(start + parenthesizedForms[storeIndex].length);
+ if (flag) this.nodeTree[this.layer][i] = this.nodeTree[this.layer][i].substring(1, this.nodeTree[this.layer][i].length - 1);
+ // break;
+ j += parenthesizedForms[storeIndex].length + 2;
+ }
+ }
+ }
+
+ // for (let i = nail; i < this.nodeTree[this.layer].length; i++) {
+ // console.log(this.layer + " " + this.nodeTree[this.layer][i]);
+ // }
+
+ for (let i = nail; i < this.nodeTree[this.layer].length; i++) {
+ this.layer++;
+ this.recursivePartitioning(this.nodeTree[this.layer - 1][i]);
+ this.layer--;
+ }
+ }
+
+ createNode(func: string) {
+ // this.nodeTree.length = 0;
+ // this.nodeTree = new Array(50).fill([]);
+ this.nodeTree = [];
+ for (let i = 0; i < 50; i++) {
+ this.nodeTree.push([]);
+ }
+ this.recursivePartitioning(func);
+ return this.nodeTree;
+ }
+}
+
+export let mathjs: MathExpressionParser = new MathExpressionParser();
diff --git a/drawing/draw/entry/src/main/ets/utils/handleFunc/processFunc.ets b/drawing/draw/entry/src/main/ets/utils/handleFunc/processFunc.ets
new file mode 100644
index 0000000..987fbe2
--- /dev/null
+++ b/drawing/draw/entry/src/main/ets/utils/handleFunc/processFunc.ets
@@ -0,0 +1,399 @@
+import promptAction from '@ohos.promptAction';
+import { BusinessError } from '@ohos.base';
+import { mathjs } from '../handleFunc/analysis'
+import { PointType, IPoint, FuncType } from '../drawBoard/drawPoint'
+import { Dimension } from '../drawBoard/BoardType'
+
+export class ProcessFunc {
+ private funcId: string; // 函数(用以查询坐标轴进而确定函数类型)
+ private funcText: string; // 函数体(经过一定符号转换处理,用以计算)
+ xMin: number; // x轴最小整数值
+ xMax: number; // y轴最大整数值
+ private yMin: number; // x轴最小整数值
+ private yMax: number; // y轴最大整数值
+ private xMinDefault: number;
+ private xMaxDefault: number;
+ private yMinDefault: number;
+ private yMaxDefault: number;
+
+ nodeTree: Array> // 节点树数组
+ coPot: Array; // 存储获取的坐标点
+ funcHead: string; // 存储函数头
+ funcBody: string; // 存储函数体
+ xCount: number; // 取x点个数
+ yCount: number; // 取y点个数
+ xStep: number; // x轴步长值,决定每个点取点间隔
+ yStep: number; // y轴步长值,决定每个点取点间隔
+ row: number; // 三维取点点集转为二维数组的行数
+ col: number; // 三维取点点集转为二维数组的列数
+
+ constructor() {
+ this.nodeTree = [];
+ this.coPot = [];
+ this.funcId = this.funcText = this.funcHead = this.funcBody = "";
+ this.xStep = this.yStep = 0.1;
+ this.xCount = this.yCount = 0;
+ this.xMin = this.xMax = this.yMin = this.yMax = 0;
+ this.xMinDefault = this.xMaxDefault = this.yMinDefault = this.yMaxDefault = 0;
+ this.row = this.col = 0;
+ }
+
+ /**
+ * 对promptAction.showToast()的封装。默认持续1.5s,距离底部50vp
+ * @param message 弹窗提示的文本信息
+ */
+ private showToast(message: string) {
+ try {
+ promptAction.showToast({
+ message: message,
+ duration: 1500,
+ bottom: 20
+ });
+ } catch (error) {
+ let message = (error as BusinessError).message
+ let code = (error as BusinessError).code
+ console.error(`showToast args error code is ${code}, message is ${message}`);
+ }
+ }
+
+ /**
+ * 初始化默认的坐标轴最大最小边界点
+ * @param xMin
+ * @param xMax
+ * @param yMin
+ * @param yMax
+ */
+ setEdge(xMin: number, xMax: number, y?: number, ) {
+ this.xMinDefault = xMin;
+ this.xMaxDefault = xMax;
+ if (y) {
+ this.yMinDefault = -y;
+ this.yMaxDefault = y;
+ }
+ this.updateEdge(1);
+ }
+
+ /**
+ * 根据放大倍数更新边缘点
+ * @param xTimes
+ * @param yTimes
+ */
+ updateEdge(xTimes: number, yTimes?: number) {
+ this.xMin = this.xMinDefault * xTimes;
+ this.xMax = this.xMaxDefault * xTimes;
+ if (yTimes) {
+ this.yMin = this.yMinDefault * yTimes;
+ this.yMax = this.yMaxDefault * yTimes;
+ }
+ }
+
+ /**
+ * 判断输入的数学表达式是否合法,能够运算则合法,抛出错误则不合法
+ * @param func 数学表达式
+ * @returns
+ */
+ isValidFunc(func: string): boolean {
+ this.funcId = this.funcText = "";
+ let temp: RegExp = new RegExp("\\s+", "g");
+ func = func.trim().replace(temp, "");
+ // temp = new RegExp("(\\(([^()]+)\\)|\\w+)(?:\\*\\*|\\^)(\\(([^()]+)\\)|\\w+)", "g");
+ temp = new RegExp("(\\([^()]*?(?:\\([^()]*?\\)[^()]*?)*\\)|\\w+)(?:\\*\\*|\\^)(\\([^()]*?(?:\\([^()]*?\\)[^()]*?)*\\)|\\w+)", "g");
+ func = func.replace(temp, "pow($1, $2)");
+ if (func.includes("=") && func.split("=").length === 2) {
+ this.funcId = func.split("=")[0];
+ this.funcText = func.split("=")[1];
+ } else {
+ this.funcId = "";
+ this.funcText = func;
+ }
+
+ try {
+ let testX: number = 1;
+ let testY: number = 1;
+ let uselessRes: number = mathjs.evaluate(this.funcText, [{ char: "x", value: testX }, { char: "y", value: testY }]);
+ if (!Number.isNaN(uselessRes)) return true;
+ else return false;
+ } catch (err) {
+ console.log("错误的函数格式为:" + this.funcText)
+ this.showToast("函数错误!" + err);
+ return false;
+ }
+ }
+
+ /**
+ * 分离函数头和函数体
+ * @param func
+ */
+ separateFunc(func: string) {
+ this.funcHead = this.funcBody = "";
+ let temp: RegExp = new RegExp("\\s+", "g");
+ func = func.trim().replace(temp, "");
+ if (func.includes("=") && func.split("=").length === 2) {
+ this.funcHead = func.split("=")[0];
+ this.funcBody = func.split("=")[1];
+ } else {
+ this.funcHead = "";
+ this.funcBody = func;
+ }
+ }
+
+ /**
+ * 获取函数类型
+ * @param dimension 当前的维度
+ * @returns
+ */
+ getFuncType(dimension: Dimension): FuncType {
+ if (dimension === Dimension.TWO) {
+ if (!this.funcId) {
+ if (Number.isNaN(Number(this.funcText))) return FuncType.YX;
+ else this.showToast("请输入正确的函数格式");
+ }
+ if (this.funcId && this.funcId != "x") {
+ if (Number.isNaN(Number(this.funcText))) return FuncType.YX;
+ else return FuncType.YC;
+ }
+ else if (!Number.isNaN(Number(this.funcText))) return FuncType.XC;
+ else this.showToast("函数命名不可以与自变量同名!");
+ } else if (dimension === Dimension.THREE) {
+ let standard_x: RegExp = new RegExp("(^|[^a-zA-Z])x($|[^a-zA-Z])");
+ let standard_y: RegExp = new RegExp("(^|[^a-zA-Z])y($|[^a-zA-Z])");
+ if (!this.funcId) {
+ if (standard_x.test(this.funcText) && standard_y.test(this.funcText)) return FuncType.ZXY;
+ else if (standard_x.test(this.funcText) && !standard_y.test(this.funcText)) return FuncType.ZX;
+ else if (!standard_x.test(this.funcText) && standard_y.test(this.funcText)) return FuncType.ZY;
+ else this.showToast("请输入正确的函数格式");
+ }
+ if (this.funcId && this.funcId != "x" && this.funcId != "y") {
+ if (!Number.isNaN(Number(this.funcText))) return FuncType.ZC;
+ else if (standard_x.test(this.funcText) && standard_y.test(this.funcText)) return FuncType.ZXY;
+ else if (standard_x.test(this.funcText) && !standard_y.test(this.funcText)) return FuncType.ZX;
+ else if (!standard_x.test(this.funcText) && standard_y.test(this.funcText)) return FuncType.ZY;
+ }
+ else if (this.funcId == "x" && !Number.isNaN(Number(this.funcText))) return FuncType.XC;
+ else if (this.funcId == "y" && !Number.isNaN(Number(this.funcText))) return FuncType.YC;
+ else this.showToast("没有YX或XY类型函数||函数命名不可与自变量同名!");
+ }
+ return FuncType.NONE;
+ }
+
+ /**
+ * 判断当前点是否连续
+ * @param xValue 当前x值
+ * @param yValue 当前y值
+ * @param zValue 当前z值
+ * @param epsilon 模拟的逼近无限小值
+ * @param threshold 模拟的逼近无限大值
+ * @returns 返回一个布尔值,true则表示此点连续,false表示不连续
+ */
+ private judgeContinue(xValue: number, yValue: number, zValue?: number, epsilon: number = 1e-10, threshold: number = 1e5): boolean {
+ if (Number.isNaN(yValue) || Number.isNaN(zValue)) {
+ return false;
+ }
+ let leftLimitX: number = 0;
+ let rightLimitX: number = 0;
+ let leftLimitY: number = 0;
+ let rightLimitY: number = 0;
+ let standard: RegExp = new RegExp("(^|[^a-zA-Z])y($|[^a-zA-Z])")
+ try {
+ if (!standard.test(this.funcText)) {
+ leftLimitX = mathjs.evaluate(this.funcText, [{ char: "x", value: xValue - epsilon }]);
+ rightLimitX = mathjs.evaluate(this.funcText, [{ char: "x", value: xValue + epsilon }]);
+ if (Math.abs(rightLimitX - leftLimitX) > 10 * epsilon) {
+ return false;
+ }
+ if (Math.abs(leftLimitX - yValue) > 10 * epsilon || Math.abs(rightLimitX - yValue) > 10 * epsilon) {
+ return false;
+ }
+ } else {
+ leftLimitX = mathjs.evaluate(this.funcText, [{ char: "x", value: xValue - epsilon }, { char: "y", value: yValue }]);
+ rightLimitX = mathjs.evaluate(this.funcText, [{ char: "x", value: xValue + epsilon }, { char: "y", value: yValue }]);
+ leftLimitX = mathjs.evaluate(this.funcText, [{ char: "x", value: xValue }, { char: "y", value: yValue - epsilon }]);
+ rightLimitX = mathjs.evaluate(this.funcText, [{ char: "x", value: xValue }, { char: "y", value: yValue + epsilon }]);
+ if (Math.abs(rightLimitX - leftLimitX) > 10 * epsilon && Math.abs(rightLimitY - leftLimitY) > 10 * epsilon) {
+ return false;
+ }
+ if ((Math.abs(leftLimitX - zValue!) > 10 * epsilon || Math.abs(rightLimitX - zValue!) > 10 * epsilon) && (Math.abs(leftLimitY - zValue!) > 10 * epsilon || Math.abs(rightLimitY - zValue!) > 10 * epsilon)) {
+ return false;
+ }
+ }
+ const isLeftInfinite: boolean = Math.abs(leftLimitX) > threshold || Math.abs(leftLimitY) > threshold;
+ const isRightInfinite: boolean = Math.abs(rightLimitX) > threshold || Math.abs(rightLimitY) > threshold;
+ if (isLeftInfinite || isRightInfinite) {
+ return false;
+ }
+ } catch {
+ this.showToast("判断是否为间断点时发生错误,默认此点非连续");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 一元函数获取点的方法封装
+ * @param independentVar 自变量
+ * @param dependentVar 因变量
+ * @param min 负轴坐标最大值
+ * @param max 正轴坐标最大值
+ * @param step 步长值
+ * @param count 个数
+ */
+ private getPointsBasic(independentVar: string, dependentVar: string, min: number, max: number, step: number, count?: number) {
+ let _temp: number = Math.abs(max - min) / step;
+ if (_temp <= 10000) {
+ for (let argument: number = min; argument <= max && step > 0; argument += step) {
+ argument = Number(argument.toFixed(4));
+ let standard: RegExp = new RegExp(`(^|[^a-zA-Z])${independentVar}($|[^a-zA-Z])`)
+ let calculateRes: number = 0;
+ if (standard.test(this.funcText)) {
+ try {
+ calculateRes = mathjs.evaluate(this.funcText, [{ char: independentVar, value: argument }]);
+ } catch {
+ this.coPot.length = 0;
+ this.showToast("运算过程中出错");
+ return;
+ }
+ }
+ if (this.judgeContinue(argument, calculateRes)) {
+ // this.coPot.push({ [independentVar]: argument, [dependentVar]: calculateRes, pointType: PointType.CONTINUE });
+ this.coPot.push({ pointType: PointType.CONTINUE });
+ let index: number = this.coPot.length - 1;
+ if (independentVar == "x") this.coPot[index].x = argument;
+ else if (independentVar == "y") this.coPot[index].y = argument;
+ if (dependentVar == "y") this.coPot[index].y = calculateRes;
+ else if (dependentVar == "z") this.coPot[index].z = calculateRes;
+ } else {
+ // this.coPot.push({ [independentVar]: argument, pointType: PointType.DISCONTINUE })
+ this.coPot.push({ pointType: PointType.DISCONTINUE });
+ let index: number = this.coPot.length - 1;
+ if (independentVar == "x") this.coPot[index].x = argument;
+ else if (independentVar == "y") this.coPot[index].y = argument;
+ }
+ if (argument != max && argument + step > max) {
+ argument = max - step;
+ }
+ }
+ if (count && count > 0 && count < this.coPot.length) {
+ this.coPot = this.coPot.slice(0, count);
+ }
+ } else {
+ this.coPot.push({ x: 0, y: 0, pointType: PointType.CONTINUE });
+ this.coPot.length = 1;
+ this.showToast("请适当增大步长");
+ }
+
+ }
+
+ /**
+ * 获取用于绘制2维图像的各个坐标点
+ * @returns 返回坐标点信息数组
+ */
+ getPoints2D(): IPoint[] {
+ this.coPot.length = 0;
+ if (this.getFuncType(Dimension.TWO) == FuncType.YX) {
+ this.getPointsBasic("x", "y", this.xMin, this.xMax, this.xStep, this.xCount);
+ } else if (this.getFuncType(Dimension.TWO) == FuncType.YC) {
+ this.coPot.push({ y: Number(this.funcText), pointType: PointType.CONTINUE })
+ } else if (this.getFuncType(Dimension.TWO) == FuncType.XC) {
+ this.coPot.push({ x: Number(this.funcText), pointType: PointType.CONTINUE })
+ }
+ return this.coPot;
+ }
+
+ /**
+ * 获取用于绘制3维图像的各个坐标点
+ * @returns 返回坐标点信息数组
+ */
+ getPoints3D(): IPoint[] {
+ this.coPot.length = 0;
+ if (this.getFuncType(Dimension.THREE) == FuncType.ZXY) {
+ let _temp: number = (Math.abs(this.yMax - this.yMin) / this.yStep) * (Math.abs(this.xMax - this.xMin) / this.xStep);
+ if (_temp <= 10000) {
+ for (let x: number = this.xMin; x <= this.xMax && this.xStep > 0; x += this.xStep) {
+ for (let y: number = this.yMin; y <= this.yMax && this.yStep > 0; y += this.yStep) {
+ x = Number(x.toFixed(4));
+ y = Number(y.toFixed(4));
+ let standard: RegExp = new RegExp("(^|[^a-zA-Z])(?:x|y)($|[^a-zA-Z])")
+ let z: number = 0;
+ if (standard.test(this.funcText)) {
+ try {
+ z = mathjs.evaluate(this.funcText, [{ char: "x", value: x }, { char: "y", value: y }]);
+ } catch {
+ this.coPot.length = 0;
+ this.showToast("运算过程中出错");
+ return [];
+ }
+ }
+ if (this.judgeContinue(x, y)) {
+ this.coPot.push({ x: x, y: y, z: z, pointType: PointType.CONTINUE });
+ } else {
+ this.coPot.push({ x: x, y: y, pointType: PointType.DISCONTINUE })
+ }
+ if (y != this.yMax && y + this.yStep >= this.yMax) {
+ let temp: number = y + this.yStep + (-this.yMin);
+ this.col = Number((temp / this.yStep).toFixed(0)) + 1;
+ y = this.yMax - this.yStep;
+ }
+ }
+ if (x != this.xMax && x + this.xStep >= this.xMax) {
+ let temp: number = x + this.xStep + (-this.xMin);
+ this.row = Number((temp / this.xStep).toFixed(0)) + 1;
+ x = this.xMax - this.xStep;
+ }
+ }
+ } else {
+ this.coPot.push({ x: 0, y: 0, pointType: PointType.CONTINUE });
+ this.coPot.length = 1;
+ this.showToast("请适当增大步长");
+ }
+ // let row: number = Math.abs(this.xMax - this.xMin) / this.xStep;
+ // let col: number = Math.abs(this.yMax - this.yMin) / this.yStep;
+ // let temp: IPoint[] = [];
+ // if (this.xCount > 0 && this.yCount > 0 && this.xCount < row && this.yCount < col) {
+ // for (let i: number = 0; i < this.xCount * col; i += col) {
+ // temp = temp.concat(this.coPot.slice(i, i + this.yCount));
+ // }
+ // this.coPot = temp;
+ // } else if (this.xCount > 0 && this.xCount < row) {
+ // this.coPot = this.coPot.slice(0, this.xCount * col);
+ // } else if (this.yCount > 0 && this.xCount < col) {
+ // for (let i: number = 0; i < this.coPot.length; i += col) {
+ // temp = temp.concat(this.coPot.slice(i, i + this.yCount));
+ // }
+ // this.coPot = temp;
+ // }
+ } else if (this.getFuncType(Dimension.THREE) == FuncType.ZX) {
+ this.getPointsBasic("x", "z", this.xMin, this.xMax, this.xStep);
+ } else if (this.getFuncType(Dimension.THREE) == FuncType.ZY) {
+ this.getPointsBasic("y", "z", this.yMin, this.yMax, this.yStep);
+ } else if (this.getFuncType(Dimension.THREE) == FuncType.ZC) {
+ this.coPot.push({ z: Number(this.funcText), pointType: PointType.CONTINUE });
+ } else if (this.getFuncType(Dimension.THREE) == FuncType.XC) {
+ this.coPot.push({ x: Number(this.funcText), pointType: PointType.CONTINUE });
+ } else if (this.getFuncType(Dimension.THREE) == FuncType.YC) {
+ this.coPot.push({ y: Number(this.funcText), pointType: PointType.CONTINUE });
+ }
+ return this.coPot;
+ }
+
+ createNodeTree(func: string) {
+ this.separateFunc(func);
+ this.nodeTree = [];
+ if (this.isValidFunc(func)) {
+ let temp: RegExp = new RegExp("\\s+", "g");
+ let machiningFunc: string = this.funcBody;
+ machiningFunc = machiningFunc.trim().replace(temp, "");
+ this.nodeTree.push([machiningFunc]);
+ let leaf: Array> = mathjs.createNode(machiningFunc);
+ for (let i: number = 0; i < leaf.length; i++) {
+ if (leaf[i][0]) this.nodeTree.push([]);
+ else break;
+ for (let j: number = 0; j < leaf[i].length; j++) {
+ this.nodeTree[i + 1].push(leaf[i][j]);
+ }
+ }
+ }
+ return this.nodeTree;
+ }
+}
+
+export let handle: ProcessFunc = new ProcessFunc();
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/module.json5 b/drawing/draw/entry/src/main/module.json5
new file mode 100644
index 0000000..0f91820
--- /dev/null
+++ b/drawing/draw/entry/src/main/module.json5
@@ -0,0 +1,44 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "metadata": [
+ {
+ "name": "ArkTSPartialUpdate",
+ "value": "true"
+ }
+ ],
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "orientation": "landscape",
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/resources/base/element/color.json b/drawing/draw/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/drawing/draw/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/resources/base/element/string.json b/drawing/draw/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000..f945955
--- /dev/null
+++ b/drawing/draw/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/resources/base/media/icon.png b/drawing/draw/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/drawing/draw/entry/src/main/resources/base/media/icon.png differ
diff --git a/drawing/draw/entry/src/main/resources/base/media/startIcon.png b/drawing/draw/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000..366f764
Binary files /dev/null and b/drawing/draw/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/drawing/draw/entry/src/main/resources/base/profile/main_pages.json b/drawing/draw/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000..55c3f00
--- /dev/null
+++ b/drawing/draw/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/resources/en_US/element/string.json b/drawing/draw/entry/src/main/resources/en_US/element/string.json
new file mode 100644
index 0000000..f945955
--- /dev/null
+++ b/drawing/draw/entry/src/main/resources/en_US/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/main/resources/zh_CN/element/string.json b/drawing/draw/entry/src/main/resources/zh_CN/element/string.json
new file mode 100644
index 0000000..597ecf9
--- /dev/null
+++ b/drawing/draw/entry/src/main/resources/zh_CN/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "模块描述"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/ohosTest/ets/test/Ability.test.ets b/drawing/draw/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000..8aa3749
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,35 @@
+import hilog from '@ohos.hilog';
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function abilityTest() {
+ describe('ActsAbilityTest', () => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ })
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ })
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ })
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ })
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ })
+ })
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/ohosTest/ets/test/List.test.ets b/drawing/draw/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000..794c7dc
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/ohosTest/ets/testability/TestAbility.ets b/drawing/draw/entry/src/ohosTest/ets/testability/TestAbility.ets
new file mode 100644
index 0000000..9484761
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/ets/testability/TestAbility.ets
@@ -0,0 +1,50 @@
+import UIAbility from '@ohos.app.ability.UIAbility';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import hilog from '@ohos.hilog';
+import { Hypium } from '@ohos/hypium';
+import testsuite from '../test/List.test';
+import window from '@ohos.window';
+import Want from '@ohos.app.ability.Want';
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+
+export default class TestAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
+ let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator;
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs;
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
+ hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
+ }
+
+ onDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
+ windowStage.loadContent('testability/pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
+ JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
+ }
+
+ onForeground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
+ }
+
+ onBackground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
+ }
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/ohosTest/ets/testability/pages/Index.ets b/drawing/draw/entry/src/ohosTest/ets/testability/pages/Index.ets
new file mode 100644
index 0000000..423b427
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/ets/testability/pages/Index.ets
@@ -0,0 +1,17 @@
+@Entry
+@Component
+struct Index {
+ @State message: string = 'Hello World';
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/drawing/draw/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
new file mode 100644
index 0000000..917d27a
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
@@ -0,0 +1,47 @@
+import hilog from '@ohos.hilog';
+import TestRunner from '@ohos.application.testRunner';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import Want from '@ohos.app.ability.Want';
+
+let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined
+let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined
+
+async function onAbilityCreateCallback() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
+}
+
+async function addAbilityMonitorCallback(err : Error) {
+ hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
+ }
+
+ async onRun() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ const bundleName = abilityDelegatorArguments.bundleName;
+ const testAbilityName = 'TestAbility';
+ let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ const want: Want = {
+ bundleName: bundleName,
+ abilityName: testAbilityName
+ };
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ abilityDelegator.startAbility(want, (err, data) => {
+ hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
+ hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? '');
+ })
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
+ }
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/ohosTest/module.json5 b/drawing/draw/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000..4fc9701
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "description": "$string:module_test_desc",
+ "mainElement": "TestAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:test_pages",
+ "abilities": [
+ {
+ "name": "TestAbility",
+ "srcEntry": "./ets/testability/TestAbility.ets",
+ "description": "$string:TestAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:TestAbility_label",
+ "exported": true,
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "skills": [
+ {
+ "actions": [
+ "action.system.home"
+ ],
+ "entities": [
+ "entity.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/drawing/draw/entry/src/ohosTest/resources/base/element/color.json b/drawing/draw/entry/src/ohosTest/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/ohosTest/resources/base/element/string.json b/drawing/draw/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000..65d8fa5
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_test_desc",
+ "value": "test ability description"
+ },
+ {
+ "name": "TestAbility_desc",
+ "value": "the test ability"
+ },
+ {
+ "name": "TestAbility_label",
+ "value": "test label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/ohosTest/resources/base/media/icon.png b/drawing/draw/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000..ce307a8
Binary files /dev/null and b/drawing/draw/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/drawing/draw/entry/src/ohosTest/resources/base/profile/test_pages.json b/drawing/draw/entry/src/ohosTest/resources/base/profile/test_pages.json
new file mode 100644
index 0000000..b7e7343
--- /dev/null
+++ b/drawing/draw/entry/src/ohosTest/resources/base/profile/test_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "testability/pages/Index"
+ ]
+}
diff --git a/drawing/draw/entry/src/test/List.test.ets b/drawing/draw/entry/src/test/List.test.ets
new file mode 100644
index 0000000..bb5b5c3
--- /dev/null
+++ b/drawing/draw/entry/src/test/List.test.ets
@@ -0,0 +1,5 @@
+import localUnitTest from './LocalUnit.test';
+
+export default function testsuite() {
+ localUnitTest();
+}
\ No newline at end of file
diff --git a/drawing/draw/entry/src/test/LocalUnit.test.ets b/drawing/draw/entry/src/test/LocalUnit.test.ets
new file mode 100644
index 0000000..ed22d4d
--- /dev/null
+++ b/drawing/draw/entry/src/test/LocalUnit.test.ets
@@ -0,0 +1,33 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function localUnitTest() {
+ describe('localUnitTest',() => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ });
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ });
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ });
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ });
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ });
+ });
+}
\ No newline at end of file
diff --git a/drawing/draw/hvigor/hvigor-config.json5 b/drawing/draw/hvigor/hvigor-config.json5
new file mode 100644
index 0000000..1a47490
--- /dev/null
+++ b/drawing/draw/hvigor/hvigor-config.json5
@@ -0,0 +1,18 @@
+{
+ "hvigorVersion": "3.0.9",
+ "dependencies": {
+ "@ohos/hvigor-ohos-plugin": "3.0.9"
+ },
+ "execution": {
+ // "daemon": true, /* Enable daemon compilation. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Default: false */
+ }
+}
diff --git a/drawing/draw/hvigor/hvigor-wrapper.js b/drawing/draw/hvigor/hvigor-wrapper.js
new file mode 100644
index 0000000..372eae8
--- /dev/null
+++ b/drawing/draw/hvigor/hvigor-wrapper.js
@@ -0,0 +1 @@
+"use strict";var u=require("path"),D=require("os"),e=require("fs"),t=require("crypto"),r=require("child_process"),n="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},i={},C={},F=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(C,"__esModule",{value:!0}),C.maxPathLength=C.isMac=C.isLinux=C.isWindows=void 0;const E=F(D),A="Windows_NT",o="Darwin";function a(){return E.default.type()===A}function c(){return E.default.type()===o}C.isWindows=a,C.isLinux=function(){return"Linux"===E.default.type()},C.isMac=c,C.maxPathLength=function(){return c()?1016:a()?259:4095},function(e){var t=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),r=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),i=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&t(D,u,e);return r(D,u),D};Object.defineProperty(e,"__esModule",{value:!0}),e.WORK_SPACE=e.HVIGOR_PROJECT_WRAPPER_HOME=e.HVIGOR_PROJECT_ROOT_DIR=e.HVIGOR_PROJECT_CACHES_HOME=e.HVIGOR_PNPM_STORE_PATH=e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=e.PROJECT_CACHES=e.HVIGOR_WRAPPER_TOOLS_HOME=e.HVIGOR_USER_HOME=e.DEFAULT_PACKAGE_JSON=e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME=e.PNPM=e.HVIGOR=e.NPM_TOOL=e.PNPM_TOOL=e.HVIGOR_ENGINE_PACKAGE_NAME=void 0;const F=i(D),E=i(u),A=C;e.HVIGOR_ENGINE_PACKAGE_NAME="@ohos/hvigor",e.PNPM_TOOL=(0,A.isWindows)()?"pnpm.cmd":"pnpm",e.NPM_TOOL=(0,A.isWindows)()?"npm.cmd":"npm",e.HVIGOR="hvigor",e.PNPM="pnpm",e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME="hvigor-config.json5",e.DEFAULT_PACKAGE_JSON="package.json",e.HVIGOR_USER_HOME=E.resolve(F.homedir(),".hvigor"),e.HVIGOR_WRAPPER_TOOLS_HOME=E.resolve(e.HVIGOR_USER_HOME,"wrapper","tools"),e.PROJECT_CACHES="project_caches",e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=E.resolve(e.HVIGOR_WRAPPER_TOOLS_HOME,"node_modules",".bin",e.PNPM_TOOL),e.HVIGOR_PNPM_STORE_PATH=E.resolve(e.HVIGOR_USER_HOME,"caches"),e.HVIGOR_PROJECT_CACHES_HOME=E.resolve(e.HVIGOR_USER_HOME,e.PROJECT_CACHES),e.HVIGOR_PROJECT_ROOT_DIR=process.cwd(),e.HVIGOR_PROJECT_WRAPPER_HOME=E.resolve(e.HVIGOR_PROJECT_ROOT_DIR,e.HVIGOR),e.WORK_SPACE="workspace"}(i);var s={},l={};Object.defineProperty(l,"__esModule",{value:!0}),l.logInfoPrintConsole=l.logErrorAndExit=void 0,l.logErrorAndExit=function(u){u instanceof Error?console.error(u.message):console.error(u),process.exit(-1)},l.logInfoPrintConsole=function(u){console.log(u)};var B=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),d=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),f=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&B(D,u,e);return d(D,u),D};Object.defineProperty(s,"__esModule",{value:!0});var _=s.executeBuild=void 0;const p=f(e),O=f(u),h=l;_=s.executeBuild=function(u){const D=O.resolve(u,"node_modules","@ohos","hvigor","bin","hvigor.js");try{const u=p.realpathSync(D);require(u)}catch(e){(0,h.logErrorAndExit)(`Error: ENOENT: no such file ${D},delete ${u} and retry.`)}};var P={},v={};!function(u){var D=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(u,"__esModule",{value:!0}),u.hashFile=u.hash=u.createHash=void 0;const r=D(t),i=D(e);u.createHash=(u="MD5")=>r.default.createHash(u);u.hash=(D,e)=>(0,u.createHash)(e).update(D).digest("hex");u.hashFile=(D,e)=>{if(i.default.existsSync(D))return(0,u.hash)(i.default.readFileSync(D,"utf-8"),e)}}(v);var g={},m={},R={};Object.defineProperty(R,"__esModule",{value:!0}),R.Unicode=void 0;class y{}R.Unicode=y,y.SPACE_SEPARATOR=/[\u1680\u2000-\u200A\u202F\u205F\u3000]/,y.ID_START=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/,y.ID_CONTINUE=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/,Object.defineProperty(m,"__esModule",{value:!0}),m.JudgeUtil=void 0;const I=R;m.JudgeUtil=class{static isIgnoreChar(u){return"string"==typeof u&&("\t"===u||"\v"===u||"\f"===u||" "===u||" "===u||"\ufeff"===u||"\n"===u||"\r"===u||"\u2028"===u||"\u2029"===u)}static isSpaceSeparator(u){return"string"==typeof u&&I.Unicode.SPACE_SEPARATOR.test(u)}static isIdStartChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||"$"===u||"_"===u||I.Unicode.ID_START.test(u))}static isIdContinueChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||u>="0"&&u<="9"||"$"===u||"_"===u||""===u||""===u||I.Unicode.ID_CONTINUE.test(u))}static isDigitWithoutZero(u){return/[1-9]/.test(u)}static isDigit(u){return"string"==typeof u&&/[0-9]/.test(u)}static isHexDigit(u){return"string"==typeof u&&/[0-9A-Fa-f]/.test(u)}};var N=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(g,"__esModule",{value:!0}),g.parseJsonText=g.parseJsonFile=void 0;const b=N(e),S=N(D),w=N(u),H=m;var x;!function(u){u[u.Char=0]="Char",u[u.EOF=1]="EOF",u[u.Identifier=2]="Identifier"}(x||(x={}));let M,T,V,G,j,J,W="start",U=[],L=0,$=1,k=0,K=!1,z="default",q="'",Z=1;function X(u,D=!1){T=String(u),W="start",U=[],L=0,$=1,k=0,G=void 0,K=D;do{M=Q(),nu[W]()}while("eof"!==M.type);return G}function Q(){for(z="default",j="",q="'",Z=1;;){J=Y();const u=Du[z]();if(u)return u}}function Y(){if(T[L])return String.fromCodePoint(T.codePointAt(L))}function uu(){const u=Y();return"\n"===u?($++,k=0):u?k+=u.length:k++,u&&(L+=u.length),u}g.parseJsonFile=function(u,D=!1,e="utf-8"){const t=b.default.readFileSync(w.default.resolve(u),{encoding:e});try{return X(t,D)}catch(D){if(D instanceof SyntaxError){const e=D.message.split("at");if(2===e.length)throw new Error(`${e[0].trim()}${S.default.EOL}\t at ${u}:${e[1].trim()}`)}throw new Error(`${u} is not in valid JSON/JSON5 format.`)}},g.parseJsonText=X;const Du={default(){switch(J){case"/":return uu(),void(z="comment");case void 0:return uu(),eu("eof")}if(!H.JudgeUtil.isIgnoreChar(J)&&!H.JudgeUtil.isSpaceSeparator(J))return Du[W]();uu()},start(){z="value"},beforePropertyName(){switch(J){case"$":case"_":return j=uu(),void(z="identifierName");case"\\":return uu(),void(z="identifierNameStartEscape");case"}":return eu("punctuator",uu());case'"':case"'":return q=J,uu(),void(z="string")}if(H.JudgeUtil.isIdStartChar(J))return j+=uu(),void(z="identifierName");throw Eu(x.Char,uu())},afterPropertyName(){if(":"===J)return eu("punctuator",uu());throw Eu(x.Char,uu())},beforePropertyValue(){z="value"},afterPropertyValue(){switch(J){case",":case"}":return eu("punctuator",uu())}throw Eu(x.Char,uu())},beforeArrayValue(){if("]"===J)return eu("punctuator",uu());z="value"},afterArrayValue(){switch(J){case",":case"]":return eu("punctuator",uu())}throw Eu(x.Char,uu())},end(){throw Eu(x.Char,uu())},comment(){switch(J){case"*":return uu(),void(z="multiLineComment");case"/":return uu(),void(z="singleLineComment")}throw Eu(x.Char,uu())},multiLineComment(){switch(J){case"*":return uu(),void(z="multiLineCommentAsterisk");case void 0:throw Eu(x.Char,uu())}uu()},multiLineCommentAsterisk(){switch(J){case"*":return void uu();case"/":return uu(),void(z="default");case void 0:throw Eu(x.Char,uu())}uu(),z="multiLineComment"},singleLineComment(){switch(J){case"\n":case"\r":case"\u2028":case"\u2029":return uu(),void(z="default");case void 0:return uu(),eu("eof")}uu()},value(){switch(J){case"{":case"[":return eu("punctuator",uu());case"n":return uu(),tu("ull"),eu("null",null);case"t":return uu(),tu("rue"),eu("boolean",!0);case"f":return uu(),tu("alse"),eu("boolean",!1);case"-":case"+":return"-"===uu()&&(Z=-1),void(z="numerical");case".":case"0":case"I":case"N":return void(z="numerical");case'"':case"'":return q=J,uu(),j="",void(z="string")}if(void 0===J||!H.JudgeUtil.isDigitWithoutZero(J))throw Eu(x.Char,uu());z="numerical"},numerical(){switch(J){case".":return j=uu(),void(z="decimalPointLeading");case"0":return j=uu(),void(z="zero");case"I":return uu(),tu("nfinity"),eu("numeric",Z*(1/0));case"N":return uu(),tu("aN"),eu("numeric",NaN)}if(void 0!==J&&H.JudgeUtil.isDigitWithoutZero(J))return j=uu(),void(z="decimalInteger");throw Eu(x.Char,uu())},zero(){switch(J){case".":case"e":case"E":return void(z="decimal");case"x":case"X":return j+=uu(),void(z="hexadecimal")}return eu("numeric",0)},decimalInteger(){switch(J){case".":case"e":case"E":return void(z="decimal")}if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},decimal(){switch(J){case".":j+=uu(),z="decimalFraction";break;case"e":case"E":j+=uu(),z="decimalExponent"}},decimalPointLeading(){if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalFraction");throw Eu(x.Char,uu())},decimalFraction(){switch(J){case"e":case"E":return j+=uu(),void(z="decimalExponent")}if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},decimalExponent(){switch(J){case"+":case"-":return j+=uu(),void(z="decimalExponentSign")}if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalExponentInteger");throw Eu(x.Char,uu())},decimalExponentSign(){if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalExponentInteger");throw Eu(x.Char,uu())},decimalExponentInteger(){if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},hexadecimal(){if(H.JudgeUtil.isHexDigit(J))return j+=uu(),void(z="hexadecimalInteger");throw Eu(x.Char,uu())},hexadecimalInteger(){if(!H.JudgeUtil.isHexDigit(J))return eu("numeric",Z*Number(j));j+=uu()},identifierNameStartEscape(){if("u"!==J)throw Eu(x.Char,uu());uu();const u=ru();switch(u){case"$":case"_":break;default:if(!H.JudgeUtil.isIdStartChar(u))throw Eu(x.Identifier)}j+=u,z="identifierName"},identifierName(){switch(J){case"$":case"_":case"":case"":return void(j+=uu());case"\\":return uu(),void(z="identifierNameEscape")}if(!H.JudgeUtil.isIdContinueChar(J))return eu("identifier",j);j+=uu()},identifierNameEscape(){if("u"!==J)throw Eu(x.Char,uu());uu();const u=ru();switch(u){case"$":case"_":case"":case"":break;default:if(!H.JudgeUtil.isIdContinueChar(u))throw Eu(x.Identifier)}j+=u,z="identifierName"},string(){switch(J){case"\\":return uu(),void(j+=function(){const u=Y(),D=function(){switch(Y()){case"b":return uu(),"\b";case"f":return uu(),"\f";case"n":return uu(),"\n";case"r":return uu(),"\r";case"t":return uu(),"\t";case"v":return uu(),"\v"}return}();if(D)return D;switch(u){case"0":if(uu(),H.JudgeUtil.isDigit(Y()))throw Eu(x.Char,uu());return"\0";case"x":return uu(),function(){let u="",D=Y();if(!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());if(u+=uu(),D=Y(),!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());return u+=uu(),String.fromCodePoint(parseInt(u,16))}();case"u":return uu(),ru();case"\n":case"\u2028":case"\u2029":return uu(),"";case"\r":return uu(),"\n"===Y()&&uu(),""}if(void 0===u||H.JudgeUtil.isDigitWithoutZero(u))throw Eu(x.Char,uu());return uu()}());case'"':case"'":if(J===q){const u=eu("string",j);return uu(),u}return void(j+=uu());case"\n":case"\r":case void 0:throw Eu(x.Char,uu());case"\u2028":case"\u2029":!function(u){console.warn(`JSON5: '${Fu(u)}' in strings is not valid ECMAScript; consider escaping.`)}(J)}j+=uu()}};function eu(u,D){return{type:u,value:D,line:$,column:k}}function tu(u){for(const D of u){if(Y()!==D)throw Eu(x.Char,uu());uu()}}function ru(){let u="",D=4;for(;D-- >0;){const D=Y();if(!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());u+=uu()}return String.fromCodePoint(parseInt(u,16))}const nu={start(){if("eof"===M.type)throw Eu(x.EOF);iu()},beforePropertyName(){switch(M.type){case"identifier":case"string":return V=M.value,void(W="afterPropertyName");case"punctuator":return void Cu();case"eof":throw Eu(x.EOF)}},afterPropertyName(){if("eof"===M.type)throw Eu(x.EOF);W="beforePropertyValue"},beforePropertyValue(){if("eof"===M.type)throw Eu(x.EOF);iu()},afterPropertyValue(){if("eof"===M.type)throw Eu(x.EOF);switch(M.value){case",":return void(W="beforePropertyName");case"}":Cu()}},beforeArrayValue(){if("eof"===M.type)throw Eu(x.EOF);"punctuator"!==M.type||"]"!==M.value?iu():Cu()},afterArrayValue(){if("eof"===M.type)throw Eu(x.EOF);switch(M.value){case",":return void(W="beforeArrayValue");case"]":Cu()}},end(){}};function iu(){const u=function(){let u;switch(M.type){case"punctuator":switch(M.value){case"{":u={};break;case"[":u=[]}break;case"null":case"boolean":case"numeric":case"string":u=M.value}return u}();if(K&&"object"==typeof u&&(u._line=$,u._column=k),void 0===G)G=u;else{const D=U[U.length-1];Array.isArray(D)?K&&"object"!=typeof u?D.push({value:u,_line:$,_column:k}):D.push(u):D[V]=K&&"object"!=typeof u?{value:u,_line:$,_column:k}:u}!function(u){if(u&&"object"==typeof u)U.push(u),W=Array.isArray(u)?"beforeArrayValue":"beforePropertyName";else{const u=U[U.length-1];W=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}}(u)}function Cu(){U.pop();const u=U[U.length-1];W=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}function Fu(u){const D={"'":"\\'",'"':'\\"',"\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\v":"\\v","\0":"\\0","\u2028":"\\u2028","\u2029":"\\u2029"};if(D[u])return D[u];if(u<" "){const D=u.charCodeAt(0).toString(16);return`\\x${`00${D}`.substring(D.length)}`}return u}function Eu(u,D){let e="";switch(u){case x.Char:e=void 0===D?`JSON5: invalid end of input at ${$}:${k}`:`JSON5: invalid character '${Fu(D)}' at ${$}:${k}`;break;case x.EOF:e=`JSON5: invalid end of input at ${$}:${k}`;break;case x.Identifier:k-=5,e=`JSON5: invalid identifier character at ${$}:${k}`}const t=new Au(e);return t.lineNumber=$,t.columnNumber=k,t}class Au extends SyntaxError{}var ou={},au=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),cu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),su=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&au(D,u,e);return cu(D,u),D},lu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(ou,"__esModule",{value:!0}),ou.isFileExists=ou.offlinePluginConversion=ou.executeCommand=ou.getNpmPath=ou.hasNpmPackInPaths=void 0;const Bu=r,du=lu(e),fu=su(u),_u=i,pu=l;ou.hasNpmPackInPaths=function(u,D){try{return require.resolve(u,{paths:[...D]}),!0}catch(u){return!1}},ou.getNpmPath=function(){const u=process.execPath;return fu.join(fu.dirname(u),_u.NPM_TOOL)},ou.executeCommand=function(u,D,e){0!==(0,Bu.spawnSync)(u,D,e).status&&(0,pu.logErrorAndExit)(`Error: ${u} ${D} execute failed.See above for details.`)},ou.offlinePluginConversion=function(u,D){return D.startsWith("file:")||D.endsWith(".tgz")?fu.resolve(u,_u.HVIGOR,D.replace("file:","")):D},ou.isFileExists=function(u){return du.default.existsSync(u)&&du.default.statSync(u).isFile()};var Ou=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),hu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),Pu=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&Ou(D,u,e);return hu(D,u),D},vu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(P,"__esModule",{value:!0});var gu=P.initProjectWorkSpace=void 0;const mu=Pu(e),Ru=vu(D),yu=Pu(u),Iu=v,Nu=i,bu=g,Su=l,wu=ou;let Hu,xu,Mu;function Tu(u,D,e){return void 0!==e.dependencies&&(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,D.dependencies[u])===yu.normalize(e.dependencies[u])}function Vu(){const u=yu.join(Mu,Nu.WORK_SPACE);if((0,Su.logInfoPrintConsole)("Hvigor cleaning..."),!mu.existsSync(u))return;const D=mu.readdirSync(u);if(!D||0===D.length)return;const e=yu.resolve(Mu,"node_modules","@ohos","hvigor","bin","hvigor.js");mu.existsSync(e)&&(0,wu.executeCommand)(process.argv[0],[e,"--stop-daemon"],{});try{D.forEach((D=>{mu.rmSync(yu.resolve(u,D),{recursive:!0})}))}catch(D){(0,Su.logErrorAndExit)(`The hvigor build tool cannot be installed. Please manually clear the workspace directory and synchronize the project again.\n\n Workspace Path: ${u}.`)}}gu=P.initProjectWorkSpace=function(){if(Hu=function(){const u=yu.resolve(Nu.HVIGOR_PROJECT_WRAPPER_HOME,Nu.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME);mu.existsSync(u)||(0,Su.logErrorAndExit)(`Error: Hvigor config file ${u} does not exist.`);return(0,bu.parseJsonFile)(u)}(),Mu=function(u){let D;D=function(u){let D=u.hvigorVersion;if(D.startsWith("file:")||D.endsWith(".tgz"))return!1;const e=u.dependencies,t=Object.getOwnPropertyNames(e);for(const u of t){const D=e[u];if(D.startsWith("file:")||D.endsWith(".tgz"))return!1}if(1===t.length&&"@ohos/hvigor-ohos-plugin"===t[0])return D>"2.5.0";return!1}(u)?function(u){let D=`${Nu.HVIGOR_ENGINE_PACKAGE_NAME}@${u.hvigorVersion}`;const e=u.dependencies;if(e){Object.getOwnPropertyNames(e).sort().forEach((u=>{D+=`,${u}@${e[u]}`}))}return(0,Iu.hash)(D)}(u):(0,Iu.hash)(process.cwd());return yu.resolve(Ru.default.homedir(),".hvigor","project_caches",D)}(Hu),xu=function(){const u=yu.resolve(Mu,Nu.WORK_SPACE,Nu.DEFAULT_PACKAGE_JSON);return mu.existsSync(u)?(0,bu.parseJsonFile)(u):{dependencies:{}}}(),!(0,wu.hasNpmPackInPaths)(Nu.HVIGOR_ENGINE_PACKAGE_NAME,[yu.join(Mu,Nu.WORK_SPACE)])||(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion)!==xu.dependencies[Nu.HVIGOR_ENGINE_PACKAGE_NAME]||!function(){function u(u){const D=null==u?void 0:u.dependencies;return void 0===D?0:Object.getOwnPropertyNames(D).length}const D=u(Hu),e=u(xu);if(D+1!==e)return!1;for(const u in null==Hu?void 0:Hu.dependencies)if(!(0,wu.hasNpmPackInPaths)(u,[yu.join(Mu,Nu.WORK_SPACE)])||!Tu(u,Hu,xu))return!1;return!0}()){Vu();try{!function(){(0,Su.logInfoPrintConsole)("Hvigor installing...");for(const u in Hu.dependencies)Hu.dependencies[u]&&(Hu.dependencies[u]=(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.dependencies[u]));const u={dependencies:{...Hu.dependencies}};u.dependencies[Nu.HVIGOR_ENGINE_PACKAGE_NAME]=(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion);const D=yu.join(Mu,Nu.WORK_SPACE);try{mu.mkdirSync(D,{recursive:!0});const e=yu.resolve(D,Nu.DEFAULT_PACKAGE_JSON);mu.writeFileSync(e,JSON.stringify(u))}catch(u){(0,Su.logErrorAndExit)(u)}(function(){const u=["config","set","store-dir",Nu.HVIGOR_PNPM_STORE_PATH],D={cwd:yu.join(Mu,Nu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,wu.executeCommand)(Nu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)})(),function(){const u=["install"],D={cwd:yu.join(Mu,Nu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,wu.executeCommand)(Nu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)}(),(0,Su.logInfoPrintConsole)("Hvigor install success.")}()}catch(u){Vu()}}return Mu};var Gu={};!function(t){var C=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),F=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),E=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&C(D,u,e);return F(D,u),D},A=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(t,"__esModule",{value:!0}),t.executeInstallPnpm=t.isPnpmInstalled=t.environmentHandler=t.checkNpmConifg=t.PNPM_VERSION=void 0;const o=r,a=E(e),c=A(D),s=E(u),B=i,d=l,f=ou;t.PNPM_VERSION="7.30.0",t.checkNpmConifg=function(){const u=s.resolve(B.HVIGOR_PROJECT_ROOT_DIR,".npmrc"),D=s.resolve(c.default.homedir(),".npmrc");if((0,f.isFileExists)(u)||(0,f.isFileExists)(D))return;const e=(0,f.getNpmPath)(),t=(0,o.spawnSync)(e,["config","get","prefix"],{cwd:B.HVIGOR_PROJECT_ROOT_DIR});if(0!==t.status||!t.stdout)return void(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.");const r=s.resolve(`${t.stdout}`.replace(/[\r\n]/gi,""),".npmrc");(0,f.isFileExists)(r)||(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.")},t.environmentHandler=function(){process.env["npm_config_update-notifier"]="false"},t.isPnpmInstalled=function(){return!!a.existsSync(B.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH)&&(0,f.hasNpmPackInPaths)("pnpm",[B.HVIGOR_WRAPPER_TOOLS_HOME])},t.executeInstallPnpm=function(){(0,d.logInfoPrintConsole)(`Installing pnpm@${t.PNPM_VERSION}...`);const u=(0,f.getNpmPath)();!function(){const u=s.resolve(B.HVIGOR_WRAPPER_TOOLS_HOME,B.DEFAULT_PACKAGE_JSON);try{a.existsSync(B.HVIGOR_WRAPPER_TOOLS_HOME)||a.mkdirSync(B.HVIGOR_WRAPPER_TOOLS_HOME,{recursive:!0});const D={dependencies:{}};D.dependencies[B.PNPM]=t.PNPM_VERSION,a.writeFileSync(u,JSON.stringify(D))}catch(D){(0,d.logErrorAndExit)(`Error: EPERM: operation not permitted,create ${u} failed.`)}}(),(0,f.executeCommand)(u,["install","pnpm"],{cwd:B.HVIGOR_WRAPPER_TOOLS_HOME,stdio:["inherit","inherit","inherit"],env:process.env}),(0,d.logInfoPrintConsole)("Pnpm install success.")}}(Gu),function(){Gu.checkNpmConifg(),Gu.environmentHandler(),Gu.isPnpmInstalled()||Gu.executeInstallPnpm();const D=gu();_(u.join(D,i.WORK_SPACE))}();
\ No newline at end of file
diff --git a/drawing/draw/hvigorfile.ts b/drawing/draw/hvigorfile.ts
new file mode 100644
index 0000000..f3cb9f1
--- /dev/null
+++ b/drawing/draw/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/drawing/draw/hvigorw b/drawing/draw/hvigorw
new file mode 100644
index 0000000..ff6a29a
--- /dev/null
+++ b/drawing/draw/hvigorw
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# ----------------------------------------------------------------------------
+# Hvigor startup script, version 1.0.0
+#
+# Required ENV vars:
+# ------------------
+# NODE_HOME - location of a Node home dir
+# or
+# Add /usr/local/nodejs/bin to the PATH environment variable
+# ----------------------------------------------------------------------------
+
+HVIGOR_APP_HOME="`pwd -P`"
+HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
+warn() {
+ echo ""
+ echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
+}
+
+error() {
+ echo ""
+ echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
+}
+
+fail() {
+ error "$@"
+ exit 1
+}
+
+# Determine node to start hvigor wrapper script
+if [ -n "${NODE_HOME}" ];then
+ EXECUTABLE_NODE="${NODE_HOME}/bin/node"
+ if [ ! -x "$EXECUTABLE_NODE" ];then
+ fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
+ fi
+else
+ EXECUTABLE_NODE="node"
+ which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path"
+fi
+
+# Check hvigor wrapper script
+if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then
+ fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
+fi
+
+# start hvigor-wrapper script
+exec "${EXECUTABLE_NODE}" \
+ "${HVIGOR_WRAPPER_SCRIPT}" "$@"
diff --git a/drawing/draw/hvigorw.bat b/drawing/draw/hvigorw.bat
new file mode 100644
index 0000000..d570007
--- /dev/null
+++ b/drawing/draw/hvigorw.bat
@@ -0,0 +1,64 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Hvigor startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
+set NODE_EXE=node.exe
+
+goto start
+
+:start
+@rem Find node.exe
+if defined NODE_HOME goto findNodeFromNodeHome
+
+%NODE_EXE% --version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
+echo.
+echo Please set the NODE_HOME variable in your environment to match the
+echo location of your NodeJs installation.
+
+goto fail
+
+:findNodeFromNodeHome
+set NODE_HOME=%NODE_HOME:"=%
+set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
+
+if exist "%NODE_EXE_PATH%" goto execute
+echo.
+echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
+echo.
+echo Please set the NODE_HOME variable in your environment to match the
+echo location of your NodeJs installation.
+
+goto fail
+
+:execute
+@rem Execute hvigor
+"%NODE_EXE%" "%WRAPPER_MODULE_PATH%" %*
+
+if "%ERRORLEVEL%" == "0" goto hvigorwEnd
+
+:fail
+exit /b 1
+
+:hvigorwEnd
+if "%OS%" == "Windows_NT" endlocal
+
+:end
diff --git a/drawing/draw/oh-package-lock.json5 b/drawing/draw/oh-package-lock.json5
new file mode 100644
index 0000000..ddc8a54
--- /dev/null
+++ b/drawing/draw/oh-package-lock.json5
@@ -0,0 +1,13 @@
+{
+ "lockfileVersion": 1,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hypium@1.0.11": "@ohos/hypium@1.0.11"
+ },
+ "packages": {
+ "@ohos/hypium@1.0.11": {
+ "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.11.tgz",
+ "integrity": "sha512-KawcLnv43C3QIYv1UbDnKCFX3MohtDxGuFvzlUxT/qf2DBilR56Ws6zrj90LdH6PjloJQwOPESuBQIHBACAK7w=="
+ }
+ }
+}
\ No newline at end of file
diff --git a/drawing/draw/oh-package.json5 b/drawing/draw/oh-package.json5
new file mode 100644
index 0000000..f0c54ba
--- /dev/null
+++ b/drawing/draw/oh-package.json5
@@ -0,0 +1,12 @@
+{
+ "license": "",
+ "devDependencies": {
+ "@ohos/hypium": "1.0.11"
+ },
+ "author": "",
+ "name": "myapplication",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
diff --git a/drawing/draw/package-lock.json b/drawing/draw/package-lock.json
new file mode 100644
index 0000000..e10b254
--- /dev/null
+++ b/drawing/draw/package-lock.json
@@ -0,0 +1,58 @@
+{
+ "name": "draw",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "echarts": "^5.5.0"
+ }
+ },
+ "node_modules/echarts": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.5.0.tgz",
+ "integrity": "sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw==",
+ "dependencies": {
+ "tslib": "2.3.0",
+ "zrender": "5.5.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+ },
+ "node_modules/zrender": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.5.0.tgz",
+ "integrity": "sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==",
+ "dependencies": {
+ "tslib": "2.3.0"
+ }
+ }
+ },
+ "dependencies": {
+ "echarts": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.5.0.tgz",
+ "integrity": "sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw==",
+ "requires": {
+ "tslib": "2.3.0",
+ "zrender": "5.5.0"
+ }
+ },
+ "tslib": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+ },
+ "zrender": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.5.0.tgz",
+ "integrity": "sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==",
+ "requires": {
+ "tslib": "2.3.0"
+ }
+ }
+ }
+}
diff --git a/drawing/draw/package.json b/drawing/draw/package.json
new file mode 100644
index 0000000..121abb4
--- /dev/null
+++ b/drawing/draw/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "echarts": "^5.5.0"
+ }
+}
diff --git a/drawing/figs/evolution.png b/drawing/figs/evolution.png
new file mode 100644
index 0000000..41ed06a
Binary files /dev/null and b/drawing/figs/evolution.png differ
diff --git a/drawing/figs/relation.png b/drawing/figs/relation.png
new file mode 100644
index 0000000..c79f9fb
Binary files /dev/null and b/drawing/figs/relation.png differ
diff --git a/filestoraging/README.md b/filestoraging/README.md
new file mode 100644
index 0000000..5c72e71
--- /dev/null
+++ b/filestoraging/README.md
@@ -0,0 +1,21 @@
+# filestoraging
+### 1、项目说明
+总体思路: 磁盘管理与文件存取仿真程序项目开发的总体思路如图7.4示意。首先仿真出四个要素:文件、文件夹、文件分配表和磁盘。(1)磁盘以立体方块表示,一个立体方块表示一簇,磁盘块的编号被显示在其左部和上部,立体方块上面因需要可以显示标签并允许读者修改,以示意哪些立体方块属于同一个文件。(2)文件以有先后次序的立体方块表示,其上亦可因需要显示标签并允许读者修改。(3)文件分配表以表格来显示,其左部和上部显示表项编号,表项内显示的是磁盘块编号,空白表示未被占用。表项内的值亦可因需要允许读者修改。注意表格表项和磁盘的磁盘块有一一对应的关系,即同一编号的表项对应同一编号的磁盘块。(4)文件夹以列表形式显示,每一条目包含文件名称、文件长度、文件的首个磁盘块编号等。因需要允许读者增加或删除某一列表条目,以及修改该条目中的内容。
+ 图1.1 项目开发的总体思路图
+
+
+
+### 2、开发环境说明
+(1)系统版本:OpenHarmony 4.0 Release
+(2)SDK版本:API 10
+(3)Model类型:Stage
+(4)DevEco Studio版本:Deveco Studio 4.0 release
+(5)硬件环境:Unionpi Whale、RK3566开发板
+(6)预览器参数:(1)DeviceType:default;(2)Resolution:560-1280;(3)DPI:240;其余参数自定。
+### 3、项目主要函数调用关系图与项目输出界面演进图
+ 图3.1 项目主要函数调用关系图
+
+
+
+ 图3.2 项目输出界面演进图
+
\ No newline at end of file
diff --git a/filestoraging/figs/evolution.png b/filestoraging/figs/evolution.png
new file mode 100644
index 0000000..eb2bf91
Binary files /dev/null and b/filestoraging/figs/evolution.png differ
diff --git a/filestoraging/figs/overall.png b/filestoraging/figs/overall.png
new file mode 100644
index 0000000..3367536
Binary files /dev/null and b/filestoraging/figs/overall.png differ
diff --git a/filestoraging/figs/relation.png b/filestoraging/figs/relation.png
new file mode 100644
index 0000000..3dc8a07
Binary files /dev/null and b/filestoraging/figs/relation.png differ
diff --git a/filestoraging/filestorage/.gitignore b/filestoraging/filestorage/.gitignore
new file mode 100644
index 0000000..fbabf77
--- /dev/null
+++ b/filestoraging/filestorage/.gitignore
@@ -0,0 +1,11 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
\ No newline at end of file
diff --git a/filestoraging/filestorage/AppScope/app.json5 b/filestoraging/filestorage/AppScope/app.json5
new file mode 100644
index 0000000..a305ebc
--- /dev/null
+++ b/filestoraging/filestorage/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.example.filereality",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
diff --git a/filestoraging/filestorage/AppScope/resources/base/element/string.json b/filestoraging/filestorage/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000..dc1fdc0
--- /dev/null
+++ b/filestoraging/filestorage/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "FileReality"
+ }
+ ]
+}
diff --git a/filestoraging/filestorage/AppScope/resources/base/media/app_icon.png b/filestoraging/filestorage/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/filestoraging/filestorage/AppScope/resources/base/media/app_icon.png differ
diff --git a/filestoraging/filestorage/build-profile.json5 b/filestoraging/filestorage/build-profile.json5
new file mode 100644
index 0000000..cc9434a
--- /dev/null
+++ b/filestoraging/filestorage/build-profile.json5
@@ -0,0 +1,36 @@
+{
+ "app": {
+ "signingConfigs": [],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 10,
+ "compatibleSdkVersion": 9,
+ "runtimeOS": "OpenHarmony",
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug",
+ },
+ {
+ "name": "release"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/.gitignore b/filestoraging/filestorage/entry/.gitignore
new file mode 100644
index 0000000..e2713a2
--- /dev/null
+++ b/filestoraging/filestorage/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/build-profile.json5 b/filestoraging/filestorage/entry/build-profile.json5
new file mode 100644
index 0000000..197e83c
--- /dev/null
+++ b/filestoraging/filestorage/entry/build-profile.json5
@@ -0,0 +1,31 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ "arkOptions": {
+ // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
+ }
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": true,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/hvigorfile.ts b/filestoraging/filestorage/entry/hvigorfile.ts
new file mode 100644
index 0000000..c6edcd9
--- /dev/null
+++ b/filestoraging/filestorage/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/filestoraging/filestorage/entry/obfuscation-rules.txt b/filestoraging/filestorage/entry/obfuscation-rules.txt
new file mode 100644
index 0000000..985b2ae
--- /dev/null
+++ b/filestoraging/filestorage/entry/obfuscation-rules.txt
@@ -0,0 +1,18 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/oh-package.json5 b/filestoraging/filestorage/entry/oh-package.json5
new file mode 100644
index 0000000..225946c
--- /dev/null
+++ b/filestoraging/filestorage/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "license": "",
+ "devDependencies": {},
+ "author": "",
+ "name": "entry",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
diff --git a/filestoraging/filestorage/entry/src/main/ets/common/constants/CommonConstants.ets b/filestoraging/filestorage/entry/src/main/ets/common/constants/CommonConstants.ets
new file mode 100644
index 0000000..414f58d
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/ets/common/constants/CommonConstants.ets
@@ -0,0 +1,34 @@
+//公共常量
+export const boardNum: number = 11 // 行列数
+export const gridSize: number = 19 // 格子大小
+export const blockSize: number = 17 // 方块大小
+
+// 绘制Fat区域背景
+export const settings: RenderingContextSettings = new RenderingContextSettings(true)
+export const context: CanvasRenderingContext2D = new CanvasRenderingContext2D(settings)
+
+// 绘制Fat区域信息
+export const settings2: RenderingContextSettings = new RenderingContextSettings(true)
+export const context2: CanvasRenderingContext2D = new CanvasRenderingContext2D(settings2)
+
+// 绘制Disk区域背景
+export const settings3: RenderingContextSettings = new RenderingContextSettings(true)
+export const context3: CanvasRenderingContext2D = new CanvasRenderingContext2D(settings3)
+
+// 绘制Disk区域信息
+export const settings4: RenderingContextSettings = new RenderingContextSettings(true)
+export const context4: CanvasRenderingContext2D = new CanvasRenderingContext2D(settings4)
+
+// 绘制模拟区域信息
+export const settings5: RenderingContextSettings = new RenderingContextSettings(true)
+export const context5: CanvasRenderingContext2D = new CanvasRenderingContext2D(settings5)
+
+// 绘制文件夹区域信息
+export const settings6: RenderingContextSettings = new RenderingContextSettings(true);
+export const context6: CanvasRenderingContext2D = new CanvasRenderingContext2D(settings6);
+
+export const img1:ImageBitmap = new ImageBitmap("/common/image/fk1.png")
+export const img2:ImageBitmap = new ImageBitmap("/common/image/fk2.png")
+export const img3:ImageBitmap = new ImageBitmap("/common/image/fk3.png")
+
+
diff --git a/filestoraging/filestorage/entry/src/main/ets/common/image/fk1.png b/filestoraging/filestorage/entry/src/main/ets/common/image/fk1.png
new file mode 100644
index 0000000..52794ac
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/ets/common/image/fk1.png differ
diff --git a/filestoraging/filestorage/entry/src/main/ets/common/image/fk11.png b/filestoraging/filestorage/entry/src/main/ets/common/image/fk11.png
new file mode 100644
index 0000000..f7a3a7c
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/ets/common/image/fk11.png differ
diff --git a/filestoraging/filestorage/entry/src/main/ets/common/image/fk2.png b/filestoraging/filestorage/entry/src/main/ets/common/image/fk2.png
new file mode 100644
index 0000000..86b4edb
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/ets/common/image/fk2.png differ
diff --git a/filestoraging/filestorage/entry/src/main/ets/common/image/fk3.png b/filestoraging/filestorage/entry/src/main/ets/common/image/fk3.png
new file mode 100644
index 0000000..808ea7f
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/ets/common/image/fk3.png differ
diff --git a/filestoraging/filestorage/entry/src/main/ets/components/InterfaceFile.ets b/filestoraging/filestorage/entry/src/main/ets/components/InterfaceFile.ets
new file mode 100644
index 0000000..fcc8a3e
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/ets/components/InterfaceFile.ets
@@ -0,0 +1,744 @@
+import {initialize_simdisk,initialize_simfat,drawFatMessage,clearEmulation,draw_blocks,drawDiskText,clearFatMessage,clearBlock,clearDiskText,read_sim_fat,draw_blocks_emulation,
+ draw_files,
+ clearFiles
+} from '../utils/functions'
+
+// 文件项的唯一集合
+let file_name_set: Set = new Set()
+
+// 文件标签的唯一集合
+let blocks_label_set: Set = new Set()
+
+// 获取唯一字母标签
+function get_unique_tag(): string | null {
+ for (let ascii_code = 65; ascii_code <= 90; ascii_code++) {
+ let character = String.fromCharCode(ascii_code)
+ if (!blocks_label_set.has(character)) {
+ blocks_label_set.add(character)
+ return character
+ }
+ }
+ return null
+}
+
+function initialize_fileblock(block_num: string, code: string): string[] {
+ let files: string[] = []
+ for (let n = 0; n < parseInt(block_num); n++) {
+ files.push(`${code}${n + 1}`)
+ }
+ if (code === "Z") {
+ blocks_label_set.clear() // 确保blocks_label_set已经声明
+ }
+ return files
+}
+
+export class InterfaceFile {
+ messages: string[] // 系统消息队列
+ sim_fat_copy: string[][] // 拷贝simFAT
+ ex_disk_oc: boolean // 交替显示保存占用和添加占用标志
+ ex_disk_la: boolean // 修改保存标签和清除标签的标志
+ sim_disk_copy: string[][] // 拷贝simDisk
+ block_modi_tag: boolean // 磁盘块修改标志
+ block_modi_lb: string // 磁盘块标签值初始化
+ old_key: number[] // FAT表上一次的记录值
+ fat_modi_num: string // 打开下一个FAT单元格之前的修改数值
+ fat_modi_tag: boolean // 修改状态标签,为True时进入修改状态
+ clear_tag: boolean // 清除标签,让标签清理和fat清理操作互斥
+ check: boolean // 检查磁盘条件
+ code: string // 当前磁盘块标签字母
+ creating: boolean // 正在创建的状态
+ simFAT: string[][] // SimFAT 表初始化
+ simDisk: string[][] // SimDisk 区域初始化
+ folder_items: any[] // 文件项临时储存
+ fat_unique_set: Set // fat表去重集合,防止在一个位置建立多个磁盘块
+ file_name_label: string // 输入文件名输入框
+ blocks_num_label: string // 块数输入框
+ path_name_label: string // 创建目录项输入框
+ file_label:string[]
+ fat_tags: string[][] // FAT删除标志
+ fat_disks: string[][] // Disk方块删除标志
+ label_disks: string[][] // Disk标签删除标志
+ default: string // MessageDialog传参
+
+ constructor(len: number) {
+ this. messages = []
+ this.sim_fat_copy = null
+ this.ex_disk_oc = true
+ this.ex_disk_la = true
+ this.sim_disk_copy = null
+ this.block_modi_tag = false
+ this.block_modi_lb = ''
+ this.old_key = null
+ this.fat_modi_num = null
+ this.fat_modi_tag = false
+ this.clear_tag = true // 清除标签,让标签清理和FAT清理操作互斥
+ this.check = false // 检查磁盘条件
+ this.code = null // 当前磁盘块标签字母
+ this.creating = true // 正在创建的状态
+ this.simFAT = initialize_simfat() // SimFAT 表初始化
+ this.simDisk = initialize_simdisk() // SimDisk 区域初始化
+ this.folder_items = []
+ this.fat_unique_set = new Set(['0'])
+ this.file_name_label = ''
+ this.blocks_num_label = ''
+ this.path_name_label = ''
+ this.default = ''
+ this.file_label= new Array(0)
+ this.fat_tags = new Array(len)
+ this.fat_disks = new Array(len)
+ this.label_disks = new Array(len)
+ for (let i = 0; i < len; i++) {
+ this.fat_tags[i] = new Array(len)
+ this.fat_disks[i] = new Array(len)
+ this.label_disks[i] = new Array(len)
+
+ for (let j = 0; j < 10; j++) {
+ this.fat_tags[i][j] = ''
+ this.fat_disks[i][j] = ''
+ this.label_disks[i][j] = ''
+
+ }
+ }
+ }
+
+
+ create_file(file_name?: string, f_block?: string, block_num?: string) {
+ console.log("创建文件")
+ file_name = file_name ?? this.file_name_label // 输入文件名
+ block_num = block_num ?? this.blocks_num_label // 块数
+ f_block = f_block ?? this.select_fat_unique()
+
+ this.check = this.check_condition(file_name, f_block, block_num) // 执行数据合规检查
+
+ if (this.check) { // 合规时执行
+ if (this.creating) { // 初始时获取字母
+ this.code = get_unique_tag()
+ this.creating = false // 获取后除非触发保存,下次创建不更新字母
+ }
+ this.file_label = initialize_fileblock(block_num, this.code!)
+ this.creat_file_blocks()
+ this.sys_info("创建文件成功!")
+ }
+ }
+
+ // 获取唯一的FAT表编号
+ select_fat_unique(): string | null {
+ while (true) {
+ const unique_num = Math.floor(Math.random() * 99).toString()
+ if (!this.fat_unique_set.has(unique_num)) {
+ return unique_num
+ }
+ if (this.fat_unique_set.size >= 100) {
+ return null
+ }
+ }
+ }
+
+ // 检查创建和保存条件
+ check_condition(file_name: string, start_block_num: string, block_num: string): boolean {
+ // 更新唯一SimFAT表
+ this.simFAT.forEach(row => { // 更新唯一SimFAT表
+ row.forEach(item => this.fat_unique_set.add(item))
+ })
+
+ if (this.fat_unique_set.has('FF')) { // 判断磁盘空间时,排除掉非位置字符
+ this.fat_unique_set.delete('FF')
+ }
+ this.fat_unique_set.delete('100') // 收藏判断需要删除100这个非位置值
+
+ if (this.clear_tag) {
+ if (file_name !== "" && block_num !== "") { // 文件名和块数不为空才能保存
+ if (/^\d+$/.test(block_num)) { // 检查块数为正整数
+ if (!file_name_set.has(file_name)) { // 文件名不重复
+ if (this.fat_unique_set.size + parseInt(block_num) <= 100) {
+ if (start_block_num) {
+ if (!this.fat_unique_set.has(start_block_num)) {
+ return true
+ } else {
+ this.sys_info("首块位置已被占用!")
+ }
+ } else {
+ this.sys_info("磁盘已满!")
+ }
+ } else {
+ this.sys_info("磁盘空间不足!")
+ }
+ } else {
+ this.sys_info("文件名不能重复!")
+ }
+ } else {
+ this.sys_info("请输入正整数!")
+ }
+ } else {
+ this.sys_info("文件名或块数不能为空!")
+ }
+ } else {
+ this.sys_info("正在执行磁盘修改任务!")
+ }
+ }
+
+ creat_file_start_end_label() {
+
+ }
+
+ creat_file_blocks(): void {
+ const left_x: number = 210
+ const left_y: number = 40
+ const side: number = 20 // 元素边
+ const n: number = this.file_label.length
+
+ if (n <= 11) {
+ for (let i = 0; i < n; i++) {
+ const x: number = left_x - i * side
+ const y: number = left_y
+ draw_blocks_emulation(x,y,this.file_label[i])
+ }
+ }
+ else {
+ let end_i: number = n - 11 // 取最后5块
+ for (let i = 0; i < n; i++) { // i < 11 确保循环在最后5块内
+ const x: number = left_x - i * side
+ const y: number = left_y
+
+ if (i < 5) {
+ draw_blocks_emulation(x,y,this.file_label[i])
+ } else if (i === 5) {
+ draw_blocks_emulation(x,y,'...')
+ } else if (i < 11) {
+ draw_blocks_emulation(x,y,this.file_label[i+end_i])
+ }
+ }
+ }
+ }
+
+
+ //显示文件夹
+ show_files(path_name: any[]){
+ draw_files(path_name)
+ }
+
+
+ // 映射显示FAT表
+ show_fat(row: number, column: number): void {
+ // 获取FAT表中的值
+ const num = this.simFAT[row][column]
+ if (num !== "0") { // 检查FAT表中的值是否为非零
+ // 定义删除标志
+ this.fat_tags[row][column] = "fat_tag"
+ drawFatMessage(num, row, column)
+ }
+ }
+
+ // 显示整个FAT表
+ show_all_fat(): void {
+ // 清空画布上所有的"FAT_tag"标签
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ if (this.fat_tags[i][n] == "fat_tag") {
+ clearFatMessage(i,n)
+ }
+ }
+ }
+ // 遍历FAT表的行和列,显示FAT表中的所有元素
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ this.show_fat(i, n)
+ }
+ }
+ }
+
+ show_disk(row: number, column: number, color_tag: boolean | null = null): void {
+ // 获取磁盘块上的文本内容
+ const text = this.simDisk[row][column]
+ if (text !== "0") { // 检查磁盘块内容是否为非零值
+ console.log("text="+text+"+row="+row+"+column="+column)
+ // 定义删除标志
+ this.fat_disks[row][column] = 'fat_disk'
+ this.label_disks[row][column] = "label_disk"
+ if (color_tag) {
+ // 根据颜色标签绘制磁盘块 黄色 初始创建
+ draw_blocks(row, column, true)
+ } else {
+ // 绘制普通磁盘块 灰色 占用
+ draw_blocks(row, column, false)
+ }
+ drawDiskText(text,row,column)
+ }
+ }
+
+ // 显示所有磁盘块
+ show_all_disk(): void {
+ // 清除之前的磁盘块和标签
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ if (this.fat_disks[i][n] == 'fat_disk') {
+ clearBlock(i,n)
+ }
+ if (this.label_disks[i][n] == "label_disk") {
+ clearDiskText(i,n)
+ }
+ }
+ }
+
+ // 遍历所有行和列,显示每个磁盘块
+ for (let row = 0; row < 10; row++) {
+ for (let column = 0; column < 10; column++) {
+ this.show_disk(row, column)
+ }
+ }
+ }
+
+ save_file(file_name: string | null = null, f_block: string | null = null, blocks: string | null = null) {
+ console.log("保存文件")
+
+ file_name = file_name ?? this.file_name_label // 输入文件名
+ blocks = blocks ?? this.blocks_num_label // 块数
+
+ if (this.creating) {
+ this.create_file(file_name, f_block, blocks)
+ }
+
+ if (this.check) {
+ let fat_block = f_block ? f_block : this.select_fat_unique()
+ let fat_arr = this.generate_fat_array(fat_block, parseInt(blocks)) // 生成fat表
+ this.folder_items.push([file_name, fat_block, blocks, this.code]) // 添加到文件夹
+ file_name_set.add(file_name) // 添加唯一性文件名集合
+ fat_arr.forEach((block) => this.fat_unique_set.add(block)) // 将占用的磁盘位置信息添加进唯一集合,防止重复取数
+ this.load_files_list(fat_arr, this.code) // 根据fat表向磁盘装载文件数据并显示
+ this.show_path_info() // 保存后显示文件夹
+ this.creating = true // 上一次保存执行完成后才能开始二次执行
+ this.sys_info("保存成功")
+ }
+ }
+
+ generate_fat_array(first_block: string, blockNum: number): string[] {
+ const fat_arr = [first_block]
+
+ // 放入首块信息
+ this.fat_unique_set.add(first_block)
+
+ for (let i = 0; i < blockNum - 1; i++) {
+ let num: number | null
+ while (true) {
+ num = Math.floor(Math.random() * 99) + 1
+ if (this.fat_unique_set.size >= 101) {
+ num = null
+ break
+ }
+ if (!this.fat_unique_set.has(num.toString())) {
+ this.fat_unique_set.add(num.toString())
+ break
+ }
+ }
+ if (num !== null) {
+ fat_arr.push(num.toString())
+ } else {
+ break
+ }
+ }
+ return fat_arr
+ }
+
+ load_files_list(fat_ls: string[], block_label: string = "default") {
+ this.show_all_disk() // 更新磁盘显示
+
+ fat_ls.forEach((value, index) => {
+ const row = Math.floor(parseInt(value) / 10)
+ const column = parseInt(value) % 10
+
+ if (block_label == "default") {
+ block_label = this.simDisk[row][column][0]
+
+ }
+ if (index < fat_ls.length - 1) {
+ this.simFAT[row][column] = fat_ls[index + 1]
+ } else {
+ this.simFAT[row][column] = "FF"
+ }
+
+ this.simDisk[row][column] = `${block_label}${index + 1}`
+ this.show_disk(row, column, true) // 最后创建颜色才为黄色
+ })
+
+ this.show_all_fat() // 更新fat表显示
+ }
+
+ // 查询文件功能
+ query_file() {
+ const file_name = this.file_name_label
+ if(file_name_set.has(file_name)) {
+ console.log('folder_items='+this.folder_items)
+ this.folder_items.forEach((item) => {
+ if (file_name === item[0]) {
+ this.file_label = initialize_fileblock(item[2], item[3])
+ this.creat_file_blocks()
+ const block_nums = read_sim_fat(item[1], this.simFAT) // 通过首块fat获取全部文件fat
+ this.load_files_list(block_nums)
+ }
+ })
+ this.sys_info('查询成功')
+ } else {
+ console.log('文件夹中无该文件')
+ this.sys_info('文件夹中无该文件')
+ }
+ }
+
+ // FAT校验功能
+ fat_checkout() {
+ console.log('FAT校验')
+ if (this.sim_fat_copy) {
+ let num = 0
+ let tag = false
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ num++
+ if (this.simFAT[i][n] !== this.sim_fat_copy[i][n]) {
+ this.sys_info(`校验失败\n${i}行${n}列错误`)
+ tag = true
+ break
+ }
+ }
+ if (tag) {
+ break
+ }
+ }
+
+ if (num === 100) {
+ this.sys_info('校验正确')
+ }
+ } else {
+ this.sys_info('未进行修改操作,不可校验')
+ }
+ }
+
+ // 清除表单项
+ clear_fat_label() {
+ console.log('清除表单项')
+ if (this.clear_tag) {
+ // 清空画布上所有的"fat_tag"标签
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ if (this.fat_tags[i][n] == "fat_tag") {
+ clearFatMessage(i,n)
+ }
+ }
+ }
+ this.clear_tag = false
+ if (!this.sim_fat_copy) {
+ this.sim_fat_copy = JSON.parse(JSON.stringify(this.simFAT)) // # 深拷贝simFAT复制一份原正确列表并保存为复制对象
+ }
+ this.simFAT = initialize_simfat() // 清空原FAT表
+ this.sys_info("清除成功!")
+ } else {
+ this.sys_info("正在执行标注任务, 无法清除表单项!")
+ }
+ }
+
+ // 保存表单项
+ modi_fat_save() {
+ console.log("保存表单项")
+ this.fat_modi_tag = false // 关闭修改模式
+ this.clear_tag = true // 保存后可以清除
+ if (this.fat_modi_num && this.old_key) {
+ if (this.fat_modi_num.match(/^\d+$/) || this.fat_modi_num === "FF") {
+ this.simFAT[this.old_key[0]][this.old_key[1]] = this.fat_modi_num.match(/^\d+$/) ? this.fat_modi_num : "FF"
+ } else {
+ this.sys_info("请输入正整数或FF!")
+ }
+ }
+
+ this.show_all_fat()
+ this.old_key = null
+
+ for(let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ if (this.simFAT[i][n] != '0') {
+ let num = i * 10 + n
+ this.fat_unique_set.add(num.toString())
+ }
+ }
+ }
+ this.sys_info("保存表单成功!")
+ }
+
+ // 修改表单项
+ modi_fat() {
+ this.sys_info("正在修改表单项!")
+ this.fat_modi_tag = true
+ if (!this.sim_fat_copy) {
+ this.sim_fat_copy = JSON.parse(JSON.stringify(this.simFAT)) // # 深拷贝simFAT复制一份原正确列表并保存为复制对象
+ }
+ }
+
+ modi_fat_entry(row: number, column: number) {
+ if (this.fat_modi_num && this.old_key) {
+ if (/^\d+$/.test(this.fat_modi_num) || this.fat_modi_num === "FF") {
+ if (/^\d+$/.test(this.fat_modi_num)) {
+ this.simFAT[this.old_key[0]][this.old_key[1]] = this.fat_modi_num
+ } else {
+ this.simFAT[this.old_key[0]][this.old_key[1]] = "FF"
+ }
+ } else {
+ this.sys_info("请输入正整数,或FF!")
+ }
+ }
+ this.old_key = [column, row]
+ this.show_all_fat()
+ }
+
+
+
+ // Disk校验方法
+ disk_checkout() {
+ console.log("Disk校验")
+ if (this.sim_disk_copy) {
+ let num = 0
+ let tag = false
+
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ num ++
+ const diskValue = this.simDisk[i][n]
+
+ // 匹配 [A-Za-z]开头,后面跟数字的字符串
+ if (/^[A-Za-z]\d+$/.test(diskValue)) {
+ if (this.simDisk[i][n] !== this.sim_disk_copy[i][n]) {
+ this.sys_info(`校验失败\n${i}行${n}列错误`)
+ tag = true
+ break
+ }
+ }
+ }
+ if (tag) {
+ break
+ }
+ }
+
+ if (num === 100) {
+ this.sys_info("校验正确")
+ }
+ } else {
+ this.sys_info("未进行修改操作,不可校验")
+ }
+ }
+
+ // 添加占用
+ add_occupy() {
+ console.log("添加占用")
+ this.sys_info("正在添加占用...")
+ }
+
+ // 点击添加占用
+ add_occupy_click(row: number, col: number) {
+ if (!this.ex_disk_oc) {
+ this.simDisk[col][row] = '' // 清空simDisk中对应位置的值
+ console.log(col.toString(), row.toString())
+ this.show_all_disk() // 假设 show_all_disk 是更新磁盘显示的方法
+ this.sys_info(`(${[col, row]}) 添加成功`)
+ }
+ }
+
+ // 保存占用
+ save_occupy() {
+ console.log("保存占用")
+
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ if (this.simDisk[i][n] != '0') {
+ let num = i * 10 + n
+ this.fat_unique_set.add(num.toString()) // 将占用块号添加到 fat_unique_set 中
+ }
+ }
+ }
+ this.sys_info("保存占用成功!")
+ }
+
+ // 修改标签
+ modi_block_lb() {
+ console.info("修改标签")
+ this.sys_info("正在修改标签...")
+ this.block_modi_tag = true // 磁盘块修改标志
+ this.clear_tag = false // 修改磁盘标签时冻结文件分配表的按钮
+ if (!this.sim_disk_copy) {
+ this.sim_disk_copy = JSON.parse(JSON.stringify(this.simDisk)) // 深拷贝数组
+ }
+ }
+
+ // 修改标签条目
+ modi_block_entry(row: number, column: number) {
+ let label = this.block_modi_lb
+
+ if (this.block_modi_lb) {
+ if (label !== "0") {
+ const regex = /^[A-Za-z]\d+$/ // 正则表达式将匹配如 "A1"、"b2"、"Z9" 等形式的字符串
+ if (regex.test(label)) {
+ this.simDisk[this.old_key[0]][this.old_key[1]] = label
+ this.sys_info(`${this.old_key} -> ${label}添加成功!`)
+ } else {
+ this.sys_info("请输入正确格式,如:A1!")
+ }
+ }
+ }
+
+ this.old_key = [column, row]
+ this.show_all_disk()
+ }
+
+ // 保存标签
+ modi_block_save() {
+ console.info("保存标签")
+
+ if (this.block_modi_lb) {
+ let label = this.block_modi_lb
+ if (label !== "0") {
+ const regex = /^[A-Za-z]\d+$/
+ if (regex.test(label)) {
+ this.simDisk[this.old_key[0]][this.old_key[1]] = label
+ this.sys_info(`${this.old_key} -> ${label}添加成功!`)
+ } else {
+ this.sys_info("请输入正确格式,如:A1!")
+ }
+
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ if (this.simDisk[i][n] !== '0' && this.simDisk[i][n] !== '') {
+ let num = i * 10 + n
+ let code = this.simDisk[i][n][0] // 取第一个字母
+ blocks_label_set.add(code) // 添加到唯一集合
+ this.fat_unique_set.add(num.toString()) // 添加到FAT表
+ }
+ }
+ }
+ }
+ }
+
+ this.block_modi_lb = '' // 重置 block_modi_lb
+ this.show_all_disk()
+ this.block_modi_tag = false // 关闭标签修改状态
+ this.clear_tag = true
+ this.sys_info("保存标签成功!")
+ }
+
+ // 清除标签
+ clear_disk_label() {
+ console.info("清除标签")
+
+ if (this.clear_tag) {
+ // 清除之前的标签
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ if (this.label_disks[i][n] == "label_disk") {
+ clearDiskText(i,n)
+ }
+ }
+ }
+ this.clear_tag = false // 将清除标志置否,防止其他模块改动
+
+ if (!this.sim_disk_copy) {
+ this.sim_disk_copy = JSON.parse(JSON.stringify(this.simDisk)) // 深拷贝原列表
+ }
+
+ for (let i = 0; i < 10; i++) {
+ for (let j = 0; j < 10; j++) {
+ if (this.simDisk[i][j] !== '0') {
+ this.simDisk[i][j] = "" // 清除标签
+ }
+ }
+ }
+
+ this.sys_info("清除成功!")
+ } else {
+ this.sys_info("正在执行标注任务,无法清除标签")
+ }
+ }
+
+ show_path_info() {
+
+ }
+
+ //创建目录项
+ create_path(path_name:string){
+ if(this.clear_tag){
+ const text_list = path_name.split(',')
+ if(!file_name_set.has(text_list[0])){
+ if(text_list.length===3 && !isNaN(parseInt(text_list[1])) && !isNaN(parseInt(text_list[2]))){
+ if(this.check_condition(text_list[0],text_list[1],text_list[2])){
+ this.save_file(text_list[0],text_list[1],text_list[2])
+ this.show_files(this.folder_items)
+ this.sys_info('创建目录成功!')
+ }
+ }else{
+ this.sys_info('请检查输入格式{\'str\',\'int\',\'int\'}!')
+ }
+ }else{
+ this.sys_info('文件名重复')
+ }
+ }else{
+ this.sys_info('目前正在执行磁盘修复任务!')
+ }
+ }
+
+ // 重置功能
+ reset_path(len:number) {
+ for (let i = 0; i < 10; i++) {
+ for (let n = 0; n < 10; n++) {
+ clearFatMessage(i, n)
+ clearDiskText(i, n)
+ clearBlock(i, n)
+ }
+ }
+ clearEmulation()
+ clearFiles()
+
+ file_name_set = new Set()
+ blocks_label_set = new Set()
+
+ this. messages = []
+ this.sim_fat_copy = null
+ this.ex_disk_oc = true
+ this.ex_disk_la = true
+ this.sim_disk_copy = null
+ this.block_modi_tag = false
+ this.block_modi_lb = ''
+ this.old_key = null
+ this.fat_modi_num = null
+ this.fat_modi_tag = false
+ this.clear_tag = true // 清除标签,让标签清理和FAT清理操作互斥
+ this.check = null // 检查磁盘条件
+ this.code = null // 当前磁盘块标签字母
+ this.creating = true // 正在创建的状态
+ this.simFAT = initialize_simfat() // SimFAT 表初始化
+ this.simDisk = initialize_simdisk() // SimDisk 区域初始化
+ this.folder_items = []
+ this.fat_unique_set = new Set(['0'])
+ this.default = ''
+ this.file_label = new Array(0)
+ this.fat_tags = new Array(len)
+ this.fat_disks = new Array(len)
+ this.label_disks = new Array(len)
+ for (let i = 0; i < len; i++) {
+ this.fat_tags[i] = new Array(len)
+ this.fat_disks[i] = new Array(len)
+ this.label_disks[i] = new Array(len)
+
+ for (let j = 0; j < 10; j++) {
+ this.fat_tags[i][j] = ''
+ this.fat_disks[i][j] = ''
+ this.label_disks[i][j] = ''
+
+ }
+ }
+ this.sys_info('重置成功!')
+ }
+
+ sys_info(message:string) {
+ if(this.messages.length < 9){
+ this.messages.unshift(message)
+ }else{
+ this.messages.pop()
+ this.messages.unshift(message)
+ }
+ this.messages = [...this.messages]
+ }
+}
+
diff --git a/filestoraging/filestorage/entry/src/main/ets/components/MessageDialog.ets b/filestoraging/filestorage/entry/src/main/ets/components/MessageDialog.ets
new file mode 100644
index 0000000..82ac463
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/ets/components/MessageDialog.ets
@@ -0,0 +1,48 @@
+//信息提示弹窗
+import { InterfaceFile } from './InterfaceFile'
+
+@CustomDialog
+export default struct MessageDialog {
+ controller: CustomDialogController
+ @Link File:InterfaceFile
+ build(){
+ Column({space:5}){
+ Text(`${this.File.old_key[0]}行${this.File.old_key[1]}列`)
+ .fontSize(20)
+ .height(45)
+ .textAlign(TextAlign.Center)
+ .fontWeight(FontWeight.Bold)
+ .fontColor(Color.White)
+
+ TextInput({placeholder:this.File.default})
+ .fontSize(20)
+ .height(45)
+ .placeholderColor(Color.White)
+ .placeholderFont({size:20, weight:FontWeight.Bold})
+ .textAlign(TextAlign.Center)
+ .fontWeight(FontWeight.Bold)
+ .fontColor(Color.White)
+ .onChange((value: string) => {
+ if(this.File.fat_modi_tag) {
+ this.File.fat_modi_num = value
+ }
+ else if (this.File.block_modi_tag) {
+ this.File.block_modi_lb = value
+ }
+ })
+
+ Text('确定')
+ .fontSize(20)
+ .textAlign(TextAlign.Center)
+ .fontWeight(FontWeight.Bold)
+ .fontColor(Color.White)
+ .onClick(()=>{
+ this.controller.close()
+ })
+ }
+ .backgroundColor('#00a5df')
+ .justifyContent(FlexAlign.Center)
+ .width(500)
+ .height(150)
+ }
+}
diff --git a/filestoraging/filestorage/entry/src/main/ets/components/five.ets b/filestoraging/filestorage/entry/src/main/ets/components/five.ets
new file mode 100644
index 0000000..853a348
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/ets/components/five.ets
@@ -0,0 +1,159 @@
+// 第五章
+// 编程7.15
+// 产生一个FAT表
+function create_sim_fat(): string[][] {
+ let sim_fat: string[][] = [
+ ['00', '01', 'FF', '03', 'FF', '05', '06', '07', '08', '09'],
+ ['0A', '0B', '0C', '0D', '0E', '0F', '10', '11', '12', '13'],
+ ['14', '15', '16', '17', '18', '19', '1A', '1B', '1C', '1D'],
+ ['1E', '1F', '20', '21', '22', '23', '24', '25', '26', '27'],
+ ['28', '29', '2A', '2B', '2C', '2D', '2E', '2F', '30', '31'],
+ ['32', '33', '34', '35', '36', '37', '38', '39', '3A', '3B'],
+ ['3C', '3D', '3E', '3F', '40', '41', '42', '43', '44', '45'],
+ ['46', '47', '48', '49', '4A', '4B', '4C', '4D', '4E', '4F'],
+ ['50', '51', '52', '53', '54', '55', '56', '57', '58', '59'],
+ ['5A', '5B', '5C', '5D', '5E', '5F', '60', '61', '62', '63']
+ ];
+ return sim_fat;
+}
+
+// 恢复文件夹信息根据FAT表
+function restore_folder_by_fat(): string[] {
+ let sim_fat = create_sim_fat(); // 创建模拟的FAT表
+ let folder_item: string[] = []; // 用于存储文件夹信息的列表
+ let last_item: Set = new Set(); // 用于跟踪已经处理过的磁盘块
+
+ for (let num = 0; num < 100; num++) { // 主循环,用于分析文件个数
+ let sim_fat_array: string[] = []; // 清除单个文件的磁盘块
+ let data: number | null = null; // 用于跟踪当前磁盘块
+
+ // 寻找下一个可用的磁盘块作为文件的起始磁盘块
+ for (let ab = 0; ab < 100; ab++) {
+ let y = ab % 10;
+ let x = Math.floor(ab / 10);
+ if (sim_fat[x][y] === 'FF' && !last_item.has(ab)) {
+ data = ab;
+ last_item.add(ab);
+ break;
+ }
+ }
+
+ if (data === null) {
+ break;
+ }
+
+ // 遍历链接的磁盘块,构建文件
+ while (data !== null) {
+ let x = Math.floor(data / 10);
+ let y = data % 10;
+ sim_fat_array.push(sim_fat[x][y]);
+ let next_data = parseInt(sim_fat[x][y], 16);
+ // 如果下一个磁盘块是0xFF,表示文件结束
+ if (next_data === 0xFF) {
+ break;
+ }
+ data = next_data;
+ }
+
+ // 构建文件项,并将其添加到文件夹列表
+ let fileName = `test${num}`;
+ let filestr = `<${fileName},${sim_fat_array[0]},${sim_fat_array.length + 1}>`;
+ folder_item.push(filestr);
+ }
+ return folder_item;
+}
+
+let folder_item = restore_folder_by_fat();
+folder_item.forEach(item => console.log(item));
+
+
+// ————————————————————————————————————————————————————————————————————————————————
+
+
+// 编程7.16
+// 模拟一个虚拟的磁盘扇区
+let virtual_sector_data: number[] = Array.from("This is a simulated disk sector.").map(c => c.charCodeAt(0));
+
+// 将数字数组转换为字符串
+function decodeToString(data: number[]): string {
+ return data.map(byte => String.fromCharCode(byte)).join('');
+}
+
+// 读取虚拟扇区内容
+function read_zero(data: number[]): void {
+ // 将二进制数据(数字数组)转换为字符串
+ let sector_content = decodeToString(data);
+ // 读取并打印扇区内容
+ console.log(sector_content);
+}
+
+// 主程序执行
+read_zero(virtual_sector_data);
+
+
+// ————————————————————————————————————————————————————————————————————————————————
+
+
+// 编程7.17
+// 模拟一个简单的FAT表的二进制数据
+let fat_table_data: Uint8Array = new Uint8Array([
+ 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+]);
+
+// 读取FAT表数据并转换为十六进制编号字符串
+function read_fat_table(data: Uint8Array): string {
+ let hex_values: string[] = []
+ for (let i = 0; i < data.length; i += 2) {
+ // 从二进制数据中提取两个字节作为一个FAT项
+ let fat_entry = (data[i] | (data[i + 1] << 8))
+ // 将FAT项转换成十六进制编号并添加到列表中
+ let hex_value = `0x${fat_entry.toString(16).toUpperCase().padStart(4, '0')}`
+ hex_values.push(hex_value)
+ }
+ // 将十六进制编号字符串列表连接为一个输出字符串
+ let output_string = hex_values.join(' ')
+ return output_string
+}
+
+let output = read_fat_table(fat_table_data)
+console.log(output)
+
+
+// ————————————————————————————————————————————————————————————————————————————————
+
+
+// 编程7.18
+// 模拟文件夹数据
+let folder_data: string[] = [
+ "File1 TXT 07 1B 00 0A 15 21 02 3E 01 00 00 00 0E 00 00 00", // 文件1
+ "File2 TXT 07 1B 00 0A 15 21 02 3E 01 00 00 00 0F 00 00 00", // 文件2
+ "Folder1 DIR 07 1B 00 0A 15 21 02 3E 01 00 00 00 10 00 00 00", // 文件夹1
+ "File3 TXT 07 1B 00 0A 15 21 02 3E 01 00 00 00 12 00 00 00", // 文件3
+ "Folder2 DIR 07 1B 00 0A 15 21 02 3E 01 00 00 00 14 00 00 00", // 文件夹2
+];
+
+// 读取文件夹数据并解析
+function read_folder_parse(data: string[]): void {
+ data.forEach(line => {
+ // 解析每一行的信息
+ // 获取文件名,前20个字符为文件名,使用trim()去掉额外空白字符
+ let filename = line.substring(0, 20).trim();
+ // 获取文件类型,接下来的11个字符为文件类型,使用trim()去掉额外空白字符
+ let filetype = line.substring(21, 32).trim();
+ // 获取创建时间,接下来的14个字符为创建时间,使用trim()去掉额外空白字符
+ let create_time = line.substring(32, 46).trim();
+ // 获取修改时间,接下来的14个字符为修改时间,使用trim()去掉额外空白字符
+ let update_time = line.substring(46, 60).trim();
+ // 打印可读信息
+ console.log("文件名: " + filename);
+ console.log("类型: " + filetype);
+ console.log("创建时间: " + create_time);
+ console.log("修改时间: " + update_time);
+ });
+}
+
+read_folder_parse(folder_data);
+
diff --git a/filestoraging/filestorage/entry/src/main/ets/components/one.ets b/filestoraging/filestorage/entry/src/main/ets/components/one.ets
new file mode 100644
index 0000000..6213908
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/ets/components/one.ets
@@ -0,0 +1,204 @@
+// 第一章
+// 编程7.1
+// 定义文件块数组
+let FOLDER_ITEM: any[] = []
+let SIM_FAT: string[][] = Array.from({ length: 3 }, () => Array(5).fill("0"))
+
+// 初始化基本数组
+export function init_base_array(): string[] {
+ let xy: number = Math.floor(Math.random() * 101)
+ let num: number = Math.floor(Math.random() * 28)
+ let sim_fat_back: string[] = [xy.toString()]
+ let flag: number = 0
+ for (let i = 0; i < num; i++) {
+ xy = Math.floor(Math.random() * 101)
+ let ab = xy.toString()
+ if (!sim_fat_back.includes(ab)) {
+ sim_fat_back.push(ab)
+ flag += 1
+ if (sim_fat_back.length === num) {
+ break
+ }
+ }
+ }
+ return sim_fat_back
+}
+
+// 生成数据块
+export function create_file_block(): string[] {
+ let num = Math.floor(Math.random() * 28) // 取随机数据
+ const zm: string[] = ['A', 'B', 'C', 'D', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] // 定义字母数组
+ let file_block: string[] = zm.slice(0, num) // 截取数组字符串
+ return file_block
+}
+
+// 生成仿真目录/文件夹
+export function create_folder_item(): any[] {
+ let file_name: string = "测试文件" // 定义文件名称
+ let xy: number = Math.floor(Math.random() * 101) // 定义100以内的随机数据
+ let num: number = Math.floor(Math.random() * 28) // 定义字符串标签数组
+ let folder_item: any[] = [file_name, xy, num] // 定义文件目录项
+ return folder_item
+}
+
+// 仿真磁盘区域
+export function create_sim_disk(): string[][] {
+ const zm: string[] = ['A', 'B', 'C', 'D', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] // 定义字母数组
+ let base_array: string[] = init_base_array() // 初始生成数组
+ let sim_disk: string[][] = [] // 定义磁盘仿真区域数组
+ let flag: number = 0 // 定义数组序号
+ for (let i = 0; i < 10; i++) { // 定义数组序号
+ let element: string[] = []
+ for (let j = 0; j < 10; j++) {
+ let ab: string = i.toString() + j.toString()
+ if (base_array.includes(ab)) {
+ element.push(zm[flag])
+ flag += 1
+ }
+ else {
+ element.push("0")
+ }
+ }
+ sim_disk.push(element)
+ }
+ return sim_disk
+}
+
+// 仿真文件分配表
+export function create_sim_fat(): string[][] {
+ let sim_fat: string[][] = []
+ let base_array: string[] = init_base_array() // 初始生成数组
+ for (let i = 0; i < 10; i++) { // 循环仿真文件分配二维数组
+ let element: string[] = []
+ for (let j = 0; j < 10; j++) {
+ let ab: string = i.toString() + j.toString()
+ if (base_array.includes(ab)) {
+ if (base_array.indexOf(ab) + 1 === base_array.length) {
+ element.push("FF")
+ } else {
+ element.push(base_array[base_array.indexOf(ab) + 1])
+ }
+ } else {
+ element.push("0")
+ }
+ }
+ sim_fat.push(element)
+ }
+ return sim_fat
+}
+
+// 总函数创建
+export function createData(): void {
+ console.log('create_file_block()='+create_file_block()) // 文件块
+ console.log('create_folder_item()='+create_folder_item()) // 文件目录项
+ console.log('create_sim_disk()='+create_sim_disk()) // 文件磁盘区域
+ console.log('create_sim_fat()='+create_sim_fat()) // 仿真文件分配表
+}
+
+
+// ——————————————————————————————————————————————————————————————————————————————————
+
+
+// 编程7.2
+// 统计磁盘空间大小
+export function count_sim_fat_size(): void {
+ let n: number = 0
+ for (let element of SIM_FAT) {
+ console.log('element='+element) // 打印每一行的内容
+ for (let i of element) {
+ if (i === "0") {
+ n += 1 // 统计空闲扇区数量
+ }
+ }
+ }
+ let size: string = (64 * n) + " KB" // 计算总的空闲磁盘空间大小
+ console.log(size)
+}
+
+
+// ——————————————————————————————————————————————————————————————————————————————————
+
+
+// 编程7.3
+// 创建FAT表
+export function create_fat(): string[][] {
+ let sim_fat_array = init_base_array()
+ console.log('sim_fat_array='+sim_fat_array)
+ for (let i = 0; i < 10; i++) {
+ for (let j = 0; j < 10; j++) {
+ let ab: string = i.toString() + j.toString()
+ if (sim_fat_array.includes(ab)) {
+ if (sim_fat_array.indexOf(ab) + 1 === sim_fat_array.length) {
+ SIM_FAT[i][j] = "FF" // 注意数组越界问题
+ }
+ else {
+ SIM_FAT[i][j] = sim_fat_array[sim_fat_array.indexOf(ab) + 1]
+ }
+ }
+ }
+ }
+ return SIM_FAT
+}
+
+
+// ——————————————————————————————————————————————————————————————————————————————————
+
+
+// 编程7.4
+// 定义FAT链表和第一块FAT位置
+let sim_fat_chain: { [key: string]: string }[] = [
+ { '08': '02' },
+ { '02': '56' },
+ { '56': '31' },
+ { '31': '55' },
+ { '55': '67' },
+ { '67': '74' },
+ { '74': 'FF' }
+]
+const FIRST_BLOCK: string = '08'
+
+// 获取磁盘块顺序
+export function get_disk_block_order(): string[] {
+ let disk_order: string[] = [FIRST_BLOCK]
+ let current_block: string = FIRST_BLOCK
+
+ while (current_block !== 'FF') {
+ let next_block: string = null
+ for (let item of sim_fat_chain) {
+ if (current_block in item) {
+ next_block = item[current_block]
+ break
+ }
+ }
+ if (next_block === null) {
+ break
+ }
+ disk_order.push(next_block)
+ current_block = next_block
+ }
+ return disk_order
+}
+
+
+// ——————————————————————————————————————————————————————————————————————————————————
+
+
+// 编程7.5
+// 插入一个目录项
+export function add_folder_item(item: any): any[] {
+ FOLDER_ITEM.push(item)
+ return FOLDER_ITEM
+}
+
+// 删除一个目录项
+export function del_folder_item(item: any): any[] {
+ const index = FOLDER_ITEM.indexOf(item)
+ if (index !== -1) {
+ FOLDER_ITEM.splice(index, 1)
+ console.log("删除成功")
+ }
+ else {
+ console.log("删除失败,元素不在目录项中")
+ }
+ return FOLDER_ITEM
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/main/ets/entryability/EntryAbility.ets b/filestoraging/filestorage/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000..1c7aa63
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,43 @@
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+import hilog from '@ohos.hilog';
+import UIAbility from '@ohos.app.ability.UIAbility';
+import Want from '@ohos.app.ability.Want';
+import window from '@ohos.window';
+
+export default class EntryAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
+ }
+
+ onDestroy(): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ // Main window is created, set main page for this ability
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+
+ windowStage.loadContent('pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy(): void {
+ // Main window is destroyed, release UI related resources
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
+ }
+
+ onForeground(): void {
+ // Ability has brought to foreground
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
+ }
+
+ onBackground(): void {
+ // Ability has back to background
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
+ }
+}
diff --git a/filestoraging/filestorage/entry/src/main/ets/pages/Index.ets b/filestoraging/filestorage/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000..a0753eb
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,468 @@
+import *as CommonConstant from '../common/constants/CommonConstants'
+import {drawFatLine,drawFatLabels,drawDiskLabels,draw_blocks_background} from '../utils/functions'
+import {InterfaceFile} from '../components/InterfaceFile'
+import MessageDialog from '../components/MessageDialog'
+import {createData,count_sim_fat_size,create_fat,get_disk_block_order, init_base_array,create_folder_item,add_folder_item,del_folder_item} from '../components/one'
+
+
+@Entry
+@Component
+struct Index {
+ @State File:InterfaceFile=new InterfaceFile(10)
+
+ //弹窗控制器
+ MessageDialogController: CustomDialogController = new CustomDialogController({
+ builder: MessageDialog({
+ File: $File
+ })
+ })
+
+ build() {
+ Row() {
+ Column() {
+ Row() {
+ Column() {
+ Row({space:4}) {
+ Text('输入文件名')
+ .fontSize(8)
+ .fontColor(Color.White)
+
+ TextInput()
+ .height(20)
+ .width(35)
+ .backgroundColor(Color.White)
+ .fontColor('#000')
+ .textAlign(TextAlign.Start)
+ .align(Alignment.Center)
+ .fontSize(12)
+ .borderRadius(0)
+ .padding({
+ top: 0
+ , right: 0
+ , bottom: 0
+ , left: 0
+ })
+ .onChange((value: string) => {
+ this.File.file_name_label = value;
+ })
+
+ Text('块数')
+ .fontSize(8)
+ .fontColor(Color.White)
+
+ TextInput()
+ .height(20)
+ .width(35)
+ .backgroundColor(Color.White)
+ .fontColor('#000')
+ .textAlign(TextAlign.Start)
+ .align(Alignment.Center)
+ .fontSize(12)
+ .borderRadius(0)
+ .padding({
+ top: 0
+ , right: 0
+ , bottom: 0
+ , left: 0
+ })
+ .onChange((value: string) => {
+ this.File.blocks_num_label = value;
+ })
+
+ Image($r('app.media.createFile'))
+ .width(30)
+ .height(15)
+ .onClick(()=>{
+ this.File.create_file()
+ })
+
+ Image($r('app.media.save'))
+ .width(30)
+ .height(15)
+ .onClick(()=>{
+ this.File.save_file()
+ this.File.show_files(this.File.folder_items)
+ })
+
+ Image($r('app.media.query'))
+ .width(30)
+ .height(15)
+ .onClick(()=>{
+ this.File.query_file()
+ })
+ }
+ .height(12)
+ .width('100%')
+ .margin({top:6,left:5})
+
+ Column() {
+ // 文字区域
+ Row() {
+ Text('初始文件模拟区:')
+ .fontSize(8)
+ .fontColor(Color.White)
+ }
+ .width('100%')
+ .height('20%')
+ .margin({left:5})
+
+ // 绘制区域
+ Column() {
+ Stack() {
+ Canvas(CommonConstant.context5) // 初始文件模拟区域
+ .width('100%')
+ .height('100%')
+ .margin({top: 15})
+ .onReady(() => {
+ // 方块部分
+ this.File.creat_file_blocks()
+ })
+ }
+ }
+ .width('100%')
+ }
+ }
+ .width('47%')
+ .height('100%')
+ .margin({top:5,left:10 })
+ .backgroundImage($r('app.media.pink_bg'))
+ .backgroundImageSize({width:270, height:140})
+
+ // 文件夹(目录)
+ Column() {
+ Row({space:2}) {
+ Text('文件夹(目录)')
+ .fontSize(8)
+ .fontColor(Color.White)
+
+ TextInput()
+ .height(20)
+ .width(60)
+ .backgroundColor(Color.White)
+ .fontColor('#000')
+ .textAlign(TextAlign.Start)
+ .align(Alignment.Center)
+ .fontSize(12)
+ .borderRadius(0)
+ .padding({
+ top: 0
+ , right: 0
+ , bottom: 0
+ , left: 0
+ })
+ .onChange((value:string)=>{
+ this.File.path_name_label = value
+ })
+
+ Image($r('app.media.createDirectory'))
+ .width(50)
+ .height(20)
+ .margin({left:5,right:5})
+ .onClick(()=>{
+ this.File.create_path(this.File.path_name_label)
+ })
+
+ Image($r('app.media.reset'))
+ .width(30)
+ .height(20)
+ .margin({left:5})
+ .onClick(()=>{
+ this.File.reset_path(10)
+ })
+
+ }
+ .height(12)
+ .width('100%')
+ .margin({top:4,left:10})
+
+ Column() {
+ // 文字区域
+ Row({space:10}) {
+ Text('文件名')
+ .fontSize(8)
+ .fontColor(Color.White)
+
+ Text('首块')
+ .fontSize(8)
+ .fontColor(Color.White)
+
+ Text('块数')
+ .fontSize(8)
+ .fontColor(Color.White)
+
+ Text('标签')
+ .fontSize(8)
+ .fontColor(Color.White)
+ }
+ .width('100%')
+ .height('15%')
+ .margin({left:5})
+ // .backgroundColor(Color.Black)
+ .alignItems(VerticalAlign.Bottom)
+
+ // 绘制区域
+ Row(){
+ Canvas(CommonConstant.context6) // 初始文件模拟区域
+ .width('100%')
+ .height('100%')
+ // .margin({top: 15})
+ // .backgroundColor(Color.Black)
+ .onReady(() => {
+ // 方块部分
+ this.File.show_files(this.File.folder_items)
+ })
+ }
+ .width('100%')
+ .height('75%')
+ }
+ .justifyContent(FlexAlign.Center)
+
+ }
+ .width('47%')
+ .height('100%')
+ .margin({top:5,left:10 })
+ .backgroundImage($r('app.media.purple_bg'))
+ .backgroundImageSize({width:270, height:140})
+
+ }
+ .height('35%')
+ .width('100%')
+
+ Row() {
+ // 文件分配表FAT
+ Column() {
+ Row({space:2}) {
+ Text('文件分配表FAT')
+ .fontSize(8)
+ .fontColor(Color.White)
+
+
+ Image($r("app.media.check1"))
+ .width(30)
+ .height(15)
+ .onClick(()=>{
+ this.File.fat_checkout()
+ })
+
+ Image($r('app.media.clearFormItem'))
+ .width(45)
+ .height(15)
+ .onClick(()=>{
+ this.File.clear_fat_label()
+ })
+
+ Image($r('app.media.saveFormItem'))
+ .width(45)
+ .height(15)
+ .onClick(()=>{
+ this.File.modi_fat_save()
+ })
+
+ Image($r('app.media.changeFormItem'))
+ .width(45)
+ .height(15)
+ .onClick(()=>{
+ this.File.modi_fat()
+ })
+ }
+ .height(15)
+ .width('100%')
+ .margin({top:4,left:5})
+
+ Column() {
+ Stack() {
+ Canvas(CommonConstant.context) // Fat区域
+ .width('100%')
+ .height('100%')
+ .margin({top: 15})
+ .onReady(() => {
+ // Fat区域背景
+ drawFatLine()
+
+ // 数字标签
+ drawFatLabels()
+ })
+
+ Canvas(CommonConstant.context2) // 文字
+ .width('100%')
+ .height('100%')
+ .margin({top: 15})
+
+ .onClick((event)=>{
+ //计算点击的的画布横纵坐标
+ let playX = event.x - CommonConstant.gridSize
+ let playY = event.y - CommonConstant.gridSize
+ //计算行列数 横纵坐标/格子大小
+ let row: number = Math.floor(playX / CommonConstant.gridSize)
+ let col: number = Math.floor(playY / CommonConstant.gridSize)
+
+ if (this.File.fat_modi_tag) {
+ this.File.modi_fat_entry(row, col)
+ this.File.default = this.File.simFAT[this.File.old_key[0]][this.File.old_key[1]]
+ this.MessageDialogController.open()
+ }
+ })
+ }
+
+ }
+ .width('100%')
+ .padding({left:10})
+ }
+ .width('47%')
+ .height('100%')
+ .margin({top:10,left:10 })
+ .backgroundImage($r('app.media.jade_blue_bg'))
+ .backgroundImageSize({width:270, height:240})
+
+
+ // 磁盘模块
+ Column() {
+ Row({space:2}) {
+ Text('磁盘模块')
+ .fontSize(8)
+ .fontColor(Color.White)
+
+ Image($r("app.media.check2"))
+ .width(30)
+ .height(15)
+ .onClick(()=>{
+ this.File.disk_checkout()
+ })
+
+ Image(this.File.ex_disk_oc ? $r('app.media.add') : $r("app.media.saveOccupy"))
+ .width(45)
+ .height(15)
+ .onClick(()=>{
+ if (this.File.ex_disk_oc) {
+ this.File.ex_disk_oc = false
+ }
+ else {
+ this.File.ex_disk_oc = true
+ }
+ if (this.File.ex_disk_oc == false) {
+ this.File.add_occupy()
+ }
+ else {
+ this.File.save_occupy()
+ }
+ })
+ Image(this.File.ex_disk_la ? $r("app.media.changeLabel") : $r("app.media.saveLabel"))
+ .width(45)
+ .height(15)
+ .onClick(()=>{
+ if (this.File.ex_disk_la) {
+ this.File.ex_disk_la = false
+ }
+ else {
+ this.File.ex_disk_la = true
+ }
+ if (this.File.ex_disk_la == false) {
+ this.File.modi_block_lb()
+ }
+ else {
+ this.File.modi_block_save()
+ }
+ })
+
+ Image($r('app.media.clearLabel'))
+ .width(45)
+ .height(15)
+ .onClick(()=>{
+ this.File.clear_disk_label()
+ })
+ }
+ .height(12)
+ .width('100%')
+ .margin({top:4,left:5})
+
+ Column() {
+ Stack() {
+ Canvas(CommonConstant.context3) // Disk区域
+ .width('100%')
+ .height('100%')
+ .margin({top: 15})
+ .onReady(() => {
+ // 数字标签部分
+ drawDiskLabels()
+
+ // 方块部分
+ draw_blocks_background()
+ })
+
+ Canvas(CommonConstant.context4) // 编号
+ .width('100%')
+ .height('100%')
+ .margin({top: 5})
+
+ .onClick((event)=>{
+ //计算点击的的画布横纵坐标
+ let playX = event.x - CommonConstant.blockSize
+ let playY = event.y - CommonConstant.blockSize
+ //计算行列数 横纵坐标/格子大小
+ let row: number = Math.floor(playX / CommonConstant.gridSize)
+ let col: number = Math.floor(playY / CommonConstant.gridSize)
+
+ this.File.add_occupy_click(row, col)
+
+ if (this.File.block_modi_tag) {
+ this.File.modi_block_entry(row, col)
+ this.File.default = this.File.simDisk[this.File.old_key[0]][this.File.old_key[1]]
+ this.MessageDialogController.open()
+ }
+ })
+ }
+ }
+ .width('100%')
+ .padding({left:15})
+ }
+ .width('47%')
+ .height('100%')
+ .margin({top:10,left:10 })
+ .backgroundImage($r('app.media.sky_blue_bg'))
+ .backgroundImageSize({width:270, height:240})
+ }
+ .height('65%')
+ .width('100%')
+
+ }
+ .width('80%')
+ .height('100%')
+
+ Column() {
+ Column() {
+ Text('系统消息框')
+ .fontSize(12)
+ .fontColor(Color.White)
+ .margin({top:3})
+ }
+ .width('100%')
+ .height('6%')
+ .margin({top:2})
+ .backgroundImage($r('app.media.rightbgtop'))
+
+ Column() {
+ ForEach(this.File.messages,message=>{
+ Text(message)
+ .fontSize(10).textAlign(TextAlign.Center)
+ .fontColor(Color.White)
+ .margin({top:4})
+ .backgroundImage($r('app.media.messagebg'))
+ .width('100%')
+ .height('11%')
+ })
+ }
+ .width('100%')
+ .height('90%')
+ .backgroundImage($r('app.media.rightbg'))
+
+ }
+ .width('20%')
+ .height('100%')
+
+ }
+ .width('100%')
+ .height('100%')
+ .backgroundImage($r('app.media.bg2'))
+ .backgroundImageSize(ImageSize.Cover)
+ }
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/main/ets/utils/functions.ets b/filestoraging/filestorage/entry/src/main/ets/utils/functions.ets
new file mode 100644
index 0000000..4c7f233
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/ets/utils/functions.ets
@@ -0,0 +1,198 @@
+// 功能函数
+import * as CommonConstant from '../common/constants/CommonConstants'
+
+// 初始化FAT矩阵
+export function initialize_simfat(): string[][] {
+ // 创建一个10x10的二维数组,每个元素都初始化为字符串 "0"
+ const simFat: string[][] = Array.from({ length: 10 }, () => Array(10).fill("0"))
+ simFat[0][0] = "100"; // 将第一个元素(第一行第一列)设置为字符串 "100"
+ return simFat; // 返回初始化的FAT矩阵
+}
+
+// 初始化磁盘矩阵
+export function initialize_simdisk(): string[][] {
+ // 创建一个10x10的二维数组,每个元素都初始化为字符串 "0"
+ const simDisk: string[][] = Array.from({ length: 10 }, () => Array(10).fill("0"))
+ return simDisk // 返回初始化的磁盘矩阵
+}
+
+// 绘制Fat区域线条
+export function drawFatLine() {
+ CommonConstant.context.strokeStyle = '#fff' //线条颜色
+ CommonConstant.context.lineWidth = 1 //线条宽
+
+ for (let i = 0; i < CommonConstant.boardNum; i++) {
+ // 横线
+ CommonConstant.context.beginPath()
+ CommonConstant.context.moveTo(CommonConstant.gridSize, i * CommonConstant.gridSize + CommonConstant.gridSize)
+ CommonConstant.context.lineTo(CommonConstant.gridSize * (CommonConstant.boardNum - 1) + CommonConstant.gridSize, i * CommonConstant.gridSize + CommonConstant.gridSize)
+ CommonConstant.context.stroke()
+
+ // 竖线
+ CommonConstant.context.beginPath()
+ CommonConstant.context.moveTo(i * CommonConstant.gridSize + CommonConstant.gridSize, CommonConstant.gridSize)
+ CommonConstant.context.lineTo(i * CommonConstant.gridSize + CommonConstant.gridSize, CommonConstant.gridSize * (CommonConstant.boardNum - 1) + CommonConstant.gridSize)
+ CommonConstant.context.stroke()
+ }
+}
+
+// 绘制Fat区域边框外侧数字
+export function drawFatLabels() {
+ CommonConstant.context.fillStyle = 'white' // 设置文字颜色为白色
+ CommonConstant.context.font = '25px Arial' // 设置字体和大小
+ CommonConstant.context.textAlign = 'center' // 设置文字对齐方式为居中
+ CommonConstant.context.textBaseline = 'middle' // 设置文字基线为居中
+
+ // 绘制数字标签
+ for (let i = 0; i < CommonConstant.boardNum - 1; i++) {
+ CommonConstant.context.fillText(i.toString(), i * CommonConstant.gridSize + CommonConstant.gridSize + CommonConstant.gridSize / 2, CommonConstant.gridSize / 2) // 上边标签
+ CommonConstant.context.fillText(i.toString(), CommonConstant.gridSize / 2, i * CommonConstant.gridSize + CommonConstant.gridSize + CommonConstant.gridSize / 2) // 左边标签
+ }
+}
+
+// 绘制Disk区域边框外侧数字
+export function drawDiskLabels() {
+ CommonConstant.context3.fillStyle = 'white' // 设置文字颜色为白色
+ CommonConstant.context3.font = '25px Arial' // 设置字体和大小
+ CommonConstant.context3.textAlign = 'center' // 设置文字对齐方式为居中
+ CommonConstant.context3.textBaseline = 'middle' // 设置文字基线为居中
+
+ // 绘制数字标签
+ for (let i = 0; i < CommonConstant.boardNum - 1; i++) {
+ CommonConstant.context3.fillText(i.toString(), i * CommonConstant.gridSize + CommonConstant.blockSize * 1.5, CommonConstant.blockSize / 2) // 上边标签
+ CommonConstant.context3.fillText(i.toString(), CommonConstant.blockSize / 2, i * CommonConstant.gridSize + CommonConstant.blockSize * 1.5) // 左边标签
+ }
+}
+
+//绘制模拟区方块
+export function draw_blocks_emulation(x:number,y:number,list_label:string) {
+ CommonConstant.context5.fillStyle = 'black' // 设置文字颜色为黑色
+ CommonConstant.context5.font = '20px Arial' // 设置字体和大小
+ CommonConstant.context5.textAlign = 'center' // 设置文字对齐方式为居中
+ CommonConstant.context5.textBaseline = 'middle' // 设置文字基线为居中
+ CommonConstant.context5.clearRect(0,0,x,y+20)
+ CommonConstant.context5.drawImage(CommonConstant.img3, x, y, CommonConstant.gridSize, CommonConstant.gridSize)
+ CommonConstant.context5.fillText(list_label, x + CommonConstant.gridSize / 2, y + CommonConstant.gridSize / 2)
+ CommonConstant.context5.fillStyle = 'white'
+ CommonConstant.context5.fillText('起始', x + CommonConstant.gridSize / 2, y - CommonConstant.gridSize)
+ CommonConstant.context5.clearRect(0,0, 210, 40)
+ CommonConstant.context5.fillText('尾部',x + CommonConstant.gridSize / 2,y - CommonConstant.gridSize/2)
+ CommonConstant.context5.clearRect(x + CommonConstant.gridSize+2,y - 13, 210, CommonConstant.gridSize/2)
+ for (let index = 0; index < (230-x)/20; index++) {
+ CommonConstant.context5.fillText('—', 230-index*4, y - CommonConstant.gridSize/2)
+ }
+ CommonConstant.context5.fillText('<',230-(230-x)/5 , y - CommonConstant.gridSize/2)
+}
+
+export function clearEmulation(){
+ CommonConstant.context5.clearRect(0,0,300,300)
+}
+
+export function draw_files(text_list:any[]){
+ CommonConstant.context6.fillStyle = 'white'; // 设置文字颜色为白色
+ CommonConstant.context6.font = '30px Arial'; // 设置字体和大小
+ CommonConstant.context6.textAlign = 'center'; // 设置文字对齐方式为居中
+ CommonConstant.context6.textBaseline = 'middle'; // 设置文字基线为居中
+ CommonConstant.context6.clearRect(0,0,300,300)
+ console.log('text_list.length='+text_list.length)
+ for (let index = 0; index < text_list.length; index++) {
+ const x = 10
+ const y = 10
+ CommonConstant.context6.fillText(text_list[index][0],x,y+index*20)
+ CommonConstant.context6.fillText(text_list[index][1],x+30,y+index*20)
+ CommonConstant.context6.fillText(text_list[index][2],x+60,y+index*20)
+ CommonConstant.context6.fillText(text_list[index][3],x+90,y+index*20)
+ }
+}
+
+export function clearFiles(){
+ CommonConstant.context6.clearRect(0,0,300,300)
+}
+// 绘制Disk区域初始方块
+export function draw_blocks_background() {
+ for (let row = 0; row < CommonConstant.boardNum - 1; row++) {
+ for (let col = 0; col < CommonConstant.boardNum - 1; col++) {
+ const x = col * CommonConstant.gridSize + CommonConstant.blockSize
+ const y = row * CommonConstant.gridSize + CommonConstant.blockSize
+ CommonConstant.context3.clearRect(x,y, CommonConstant.blockSize, CommonConstant.blockSize)
+ CommonConstant.context3.drawImage(CommonConstant.img1, x, y, CommonConstant.blockSize, CommonConstant.blockSize)
+ }
+ }
+}
+
+// 绘制Disk区域方块
+export function draw_blocks(row:number, col:number, color_tag:boolean) {
+ const x = col * CommonConstant.gridSize + CommonConstant.blockSize
+ const y = row * CommonConstant.gridSize + CommonConstant.blockSize
+
+ CommonConstant.context3.clearRect(x,y, CommonConstant.blockSize, CommonConstant.blockSize)
+
+ if (color_tag) {
+ CommonConstant.context3.drawImage(CommonConstant.img3, x, y, CommonConstant.blockSize, CommonConstant.blockSize)
+ }
+ else {
+ CommonConstant.context3.drawImage(CommonConstant.img2, x, y, CommonConstant.blockSize, CommonConstant.blockSize)
+ }
+}
+
+export function drawFatMessage(num: string, row: number, clown: number) {
+ CommonConstant.context2.fillStyle = 'white' // 设置文字颜色为白色
+ CommonConstant.context2.font = '20px Arial' // 设置字体和大小
+ CommonConstant.context2.textAlign = 'center' // 设置文字对齐方式为居中
+ CommonConstant.context2.textBaseline = 'middle' // 设置文字基线为居中
+
+ const x = clown * CommonConstant.gridSize + 1.5 * CommonConstant.gridSize
+ const y = row * CommonConstant.gridSize + 1.5 * CommonConstant.gridSize
+
+ CommonConstant.context2.fillText(num, x, y)
+}
+
+export function clearFatMessage(row: number, clown: number) {
+ const x = clown * CommonConstant.gridSize + CommonConstant.gridSize
+ const y = row * CommonConstant.gridSize + CommonConstant.gridSize
+
+ CommonConstant.context2.clearRect(x, y, CommonConstant.gridSize, CommonConstant.blockSize)
+}
+
+export function drawDiskText(text: string, row: number, clown: number) {
+ CommonConstant.context4.fillStyle = 'black' // 设置文字颜色为白色
+ CommonConstant.context4.font = '20px Arial' // 设置字体和大小
+
+ const x = clown * CommonConstant.gridSize + CommonConstant.gridSize
+ const y = row * CommonConstant.gridSize + 2 * CommonConstant.blockSize
+
+ CommonConstant.context4.clearRect(x,y, CommonConstant.gridSize, CommonConstant.gridSize)
+ CommonConstant.context4.fillText(text, x, y)
+}
+
+export function clearBlock(row: number, col: number) {
+ const x = col * CommonConstant.gridSize + CommonConstant.blockSize;
+ const y = row * CommonConstant.gridSize + CommonConstant.blockSize;
+ CommonConstant.context3.clearRect(x,y, CommonConstant.blockSize, CommonConstant.blockSize)
+ CommonConstant.context3.drawImage(CommonConstant.img1, x, y, CommonConstant.blockSize, CommonConstant.blockSize)
+}
+
+export function clearDiskText(row: number, col: number) {
+ const x = col * CommonConstant.gridSize + CommonConstant.gridSize;
+ const y = row * CommonConstant.gridSize + CommonConstant.gridSize;
+ CommonConstant.context4.clearRect(x,y, CommonConstant.gridSize, CommonConstant.gridSize)
+}
+
+export function read_sim_fat(first_block: string, sim_fat: string[][]): string[] {
+ const block_nums: Array = []; // 创建一个空数组来存储块号
+ block_nums.push(first_block)
+
+ while (true) {
+ const row = Math.floor(parseInt(first_block) / 10);
+ const clown = parseInt(first_block) % 10;
+ const b_num = sim_fat[row][clown];
+
+ if (b_num !== "FF") {
+ block_nums.push(b_num) // 添加下一个块号
+ first_block = b_num // 更新 first_block 以继续查找下一个块
+ } else {
+ break; // 如果找到 "FF",则退出循环
+ }
+ }
+ return block_nums
+}
diff --git a/filestoraging/filestorage/entry/src/main/module.json5 b/filestoraging/filestorage/entry/src/main/module.json5
new file mode 100644
index 0000000..f2ff2c7
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/element/color.json b/filestoraging/filestorage/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/element/string.json b/filestoraging/filestorage/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000..f945955
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/add.png b/filestoraging/filestorage/entry/src/main/resources/base/media/add.png
new file mode 100644
index 0000000..f776c49
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/add.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/bg2.png b/filestoraging/filestorage/entry/src/main/resources/base/media/bg2.png
new file mode 100644
index 0000000..21de35f
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/bg2.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/changeFormItem.png b/filestoraging/filestorage/entry/src/main/resources/base/media/changeFormItem.png
new file mode 100644
index 0000000..4dc44bd
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/changeFormItem.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/changeLabel.png b/filestoraging/filestorage/entry/src/main/resources/base/media/changeLabel.png
new file mode 100644
index 0000000..cabac96
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/changeLabel.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/check1.png b/filestoraging/filestorage/entry/src/main/resources/base/media/check1.png
new file mode 100644
index 0000000..f9aa602
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/check1.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/check2.png b/filestoraging/filestorage/entry/src/main/resources/base/media/check2.png
new file mode 100644
index 0000000..e04acb6
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/check2.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/clearFormItem.png b/filestoraging/filestorage/entry/src/main/resources/base/media/clearFormItem.png
new file mode 100644
index 0000000..7310295
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/clearFormItem.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/clearLabel.png b/filestoraging/filestorage/entry/src/main/resources/base/media/clearLabel.png
new file mode 100644
index 0000000..40edffe
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/clearLabel.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/createDirectory.png b/filestoraging/filestorage/entry/src/main/resources/base/media/createDirectory.png
new file mode 100644
index 0000000..7bacfbf
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/createDirectory.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/createFile.png b/filestoraging/filestorage/entry/src/main/resources/base/media/createFile.png
new file mode 100644
index 0000000..5db7844
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/createFile.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/fk11.png b/filestoraging/filestorage/entry/src/main/resources/base/media/fk11.png
new file mode 100644
index 0000000..f7a3a7c
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/fk11.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/icon.png b/filestoraging/filestorage/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/icon.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/jade_blue_bg.png b/filestoraging/filestorage/entry/src/main/resources/base/media/jade_blue_bg.png
new file mode 100644
index 0000000..7cf0cdf
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/jade_blue_bg.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/messagebg.png b/filestoraging/filestorage/entry/src/main/resources/base/media/messagebg.png
new file mode 100644
index 0000000..f8b3eb1
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/messagebg.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/pink_bg.png b/filestoraging/filestorage/entry/src/main/resources/base/media/pink_bg.png
new file mode 100644
index 0000000..67b2517
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/pink_bg.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/purple_bg.png b/filestoraging/filestorage/entry/src/main/resources/base/media/purple_bg.png
new file mode 100644
index 0000000..acd7ff5
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/purple_bg.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/query.png b/filestoraging/filestorage/entry/src/main/resources/base/media/query.png
new file mode 100644
index 0000000..5e3282c
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/query.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/reset.png b/filestoraging/filestorage/entry/src/main/resources/base/media/reset.png
new file mode 100644
index 0000000..708c046
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/reset.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/rightbg.png b/filestoraging/filestorage/entry/src/main/resources/base/media/rightbg.png
new file mode 100644
index 0000000..70b9826
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/rightbg.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/rightbgtop.png b/filestoraging/filestorage/entry/src/main/resources/base/media/rightbgtop.png
new file mode 100644
index 0000000..6055fe3
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/rightbgtop.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/save.png b/filestoraging/filestorage/entry/src/main/resources/base/media/save.png
new file mode 100644
index 0000000..031ebb6
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/save.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/saveFormItem.png b/filestoraging/filestorage/entry/src/main/resources/base/media/saveFormItem.png
new file mode 100644
index 0000000..77d2d04
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/saveFormItem.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/saveLabel.png b/filestoraging/filestorage/entry/src/main/resources/base/media/saveLabel.png
new file mode 100644
index 0000000..09a6003
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/saveLabel.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/saveOccupy.png b/filestoraging/filestorage/entry/src/main/resources/base/media/saveOccupy.png
new file mode 100644
index 0000000..af529f2
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/saveOccupy.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/sky_blue_bg.png b/filestoraging/filestorage/entry/src/main/resources/base/media/sky_blue_bg.png
new file mode 100644
index 0000000..47abb3e
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/sky_blue_bg.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/media/startIcon.png b/filestoraging/filestorage/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000..366f764
Binary files /dev/null and b/filestoraging/filestorage/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/filestoraging/filestorage/entry/src/main/resources/base/profile/main_pages.json b/filestoraging/filestorage/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000..1898d94
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/filestoraging/filestorage/entry/src/main/resources/en_US/element/string.json b/filestoraging/filestorage/entry/src/main/resources/en_US/element/string.json
new file mode 100644
index 0000000..f945955
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/resources/en_US/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/main/resources/zh_CN/element/string.json b/filestoraging/filestorage/entry/src/main/resources/zh_CN/element/string.json
new file mode 100644
index 0000000..597ecf9
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/main/resources/zh_CN/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "模块描述"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/ohosTest/ets/test/Ability.test.ets b/filestoraging/filestorage/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000..8aa3749
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,35 @@
+import hilog from '@ohos.hilog';
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function abilityTest() {
+ describe('ActsAbilityTest', () => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ })
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ })
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ })
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ })
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ })
+ })
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/ohosTest/ets/test/List.test.ets b/filestoraging/filestorage/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000..794c7dc
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/ohosTest/ets/testability/TestAbility.ets b/filestoraging/filestorage/entry/src/ohosTest/ets/testability/TestAbility.ets
new file mode 100644
index 0000000..9484761
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/ets/testability/TestAbility.ets
@@ -0,0 +1,50 @@
+import UIAbility from '@ohos.app.ability.UIAbility';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import hilog from '@ohos.hilog';
+import { Hypium } from '@ohos/hypium';
+import testsuite from '../test/List.test';
+import window from '@ohos.window';
+import Want from '@ohos.app.ability.Want';
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+
+export default class TestAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
+ let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator;
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs;
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
+ hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
+ }
+
+ onDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
+ windowStage.loadContent('testability/pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
+ JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
+ }
+
+ onForeground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
+ }
+
+ onBackground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
+ }
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/ohosTest/ets/testability/pages/Index.ets b/filestoraging/filestorage/entry/src/ohosTest/ets/testability/pages/Index.ets
new file mode 100644
index 0000000..423b427
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/ets/testability/pages/Index.ets
@@ -0,0 +1,17 @@
+@Entry
+@Component
+struct Index {
+ @State message: string = 'Hello World';
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/filestoraging/filestorage/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
new file mode 100644
index 0000000..917d27a
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
@@ -0,0 +1,47 @@
+import hilog from '@ohos.hilog';
+import TestRunner from '@ohos.application.testRunner';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import Want from '@ohos.app.ability.Want';
+
+let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined
+let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined
+
+async function onAbilityCreateCallback() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
+}
+
+async function addAbilityMonitorCallback(err : Error) {
+ hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
+ }
+
+ async onRun() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ const bundleName = abilityDelegatorArguments.bundleName;
+ const testAbilityName = 'TestAbility';
+ let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ const want: Want = {
+ bundleName: bundleName,
+ abilityName: testAbilityName
+ };
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ abilityDelegator.startAbility(want, (err, data) => {
+ hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
+ hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? '');
+ })
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
+ }
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/ohosTest/module.json5 b/filestoraging/filestorage/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000..4fc9701
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "description": "$string:module_test_desc",
+ "mainElement": "TestAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:test_pages",
+ "abilities": [
+ {
+ "name": "TestAbility",
+ "srcEntry": "./ets/testability/TestAbility.ets",
+ "description": "$string:TestAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:TestAbility_label",
+ "exported": true,
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "skills": [
+ {
+ "actions": [
+ "action.system.home"
+ ],
+ "entities": [
+ "entity.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/filestoraging/filestorage/entry/src/ohosTest/resources/base/element/color.json b/filestoraging/filestorage/entry/src/ohosTest/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/ohosTest/resources/base/element/string.json b/filestoraging/filestorage/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000..65d8fa5
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_test_desc",
+ "value": "test ability description"
+ },
+ {
+ "name": "TestAbility_desc",
+ "value": "the test ability"
+ },
+ {
+ "name": "TestAbility_label",
+ "value": "test label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/ohosTest/resources/base/media/icon.png b/filestoraging/filestorage/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000..ce307a8
Binary files /dev/null and b/filestoraging/filestorage/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/filestoraging/filestorage/entry/src/ohosTest/resources/base/profile/test_pages.json b/filestoraging/filestorage/entry/src/ohosTest/resources/base/profile/test_pages.json
new file mode 100644
index 0000000..b7e7343
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/ohosTest/resources/base/profile/test_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "testability/pages/Index"
+ ]
+}
diff --git a/filestoraging/filestorage/entry/src/test/List.test.ets b/filestoraging/filestorage/entry/src/test/List.test.ets
new file mode 100644
index 0000000..bb5b5c3
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/test/List.test.ets
@@ -0,0 +1,5 @@
+import localUnitTest from './LocalUnit.test';
+
+export default function testsuite() {
+ localUnitTest();
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/entry/src/test/LocalUnit.test.ets b/filestoraging/filestorage/entry/src/test/LocalUnit.test.ets
new file mode 100644
index 0000000..ed22d4d
--- /dev/null
+++ b/filestoraging/filestorage/entry/src/test/LocalUnit.test.ets
@@ -0,0 +1,33 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function localUnitTest() {
+ describe('localUnitTest',() => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ });
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ });
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ });
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ });
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ });
+ });
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/hvigor/hvigor-config.json5 b/filestoraging/filestorage/hvigor/hvigor-config.json5
new file mode 100644
index 0000000..1a47490
--- /dev/null
+++ b/filestoraging/filestorage/hvigor/hvigor-config.json5
@@ -0,0 +1,18 @@
+{
+ "hvigorVersion": "3.0.9",
+ "dependencies": {
+ "@ohos/hvigor-ohos-plugin": "3.0.9"
+ },
+ "execution": {
+ // "daemon": true, /* Enable daemon compilation. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Default: false */
+ }
+}
diff --git a/filestoraging/filestorage/hvigor/hvigor-wrapper.js b/filestoraging/filestorage/hvigor/hvigor-wrapper.js
new file mode 100644
index 0000000..372eae8
--- /dev/null
+++ b/filestoraging/filestorage/hvigor/hvigor-wrapper.js
@@ -0,0 +1 @@
+"use strict";var u=require("path"),D=require("os"),e=require("fs"),t=require("crypto"),r=require("child_process"),n="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},i={},C={},F=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(C,"__esModule",{value:!0}),C.maxPathLength=C.isMac=C.isLinux=C.isWindows=void 0;const E=F(D),A="Windows_NT",o="Darwin";function a(){return E.default.type()===A}function c(){return E.default.type()===o}C.isWindows=a,C.isLinux=function(){return"Linux"===E.default.type()},C.isMac=c,C.maxPathLength=function(){return c()?1016:a()?259:4095},function(e){var t=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),r=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),i=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&t(D,u,e);return r(D,u),D};Object.defineProperty(e,"__esModule",{value:!0}),e.WORK_SPACE=e.HVIGOR_PROJECT_WRAPPER_HOME=e.HVIGOR_PROJECT_ROOT_DIR=e.HVIGOR_PROJECT_CACHES_HOME=e.HVIGOR_PNPM_STORE_PATH=e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=e.PROJECT_CACHES=e.HVIGOR_WRAPPER_TOOLS_HOME=e.HVIGOR_USER_HOME=e.DEFAULT_PACKAGE_JSON=e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME=e.PNPM=e.HVIGOR=e.NPM_TOOL=e.PNPM_TOOL=e.HVIGOR_ENGINE_PACKAGE_NAME=void 0;const F=i(D),E=i(u),A=C;e.HVIGOR_ENGINE_PACKAGE_NAME="@ohos/hvigor",e.PNPM_TOOL=(0,A.isWindows)()?"pnpm.cmd":"pnpm",e.NPM_TOOL=(0,A.isWindows)()?"npm.cmd":"npm",e.HVIGOR="hvigor",e.PNPM="pnpm",e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME="hvigor-config.json5",e.DEFAULT_PACKAGE_JSON="package.json",e.HVIGOR_USER_HOME=E.resolve(F.homedir(),".hvigor"),e.HVIGOR_WRAPPER_TOOLS_HOME=E.resolve(e.HVIGOR_USER_HOME,"wrapper","tools"),e.PROJECT_CACHES="project_caches",e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=E.resolve(e.HVIGOR_WRAPPER_TOOLS_HOME,"node_modules",".bin",e.PNPM_TOOL),e.HVIGOR_PNPM_STORE_PATH=E.resolve(e.HVIGOR_USER_HOME,"caches"),e.HVIGOR_PROJECT_CACHES_HOME=E.resolve(e.HVIGOR_USER_HOME,e.PROJECT_CACHES),e.HVIGOR_PROJECT_ROOT_DIR=process.cwd(),e.HVIGOR_PROJECT_WRAPPER_HOME=E.resolve(e.HVIGOR_PROJECT_ROOT_DIR,e.HVIGOR),e.WORK_SPACE="workspace"}(i);var s={},l={};Object.defineProperty(l,"__esModule",{value:!0}),l.logInfoPrintConsole=l.logErrorAndExit=void 0,l.logErrorAndExit=function(u){u instanceof Error?console.error(u.message):console.error(u),process.exit(-1)},l.logInfoPrintConsole=function(u){console.log(u)};var B=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),d=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),f=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&B(D,u,e);return d(D,u),D};Object.defineProperty(s,"__esModule",{value:!0});var _=s.executeBuild=void 0;const p=f(e),O=f(u),h=l;_=s.executeBuild=function(u){const D=O.resolve(u,"node_modules","@ohos","hvigor","bin","hvigor.js");try{const u=p.realpathSync(D);require(u)}catch(e){(0,h.logErrorAndExit)(`Error: ENOENT: no such file ${D},delete ${u} and retry.`)}};var P={},v={};!function(u){var D=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(u,"__esModule",{value:!0}),u.hashFile=u.hash=u.createHash=void 0;const r=D(t),i=D(e);u.createHash=(u="MD5")=>r.default.createHash(u);u.hash=(D,e)=>(0,u.createHash)(e).update(D).digest("hex");u.hashFile=(D,e)=>{if(i.default.existsSync(D))return(0,u.hash)(i.default.readFileSync(D,"utf-8"),e)}}(v);var g={},m={},R={};Object.defineProperty(R,"__esModule",{value:!0}),R.Unicode=void 0;class y{}R.Unicode=y,y.SPACE_SEPARATOR=/[\u1680\u2000-\u200A\u202F\u205F\u3000]/,y.ID_START=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/,y.ID_CONTINUE=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/,Object.defineProperty(m,"__esModule",{value:!0}),m.JudgeUtil=void 0;const I=R;m.JudgeUtil=class{static isIgnoreChar(u){return"string"==typeof u&&("\t"===u||"\v"===u||"\f"===u||" "===u||" "===u||"\ufeff"===u||"\n"===u||"\r"===u||"\u2028"===u||"\u2029"===u)}static isSpaceSeparator(u){return"string"==typeof u&&I.Unicode.SPACE_SEPARATOR.test(u)}static isIdStartChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||"$"===u||"_"===u||I.Unicode.ID_START.test(u))}static isIdContinueChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||u>="0"&&u<="9"||"$"===u||"_"===u||""===u||""===u||I.Unicode.ID_CONTINUE.test(u))}static isDigitWithoutZero(u){return/[1-9]/.test(u)}static isDigit(u){return"string"==typeof u&&/[0-9]/.test(u)}static isHexDigit(u){return"string"==typeof u&&/[0-9A-Fa-f]/.test(u)}};var N=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(g,"__esModule",{value:!0}),g.parseJsonText=g.parseJsonFile=void 0;const b=N(e),S=N(D),w=N(u),H=m;var x;!function(u){u[u.Char=0]="Char",u[u.EOF=1]="EOF",u[u.Identifier=2]="Identifier"}(x||(x={}));let M,T,V,G,j,J,W="start",U=[],L=0,$=1,k=0,K=!1,z="default",q="'",Z=1;function X(u,D=!1){T=String(u),W="start",U=[],L=0,$=1,k=0,G=void 0,K=D;do{M=Q(),nu[W]()}while("eof"!==M.type);return G}function Q(){for(z="default",j="",q="'",Z=1;;){J=Y();const u=Du[z]();if(u)return u}}function Y(){if(T[L])return String.fromCodePoint(T.codePointAt(L))}function uu(){const u=Y();return"\n"===u?($++,k=0):u?k+=u.length:k++,u&&(L+=u.length),u}g.parseJsonFile=function(u,D=!1,e="utf-8"){const t=b.default.readFileSync(w.default.resolve(u),{encoding:e});try{return X(t,D)}catch(D){if(D instanceof SyntaxError){const e=D.message.split("at");if(2===e.length)throw new Error(`${e[0].trim()}${S.default.EOL}\t at ${u}:${e[1].trim()}`)}throw new Error(`${u} is not in valid JSON/JSON5 format.`)}},g.parseJsonText=X;const Du={default(){switch(J){case"/":return uu(),void(z="comment");case void 0:return uu(),eu("eof")}if(!H.JudgeUtil.isIgnoreChar(J)&&!H.JudgeUtil.isSpaceSeparator(J))return Du[W]();uu()},start(){z="value"},beforePropertyName(){switch(J){case"$":case"_":return j=uu(),void(z="identifierName");case"\\":return uu(),void(z="identifierNameStartEscape");case"}":return eu("punctuator",uu());case'"':case"'":return q=J,uu(),void(z="string")}if(H.JudgeUtil.isIdStartChar(J))return j+=uu(),void(z="identifierName");throw Eu(x.Char,uu())},afterPropertyName(){if(":"===J)return eu("punctuator",uu());throw Eu(x.Char,uu())},beforePropertyValue(){z="value"},afterPropertyValue(){switch(J){case",":case"}":return eu("punctuator",uu())}throw Eu(x.Char,uu())},beforeArrayValue(){if("]"===J)return eu("punctuator",uu());z="value"},afterArrayValue(){switch(J){case",":case"]":return eu("punctuator",uu())}throw Eu(x.Char,uu())},end(){throw Eu(x.Char,uu())},comment(){switch(J){case"*":return uu(),void(z="multiLineComment");case"/":return uu(),void(z="singleLineComment")}throw Eu(x.Char,uu())},multiLineComment(){switch(J){case"*":return uu(),void(z="multiLineCommentAsterisk");case void 0:throw Eu(x.Char,uu())}uu()},multiLineCommentAsterisk(){switch(J){case"*":return void uu();case"/":return uu(),void(z="default");case void 0:throw Eu(x.Char,uu())}uu(),z="multiLineComment"},singleLineComment(){switch(J){case"\n":case"\r":case"\u2028":case"\u2029":return uu(),void(z="default");case void 0:return uu(),eu("eof")}uu()},value(){switch(J){case"{":case"[":return eu("punctuator",uu());case"n":return uu(),tu("ull"),eu("null",null);case"t":return uu(),tu("rue"),eu("boolean",!0);case"f":return uu(),tu("alse"),eu("boolean",!1);case"-":case"+":return"-"===uu()&&(Z=-1),void(z="numerical");case".":case"0":case"I":case"N":return void(z="numerical");case'"':case"'":return q=J,uu(),j="",void(z="string")}if(void 0===J||!H.JudgeUtil.isDigitWithoutZero(J))throw Eu(x.Char,uu());z="numerical"},numerical(){switch(J){case".":return j=uu(),void(z="decimalPointLeading");case"0":return j=uu(),void(z="zero");case"I":return uu(),tu("nfinity"),eu("numeric",Z*(1/0));case"N":return uu(),tu("aN"),eu("numeric",NaN)}if(void 0!==J&&H.JudgeUtil.isDigitWithoutZero(J))return j=uu(),void(z="decimalInteger");throw Eu(x.Char,uu())},zero(){switch(J){case".":case"e":case"E":return void(z="decimal");case"x":case"X":return j+=uu(),void(z="hexadecimal")}return eu("numeric",0)},decimalInteger(){switch(J){case".":case"e":case"E":return void(z="decimal")}if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},decimal(){switch(J){case".":j+=uu(),z="decimalFraction";break;case"e":case"E":j+=uu(),z="decimalExponent"}},decimalPointLeading(){if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalFraction");throw Eu(x.Char,uu())},decimalFraction(){switch(J){case"e":case"E":return j+=uu(),void(z="decimalExponent")}if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},decimalExponent(){switch(J){case"+":case"-":return j+=uu(),void(z="decimalExponentSign")}if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalExponentInteger");throw Eu(x.Char,uu())},decimalExponentSign(){if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalExponentInteger");throw Eu(x.Char,uu())},decimalExponentInteger(){if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},hexadecimal(){if(H.JudgeUtil.isHexDigit(J))return j+=uu(),void(z="hexadecimalInteger");throw Eu(x.Char,uu())},hexadecimalInteger(){if(!H.JudgeUtil.isHexDigit(J))return eu("numeric",Z*Number(j));j+=uu()},identifierNameStartEscape(){if("u"!==J)throw Eu(x.Char,uu());uu();const u=ru();switch(u){case"$":case"_":break;default:if(!H.JudgeUtil.isIdStartChar(u))throw Eu(x.Identifier)}j+=u,z="identifierName"},identifierName(){switch(J){case"$":case"_":case"":case"":return void(j+=uu());case"\\":return uu(),void(z="identifierNameEscape")}if(!H.JudgeUtil.isIdContinueChar(J))return eu("identifier",j);j+=uu()},identifierNameEscape(){if("u"!==J)throw Eu(x.Char,uu());uu();const u=ru();switch(u){case"$":case"_":case"":case"":break;default:if(!H.JudgeUtil.isIdContinueChar(u))throw Eu(x.Identifier)}j+=u,z="identifierName"},string(){switch(J){case"\\":return uu(),void(j+=function(){const u=Y(),D=function(){switch(Y()){case"b":return uu(),"\b";case"f":return uu(),"\f";case"n":return uu(),"\n";case"r":return uu(),"\r";case"t":return uu(),"\t";case"v":return uu(),"\v"}return}();if(D)return D;switch(u){case"0":if(uu(),H.JudgeUtil.isDigit(Y()))throw Eu(x.Char,uu());return"\0";case"x":return uu(),function(){let u="",D=Y();if(!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());if(u+=uu(),D=Y(),!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());return u+=uu(),String.fromCodePoint(parseInt(u,16))}();case"u":return uu(),ru();case"\n":case"\u2028":case"\u2029":return uu(),"";case"\r":return uu(),"\n"===Y()&&uu(),""}if(void 0===u||H.JudgeUtil.isDigitWithoutZero(u))throw Eu(x.Char,uu());return uu()}());case'"':case"'":if(J===q){const u=eu("string",j);return uu(),u}return void(j+=uu());case"\n":case"\r":case void 0:throw Eu(x.Char,uu());case"\u2028":case"\u2029":!function(u){console.warn(`JSON5: '${Fu(u)}' in strings is not valid ECMAScript; consider escaping.`)}(J)}j+=uu()}};function eu(u,D){return{type:u,value:D,line:$,column:k}}function tu(u){for(const D of u){if(Y()!==D)throw Eu(x.Char,uu());uu()}}function ru(){let u="",D=4;for(;D-- >0;){const D=Y();if(!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());u+=uu()}return String.fromCodePoint(parseInt(u,16))}const nu={start(){if("eof"===M.type)throw Eu(x.EOF);iu()},beforePropertyName(){switch(M.type){case"identifier":case"string":return V=M.value,void(W="afterPropertyName");case"punctuator":return void Cu();case"eof":throw Eu(x.EOF)}},afterPropertyName(){if("eof"===M.type)throw Eu(x.EOF);W="beforePropertyValue"},beforePropertyValue(){if("eof"===M.type)throw Eu(x.EOF);iu()},afterPropertyValue(){if("eof"===M.type)throw Eu(x.EOF);switch(M.value){case",":return void(W="beforePropertyName");case"}":Cu()}},beforeArrayValue(){if("eof"===M.type)throw Eu(x.EOF);"punctuator"!==M.type||"]"!==M.value?iu():Cu()},afterArrayValue(){if("eof"===M.type)throw Eu(x.EOF);switch(M.value){case",":return void(W="beforeArrayValue");case"]":Cu()}},end(){}};function iu(){const u=function(){let u;switch(M.type){case"punctuator":switch(M.value){case"{":u={};break;case"[":u=[]}break;case"null":case"boolean":case"numeric":case"string":u=M.value}return u}();if(K&&"object"==typeof u&&(u._line=$,u._column=k),void 0===G)G=u;else{const D=U[U.length-1];Array.isArray(D)?K&&"object"!=typeof u?D.push({value:u,_line:$,_column:k}):D.push(u):D[V]=K&&"object"!=typeof u?{value:u,_line:$,_column:k}:u}!function(u){if(u&&"object"==typeof u)U.push(u),W=Array.isArray(u)?"beforeArrayValue":"beforePropertyName";else{const u=U[U.length-1];W=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}}(u)}function Cu(){U.pop();const u=U[U.length-1];W=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}function Fu(u){const D={"'":"\\'",'"':'\\"',"\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\v":"\\v","\0":"\\0","\u2028":"\\u2028","\u2029":"\\u2029"};if(D[u])return D[u];if(u<" "){const D=u.charCodeAt(0).toString(16);return`\\x${`00${D}`.substring(D.length)}`}return u}function Eu(u,D){let e="";switch(u){case x.Char:e=void 0===D?`JSON5: invalid end of input at ${$}:${k}`:`JSON5: invalid character '${Fu(D)}' at ${$}:${k}`;break;case x.EOF:e=`JSON5: invalid end of input at ${$}:${k}`;break;case x.Identifier:k-=5,e=`JSON5: invalid identifier character at ${$}:${k}`}const t=new Au(e);return t.lineNumber=$,t.columnNumber=k,t}class Au extends SyntaxError{}var ou={},au=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),cu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),su=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&au(D,u,e);return cu(D,u),D},lu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(ou,"__esModule",{value:!0}),ou.isFileExists=ou.offlinePluginConversion=ou.executeCommand=ou.getNpmPath=ou.hasNpmPackInPaths=void 0;const Bu=r,du=lu(e),fu=su(u),_u=i,pu=l;ou.hasNpmPackInPaths=function(u,D){try{return require.resolve(u,{paths:[...D]}),!0}catch(u){return!1}},ou.getNpmPath=function(){const u=process.execPath;return fu.join(fu.dirname(u),_u.NPM_TOOL)},ou.executeCommand=function(u,D,e){0!==(0,Bu.spawnSync)(u,D,e).status&&(0,pu.logErrorAndExit)(`Error: ${u} ${D} execute failed.See above for details.`)},ou.offlinePluginConversion=function(u,D){return D.startsWith("file:")||D.endsWith(".tgz")?fu.resolve(u,_u.HVIGOR,D.replace("file:","")):D},ou.isFileExists=function(u){return du.default.existsSync(u)&&du.default.statSync(u).isFile()};var Ou=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),hu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),Pu=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&Ou(D,u,e);return hu(D,u),D},vu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(P,"__esModule",{value:!0});var gu=P.initProjectWorkSpace=void 0;const mu=Pu(e),Ru=vu(D),yu=Pu(u),Iu=v,Nu=i,bu=g,Su=l,wu=ou;let Hu,xu,Mu;function Tu(u,D,e){return void 0!==e.dependencies&&(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,D.dependencies[u])===yu.normalize(e.dependencies[u])}function Vu(){const u=yu.join(Mu,Nu.WORK_SPACE);if((0,Su.logInfoPrintConsole)("Hvigor cleaning..."),!mu.existsSync(u))return;const D=mu.readdirSync(u);if(!D||0===D.length)return;const e=yu.resolve(Mu,"node_modules","@ohos","hvigor","bin","hvigor.js");mu.existsSync(e)&&(0,wu.executeCommand)(process.argv[0],[e,"--stop-daemon"],{});try{D.forEach((D=>{mu.rmSync(yu.resolve(u,D),{recursive:!0})}))}catch(D){(0,Su.logErrorAndExit)(`The hvigor build tool cannot be installed. Please manually clear the workspace directory and synchronize the project again.\n\n Workspace Path: ${u}.`)}}gu=P.initProjectWorkSpace=function(){if(Hu=function(){const u=yu.resolve(Nu.HVIGOR_PROJECT_WRAPPER_HOME,Nu.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME);mu.existsSync(u)||(0,Su.logErrorAndExit)(`Error: Hvigor config file ${u} does not exist.`);return(0,bu.parseJsonFile)(u)}(),Mu=function(u){let D;D=function(u){let D=u.hvigorVersion;if(D.startsWith("file:")||D.endsWith(".tgz"))return!1;const e=u.dependencies,t=Object.getOwnPropertyNames(e);for(const u of t){const D=e[u];if(D.startsWith("file:")||D.endsWith(".tgz"))return!1}if(1===t.length&&"@ohos/hvigor-ohos-plugin"===t[0])return D>"2.5.0";return!1}(u)?function(u){let D=`${Nu.HVIGOR_ENGINE_PACKAGE_NAME}@${u.hvigorVersion}`;const e=u.dependencies;if(e){Object.getOwnPropertyNames(e).sort().forEach((u=>{D+=`,${u}@${e[u]}`}))}return(0,Iu.hash)(D)}(u):(0,Iu.hash)(process.cwd());return yu.resolve(Ru.default.homedir(),".hvigor","project_caches",D)}(Hu),xu=function(){const u=yu.resolve(Mu,Nu.WORK_SPACE,Nu.DEFAULT_PACKAGE_JSON);return mu.existsSync(u)?(0,bu.parseJsonFile)(u):{dependencies:{}}}(),!(0,wu.hasNpmPackInPaths)(Nu.HVIGOR_ENGINE_PACKAGE_NAME,[yu.join(Mu,Nu.WORK_SPACE)])||(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion)!==xu.dependencies[Nu.HVIGOR_ENGINE_PACKAGE_NAME]||!function(){function u(u){const D=null==u?void 0:u.dependencies;return void 0===D?0:Object.getOwnPropertyNames(D).length}const D=u(Hu),e=u(xu);if(D+1!==e)return!1;for(const u in null==Hu?void 0:Hu.dependencies)if(!(0,wu.hasNpmPackInPaths)(u,[yu.join(Mu,Nu.WORK_SPACE)])||!Tu(u,Hu,xu))return!1;return!0}()){Vu();try{!function(){(0,Su.logInfoPrintConsole)("Hvigor installing...");for(const u in Hu.dependencies)Hu.dependencies[u]&&(Hu.dependencies[u]=(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.dependencies[u]));const u={dependencies:{...Hu.dependencies}};u.dependencies[Nu.HVIGOR_ENGINE_PACKAGE_NAME]=(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion);const D=yu.join(Mu,Nu.WORK_SPACE);try{mu.mkdirSync(D,{recursive:!0});const e=yu.resolve(D,Nu.DEFAULT_PACKAGE_JSON);mu.writeFileSync(e,JSON.stringify(u))}catch(u){(0,Su.logErrorAndExit)(u)}(function(){const u=["config","set","store-dir",Nu.HVIGOR_PNPM_STORE_PATH],D={cwd:yu.join(Mu,Nu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,wu.executeCommand)(Nu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)})(),function(){const u=["install"],D={cwd:yu.join(Mu,Nu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,wu.executeCommand)(Nu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)}(),(0,Su.logInfoPrintConsole)("Hvigor install success.")}()}catch(u){Vu()}}return Mu};var Gu={};!function(t){var C=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),F=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),E=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&C(D,u,e);return F(D,u),D},A=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(t,"__esModule",{value:!0}),t.executeInstallPnpm=t.isPnpmInstalled=t.environmentHandler=t.checkNpmConifg=t.PNPM_VERSION=void 0;const o=r,a=E(e),c=A(D),s=E(u),B=i,d=l,f=ou;t.PNPM_VERSION="7.30.0",t.checkNpmConifg=function(){const u=s.resolve(B.HVIGOR_PROJECT_ROOT_DIR,".npmrc"),D=s.resolve(c.default.homedir(),".npmrc");if((0,f.isFileExists)(u)||(0,f.isFileExists)(D))return;const e=(0,f.getNpmPath)(),t=(0,o.spawnSync)(e,["config","get","prefix"],{cwd:B.HVIGOR_PROJECT_ROOT_DIR});if(0!==t.status||!t.stdout)return void(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.");const r=s.resolve(`${t.stdout}`.replace(/[\r\n]/gi,""),".npmrc");(0,f.isFileExists)(r)||(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.")},t.environmentHandler=function(){process.env["npm_config_update-notifier"]="false"},t.isPnpmInstalled=function(){return!!a.existsSync(B.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH)&&(0,f.hasNpmPackInPaths)("pnpm",[B.HVIGOR_WRAPPER_TOOLS_HOME])},t.executeInstallPnpm=function(){(0,d.logInfoPrintConsole)(`Installing pnpm@${t.PNPM_VERSION}...`);const u=(0,f.getNpmPath)();!function(){const u=s.resolve(B.HVIGOR_WRAPPER_TOOLS_HOME,B.DEFAULT_PACKAGE_JSON);try{a.existsSync(B.HVIGOR_WRAPPER_TOOLS_HOME)||a.mkdirSync(B.HVIGOR_WRAPPER_TOOLS_HOME,{recursive:!0});const D={dependencies:{}};D.dependencies[B.PNPM]=t.PNPM_VERSION,a.writeFileSync(u,JSON.stringify(D))}catch(D){(0,d.logErrorAndExit)(`Error: EPERM: operation not permitted,create ${u} failed.`)}}(),(0,f.executeCommand)(u,["install","pnpm"],{cwd:B.HVIGOR_WRAPPER_TOOLS_HOME,stdio:["inherit","inherit","inherit"],env:process.env}),(0,d.logInfoPrintConsole)("Pnpm install success.")}}(Gu),function(){Gu.checkNpmConifg(),Gu.environmentHandler(),Gu.isPnpmInstalled()||Gu.executeInstallPnpm();const D=gu();_(u.join(D,i.WORK_SPACE))}();
\ No newline at end of file
diff --git a/filestoraging/filestorage/hvigorfile.ts b/filestoraging/filestorage/hvigorfile.ts
new file mode 100644
index 0000000..f3cb9f1
--- /dev/null
+++ b/filestoraging/filestorage/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/filestoraging/filestorage/hvigorw b/filestoraging/filestorage/hvigorw
new file mode 100644
index 0000000..ff6a29a
--- /dev/null
+++ b/filestoraging/filestorage/hvigorw
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# ----------------------------------------------------------------------------
+# Hvigor startup script, version 1.0.0
+#
+# Required ENV vars:
+# ------------------
+# NODE_HOME - location of a Node home dir
+# or
+# Add /usr/local/nodejs/bin to the PATH environment variable
+# ----------------------------------------------------------------------------
+
+HVIGOR_APP_HOME="`pwd -P`"
+HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
+warn() {
+ echo ""
+ echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
+}
+
+error() {
+ echo ""
+ echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
+}
+
+fail() {
+ error "$@"
+ exit 1
+}
+
+# Determine node to start hvigor wrapper script
+if [ -n "${NODE_HOME}" ];then
+ EXECUTABLE_NODE="${NODE_HOME}/bin/node"
+ if [ ! -x "$EXECUTABLE_NODE" ];then
+ fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
+ fi
+else
+ EXECUTABLE_NODE="node"
+ which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path"
+fi
+
+# Check hvigor wrapper script
+if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then
+ fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
+fi
+
+# start hvigor-wrapper script
+exec "${EXECUTABLE_NODE}" \
+ "${HVIGOR_WRAPPER_SCRIPT}" "$@"
diff --git a/filestoraging/filestorage/hvigorw.bat b/filestoraging/filestorage/hvigorw.bat
new file mode 100644
index 0000000..d570007
--- /dev/null
+++ b/filestoraging/filestorage/hvigorw.bat
@@ -0,0 +1,64 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Hvigor startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
+set NODE_EXE=node.exe
+
+goto start
+
+:start
+@rem Find node.exe
+if defined NODE_HOME goto findNodeFromNodeHome
+
+%NODE_EXE% --version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
+echo.
+echo Please set the NODE_HOME variable in your environment to match the
+echo location of your NodeJs installation.
+
+goto fail
+
+:findNodeFromNodeHome
+set NODE_HOME=%NODE_HOME:"=%
+set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
+
+if exist "%NODE_EXE_PATH%" goto execute
+echo.
+echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
+echo.
+echo Please set the NODE_HOME variable in your environment to match the
+echo location of your NodeJs installation.
+
+goto fail
+
+:execute
+@rem Execute hvigor
+"%NODE_EXE%" "%WRAPPER_MODULE_PATH%" %*
+
+if "%ERRORLEVEL%" == "0" goto hvigorwEnd
+
+:fail
+exit /b 1
+
+:hvigorwEnd
+if "%OS%" == "Windows_NT" endlocal
+
+:end
diff --git a/filestoraging/filestorage/oh-package-lock.json5 b/filestoraging/filestorage/oh-package-lock.json5
new file mode 100644
index 0000000..ddc8a54
--- /dev/null
+++ b/filestoraging/filestorage/oh-package-lock.json5
@@ -0,0 +1,13 @@
+{
+ "lockfileVersion": 1,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hypium@1.0.11": "@ohos/hypium@1.0.11"
+ },
+ "packages": {
+ "@ohos/hypium@1.0.11": {
+ "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.11.tgz",
+ "integrity": "sha512-KawcLnv43C3QIYv1UbDnKCFX3MohtDxGuFvzlUxT/qf2DBilR56Ws6zrj90LdH6PjloJQwOPESuBQIHBACAK7w=="
+ }
+ }
+}
\ No newline at end of file
diff --git a/filestoraging/filestorage/oh-package.json5 b/filestoraging/filestorage/oh-package.json5
new file mode 100644
index 0000000..705bed2
--- /dev/null
+++ b/filestoraging/filestorage/oh-package.json5
@@ -0,0 +1,12 @@
+{
+ "license": "",
+ "devDependencies": {
+ "@ohos/hypium": "1.0.11"
+ },
+ "author": "",
+ "name": "filereality",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
diff --git a/macexesiming/README.md b/macexesiming/README.md
new file mode 100644
index 0000000..6825831
--- /dev/null
+++ b/macexesiming/README.md
@@ -0,0 +1,21 @@
+# macexesiming
+### 1、项目说明
+机器程序执行仿真项目开发的总体思路如图1.1示意,拟仿真4项内容:运算器的仿真、控制器的仿真、存储器的仿真和机器程序执行过程仿真,最终开发的程序可以由用户交互式操作(不用编写程序)来模拟体验CPU执行机器程序的过程。
+ 图1.1 项目开发的总体思路图
+
+
+
+### 2、开发环境说明
+(1)系统版本:OpenHarmony 4.0 Release
+(2)SDK版本:API 10
+(3)Model类型:Stage
+(4)DevEco Studio版本:Deveco Studio 4.0 release
+(5)硬件环境:Unionpi Whale、RK3566开发板
+(6)预览器参数:(1)DeviceType:default;(2)Resolution:560-1280;(3)DPI:240;其余参数自定。
+### 3、项目主要函数调用关系图与项目输出界面演进图
+ 图3.1 项目主要函数调用关系图
+
+
+
+ 图3.2 项目输出界面演进图
+
\ No newline at end of file
diff --git a/macexesiming/figs/evolution.png b/macexesiming/figs/evolution.png
new file mode 100644
index 0000000..d69f71e
Binary files /dev/null and b/macexesiming/figs/evolution.png differ
diff --git a/macexesiming/figs/overall.png b/macexesiming/figs/overall.png
new file mode 100644
index 0000000..8da81e0
Binary files /dev/null and b/macexesiming/figs/overall.png differ
diff --git a/macexesiming/figs/relation.png b/macexesiming/figs/relation.png
new file mode 100644
index 0000000..b99d6cc
Binary files /dev/null and b/macexesiming/figs/relation.png differ
diff --git a/macexesiming/macexesim/.gitignore b/macexesiming/macexesim/.gitignore
new file mode 100644
index 0000000..fbabf77
--- /dev/null
+++ b/macexesiming/macexesim/.gitignore
@@ -0,0 +1,11 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
\ No newline at end of file
diff --git a/macexesiming/macexesim/AppScope/app.json5 b/macexesiming/macexesim/AppScope/app.json5
new file mode 100644
index 0000000..c7fd83d
--- /dev/null
+++ b/macexesiming/macexesim/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.example.machineprogramexecutionsimulation",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
diff --git a/macexesiming/macexesim/AppScope/resources/base/element/string.json b/macexesiming/macexesim/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000..f9cee4a
--- /dev/null
+++ b/macexesiming/macexesim/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MachineProgramExecutionSimulation"
+ }
+ ]
+}
diff --git a/macexesiming/macexesim/AppScope/resources/base/media/app_icon.png b/macexesiming/macexesim/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/macexesiming/macexesim/AppScope/resources/base/media/app_icon.png differ
diff --git a/macexesiming/macexesim/build-profile.json5 b/macexesiming/macexesim/build-profile.json5
new file mode 100644
index 0000000..4532a29
--- /dev/null
+++ b/macexesiming/macexesim/build-profile.json5
@@ -0,0 +1,49 @@
+{
+ "app": {
+ "signingConfigs": [
+ {
+ "name": "default",
+ "material": {
+ "certpath": "C:\\Users\\admin\\.ohos\\config\\openharmony\\auto_ohos_default_MachineProgramExecutionSimulation_com.example.machineprogramexecutionsimulation.cer",
+ "storePassword": "0000001B625786EDC606E1C438A2723597B6D3BCB95F43E7C62B178B41DE67FFDF2CF75B80104801DEE7D5",
+ "keyAlias": "debugKey",
+ "keyPassword": "0000001BCCCFBCB4275109CACC0FC0ACBDC0FC34F067FC23653ABE87475A1EC6C3D662C75F1D7C581AC2CC",
+ "profile": "C:\\Users\\admin\\.ohos\\config\\openharmony\\auto_ohos_default_MachineProgramExecutionSimulation_com.example.machineprogramexecutionsimulation.p7b",
+ "signAlg": "SHA256withECDSA",
+ "storeFile": "C:\\Users\\admin\\.ohos\\config\\openharmony\\auto_ohos_default_MachineProgramExecutionSimulation_com.example.machineprogramexecutionsimulation.p12"
+ }
+ }
+ ],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 10,
+ "compatibleSdkVersion": 9,
+ "runtimeOS": "OpenHarmony",
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug",
+ },
+ {
+ "name": "release"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/.gitignore b/macexesiming/macexesim/entry/.gitignore
new file mode 100644
index 0000000..e2713a2
--- /dev/null
+++ b/macexesiming/macexesim/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/build-profile.json5 b/macexesiming/macexesim/entry/build-profile.json5
new file mode 100644
index 0000000..197e83c
--- /dev/null
+++ b/macexesiming/macexesim/entry/build-profile.json5
@@ -0,0 +1,31 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ "arkOptions": {
+ // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
+ }
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": true,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/hvigorfile.ts b/macexesiming/macexesim/entry/hvigorfile.ts
new file mode 100644
index 0000000..c6edcd9
--- /dev/null
+++ b/macexesiming/macexesim/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/macexesiming/macexesim/entry/obfuscation-rules.txt b/macexesiming/macexesim/entry/obfuscation-rules.txt
new file mode 100644
index 0000000..985b2ae
--- /dev/null
+++ b/macexesiming/macexesim/entry/obfuscation-rules.txt
@@ -0,0 +1,18 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/oh-package.json5 b/macexesiming/macexesim/entry/oh-package.json5
new file mode 100644
index 0000000..225946c
--- /dev/null
+++ b/macexesiming/macexesim/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "license": "",
+ "devDependencies": {},
+ "author": "",
+ "name": "entry",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
diff --git a/macexesiming/macexesim/entry/src/main/ets/classes/ALU.ets b/macexesiming/macexesim/entry/src/main/ets/classes/ALU.ets
new file mode 100644
index 0000000..06f9d01
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/classes/ALU.ets
@@ -0,0 +1,548 @@
+import CPU from './CPU'
+import {sleep} from '../utils/util'
+import * as CommonConstants from '../common/constants/CommonConstants'
+
+//ALU数据结构
+export default class ALU {
+ show(cpu:CPU,cv:CanvasRenderingContext2D){
+ if(cpu.ALUio["ALU_R1"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.ALU_R1(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.ALU_R1(cv,1)
+ }
+
+ if(cpu.ALUio["ALU_R2"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.ALU_R2(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.ALU_R2(cv,1)
+ }
+
+ if(cpu.ALUio["ALU_R3"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.ALU_R3(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.ALU_R3(cv,1)
+ }
+
+ if(cpu.ALUio["ALU_R4"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.ALU_R4(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.ALU_R4(cv,1)
+ }
+
+ if(cpu.ALUio["R1_ALU1"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.R1_ALU1(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.R1_ALU1(cv,1)
+ }
+
+ if(cpu.ALUio["R2_ALU1"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.R2_ALU1(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.R2_ALU1(cv,1)
+ }
+
+ if(cpu.ALUio["R3_ALU1"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.R3_ALU1(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.R3_ALU1(cv,1)
+ }
+
+ if(cpu.ALUio["R4_ALU1"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.R4_ALU1(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.R4_ALU1(cv,1)
+ }
+
+ if(cpu.ALUio["R1_ALU2"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.R1_ALU2(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.R1_ALU2(cv,1)
+ }
+
+ if(cpu.ALUio["R2_ALU2"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.R2_ALU2(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.R2_ALU2(cv,1)
+ }
+
+ if(cpu.ALUio["R3_ALU2"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.R3_ALU2(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.R3_ALU2(cv,1)
+ }
+
+ if(cpu.ALUio["R4_ALU2"]==false){
+ //如果ALUio中该线为False,则非高亮显示
+ this.R4_ALU2(cv,0)
+ }else{
+ //如果ALUio中该线为True,则高亮显示
+ this.R4_ALU2(cv,1)
+ }
+
+ if(cpu.ALUop['+']==true){
+ this.opa(cv)
+ }
+ if(cpu.ALUop['-']==true){
+ this.opb(cv)
+ }
+ if(cpu.ALUop['*']==true){
+ this.opc(cv)
+ }
+ if(cpu.ALUop['/']==true){
+ this.opd(cv)
+ }
+ }
+
+ line_init(cv:CanvasRenderingContext2D){
+ this.ALU_R1(cv,0)
+ this.ALU_R2(cv,0)
+ this.ALU_R3(cv,0)
+ this.ALU_R4(cv,0)
+ this.R1_ALU1(cv,0)
+ this.R2_ALU1(cv,0)
+ this.R3_ALU1(cv,0)
+ this.R4_ALU1(cv,0)
+ this.R1_ALU2(cv,0)
+ this.R2_ALU2(cv,0)
+ this.R3_ALU2(cv,0)
+ this.R4_ALU2(cv,0)
+ }
+
+ async mark(lines:Array){
+ for(let i=0;i<5;i++){
+ if(i){
+ await sleep(500)
+ }
+ if(i%2){
+ for(let l=0;l
+ SimMARK: Array
+ PC_int: number
+ IR_int: number
+ clostep: number
+ alu: number
+ code: number
+ R_int: Array
+ MAD_int: number
+ MCO_int: number
+
+ constructor() {
+ this.ALUio = {
+ 'ALU_R1': false,
+ 'ALU_R2': false,
+ 'ALU_R3': false,
+ 'ALU_R4': false,
+ 'R1_ALU1': false,
+ 'R2_ALU1': false,
+ 'R3_ALU1': false,
+ 'R4_ALU1': false,
+ 'R1_ALU2': false,
+ 'R2_ALU2': false,
+ 'R3_ALU2': false,
+ 'R4_ALU2': false
+ }
+ this.ALUop = { '+': false, '-': false, '*': false, '/': false }
+ this.clo = new Array(6)
+ this.clo = [1, 0, 0, 0, 0, 0]
+ this.SigObj = {
+ 'PC->Maddr': ['PC->Maddr', false, 'DataSig'],
+ 'SigCtrl->Memory': ['SigCtrl->Memory', false, 'CtrlSig'],
+ 'SigCtrl->IR': ['SigCtrl->IR', false, 'CtrlSig'],
+ 'IR->SigCtrl': ['IR->SigCtrl', false, 'CtrlSig'],
+ 'IR->Mcontent': ['IR->Mcontent', false, 'DataSig'],
+ 'Maddr->IR': ['Maddr->IR', false, 'DataSig'],
+ 'Mcontent->Memory': ['Mcontent->Memory', false, 'DataSig'],
+ 'Memory->Mcontent': ['Memory->Mcontent', false, 'DataSig'],
+ 'PC->SigCtrl': ['PC->SigCtrl', false, 'CtrlSig'],
+ 'SigCtrl->PC': ['SigCtrl->PC', false, 'CtrlSig'],
+ 'Mcontent_PC': ['Mcontent_PC', false, 'DataSig'],
+ 'IR->Maddr': ['IR->Maddr', false, 'DataSig'],
+ 'SigCtrl->R1': ['SigCtrl->R1', false, 'CtrlSig'],
+ 'SigCtrl->R2': ['SigCtrl->R2', false, 'CtrlSig'],
+ 'SigCtrl->R3': ['SigCtrl->R3', false, 'CtrlSig'],
+ 'SigCtrl->R4': ['SigCtrl->R4', false, 'CtrlSig'],
+ 'Mcontent->R1': ['Mcontent->R1', false, 'DataSig'],
+ 'Mcontent->R2': ['Mcontent->R2', false, 'DataSig'],
+ 'Mcontent->R3': ['Mcontent->R3', false, 'DataSig'],
+ 'Mcontent->R4': ['Mcontent->R4', false, 'DataSig'],
+ 'R1->Mcontent': ['R1->Mcontent', false, 'DataSig'],
+ 'R2->Mcontent': ['R2->Mcontent', false, 'DataSig'],
+ 'R3->Mcontent': ['R3->Mcontent', false, 'DataSig'],
+ 'R4->Mcontent': ['R4->Mcontent', false, 'DataSig'],
+ 'SigCtrl->ALU': ['SigCtrl->ALU', false, 'CtrlSig'],
+ }
+ this.SimMem = new Array(20)
+ for (let i = 0; i < 20; i++) {
+ this.SimMem[i] = '0000000000000000'
+ }
+ this.SimMARK = new Array(20)
+ for (let i = 0; i < 20; i++) {
+ this.SimMARK.push(false)
+ }
+ this.PC_int = 0
+ this.IR_int = 0
+ this.clostep = 0
+ this.alu = 0
+ this.code = 0
+ this.R_int = new Array(4)
+ for (let i = 0; i < 4; i++) {
+ let randomNum = Math.floor(Math.random() * 65536)
+ this.R_int[i] = randomNum
+ }
+ this.MAD_int = 0
+ this.MCO_int = 0
+ }
+
+ //重置CPU
+ reset() {
+ this.ALUio = {
+ 'ALU_R1': false,
+ 'ALU_R2': false,
+ 'ALU_R3': false,
+ 'ALU_R4': false,
+ 'R1_ALU1': false,
+ 'R2_ALU1': false,
+ 'R3_ALU1': false,
+ 'R4_ALU1': false,
+ 'R1_ALU2': false,
+ 'R2_ALU2': false,
+ 'R3_ALU2': false,
+ 'R4_ALU2': false
+ }
+ this.ALUop = { '+': false, '-': false, '*': false, '/': false }
+ this.clo = [0, 0, 0, 0, 0, 0]
+ this.SigObj = {
+ 'PC->Maddr': ['PC->Maddr', false, 'DataSig'],
+ 'SigCtrl->Memory': ['SigCtrl->Memory', false, 'CtrlSig'],
+ 'SigCtrl->IR': ['SigCtrl->IR', false, 'CtrlSig'],
+ 'IR->SigCtrl': ['IR->SigCtrl', false, 'CtrlSig'],
+ 'IR->Mcontent': ['IR->Mcontent', false, 'DataSig'],
+ 'Maddr->IR': ['Maddr->IR', false, 'DataSig'],
+ 'Mcontent->Memory': ['Mcontent->Memory', false, 'DataSig'],
+ 'Memory->Mcontent': ['Memory->Mcontent', false, 'DataSig'],
+ 'PC->SigCtrl': ['PC->SigCtrl', false, 'CtrlSig'],
+ 'SigCtrl->PC': ['SigCtrl->PC', false, 'CtrlSig'],
+ 'Mcontent_PC': ['Mcontent_PC', false, 'DataSig'],
+ 'IR->Maddr': ['IR->Maddr', false, 'DataSig'],
+ 'SigCtrl->R1': ['SigCtrl->R1', false, 'CtrlSig'],
+ 'SigCtrl->R2': ['SigCtrl->R2', false, 'CtrlSig'],
+ 'SigCtrl->R3': ['SigCtrl->R3', false, 'CtrlSig'],
+ 'SigCtrl->R4': ['SigCtrl->R4', false, 'CtrlSig'],
+ 'Mcontent->R1': ['Mcontent->R1', false, 'DataSig'],
+ 'Mcontent->R2': ['Mcontent->R2', false, 'DataSig'],
+ 'Mcontent->R3': ['Mcontent->R3', false, 'DataSig'],
+ 'Mcontent->R4': ['Mcontent->R4', false, 'DataSig'],
+ 'R1->Mcontent': ['R1->Mcontent', false, 'DataSig'],
+ 'R2->Mcontent': ['R2->Mcontent', false, 'DataSig'],
+ 'R3->Mcontent': ['R3->Mcontent', false, 'DataSig'],
+ 'R4->Mcontent': ['R4->Mcontent', false, 'DataSig'],
+ 'SigCtrl->ALU': ['SigCtrl->ALU', false, 'CtrlSig'],
+ }
+ for (let i = 0; i < 20; i++) {
+ this.SimMem[i] = '0000000000000000'
+ }
+ for (let i = 0; i < 20; i++) {
+ this.SimMARK.push(false)
+ }
+ this.PC_int = 0
+ this.IR_int = 0
+ this.clostep = 0
+ this.alu = 0
+ this.code = 0
+ for (let i = 0; i < 4; i++) {
+ let randomNum = Math.floor(Math.random() * 65536)
+ this.R_int[i] = randomNum
+ }
+ this.MAD_int = 0
+ this.MCO_int = 0
+ }
+
+ Sim_init() {
+ if (0) {
+ // # 如果SimMem存在则说明已经初始化完毕,不做操作
+ } else {
+ // # 如果SimMem不存在则说明未初始化,则将存储器所有值初始为0000000000000000
+ let SimMem = []
+ for (let i = 0; i < 20; i++) {
+ SimMem.push('0000000000000000')
+ }
+ }
+ }
+
+ CODE() {
+ return Bin(this.code, 6)
+ }
+
+ PC() {
+ let ans = Bin(this.PC_int, 16)
+ let pc = ''
+ for (let i = 0; i < 8; i++) {
+ pc += ans[i]
+ }
+ pc += ' '
+ for (let i = 0; i < 8; i++) {
+ pc += ans[i+8]
+ }
+ return pc
+ }
+
+ IR() {
+ let ans = Bin(this.IR_int, 16)
+ let ir = ''
+ for (let i = 0; i < 8; i++) {
+ ir += ans[i]
+ }
+ ir += ' '
+ for (let i = 0; i < 8; i++) {
+ ir += ans[i+8]
+ }
+ return ir
+ }
+
+ async CLO(num: number) {
+ this.clostep = num
+ for (let i = 0; i < 6; i++) {
+ this.clo[i] = false
+ }
+ this.clo[this.clostep] = true
+ }
+
+ ALU() {
+ let AL = ['无', '+', '-', 'x', '÷']
+ return AL[this.alu]
+ }
+
+ R(num: number) {
+ return Bin(this.R_int[num], 16)
+ }
+
+ MAD() {
+ let sum = Bin(this.MAD_int, 16)
+ let ans = ''
+ for (let i = 0; i < 8; i++) {
+ ans += sum[i]
+ }
+ ans += ' '
+ for (let i = 0; i < 8; i++) {
+ ans += sum[i+8]
+ }
+ return ans
+ }
+
+ MCO() {
+ let sum = Bin(this.MCO_int, 16)
+ let ans = ''
+ for (let i = 0; i < 8; i++) {
+ ans += sum[i]
+ }
+ ans += ' '
+ for (let i = 0; i < 8; i++) {
+ ans += sum[i+8]
+ }
+ return ans
+ }
+
+ async str_int(ans: string) {
+ if (ans[0] == ' ') {
+ return -1
+ }
+ let sum = 0
+ for (let i = 0; i < ans.length; i++) {
+ if (ans[i] == ' ') {
+ continue
+ }
+ sum *= 2
+ sum += Number(ans[i])
+ }
+ return sum
+ }
+}
+
diff --git a/macexesiming/macexesim/entry/src/main/ets/classes/Clock.ets b/macexesiming/macexesim/entry/src/main/ets/classes/Clock.ets
new file mode 100644
index 0000000..45807f7
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/classes/Clock.ets
@@ -0,0 +1,75 @@
+import CPU from './CPU'
+
+//时钟数据结构
+export default class Clock {
+ R:number
+ x0:number
+ y0:number
+ dx:number
+
+ constructor() {
+ this.R=10
+ this.x0=20
+ this.y0=30
+ this.dx=25
+ }
+
+ //依据ClockStep[]的值显示时钟元素
+ async clo_mark(cpu:CPU,cv:CanvasRenderingContext2D){
+ //遍历六个时钟刻,绘制各个时钟
+ for(let i=0;i<6;i++) {
+ //绘制时钟圆圈
+ cv.beginPath()
+ cv.strokeStyle='15px'
+ cv.arc(i*this.dx+this.x0,this.y0,this.R,0,6.28)
+ cv.stroke()
+ cv.closePath()
+ if(cpu.clo[i]==true){
+ //如果存储结构中clo[i]为1,则该时钟高亮显示
+ cv.beginPath()
+ cv.fillStyle='#ff0000'
+ cv.arc(i*this.dx+this.x0,this.y0,this.R,0,6.28)
+ cv.fill()
+ cv.closePath()
+ }else{
+ //如果存储结构中clo[i]为0,则该时钟正常显示
+ cv.beginPath()
+ cv.fillStyle='#ffffff'
+ cv.arc(i*this.dx+this.x0,this.y0,this.R,0,6.28)
+ cv.fill()
+ cv.closePath()
+ }
+ }
+ //绘制文字
+ cv.beginPath()
+ cv.font ='45px';
+ cv.fillStyle='#000000'
+ cv.fillText('1',15,35)
+ cv.fillText('2',40,35)
+ cv.fillText('3',65,35)
+ cv.fillText('4',90,35)
+ cv.fillText('5',115,35)
+ cv.fillText('6',140,35)
+ cv.fill()
+ cv.closePath()
+ }
+
+
+ // 实现仿真控制器的各个屏幕元素,同时依据ClockStep[]的值显示节拍元素
+ async init(cpu:CPU,cv:CanvasRenderingContext2D){
+ //绘制PC和IR
+ cv.beginPath()
+ cv.fillStyle='#00ffff'
+ cv.font ='40px';
+ //清除先前的数据
+ cv.clearRect(170,25,125,20)
+ cv.clearRect(170,75,125,20)
+
+ cv.fillText(String(cpu.PC()),170,35)
+ cv.fillText(String(cpu.IR()),170,85)
+ cv.fill()
+ cv.closePath()
+ //绘制时钟
+ await this.clo_mark(cpu,cv)
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/ets/classes/ExecInstructWithAnim.ets b/macexesiming/macexesim/entry/src/main/ets/classes/ExecInstructWithAnim.ets
new file mode 100644
index 0000000..4f3702a
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/classes/ExecInstructWithAnim.ets
@@ -0,0 +1,787 @@
+import CPU from './CPU'
+import Clock from './Clock'
+import SIG from './SIG'
+import MEMORY from './MEMORY'
+import ALU from './ALU'
+import Line from './Line'
+import {Bin,sleep,init} from '../utils/util'
+import * as CommonConstants from '../common/constants/CommonConstants'
+
+//执行指令(带UI)
+export default class ExecInstructWithAnim {
+ play: number
+ outArray:Array
+ SimInstrCtrl:object[]
+ command:string[] = ['取指令', '取数指令', '存数指令', '加法指令', '乘法指令', '打印指令', '停机指令', '减法指令', '除法指令', '跳转指令']
+
+ constructor() {
+ this.outArray=new Array(0) //初始化综合输出框
+ this.play=0//初始化程序运行状态
+ this.SimInstrCtrl=new Array(0)//初始化指令集数组
+ }
+
+ async step_run(cpu:CPU,cl:Clock,si:SIG,mem:MEMORY,alu:ALU,line:Line){
+ let cur_clock=-1
+ while(this.SimInstrCtrl.length){
+ await sleep(500)
+ let cur_step=this.SimInstrCtrl.pop()//取出下一条指令
+ if(cur_clock==-1){//记录当前运行的时钟刻
+ cur_clock=cur_step[1]
+ }else{//若时钟刻与记录的时钟刻不同则暂停程序的运行,等待下一次操作
+ if(cur_clock!=cur_step[1]){
+ this.SimInstrCtrl.push(cur_step)
+ this.play=0
+ break
+ }
+ }
+ await cpu.CLO(cur_step[1]-1)//根据指令设置时钟刻
+ await cl.clo_mark(cpu,CommonConstants.CPUContext)//显示当前时钟时刻
+ // 执行当前指令
+ if(cur_step[2]=='this.PC_Maddr()'){
+ await this.PC_Maddr(cpu,si,mem,line)
+ }else if(cur_step[2]=='this.SimSigCtrl_Memory()'){
+ await this.SimSigCtrl_Memory(si,line)
+ }else if(cur_step[2]=='this.SimMaddr_Memory()'){
+ await this.SimMaddr_Memory(cpu,line,mem)
+ }else if(cur_step[2]=='this.SimMemory_Mcontent()'){
+ await this.SimMemory_Mcontent(line,cpu,mem)
+ }else if(cur_step[2]=='this.SimSigCtrl_IR()'){
+ await this.SimSigCtrl_IR(si,line)
+ }else if(cur_step[2]=='this.SimMcontent_IR()'){
+ await this.SimMcontent_IR(line,cpu,si,cl)
+ }else if(cur_step[2]=='this.SimIR_SigCtrl()'){
+ await this.SimIR_SigCtrl(line,cpu,si)
+ }else if(cur_step[2]=='this.SimPC_1()'){
+ await this.SimPC_1(si,line,cpu,cl)
+ }else if(cur_step[2]=='this.Showget()'){
+ await this.Showget(cpu)
+ }else if(cur_step[2]=='this.SimIR_Maddr()'){
+ await this.SimIR_Maddr(line,cpu,mem,si)
+ }else if(cur_step[2]=='this.SimSigCtrl_Memory()'){
+ await this.SimSigCtrl_Memory(si,line)
+ }else if(cur_step[2]=='this.SimMaddr_Memory()'){
+ await this.SimMaddr_Memory(cpu,line,mem)
+ }else if(cur_step[2]=='this.SimMemory_Mcontent()'){
+ await this.SimMemory_Mcontent(line,cpu,mem)
+ }else if(cur_step[2]=='this.SimSigCtrl_R('+ String(Math.floor(cpu.code/16)) +' )'){
+ this.SimSigCtrl_R(Math.floor(cpu.code/16),si,line,cpu)
+ }else if(cur_step[2]=='this.SimMcontent_R('+ String(Math.floor(cpu.code/16)) +')'){
+ this.SimMcontent_R(cpu,alu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.ShowSimget('+ String(Math.floor(cpu.code/16)) +')'){
+ this.ShowSimget(cpu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimMcontent_Memory()'){
+ await this.SimMcontent_Memory(line,cpu,mem)
+ }else if(cur_step[2]=='this.SimSigCtrl_ALU'){
+ await this.SimSigCtrl_ALU(si,line)
+ }else if(cur_step[2]=='this.ShowPrint()'){
+ await this.ShowPrint(cpu)
+ }else if(cur_step[2]=='this.ShowStop()'){
+ await this.ShowStop(cpu)
+ }else if(cur_step[2]=='this.SimSigCtrl_ALU'){
+ await this.SimSigCtrl_ALU(si,line)
+ }else if(cur_step[2]=='this.SimSigCtrl_PC()'){
+ await this.SimSigCtrl_PC(si,line)
+ }else if(cur_step[2]=='this.SimMcontent_PC()'){
+ await this.SimMcontent_PC(line,cpu,si)
+ }else if(cur_step[2]=='this.ShowSimGoto()'){
+ await this.ShowSimGoto(cpu)
+ } else if(cur_step[2]=='this.SimMcontent_R(' + String(Math.floor(cpu.code/16) + 1) + ')'){
+ await this.SimMcontent_R(cpu,alu,Math.floor(cpu.code/16) + 1)
+ }else if(cur_step[2]=='this.SimR_ALU1(' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimR_ALU1(alu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimR_ALU2(' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimR_ALU2(alu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='SimALU_R("/",' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimALU_R(alu,cpu,'/',Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.ShowSimDiv(' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.ShowSimDiv(cpu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimMcontent_R(' + String(Math.floor(cpu.code/16) + 1) + ')'){
+ await this.SimMcontent_R(cpu,alu,Math.floor(cpu.code/16)+1)
+ }else if(cur_step[2]=='this.SimALU_R("-",' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimALU_R(alu,cpu,'-',Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimALU_R("*",' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimALU_R(alu,cpu,'*',Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.ShowSimAddr(' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.ShowSimAddr(cpu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimR_Mcontent(' + String(Math.floor(cpu.code/16) + 1) + ')'){
+ await this.SimR_Mcontent(line,cpu,mem,alu,Math.floor(cpu.code/16)+1)
+ }else if(cur_step[2]=='this.ShowSimPut(' + String(Math.floor(cpu.code/16) + 1) + ')'){
+ await this.ShowSimPut(cpu,Math.floor(cpu.code/16)+1)
+ }
+ let clo=0
+ for(let i=0;i<6;i++){
+ if(cpu.clo[i]){
+ clo=i
+ break
+ }
+ }
+ CommonConstants.ShowContext.beginPath()
+ //当前节拍
+ CommonConstants.ShowContext.font='45px'
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(75,0,40,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText((clo+1).toString(),90,15)
+ //当前操作码
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(0,40,150,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText(cpu.CODE(),53,55)
+ //正在执行指令
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(0,80,150,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText(this.command[cpu.code%16],53,95)
+ CommonConstants.ShowContext.closePath()
+
+ }
+ if(this.play){//若没有停机,解析当前指令
+ await this.solve_step(cpu,cl,si,mem,alu,line)
+ }
+ }
+
+ //解析一条指令并将解析后的步骤加入到self.SimInstrCtrl中
+ async solve_step(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,line:Line){
+ if(this.play==0){
+ return
+ }
+ let code=cpu.code
+ if(code==0){//000000取指令
+ await this.get()
+ }else if (code % 16 == 1) { //000001取数指令(R1)
+ await this.SimGet(Math.floor(code/16))
+ } else if (code % 16 == 2) { //000010存数指令(R1)
+ await this.SimPut(Math.floor(code/16))
+ } else if (code % 16 == 3) { //000011加法指令 op = 0(R1)
+ await this.SimAddr(Math.floor(code/16))
+ } else if (code % 16 == 4) { //000100乘法指令 op = 2
+ await this.SimProduct(Math.floor(code/16))
+ } else if (code % 16 == 5) { //打印指令000101
+ await this.SimPrint()
+ } else if (code % 16 == 6) { //停机指令000110
+ await this.SimStop()
+ } else if (code % 16 == 7) { //000111减法指令 op = 1
+ await this.SimMinus(Math.floor(code/16))
+ } else if (code % 16 == 8) { //001000除法指令 op = 3
+ await this.SimDiv(Math.floor(code/16))
+ } else if(code % 16 == 9){//001001跳转指令Simgoto
+ this.SimGoto()
+ }else{//无法解析指令视为停机指令
+ await this.SimStop()
+ }
+ await si.init(cpu,CommonConstants.CPUContext)
+ await this.step_run(cpu,clo,si,mem,alu,line)
+ }
+
+ async clock(cpu:CPU,clo:Clock,n: number) {
+ await cpu.CLO(n - 1) //更改cpu内时钟刻的信息
+ await clo.clo_mark(cpu,CommonConstants.CPUContext)//根据cpu显示时钟刻
+ await sleep(500)
+ }
+
+ async print_mark(lines:Array){
+ for(let l=0;l')+'\n')//显示综合输出框
+ await sleep(200)
+ }
+ }
+
+ //执行指令
+ async exec_instruct_with_anim(cpu:CPU,cl:Clock,si:SIG,mem:MEMORY,alu:ALU,line:Line) {
+ while (this.SimInstrCtrl.length) {//逐个取出指令集的指令并且执行
+ await sleep(500)//等待一段时间
+ let cur_step=this.SimInstrCtrl.pop()//取出下一条指令
+ cpu.CLO(cur_step[1]-1)//根据指令设置时钟刻
+ cl.clo_mark(cpu,CommonConstants.CPUContext)
+ // 执行当前指令
+ if(cur_step[2]=='this.PC_Maddr()'){
+ await this.PC_Maddr(cpu,si,mem,line)
+ }else if(cur_step[2]=='this.SimSigCtrl_Memory()'){
+ await this.SimSigCtrl_Memory(si,line)
+ }else if(cur_step[2]=='this.SimMaddr_Memory()'){
+ await this.SimMaddr_Memory(cpu,line,mem)
+ }else if(cur_step[2]=='this.SimMemory_Mcontent()'){
+ await this.SimMemory_Mcontent(line,cpu,mem)
+ }else if(cur_step[2]=='this.SimSigCtrl_IR()'){
+ await this.SimSigCtrl_IR(si,line)
+ }else if(cur_step[2]=='this.SimMcontent_IR()'){
+ await this.SimMcontent_IR(line,cpu,si,cl)
+ }else if(cur_step[2]=='this.SimIR_SigCtrl()'){
+ await this.SimIR_SigCtrl(line,cpu,si)
+ }else if(cur_step[2]=='this.SimPC_1()'){
+ await this.SimPC_1(si,line,cpu,cl)
+ }else if(cur_step[2]=='this.Showget()'){
+ await this.Showget(cpu)
+ }else if(cur_step[2]=='this.SimIR_Maddr()'){
+ await this.SimIR_Maddr(line,cpu,mem,si)
+ }else if(cur_step[2]=='this.SimSigCtrl_Memory()'){
+ await this.SimSigCtrl_Memory(si,line)
+ }else if(cur_step[2]=='this.SimMaddr_Memory()'){
+ await this.SimMaddr_Memory(cpu,line,mem)
+ }else if(cur_step[2]=='this.SimMemory_Mcontent()'){
+ await this.SimMemory_Mcontent(line,cpu,mem)
+ }else if(cur_step[2]=='this.SimSigCtrl_R('+ String(Math.floor(cpu.code/16)) +' )'){
+ this.SimSigCtrl_R(Math.floor(cpu.code/16),si,line,cpu)
+ }else if(cur_step[2]=='this.SimMcontent_R('+ String(Math.floor(cpu.code/16)) +')'){
+ this.SimMcontent_R(cpu,alu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.ShowSimget('+ String(Math.floor(cpu.code/16)) +')'){
+ this.ShowSimget(cpu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimMcontent_Memory()'){
+ await this.SimMcontent_Memory(line,cpu,mem)
+ }else if(cur_step[2]=='this.SimSigCtrl_ALU'){
+ await this.SimSigCtrl_ALU(si,line)
+ }else if(cur_step[2]=='this.ShowPrint()'){
+ await this.ShowPrint(cpu)
+ }else if(cur_step[2]=='this.ShowStop()'){
+ await this.ShowStop(cpu)
+ }else if(cur_step[2]=='this.SimSigCtrl_ALU'){
+ await this.SimSigCtrl_ALU(si,line)
+ }else if(cur_step[2]=='this.SimSigCtrl_PC()'){
+ await this.SimSigCtrl_PC(si,line)
+ }else if(cur_step[2]=='this.SimMcontent_PC()'){
+ await this.SimMcontent_PC(line,cpu,si)
+ }else if(cur_step[2]=='this.ShowSimGoto()'){
+ await this.ShowSimGoto(cpu)
+ } else if(cur_step[2]=='this.SimMcontent_R(' + String(Math.floor(cpu.code/16) + 1) + ')'){
+ await this.SimMcontent_R(cpu,alu,Math.floor(cpu.code/16) + 1)
+ }else if(cur_step[2]=='this.SimR_ALU1(' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimR_ALU1(alu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimR_ALU2(' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimR_ALU2(alu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='SimALU_R("/",' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimALU_R(alu,cpu,'/',Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.ShowSimDiv(' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.ShowSimDiv(cpu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimMcontent_R(' + String(Math.floor(cpu.code/16) + 1) + ')'){
+ await this.SimMcontent_R(cpu,alu,Math.floor(cpu.code/16)+1)
+ }else if(cur_step[2]=='this.SimALU_R("-",' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimALU_R(alu,cpu,'-',Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimALU_R("*",' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.SimALU_R(alu,cpu,'*',Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.ShowSimAddr(' + String(Math.floor(cpu.code/16)) + ')'){
+ await this.ShowSimAddr(cpu,Math.floor(cpu.code/16))
+ }else if(cur_step[2]=='this.SimR_Mcontent(' + String(Math.floor(cpu.code/16) + 1) + ')'){
+ await this.SimR_Mcontent(line,cpu,mem,alu,Math.floor(cpu.code/16)+1)
+ }else if(cur_step[2]=='this.ShowSimPut(' + String(Math.floor(cpu.code/16) + 1) + ')'){
+ await this.ShowSimPut(cpu,Math.floor(cpu.code/16)+1)
+ }
+ let clo=0
+ for(let i=0;i<6;i++){
+ if(cpu.clo[i]){
+ clo=i
+ break
+ }
+ }
+ CommonConstants.ShowContext.beginPath()
+ //当前节拍
+ CommonConstants.ShowContext.font='45px'
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(75,0,40,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText((clo+1).toString(),90,15)
+ //当前操作码
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(0,40,150,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText(cpu.CODE(),53,55)
+ //正在执行指令
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(0,80,150,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText(this.command[cpu.code%16],53,95)
+ CommonConstants.ShowContext.closePath()
+ }
+ if(this.play){//若没有停机,解析当前指令
+ await this.solve(cpu,cl,si,mem,alu,line)
+ }
+ }
+
+ out_clear(){
+ let len=this.outArray.length
+ for(let i=0;iSigCtrl
+ this.SimInstrCtrl.push(['000000',2,'this.SimMcontent_IR()'])//Mcontent->IR
+ this.SimInstrCtrl.push(['000000',2,'this.SimSigCtrl_IR()'])// SigCtrl->IR
+ this.SimInstrCtrl.push(['000000',2,'this.SimMemory_Mcontent()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['000000',2,'this.SimMaddr_Memory()'])//Maddr->Memory
+ this.SimInstrCtrl.push(['000000',1,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['000000',1,'this.PC_Maddr()'])//PC->Maddr
+ }
+
+ async SimIR_Maddr(line:Line,cpu:CPU,mem:MEMORY,si:SIG){
+ await line.mark(['IR_MAD'])
+ let IR=cpu.IR()
+ let sum=0
+ for(let i=0;i<11;i++){
+ if(IR[i+6]==' '){
+ continue
+ }
+ sum*=2
+ sum+=Number(IR[i+6])
+ }
+ // # 将IR的后六位(操作对应的存储单元地址)取到Maddr中
+ cpu.MAD_int=sum
+ await mem.show(cpu,CommonConstants.MEMContext)
+ await si.init(cpu,CommonConstants.CPUContext)
+ }
+
+ async SimSigCtrl_R(n:number,si:SIG,line:Line,cpu:CPU){
+ // # SIG通知R1接受数据
+ if(n==0){
+ await si.R1(CommonConstants.CPUContext,1)
+ await line.mark(['SIG_R1','MCO_R1'])
+ }else if(n==1){
+ await si.R2(CommonConstants.CPUContext,1)
+ await line.mark(['SIG_R2','MCO_R2'])
+ }else if(n==2){
+ await si.R3(CommonConstants.CPUContext,1)
+ await line.mark(['SIG_R3','MCO_R3'])
+ }else if(n==3){
+ await si.R4(CommonConstants.CPUContext,1)
+ await line.mark(['SIG_R4','MCO_R4'])
+ }
+
+ await sleep(500)
+ if(n==0){
+ await si.R1(CommonConstants.CPUContext,0)
+ }else if(n==1){
+ await si.R2(CommonConstants.CPUContext,0)
+ }else if(n==2){
+ await si.R3(CommonConstants.CPUContext,0)
+ }else if(n==3){
+ await si.R4(CommonConstants.CPUContext,0)
+ }
+ await si.init(cpu,CommonConstants.CPUContext)
+ }
+
+ async SimMcontent_R(cpu:CPU,alu:ALU,n:number){
+ // # 将Mcontent中的数字存到R中
+ cpu.R_int[n]=cpu.MCO_int
+ await alu.init(cpu,CommonConstants.ALUContext)
+ }
+
+ async ShowSimget(cpu:CPU,n:number){
+ this.outArray.push('取数指令:' + '\n')
+ this.outArray.push('SimMem[' + String(cpu.MAD_int) + '] -> R' + String(n + 1) + '\n')
+ cpu.code=0
+ }
+
+ async SimGet(n:number){
+ // # 000001取数指令(R1) n = 0
+ // # 010001取数指令(R2) n = 1
+ // # 100001取数指令(R3) n = 2
+ // # 110001取数指令(R4) n = 3
+ this.SimInstrCtrl.push(['000001',4,'this.ShowSimget('+String(n)+')'])//显示信息到输出框
+ this.SimInstrCtrl.push(['000001',4,'this.SimMcontent_R('+String(n)+')'])//Mcontent->Rn
+ this.SimInstrCtrl.push(['000001',4,'this.SimSigCtrl_R('+String(n)+')'])// SigCtrl->Rn
+ this.SimInstrCtrl.push(['000001',4,'this.SimMemory_Mcontent()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['000001',4,'this.SimMaddr_Memory()'])//Maddr->Memory
+ this.SimInstrCtrl.push(['000001',3,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['000001',3,'this.SimIR_Maddr()'])//IR->Maddr
+ }
+
+ async SimR_Mcontent(line:Line,cpu:CPU,mem:MEMORY,alu:ALU,n:number){
+ //R1->MCO
+ if(n==0){
+ await line.mark(['R1_MCO'])
+ }else if(n==1){
+ await line.mark(['R2_MCO'])
+ }else if(n==2){
+ await line.mark(['R3_MCO'])
+ }else if(n==3){
+ await line.mark(['R4_MCO'])
+ }
+
+ cpu.MCO_int=cpu.R_int[n]
+ await mem.show(cpu,CommonConstants.MEMContext)
+ await alu.init(cpu,CommonConstants.ALUContext)
+ }
+
+ async SimMcontent_Memory(line:Line,cpu:CPU,mem:MEMORY){
+ await sleep(500)
+ await line.mark(['MCO_MEM'])
+ cpu.SimMem[cpu.MAD_int]=Bin(cpu.MCO_int,16)
+ await mem.show(cpu,CommonConstants.MEMContext)
+ await sleep(500)
+ cpu.SimMARK[cpu.MAD_int]=false
+ await mem.mark(cpu,CommonConstants.MEMContext)
+ }
+
+ async ShowSimPut(cpu:CPU,n:number){
+ //# 输出信息到综合输出框
+ this.outArray.push('存数指令:' + '\n')
+ this.outArray.push('R' + String(n + 1) + ' -> SimMem[' + String(cpu.MAD_int) + ']' + '\n')
+ cpu.code=0
+ }
+
+ async SimPut(n:number){
+ // # 000010存数指令(R1)
+ // # 010010存数指令(R2)
+ // # 100010存数指令(R3)
+ // # 110010存数指令(R4)
+ this.SimInstrCtrl.push(['000010',4,'this.ShowSimPut(' + String(n + 1) + ')'])//显示信息到输出框
+ this.SimInstrCtrl.push(['000010',4,'this.SimMcontent_Memory()'])// Mcontent_Memory
+ this.SimInstrCtrl.push(['000010',4,'this.SimR_Mcontent(' + String(n + 1) + ')'])//Rn->Mcontent
+ this.SimInstrCtrl.push(['000010',4,'this.SimMaddr_Memory()'])//Maddr_Memory
+ this.SimInstrCtrl.push(['000010',3,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['000010',3,'this.SimIR_Maddr()'])//IR->Maddr
+ }
+
+ async SimR_ALU1(alu:ALU,n:number){
+ // # 高亮显示R1->ALU
+ // eval('alu.mark(["R' + str(n + 1) + '_ALU1"])')
+ if(n==0){
+ await alu.mark(['R1_ALU1'])
+ }else if(n==1){
+ await alu.mark(['R2_ALU1'])
+ }else if(n==2){
+ await alu.mark(['R3_ALU1'])
+ }else if(n==3){
+ await alu.mark(['R4_ALU1'])
+ }
+ }
+
+ async SimR_ALU2(alu:ALU,n:number){
+ // # 高亮显示R2->ALU
+ if(n==0){
+ await alu.mark(['R2_ALU2'])
+ }else if(n==1){
+ await alu.mark(['R3_ALU2'])
+ }else if(n==2){
+ await alu.mark(['R4_ALU2'])
+ }
+ }
+
+ async SimSigCtrl_ALU(si:SIG,line:Line){
+ // # SIG向ALU运算器发出指令
+ await si.ALU(CommonConstants.CPUContext,1)
+ await line.mark(['SIG_ALU'])
+ await sleep(500)
+ await si.ALU(CommonConstants.CPUContext,0)
+ }
+
+ async SimALU_R(alu:ALU,cpu:CPU,op:string,n:number){
+ if(n==0){
+ await alu.mark(['ALU_R1'])
+ }else if(n==1){
+ await alu.mark(['ALU_R2'])
+ }else if(n==2){
+ await alu.mark(['ALU_R3'])
+ }else if(n==3){
+ await alu.mark(['ALU_R4'])
+ }
+
+ await sleep(500)
+ //# 将运算结果存入R1中
+ // cpu.R_int[n] = eval('cpu.R_int[n]' + op + 'cpu.R_int[n + 1]')
+ // cpu.R_int[n]
+ await alu.init(cpu,CommonConstants.ALUContext)
+ }
+
+ async ShowSimAddr(cpu:CPU,n:number){
+ // 输出信息到综合输出框
+ this.outArray.push('加法指令:' + '\n')
+ this.outArray.push('R' + String(n + 1) + ' + R' + String(n + 2) + ' -> R' + String(n + 1) + '\n')
+ cpu.code=0
+ }
+
+ async SimAddr(n:number){
+ // # 加法指令000011
+ this.SimInstrCtrl.push(['000011',6,'this.ShowSimAddr(' + String(n) + ')'])//输出信息到综合输出框
+ this.SimInstrCtrl.push(['000011',6,'this.SimALU_R("+",' + String(n) + ')'])//ALU->Rn,并计算Rn+Rn+1
+ this.SimInstrCtrl.push(['000011',5,'this.SimSigCtrl_ALU'])//SigCtrl->ALU
+ this.SimInstrCtrl.push(['000011',5,'this.SimR_ALU2(' + String(n) + ')'])//Rn+1->ALU2
+ this.SimInstrCtrl.push(['000011',5,'this.SimR_ALU1(' + String(n) + ')'])//Rn->ALU1
+ this.SimInstrCtrl.push(['000011',4,'this.SimMcontent_R(' + String(n + 1) + ')'])// Mcontent->Rn+1
+ this.SimInstrCtrl.push(['000011',4,'this.SimMemory_Mcontent()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['000011',4,'this.SimMaddr_Memory()'])//Maddr_Memory
+ this.SimInstrCtrl.push(['000011',3,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['000011',3,'this.SimIR_Maddr()'])//IR->Maddr
+ }
+
+ async ShowSimProduct(cpu:CPU,n:number){
+ //# 输出信息到综合输出框
+ this.outArray.push('乘法指令:' + '\n')
+ this.outArray.push('R' + String(n + 1) + ' x R' + String(n + 2) + ' -> R' + String(n + 1) + '\n')
+ cpu.code=0
+ }
+
+ async SimProduct(n:number){
+ //# 乘法指令000100
+ this.SimInstrCtrl.push(['000100',6,'this.ShowSimAddr(' + String(n) + ')'])//输出信息到综合输出框
+ this.SimInstrCtrl.push(['000100',6,'this.SimALU_R("*",' + String(n) + ')'])//ALU->Rn,并计算Rn*Rn+1
+
+ this.SimInstrCtrl.push(['000100',5,'this.SimSigCtrl_ALU'])//SigCtrl->ALU
+ this.SimInstrCtrl.push(['000100',5,'this.SimR_ALU2(' + String(n) + ')'])//Rn+1->ALU2
+ this.SimInstrCtrl.push(['000100',5,'this.SimR_ALU1(' + String(n) + ')'])//Rn->ALU1
+
+ this.SimInstrCtrl.push(['000100',4,'this.SimMcontent_R(' + String(n + 1) + ')'])// Mcontent->Rn+1
+ this.SimInstrCtrl.push(['000100',4,'this.SimMemory_Mcontent()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['000100',4,'this.SimMaddr_Memory()'])//Maddr_Memory
+ this.SimInstrCtrl.push(['000100',3,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['000100',3,'this.SimIR_Maddr()'])//IR->Maddr
+ }
+
+ async ShowPrint(cpu:CPU){
+ //# 添加信息到综合输出框
+ this.outArray.push('打印指令:' + '\n')
+ this.outArray.push(''+cpu.MCO()+'\n')
+ cpu.code=0
+ }
+
+ async SimPrint(){
+ //# 打印指令000101
+ this.SimInstrCtrl.push(['000101',4,'this.ShowPrint()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['000101',4,'this.SimMemory_Mcontent()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['000101',4,'this.SimMaddr_Memory()'])//Maddr_Memory
+ this.SimInstrCtrl.push(['000101',3,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['000101',3,'this.SimIR_Maddr()'])//IR->Maddr
+ }
+
+ async ShowStop(cpu:CPU){
+ this.outArray.push('停机指令:\n')
+ this.outArray.push('停机\n')
+ cpu.reset()
+ this.play=0
+ cpu.code=0
+ }
+
+ async SimStop(){
+ //# 停机指令000110
+ this.SimInstrCtrl.push(['000110',4,'this.ShowStop()'])
+ }
+
+ async ShowSimMinus(cpu:CPU,n:number){
+ //# 输出信息到综合输出框
+ this.outArray.push('减法指令:' + '\n')
+ this.outArray.push('R' + String(n + 1) + ' - R' + String(n + 2) + ' -> R' + String(n + 1) + '\n')
+ cpu.code=0
+ }
+
+ async SimMinus(n:number){
+ //# 减法指令000111
+ this.SimInstrCtrl.push(['000111',6,'this.ShowSimMinus(' + String(n) + ')'])//输出信息到综合输出框
+ this.SimInstrCtrl.push(['000111',6,'this.SimALU_R("-",' + String(n) + ')'])//ALU->Rn,并计算Rn-Rn+1
+ this.SimInstrCtrl.push(['000111',5,'this.SimSigCtrl_ALU'])//SigCtrl->ALU
+ this.SimInstrCtrl.push(['000111',5,'this.SimR_ALU2(' + String(n) + ')'])//Rn->ALU2
+ this.SimInstrCtrl.push(['000111',5,'this.SimR_ALU1(' + String(n) + ')'])//Rn->ALU1
+ this.SimInstrCtrl.push(['000111',4,'this.SimMcontent_R(' + String(n + 1) + ')'])//Mcontent->Rn+1
+ this.SimInstrCtrl.push(['000111',4,'this.SimMemory_Mcontent()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['000111',4,'this.SimMaddr_Memory()'])//Maddr_Memory
+ this.SimInstrCtrl.push(['000111',3,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['000111',3,'this.SimIR_Maddr()'])//IR->Maddr
+ }
+
+ async ShowSimDiv(cpu:CPU,n:number){
+ // //# 输出信息到综合输出框
+ this.outArray.push('除法指令:' + '\n')
+ this.outArray.push('R' + String(n + 1) + ' / R' + String(n + 2) + ' -> R' + String(n + 1) + '\n')
+ cpu.code=0
+ }
+
+ async SimDiv(n:number){
+ this.SimInstrCtrl.push(['001000',6,'this.ShowSimDiv(' + String(n) + ')'])//输出信息到综合输出框
+ this.SimInstrCtrl.push(['001000',6,'this.SimALU_R("/",' + String(n) + ')'])//ALU->Rn,并计算Rn/Rn+1
+ this.SimInstrCtrl.push(['001000',5,'this.SimSigCtrl_ALU'])//SigCtrl->ALU
+ this.SimInstrCtrl.push(['001000',5,'this.SimR_ALU2(' + String(n) + ')'])//Rn+1->ALU2
+ this.SimInstrCtrl.push(['001000',5,'this.SimR_ALU1(' + String(n) + ')'])//Rn->ALU1
+ this.SimInstrCtrl.push(['001000',4,'this.SimMcontent_R(' + String(n + 1) + ')'])//Mcontent->Rn+1
+ this.SimInstrCtrl.push(['001000',4,'this.SimMemory_Mcontent()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['001000',4,'this.SimMaddr_Memory()'])//Maddr_Memory
+ this.SimInstrCtrl.push(['001000',3,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['001000',3,'this.SimIR_Maddr()'])//IR->Maddr
+ }
+
+ async SimSigCtrl_PC(si:SIG,line:Line){
+ //# SIG通知PC接受数据
+ await si.PC(CommonConstants.CPUContext,1)
+ await line.mark(['SIG_PC'])
+ await sleep(500)
+ await si.PC(CommonConstants.CPUContext,0)
+ }
+
+ async SimMcontent_PC(line:Line,cpu:CPU,si:SIG){
+ await line.mark(['MCO_PC'])
+ cpu.PC_int=cpu.MCO_int
+ await si.init(cpu,CommonConstants.CPUContext)
+ }
+
+ async ShowSimGoto(cpu:CPU){
+ //# 添加信息到综合输出框
+ this.outArray.push('跳转指令:' + '\n')
+ this.outArray.push('SimMem[' + String(cpu.MAD_int) + ']' + '\n')
+ cpu.code=0
+ }
+
+ async SimGoto(){
+ //# 001001跳转指令 SimGoto
+ this.SimInstrCtrl.push(['001001',4,'this.ShowSimGoto()'])
+ this.SimInstrCtrl.push(['001001',4,'this.SimMcontent_PC()'])
+ this.SimInstrCtrl.push(['001001',4,'this.SimSigCtrl_PC()'])
+ this.SimInstrCtrl.push(['001001',4,'this.SimMemory_Mcontent()'])//Memory->Mcontent
+ this.SimInstrCtrl.push(['001001',4,'this.SimMaddr_Memory()'])//Maddr_Memory
+ this.SimInstrCtrl.push(['001001',3,'this.SimSigCtrl_Memory()'])//SigCtrl->Memory
+ this.SimInstrCtrl.push(['001001',3,'this.SimIR_Maddr()'])//IR->Maddr
+ }
+
+ async Begin_step(cpu:CPU,cl:Clock,sig:SIG,mem:MEMORY,alu:ALU,line:Line){
+ this.play=1
+ await this.step_run(cpu,cl,sig,mem,alu,line)
+ }
+
+ //执行一条指令(不仅改变寄存器,并且使得信号线高亮显示)
+ async solve(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,line:Line){
+ //解析一条指令并将解析后的步骤加入到self.SimInstrCtrl中
+ if(this.play==0){
+ return
+ }
+ let code=cpu.code//读取当前指令
+ if(code==0){//000000取指令
+ await this.get()
+ }else if(code%16==1){//000001取数指令(R1)
+ await this.SimGet(Math.floor(code/16))
+ }else if(code%16==2){//000010存数指令(R1)
+ await this.SimPut(Math.floor(code/16))
+ }else if(code%16==3){//000011加法指令
+ await this.SimAddr(Math.floor(code/16))
+ }else if(code%16==4){//000100乘法指令
+ await this.SimProduct(Math.floor(code/16))
+ }else if(code%16==5){//打印指令000101
+ await this.SimPrint()
+ }else if(code%16==6){//停机指令000110
+ await this.SimStop()
+ }else if(code%16==7){//000111减法指令 op = 1(R1)
+ await this.SimMinus(Math.floor(code/16))
+ }else if(code%16==8){//001000除法指令 op = 3(R1)
+ await this.SimDiv(Math.floor(code/16))
+ }else if(code%16==9){//001001跳转指令Simgoto
+ await this.SimGoto()
+ }else{//无法解析指令视为停机指令
+ await this.SimStop()
+ }
+ await si.init(cpu,CommonConstants.CPUContext)
+ await this.exec_instruct_with_anim(cpu,clo,si,mem,alu,line)
+ }
+
+ async Begin(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,line:Line){
+ this.play=1
+ await this.exec_instruct_with_anim(cpu,clo,si,mem,alu,line)
+ }
+
+ async get_mem(line:Line,cpu:CPU,mem:MEMORY,num:number){
+ //# 将MAD指定地址的内容取到MCO中
+ await line.mark(["MAD_MEM"])
+ for(let j=0;j<20;j++){
+ cpu.SimMARK[j]=false
+ }
+ cpu.SimMARK[num]=true
+ await mem.mark(cpu,CommonConstants.MEMContext)
+ cpu.SimMARK[num]=false
+ await mem.mark(cpu,CommonConstants.MEMContext)
+ }
+}
+
+
diff --git a/macexesiming/macexesim/entry/src/main/ets/classes/ExecInstructWithText.ets b/macexesiming/macexesim/entry/src/main/ets/classes/ExecInstructWithText.ets
new file mode 100644
index 0000000..4003d65
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/classes/ExecInstructWithText.ets
@@ -0,0 +1,512 @@
+import CPU from './CPU'
+import Clock from './Clock'
+import SIG from './SIG'
+import MEMORY from './MEMORY'
+import ALU from './ALU'
+import {Bin,sleep,init} from '../utils/util'
+import * as CommonConstants from '../common/constants/CommonConstants'
+
+//执行指令(仅寄存器)
+export default class ExecInstructWithText {
+ play: number
+ outArray:Array
+ command:string[] = ['取指令', '取数指令', '存数指令', '加法指令', '乘法指令', '打印指令', '停机指令', '减法指令', '除法指令', '跳转指令']
+
+ constructor() {
+ this.outArray=new Array(0) //初始化综合输出框
+ this.play=0//初始化程序运行状态
+ }
+
+ async clock(cpu:CPU,clo:Clock,n: number) {
+ await cpu.CLO(n - 1) //更改cpu内时钟刻的信息
+ await clo.clo_mark(cpu,CommonConstants.CPUContext)//根据cpu显示时钟刻
+ await sleep(500)
+ }
+
+ async print_mark(lines:Array){
+ for(let l=0;l')+'\n')//显示综合输出框
+ await sleep(200)
+ }
+ }
+
+ out_clear(){
+ let len=this.outArray.length
+ for(let i=0;iSIG
+ await this.SimSIG_MAD(si)//将地址传到MAD并且SIG发出信号
+ await this.SimPC_MAD(cpu,mem,si)//PC传参数给MAD
+ await this.clock(cpu,clo,2)//第二个节拍
+ await this.get_mem(cpu,mem,cpu.MAD_int)//将MAD指定地址的内容取到MCO中
+ await this.SimMCO_IR(si,cpu,clo)//mco把值传给IR
+ await this.SimIR_SIG(cpu,si)//IR把CODE值传给SIG
+ await this.clock(cpu,clo,3)//第三个节拍
+ await this.PC_1(si,cpu,clo)//PC+1
+ this.outArray.push('取指令: ' + '\n')
+ this.outArray.push(''+cpu.CODE()+ '\n')
+ }
+
+ async HandleOutArrayPush(cpu:CPU,str:string){
+ this.outArray.push(str + '\n')
+ }
+
+ async SimSIG_Rn(si:SIG,cpu:CPU,alu:ALU,n: number) {
+ //# SIG->R[n]
+ if(n==1){
+ await si.R1(CommonConstants.CPUContext,1)
+ await this.print_mark(['SIG_R1','MCO_R1'])
+ }else if(n==2){
+ await si.R2(CommonConstants.CPUContext,1)
+ await this.print_mark(['SIG_R2','MCO_R2'])
+ }else if(n==3){
+ await si.R3(CommonConstants.CPUContext,1)
+ await this.print_mark(['SIG_R3','MCO_R3'])
+ }else if(n==4){
+ await si.R4(CommonConstants.CPUContext,1)
+ await this.print_mark(['SIG_R4','MCO_R4'])
+ }
+ await sleep(500)
+ if(n==1){
+ await si.R1(CommonConstants.CPUContext,0)
+ }else if(n==2){
+ await si.R2(CommonConstants.CPUContext,0)
+ }else if(n==3){
+ await si.R3(CommonConstants.CPUContext,0)
+ }else if(n==4){
+ await si.R4(CommonConstants.CPUContext,0)
+ }
+ await si.init(cpu,CommonConstants.CPUContext)
+ //将Mcontent中的数字存到R中
+ cpu.R_int[n - 1] = cpu.MCO_int
+ await alu.init(cpu,CommonConstants.ALUContext)
+ }
+
+ async SimGet(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,n: number) {
+ // # 000001取数指令(R1) n = 0
+ // # 010001取数指令(R2) n = 1
+ // # 100001取数指令(R3) n = 2
+ // # 110001取数指令(R4) n = 3
+ await this.clock(cpu,clo,3) // 第三个节拍
+ await this.SimIR_MAD(si,cpu,mem) // 将地址从IR传到MAD并且SIG发出信号
+
+ await this.clock(cpu,clo,4) // 第四个节拍
+ await this.get_mem(cpu,mem,cpu.MAD_int) // 将MAD指定地址的内容取到MCO中
+
+ await this.SimSIG_Rn(si,cpu,alu,n+1)// SIG通知R1接受数据
+
+ this.outArray.push('取数指令:' + '\n') // 输出信息到综合输出框
+ this.outArray.push('SimMem[' + String(cpu.MAD_int) + '] -> R' + String(n + 1) + '\n') // 输出信息到综合输出框
+ }
+
+ async mark_MEM(cpu:CPU,mem:MEMORY){
+ await this.print_mark(["MAD_MEM"])
+ for(let i=0;i<20;i++){
+ cpu.SimMARK[i]=false
+ }
+ cpu.SimMARK[cpu.MAD_int] = true
+ await mem.mark(cpu,CommonConstants.MEMContext)
+ }
+
+ async SinRn_MCO(cpu:CPU,mem:MEMORY,alu:ALU,n:number){
+ //暂定
+ if(n==1){
+ await this.print_mark(['R2_MCO'])
+ }else if(n==2){
+ await this.print_mark(['R3_MCO'])
+ }else if(n==3){
+ await this.print_mark(['R4_MCO'])
+ }else if(n==4){
+ await this.print_mark(['R5_MCO'])
+ }
+
+ await this.print_mark(["R1_MCO"])
+ cpu.MCO_int = cpu.R_int[n]
+ await mem.show(cpu,CommonConstants.MEMContext)
+ await alu.init(cpu,CommonConstants.ALUContext)
+ await sleep(500)
+ await this.print_mark(["MCO_MEM"])
+ }
+
+ async SimMCO_MEM(cpu:CPU,mem:MEMORY){
+ cpu.SimMem[cpu.MAD_int]=Bin(cpu.MCO_int,16)
+ await mem.show(cpu,CommonConstants.MEMContext)
+ await sleep(400)
+ cpu.SimMARK[cpu.MAD_int] = false
+ await mem.mark(cpu,CommonConstants.MEMContext)
+ }
+
+ async SimPut(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,n:number){
+ // # 000010存数指令(R1)
+ // # 010010存数指令(R2)
+ // # 100010存数指令(R3)
+ // # 110010存数指令(R4)
+ await this.clock(cpu,clo,3)// 第三个节拍
+ await this.SimIR_MAD(si,cpu,mem) // 将地址从IR传到MAD并且SIG发出信号
+
+ await this.clock(cpu,clo,4)// 第四个节拍
+ await this.mark_MEM(cpu,mem)// 标记MAD对应的存储单元
+ await this.SinRn_MCO(cpu,mem,alu,n) // Rn->MCO
+ await this.SimMCO_MEM(cpu,mem) // MCO->对应的存储单元
+
+ this.outArray.push('存数指令:' + '\n') // 输出信息到综合输出框
+ this.outArray.push('R' + String(n + 1) + ' -> SimMem[' + String(cpu.MAD_int) + ']' + '\n') // 输出信息到综合输出框
+ }
+
+ async SimR_ALU(cpu:CPU,alu:ALU,n:number){
+ // # 高亮显示R1->ALU, R2->ALU
+ if(n==0){
+ await this.print_mark(['R1_ALU1','R2_ALU2'])
+ } else if(n==1){
+ await this.print_mark(['R2_ALU1','R3_ALU2'])
+ }else if(n==2){
+ await this.print_mark(['R3_ALU1','R4_ALU2'])
+ }else if(n==3){
+ await this.print_mark(['R4_ALU1','R5_ALU2'])
+ }else if(n==4){
+ await this.print_mark(['R5_ALU1','R6_ALU2'])
+ }
+ await sleep(500)
+ await alu.init(cpu,CommonConstants.ALUContext)
+ await sleep(500)
+ // # SIG向ALU运算器发出指令
+ await this.print_mark(["SIG_ALU"])
+ }
+
+ async SimANS_Rn(cpu:CPU,alu:ALU,ans:number,n:number){
+ if(n==0){
+ await this.print_mark(['ALU_R1'])
+ } else if(n==1){
+ await this.print_mark(['ALU_R2'])
+ }else if(n==2){
+ await this.print_mark(['ALU_R3'])
+ }else if(n==3){
+ await this.print_mark(['ALU_R4'])
+ }
+
+ await sleep(500)
+ // # 将运算结果存入R1中
+ cpu.R_int[n] = ans
+ await alu.init(cpu,CommonConstants.ALUContext)
+ }
+
+ async SimAddr(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,n:number){
+ // # 加法指令000011
+ await this.clock(cpu,clo,3)// 第三个节拍
+ await this.SimIR_MAD(si,cpu,mem)//# 将地址从IR传到MAD并且SIG发出信号
+
+ await this.clock(cpu,clo,4)//第四个节拍
+ await this.get_mem(cpu,mem,cpu.MAD_int)// 将MAD指定地址的内容取到MCO中
+ await this.SimSIG_Rn(si,cpu,alu,n+2)//SIG通知Rn+1接受数据
+
+ //开始计算
+ await this.clock(cpu,clo,5)//第五个节拍
+ await this.SimR_ALU(cpu,alu,n)//R[n] R[n+1] 进入ALU中
+
+ await this.clock(cpu,clo,6)//第六个节拍
+ // let ans=cpu.R_int[n]+cpu.R_int[n+1]//记录计算结果到ans中
+ let ans=await this.HandleCpu_R_int_Addr(cpu,n)//记录计算结果到ans中
+ await this.SimANS_Rn(cpu,alu,ans,n)//ALU将计算结果存到Rn
+
+ this.outArray.push('加法指令: '+'\n')//输出信息到综合输出框
+ this.outArray.push('R'+String(n+1)+' + R'+String(n+2)+' -> R'+String(n+1)+'\n')//输出信息到综合输出框
+ }
+
+ async HandleCpu_R_int_Addr(cpu:CPU,n:number){
+ return cpu.R_int[n]+cpu.R_int[n+1]
+ }
+
+ async SimProduct(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,n:number){
+ //# 乘法指令000100
+ await this.clock(cpu,clo,3)// 第三个节拍
+ await this.SimIR_MAD(si,cpu,mem)//# 将地址从IR传到MAD并且SIG发出信号
+
+ await this.clock(cpu,clo,4)//第四个节拍
+ await this.get_mem(cpu,mem,cpu.MAD_int)// 将MAD指定地址的内容取到MCO中
+ await this.SimSIG_Rn(si,cpu,alu,(n+2))//SIG通知R2接受数据
+
+ //开始计算
+ await this.clock(cpu,clo,5)//第五个节拍
+ await this.SimR_ALU(cpu,alu,n)//R1 R2 进入ALU中
+
+ await this.clock(cpu,clo,6)//第六个节拍
+ let ans=await this.HandleCpu_R_int_Product(cpu,n)//记录计算结果到ans中
+ await this.SimANS_Rn(cpu,alu,ans,n)//ALU将计算结果存到Rn
+
+ this.outArray.push('乘法指令: '+'\n')//输出信息到综合输出框
+ this.outArray.push('R'+String(n+1)+' x R'+String(n+2)+' -> R'+String(n+1)+'\n')//输出信息到综合输出框
+ }
+
+ async HandleCpu_R_int_Product(cpu:CPU,n:number){
+ return cpu.R_int[n]*cpu.R_int[n+1]
+ }
+
+ async SimMinus(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,n:number){
+ // # 减法指令000111
+ await this.clock(cpu,clo,3)// 第三个节拍
+ await this.SimIR_MAD(si,cpu,mem)//# 将地址从IR传到MAD并且SIG发出信号
+
+ await this.clock(cpu,clo,4)//第四个节拍
+ await this.get_mem(cpu,mem,cpu.MAD_int)// 将MAD指定地址的内容取到MCO中
+ await this.SimSIG_Rn(si,cpu,alu,(n+2))//SIG通知R2接受数据
+
+ //开始计算
+ await this.clock(cpu,clo,5)//第五个节拍
+ await this.SimR_ALU(cpu,alu,n)//R1 R2 进入ALU中
+
+ await this.clock(cpu,clo,6)//第六个节拍
+ let ans=await this.HandleCpu_R_int_Minus(cpu,n)//记录计算结果到ans中
+ await this.SimANS_Rn(cpu,alu,ans,n)//ALU将计算结果存到Rn
+
+ this.outArray.push('减法指令: '+'\n')//输出信息到综合输出框
+ this.outArray.push('R'+String(n+1)+' - R'+String(n+2)+' -> R'+String(n+1)+'\n')//输出信息到综合输出框
+ }
+
+ async HandleCpu_R_int_Minus(cpu:CPU,n:number){
+ return cpu.R_int[n]-cpu.R_int[n+1]
+ }
+
+ async SimDiv(cpu:CPU,clo:Clock,si:SIG,mem:MEMORY,alu:ALU,n:number){
+ // # 除法指令001000
+ await this.clock(cpu,clo,3)// 第三个节拍
+ await this.SimIR_MAD(si,cpu,mem)//# 将地址从IR传到MAD并且SIG发出信号
+
+ await this.clock(cpu,clo,4)//第四个节拍
+ await this.get_mem(cpu,mem,cpu.MAD_int)// 将MAD指定地址的内容取到MCO中
+ await this.SimSIG_Rn(si,cpu,alu,(n+2))//SIG通知R2接受数据
+
+ //开始计算
+ await this.clock(cpu,clo,5)//第五个节拍
+ await this.SimR_ALU(cpu,alu,n)//R1 R2 进入ALU中
+
+ await this.clock(cpu,clo,6)//第六个节拍
+ let ans=await this.HandleCpu_R_int_Div(cpu,n)//记录计算结果到ans中
+ await this.SimANS_Rn(cpu,alu,ans,n)//ALU将计算结果存到Rn
+
+ this.outArray.push('除法指令: '+'\n')//输出信息到综合输出框
+ this.outArray.push('R'+String(n+1)+' / R'+String(n+2)+' -> R'+String(n+1)+'\n')//输出信息到综合输出框
+ }
+
+ async HandleCpu_R_int_Div(cpu:CPU,n:number){
+ return cpu.R_int[n]/cpu.R_int[n+1]
+ }
+
+ async get_mem(cpu:CPU,mem:MEMORY,num:number){
+ // # 将MAD指定地址的内容取到MCO中
+ await this.print_mark(["MAD_MEM"])
+ await this.HandelCpu_SimMARK(cpu,num)
+ await mem.mark(cpu,CommonConstants.MEMContext)
+ await this.print_mark(["MEM_MCO"])
+ await this.SimMEM_MCO(cpu,mem)
+ await this.HandelCpu_SimMARK2(cpu,num)
+ await mem.mark(cpu,CommonConstants.MEMContext)
+ }
+
+ async HandelCpu_SimMARK(cpu:CPU,num:number){
+ for(let j=0;j<20;j++){
+ cpu.SimMARK[j] = false
+ }
+ cpu.SimMARK[num] = true
+ }
+
+ async HandelCpu_SimMARK2(cpu:CPU,num:number){
+ cpu.SimMARK[num] = false
+ }
+}
+
+
diff --git a/macexesiming/macexesim/entry/src/main/ets/classes/Line.ets b/macexesiming/macexesim/entry/src/main/ets/classes/Line.ets
new file mode 100644
index 0000000..b010893
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/classes/Line.ets
@@ -0,0 +1,868 @@
+import { sleep } from '../utils/util'
+import * as CommonConstants from '../common/constants/CommonConstants'
+
+//连接线数据结构
+export default class Line {
+ all(cv:CanvasRenderingContext2D){
+ // this.PC_MAD(cv,1)
+ // this.SIG_MEM(cv,1)
+ // this.SIG_IR(cv,1)
+ // this.IR_SIG(cv,1)
+ // this.IR_MCO(cv,1)
+ // this.MCO_IR(cv,1)
+ // this.MCO_MEM(cv,1)
+ // this.MEM_MCO(cv,1)
+ // this.PC_SIG(cv,1)
+ // this.SIG_PC(cv,1)
+ // this.IR_MAD(cv,1)
+ // this.SIG_R1(cv,1)
+ // this.SIG_R2(cv,1)
+ // this.SIG_R3(cv,1)
+ // this.SIG_R4(cv,1)
+ // this.MCO_R1(cv,1)
+ // this.R1_MCO(cv,1)
+ // this.MCO_R2(cv,1)
+ // this.R2_MCO(cv,1)
+ // this.MCO_R3(cv,1)
+ // this.R3_MCO(cv,1)
+ // this.MCO_R4(cv,1)
+ // this.R4_MCO(cv,1)
+ // this.SIG_ALU(cv,1)
+ // this.MAD_MEM(cv,1)
+ // this.MCO_PC(cv,1)
+
+ this.PC_MAD(cv,0)
+ this.SIG_MEM(cv,0)
+ this.SIG_IR(cv,0)
+ this.IR_SIG(cv,0)
+ this.IR_MCO(cv,0)
+ this.MCO_IR(cv,0)
+ this.MCO_MEM(cv,0)
+ this.MEM_MCO(cv,0)
+ this.PC_SIG(cv,0)
+ this.SIG_PC(cv,0)
+ this.IR_MAD(cv,0)
+ this.SIG_R1(cv,0)
+ this.SIG_R2(cv,0)
+ this.SIG_R3(cv,0)
+ this.SIG_R4(cv,0)
+ this.MCO_R1(cv,0)
+ this.R1_MCO(cv,0)
+ this.MCO_R2(cv,0)
+ this.R2_MCO(cv,0)
+ this.MCO_R3(cv,0)
+ this.R3_MCO(cv,0)
+ this.MCO_R4(cv,0)
+ this.R4_MCO(cv,0)
+ this.SIG_ALU(cv,0)
+ this.MAD_MEM(cv,0)
+ this.MCO_PC(cv,0)
+ }
+
+ async mark(lines:string[]){
+ for(let i=0;i<5;i++){
+ if(i){
+ await sleep(500)
+ }
+ if(i%2){
+ for(let l=0;l{
+ for(let j=0;j<20;j++){
+ cpu.SimMARK[j]=false
+ }
+ cpu.SimMARK[Math.floor(Math.random() * 20)]=true
+ this.mark(cpu,cv)
+ num++
+ if(num==20){
+ clearInterval(timer)
+ }
+ },2000)
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/ets/classes/SIG.ets b/macexesiming/macexesim/entry/src/main/ets/classes/SIG.ets
new file mode 100644
index 0000000..9eb778f
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/classes/SIG.ets
@@ -0,0 +1,154 @@
+import CPU from './CPU'
+
+//SIG数据结构
+export default class SIG {
+ async init(cpu:CPU,cv:CanvasRenderingContext2D){
+ // 显示sig_ctrl各部分的名字
+ cv.beginPath()
+ cv.fillStyle='#000000'
+ cv.fillRect(75,75,45,10)//清除先前的数据
+ cv.fillStyle='#FFD700'
+ cv.font ='40px';
+ cv.fillText('insCode',15,85)
+ cv.fillText(String(cpu.CODE()),75,85)
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->ALU',15,100)
+ cv.fillText('->IR',15,110)
+ cv.fillText('->PC+1',15,120)
+ cv.fillText('->MEMORY',15,130)
+ cv.fillText('->R1',95,100)
+ cv.fillText('->R2',95,110)
+ cv.fillText('->R3',95,120)
+ cv.fillText('->R4',95,130)
+ cv.closePath()
+ }
+
+ async ALU(cv:CanvasRenderingContext2D,flag:number){
+ if(flag){
+ cv.beginPath()
+ cv.fillStyle='#FFD700'
+ cv.font ='30px';
+ cv.fillText('->ALU',15,100)
+ cv.closePath()
+ }else{
+ cv.beginPath()
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->ALU',15,100)
+ cv.closePath()
+ }
+ }
+
+ async IR(cv:CanvasRenderingContext2D,flag:number){
+ if(flag){
+ cv.beginPath()
+ cv.fillStyle='#FFD700'
+ cv.font ='30px';
+ cv.fillText('->IR',15,110)
+ cv.closePath()
+ }else{
+ cv.beginPath()
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->IR',15,110)
+ cv.closePath()
+ }
+ }
+
+ async PC(cv:CanvasRenderingContext2D,flag:number){
+ if(flag){
+ cv.beginPath()
+ cv.fillStyle='#FFD700'
+ cv.font ='30px';
+ cv.fillText('->PC+1',15,120)
+ cv.closePath()
+ }else{
+ cv.beginPath()
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->PC+1',15,120)
+ cv.closePath()
+ }
+ }
+
+ async MEM(cv:CanvasRenderingContext2D,flag:number){
+ if(flag){
+ cv.beginPath()
+ cv.fillStyle='#FFD700'
+ cv.font ='30px';
+ cv.fillText('->MEMORY',15,130)
+ cv.closePath()
+ }else{
+ cv.beginPath()
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->MEMORY',15,130)
+ cv.closePath()
+ }
+ }
+
+ async R1(cv:CanvasRenderingContext2D,flag:number){
+ if(flag){
+ cv.beginPath()
+ cv.fillStyle='#FFD700'
+ cv.font ='30px';
+ cv.fillText('->R1',95,100)
+ cv.closePath()
+ }else{
+ cv.beginPath()
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->R1',95,100)
+ cv.closePath()
+ }
+ }
+
+ async R2(cv:CanvasRenderingContext2D,flag:number){
+ if(flag){
+ cv.beginPath()
+ cv.fillStyle='#FFD700'
+ cv.font ='30px';
+ cv.fillText('->R2',95,110)
+ cv.closePath()
+ }else{
+ cv.beginPath()
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->R2',95,110)
+ cv.closePath()
+ }
+ }
+
+ async R3(cv:CanvasRenderingContext2D,flag:number){
+ if(flag){
+ cv.beginPath()
+ cv.fillStyle='#FFD700'
+ cv.font ='30px';
+ cv.fillText('->R3',95,120)
+ cv.closePath()
+ }else{
+ cv.beginPath()
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->R3',95,120)
+ cv.closePath()
+ }
+ }
+
+ async R4(cv:CanvasRenderingContext2D,flag:number){
+ if(flag){
+ cv.beginPath()
+ cv.fillStyle='#FFD700'
+ cv.font ='30px';
+ cv.fillText('->R4',95,130)
+ cv.closePath()
+ }else{
+ cv.beginPath()
+ cv.fillStyle='#808080'
+ cv.font ='30px';
+ cv.fillText('->R4',95,130)
+ cv.closePath()
+ }
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/ets/classes/test.ets b/macexesiming/macexesim/entry/src/main/ets/classes/test.ets
new file mode 100644
index 0000000..ab0746b
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/classes/test.ets
@@ -0,0 +1,38 @@
+export default class ALU {// ALU数据结构
+ show(cpu: CPU,cv: CanvasRenderingContext2D){this.line_init(cv);this.init(cpu, cv);}//显示ALU状态
+ line_init(cv: CanvasRenderingContext2D) {this.ALU_R1(cv, 0); this.ALU_R2(cv, 0); this.ALU_R3(cv, 0);
+ this.ALU_R4(cv, 0);this.R1_ALU1(cv, 0); this.R2_ALU1(cv, 0); this.R3_ALU1(cv, 0);
+ this.R4_ALU1(cv, 0); this.R1_ALU2(cv, 0); this.R2_ALU2(cv, 0); this.R3_ALU2(cv, 0); this.R4_ALU2(cv, 0); }// 初始化连接线
+ // 标记连接线高亮状态
+ async mark(lines: Array) {for (let i = 0; i < 5; i++) {if (i) await sleep(500); // 闪烁间隔
+ const isHighlight = i % 2; // 奇数索引高亮
+ for (let l = 0; l < lines.length; l++){this.setLineState(lines[l], isHighlight); }}}
+ //初始化ALU显示
+ async init(cpu: CPU, cv: CanvasRenderingContext2D){this.no(cv);const R_Text = [cpu.R(0), cpu.R(1), cpu.R(2), cpu.R(3)];
+ cv.beginPath(); cv.fillStyle = '#00ffff'; cv.font = '40px';cv.clearRect(170, 20, 122, 10);
+ cv.fillText(R_Text[0], 170, 30);cv.clearRect(170, 40, 122, 10); cv.fillText(R_Text[1], 170, 50);
+ cv.clearRect(170, 60, 122, 10); cv.fillText(R_Text[2], 170, 70);cv.clearRect(170, 80, 122, 10);
+ cv.fillText(R_Text[3], 170, 90)};
+ //设置连接线状态(核心方法)
+ async setLineState(lineName: string, flag: number) {const color =flag ? '#ee28a3' : '#c5c9c5';
+ {case'ALU_R1':this.drawALU_R1(color); break; case 'ALU_R2': this.drawALU_R2(color); break;// ... 其他连线}}
+ // 连接线绘制方法
+ async ALU_R1(cv: CanvasRenderingContext2D, flag: number) { cv.strokeStyle = flag ? '#ee28a3' : '#c5c9c5';cv.beginPath();}
+ async ALU_R2(cv: CanvasRenderingContext2D, flag: number) { /*类似ALU_R1*/ }
+ async ALU_R3(cv: CanvasRenderingContext2D, flag: number) { /*类似ALU_R1 */ }
+ async ALU_R4(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ async R1_ALU1(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ async R2_ALU1(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ async R3_ALU1(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ async R4_ALU1(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ async R1_ALU2(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ async R2_ALU2(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ async R3_ALU2(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ async R4_ALU2(cv: CanvasRenderingContext2D, flag: number) { /* 类似ALU_R1 */ }
+ // 运算符高亮控制opa(cv: CanvasRenderingContext2D) { this.setOperatorHighlight('+', true, cv); }
+ opb(cv: CanvasRenderingContext2D) { this.setOperatorHighlight('-', true, cv); }
+ opc(cv: CanvasRenderingContext2D) { this.setOperatorHighlight('*', true, cv); }
+ opd(cv: CanvasRenderingContext2D) { this.setOperatorHighlight('/', true, cv); }
+ no(cv: CanvasRenderingContext2D) { ['+', '-', '*', '/'].forEach(op=>this.setOperatorHighlight(op,false,cv)); }
+ finish(cv: CanvasRenderingContext2D) { /* 完成运算状态显示 */ } // 设置运算符高亮状态
+ private setOperatorHighlight(op: string, state: boolean, cv: CanvasRenderingContext2D) { cv.fillStyle = state ? '#ff0000' : '#c5c9c5';}// 绘制运算符图形
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/ets/common/constants/CommonConstants.ets b/macexesiming/macexesim/entry/src/main/ets/common/constants/CommonConstants.ets
new file mode 100644
index 0000000..27ed04e
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/common/constants/CommonConstants.ets
@@ -0,0 +1,19 @@
+//绘制运算器
+export const ALUSettings: RenderingContextSettings = new RenderingContextSettings(true);
+export const ALUContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(ALUSettings);
+
+//绘制控制器
+export const CPUSettings: RenderingContextSettings = new RenderingContextSettings(true);
+export const CPUContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(CPUSettings);
+
+//绘制存储器
+export const MEMSettings: RenderingContextSettings = new RenderingContextSettings(true);
+export const MEMContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(MEMSettings);
+
+//绘制连接线
+export const LineSettings: RenderingContextSettings = new RenderingContextSettings(true);
+export const LineContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(LineSettings);
+
+//绘制数据
+export const ShowSettings: RenderingContextSettings = new RenderingContextSettings(true);
+export const ShowContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(ShowSettings);
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/ets/common/pictrues/icon_logo.png b/macexesiming/macexesim/entry/src/main/ets/common/pictrues/icon_logo.png
new file mode 100644
index 0000000..2eb3b01
Binary files /dev/null and b/macexesiming/macexesim/entry/src/main/ets/common/pictrues/icon_logo.png differ
diff --git a/macexesiming/macexesim/entry/src/main/ets/components/LoaderDialog.ets b/macexesiming/macexesim/entry/src/main/ets/components/LoaderDialog.ets
new file mode 100644
index 0000000..23a3ffd
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/components/LoaderDialog.ets
@@ -0,0 +1,137 @@
+import {Bin} from '../utils/util'
+
+//程序装载弹窗
+@CustomDialog
+export default struct LoaderDialog {
+ controller: CustomDialogController
+ @State flag:boolean=false
+ @State text:string=''
+ @State showArr:string[]=[]
+ @Link isLoad:boolean
+ @Link loadArr:string[]
+
+ build() {
+ Column() {
+ Row() {
+ Image('/common/pictrues/icon_logo.png')
+ .objectFit(ImageFit.Contain)
+ .width(16)
+
+ Text('装入程序')
+ .fontSize(16)
+ }
+ .padding({left:10})
+ .width('100%')
+ .height('10%')
+
+ Row({space:5}){
+ Column(){
+ Text('装入程序,用逗号隔开指令')
+ .fontSize(22)
+ .fontWeight(FontWeight.Bold)
+
+ TextArea({ placeholder:
+ '示例:'+ '\n' +
+ '0000010000001000,' + '\n' +
+ '0000110000001010,' + '\n' +
+ '0001000000001001,' + '\n' +
+ '0001000000001000,' + '\n' +
+ '0000110000001011,' + '\n' +
+ '0000100000001100,' + '\n' +
+ '0001010000001100,' + '\n' +
+ '0001100000000000,' + '\n' +
+ '0000000000000101,' + '\n' +
+ '0000000000001001,' + '\n' +
+ '0000000000000110,' + '\n' +
+ '0000000000001000,' + '\n'
+ })
+ .height(230)
+ .placeholderFont({ size: 14})
+ .fontSize(14)
+ .barState(BarState.Auto)
+ .onChange((value:string)=>{
+ this.text=value
+ })
+
+ Text('载入程序')
+ .fontWeight(FontWeight.Bold)
+ .onClick(()=>{
+ if(this.text.length){
+ let check=true
+ this.loadArr=this.text.split('\n')
+ for(let i=0;i {
+ ListItem() {
+ Text(item)
+ .fontSize(14)
+ .textAlign(TextAlign.Center)
+ }
+ // .width('100%')
+ .height(16)
+ }, (item: string) => item)
+ }
+
+ .height(230)
+ }
+ }else{
+ Text()
+ .height(230)
+ }
+
+ Text('确认载入程序')
+ .fontWeight(FontWeight.Bold)
+ .onClick(()=>{
+ if(this.loadArr.length){
+ for(let i=this.loadArr.length;i<20;i++){
+ this.loadArr.push('0000000000000000')
+ }
+ this.isLoad=true
+ }
+ this.controller.close()
+ })
+ }
+ .justifyContent(FlexAlign.Center)
+ .width('50%')
+ .height('100%')
+ }
+ .width('100%')
+ .height('90%')
+ }
+ .justifyContent(FlexAlign.Center)
+ .width('100%')
+ .height('100%')
+ }
+}
diff --git a/macexesiming/macexesim/entry/src/main/ets/components/MessageDialog.ets b/macexesiming/macexesim/entry/src/main/ets/components/MessageDialog.ets
new file mode 100644
index 0000000..de33c3c
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/components/MessageDialog.ets
@@ -0,0 +1,30 @@
+//信息提示弹窗
+@CustomDialog
+export default struct MessageDialog {
+ @Link msg:string
+ controller: CustomDialogController
+
+ build(){
+ Column({space:5}){
+ Text(this.msg)
+ .fontSize(18)
+ .height(70)
+ .textAlign(TextAlign.Center)
+ .fontWeight(FontWeight.Bold)
+ .fontColor(Color.White)
+
+ Text('确定')
+ .fontSize(18)
+ .textAlign(TextAlign.Center)
+ .fontWeight(FontWeight.Bold)
+ .fontColor(Color.White)
+ .onClick(()=>{
+ this.controller.close()
+ })
+ }
+ .backgroundColor("#1E90FF")
+ .justifyContent(FlexAlign.Center)
+ .width(600)
+ .height(150)
+ }
+}
diff --git a/macexesiming/macexesim/entry/src/main/ets/components/RightPanel.ets b/macexesiming/macexesim/entry/src/main/ets/components/RightPanel.ets
new file mode 100644
index 0000000..a3e85d9
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/components/RightPanel.ets
@@ -0,0 +1,273 @@
+import ALU from '../classes/ALU'
+import Clock from '../classes/Clock'
+import SIG from '../classes/SIG'
+import MEMORY from '../classes/MEMORY'
+import Line from '../classes/Line'
+import CPU from '../classes/CPU'
+import ExecInstructWithText from '../classes/ExecInstructWithText'
+import ExecInstructWithAnim from '../classes/ExecInstructWithAnim'
+import MessageDialog from '../components/MessageDialog'
+import {init,Bin} from '../utils/util'
+import * as CommonConstants from '../common/constants/CommonConstants'
+
+//右侧数据面板
+@Component
+export default struct RightPanel {
+ @Link @Watch('onFlag') flag:number
+ @Link alu:ALU
+ @Link clock:Clock
+ @Link sig:SIG
+ @Link memory:MEMORY
+ @Link line:Line
+ @Link cpu:CPU
+ @Link isLoad:boolean
+ @Link run_text:ExecInstructWithText
+ @Link run_ani:ExecInstructWithAnim
+ @State msg:string=''
+ private scrollerForList: Scroller = new Scroller()
+ //信息弹窗控制器
+ MessageDialogController: CustomDialogController = new CustomDialogController({
+ builder: MessageDialog({msg:$msg}),
+ gridCount: 5
+ })
+
+ onFlag(){
+ if(!this.isLoad){
+ if(this.flag==1){
+ this.exec_test_program_text()
+ }else if(this.flag==2){
+ this.exec_test_program_anim()
+ }
+ }
+ }
+
+
+ exec_test_program_text(){
+ let Program = [
+ '0000010000001000',
+ '0000110000001010',
+ '0001000000001001',
+ '0001000000001000',
+ '0000110000001011',
+ '0000100000001100',
+ '0001010000001100',
+ '0001100000000000',
+ '0000000000000101',
+ '0000000000001001',
+ '0000000000000110',
+ '0000000000001000'
+ ] // 输入题目要求的程序
+
+ for(let i=0;i{
+ if(this.run_text.play==1){//程序正在运行中
+ this.msg='程序正在运行中'
+ this.MessageDialogController.open()
+ }else{//程序空闲
+ this.run_text.exec_instruct_with_text(this.cpu,this.clock,this.sig,this.memory,this.alu)
+ }
+ })Canvas(CommonConstants.ShowContext){
+
+ }
+ .onReady(()=>{
+ CommonConstants.ShowContext.beginPath()
+ //当前操作码
+ CommonConstants.ShowContext.font='50px'
+ CommonConstants.ShowContext.fillStyle='#000000'
+ CommonConstants.ShowContext.fillText('当前操作码:',0,15)
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(0,20,150,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText(this.cpu.CODE(),50,35)
+ //正在执行指令
+ CommonConstants.ShowContext.fillStyle='#000000'
+ CommonConstants.ShowContext.fillText('正在执行指令:',0,55)
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(0,60,150,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText(this.run_text.command[this.cpu.code%16],50,75)
+ CommonConstants.ShowContext.closePath()
+ })
+ .width(150)
+ .height(80)
+
+ Row(){
+ Text('综合输出框:')
+ Text('清空')
+ .width(40)
+ .borderWidth(1)
+ .textAlign(TextAlign.Center)
+ .onClick(()=>{
+ this.run_text.out_clear()
+ })
+ }
+ .width(150)
+
+ Scroll() {
+ List({ space:2,scroller: this.scrollerForList }) {
+ ForEach(this.run_text.outArray, (item: string,index:number) => {
+ ListItem() {
+ Text(item)
+ .fontSize(14)
+ }.width("100%").height(16)
+ }, (item: string) => item)
+ }
+ }
+ .border({width:1})
+ .width(150)
+ .height('45%')
+
+
+ }else if(this.flag==2){
+ Text('执行指令(带UI)')
+ .fontSize(20)
+ .textAlign(TextAlign.Center)
+ .fontWeight(FontWeight.Bold)
+
+
+ Text('自动执行程序(连续)')
+ .width(150)
+ .fontSize(16)
+ .textAlign(TextAlign.Center)
+ .borderWidth(1)
+ .onClick(()=>{
+ if(this.run_ani.play==1){//程序正在运行中
+ this.msg='程序正在运行中'
+ this.MessageDialogController.open()
+ }else{//程序空闲
+ this.run_ani.Begin(this.cpu,this.clock,this.sig,this.memory,this.alu,this.line)
+ }
+ })
+
+ Text('自动执行程序(分节拍)')
+ .width(150)
+ .fontSize(15)
+ .textAlign(TextAlign.Center)
+ .borderWidth(1)
+ .onClick(()=>{
+ if(this.run_ani.play==1){//程序正在运行中
+ this.msg='程序正在运行中'
+ this.MessageDialogController.open()
+ }else{//程序空闲
+ this.run_ani.Begin_step(this.cpu,this.clock,this.sig,this.memory,this.alu,this.line)
+ }
+ })
+
+
+ Canvas(CommonConstants.ShowContext){
+
+ }
+ .onReady(()=>{
+ let clo=0
+ for(let i=0;i<6;i++){
+ if(this.cpu.clo[i]){
+ clo=i
+ }
+ }
+ CommonConstants.ShowContext.beginPath()
+ //当前节拍
+ CommonConstants.ShowContext.font='45px'
+ CommonConstants.ShowContext.fillStyle='#000000'
+ CommonConstants.ShowContext.fillText('当前节拍:',0,15)
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(75,0,40,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText((clo+1).toString(),90,15)
+ //当前操作码
+ CommonConstants.ShowContext.fillStyle='#000000'
+ CommonConstants.ShowContext.fillText('当前操作码:',0,35)
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(0,40,150,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText(this.cpu.CODE(),53,55)
+ //正在执行指令
+ CommonConstants.ShowContext.fillStyle='#000000'
+ CommonConstants.ShowContext.fillText('正在执行指令:',0,75)
+ CommonConstants.ShowContext.fillStyle='#0153d2'
+ CommonConstants.ShowContext.fillRect(0,80,150,20)
+ CommonConstants.ShowContext.fillStyle='#ffffff'
+ CommonConstants.ShowContext.fillText(this.run_ani.command[this.cpu.code%16],53,95)
+ CommonConstants.ShowContext.closePath()
+ })
+ .width(150)
+ .height(100)
+
+
+ Row(){
+ Text('综合输出框:')
+ Text('清空')
+ .width(40)
+ .borderWidth(1)
+ .textAlign(TextAlign.Center)
+ .onClick(()=>{
+ this.run_ani.out_clear()
+ })
+ }
+ .width(150)
+
+ Scroll() {
+ List({ space:2,scroller: this.scrollerForList }) {
+ ForEach(this.run_ani.outArray, (item: string,index:number) => {
+ ListItem() {
+ Text(item)
+ .fontSize(14)
+ }.width("100%").height(16)
+ }, (item: string) => item)
+ }
+ }
+ .border({width:1})
+ .width(150)
+ .height('35%')
+ }
+ }
+ .width('100%')
+ .height('100%')
+ }
+}
+
+
diff --git a/macexesiming/macexesim/entry/src/main/ets/components/Title.ets b/macexesiming/macexesim/entry/src/main/ets/components/Title.ets
new file mode 100644
index 0000000..9b002c4
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/components/Title.ets
@@ -0,0 +1,17 @@
+//头部标题
+@Component
+export default struct Title {
+ build() {
+ Row() {
+ Image('/common/pictrues/icon_logo.png')
+ .objectFit(ImageFit.Contain)
+ .width(18)
+
+ Text('CPU可视化')
+ .fontSize(18)
+ }
+ .padding({left:10})
+ .width('100%')
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/ets/components/UI.ets b/macexesiming/macexesim/entry/src/main/ets/components/UI.ets
new file mode 100644
index 0000000..bb3edcf
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/components/UI.ets
@@ -0,0 +1,171 @@
+import * as CommonConstants from '../common/constants/CommonConstants'
+import LoaderDialog from '../components/LoaderDialog'
+import {drawALU,drawCPU,drawMEM,init} from '../utils/util'
+import ALU from '../classes/ALU'
+import Clock from '../classes/Clock'
+import SIG from '../classes/SIG'
+import MEMORY from '../classes/MEMORY'
+import Line from '../classes/Line'
+import CPU from '../classes/CPU'
+
+//左侧UI绘制
+@Component
+export default struct UI {
+ @Link flag:number
+ @Link alu:ALU
+ @Link clock:Clock
+ @Link sig:SIG
+ @Link memory:MEMORY
+ @Link line:Line
+ @Link cpu:CPU
+ @Link @Watch('onisLoad') isLoad:boolean
+ @State loadArr:string[]=[]
+
+ LoaderDialogController: CustomDialogController = new CustomDialogController({
+ builder: LoaderDialog({isLoad:$isLoad,loadArr:$loadArr}),
+ gridCount: 8
+ }) // 设置弹窗控制器
+
+ onisLoad(){
+ if(this.isLoad){
+ for(let i=0;i{
+ drawALU()
+ this.alu.line_init(CommonConstants.ALUContext)
+ this.alu.init(this.cpu,CommonConstants.ALUContext)
+ })
+ .margin({top:5})
+ .width(300)
+ .height(180)
+ .borderRadius(10)
+ .backgroundColor('#0153d2')
+
+ Canvas(CommonConstants.CPUContext){
+
+ }
+ .onReady(()=>{
+ drawCPU()
+ this.clock.init(this.cpu,CommonConstants.CPUContext)
+ this.sig.init(this.cpu,CommonConstants.CPUContext)
+
+ })
+ .width(300)
+ .height(140)
+ .borderRadius(10)
+ .backgroundColor('#0153d2')
+ }
+ .width('55%')
+ .height('100%')
+
+ Column({space:5}){
+ //占位
+ Column()
+ .width(220)
+ .height(100)
+
+ //存储器
+ Canvas(CommonConstants.MEMContext){
+
+ }
+ .onReady(()=>{
+ drawMEM()
+ this.memory.init(this.cpu,CommonConstants.MEMContext)
+ })
+ .width(220)
+ .height(220)
+ .borderRadius(10)
+ .backgroundColor('#0153d2')
+ }
+ .width('45%')
+ .height('100%')
+ }
+ .width('100%')
+ .height('100%')
+
+ //绘制连接线
+ Canvas(CommonConstants.LineContext){
+
+ }
+ .onReady(()=>{
+ this.line.all(CommonConstants.LineContext)
+ })
+ .width('100%')
+ .height('100%')
+
+ //功能按钮
+ Row(){
+ Column()
+ .width('60%')
+ .height('100%')
+
+ Column({space:5}){
+ Text('自动执行指令(仅寄存器)')
+ .fontColor(Color.Black)
+ .backgroundColor("#FFD700")
+ .fontSize(16)
+ .width(220)
+ .height(30)
+ .textAlign(TextAlign.Center)
+ .margin({top:3})
+ .onClick(()=>{
+ this.flag=1
+ })
+
+ Text('自动执行指令(带UI)')
+ .fontColor(Color.Black)
+ .backgroundColor("#FFD700")
+ .fontSize(16)
+ .width(220)
+ .height(30)
+ .textAlign(TextAlign.Center)
+ .onClick(()=>{
+ this.flag=2
+ // this.memory.test(this.cpu,CommonConstants.MEMContext)
+ })
+
+ Row(){
+ Blank()
+ Text('装载程序')
+ .fontColor(Color.Black)
+ .backgroundColor("#FFAAAA")
+ .fontSize(16)
+ .width(100)
+ .height(30)
+ .textAlign(TextAlign.Center)
+ .onClick(()=>{
+ this.LoaderDialogController.open()
+ })
+ }
+ .width(220)
+ .height(30)
+ }
+ .width('40%')
+ .height('100%')
+ }
+ .width('100%')
+ .height('100%')
+
+ }
+ .width('100%')
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/ets/entryability/EntryAbility.ets b/macexesiming/macexesim/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000..1c7aa63
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,43 @@
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+import hilog from '@ohos.hilog';
+import UIAbility from '@ohos.app.ability.UIAbility';
+import Want from '@ohos.app.ability.Want';
+import window from '@ohos.window';
+
+export default class EntryAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
+ }
+
+ onDestroy(): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ // Main window is created, set main page for this ability
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+
+ windowStage.loadContent('pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy(): void {
+ // Main window is destroyed, release UI related resources
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
+ }
+
+ onForeground(): void {
+ // Ability has brought to foreground
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
+ }
+
+ onBackground(): void {
+ // Ability has back to background
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
+ }
+}
diff --git a/macexesiming/macexesim/entry/src/main/ets/pages/Index.ets b/macexesiming/macexesim/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000..b5ba8c3
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,84 @@
+import RightPanel from '../components/RightPanel'
+import Title from '../components/Title'
+import UI from '../components/UI'
+import ALU from '../classes/ALU'
+import Clock from '../classes/Clock'
+import SIG from '../classes/SIG'
+import MEMORY from '../classes/MEMORY'
+import Line from '../classes/Line'
+import CPU from '../classes/CPU'
+import ExecInstructWithText from '../classes/ExecInstructWithText'
+import ExecInstructWithAnim from '../classes/ExecInstructWithAnim'
+import common from '@ohos.app.ability.common';
+import Window from '@ohos.window'
+import { BusinessError } from '@ohos.base';
+
+@Entry
+@Component
+struct Index {
+ @State flag:number=0//功能选择标志
+ @State alu:ALU=new ALU()//ALU
+ @State clock:Clock=new Clock()//时钟
+ @State sig:SIG=new SIG()//SigCtrl
+ @State memory:MEMORY=new MEMORY()//存储器
+ @State line:Line=new Line()//连接线
+ @State cpu:CPU=new CPU()//CPU
+ @State isLoad:boolean=false//程序装载标志
+ @State run_text:ExecInstructWithText=new ExecInstructWithText()//自动执行指令(仅寄存器)
+ @State run_ani:ExecInstructWithAnim=new ExecInstructWithAnim()//自动执行指令(带UI)
+
+ // 设置开发板横屏显示
+ private changeOrientation() {
+ let windowClass: Window.Window | undefined = undefined;
+ // 获取上下文,使用common模块
+ let context = getContext(this) as common.UIAbilityContext;
+ let promise = Window.getLastWindow(context);
+ promise.then((data) => {
+ windowClass = data;
+ //切换成横屏
+ let orientation = Window.Orientation.LANDSCAPE;
+ windowClass.setPreferredOrientation(orientation, (err:BusinessError) => {
+ });
+ console.info('Succeeded in obtaining the top window. Data: ' + JSON.stringify(data));
+ }).catch((err:BusinessError) => {
+ console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(err));
+ });
+ }
+
+ aboutToAppear(){
+ // this.changeOrientation()
+ }
+
+ build() {
+ Column() {
+ //头部标题
+ Title()
+ .width('100%')
+ .height('5%')
+ .backgroundColor(Color.White)
+
+ Row(){
+ //左侧UI绘制
+ UI({flag:$flag,alu:$alu,clock:$clock,sig:$sig,memory:$memory,line:$line,cpu:$cpu,isLoad:$isLoad})
+ .width('75%')
+ .height('97%')
+ .backgroundColor(Color.White)
+ .borderRadius(10)
+ .margin(3)
+
+ //右侧数据面板
+ RightPanel({flag:$flag,alu:$alu,clock:$clock,sig:$sig,memory:$memory,line:$line,cpu:$cpu,isLoad:$isLoad,run_text:$run_text,run_ani:$run_ani})
+ .width('23%')
+ .height('97%')
+ .backgroundColor(Color.White)
+ .borderRadius(10)
+ .margin(3)
+ }
+ .width('100%')
+ .height('95%')
+ }
+ .backgroundColor(Color.Black)
+ .width('100%')
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/ets/utils/util.ets b/macexesiming/macexesim/entry/src/main/ets/utils/util.ets
new file mode 100644
index 0000000..a4d6170
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/ets/utils/util.ets
@@ -0,0 +1,134 @@
+import Clock from '../classes/Clock';
+import MEMORY from '../classes/MEMORY';
+import ALU from '../classes/ALU'
+import SIG from '../classes/SIG'
+import Line from '../classes/Line'
+import CPU from '../classes/CPU'
+import * as CommonConstants from '../common/constants/CommonConstants'
+
+//数字以指定长度二进制表示,并移除前缀'0b'
+export function Bin(num:number, length = 6) {
+ let binaryStr = num.toString(2);
+ return binaryStr.padStart(length, '0');
+}
+
+//绘制运算器
+export function drawALU() {
+ //运算器形状
+ CommonConstants.ALUContext.beginPath()
+ CommonConstants.ALUContext.fillStyle='#000000'
+ CommonConstants.ALUContext.lineWidth = 1.5; //线条宽
+ CommonConstants.ALUContext.moveTo(5,70)
+ CommonConstants.ALUContext.lineTo(20,70)
+ CommonConstants.ALUContext.lineTo(25,80)
+ CommonConstants.ALUContext.lineTo(60,80)
+ CommonConstants.ALUContext.lineTo(65,70)
+ CommonConstants.ALUContext.lineTo(80,70)
+ CommonConstants.ALUContext.lineTo(65,120)
+ CommonConstants.ALUContext.lineTo(20,120)
+ CommonConstants.ALUContext.lineTo(5,70)
+ CommonConstants.ALUContext.fill()
+ CommonConstants.ALUContext.closePath()
+
+ //名称
+ CommonConstants.ALUContext.beginPath()
+ CommonConstants.ALUContext.fillStyle='#c89265'
+ CommonConstants.ALUContext.font ='30px';
+ CommonConstants.ALUContext.fillText('完成运算',25,100)
+ CommonConstants.ALUContext.font ='35px';
+ CommonConstants.ALUContext.fillText('+',25,115)
+ CommonConstants.ALUContext.fillText('-',35,115)
+ CommonConstants.ALUContext.fillText('x',45,115)
+ CommonConstants.ALUContext.fillText('÷',55,115)
+ CommonConstants.ALUContext.font ='45px';
+ CommonConstants.ALUContext.fillStyle='#00ffff'
+ CommonConstants.ALUContext.fillText('ALU',30,80)
+ CommonConstants.ALUContext.fillText('R1',150,30)
+ CommonConstants.ALUContext.fillText('R2',150,70)
+ CommonConstants.ALUContext.fillText('R3',150,110)
+ CommonConstants.ALUContext.fillText('R4',150,150)
+ CommonConstants.ALUContext.closePath()
+}
+
+//绘制控制器
+export function drawCPU(){
+ //SigCtrl
+ CommonConstants.CPUContext.beginPath()
+ CommonConstants.CPUContext.fillStyle='#000000'
+ CommonConstants.CPUContext.lineWidth = 1.5; //线条宽
+ CommonConstants.CPUContext.moveTo(10,70)
+ CommonConstants.CPUContext.lineTo(120,70)
+ CommonConstants.CPUContext.lineTo(120,135)
+ CommonConstants.CPUContext.lineTo(10,135)
+ CommonConstants.CPUContext.fill()
+ CommonConstants.CPUContext.closePath()
+
+ //名称
+ CommonConstants.CPUContext.beginPath()
+ CommonConstants.CPUContext.fillStyle='#00ffff'
+ CommonConstants.CPUContext.font ='35px';
+ CommonConstants.CPUContext.fillText('Clock',15,10)
+ CommonConstants.CPUContext.fillText('PC',170,10)
+ CommonConstants.CPUContext.fillText('SigCtrl',15,65)
+ CommonConstants.CPUContext.fillText('IR',170,65)
+
+ CommonConstants.CPUContext.closePath()
+}
+
+//绘制存储器
+export function drawMEM(){
+ //MEM
+ CommonConstants.MEMContext.beginPath()
+ CommonConstants.MEMContext.fillStyle='#000000'
+ CommonConstants.MEMContext.lineWidth = 1.5; //线条宽
+ CommonConstants.MEMContext.moveTo(40,30)
+ CommonConstants.MEMContext.lineTo(210,30)
+ CommonConstants.MEMContext.lineTo(210,215)
+ CommonConstants.MEMContext.lineTo(40,215)
+ CommonConstants.MEMContext.fill()
+ CommonConstants.MEMContext.closePath()
+
+ CommonConstants.MEMContext.beginPath()
+ CommonConstants.MEMContext.fillStyle='#ff9900'
+ CommonConstants.MEMContext.moveTo(125,32)
+ CommonConstants.MEMContext.lineTo(208,32)
+ CommonConstants.MEMContext.lineTo(208,213)
+ CommonConstants.MEMContext.lineTo(125,213)
+ CommonConstants.MEMContext.fill()
+ CommonConstants.MEMContext.closePath()
+
+ //名称
+ CommonConstants.MEMContext.beginPath()
+ CommonConstants.MEMContext.fillStyle='#00ffff'
+ CommonConstants.MEMContext.font ='35px';
+ CommonConstants.MEMContext.fillText('Maddr',5,80)
+ CommonConstants.MEMContext.fillText('Mcontent',45,10)
+ CommonConstants.MEMContext.fillStyle='#FFD700'
+ CommonConstants.MEMContext.font ='35px';
+ CommonConstants.MEMContext.fillText('地址(编号)',50,25)
+ CommonConstants.MEMContext.fillText('在选单元',140,25)
+ CommonConstants.MEMContext.closePath()
+}
+
+export function init(cpu:CPU,cl:Clock,alu:ALU,si:SIG,mem:MEMORY,line?:Line){
+ cl.init(cpu,CommonConstants.CPUContext)
+ alu.init(cpu,CommonConstants.ALUContext)
+ si.init(cpu,CommonConstants.CPUContext)
+ mem.init(cpu,CommonConstants.MEMContext)
+ // line.init(CommonConstants.LineContext)
+}
+
+//延迟函数 通过异步和定时器实现
+export function sleep(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+}
+
+//延迟函数 阻塞整个线程 不推荐 会引起UI线程影响
+export function sleep2(ms) {
+ const date = Date.now();
+ let currentDate = null;
+ do {
+ currentDate = Date.now();
+ } while (currentDate - date < ms);
+}
+
diff --git a/macexesiming/macexesim/entry/src/main/module.json5 b/macexesiming/macexesim/entry/src/main/module.json5
new file mode 100644
index 0000000..f2ff2c7
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/resources/base/element/color.json b/macexesiming/macexesim/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/resources/base/element/string.json b/macexesiming/macexesim/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000..f945955
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/resources/base/media/icon.png b/macexesiming/macexesim/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/macexesiming/macexesim/entry/src/main/resources/base/media/icon.png differ
diff --git a/macexesiming/macexesim/entry/src/main/resources/base/media/startIcon.png b/macexesiming/macexesim/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000..366f764
Binary files /dev/null and b/macexesiming/macexesim/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/macexesiming/macexesim/entry/src/main/resources/base/profile/main_pages.json b/macexesiming/macexesim/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000..1898d94
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/macexesiming/macexesim/entry/src/main/resources/en_US/element/string.json b/macexesiming/macexesim/entry/src/main/resources/en_US/element/string.json
new file mode 100644
index 0000000..f945955
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/resources/en_US/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/main/resources/zh_CN/element/string.json b/macexesiming/macexesim/entry/src/main/resources/zh_CN/element/string.json
new file mode 100644
index 0000000..597ecf9
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/main/resources/zh_CN/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "模块描述"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/ohosTest/ets/test/Ability.test.ets b/macexesiming/macexesim/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000..8aa3749
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,35 @@
+import hilog from '@ohos.hilog';
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function abilityTest() {
+ describe('ActsAbilityTest', () => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ })
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ })
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ })
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ })
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ })
+ })
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/ohosTest/ets/test/List.test.ets b/macexesiming/macexesim/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000..794c7dc
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/ohosTest/ets/testability/TestAbility.ets b/macexesiming/macexesim/entry/src/ohosTest/ets/testability/TestAbility.ets
new file mode 100644
index 0000000..9484761
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/ets/testability/TestAbility.ets
@@ -0,0 +1,50 @@
+import UIAbility from '@ohos.app.ability.UIAbility';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import hilog from '@ohos.hilog';
+import { Hypium } from '@ohos/hypium';
+import testsuite from '../test/List.test';
+import window from '@ohos.window';
+import Want from '@ohos.app.ability.Want';
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+
+export default class TestAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
+ let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator;
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs;
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
+ hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
+ }
+
+ onDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
+ windowStage.loadContent('testability/pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
+ JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
+ }
+
+ onForeground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
+ }
+
+ onBackground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/ohosTest/ets/testability/pages/Index.ets b/macexesiming/macexesim/entry/src/ohosTest/ets/testability/pages/Index.ets
new file mode 100644
index 0000000..423b427
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/ets/testability/pages/Index.ets
@@ -0,0 +1,17 @@
+@Entry
+@Component
+struct Index {
+ @State message: string = 'Hello World';
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/macexesiming/macexesim/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
new file mode 100644
index 0000000..917d27a
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
@@ -0,0 +1,47 @@
+import hilog from '@ohos.hilog';
+import TestRunner from '@ohos.application.testRunner';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import Want from '@ohos.app.ability.Want';
+
+let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined
+let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined
+
+async function onAbilityCreateCallback() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
+}
+
+async function addAbilityMonitorCallback(err : Error) {
+ hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
+ }
+
+ async onRun() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ const bundleName = abilityDelegatorArguments.bundleName;
+ const testAbilityName = 'TestAbility';
+ let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ const want: Want = {
+ bundleName: bundleName,
+ abilityName: testAbilityName
+ };
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ abilityDelegator.startAbility(want, (err, data) => {
+ hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
+ hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? '');
+ })
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/ohosTest/module.json5 b/macexesiming/macexesim/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000..4fc9701
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "description": "$string:module_test_desc",
+ "mainElement": "TestAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:test_pages",
+ "abilities": [
+ {
+ "name": "TestAbility",
+ "srcEntry": "./ets/testability/TestAbility.ets",
+ "description": "$string:TestAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:TestAbility_label",
+ "exported": true,
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "skills": [
+ {
+ "actions": [
+ "action.system.home"
+ ],
+ "entities": [
+ "entity.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/macexesiming/macexesim/entry/src/ohosTest/resources/base/element/color.json b/macexesiming/macexesim/entry/src/ohosTest/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/ohosTest/resources/base/element/string.json b/macexesiming/macexesim/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000..65d8fa5
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_test_desc",
+ "value": "test ability description"
+ },
+ {
+ "name": "TestAbility_desc",
+ "value": "the test ability"
+ },
+ {
+ "name": "TestAbility_label",
+ "value": "test label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/ohosTest/resources/base/media/icon.png b/macexesiming/macexesim/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000..ce307a8
Binary files /dev/null and b/macexesiming/macexesim/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/macexesiming/macexesim/entry/src/ohosTest/resources/base/profile/test_pages.json b/macexesiming/macexesim/entry/src/ohosTest/resources/base/profile/test_pages.json
new file mode 100644
index 0000000..b7e7343
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/ohosTest/resources/base/profile/test_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "testability/pages/Index"
+ ]
+}
diff --git a/macexesiming/macexesim/entry/src/test/List.test.ets b/macexesiming/macexesim/entry/src/test/List.test.ets
new file mode 100644
index 0000000..bb5b5c3
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/test/List.test.ets
@@ -0,0 +1,5 @@
+import localUnitTest from './LocalUnit.test';
+
+export default function testsuite() {
+ localUnitTest();
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/entry/src/test/LocalUnit.test.ets b/macexesiming/macexesim/entry/src/test/LocalUnit.test.ets
new file mode 100644
index 0000000..ed22d4d
--- /dev/null
+++ b/macexesiming/macexesim/entry/src/test/LocalUnit.test.ets
@@ -0,0 +1,33 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function localUnitTest() {
+ describe('localUnitTest',() => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ });
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ });
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ });
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ });
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ });
+ });
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/hvigor/hvigor-config.json5 b/macexesiming/macexesim/hvigor/hvigor-config.json5
new file mode 100644
index 0000000..0c81a69
--- /dev/null
+++ b/macexesiming/macexesim/hvigor/hvigor-config.json5
@@ -0,0 +1,17 @@
+{
+ "modelVersion": "5.0.5",
+ "dependencies": {
+ },
+ "execution": {
+ // "daemon": true, /* Enable daemon compilation. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Default: false */
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/hvigorfile.ts b/macexesiming/macexesim/hvigorfile.ts
new file mode 100644
index 0000000..f3cb9f1
--- /dev/null
+++ b/macexesiming/macexesim/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/macexesiming/macexesim/oh-package-lock.json5 b/macexesiming/macexesim/oh-package-lock.json5
new file mode 100644
index 0000000..ea0c500
--- /dev/null
+++ b/macexesiming/macexesim/oh-package-lock.json5
@@ -0,0 +1,20 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hypium@1.0.11": "@ohos/hypium@1.0.11"
+ },
+ "packages": {
+ "@ohos/hypium@1.0.11": {
+ "name": "@ohos/hypium",
+ "version": "1.0.11",
+ "integrity": "sha512-KawcLnv43C3QIYv1UbDnKCFX3MohtDxGuFvzlUxT/qf2DBilR56Ws6zrj90LdH6PjloJQwOPESuBQIHBACAK7w==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.11.tgz",
+ "shasum": "fa799d273fa7d921701578c5e7084849354a4af0",
+ "registryType": "ohpm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/macexesiming/macexesim/oh-package.json5 b/macexesiming/macexesim/oh-package.json5
new file mode 100644
index 0000000..edc6b6f
--- /dev/null
+++ b/macexesiming/macexesim/oh-package.json5
@@ -0,0 +1,13 @@
+{
+ "modelVersion": "5.0.5",
+ "license": "",
+ "devDependencies": {
+ "@ohos/hypium": "1.0.11"
+ },
+ "author": "",
+ "name": "machineprogramexecutionsimulation",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
\ No newline at end of file
diff --git a/minesweeping/README.md b/minesweeping/README.md
new file mode 100644
index 0000000..6453aab
--- /dev/null
+++ b/minesweeping/README.md
@@ -0,0 +1,21 @@
+# minesweeping
+### 1、项目说明
+总体思路:扫雷程序项目开发的总体思路如图1.1示意,拟实现交互界面与交互控制、数据结构和扫雷算法等。
+ 图1.1 项目开发的总体思路图
+
+
+
+### 2、开发环境说明
+(1)系统版本:OpenHarmony 4.0 Release
+(2)SDK版本:API 10
+(3)Model类型:Stage
+(4)DevEco Studio版本:Deveco Studio 4.0 release
+(5)硬件环境:Unionpi Whale、RK3566开发板
+(6)预览器参数:(1)DeviceType:default;(2)Resolution:560-1280;(3)DPI:240;其余参数自定。
+### 3、项目主要函数调用关系图与项目输出界面演进图
+ 图3.1 项目主要函数调用关系图
+
+
+
+ 图3.2 项目输出界面演进图
+
\ No newline at end of file
diff --git a/minesweeping/figs/evolution.png b/minesweeping/figs/evolution.png
new file mode 100644
index 0000000..82d7888
Binary files /dev/null and b/minesweeping/figs/evolution.png differ
diff --git a/minesweeping/figs/overall.png b/minesweeping/figs/overall.png
new file mode 100644
index 0000000..84556a0
Binary files /dev/null and b/minesweeping/figs/overall.png differ
diff --git a/minesweeping/figs/relation.png b/minesweeping/figs/relation.png
new file mode 100644
index 0000000..3f85ce1
Binary files /dev/null and b/minesweeping/figs/relation.png differ
diff --git a/minesweeping/minesweeper/AutoMineSweeper.bat b/minesweeping/minesweeper/AutoMineSweeper.bat
new file mode 100644
index 0000000..af52561
--- /dev/null
+++ b/minesweeping/minesweeper/AutoMineSweeper.bat
@@ -0,0 +1,979 @@
+@echo off
+echo D:\DevecoStudio_SDK _4.0.0.600\openHarmony-SDK\10\toolchains\
+:: 设置变量接收用户输入,输入1,2,3,4分别代表简单,一般,困难,噩梦模式
+set /p var="Please input the number(1,2,3,4) representing Easy Mode, Normal Mode, Hard Mode, and Nightmare Mode:"
+ if %var% == 1 (
+:: 简单模式
+echo "Easy Mode"
+hdc shell uinput -T -c 300 85 100
+hdc shell uinput -T -c 355 340 100
+hdc shell uinput -T -c 385 340 100
+hdc shell uinput -T -c 415 340 100
+hdc shell uinput -T -c 445 340 100
+hdc shell uinput -T -c 475 340 100
+hdc shell uinput -T -c 505 340 100
+hdc shell uinput -T -c 355 370 100
+hdc shell uinput -T -c 385 370 100
+hdc shell uinput -T -c 415 370 100
+hdc shell uinput -T -c 445 370 100
+hdc shell uinput -T -c 475 370 100
+hdc shell uinput -T -c 505 370 100
+hdc shell uinput -T -c 355 400 100
+hdc shell uinput -T -c 385 400 100
+hdc shell uinput -T -c 415 400 100
+hdc shell uinput -T -c 445 400 100
+hdc shell uinput -T -c 475 400 100
+hdc shell uinput -T -c 505 400 100
+hdc shell uinput -T -c 355 430 100
+hdc shell uinput -T -c 385 430 100
+hdc shell uinput -T -c 415 430 100
+hdc shell uinput -T -c 445 430 100
+hdc shell uinput -T -c 475 430 100
+hdc shell uinput -T -c 505 430 100
+hdc shell uinput -T -c 355 460 100
+hdc shell uinput -T -c 385 460 100
+hdc shell uinput -T -c 415 460 100
+hdc shell uinput -T -c 445 460 100
+hdc shell uinput -T -c 475 460 100
+hdc shell uinput -T -c 505 460 100
+hdc shell uinput -T -c 355 490 100
+hdc shell uinput -T -c 385 490 100
+hdc shell uinput -T -c 415 490 100
+hdc shell uinput -T -c 445 490 100
+hdc shell uinput -T -c 475 490 100
+hdc shell uinput -T -c 505 490 100
+ ) else if %var% == 2 (
+:: 一般模式
+echo "Normal Mode"
+hdc shell uinput -T -c 300 85 50
+hdc shell uinput -T -c 300 285 50
+hdc shell uinput -T -c 330 285 50
+hdc shell uinput -T -c 360 285 50
+hdc shell uinput -T -c 390 285 50
+hdc shell uinput -T -c 420 285 50
+hdc shell uinput -T -c 450 285 50
+hdc shell uinput -T -c 480 285 50
+hdc shell uinput -T -c 510 285 50
+hdc shell uinput -T -c 540 285 50
+hdc shell uinput -T -c 570 285 50
+hdc shell uinput -T -c 600 285 50
+hdc shell uinput -T -c 300 315 50
+hdc shell uinput -T -c 330 315 50
+hdc shell uinput -T -c 360 315 50
+hdc shell uinput -T -c 390 315 50
+hdc shell uinput -T -c 420 315 50
+hdc shell uinput -T -c 450 315 50
+hdc shell uinput -T -c 480 315 50
+hdc shell uinput -T -c 510 315 50
+hdc shell uinput -T -c 540 315 50
+hdc shell uinput -T -c 570 315 50
+hdc shell uinput -T -c 600 315 50
+hdc shell uinput -T -c 300 345 50
+hdc shell uinput -T -c 330 345 50
+hdc shell uinput -T -c 360 345 50
+hdc shell uinput -T -c 390 345 50
+hdc shell uinput -T -c 420 345 50
+hdc shell uinput -T -c 450 345 50
+hdc shell uinput -T -c 480 345 50
+hdc shell uinput -T -c 510 345 50
+hdc shell uinput -T -c 540 345 50
+hdc shell uinput -T -c 570 345 50
+hdc shell uinput -T -c 600 345 50
+hdc shell uinput -T -c 300 375 50
+hdc shell uinput -T -c 330 375 50
+hdc shell uinput -T -c 360 375 50
+hdc shell uinput -T -c 390 375 50
+hdc shell uinput -T -c 420 375 50
+hdc shell uinput -T -c 450 375 50
+hdc shell uinput -T -c 480 375 50
+hdc shell uinput -T -c 510 375 50
+hdc shell uinput -T -c 540 375 50
+hdc shell uinput -T -c 570 375 50
+hdc shell uinput -T -c 600 375 50
+hdc shell uinput -T -c 300 405 50
+hdc shell uinput -T -c 330 405 50
+hdc shell uinput -T -c 360 405 50
+hdc shell uinput -T -c 390 405 50
+hdc shell uinput -T -c 420 405 50
+hdc shell uinput -T -c 450 405 50
+hdc shell uinput -T -c 480 405 50
+hdc shell uinput -T -c 510 405 50
+hdc shell uinput -T -c 540 405 50
+hdc shell uinput -T -c 570 405 50
+hdc shell uinput -T -c 600 405 50
+hdc shell uinput -T -c 300 435 50
+hdc shell uinput -T -c 330 435 50
+hdc shell uinput -T -c 360 435 50
+hdc shell uinput -T -c 390 435 50
+hdc shell uinput -T -c 420 435 50
+hdc shell uinput -T -c 450 435 50
+hdc shell uinput -T -c 480 435 50
+hdc shell uinput -T -c 510 435 50
+hdc shell uinput -T -c 540 435 50
+hdc shell uinput -T -c 570 435 50
+hdc shell uinput -T -c 600 435 50
+hdc shell uinput -T -c 300 465 50
+hdc shell uinput -T -c 330 465 50
+hdc shell uinput -T -c 360 465 50
+hdc shell uinput -T -c 390 465 50
+hdc shell uinput -T -c 420 465 50
+hdc shell uinput -T -c 450 465 50
+hdc shell uinput -T -c 480 465 50
+hdc shell uinput -T -c 510 465 50
+hdc shell uinput -T -c 540 465 50
+hdc shell uinput -T -c 570 465 50
+hdc shell uinput -T -c 600 465 50
+hdc shell uinput -T -c 300 495 50
+hdc shell uinput -T -c 330 495 50
+hdc shell uinput -T -c 360 495 50
+hdc shell uinput -T -c 390 495 50
+hdc shell uinput -T -c 420 495 50
+hdc shell uinput -T -c 450 495 50
+hdc shell uinput -T -c 480 495 50
+hdc shell uinput -T -c 510 495 50
+hdc shell uinput -T -c 540 495 50
+hdc shell uinput -T -c 570 495 50
+hdc shell uinput -T -c 600 495 50
+hdc shell uinput -T -c 300 525 50
+hdc shell uinput -T -c 330 525 50
+hdc shell uinput -T -c 360 525 50
+hdc shell uinput -T -c 390 525 50
+hdc shell uinput -T -c 420 525 50
+hdc shell uinput -T -c 450 525 50
+hdc shell uinput -T -c 480 525 50
+hdc shell uinput -T -c 510 525 50
+hdc shell uinput -T -c 540 525 50
+hdc shell uinput -T -c 570 525 50
+hdc shell uinput -T -c 600 525 50
+hdc shell uinput -T -c 300 555 50
+hdc shell uinput -T -c 330 555 50
+hdc shell uinput -T -c 360 555 50
+hdc shell uinput -T -c 390 555 50
+hdc shell uinput -T -c 420 555 50
+hdc shell uinput -T -c 450 555 50
+hdc shell uinput -T -c 480 555 50
+hdc shell uinput -T -c 510 555 50
+hdc shell uinput -T -c 540 555 50
+hdc shell uinput -T -c 570 555 50
+hdc shell uinput -T -c 600 555 50
+ ) else if %var% == 3 (
+:: 困难模式
+echo "Hard Mode"
+hdc shell uinput -T -c 300 85 20
+hdc shell uinput -T -c 150 205 20
+hdc shell uinput -T -c 180 205 20
+hdc shell uinput -T -c 210 205 20
+hdc shell uinput -T -c 240 205 20
+hdc shell uinput -T -c 270 205 20
+hdc shell uinput -T -c 300 205 20
+hdc shell uinput -T -c 330 205 20
+hdc shell uinput -T -c 360 205 20
+hdc shell uinput -T -c 390 205 20
+hdc shell uinput -T -c 420 205 20
+hdc shell uinput -T -c 450 205 20
+hdc shell uinput -T -c 480 205 20
+hdc shell uinput -T -c 510 205 20
+hdc shell uinput -T -c 540 205 20
+hdc shell uinput -T -c 570 205 20
+hdc shell uinput -T -c 600 205 20
+hdc shell uinput -T -c 630 205 20
+hdc shell uinput -T -c 660 205 20
+hdc shell uinput -T -c 690 205 20
+hdc shell uinput -T -c 720 205 20
+hdc shell uinput -T -c 150 235 20
+hdc shell uinput -T -c 180 235 20
+hdc shell uinput -T -c 210 235 20
+hdc shell uinput -T -c 240 235 20
+hdc shell uinput -T -c 270 235 20
+hdc shell uinput -T -c 300 235 20
+hdc shell uinput -T -c 330 235 20
+hdc shell uinput -T -c 360 235 20
+hdc shell uinput -T -c 390 235 20
+hdc shell uinput -T -c 420 235 20
+hdc shell uinput -T -c 450 235 20
+hdc shell uinput -T -c 480 235 20
+hdc shell uinput -T -c 510 235 20
+hdc shell uinput -T -c 540 235 20
+hdc shell uinput -T -c 570 235 20
+hdc shell uinput -T -c 600 235 20
+hdc shell uinput -T -c 630 235 20
+hdc shell uinput -T -c 660 235 20
+hdc shell uinput -T -c 690 235 20
+hdc shell uinput -T -c 720 235 20
+hdc shell uinput -T -c 150 265 20
+hdc shell uinput -T -c 180 265 20
+hdc shell uinput -T -c 210 265 20
+hdc shell uinput -T -c 240 265 20
+hdc shell uinput -T -c 270 265 20
+hdc shell uinput -T -c 300 265 20
+hdc shell uinput -T -c 330 265 20
+hdc shell uinput -T -c 360 265 20
+hdc shell uinput -T -c 390 265 20
+hdc shell uinput -T -c 420 265 20
+hdc shell uinput -T -c 450 265 20
+hdc shell uinput -T -c 480 265 20
+hdc shell uinput -T -c 510 265 20
+hdc shell uinput -T -c 540 265 20
+hdc shell uinput -T -c 570 265 20
+hdc shell uinput -T -c 600 265 20
+hdc shell uinput -T -c 630 265 20
+hdc shell uinput -T -c 660 265 20
+hdc shell uinput -T -c 690 265 20
+hdc shell uinput -T -c 720 265 20
+hdc shell uinput -T -c 150 295 20
+hdc shell uinput -T -c 180 295 20
+hdc shell uinput -T -c 210 295 20
+hdc shell uinput -T -c 240 295 20
+hdc shell uinput -T -c 270 295 20
+hdc shell uinput -T -c 300 295 20
+hdc shell uinput -T -c 330 295 20
+hdc shell uinput -T -c 360 295 20
+hdc shell uinput -T -c 390 295 20
+hdc shell uinput -T -c 420 295 20
+hdc shell uinput -T -c 450 295 20
+hdc shell uinput -T -c 480 295 20
+hdc shell uinput -T -c 510 295 20
+hdc shell uinput -T -c 540 295 20
+hdc shell uinput -T -c 570 295 20
+hdc shell uinput -T -c 600 295 20
+hdc shell uinput -T -c 630 295 20
+hdc shell uinput -T -c 660 295 20
+hdc shell uinput -T -c 690 295 20
+hdc shell uinput -T -c 720 295 20
+hdc shell uinput -T -c 150 325 20
+hdc shell uinput -T -c 180 325 20
+hdc shell uinput -T -c 210 325 20
+hdc shell uinput -T -c 240 325 20
+hdc shell uinput -T -c 270 325 20
+hdc shell uinput -T -c 300 325 20
+hdc shell uinput -T -c 330 325 20
+hdc shell uinput -T -c 360 325 20
+hdc shell uinput -T -c 390 325 20
+hdc shell uinput -T -c 420 325 20
+hdc shell uinput -T -c 450 325 20
+hdc shell uinput -T -c 480 325 20
+hdc shell uinput -T -c 510 325 20
+hdc shell uinput -T -c 540 325 20
+hdc shell uinput -T -c 570 325 20
+hdc shell uinput -T -c 600 325 20
+hdc shell uinput -T -c 630 325 20
+hdc shell uinput -T -c 660 325 20
+hdc shell uinput -T -c 690 325 20
+hdc shell uinput -T -c 720 325 20
+hdc shell uinput -T -c 150 355 20
+hdc shell uinput -T -c 180 355 20
+hdc shell uinput -T -c 210 355 20
+hdc shell uinput -T -c 240 355 20
+hdc shell uinput -T -c 270 355 20
+hdc shell uinput -T -c 300 355 20
+hdc shell uinput -T -c 330 355 20
+hdc shell uinput -T -c 360 355 20
+hdc shell uinput -T -c 390 355 20
+hdc shell uinput -T -c 420 355 20
+hdc shell uinput -T -c 450 355 20
+hdc shell uinput -T -c 480 355 20
+hdc shell uinput -T -c 510 355 20
+hdc shell uinput -T -c 540 355 20
+hdc shell uinput -T -c 570 355 20
+hdc shell uinput -T -c 600 355 20
+hdc shell uinput -T -c 630 355 20
+hdc shell uinput -T -c 660 355 20
+hdc shell uinput -T -c 690 355 20
+hdc shell uinput -T -c 720 355 20
+hdc shell uinput -T -c 150 385 20
+hdc shell uinput -T -c 180 385 20
+hdc shell uinput -T -c 210 385 20
+hdc shell uinput -T -c 240 385 20
+hdc shell uinput -T -c 270 385 20
+hdc shell uinput -T -c 300 385 20
+hdc shell uinput -T -c 330 385 20
+hdc shell uinput -T -c 360 385 20
+hdc shell uinput -T -c 390 385 20
+hdc shell uinput -T -c 420 385 20
+hdc shell uinput -T -c 450 385 20
+hdc shell uinput -T -c 480 385 20
+hdc shell uinput -T -c 510 385 20
+hdc shell uinput -T -c 540 385 20
+hdc shell uinput -T -c 570 385 20
+hdc shell uinput -T -c 600 385 20
+hdc shell uinput -T -c 630 385 20
+hdc shell uinput -T -c 660 385 20
+hdc shell uinput -T -c 690 385 20
+hdc shell uinput -T -c 720 385 20
+hdc shell uinput -T -c 150 415 20
+hdc shell uinput -T -c 180 415 20
+hdc shell uinput -T -c 210 415 20
+hdc shell uinput -T -c 240 415 20
+hdc shell uinput -T -c 270 415 20
+hdc shell uinput -T -c 300 415 20
+hdc shell uinput -T -c 330 415 20
+hdc shell uinput -T -c 360 415 20
+hdc shell uinput -T -c 390 415 20
+hdc shell uinput -T -c 420 415 20
+hdc shell uinput -T -c 450 415 20
+hdc shell uinput -T -c 480 415 20
+hdc shell uinput -T -c 510 415 20
+hdc shell uinput -T -c 540 415 20
+hdc shell uinput -T -c 570 415 20
+hdc shell uinput -T -c 600 415 20
+hdc shell uinput -T -c 630 415 20
+hdc shell uinput -T -c 660 415 20
+hdc shell uinput -T -c 690 415 20
+hdc shell uinput -T -c 720 415 20
+hdc shell uinput -T -c 150 445 20
+hdc shell uinput -T -c 180 445 20
+hdc shell uinput -T -c 210 445 20
+hdc shell uinput -T -c 240 445 20
+hdc shell uinput -T -c 270 445 20
+hdc shell uinput -T -c 300 445 20
+hdc shell uinput -T -c 330 445 20
+hdc shell uinput -T -c 360 445 20
+hdc shell uinput -T -c 390 445 20
+hdc shell uinput -T -c 420 445 20
+hdc shell uinput -T -c 450 445 20
+hdc shell uinput -T -c 480 445 20
+hdc shell uinput -T -c 510 445 20
+hdc shell uinput -T -c 540 445 20
+hdc shell uinput -T -c 570 445 20
+hdc shell uinput -T -c 600 445 20
+hdc shell uinput -T -c 630 445 20
+hdc shell uinput -T -c 660 445 20
+hdc shell uinput -T -c 690 445 20
+hdc shell uinput -T -c 720 445 20
+hdc shell uinput -T -c 150 475 20
+hdc shell uinput -T -c 180 475 20
+hdc shell uinput -T -c 210 475 20
+hdc shell uinput -T -c 240 475 20
+hdc shell uinput -T -c 270 475 20
+hdc shell uinput -T -c 300 475 20
+hdc shell uinput -T -c 330 475 20
+hdc shell uinput -T -c 360 475 20
+hdc shell uinput -T -c 390 475 20
+hdc shell uinput -T -c 420 475 20
+hdc shell uinput -T -c 450 475 20
+hdc shell uinput -T -c 480 475 20
+hdc shell uinput -T -c 510 475 20
+hdc shell uinput -T -c 540 475 20
+hdc shell uinput -T -c 570 475 20
+hdc shell uinput -T -c 600 475 20
+hdc shell uinput -T -c 630 475 20
+hdc shell uinput -T -c 660 475 20
+hdc shell uinput -T -c 690 475 20
+hdc shell uinput -T -c 720 475 20
+hdc shell uinput -T -c 150 505 20
+hdc shell uinput -T -c 180 505 20
+hdc shell uinput -T -c 210 505 20
+hdc shell uinput -T -c 240 505 20
+hdc shell uinput -T -c 270 505 20
+hdc shell uinput -T -c 300 505 20
+hdc shell uinput -T -c 330 505 20
+hdc shell uinput -T -c 360 505 20
+hdc shell uinput -T -c 390 505 20
+hdc shell uinput -T -c 420 505 20
+hdc shell uinput -T -c 450 505 20
+hdc shell uinput -T -c 480 505 20
+hdc shell uinput -T -c 510 505 20
+hdc shell uinput -T -c 540 505 20
+hdc shell uinput -T -c 570 505 20
+hdc shell uinput -T -c 600 505 20
+hdc shell uinput -T -c 630 505 20
+hdc shell uinput -T -c 660 505 20
+hdc shell uinput -T -c 690 505 20
+hdc shell uinput -T -c 720 505 20
+hdc shell uinput -T -c 150 535 20
+hdc shell uinput -T -c 180 535 20
+hdc shell uinput -T -c 210 535 20
+hdc shell uinput -T -c 240 535 20
+hdc shell uinput -T -c 270 535 20
+hdc shell uinput -T -c 300 535 20
+hdc shell uinput -T -c 330 535 20
+hdc shell uinput -T -c 360 535 20
+hdc shell uinput -T -c 390 535 20
+hdc shell uinput -T -c 420 535 20
+hdc shell uinput -T -c 450 535 20
+hdc shell uinput -T -c 480 535 20
+hdc shell uinput -T -c 510 535 20
+hdc shell uinput -T -c 540 535 20
+hdc shell uinput -T -c 570 535 20
+hdc shell uinput -T -c 600 535 20
+hdc shell uinput -T -c 630 535 20
+hdc shell uinput -T -c 660 535 20
+hdc shell uinput -T -c 690 535 20
+hdc shell uinput -T -c 720 535 20
+hdc shell uinput -T -c 150 565 20
+hdc shell uinput -T -c 180 565 20
+hdc shell uinput -T -c 210 565 20
+hdc shell uinput -T -c 240 565 20
+hdc shell uinput -T -c 270 565 20
+hdc shell uinput -T -c 300 565 20
+hdc shell uinput -T -c 330 565 20
+hdc shell uinput -T -c 360 565 20
+hdc shell uinput -T -c 390 565 20
+hdc shell uinput -T -c 420 565 20
+hdc shell uinput -T -c 450 565 20
+hdc shell uinput -T -c 480 565 20
+hdc shell uinput -T -c 510 565 20
+hdc shell uinput -T -c 540 565 20
+hdc shell uinput -T -c 570 565 20
+hdc shell uinput -T -c 600 565 20
+hdc shell uinput -T -c 630 565 20
+hdc shell uinput -T -c 660 565 20
+hdc shell uinput -T -c 690 565 20
+hdc shell uinput -T -c 720 565 20
+hdc shell uinput -T -c 150 595 20
+hdc shell uinput -T -c 180 595 20
+hdc shell uinput -T -c 210 595 20
+hdc shell uinput -T -c 240 595 20
+hdc shell uinput -T -c 270 595 20
+hdc shell uinput -T -c 300 595 20
+hdc shell uinput -T -c 330 595 20
+hdc shell uinput -T -c 360 595 20
+hdc shell uinput -T -c 390 595 20
+hdc shell uinput -T -c 420 595 20
+hdc shell uinput -T -c 450 595 20
+hdc shell uinput -T -c 480 595 20
+hdc shell uinput -T -c 510 595 20
+hdc shell uinput -T -c 540 595 20
+hdc shell uinput -T -c 570 595 20
+hdc shell uinput -T -c 600 595 20
+hdc shell uinput -T -c 630 595 20
+hdc shell uinput -T -c 660 595 20
+hdc shell uinput -T -c 690 595 20
+hdc shell uinput -T -c 720 595 20
+hdc shell uinput -T -c 150 625 20
+hdc shell uinput -T -c 180 625 20
+hdc shell uinput -T -c 210 625 20
+hdc shell uinput -T -c 240 625 20
+hdc shell uinput -T -c 270 625 20
+hdc shell uinput -T -c 300 625 20
+hdc shell uinput -T -c 330 625 20
+hdc shell uinput -T -c 360 625 20
+hdc shell uinput -T -c 390 625 20
+hdc shell uinput -T -c 420 625 20
+hdc shell uinput -T -c 450 625 20
+hdc shell uinput -T -c 480 625 20
+hdc shell uinput -T -c 510 625 20
+hdc shell uinput -T -c 540 625 20
+hdc shell uinput -T -c 570 625 20
+hdc shell uinput -T -c 600 625 20
+hdc shell uinput -T -c 630 625 20
+hdc shell uinput -T -c 660 625 20
+hdc shell uinput -T -c 690 625 20
+hdc shell uinput -T -c 720 625 20
+ ) else if %var% == 4 (
+:: 噩梦模式
+echo "Nightmare Mode"
+hdc shell uinput -T -c 300 85 50
+hdc shell uinput -T -c 30 160 50
+hdc shell uinput -T -c 60 160 50
+hdc shell uinput -T -c 90 160 50
+hdc shell uinput -T -c 120 160 50
+hdc shell uinput -T -c 150 160 50
+hdc shell uinput -T -c 180 160 50
+hdc shell uinput -T -c 210 160 50
+hdc shell uinput -T -c 240 160 50
+hdc shell uinput -T -c 270 160 50
+hdc shell uinput -T -c 300 160 50
+hdc shell uinput -T -c 330 160 50
+hdc shell uinput -T -c 360 160 50
+hdc shell uinput -T -c 390 160 50
+hdc shell uinput -T -c 420 160 50
+hdc shell uinput -T -c 450 160 50
+hdc shell uinput -T -c 480 160 50
+hdc shell uinput -T -c 510 160 50
+hdc shell uinput -T -c 540 160 50
+hdc shell uinput -T -c 570 160 50
+hdc shell uinput -T -c 600 160 50
+hdc shell uinput -T -c 630 160 50
+hdc shell uinput -T -c 660 160 50
+hdc shell uinput -T -c 690 160 50
+hdc shell uinput -T -c 720 160 50
+hdc shell uinput -T -c 750 160 50
+hdc shell uinput -T -c 780 160 50
+hdc shell uinput -T -c 810 160 50
+hdc shell uinput -T -c 840 160 50
+hdc shell uinput -T -c 30 190 50
+hdc shell uinput -T -c 60 190 50
+hdc shell uinput -T -c 90 190 50
+hdc shell uinput -T -c 120 190 50
+hdc shell uinput -T -c 150 190 50
+hdc shell uinput -T -c 180 190 50
+hdc shell uinput -T -c 210 190 50
+hdc shell uinput -T -c 240 190 50
+hdc shell uinput -T -c 270 190 50
+hdc shell uinput -T -c 300 190 50
+hdc shell uinput -T -c 330 190 50
+hdc shell uinput -T -c 360 190 50
+hdc shell uinput -T -c 390 190 50
+hdc shell uinput -T -c 420 190 50
+hdc shell uinput -T -c 450 190 50
+hdc shell uinput -T -c 480 190 50
+hdc shell uinput -T -c 510 190 50
+hdc shell uinput -T -c 540 190 50
+hdc shell uinput -T -c 570 190 50
+hdc shell uinput -T -c 600 190 50
+hdc shell uinput -T -c 630 190 50
+hdc shell uinput -T -c 660 190 50
+hdc shell uinput -T -c 690 190 50
+hdc shell uinput -T -c 720 190 50
+hdc shell uinput -T -c 750 190 50
+hdc shell uinput -T -c 780 190 50
+hdc shell uinput -T -c 810 190 50
+hdc shell uinput -T -c 840 190 50
+hdc shell uinput -T -c 30 220 50
+hdc shell uinput -T -c 60 220 50
+hdc shell uinput -T -c 90 220 50
+hdc shell uinput -T -c 120 220 50
+hdc shell uinput -T -c 150 220 50
+hdc shell uinput -T -c 180 220 50
+hdc shell uinput -T -c 210 220 50
+hdc shell uinput -T -c 240 220 50
+hdc shell uinput -T -c 270 220 50
+hdc shell uinput -T -c 300 220 50
+hdc shell uinput -T -c 330 220 50
+hdc shell uinput -T -c 360 220 50
+hdc shell uinput -T -c 390 220 50
+hdc shell uinput -T -c 420 220 50
+hdc shell uinput -T -c 450 220 50
+hdc shell uinput -T -c 480 220 50
+hdc shell uinput -T -c 510 220 50
+hdc shell uinput -T -c 540 220 50
+hdc shell uinput -T -c 570 220 50
+hdc shell uinput -T -c 600 220 50
+hdc shell uinput -T -c 630 220 50
+hdc shell uinput -T -c 660 220 50
+hdc shell uinput -T -c 690 220 50
+hdc shell uinput -T -c 720 220 50
+hdc shell uinput -T -c 750 220 50
+hdc shell uinput -T -c 780 220 50
+hdc shell uinput -T -c 810 220 50
+hdc shell uinput -T -c 840 220 50
+hdc shell uinput -T -c 30 250 50
+hdc shell uinput -T -c 60 250 50
+hdc shell uinput -T -c 90 250 50
+hdc shell uinput -T -c 120 250 50
+hdc shell uinput -T -c 150 250 50
+hdc shell uinput -T -c 180 250 50
+hdc shell uinput -T -c 210 250 50
+hdc shell uinput -T -c 240 250 50
+hdc shell uinput -T -c 270 250 50
+hdc shell uinput -T -c 300 250 50
+hdc shell uinput -T -c 330 250 50
+hdc shell uinput -T -c 360 250 50
+hdc shell uinput -T -c 390 250 50
+hdc shell uinput -T -c 420 250 50
+hdc shell uinput -T -c 450 250 50
+hdc shell uinput -T -c 480 250 50
+hdc shell uinput -T -c 510 250 50
+hdc shell uinput -T -c 540 250 50
+hdc shell uinput -T -c 570 250 50
+hdc shell uinput -T -c 600 250 50
+hdc shell uinput -T -c 630 250 50
+hdc shell uinput -T -c 660 250 50
+hdc shell uinput -T -c 690 250 50
+hdc shell uinput -T -c 720 250 50
+hdc shell uinput -T -c 750 250 50
+hdc shell uinput -T -c 780 250 50
+hdc shell uinput -T -c 810 250 50
+hdc shell uinput -T -c 840 250 50
+hdc shell uinput -T -c 30 280 50
+hdc shell uinput -T -c 60 280 50
+hdc shell uinput -T -c 90 280 50
+hdc shell uinput -T -c 120 280 50
+hdc shell uinput -T -c 150 280 50
+hdc shell uinput -T -c 180 280 50
+hdc shell uinput -T -c 210 280 50
+hdc shell uinput -T -c 240 280 50
+hdc shell uinput -T -c 270 280 50
+hdc shell uinput -T -c 300 280 50
+hdc shell uinput -T -c 330 280 50
+hdc shell uinput -T -c 360 280 50
+hdc shell uinput -T -c 390 280 50
+hdc shell uinput -T -c 420 280 50
+hdc shell uinput -T -c 450 280 50
+hdc shell uinput -T -c 480 280 50
+hdc shell uinput -T -c 510 280 50
+hdc shell uinput -T -c 540 280 50
+hdc shell uinput -T -c 570 280 50
+hdc shell uinput -T -c 600 280 50
+hdc shell uinput -T -c 630 280 50
+hdc shell uinput -T -c 660 280 50
+hdc shell uinput -T -c 690 280 50
+hdc shell uinput -T -c 720 280 50
+hdc shell uinput -T -c 750 280 50
+hdc shell uinput -T -c 780 280 50
+hdc shell uinput -T -c 810 280 50
+hdc shell uinput -T -c 840 280 50
+hdc shell uinput -T -c 30 310 50
+hdc shell uinput -T -c 60 310 50
+hdc shell uinput -T -c 90 310 50
+hdc shell uinput -T -c 120 310 50
+hdc shell uinput -T -c 150 310 50
+hdc shell uinput -T -c 180 310 50
+hdc shell uinput -T -c 210 310 50
+hdc shell uinput -T -c 240 310 50
+hdc shell uinput -T -c 270 310 50
+hdc shell uinput -T -c 300 310 50
+hdc shell uinput -T -c 330 310 50
+hdc shell uinput -T -c 360 310 50
+hdc shell uinput -T -c 390 310 50
+hdc shell uinput -T -c 420 310 50
+hdc shell uinput -T -c 450 310 50
+hdc shell uinput -T -c 480 310 50
+hdc shell uinput -T -c 510 310 50
+hdc shell uinput -T -c 540 310 50
+hdc shell uinput -T -c 570 310 50
+hdc shell uinput -T -c 600 310 50
+hdc shell uinput -T -c 630 310 50
+hdc shell uinput -T -c 660 310 50
+hdc shell uinput -T -c 690 310 50
+hdc shell uinput -T -c 720 310 50
+hdc shell uinput -T -c 750 310 50
+hdc shell uinput -T -c 780 310 50
+hdc shell uinput -T -c 810 310 50
+hdc shell uinput -T -c 840 310 50
+hdc shell uinput -T -c 30 340 50
+hdc shell uinput -T -c 60 340 50
+hdc shell uinput -T -c 90 340 50
+hdc shell uinput -T -c 120 340 50
+hdc shell uinput -T -c 150 340 50
+hdc shell uinput -T -c 180 340 50
+hdc shell uinput -T -c 210 340 50
+hdc shell uinput -T -c 240 340 50
+hdc shell uinput -T -c 270 340 50
+hdc shell uinput -T -c 300 340 50
+hdc shell uinput -T -c 330 340 50
+hdc shell uinput -T -c 360 340 50
+hdc shell uinput -T -c 390 340 50
+hdc shell uinput -T -c 420 340 50
+hdc shell uinput -T -c 450 340 50
+hdc shell uinput -T -c 480 340 50
+hdc shell uinput -T -c 510 340 50
+hdc shell uinput -T -c 540 340 50
+hdc shell uinput -T -c 570 340 50
+hdc shell uinput -T -c 600 340 50
+hdc shell uinput -T -c 630 340 50
+hdc shell uinput -T -c 660 340 50
+hdc shell uinput -T -c 690 340 50
+hdc shell uinput -T -c 720 340 50
+hdc shell uinput -T -c 750 340 50
+hdc shell uinput -T -c 780 340 50
+hdc shell uinput -T -c 810 340 50
+hdc shell uinput -T -c 840 340 50
+hdc shell uinput -T -c 30 370 50
+hdc shell uinput -T -c 60 370 50
+hdc shell uinput -T -c 90 370 50
+hdc shell uinput -T -c 120 370 50
+hdc shell uinput -T -c 150 370 50
+hdc shell uinput -T -c 180 370 50
+hdc shell uinput -T -c 210 370 50
+hdc shell uinput -T -c 240 370 50
+hdc shell uinput -T -c 270 370 50
+hdc shell uinput -T -c 300 370 50
+hdc shell uinput -T -c 330 370 50
+hdc shell uinput -T -c 360 370 50
+hdc shell uinput -T -c 390 370 50
+hdc shell uinput -T -c 420 370 50
+hdc shell uinput -T -c 450 370 50
+hdc shell uinput -T -c 480 370 50
+hdc shell uinput -T -c 510 370 50
+hdc shell uinput -T -c 540 370 50
+hdc shell uinput -T -c 570 370 50
+hdc shell uinput -T -c 600 370 50
+hdc shell uinput -T -c 630 370 50
+hdc shell uinput -T -c 660 370 50
+hdc shell uinput -T -c 690 370 50
+hdc shell uinput -T -c 720 370 50
+hdc shell uinput -T -c 750 370 50
+hdc shell uinput -T -c 780 370 50
+hdc shell uinput -T -c 810 370 50
+hdc shell uinput -T -c 840 370 50
+hdc shell uinput -T -c 30 400 50
+hdc shell uinput -T -c 60 400 50
+hdc shell uinput -T -c 90 400 50
+hdc shell uinput -T -c 120 400 50
+hdc shell uinput -T -c 150 400 50
+hdc shell uinput -T -c 180 400 50
+hdc shell uinput -T -c 210 400 50
+hdc shell uinput -T -c 240 400 50
+hdc shell uinput -T -c 270 400 50
+hdc shell uinput -T -c 300 400 50
+hdc shell uinput -T -c 330 400 50
+hdc shell uinput -T -c 360 400 50
+hdc shell uinput -T -c 390 400 50
+hdc shell uinput -T -c 420 400 50
+hdc shell uinput -T -c 450 400 50
+hdc shell uinput -T -c 480 400 50
+hdc shell uinput -T -c 510 400 50
+hdc shell uinput -T -c 540 400 50
+hdc shell uinput -T -c 570 400 50
+hdc shell uinput -T -c 600 400 50
+hdc shell uinput -T -c 630 400 50
+hdc shell uinput -T -c 660 400 50
+hdc shell uinput -T -c 690 400 50
+hdc shell uinput -T -c 720 400 50
+hdc shell uinput -T -c 750 400 50
+hdc shell uinput -T -c 780 400 50
+hdc shell uinput -T -c 810 400 50
+hdc shell uinput -T -c 840 400 50
+hdc shell uinput -T -c 30 430 50
+hdc shell uinput -T -c 60 430 50
+hdc shell uinput -T -c 90 430 50
+hdc shell uinput -T -c 120 430 50
+hdc shell uinput -T -c 150 430 50
+hdc shell uinput -T -c 180 430 50
+hdc shell uinput -T -c 210 430 50
+hdc shell uinput -T -c 240 430 50
+hdc shell uinput -T -c 270 430 50
+hdc shell uinput -T -c 300 430 50
+hdc shell uinput -T -c 330 430 50
+hdc shell uinput -T -c 360 430 50
+hdc shell uinput -T -c 390 430 50
+hdc shell uinput -T -c 420 430 50
+hdc shell uinput -T -c 450 430 50
+hdc shell uinput -T -c 480 430 50
+hdc shell uinput -T -c 510 430 50
+hdc shell uinput -T -c 540 430 50
+hdc shell uinput -T -c 570 430 50
+hdc shell uinput -T -c 600 430 50
+hdc shell uinput -T -c 630 430 50
+hdc shell uinput -T -c 660 430 50
+hdc shell uinput -T -c 690 430 50
+hdc shell uinput -T -c 720 430 50
+hdc shell uinput -T -c 750 430 50
+hdc shell uinput -T -c 780 430 50
+hdc shell uinput -T -c 810 430 50
+hdc shell uinput -T -c 840 430 50
+hdc shell uinput -T -c 30 460 50
+hdc shell uinput -T -c 60 460 50
+hdc shell uinput -T -c 90 460 50
+hdc shell uinput -T -c 120 460 50
+hdc shell uinput -T -c 150 460 50
+hdc shell uinput -T -c 180 460 50
+hdc shell uinput -T -c 210 460 50
+hdc shell uinput -T -c 240 460 50
+hdc shell uinput -T -c 270 460 50
+hdc shell uinput -T -c 300 460 50
+hdc shell uinput -T -c 330 460 50
+hdc shell uinput -T -c 360 460 50
+hdc shell uinput -T -c 390 460 50
+hdc shell uinput -T -c 420 460 50
+hdc shell uinput -T -c 450 460 50
+hdc shell uinput -T -c 480 460 50
+hdc shell uinput -T -c 510 460 50
+hdc shell uinput -T -c 540 460 50
+hdc shell uinput -T -c 570 460 50
+hdc shell uinput -T -c 600 460 50
+hdc shell uinput -T -c 630 460 50
+hdc shell uinput -T -c 660 460 50
+hdc shell uinput -T -c 690 460 50
+hdc shell uinput -T -c 720 460 50
+hdc shell uinput -T -c 750 460 50
+hdc shell uinput -T -c 780 460 50
+hdc shell uinput -T -c 810 460 50
+hdc shell uinput -T -c 840 460 50
+hdc shell uinput -T -c 30 490 50
+hdc shell uinput -T -c 60 490 50
+hdc shell uinput -T -c 90 490 50
+hdc shell uinput -T -c 120 490 50
+hdc shell uinput -T -c 150 490 50
+hdc shell uinput -T -c 180 490 50
+hdc shell uinput -T -c 210 490 50
+hdc shell uinput -T -c 240 490 50
+hdc shell uinput -T -c 270 490 50
+hdc shell uinput -T -c 300 490 50
+hdc shell uinput -T -c 330 490 50
+hdc shell uinput -T -c 360 490 50
+hdc shell uinput -T -c 390 490 50
+hdc shell uinput -T -c 420 490 50
+hdc shell uinput -T -c 450 490 50
+hdc shell uinput -T -c 480 490 50
+hdc shell uinput -T -c 510 490 50
+hdc shell uinput -T -c 540 490 50
+hdc shell uinput -T -c 570 490 50
+hdc shell uinput -T -c 600 490 50
+hdc shell uinput -T -c 630 490 50
+hdc shell uinput -T -c 660 490 50
+hdc shell uinput -T -c 690 490 50
+hdc shell uinput -T -c 720 490 50
+hdc shell uinput -T -c 750 490 50
+hdc shell uinput -T -c 780 490 50
+hdc shell uinput -T -c 810 490 50
+hdc shell uinput -T -c 840 490 50
+hdc shell uinput -T -c 30 520 50
+hdc shell uinput -T -c 60 520 50
+hdc shell uinput -T -c 90 520 50
+hdc shell uinput -T -c 120 520 50
+hdc shell uinput -T -c 150 520 50
+hdc shell uinput -T -c 180 520 50
+hdc shell uinput -T -c 210 520 50
+hdc shell uinput -T -c 240 520 50
+hdc shell uinput -T -c 270 520 50
+hdc shell uinput -T -c 300 520 50
+hdc shell uinput -T -c 330 520 50
+hdc shell uinput -T -c 360 520 50
+hdc shell uinput -T -c 390 520 50
+hdc shell uinput -T -c 420 520 50
+hdc shell uinput -T -c 450 520 50
+hdc shell uinput -T -c 480 520 50
+hdc shell uinput -T -c 510 520 50
+hdc shell uinput -T -c 540 520 50
+hdc shell uinput -T -c 570 520 50
+hdc shell uinput -T -c 600 520 50
+hdc shell uinput -T -c 630 520 50
+hdc shell uinput -T -c 660 520 50
+hdc shell uinput -T -c 690 520 50
+hdc shell uinput -T -c 720 520 50
+hdc shell uinput -T -c 750 520 50
+hdc shell uinput -T -c 780 520 50
+hdc shell uinput -T -c 810 520 50
+hdc shell uinput -T -c 840 520 50
+hdc shell uinput -T -c 30 550 50
+hdc shell uinput -T -c 60 550 50
+hdc shell uinput -T -c 90 550 50
+hdc shell uinput -T -c 120 550 50
+hdc shell uinput -T -c 150 550 50
+hdc shell uinput -T -c 180 550 50
+hdc shell uinput -T -c 210 550 50
+hdc shell uinput -T -c 240 550 50
+hdc shell uinput -T -c 270 550 50
+hdc shell uinput -T -c 300 550 50
+hdc shell uinput -T -c 330 550 50
+hdc shell uinput -T -c 360 550 50
+hdc shell uinput -T -c 390 550 50
+hdc shell uinput -T -c 420 550 50
+hdc shell uinput -T -c 450 550 50
+hdc shell uinput -T -c 480 550 50
+hdc shell uinput -T -c 510 550 50
+hdc shell uinput -T -c 540 550 50
+hdc shell uinput -T -c 570 550 50
+hdc shell uinput -T -c 600 550 50
+hdc shell uinput -T -c 630 550 50
+hdc shell uinput -T -c 660 550 50
+hdc shell uinput -T -c 690 550 50
+hdc shell uinput -T -c 720 550 50
+hdc shell uinput -T -c 750 550 50
+hdc shell uinput -T -c 780 550 50
+hdc shell uinput -T -c 810 550 50
+hdc shell uinput -T -c 840 550 50
+hdc shell uinput -T -c 30 580 50
+hdc shell uinput -T -c 60 580 50
+hdc shell uinput -T -c 90 580 50
+hdc shell uinput -T -c 120 580 50
+hdc shell uinput -T -c 150 580 50
+hdc shell uinput -T -c 180 580 50
+hdc shell uinput -T -c 210 580 50
+hdc shell uinput -T -c 240 580 50
+hdc shell uinput -T -c 270 580 50
+hdc shell uinput -T -c 300 580 50
+hdc shell uinput -T -c 330 580 50
+hdc shell uinput -T -c 360 580 50
+hdc shell uinput -T -c 390 580 50
+hdc shell uinput -T -c 420 580 50
+hdc shell uinput -T -c 450 580 50
+hdc shell uinput -T -c 480 580 50
+hdc shell uinput -T -c 510 580 50
+hdc shell uinput -T -c 540 580 50
+hdc shell uinput -T -c 570 580 50
+hdc shell uinput -T -c 600 580 50
+hdc shell uinput -T -c 630 580 50
+hdc shell uinput -T -c 660 580 50
+hdc shell uinput -T -c 690 580 50
+hdc shell uinput -T -c 720 580 50
+hdc shell uinput -T -c 750 580 50
+hdc shell uinput -T -c 780 580 50
+hdc shell uinput -T -c 810 580 50
+hdc shell uinput -T -c 840 588 50
+hdc shell uinput -T -c 30 610 50
+hdc shell uinput -T -c 60 610 50
+hdc shell uinput -T -c 90 610 50
+hdc shell uinput -T -c 120 610 50
+hdc shell uinput -T -c 150 610 50
+hdc shell uinput -T -c 180 610 50
+hdc shell uinput -T -c 210 610 50
+hdc shell uinput -T -c 240 610 50
+hdc shell uinput -T -c 270 610 50
+hdc shell uinput -T -c 300 610 50
+hdc shell uinput -T -c 330 610 50
+hdc shell uinput -T -c 360 610 50
+hdc shell uinput -T -c 390 610 50
+hdc shell uinput -T -c 420 610 50
+hdc shell uinput -T -c 450 610 50
+hdc shell uinput -T -c 480 610 50
+hdc shell uinput -T -c 510 610 50
+hdc shell uinput -T -c 540 610 50
+hdc shell uinput -T -c 570 610 50
+hdc shell uinput -T -c 600 610 50
+hdc shell uinput -T -c 630 610 50
+hdc shell uinput -T -c 660 610 50
+hdc shell uinput -T -c 690 610 50
+hdc shell uinput -T -c 720 610 50
+hdc shell uinput -T -c 750 610 50
+hdc shell uinput -T -c 780 610 50
+hdc shell uinput -T -c 810 610 50
+hdc shell uinput -T -c 840 610 50
+hdc shell uinput -T -c 30 640 50
+hdc shell uinput -T -c 60 640 50
+hdc shell uinput -T -c 90 640 50
+hdc shell uinput -T -c 120 640 50
+hdc shell uinput -T -c 150 640 50
+hdc shell uinput -T -c 180 640 50
+hdc shell uinput -T -c 210 640 50
+hdc shell uinput -T -c 240 640 50
+hdc shell uinput -T -c 270 640 50
+hdc shell uinput -T -c 300 640 50
+hdc shell uinput -T -c 330 640 50
+hdc shell uinput -T -c 360 640 50
+hdc shell uinput -T -c 390 640 50
+hdc shell uinput -T -c 420 640 50
+hdc shell uinput -T -c 450 640 50
+hdc shell uinput -T -c 480 640 50
+hdc shell uinput -T -c 510 640 50
+hdc shell uinput -T -c 540 640 50
+hdc shell uinput -T -c 570 640 50
+hdc shell uinput -T -c 600 640 50
+hdc shell uinput -T -c 630 640 50
+hdc shell uinput -T -c 660 640 50
+hdc shell uinput -T -c 690 640 50
+hdc shell uinput -T -c 720 640 50
+hdc shell uinput -T -c 750 640 50
+hdc shell uinput -T -c 780 640 50
+hdc shell uinput -T -c 810 640 50
+hdc shell uinput -T -c 840 640 50
+hdc shell uinput -T -c 30 670 50
+hdc shell uinput -T -c 60 670 50
+hdc shell uinput -T -c 90 670 50
+hdc shell uinput -T -c 120 670 50
+hdc shell uinput -T -c 150 670 50
+hdc shell uinput -T -c 180 670 50
+hdc shell uinput -T -c 210 670 50
+hdc shell uinput -T -c 240 670 50
+hdc shell uinput -T -c 270 670 50
+hdc shell uinput -T -c 300 670 50
+hdc shell uinput -T -c 330 670 50
+hdc shell uinput -T -c 360 670 50
+hdc shell uinput -T -c 390 670 50
+hdc shell uinput -T -c 420 670 50
+hdc shell uinput -T -c 450 670 50
+hdc shell uinput -T -c 480 670 50
+hdc shell uinput -T -c 510 670 50
+hdc shell uinput -T -c 540 670 50
+hdc shell uinput -T -c 570 670 50
+hdc shell uinput -T -c 600 670 50
+hdc shell uinput -T -c 630 670 50
+hdc shell uinput -T -c 660 670 50
+hdc shell uinput -T -c 690 670 50
+hdc shell uinput -T -c 720 670 50
+hdc shell uinput -T -c 750 670 50
+hdc shell uinput -T -c 780 670 50
+hdc shell uinput -T -c 810 670 50
+hdc shell uinput -T -c 840 670 50
+ ) else (
+:: 输入其他参数退出程序
+echo "input wrong number,exit program."
+ )
+pause
+
+
+
+
diff --git a/minesweeping/minesweeper/Minesweeper/.gitignore b/minesweeping/minesweeper/Minesweeper/.gitignore
new file mode 100644
index 0000000..fbabf77
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/.gitignore
@@ -0,0 +1,11 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/AppScope/app.json5 b/minesweeping/minesweeper/Minesweeper/AppScope/app.json5
new file mode 100644
index 0000000..1b989b8
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.example.minesweeper",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
diff --git a/minesweeping/minesweeper/Minesweeper/AppScope/resources/base/element/string.json b/minesweeping/minesweeper/Minesweeper/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000..73756fc
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "Minesweeper"
+ }
+ ]
+}
diff --git a/minesweeping/minesweeper/Minesweeper/AppScope/resources/base/media/app_icon.png b/minesweeping/minesweeper/Minesweeper/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/AppScope/resources/base/media/app_icon.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/build-profile.json5 b/minesweeping/minesweeper/Minesweeper/build-profile.json5
new file mode 100644
index 0000000..447c23c
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/build-profile.json5
@@ -0,0 +1,50 @@
+{
+ "app": {
+ "signingConfigs": [
+ {
+ "name": "default",
+ "type": "HarmonyOS",
+ "material": {
+ "certpath": "C:\\Users\\admin\\.ohos\\config\\auto_debug_Minesweeper_com.example.minesweeper_70086000195336234.cer",
+ "storePassword": "0000001B81425ACE9EF495F6D1A0A0957B17F7AA6771DC03D913D1A993457211C787353765299FEA76D93E",
+ "keyAlias": "debugKey",
+ "keyPassword": "0000001B658FCE1E5B73FA235DF3A22A7A7B3BA678B311C88D3FC326CC6454FFA2A4CE62214A669FAEAF85",
+ "profile": "C:\\Users\\admin\\.ohos\\config\\auto_debug_Minesweeper_com.example.minesweeper_70086000195336234.p7b",
+ "signAlg": "SHA256withECDSA",
+ "storeFile": "C:\\Users\\admin\\.ohos\\config\\auto_debug_Minesweeper_com.example.minesweeper_70086000195336234.p12"
+ }
+ }
+ ],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 10,
+ "compatibleSdkVersion": 9,
+ "runtimeOS": "OpenHarmony",
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug",
+ },
+ {
+ "name": "release"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/.gitignore b/minesweeping/minesweeper/Minesweeper/entry/.gitignore
new file mode 100644
index 0000000..e2713a2
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/build-profile.json5 b/minesweeping/minesweeper/Minesweeper/entry/build-profile.json5
new file mode 100644
index 0000000..197e83c
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/build-profile.json5
@@ -0,0 +1,31 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ "arkOptions": {
+ // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
+ }
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": true,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/hvigorfile.ts b/minesweeping/minesweeper/Minesweeper/entry/hvigorfile.ts
new file mode 100644
index 0000000..c6edcd9
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/obfuscation-rules.txt b/minesweeping/minesweeper/Minesweeper/entry/obfuscation-rules.txt
new file mode 100644
index 0000000..985b2ae
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/obfuscation-rules.txt
@@ -0,0 +1,18 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/oh-package.json5 b/minesweeping/minesweeper/Minesweeper/entry/oh-package.json5
new file mode 100644
index 0000000..225946c
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "license": "",
+ "devDependencies": {},
+ "author": "",
+ "name": "entry",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/classes/Mine.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/classes/Mine.ets
new file mode 100644
index 0000000..a1361a0
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/classes/Mine.ets
@@ -0,0 +1,283 @@
+//数据结构
+export class MineData {
+ boardRows:number//行数
+ boardCols:number//列数
+ gameOver:boolean//游戏是否结束
+ timeRun:boolean//计时器是否启动
+ timeLimit:number//扫雷限时
+ clock:number//扫雷用时记录
+ mineWithFlag:number//是地雷被标棋子的总数
+ noMineWithFlag:number//不是地雷但被标棋子的总数
+ openButtons:number//所有被打开的按钮的总数,等于所有按钮数-所有雷数
+ mines:number//总的雷数
+ mine_number:number //剩余的地雷数量
+ ifClock:boolean //是否开始计时
+ gridSize:number//格子大小
+ ifStart:boolean//游戏是否开始
+ winFlag:boolean//游戏是否获胜
+ boardOffset:number//画布偏移值
+ setMode:number//模式选择
+
+ initData:string[][]//存储初始布局数据 0 无雷 M 有雷
+ mineNumData:string[][]//无雷方块周围雷数的数据结构 取值1~8
+ showBoardState:string[][]//计算周围雷数数组
+ curData:string[][]//扫雷过程状态数据结构 =E:空白,未挖开/凸方块;=B:已挖开, 非雷/0平方块; =1-8:已挖开,周围雷的数目; =X:已挖开,雷/红底黑雷;=M:未挖开的雷;=F:标记为雷/红旗。
+ sweeperFlag:boolean[][]//自动扫雷标记数组
+
+ //初始化
+ constructor(row:number=10,col:number=10,mines:number=10,timeLimit:number=600,boardOffset:number=8) {
+ this.boardRows=row
+ this.boardCols=col
+ this.gameOver=false
+ this.timeRun=false
+ this.timeLimit=timeLimit
+ this.clock=0
+ this.mineWithFlag=0
+ this.noMineWithFlag=0
+ this.openButtons=0
+ this.mines=mines
+ this.mine_number=this.mines
+ this.ifClock=false
+ this.gridSize=18
+ this.ifStart=false
+ this.winFlag=false
+ this.boardOffset=boardOffset
+ this.setMode=0
+
+ this.initData= new Array(row)
+ this.mineNumData=new Array(row)
+ this.showBoardState=new Array(row)
+ this.curData=new Array(row)
+ this.sweeperFlag=new Array(row)
+
+ for (let i = 0; i < row; i++) {
+ this.initData[i] = new Array(col)
+ this.mineNumData[i]=new Array(col)
+ this.showBoardState[i]=new Array(col)
+ this.curData[i]=new Array(col)
+ this.sweeperFlag[i]=new Array(col)
+ for (let j = 0; j < col; j++) {
+ this.showBoardState[i][j]='0'
+ this.mineNumData[i][j]='0'
+ this.curData[i][j]='E'
+ this.initData[i][j]='0'
+ this.sweeperFlag[i][j]=false
+ }
+ }
+ }
+
+ //测试
+ display(){
+ for (let i = 0; i < this.boardRows; i++) {
+ for (let j = 0; j < this.boardCols; j++) {
+ }
+ // console.log(this.initData[i].toString())
+ console.log(this.curData[i].toString())
+ }
+ }
+
+ //初始化地雷图
+ init_mine_map(){
+ //无雷初始化,先列后行
+ for (let i = 0; i < this.boardRows; i++) {
+ for (let j = 0; j < this.boardCols; j++) {
+ this.initData[i][j]='0'
+ }
+ }
+
+ //在boardRows*boardCols范围中随机生成mines个雷
+ for(let i = 0; i < this.mines; i++) {
+ let randomIndex: number
+ let row: number
+ let col: number
+ let flag:boolean=true
+ while(flag){
+ // 生成一个随机索引,范围从0到rows * cols - 1
+ randomIndex = Math.floor(Math.random() * (this.boardRows * this.boardCols));
+ // 计算随机索引对应的行列
+ row = Math.floor(randomIndex / this.boardCols);
+ col = randomIndex % this.boardCols;
+ // 在initData中对应位置放置'M'(地雷)
+ if(this.initData[row][col] == '0'){//该位置没有放雷
+ this.initData[row][col] = 'M';
+ flag=false
+ }
+ }
+ }
+
+ }
+
+
+ // 随机设置状态
+ random_set_state(){
+ // 随机状态数列
+ let randomList = ['E', 'M', 'B', 'X', 'F', '1', '2', '3', '4', '5', '6', '7', '8'];
+
+ // 矩阵初始化
+ for (let r = 0; r < this.boardRows; r++) {
+ for (let c = 0; c < this.boardCols; c++) {
+ this.curData[r][c] = '0';
+ }
+ }
+
+ // 为矩阵的每个元素赋予随机状态
+ for (let r = 0; r < this.boardRows; r++) {
+ for (let c = 0; c < this.boardCols; c++) {
+ // 获取随机下标
+ let r_index = Math.floor(Math.random() * randomList.length);
+ // 随机赋予状态
+ this.curData[r][c] = randomList[r_index];
+ }
+ }
+ }
+
+ //展示地雷状态
+ show_board_state_data(){
+ // 拷贝布雷方案到mineNumData
+ for (let i = 0; i < this.boardRows; i++) {
+ for (let j = 0; j < this.boardCols; j++) {
+ this.mineNumData[i][j]=this.initData[i][j]//拷贝布雷方案
+ }
+ }
+
+ // 遍历布雷方案,计算并设置每个非雷位置周围的雷数
+ for (let i = 0; i < this.boardRows; i++) {
+ for (let j = 0; j < this.boardCols; j++) {
+ if (this.initData[i][j] == 'M') { // 如果为雷,跳过
+ continue;
+ } else { // 如果不为雷,计算周围雷数
+ let aroundxy:number[][] = this.around(i, j);
+ let minesum = 0;
+ for (let [r, c] of aroundxy) {
+ // 检查initData在对应位置的值是否为'M'
+ if (this.initData[r] && this.initData[r][c] === 'M') {
+ // 如果是,则minesum加1
+ minesum++;
+ }
+ }
+ this.mineNumData[i][j] = minesum.toString(); // 把值改成周围雷的数量
+ }
+ }
+ }
+
+ for (let i = 0; i < this.boardRows; i++) {
+ for (let j = 0; j < this.boardCols; j++) {
+ this.curData[i][j]=this.mineNumData[i][j]
+ }
+ }
+ }
+
+ // 返回对应坐标周围八个方块坐标列表
+ around(x:number, y:number) {
+ // 创建一个空数组来存储周围的坐标
+ let neighbors:number[][]=[];
+
+ // 遍历周围的八个方向(不包括自身)
+ for (let i = Math.max(0, x - 1); i <= Math.min(this.boardRows - 1, x + 1); i++) {
+ for (let j = Math.max(0, y - 1); j <= Math.min(this.boardCols - 1, y + 1); j++) {
+ // 如果当前坐标不是自身,则添加到数组中
+ if (i !== x || j !== y) {
+ neighbors.push([i, j]);
+ }
+ }
+ }
+ // 返回周围的坐标列表
+ return neighbors;
+ }
+
+ //初始化方块状态
+ init_board_state() {
+ for (let i = 0; i < this.boardRows; i++) {
+ for (let j = 0; j < this.boardCols; j++) {
+ this.curData[i][j] = 'E'
+ this.showBoardState[i][j] = '0'
+ }
+ }
+ }
+
+ //返回对应坐标周围的坐标列表
+ get_around_xy(x:number, y:number){
+ // 创建一个空数组来存储周围的坐标
+ let neighbors:number[][]=[];
+
+ // 遍历周围的八个方向(不包括自身)
+ for (let i = Math.max(0, x - 1); i <= Math.min(this.boardRows - 1, x + 1); i++) {
+ for (let j = Math.max(0, y - 1); j <= Math.min(this.boardCols - 1, y + 1); j++) {
+ // 如果当前坐标不是自身,则添加到数组中
+ if (i != x || j != y) {
+ neighbors.push([i, j]);
+ }
+ }
+ }
+ // 返回周围的坐标列表
+ return neighbors;
+ }
+
+ // 递归获取周围雷数
+ get_around_mine_num(x:number, y:number){
+ if(this.initData[x][y]=='M'){//挖开的是雷,游戏结束
+ this.curData[x][y]='X'//更新状态为翻开的雷
+ return 0
+ }
+ let around_xy=this.get_around_xy(x,y)//周围按钮的下标
+ let num=this.num_of_mine(x,y)//记录周围的总雷数
+ if(num==0){//如果为0,更新状态为B且递归调用函数进行雷数计算
+ this.curData[x][y]='B'
+ for (let [i, j] of around_xy) {
+ if (this.curData[i] && this.curData[i][j] == 'E') {
+ this.get_around_mine_num(i,j)
+ }
+ }
+ }
+ return 1//返回结果不是雷,且方块已经打开,显示结果
+ }
+
+ //标志旗子
+ show_flag(x:number, y:number) {
+ if (this.curData[x][y] == 'E') { //若按钮未打开且未标记,则显示旗子标志
+ this.curData[x][y] = 'F'
+ } else if (this.curData[x][y] == 'F') { //若按钮未打开且已经标记为,则取消显示
+ this.curData[x][y] = 'E'
+ } else {//如果按钮已经打开,则不做任何操作
+ return
+ }
+ }
+
+ //得到剩余雷数
+ remaining_mine_num() {
+ this.mineWithFlag=0
+ this.noMineWithFlag=0
+ this.openButtons=0
+ for (let i = 0; i < this.boardRows; i++) {
+ for (let j = 0; j < this.boardCols; j++) {
+ if (this.initData[i][j] == 'M' && this.curData[i][j] == 'F') {//如果该按钮下地雷被标旗子
+ this.mineWithFlag += 1
+ }else if (this.initData[i][j] != 'M' && this.curData[i][j] == 'F'){//如果该按钮下无地雷被标旗子
+ this.noMineWithFlag+= 1
+ }else if (this.initData[i][j] != 'M' && this.curData[i][j] != 'E'){//如果该按钮不是雷且已被打开
+ this.openButtons+=1
+ }
+ }
+ }
+ this.mine_number = this.mines - (this.mineWithFlag + this.noMineWithFlag)
+ if (this.mine_number< 0){//如无雷也被标记红旗,可能出现标记红旗的按钮数大于地雷数,雷数不能为负
+ this.mine_number=0
+ }
+ }
+
+ //获取(x,y)处周围的雷数
+ num_of_mine(x:number, y:number){
+ let minenum = 0 //保存雷数
+ if (this.initData[x][y] != 'M'){ // 如果不是雷
+ for (let [r, c] of this.get_around_xy(x,y)) {
+ if (this.initData[r] && this.initData[r][c] == 'M') {
+ minenum++;
+ }
+ }
+ this.curData[x][y]=minenum.toString() //# 更新改方块的状态
+ }
+ return minenum//# 不是雷,返回周围雷数
+ }
+}
+
+
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/classes/TCPSocket.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/classes/TCPSocket.ets
new file mode 100644
index 0000000..9792e95
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/classes/TCPSocket.ets
@@ -0,0 +1,88 @@
+import socket from '@ohos.net.socket';
+import wifi from '@ohos.wifiManager';
+import {resolveIP} from '../utils/util'
+import { BusinessError } from '@ohos.base';
+
+class SocketInfo {
+ message: ArrayBuffer = new ArrayBuffer(10);
+ remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
+}
+
+const TAG='TCPSocket'
+
+export default class TCPSocket{
+ tcp:socket.TCPSocket
+
+ constructor() {
+ this.tcp = socket.constructTCPSocketInstance();
+ }
+
+ bindLocalAddr: socket.NetAddress = {
+ address: resolveIP(wifi.getIpInfo().ipAddress),
+ port: 8888
+ }
+
+ tcpconnectoptions: socket.TCPConnectOptions = {
+ address: {
+ address:"192.168.184.229",//服务端IP
+ port: 8888
+ },
+ timeout: 6000
+ }
+
+ TCPBind(){
+ this.tcp.bind(this.bindLocalAddr).then(() => {
+ console.info(TAG,'bind success');
+ }).catch((err:BusinessError) => {
+ console.info(TAG,'bind fail:err code='+err.code+' err message='+err.message);
+ });
+ }
+
+ TCPConnect(){
+ this.tcp.connect(this.tcpconnectoptions, (err: BusinessError) => {
+ if (err) {
+ console.info(TAG,'connect fail:err code='+err.code+' err message='+err.message);
+ return;
+ }
+ console.info(TAG,'connect success');
+ })
+ }
+
+ TCPSend(data:string='AutoMineSweeper'){
+ let tcpSendOptions: socket.TCPSendOptions = {
+ data:data
+ }
+ this.tcp.send(tcpSendOptions).then(() => {
+ console.info(TAG,'send success data='+data);
+ }).catch((err:BusinessError) => {
+ console.info(TAG,'send fail:err code='+err.code+' err message='+err.message);
+ });
+ }
+
+ TCPClose(){
+ this.tcp.close().then(() => {
+ console.info(TAG,'close success');
+ }).catch((err:BusinessError) => {
+ console.info(TAG,'close fail:err code='+err.code+' err message='+err.message);
+ });
+ }
+
+ TCPOff(type?:string){
+ setTimeout(() => {
+ this.tcp.close((err:BusinessError) => {
+ console.log('close socket.');
+ });
+ if(type=='message'){
+ this.tcp.off('message');
+ }else if(type=='connect'){
+ this.tcp.off('connect');
+ }else if(type=='close'){
+ this.tcp.off('close');
+ }else{
+ this.tcp.off('message');
+ this.tcp.off('connect');
+ this.tcp.off('close');
+ }
+ }, 60 * 1000);
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/constants/CommonConstants.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/constants/CommonConstants.ets
new file mode 100644
index 0000000..8bc5d58
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/constants/CommonConstants.ets
@@ -0,0 +1,26 @@
+//公共常量
+export const boardNum: number = 15; //行列数
+export const gridSize: number = 20; //格子大小
+
+//绘图组件canvas的设置及上下文
+export const settings: RenderingContextSettings = new RenderingContextSettings(true);
+export const context: CanvasRenderingContext2D = new CanvasRenderingContext2D(settings);
+
+export const settings2: RenderingContextSettings = new RenderingContextSettings(true);
+export const context2: CanvasRenderingContext2D = new CanvasRenderingContext2D(settings2);
+
+//图片资源
+export const imgM:ImageBitmap = new ImageBitmap("common/pictures/icon_mine.png");//地雷
+export const imgR:ImageBitmap = new ImageBitmap("common/pictures/icon_redMine.png");//爆炸雷
+export const imgF:ImageBitmap = new ImageBitmap("common/pictures/icon_redFlag.png");//红旗
+export const imgC:ImageBitmap = new ImageBitmap("common/pictures/icon_redCross.png");//红叉(标错雷)
+export const imgB:ImageBitmap = new ImageBitmap("common/pictures/icon_0.jpg");//方块
+export const img1:ImageBitmap = new ImageBitmap("common/pictures/icon_1.jpg");//周围雷数1
+export const img2:ImageBitmap = new ImageBitmap("common/pictures/icon_2.jpg");//周围雷数2
+export const img3:ImageBitmap = new ImageBitmap("common/pictures/icon_3.jpg");//周围雷数3
+export const img4:ImageBitmap = new ImageBitmap("common/pictures/icon_4.jpg");//周围雷数4
+export const img5:ImageBitmap = new ImageBitmap("common/pictures/icon_5.jpg");//周围雷数5
+export const img6:ImageBitmap = new ImageBitmap("common/pictures/icon_6.jpg");//周围雷数6
+export const img7:ImageBitmap = new ImageBitmap("common/pictures/icon_7.jpg");//周围雷数7
+export const img8:ImageBitmap = new ImageBitmap("common/pictures/icon_8.jpg");//周围雷数8
+
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_0.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_0.jpg
new file mode 100644
index 0000000..62f452c
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_0.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_1.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_1.jpg
new file mode 100644
index 0000000..e5cf312
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_1.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_2.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_2.jpg
new file mode 100644
index 0000000..3d176c9
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_2.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_3.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_3.jpg
new file mode 100644
index 0000000..768ca2b
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_3.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_4.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_4.jpg
new file mode 100644
index 0000000..e05ed39
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_4.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_5.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_5.jpg
new file mode 100644
index 0000000..8dc3130
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_5.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_6.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_6.jpg
new file mode 100644
index 0000000..c84606b
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_6.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_7.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_7.jpg
new file mode 100644
index 0000000..8604dcd
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_7.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_8.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_8.jpg
new file mode 100644
index 0000000..96b11f6
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_8.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_9.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_9.jpg
new file mode 100644
index 0000000..cfb3837
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_9.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_cry.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_cry.png
new file mode 100644
index 0000000..ba49020
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_cry.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_mine.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_mine.png
new file mode 100644
index 0000000..bb4fc28
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_mine.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_mine2.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_mine2.png
new file mode 100644
index 0000000..05c43bb
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_mine2.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redCross.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redCross.png
new file mode 100644
index 0000000..01ccc3d
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redCross.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redFlag.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redFlag.png
new file mode 100644
index 0000000..129a133
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redFlag.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redMine.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redMine.png
new file mode 100644
index 0000000..58f0c55
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_redMine.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_smile.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_smile.png
new file mode 100644
index 0000000..95372db
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/common/pictures/icon_smile.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Header.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Header.ets
new file mode 100644
index 0000000..4442db5
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Header.ets
@@ -0,0 +1,64 @@
+import ModeSelect from './ModeSelect'
+import {MineData} from '../classes/Mine'
+import {alertDialog} from '../utils/util'
+
+//头部功能栏
+@Component
+export default struct Header {
+ @Link mineData:MineData
+ @Link timers:number[]
+ rule:string="游戏说明:\n玩家点击左上角游戏菜单可选择相应等级进行游戏。右侧栏是游戏设置栏,用户可在规则内进行自定义游戏设置。\n规则:\n1 参数必须为正整数,且行数必须在[6,18]范围之内,列数必须在[6,28]范围之内;\n2雷数不能大于行列数的乘积,游戏限时不能超过99999s,且必须在右上角的规定的限制时间内完成,否则游戏失败;\n3左击方块,是雷游戏结束,显示哭脸,否则显示相邻八块方块的总地雷数,为空表示相邻八块方块无雷。当把所有无雷方块都翻开或者把有雷的方块都标记,则游戏胜利,显示耍酷脸。\n4右击方块标记红旗表示有雷,再右击取消标记。点击脸图开始游戏,再次点击暂停游戏。\n5点击自动扫雷,程序可自动完成扫雷。\n"
+ //模式选择弹窗控制器
+ ModeSelectDialogController: CustomDialogController = new CustomDialogController({
+ builder: ModeSelect({mineData:$mineData,timers:$timers}),
+ gridCount: 4
+ })
+
+ build() {
+ Row() {
+ //难度选择
+ Text('难度选择')
+ .fontSize(16)
+ .fontWeight(FontWeight.Bold)
+ .margin({left:5,right:5})
+ .onClick(()=>{
+ this.ModeSelectDialogController.open()
+ })
+
+ //帮助
+ Text('帮助')
+ .fontSize(16)
+ .fontWeight(FontWeight.Bold)
+ .margin({right:5})
+ .onClick(()=>{
+ alertDialog(this.rule)
+ })
+
+ //退出游戏
+ Text('退出游戏')
+ .fontSize(16)
+ .fontWeight(FontWeight.Bold)
+ .margin({right:5})
+ .onClick(()=>{
+ globalThis.context.terminateSelf()//销毁自身 可用于真机上退出应用
+ })
+
+ //logo
+ Row(){
+ Image($r('app.media.icon_logo'))
+ .objectFit(ImageFit.Contain)
+ .width(30)
+
+ Text('扫雷')
+ .fontSize(15)
+ .fontWeight(FontWeight.Bold)
+ }
+ .width('75%')
+ .justifyContent(FlexAlign.End)
+
+ }
+ .justifyContent(FlexAlign.Start)
+ .width('100%')
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Input.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Input.ets
new file mode 100644
index 0000000..8f7d95b
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Input.ets
@@ -0,0 +1,32 @@
+@Component
+export default struct Input {
+ //表示是否聚焦(通过焦点来判断)
+ @State isFocus: boolean = false
+ title: string
+ inputType: InputType = InputType.Normal
+ placeholder:string=''
+ change = (val:string) => {}
+
+ build() {
+ Row() {
+ Text(this.title)
+ .width(80)
+ .textAlign(TextAlign.Start)
+ .fontSize(16)
+ .fontWeight(600)
+
+ TextInput({placeholder:this.placeholder})
+ .onFocus(() => {this.isFocus = true})
+ .onChange((val: string) =>{this.change(val)})
+ .placeholderColor(`rgba(0,40,132,0.6)`)
+ .placeholderFont({size: 14, weight: 400})
+ .backgroundColor('#FBFBFD')
+ .width(150)
+ .borderRadius(5)
+ .fontSize(14)
+ .type(this.inputType)
+ }
+ .width('100%')
+ .height(30)
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Main.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Main.ets
new file mode 100644
index 0000000..3d19d5b
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/Main.ets
@@ -0,0 +1,189 @@
+import * as CommonConstants from '../common/constants/CommonConstants'
+import {drawBoard,deleteBrisk,drawFlag,deleteFlag,show_all_mines,show_game_window,win,clearAllTimers} from '../utils/util'
+import { MineData } from '../classes/Mine'
+import MessageDialog from '../components/MessageDialog'
+
+//主体区域
+@Component
+export default struct Main {
+ @State ifFlag: boolean = false //是否为插旗状态
+ @State message: string = '' //提示信息
+ @Link mineData: MineData
+ @Link timers: number[]
+ private playX: number; //下棋位置的横坐标
+ private playY: number; //下棋位置的纵坐标
+ MessageDialogController: CustomDialogController = new CustomDialogController({
+ builder: MessageDialog({ msg: $message }),
+ gridCount: 5
+ })
+
+ build() {
+ Column() {
+ Row() {
+ //地雷数目
+ Row() {
+ Image($r('app.media.icon_mine'))
+ .objectFit(ImageFit.Contain)
+ .width(20)
+ Text(this.mineData.mine_number.toString())
+ }
+
+ //笑脸按钮
+ Image(this.mineData.gameOver ? this.mineData.winFlag ? $r('app.media.icon_cool') : $r('app.media.icon_cry') : this.ifFlag ? $r('app.media.icon_cool') : $r('app.media.icon_smile'))
+ .objectFit(ImageFit.Contain)
+ .width(20)
+ .onClick(() => {
+ if (!this.mineData.timeRun) {
+ this.mineData.timeRun = true
+ let timer = setInterval(() => { //设置定时器
+ this.mineData.clock++
+ }, 1000)
+ this.timers.push(timer)
+ } else {
+ this.ifFlag = !this.ifFlag
+ }
+ })
+
+ //计时器
+ Row() {
+ Image($r('app.media.icon_clock'))
+ .objectFit(ImageFit.Contain)
+ .width(20)
+ .margin({ right: 5 })
+
+ Text(this.mineData.clock.toString())
+ }
+
+ //时间限制
+ Row() {
+ Image($r('app.media.icon_hourglass'))
+ .objectFit(ImageFit.Contain)
+ .width(20)
+ .margin({ right: 5 })
+
+ Text(this.mineData.timeLimit.toString())
+ }
+ }
+ .padding({ left: 30, right: 30 })
+ .justifyContent(FlexAlign.SpaceBetween)
+ .width('100%')
+ .height(20)
+
+ Stack() {
+ //绘制棋盘
+ Canvas(CommonConstants.context)
+ .width(this.mineData.boardCols * CommonConstants.gridSize + this.mineData.boardOffset)
+ .height(this.mineData.boardRows * CommonConstants.gridSize + this.mineData.boardOffset)
+ .backgroundColor('rgba(192,192,192,0.8)')
+ .onReady(() => {
+ drawBoard(this.mineData, this.mineData.boardRows, this.mineData.boardCols)
+ this.mineData.init_mine_map()
+ this.mineData.init_board_state()
+ show_game_window(this.mineData)
+ })
+
+ //实时绘制棋局
+ Canvas(CommonConstants.context2)
+ .width(this.mineData.boardCols * CommonConstants.gridSize + this.mineData.boardOffset)
+ .height(this.mineData.boardRows * CommonConstants.gridSize + this.mineData.boardOffset)
+ .onReady(() => {
+
+ })
+ .onTouch((event) => {
+ if (event.type === TouchType.Up) {
+ //计算落子的横纵坐标
+ this.playX = event.touches[0].x - this.mineData.boardOffset / 2
+ this.playY = event.touches[0].y - this.mineData.boardOffset / 2
+ //计算行列数 横纵坐标/格子大小
+ let row: number = Math.floor(this.playY / CommonConstants.gridSize)
+ let col: number = Math.floor(this.playX / CommonConstants.gridSize)
+
+ if (row >= 0 && row < this.mineData.boardRows && col >= 0 && col < this.mineData.boardCols) {
+ if (this.ifFlag) { //插旗
+ if (this.mineData.gameOver || (this.mineData.curData[row][col] != 'F' && this.mineData.curData[row][col] != 'E')) { //游戏结束或按钮已被打开,则不响应
+ return
+ }
+
+ // 游戏未开始,左右键均不能用
+ if (!this.mineData.timeRun) {
+ //弹窗
+ this.message = "游戏未开始,请点击笑脸开始游戏"
+ this.MessageDialogController.open()
+ return
+ }
+
+ if (this.mineData.curData[row][col] == 'F') {
+ deleteFlag(this.mineData, row, col)
+ } else if (this.mineData.curData[row][col] == 'E') {
+ drawFlag(this.mineData, row, col)
+ }
+ this.mineData.show_flag(row, col) //修改被右击的方块状态
+ } else { //扫雷
+ if (this.mineData.gameOver || this.mineData.curData[row][col] == 'F') { //游戏结束不再响应、做了雷标记按钮左键无效
+ return
+ }
+
+ // 游戏未开始,左右键均不能用
+ if (!this.mineData.timeRun) {
+ //弹窗
+ this.message = "游戏未开始,请点击笑脸开始游戏"
+ this.MessageDialogController.open()
+ clearAllTimers(this.timers)
+ return
+ }
+
+ if (this.mineData.clock > this.mineData.timeLimit) {
+ this.mineData.timeRun = false
+ this.message = "时间已到,很遗憾你未能完成"
+ this.MessageDialogController.open()
+ clearAllTimers(this.timers)
+ return
+ }
+
+ if (this.mineData.sweeperFlag[row][col]) {
+ drawFlag(this.mineData, row, col)
+ this.mineData.show_flag(row, col) //修改被右击的方块状态
+ }
+
+ if (this.mineData.curData[row][col] == 'E') { //未点开的方块才响应
+ if (this.mineData.get_around_mine_num(row, col) == 0) { //返回值为0,左击了有雷的按钮,游戏结束
+ show_all_mines(this.mineData, row, col) //将所有雷显示出来,同时把点击的雷改成爆炸雷
+ this.mineData.gameOver = true //游戏结束标志
+ this.mineData.timeRun = false //计时暂停
+ clearAllTimers(this.timers)
+ return
+ }
+ for (let i = 0; i < this.mineData.boardRows; i++) {
+ for (let j = 0; j < this.mineData.boardCols; j++) { //显示所有被点开且未显示的状态信息
+ if (this.mineData.curData[i][j] != 'E' && this.mineData.curData[i][j] != 'F' && this.mineData.showBoardState[i][j] == '0') {
+ this.mineData.showBoardState[i][j] == '1' //已显示过信息,不重复显示
+ }
+ }
+ }
+ }
+ deleteBrisk(this.mineData, row, col)//消除方块
+ }
+ show_game_window(this.mineData) //点击的不是雷,刷新游戏窗口显示
+ this.mineData.remaining_mine_num() //更新剩余雷数
+ win(this.mineData) //判断是否胜利
+ if (this.mineData.winFlag) {
+ this.message = "恭喜你限时完成游戏"
+ this.MessageDialogController.open()
+ clearAllTimers(this.timers)
+ return
+ }
+ }
+
+ }
+ })
+ }
+ .height(300)//预览器
+ // .height(420) //Dayu200
+ }
+ .alignItems(HorizontalAlign.Center)
+ .justifyContent(FlexAlign.Center)
+ .height('100%')
+ .width('100%')
+ }
+}
+
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/MessageDialog.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/MessageDialog.ets
new file mode 100644
index 0000000..de33c3c
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/MessageDialog.ets
@@ -0,0 +1,30 @@
+//信息提示弹窗
+@CustomDialog
+export default struct MessageDialog {
+ @Link msg:string
+ controller: CustomDialogController
+
+ build(){
+ Column({space:5}){
+ Text(this.msg)
+ .fontSize(18)
+ .height(70)
+ .textAlign(TextAlign.Center)
+ .fontWeight(FontWeight.Bold)
+ .fontColor(Color.White)
+
+ Text('确定')
+ .fontSize(18)
+ .textAlign(TextAlign.Center)
+ .fontWeight(FontWeight.Bold)
+ .fontColor(Color.White)
+ .onClick(()=>{
+ this.controller.close()
+ })
+ }
+ .backgroundColor("#1E90FF")
+ .justifyContent(FlexAlign.Center)
+ .width(600)
+ .height(150)
+ }
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/ModeSelect.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/ModeSelect.ets
new file mode 100644
index 0000000..cf71578
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/ModeSelect.ets
@@ -0,0 +1,88 @@
+//模式选择弹窗
+import {MineData} from '../classes/Mine'
+import {clearAllTimers} from '../utils/util'
+
+@CustomDialog
+export default struct ModeSelect {
+ @Link mineData:MineData
+ @Link timers:number[]
+ controller: CustomDialogController
+
+ build(){
+ Column(){
+ Column({ space: 10 }) {
+ Text('简单模式')
+ .fontColor(Color.White)
+ .fontWeight(500)
+ .fontSize(18)
+ .onClick(() => {
+ clearAllTimers(this.timers)
+ if(this.mineData.boardOffset==8){
+ delete this.mineData
+ this.mineData=new MineData(6,6,6,300,6)
+ }else{
+ delete this.mineData
+ this.mineData=new MineData(6,6,6,300,8)
+ }
+ this.mineData.setMode=1
+ this.controller.close()
+ })
+
+ Text('一般模式')
+ .fontColor(Color.White)
+ .fontWeight(500)
+ .fontSize(18)
+ .onClick(() => {
+ clearAllTimers(this.timers)
+ if(this.mineData.boardOffset==8){
+ delete this.mineData
+ this.mineData=new MineData(10,10,10,600,6)
+ }else{
+ delete this.mineData
+ this.mineData=new MineData(10,10,10,600,8)
+ }
+ this.mineData.setMode=2
+ this.controller.close()
+ })
+
+ Text('困难模式')
+ .fontColor(Color.White)
+ .fontWeight(500)
+ .fontSize(18)
+ .onClick(() => {
+ clearAllTimers(this.timers)
+ if(this.mineData.boardOffset==8){
+ delete this.mineData
+ this.mineData=new MineData(15,20,30,1000,6)
+ }else{
+ delete this.mineData
+ this.mineData=new MineData(15,20,30,1000,8)
+ }
+ this.mineData.setMode=3
+ this.controller.close()
+ })
+
+ Text('噩梦模式')
+ .fontColor(Color.White)
+ .fontWeight(500)
+ .fontSize(18)
+ .onClick(() => {
+ clearAllTimers(this.timers)
+ if(this.mineData.boardOffset==8){
+ delete this.mineData
+ this.mineData=new MineData(18,28,60,2000,6)
+ }else{
+ delete this.mineData
+ this.mineData=new MineData(18,28,60,2000,8)
+ }
+ this.mineData.setMode=4
+ this.controller.close()
+ })
+ }
+ }
+ .backgroundColor('#1E90FF')
+ .justifyContent(FlexAlign.Center)
+ .width(400)
+ .height(150)
+ }
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/ToolBar.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/ToolBar.ets
new file mode 100644
index 0000000..8542c79
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/components/ToolBar.ets
@@ -0,0 +1,182 @@
+import Input from '../components/Input'
+import TCPSocket from '../classes/TCPSocket'
+import {MineData} from '../classes/Mine'
+import MessageDialog from '../components/MessageDialog'
+import { checkData,clearAllTimers,checkMode} from '../utils/util'
+
+//样式扩展,方便复用
+@Extend(Text) function TextStyle(){
+ .width(100)
+ .height(30)
+ .textAlign(TextAlign.Center)
+ .fontColor(Color.White)
+ .fontWeight(FontWeight.Bold)
+ .backgroundColor(Color.Orange)
+ .borderRadius(10)
+}
+
+//右侧功能
+@Component
+export default struct ToolBar {
+ setRow:number=null
+ setCol:number=null
+ setMines:number=null
+ setTime:number=null
+ @Link mineData:MineData
+ @Link timers:number[]
+ @State message:string=''
+
+ //信息弹窗控制器
+ MessageDialogController: CustomDialogController = new CustomDialogController({
+ builder: MessageDialog({msg:$message}),
+ gridCount: 5
+ })
+
+ build() {
+ Column({space:10}) {
+ Input({
+ title: "行数:",
+ placeholder:'行数范围:[6,18]',
+ change: (val: number) => {
+ this.setRow=val
+ }
+ })
+
+ Input({
+ title: "列数:",
+ placeholder:'列数范围:[6,28]',
+ change: (val: number) => {
+ this.setCol=val
+ }
+ })
+
+ Input({
+ title: "总的雷数:",
+ placeholder:'请输入雷数',
+ change: (val: number) => {
+ this.setMines=val
+ }
+ })
+
+ Input({
+ title: "时间限制:",
+ placeholder:'请输入限制时间',
+ change: (val: number) => {
+ this.setTime=val
+ }
+ })
+
+ Text('随机布局')
+ .TextStyle()
+ .onClick(()=>{
+ clearAllTimers(this.timers)
+ this.setRow=Math.floor(Math.random() * (18 - 6 + 1)) + 6
+ this.setCol=Math.floor(Math.random() * (28 - 6 + 1)) + 6
+ this.setMines=Math.floor(Math.random() * (this.setRow*this.setCol - 1 + 1)/2) + 1
+ if(this.setRow*this.setCol<100){
+ this.setTime=600
+ }else if(this.setRow*this.setCol<200){
+ this.setTime=900
+ }else if(this.setRow*this.setCol<300){
+ this.setTime=1200
+ }else if(this.setRow*this.setCol<400){
+ this.setTime=1500
+ }else if(this.setRow*this.setCol<600) {
+ this.setTime=2000
+ }else {
+ this.setTime=3000
+ }
+ delete this.mineData
+ this.mineData=new MineData(this.setRow,this.setCol,this.setMines,this.setTime)
+ })
+
+ Text('重玩游戏')
+ .TextStyle()
+ .onClick(()=>{
+ clearAllTimers(this.timers)//清除定时器
+ if(this.mineData.setMode==1){//简单模式
+ this.setRow=6
+ this.setCol=6
+ this.setMines=6
+ this.setTime=300
+ }else if(this.mineData.setMode==2){//一般模式
+ this.setRow=10
+ this.setCol=10
+ this.setMines=10
+ this.setTime=600
+ }
+ else if(this.mineData.setMode==3){//困难模式
+ this.setRow=15
+ this.setCol=20
+ this.setMines=30
+ this.setTime=1000
+ } else if(this.mineData.setMode==4){//噩梦模式
+ this.setRow=18
+ this.setCol=28
+ this.setMines=60
+ this.setTime=2000
+ }
+
+ if(this.mineData.boardRows==this.setRow&&this.mineData.boardCols==this.setCol&& this.mineData.mines==this.setMines&&this.mineData.timeLimit==this.setTime){
+ if(this.mineData.boardOffset==8){
+ delete this.mineData
+ this.mineData=new MineData(this.setRow,this.setCol,this.setMines,this.setTime,6)
+ }else{
+ delete this.mineData
+ this.mineData=new MineData(this.setRow,this.setCol,this.setMines,this.setTime,8)
+ }
+ }
+ })
+
+ Text('自定义布局')
+ .TextStyle()
+ .onClick(()=>{
+ clearAllTimers(this.timers)//清除定时器
+ this.message=checkData(this.setRow,this.setCol,this.setMines,this.setTime,this.mineData)//检测参数合法性
+ if(this.message=='check pass'){
+ if(this.mineData.boardOffset==8){
+ delete this.mineData
+ this.mineData=new MineData(this.setRow,this.setCol,this.setMines,this.setTime,6)
+ }else{
+ delete this.mineData
+ this.mineData=new MineData(this.setRow,this.setCol,this.setMines,this.setTime,8)
+ }
+ }else{
+ this.MessageDialogController.open()
+ }
+ })
+
+ Text('自动扫雷')
+ .TextStyle()
+ .onClick(()=>{
+ if(checkMode(this.mineData)){//简单,一般,困难,噩梦四种模式下才有自动扫雷功能
+ //标记地雷
+ for (let i = 0; i < this.mineData.boardRows; i++) {
+ for (let j = 0; j < this.mineData.boardCols; j++) {
+ if(this.mineData.initData[i][j]=='M'){
+ this.mineData.sweeperFlag[i][j]=true
+ }
+ }
+ }
+ let tcpSocket:TCPSocket=new TCPSocket()
+ tcpSocket.TCPBind()//绑定本机地址
+ tcpSocket.TCPConnect()//连接服务端
+ let timer=setTimeout(()=>{
+ tcpSocket.TCPSend('AutoMineSweeper')//发送自动扫雷指令
+ clearTimeout(timer)
+ },1000)
+ }else{
+ this.message="请在简单,一般,困难,噩梦模式\n选择后再点击自动扫雷"
+ this.MessageDialogController.open()
+ }
+ })
+ }
+ .justifyContent(FlexAlign.Center)
+ .width('100%')
+ .height('100%')
+ }
+}
+
+
+
+
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/entryability/EntryAbility.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000..d7d7109
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,67 @@
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+import hilog from '@ohos.hilog';
+import UIAbility from '@ohos.app.ability.UIAbility';
+import Want from '@ohos.app.ability.Want';
+import window from '@ohos.window';
+
+export default class EntryAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
+ }
+
+ onDestroy(): void {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ // Main window is created, set main page for this ability
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+
+ globalThis.context = this.context//将当前上下文改成全局可见
+
+ //设置导航栏,状态栏均不可见
+ // names 参数设置为 ['navigation'],设置顶部状态栏不可见。
+ // names 参数设置为 ['status'],设置底部导航栏不可见。
+ // names 参数设置为空,即 [],设置底部导航栏、顶部状态栏都不可见
+ let names: Array<'status' | 'navigation'> = [];
+ let windowClass = null;
+ windowStage.getMainWindow((err, data) => {
+ if (err.code) {
+ console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));
+ return;
+ }
+ windowClass = data;
+ console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(data));
+ windowClass.setWindowSystemBarEnable(names, (err) => {
+ if (err.code) {
+ console.error('Failed to set the system bar to be invisible. Cause:' + JSON.stringify(err));
+ return;
+ }
+ console.info('Succeeded in setting the system bar to be invisible.');
+ });
+ });
+
+ windowStage.loadContent('pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy(): void {
+ // Main window is destroyed, release UI related resources
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
+ }
+
+ onForeground(): void {
+ // Ability has brought to foreground
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
+ }
+
+ onBackground(): void {
+ // Ability has back to background
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
+ }
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/pages/Index.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000..47cf866
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,60 @@
+import Header from '../components/Header'
+import Main from '../components/Main'
+import ToolBar from '../components/ToolBar'
+import {MineData} from '../classes/Mine'
+import common from '@ohos.app.ability.common';
+import Window from '@ohos.window'
+import { BusinessError } from '@ohos.base';
+
+@Entry
+@Component
+struct Index {
+ // 设置开发板横屏显示
+ private changeOrientation() {
+ let windowClass: Window.Window | undefined = undefined;
+ // 获取上下文,使用common模块
+ let context = getContext(this) as common.UIAbilityContext;
+ let promise = Window.getLastWindow(context);
+ promise.then((data) => {
+ windowClass = data;
+ //切换成横屏
+ let orientation = Window.Orientation.LANDSCAPE;
+ windowClass.setPreferredOrientation(orientation, (err:BusinessError) => {
+ });
+ console.info('Succeeded in obtaining the top window. Data: ' + JSON.stringify(data));
+ }).catch((err:BusinessError) => {
+ console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(err));
+ });
+ }
+
+ aboutToAppear(){
+ this.changeOrientation()
+ }
+ @State mineData:MineData=new MineData()//数据结构实例化
+ @State timers:number[]=[]//存储定时器的timer
+
+ build() {
+ Column() {
+ Header({mineData:$mineData,timers:$timers})
+ .width('100%')
+ .height('10%')
+
+ Row(){
+ Main({mineData:$mineData,timers:$timers})
+ .width('68%')
+ .height('100%')
+
+ ToolBar({mineData:$mineData,timers:$timers})
+ .width('32%')
+ .height('100%')
+ }
+ .width('100%')
+ .height('90%')
+ }
+ .height('100%')
+ .width('100%')
+ .justifyContent(FlexAlign.Center)
+ .backgroundImage($r('app.media.bg'))
+ .backgroundImageSize(ImageSize.Cover)
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/utils/util.ets b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/utils/util.ets
new file mode 100644
index 0000000..d747762
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/ets/utils/util.ets
@@ -0,0 +1,202 @@
+import * as CommonConstants from '../common/constants/CommonConstants'
+import {MineData} from '../classes/Mine'
+
+export function drawBoard(mineData:MineData,rowNum:number,colNum:number) {
+ // 绘制棋盘线条
+ CommonConstants.context.strokeStyle = '#D3D3D3'; //线条颜色
+ CommonConstants.context.lineWidth = 1.5; //线条宽
+
+ // 横线
+ for (let i = 0; i < colNum+1; i++) {
+ CommonConstants.context.beginPath();
+ CommonConstants.context.moveTo(mineData.boardOffset/2, i * CommonConstants.gridSize + mineData.boardOffset/2);
+ CommonConstants.context.lineTo(CommonConstants.gridSize * colNum + mineData.boardOffset/2, i * CommonConstants.gridSize + mineData.boardOffset/2);
+ CommonConstants.context.stroke();
+ CommonConstants.context.closePath();
+ }
+
+ // 竖线
+ for (let i = 0; i < rowNum+1; i++) {
+ // 竖线
+ CommonConstants.context.beginPath();
+ CommonConstants.context.moveTo(i * CommonConstants.gridSize + mineData.boardOffset/2, mineData.boardOffset/2);
+ CommonConstants.context.lineTo(i * CommonConstants.gridSize + mineData.boardOffset/2, CommonConstants.gridSize * rowNum + mineData.boardOffset/2);
+ CommonConstants.context.stroke();
+ CommonConstants.context.closePath();
+ }
+}
+
+//消除方块
+export function deleteBrisk(mineData:MineData,row:number, col:number) {
+ const X = col * CommonConstants.gridSize+mineData.boardOffset/2
+ const Y = row * CommonConstants.gridSize+mineData.boardOffset/2
+ CommonConstants.context2.clearRect(X, Y, CommonConstants.gridSize, CommonConstants.gridSize)
+}
+
+//绘制红旗
+export function drawFlag(mineData:MineData,row:number, col:number){
+ const X = col * CommonConstants.gridSize+mineData.boardOffset/2
+ const Y = row * CommonConstants.gridSize+mineData.boardOffset/2
+ CommonConstants.context2.drawImage(CommonConstants.imgF, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+}
+
+//消除红旗
+export function deleteFlag(mineData:MineData,row:number, col:number) {
+ const X = col * CommonConstants.gridSize+mineData.boardOffset/2
+ const Y = row * CommonConstants.gridSize+mineData.boardOffset/2
+ CommonConstants.context2.clearRect(X, Y, CommonConstants.gridSize, CommonConstants.gridSize)
+}
+
+//实时呈现扫雷界面
+export function show_game_window(mineData:MineData){
+ for (let i = 0; i < mineData.boardRows; i++) {
+ for (let j = 0; j < mineData.boardCols; j++) {
+ let X=j*CommonConstants.gridSize+mineData.boardOffset/2
+ let Y=i*CommonConstants.gridSize+mineData.boardOffset/2
+ if(mineData.curData[i][j]=='M'){
+ //如果是雷
+ CommonConstants.context.drawImage(CommonConstants.imgM, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='X'){
+ //如果是挖开的雷
+ CommonConstants.context.drawImage(CommonConstants.imgR, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='E'){
+ //如果是未挖开的方块
+ CommonConstants.context2.drawImage(CommonConstants.imgB, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='F'){
+ //如果是旗子
+ CommonConstants.context.drawImage(CommonConstants.imgF, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='B'){
+ //如果是挖开的空方块
+ // CommonConstants.context.drawImage(CommonConstants.imgB, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='1'){
+ CommonConstants.context.drawImage(CommonConstants.img1, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='2'){
+ CommonConstants.context.drawImage(CommonConstants.img2, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='3'){
+ CommonConstants.context.drawImage(CommonConstants.img3, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='4'){
+ CommonConstants.context.drawImage(CommonConstants.img4, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='5'){
+ CommonConstants.context.drawImage(CommonConstants.img5, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='6'){
+ CommonConstants.context.drawImage(CommonConstants.img6, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='7'){
+ CommonConstants.context.drawImage(CommonConstants.img7, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }else if(mineData.curData[i][j]=='8'){
+ CommonConstants.context.drawImage(CommonConstants.img8, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);
+ }
+ }
+ }
+}
+
+//翻开雷游戏结束,并显示所有的雷
+export function show_all_mines(mineData:MineData,x:number,y:number){
+ if(x>=0&&y>=0){//如果是因为超过限时而失败传来的无意义参数-1,-1则不处理
+ let X=y*CommonConstants.gridSize+mineData.boardOffset/2
+ let Y=x*CommonConstants.gridSize+mineData.boardOffset/2
+ deleteBrisk(mineData,x,y)
+ CommonConstants.context2.drawImage(CommonConstants.imgR, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);//显示爆炸雷
+ mineData.curData[x][y]='X'//更新状态,为爆炸雷
+ }
+
+ for (let i = 0; i < mineData.boardRows; i++) {
+ for (let j = 0; j < mineData.boardCols; j++) {
+ let X=j*CommonConstants.gridSize+mineData.boardOffset/2
+ let Y=i*CommonConstants.gridSize+mineData.boardOffset/2
+ if (mineData.initData[i][j] == 'M' && mineData.curData[i][j] != 'F' && mineData.curData[i][j] != 'X') {//如果雷没被标记,显示雷。雷被正确标记为旗子,不显示雷,且非爆炸雷
+ deleteBrisk(mineData,i,j)
+ CommonConstants.context2.drawImage(CommonConstants.imgM, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);//显示普通雷
+ mineData.curData[i][j]='M'// 更新状态,未挖开的雷
+ }
+ if (mineData.initData[i][j] != 'M' && mineData.curData[i][j] == 'F') {//不是雷被标记为旗子,显示雷有红叉
+ deleteFlag(mineData,i,j)//删除红旗
+ deleteBrisk(mineData,i,j)//删除方块
+ CommonConstants.context2.drawImage(CommonConstants.imgC, X, Y,CommonConstants.gridSize,CommonConstants.gridSize);//显示标错雷
+ mineData.curData[i][j]=mineData.initData[i][j]//更新
+ }
+ }
+ }
+}
+
+//判断是否胜利
+export function win(mineData:MineData){
+ //(1)正确标记雷的按钮数=雷的实际数量且不正确标记为0 (2) 单击打开的非雷按钮数=按钮总数-雷的实际数量。且打开的按钮不能为0,防止全部为雷时直接显示胜利
+ if((mineData.mineWithFlag==mineData.mines&&mineData.noMineWithFlag==0) ||
+ (mineData.openButtons==mineData.boardRows*mineData.boardCols-mineData.mines&&mineData.openButtons!=0)){
+ mineData.gameOver=true
+ mineData.timeRun=false//停止计时
+ mineData.winFlag=true
+ }
+}
+
+//定义弹窗函数
+export function alertDialog(msg:string){
+ AlertDialog.show({
+ message: msg,
+ gridCount: 4,
+ alignment:DialogAlignment.Center,
+ //取消
+ confirm: {
+ value: '确定',
+ action: () => {
+ }
+ },
+ cancel: () => {}
+ })
+}
+
+//检查参数合法性
+export function checkData(setRow:number,setCol:number,setMines:number,setTime:number,mineData:MineData){
+ if(setRow==null||setCol==null||setMines==null||setTime==null){
+ return "参数不能为空,请重新设置参数"
+ }
+ if (setRow < 6 || setCol < 6 || setRow > 18 || setCol > 28){
+ return "行数范围是[6,18],列数的范围是[6,28],请重新设置参数"
+ }
+ if(setMines>setRow*setCol){
+ return "雷数不能多于行列数乘积,请重新设置参数"
+ }
+ if(setTime>99999){
+ return "最高限时99999s,请重新设置参数"
+ }
+
+ let dataString=setRow.toString()+setCol.toString()+setMines.toString()+setTime.toString()
+ for(let i=0;i='0'&&dataString[i]<='9'){
+ continue
+ }else{
+ return "参数只能为正整数,请重新设置参数"
+ }
+ }
+ return "check pass"
+}
+
+//清除所有计时器
+export function clearAllTimers(timers:number[]){
+ for(let i=0;i 0xFFFFFFFF) {
+ // throw ('The number is not normal!');
+ }
+ return (ip >>> 24) + '.' + (ip >> 16 & 0xFF) + '.' + (ip >> 8 & 0xFF) + '.' + (ip & 0xFF);
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/module.json5 b/minesweeping/minesweeper/Minesweeper/entry/src/main/module.json5
new file mode 100644
index 0000000..dfde846
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/module.json5
@@ -0,0 +1,59 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon_logo",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "requestPermissions": [
+ {
+ "name": "ohos.permission.INTERNET",
+ "usedScene": {
+ "abilities": [
+ "ohos.samples.socket.EntryAbility"
+ ],
+ "when": "always"
+ }
+ },
+ {
+ "name": "ohos.permission.GET_WIFI_INFO",
+ "usedScene": {
+ "abilities": [
+ "ohos.samples.socket.EntryAbility"
+ ],
+ "when": "always"
+ }
+ }
+ ]
+ }
+}
+
+
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/element/color.json b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/element/string.json b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000..32bd5a1
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "Minesweeper"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/bg.jpg b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/bg.jpg
new file mode 100644
index 0000000..e413a28
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/bg.jpg differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000..cd45acc
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_clock.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_clock.png
new file mode 100644
index 0000000..ab09619
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_clock.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cool.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cool.png
new file mode 100644
index 0000000..315c5bc
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cool.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_countdown.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_countdown.png
new file mode 100644
index 0000000..603d6bc
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_countdown.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cry.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cry.png
new file mode 100644
index 0000000..ba49020
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cry.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cry2.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cry2.png
new file mode 100644
index 0000000..927bd87
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_cry2.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_hourglass.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_hourglass.png
new file mode 100644
index 0000000..e5e2907
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_hourglass.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_logo.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_logo.png
new file mode 100644
index 0000000..9810795
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_logo.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_mine.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_mine.png
new file mode 100644
index 0000000..bb4fc28
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_mine.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_mine2.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_mine2.png
new file mode 100644
index 0000000..05c43bb
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_mine2.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_redCross.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_redCross.png
new file mode 100644
index 0000000..01ccc3d
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_redCross.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_smile.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_smile.png
new file mode 100644
index 0000000..95372db
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/icon_smile.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/startIcon.png b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000..366f764
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/profile/main_pages.json b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000..1898d94
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/en_US/element/string.json b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/en_US/element/string.json
new file mode 100644
index 0000000..32bd5a1
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/en_US/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "Minesweeper"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/zh_CN/element/string.json b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/zh_CN/element/string.json
new file mode 100644
index 0000000..89c13d2
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/main/resources/zh_CN/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "模块描述"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "扫雷"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/test/Ability.test.ets b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000..8aa3749
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,35 @@
+import hilog from '@ohos.hilog';
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function abilityTest() {
+ describe('ActsAbilityTest', () => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ })
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ })
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ })
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ })
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ })
+ })
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/test/List.test.ets b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000..794c7dc
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testability/TestAbility.ets b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testability/TestAbility.ets
new file mode 100644
index 0000000..9484761
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testability/TestAbility.ets
@@ -0,0 +1,50 @@
+import UIAbility from '@ohos.app.ability.UIAbility';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import hilog from '@ohos.hilog';
+import { Hypium } from '@ohos/hypium';
+import testsuite from '../test/List.test';
+import window from '@ohos.window';
+import Want from '@ohos.app.ability.Want';
+import AbilityConstant from '@ohos.app.ability.AbilityConstant';
+
+export default class TestAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
+ let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator;
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs;
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
+ hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
+ }
+
+ onDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
+ windowStage.loadContent('testability/pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
+ JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
+ }
+
+ onForeground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
+ }
+
+ onBackground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testability/pages/Index.ets b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testability/pages/Index.ets
new file mode 100644
index 0000000..423b427
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testability/pages/Index.ets
@@ -0,0 +1,17 @@
+@Entry
+@Component
+struct Index {
+ @State message: string = 'Hello World';
+
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
new file mode 100644
index 0000000..917d27a
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
@@ -0,0 +1,47 @@
+import hilog from '@ohos.hilog';
+import TestRunner from '@ohos.application.testRunner';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import Want from '@ohos.app.ability.Want';
+
+let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined
+let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined
+
+async function onAbilityCreateCallback() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
+}
+
+async function addAbilityMonitorCallback(err : Error) {
+ hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
+ }
+
+ async onRun() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ const bundleName = abilityDelegatorArguments.bundleName;
+ const testAbilityName = 'TestAbility';
+ let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ const want: Want = {
+ bundleName: bundleName,
+ abilityName: testAbilityName
+ };
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ abilityDelegator.startAbility(want, (err, data) => {
+ hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
+ hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? '');
+ })
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/module.json5 b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000..4fc9701
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "description": "$string:module_test_desc",
+ "mainElement": "TestAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:test_pages",
+ "abilities": [
+ {
+ "name": "TestAbility",
+ "srcEntry": "./ets/testability/TestAbility.ets",
+ "description": "$string:TestAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:TestAbility_label",
+ "exported": true,
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "skills": [
+ {
+ "actions": [
+ "action.system.home"
+ ],
+ "entities": [
+ "entity.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/element/color.json b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/element/color.json
new file mode 100644
index 0000000..3c71296
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/element/string.json b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000..65d8fa5
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_test_desc",
+ "value": "test ability description"
+ },
+ {
+ "name": "TestAbility_desc",
+ "value": "the test ability"
+ },
+ {
+ "name": "TestAbility_label",
+ "value": "test label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/media/icon.png b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000..ce307a8
Binary files /dev/null and b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/profile/test_pages.json b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/profile/test_pages.json
new file mode 100644
index 0000000..b7e7343
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/ohosTest/resources/base/profile/test_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "testability/pages/Index"
+ ]
+}
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/test/List.test.ets b/minesweeping/minesweeper/Minesweeper/entry/src/test/List.test.ets
new file mode 100644
index 0000000..bb5b5c3
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/test/List.test.ets
@@ -0,0 +1,5 @@
+import localUnitTest from './LocalUnit.test';
+
+export default function testsuite() {
+ localUnitTest();
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/entry/src/test/LocalUnit.test.ets b/minesweeping/minesweeper/Minesweeper/entry/src/test/LocalUnit.test.ets
new file mode 100644
index 0000000..ed22d4d
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/entry/src/test/LocalUnit.test.ets
@@ -0,0 +1,33 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function localUnitTest() {
+ describe('localUnitTest',() => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ });
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ });
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ });
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ });
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ });
+ });
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/hvigor/hvigor-config.json5 b/minesweeping/minesweeper/Minesweeper/hvigor/hvigor-config.json5
new file mode 100644
index 0000000..0c81a69
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/hvigor/hvigor-config.json5
@@ -0,0 +1,17 @@
+{
+ "modelVersion": "5.0.5",
+ "dependencies": {
+ },
+ "execution": {
+ // "daemon": true, /* Enable daemon compilation. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Default: false */
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/hvigorfile.ts b/minesweeping/minesweeper/Minesweeper/hvigorfile.ts
new file mode 100644
index 0000000..f3cb9f1
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/minesweeping/minesweeper/Minesweeper/oh-package-lock.json5 b/minesweeping/minesweeper/Minesweeper/oh-package-lock.json5
new file mode 100644
index 0000000..ea0c500
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/oh-package-lock.json5
@@ -0,0 +1,20 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hypium@1.0.11": "@ohos/hypium@1.0.11"
+ },
+ "packages": {
+ "@ohos/hypium@1.0.11": {
+ "name": "@ohos/hypium",
+ "version": "1.0.11",
+ "integrity": "sha512-KawcLnv43C3QIYv1UbDnKCFX3MohtDxGuFvzlUxT/qf2DBilR56Ws6zrj90LdH6PjloJQwOPESuBQIHBACAK7w==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.11.tgz",
+ "shasum": "fa799d273fa7d921701578c5e7084849354a4af0",
+ "registryType": "ohpm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/Minesweeper/oh-package.json5 b/minesweeping/minesweeper/Minesweeper/oh-package.json5
new file mode 100644
index 0000000..07f4bfa
--- /dev/null
+++ b/minesweeping/minesweeper/Minesweeper/oh-package.json5
@@ -0,0 +1,13 @@
+{
+ "modelVersion": "5.0.5",
+ "license": "",
+ "devDependencies": {
+ "@ohos/hypium": "1.0.11"
+ },
+ "author": "",
+ "name": "minesweeper",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {}
+}
\ No newline at end of file
diff --git a/minesweeping/minesweeper/img/image-20240626225020268.png b/minesweeping/minesweeper/img/image-20240626225020268.png
new file mode 100644
index 0000000..5bec122
Binary files /dev/null and b/minesweeping/minesweeper/img/image-20240626225020268.png differ
diff --git a/minesweeping/minesweeper/img/image-20240626225202868.png b/minesweeping/minesweeper/img/image-20240626225202868.png
new file mode 100644
index 0000000..95e468e
Binary files /dev/null and b/minesweeping/minesweeper/img/image-20240626225202868.png differ
diff --git a/minesweeping/minesweeper/img/image-20240626225335681.png b/minesweeping/minesweeper/img/image-20240626225335681.png
new file mode 100644
index 0000000..62e0b37
Binary files /dev/null and b/minesweeping/minesweeper/img/image-20240626225335681.png differ
diff --git a/minesweeping/minesweeper/img/image-20240626225435857.png b/minesweeping/minesweeper/img/image-20240626225435857.png
new file mode 100644
index 0000000..1c7cbb4
Binary files /dev/null and b/minesweeping/minesweeper/img/image-20240626225435857.png differ
diff --git a/minesweeping/minesweeper/open_cmd.bat b/minesweeping/minesweeper/open_cmd.bat
new file mode 100644
index 0000000..8bc2d2d
--- /dev/null
+++ b/minesweeping/minesweeper/open_cmd.bat
@@ -0,0 +1,9 @@
+@echo off
+:: 设置openHarmonySDK10的toolchains路径(需要换为自己电脑的路径)
+set "Path=D:\DevecoStudio_SDK _4.0.0.600\openHarmony-SDK\10\toolchains"
+:: 打开命令行窗口并切换到指定路径同时调用AutoMineSweeper.bat脚本(路径需要更改为自己的)
+start "AutoMineSweeper" cmd /K "cd /d %Path% && call D:\openHarmonyProject_4.0.0.600\MyApplication\AutoMineSweeper.bat"
+
+
+
+
diff --git a/minesweeping/minesweeper/tcpSocketServer.py b/minesweeping/minesweeper/tcpSocketServer.py
new file mode 100644
index 0000000..cc37f01
--- /dev/null
+++ b/minesweeping/minesweeper/tcpSocketServer.py
@@ -0,0 +1,48 @@
+import socket # socket通信
+import subprocess # 调用批处理脚本
+
+def start_server(host, port):
+ # 创建一个socket对象
+ server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ # 绑定IP地址和端口号
+ server_socket.bind((host, port))
+
+ # 开始监听连接
+ server_socket.listen(1) # 最多挂起5个连接
+
+ print(f"Server is listening on {host}:{port}...")
+
+ while True:
+ # 接受客户端的连接请求
+ client_socket, client_address = server_socket.accept()
+ print(f"Accepted connection from {client_address}")
+
+ # 处理客户端的请求(接收和发送数据)
+ try:
+ while True:
+ # 接收客户端发送的数据
+ data = client_socket.recv(1024).decode()
+ if not data:
+ break # 如果接收到的数据为空,表示客户端已经关闭连接
+ print(f"Received from client: {data}")
+
+ if data=="AutoMineSweeper":
+ # 批处理脚本的路径 需要修改为自己电脑的路径
+ batch_file_path = 'D:\\openHarmonyProject_4.0.0.600\\MyApplication\\open_cmd.bat'
+
+ # 使用subprocess.call来运行批处理脚本
+ subprocess.call(batch_file_path, shell=True)
+
+
+ except ConnectionResetError:
+ print("Client disconnected")
+
+ finally:
+ # 关闭与客户端的连接
+ client_socket.close()
+
+if __name__ == "__main__":
+ HOST = '192.168.184.229' # 监听的IP地址,这里使用本地地址
+ PORT = 8888 # 监听的端口号,根据需要修改
+ start_server(HOST, PORT)
\ No newline at end of file
diff --git a/minesweeping/minesweeper/说明.md b/minesweeping/minesweeper/说明.md
new file mode 100644
index 0000000..34ea1be
--- /dev/null
+++ b/minesweeping/minesweeper/说明.md
@@ -0,0 +1,1089 @@
+# OpenHarmony外部注入事件
+
+## 文章
+
+https://laval.csdn.net/64f6e5d96b896f66024c9971.html
+
+## 方式
+
+### uinput命令
+
+```shell
+用法:uinput