Initial commit
This commit is contained in:
parent
5b8129e67f
commit
f72ce70ee1
|
|
@ -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 项目输出界面演进图
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/node_modules
|
||||
/oh_modules
|
||||
/local.properties
|
||||
/.idea
|
||||
**/build
|
||||
/.hvigor
|
||||
.cxx
|
||||
/.clangd
|
||||
/.clang-format
|
||||
/.clang-tidy
|
||||
**/.test
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "MyApplication"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
||||
|
|
@ -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",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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. */
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"license": "",
|
||||
"devDependencies": {},
|
||||
"author": "",
|
||||
"name": "entry",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import { basicFuncInfo } from '../common/BasicFuncInfo'
|
||||
import { VALUE } from '../common/CommonValue'
|
||||
|
||||
@Component
|
||||
export struct basicFunctionsBar {
|
||||
@Consume('basicFuncList') basicFuncList:Array<basicFuncInfo>
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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<basicFuncInfo>
|
||||
@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
|
||||
})
|
||||
}
|
||||
|
|
@ -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<Array<string>> = []
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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%')
|
||||
}
|
||||
}
|
||||
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
@ -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<basicFuncInfo> = []
|
||||
//输入的函数
|
||||
@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
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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<IPoint>
|
||||
|
||||
funcType:FuncType
|
||||
|
||||
}
|
||||
/**
|
||||
* 画板点集
|
||||
* 以屏幕左上角为原点的平面坐标系下的点集
|
||||
*/
|
||||
export interface IBoardPoint{
|
||||
x:number
|
||||
|
||||
y:number
|
||||
|
||||
pointType:PointType
|
||||
}
|
||||
|
|
@ -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<string> = [];
|
||||
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();
|
||||
|
|
@ -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<Array<string>> // 节点树数组
|
||||
coPot: Array<IPoint>; // 存储获取的坐标点
|
||||
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<Array<string>> = 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();
|
||||
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"src": [
|
||||
"pages/Index"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "模块描述"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import abilityTest from './Ability.test';
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest();
|
||||
}
|
||||
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
@ -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%')
|
||||
}
|
||||
}
|
||||
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"src": [
|
||||
"testability/pages/Index"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import localUnitTest from './LocalUnit.test';
|
||||
|
||||
export default function testsuite() {
|
||||
localUnitTest();
|
||||
}
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -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 */
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -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. */
|
||||
}
|
||||
|
|
@ -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}" "$@"
|
||||
|
|
@ -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
|
||||
|
|
@ -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=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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": {}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"echarts": "^5.5.0"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 315 KiB |
Loading…
Reference in New Issue