diff --git a/drawing/README.md b/drawing/README.md new file mode 100644 index 0000000..e8a76be --- /dev/null +++ b/drawing/README.md @@ -0,0 +1,16 @@ +# 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.7 项目主要函数调用关系图 + +图3.8 项目输出界面演进图 + 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