Compare commits
No commits in common. "main" and "master" have entirely different histories.
|
|
@ -1,3 +0,0 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
</project>
|
||||
202
LICENSE
|
|
@ -1,202 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to the Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by the Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. Please also get an ISBN
|
||||
number for the printed version if you plan to publish a book
|
||||
using this license. We recommend considering the
|
||||
Apache License 2.0 for software, and the CC-BY license for
|
||||
other creative works.
|
||||
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
计算思维程序实践共14个计算思维程序实践项目编写开源鸿蒙应用程序,为学生系统剖析了每一个实践项目的计算思维,为学生搭建了一个五级阶梯的程序实现路径,同时为学生提供了由零基础开发到最终系统实现的初始版程序和程序实现环境,供学生上机调试与研讨。
|
||||
# TSZQ_KaiYuanHongMengRISC-VJuShenZhiNengKeChengGongJianZhuanQu
|
||||
|
||||
|
|
|
|||
21
THANKS
|
|
@ -1,21 +0,0 @@
|
|||
This project thanks the following people for their contributions
|
||||
(bug reports, testing, suggestions, documentation, or other non-code help):
|
||||
|
||||
- Li Ju
|
||||
- An Xiaoxin
|
||||
- Yang Yang
|
||||
- Luo Wanxu
|
||||
- Ji Ruijin
|
||||
- Qiu Jiayu
|
||||
- Zhang Yukai
|
||||
- Lai Zijie
|
||||
- Zhuang Yaojian
|
||||
- Yao Yubin
|
||||
- Chen Yunfeng
|
||||
- Yao Xintao
|
||||
- Chen Yanbo
|
||||
- Xie Canquan
|
||||
- Liu Guihong
|
||||
- Fu Haiyao
|
||||
- Yang Zhenwei
|
||||
- Han Xinyu
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
# databasing
|
||||
### 1、项目说明
|
||||
总体思路:关系数据库系统项目开发的总体思路如图1.1示意,可交互式练习SQL语句构造与执行的系统:(1)建立一个示例数据库SCT, 内中包含3个数据表(Student, SC和Course),注意本书是以SCT为例,读者做实验时可选择建立其他的数据库和数据表;(2)利用Insert语句对示例数据库的各个表追加内容;(3)利用Select语句检索示例数据库,并显示检索结果;(4)编制应用程序使用户可以针对固定的表输入检索条件,系统自动构造SQL语句并执行该SQL语句完成检索并输出检索结果。(5)编制应用程序使用户可以对数据库中的任何表进行检索条件输入并构造SQL语句、执行SQL语句显示检索结果。
|
||||
图1.1 项目开发的总体思路图
|
||||
<img src="figs/overall.png" width=80% /></center>
|
||||
|
||||
|
||||
### 2、开发环境说明
|
||||
(1)系统版本:OpenHarmony 4.0 Release
|
||||
(2)SDK版本:API 10
|
||||
(3)Model类型:Stage
|
||||
(4)DevEco Studio版本:Deveco Studio 4.0 release
|
||||
(5)硬件环境:Unionpi Whale、RK3566开发板
|
||||
(6)预览器参数:(1)DeviceType:default;(2)Resolution:560-1280;(3)DPI:240;其余参数自定。
|
||||
### 3、项目主要函数调用关系图与项目输出界面演进图
|
||||
图3.1 项目主要函数调用关系图
|
||||
<img src="figs/relation.png" width=80% /></center>
|
||||
|
||||
|
||||
图3.2 项目输出界面演进图
|
||||
<img src="figs/evolution.png" width=80% /></center>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
/node_modules
|
||||
/oh_modules
|
||||
/local.properties
|
||||
/.idea
|
||||
**/build
|
||||
/.hvigor
|
||||
.cxx
|
||||
/.clangd
|
||||
/.clang-format
|
||||
/.clang-tidy
|
||||
**/.test
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"app": {
|
||||
"bundleName": "com.example.database13",
|
||||
|
||||
"vendor": "example",
|
||||
"versionCode": 1000000,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "database13"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
"app": {
|
||||
"signingConfigs": [
|
||||
{
|
||||
"name": "default",
|
||||
"material": {
|
||||
"certpath": "C:\\Users\\HP\\.ohos\\config\\openharmony\\auto_ohos_default_database15_com.example.database13.cer",
|
||||
"storePassword": "0000001BA3E2965E301A7181B96C92E73BB162C179834F285268D3B71F5F4F585B7AE35294E33B45C5523C",
|
||||
"keyAlias": "debugKey",
|
||||
"keyPassword": "0000001B45786F06248E3CAF0728952F4C3C3B287B3A46C1D0816136C37458692661BC4149C8FA815A989E",
|
||||
"profile": "C:\\Users\\HP\\.ohos\\config\\openharmony\\auto_ohos_default_database15_com.example.database13.p7b",
|
||||
"signAlg": "SHA256withECDSA",
|
||||
"storeFile": "C:\\Users\\HP\\.ohos\\config\\openharmony\\auto_ohos_default_database15_com.example.database13.p12"
|
||||
}
|
||||
}
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"compileSdkVersion": 10,
|
||||
"compatibleSdkVersion": 9,
|
||||
"runtimeOS": "OpenHarmony"
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
{
|
||||
"name": "debug",
|
||||
},
|
||||
{
|
||||
"name": "release"
|
||||
}
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": "entry",
|
||||
"srcPath": "./entry",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"applyToProducts": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"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",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
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. */
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"license": "",
|
||||
"devDependencies": {},
|
||||
"author": "",
|
||||
"name": "entry",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
@ -1,562 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
import relationalStore from '@ohos.data.relationalStore';
|
||||
import Student from './student'
|
||||
import Course from './course'
|
||||
import Sc from './sc'
|
||||
import ThreeTable from './ThreeTable'
|
||||
|
||||
export default class RdbUtils {
|
||||
private static rdbStore: relationalStore.RdbStore;
|
||||
|
||||
// 初始化
|
||||
static setStore(store: relationalStore.RdbStore) {
|
||||
RdbUtils.rdbStore = store;
|
||||
}
|
||||
static getStore(): relationalStore.RdbStore {
|
||||
return RdbUtils.rdbStore;
|
||||
}
|
||||
|
||||
// 创建表
|
||||
static executeSql(sql: string): Promise<void> {
|
||||
return RdbUtils.getStore().executeSql(sql);
|
||||
}
|
||||
|
||||
// 插入数据
|
||||
static insert(tableName: string, data: any): Promise<number> {
|
||||
return RdbUtils.getStore().insert(tableName, data);
|
||||
}
|
||||
|
||||
// 查询并且加载学生表所有信息
|
||||
static queryAllStudent(): Promise<Array<Student>> {
|
||||
let predicates = new relationalStore.RdbPredicates('Student');
|
||||
return new Promise<Array<Student>>((resolve, reject) => {
|
||||
RdbUtils.getStore().query(predicates).then((result) => {
|
||||
let students = new Array<Student>();
|
||||
while (result.goToNextRow()) {
|
||||
let student = new Student();
|
||||
student.sid = result.getLong(result.getColumnIndex("sid"));
|
||||
student.sname = result.getString(result.getColumnIndex('sname'));
|
||||
student.ssex = result.getString(result.getColumnIndex("ssex"));
|
||||
student.sage = result.getLong(result.getColumnIndex("sage"));
|
||||
student.sclass = result.getLong(result.getColumnIndex("sclass"));
|
||||
students.push(student);
|
||||
}
|
||||
resolve(students);
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 具体查询学生表信息
|
||||
static queryStudent(columns:string[], full_sql_text:string): Promise<Array<Student>> {
|
||||
return new Promise<Array<Student>>((resolve, reject) => {
|
||||
RdbUtils.getStore().querySql(full_sql_text).then((result) => {
|
||||
let students = new Array<Student>();
|
||||
while (result.goToNextRow()) {
|
||||
let student = new Student();
|
||||
if (columns[0].includes('*')) {
|
||||
student.sid = result.getLong(result.getColumnIndex("sid"));
|
||||
student.sname = result.getString(result.getColumnIndex('sname'));
|
||||
student.ssex = result.getString(result.getColumnIndex("ssex"));
|
||||
student.sage = result.getLong(result.getColumnIndex("sage"));
|
||||
student.sclass = result.getLong(result.getColumnIndex("sclass"));
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < columns.length; i++) {
|
||||
if (columns[i].includes('sid')) {
|
||||
student.sid = result.getLong(result.getColumnIndex("sid"));
|
||||
}
|
||||
else if (columns[i].includes('sname')) {
|
||||
student.sname = result.getString(result.getColumnIndex('sname'));
|
||||
}
|
||||
else if (columns[i].includes('ssex')) {
|
||||
student.ssex = result.getString(result.getColumnIndex("ssex"));
|
||||
}
|
||||
else if (columns[i].includes('sage')) {
|
||||
student.sage = result.getLong(result.getColumnIndex("sage"));
|
||||
}
|
||||
else if (columns[i].includes('sclass')) {
|
||||
student.sclass = result.getLong(result.getColumnIndex("sclass"));
|
||||
}
|
||||
}
|
||||
}
|
||||
students.push(student);
|
||||
}
|
||||
resolve(students);
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 查询并且加载课程表所有信息
|
||||
static queryAllCourse(): Promise<Array<Course>> {
|
||||
let predicates = new relationalStore.RdbPredicates('Course');
|
||||
return new Promise<Array<Course>>((resolve, reject) => {
|
||||
RdbUtils.getStore().query(predicates).then((result) => {
|
||||
let courses = new Array<Course>();
|
||||
while (result.goToNextRow()) {
|
||||
let course = new Course();
|
||||
course.cid = result.getLong(result.getColumnIndex("cid"));
|
||||
course.cname = result.getString(result.getColumnIndex('cname'));
|
||||
course.credit = result.getDouble(result.getColumnIndex("credit"));
|
||||
course.chours = result.getLong(result.getColumnIndex("chours"));
|
||||
courses.push(course);
|
||||
}
|
||||
resolve(courses);
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 具体查询课程表信息
|
||||
static queryCourse(columns:string[],full_sql_text:string): Promise<Array<Course>> {
|
||||
let predicates = new relationalStore.RdbPredicates('Course')
|
||||
return new Promise<Array<Course>>((resolve, reject) => {
|
||||
RdbUtils.getStore().querySql(full_sql_text).then((result) => {
|
||||
let courses = new Array<Course>();
|
||||
while (result.goToNextRow()) {
|
||||
let course = new Course()
|
||||
if (columns[0].includes('*')) {
|
||||
course.cid = result.getLong(result.getColumnIndex("cid"));
|
||||
course.cname = result.getString(result.getColumnIndex('cname'));
|
||||
course.credit = result.getDouble(result.getColumnIndex("credit"));
|
||||
course.chours = result.getLong(result.getColumnIndex("chours"));
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < columns.length; i++) {
|
||||
if (columns[i].includes('cid')) {
|
||||
course.cid = result.getLong(result.getColumnIndex("cid"));
|
||||
}
|
||||
else if (columns[i].includes('cname')) {
|
||||
course.cname = result.getString(result.getColumnIndex('cname'));
|
||||
}
|
||||
else if (columns[i].includes('credit')) {
|
||||
course.credit = result.getDouble(result.getColumnIndex("credit"));
|
||||
}
|
||||
else if (columns[i].includes('chour')) {
|
||||
course.chours = result.getLong(result.getColumnIndex("chours"));
|
||||
}
|
||||
}
|
||||
}
|
||||
courses.push(course);
|
||||
}
|
||||
resolve(courses);
|
||||
}).catch((error) => {
|
||||
console.error(`Query failed, code is ${error.code},message is ${error.message}`);
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 查询并且加载选课表所有信息
|
||||
static queryAllSc(): Promise<Array<Sc>> {
|
||||
let predicates = new relationalStore.RdbPredicates('Sc');
|
||||
return new Promise<Array<Sc>>((resolve, reject) => {
|
||||
RdbUtils.getStore().query(predicates).then((result) => {
|
||||
let scs = new Array<Sc>();
|
||||
while (result.goToNextRow()) {
|
||||
let sc = new Sc();
|
||||
sc.sid = result.getLong(result.getColumnIndex("sid"));
|
||||
sc.cid = result.getLong(result.getColumnIndex("cid"));
|
||||
sc.score = result.getLong(result.getColumnIndex('score'));
|
||||
scs.push(sc);
|
||||
}
|
||||
resolve(scs);
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 具体查询选课表所有信息
|
||||
static querySc(columns:string[],full_sql_text:string): Promise<Array<Sc>> {
|
||||
let predicates = new relationalStore.RdbPredicates('Sc');
|
||||
return new Promise<Array<Sc>>((resolve, reject) => {
|
||||
RdbUtils.getStore().querySql(full_sql_text).then((result) => {
|
||||
let scs = new Array<Sc>();
|
||||
while (result.goToNextRow()) {
|
||||
let sc = new Sc();
|
||||
if (columns[0].includes('*')) {
|
||||
sc.sid = result.getLong(result.getColumnIndex("sid"));
|
||||
sc.cid = result.getLong(result.getColumnIndex("cid"));
|
||||
sc.score = result.getLong(result.getColumnIndex('score'));
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < columns.length; i++) {
|
||||
if (columns[i].includes('sid')) {
|
||||
sc.sid = result.getLong(result.getColumnIndex("sid"));
|
||||
}
|
||||
if (columns[i].includes('cid')) {
|
||||
sc.cid = result.getLong(result.getColumnIndex("cid"));
|
||||
}
|
||||
else if (columns[i].includes('score')) {
|
||||
sc.score = result.getLong(result.getColumnIndex('score'));
|
||||
}
|
||||
}
|
||||
}
|
||||
scs.push(sc);
|
||||
}
|
||||
resolve(scs);
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 多表查询
|
||||
static queryThreeTable(columns:string[], full_sql_text:string): Promise<Array<ThreeTable>> {
|
||||
return new Promise<Array<ThreeTable>>((resolve, reject) => {
|
||||
RdbUtils.getStore().querySql(full_sql_text).then((result) => {
|
||||
let threetables = new Array<ThreeTable>();
|
||||
while (result.goToNextRow()) {
|
||||
let threetable = new ThreeTable();
|
||||
if (columns[0].includes('*')) {
|
||||
threetable.sid = result.getLong(result.getColumnIndex("s.sid"));
|
||||
threetable.sname = result.getString(result.getColumnIndex('s.sname'));
|
||||
threetable.ssex = result.getString(result.getColumnIndex("s.ssex"));
|
||||
threetable.sage = result.getLong(result.getColumnIndex("s.sage"));
|
||||
threetable.sclass = result.getLong(result.getColumnIndex("s.sclass"));
|
||||
threetable.score = result.getLong(result.getColumnIndex("sc.score"));
|
||||
threetable.cid = result.getLong(result.getColumnIndex("c.cid"));
|
||||
threetable.cname = result.getString(result.getColumnIndex("c.cname"));
|
||||
threetable.credit = result.getLong(result.getColumnIndex("c.credit"));
|
||||
threetable.chours = result.getLong(result.getColumnIndex("c.chours"));
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < columns.length; i++) {
|
||||
if (columns[i].includes('sid')) {
|
||||
threetable.sid = result.getLong(result.getColumnIndex("s.sid"));
|
||||
}
|
||||
else if (columns[i].includes('sname')) {
|
||||
threetable.sname = result.getString(result.getColumnIndex('s.sname'));
|
||||
}
|
||||
else if (columns[i].includes('ssex')) {
|
||||
threetable.ssex = result.getString(result.getColumnIndex("s.ssex"));
|
||||
}
|
||||
else if (columns[i].includes('sage')) {
|
||||
threetable.sage = result.getLong(result.getColumnIndex("s.sage"));
|
||||
}
|
||||
else if (columns[i].includes('sclass')) {
|
||||
threetable.sclass = result.getLong(result.getColumnIndex("s.sclass"));
|
||||
}
|
||||
else if (columns[i].includes('score')) {
|
||||
threetable.score = result.getLong(result.getColumnIndex("sc.score"));
|
||||
}
|
||||
else if (columns[i].includes('cid')) {
|
||||
threetable.cid = result.getLong(result.getColumnIndex("c.cid"));
|
||||
}
|
||||
else if (columns[i].includes('cname')) {
|
||||
threetable.cname = result.getString(result.getColumnIndex("c.cname"));
|
||||
}
|
||||
else if (columns[i].includes('credit')) {
|
||||
threetable.credit = result.getLong(result.getColumnIndex("c.credit"));
|
||||
}
|
||||
else if (columns[i].includes('chours')) {
|
||||
threetable.chours = result.getLong(result.getColumnIndex("c.chours"));
|
||||
}
|
||||
}
|
||||
}
|
||||
threetables.push(threetable);
|
||||
}
|
||||
resolve(threetables);
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class SQLGenerator {
|
||||
input_sid: string;
|
||||
input_sname: string;
|
||||
input_sclass: string;
|
||||
input_ssex: string;
|
||||
input_start_age: string;
|
||||
input_end_age: string;
|
||||
input_sage: string;
|
||||
input_cid: string;
|
||||
input_cname: string;
|
||||
input_credit: string;
|
||||
input_chours: string;
|
||||
input_score: string;
|
||||
sid_var: boolean;
|
||||
sname_var: boolean;
|
||||
ssex_var: boolean;
|
||||
sage_var: boolean;
|
||||
sclass_var: boolean;
|
||||
cid_var: boolean;
|
||||
cname_var: boolean;
|
||||
credit_var: boolean;
|
||||
chours_var: boolean;
|
||||
score_var: boolean;
|
||||
sql_text: string;
|
||||
full_sql_text: string;
|
||||
columns: string[];
|
||||
input_low_score: string;
|
||||
input_high_score: string;
|
||||
|
||||
constructor() {
|
||||
this.input_sid = '';
|
||||
this.input_sname = '';
|
||||
this.input_sclass = '';
|
||||
this.input_ssex = '';
|
||||
this.input_start_age = '';
|
||||
this.input_end_age = '';
|
||||
this.input_sage = '';
|
||||
this.input_start_age = '';
|
||||
this.input_end_age = '';
|
||||
this.input_cid = '';
|
||||
this.input_cname = '';
|
||||
this.input_credit = '';
|
||||
this.input_chours = '';
|
||||
this.input_score = '';
|
||||
this.input_low_score = '';
|
||||
this.input_high_score = '';
|
||||
this.sid_var = false;
|
||||
this.sname_var = false;
|
||||
this.ssex_var = false;
|
||||
this.sage_var = false;
|
||||
this.sclass_var = false;
|
||||
this.cid_var = false;
|
||||
this.cname_var = false;
|
||||
this.credit_var = false;
|
||||
this.chours_var = false;
|
||||
this.score_var = false;
|
||||
this.sql_text = "";
|
||||
this.full_sql_text = "";
|
||||
this.columns = ["*"];
|
||||
|
||||
}
|
||||
|
||||
makeStudentSQL(): void {
|
||||
this.sql_text = "select * from student where 1=1"
|
||||
if (this.input_sid !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sid like ' + `'${this.input_sid}'` + ')';
|
||||
}
|
||||
if (this.input_sname !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sname like ' + `'${this.input_sname}'` + ')';
|
||||
}
|
||||
if (this.input_ssex !== "") {
|
||||
this.sql_text = this.sql_text + ' and (ssex like ' + `'${this.input_ssex}'` + ')';
|
||||
}
|
||||
if (this.input_sage !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sage like ' + `'${this.input_sage}'` + ')';
|
||||
}
|
||||
if (this.input_sclass !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sclass like ' + `'${this.input_sclass}'` + ')';
|
||||
}
|
||||
if (this.input_start_age !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sage > ' + `'${this.input_start_age}'` + ')';
|
||||
}
|
||||
if (this.input_end_age !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sage < ' + `'${this.input_end_age}'` + ')';
|
||||
}
|
||||
if (this.sql_text == 'select * from student where 1=1') {
|
||||
this.sql_text = "select * from student"
|
||||
} else {
|
||||
this.sql_text = this.sql_text.replace("1=1 and", "")
|
||||
}
|
||||
console.log('this.sql_text='+this.sql_text);
|
||||
|
||||
if (!this.sid_var && !this.sname_var && !this.ssex_var && !this.sage_var && !this.sclass_var) {
|
||||
this.columns = ["*"];
|
||||
} else {
|
||||
this.columns = [];
|
||||
if (this.sid_var) {
|
||||
this.columns.push("sid");
|
||||
}
|
||||
if (this.sname_var) {
|
||||
this.columns.push("sname");
|
||||
}
|
||||
if (this.ssex_var) {
|
||||
this.columns.push("ssex");
|
||||
}
|
||||
if (this.sage_var) {
|
||||
this.columns.push("sage");
|
||||
}
|
||||
if (this.sclass_var) {
|
||||
this.columns.push("sclass");
|
||||
}
|
||||
}
|
||||
|
||||
let sqlQuery = `${this.columns.join(', ')}`;
|
||||
|
||||
this.sql_text = this.sql_text.replace('*',sqlQuery)
|
||||
}
|
||||
|
||||
makeCourseSQL(): void {
|
||||
this.sql_text = "select * from course where 1=1"
|
||||
if (this.input_cid !== "") {
|
||||
this.sql_text = this.sql_text + ' and (cid like ' + `'${this.input_cid}'` + ')';
|
||||
}
|
||||
if (this.input_cname !== "") {
|
||||
this.sql_text = this.sql_text + ' and (cname like ' + `'${this.input_cname}'` + ')';
|
||||
}
|
||||
if (this.input_credit !== "") {
|
||||
this.sql_text = this.sql_text + ' and (credit like ' + `'${this.input_credit}'` + ')';
|
||||
}
|
||||
if (this.input_chours !== "") {
|
||||
this.sql_text = this.sql_text + ' and (chours like ' + `'${this.input_chours}'` + ')';
|
||||
}
|
||||
if (this.sql_text == 'select * from course where 1=1') {
|
||||
this.sql_text = "select * from course"
|
||||
} else {
|
||||
this.sql_text = this.sql_text.replace("1=1 and", "")
|
||||
}
|
||||
console.log('this.sql_text='+this.sql_text);
|
||||
|
||||
if (!this.cid_var && !this.cname_var && !this.credit_var && !this.chours_var) {
|
||||
this.columns = ["*"];
|
||||
} else {
|
||||
this.columns = [];
|
||||
if (this.cid_var) {
|
||||
this.columns.push("cid");
|
||||
}
|
||||
if (this.cname_var) {
|
||||
this.columns.push("cname");
|
||||
}
|
||||
if (this.credit_var) {
|
||||
this.columns.push("credit");
|
||||
}
|
||||
if (this.chours_var) {
|
||||
this.columns.push("chours");
|
||||
}
|
||||
}
|
||||
|
||||
let sqlQuery = `${this.columns.join(', ')}`;
|
||||
|
||||
this.sql_text = this.sql_text.replace('*',sqlQuery)
|
||||
}
|
||||
|
||||
makeScSQL(): void {
|
||||
this.sql_text = "select * from sc where 1=1"
|
||||
if (this.input_sid !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sid like ' + `'${this.input_sid}'` + ')';
|
||||
}
|
||||
if (this.input_cid !== "") {
|
||||
this.sql_text = this.sql_text + ' and (cid like ' + `'${this.input_cid}'` + ')';
|
||||
}
|
||||
if (this.input_score !== "") {
|
||||
this.sql_text = this.sql_text + ' and (score like ' + `'${this.input_score}'` + ')';
|
||||
}
|
||||
if (this.sql_text == 'select * from sc where 1=1') {
|
||||
this.sql_text = "select * from sc"
|
||||
} else {
|
||||
this.sql_text = this.sql_text.replace("1=1 and", "")
|
||||
}
|
||||
console.log('this.sql_text='+this.sql_text);
|
||||
|
||||
if (!this.sid_var && !this.cid_var && !this.score_var) {
|
||||
this.columns = ["*"];
|
||||
} else {
|
||||
this.columns = [];
|
||||
if (this.sid_var) {
|
||||
this.columns.push("sid");
|
||||
}
|
||||
if (this.cid_var) {
|
||||
this.columns.push("cid");
|
||||
}
|
||||
if (this.score_var) {
|
||||
this.columns.push("score");
|
||||
}
|
||||
}
|
||||
|
||||
let sqlQuery = `${this.columns.join(', ')}`;
|
||||
|
||||
this.sql_text = this.sql_text.replace('*',sqlQuery)
|
||||
}
|
||||
|
||||
makeThreeeTableSQL(): void {
|
||||
this.sql_text = "select * from student s join sc on sc.sid=s.sid join course c on c.cid=sc.cid where 1=1"
|
||||
if (this.input_sid !== "") {
|
||||
this.sql_text = this.sql_text + ' and (s.sid like ' + `'${this.input_sid}'` + ')';
|
||||
}
|
||||
if (this.input_sname !== "") {
|
||||
this.sql_text = this.sql_text + ' and (s.sname like ' + `'${this.input_sname}'` + ')';
|
||||
}
|
||||
if (this.input_sclass !== "") {
|
||||
this.sql_text = this.sql_text + ' and (s.sclass like ' + `'${this.input_sclass}'` + ')';
|
||||
}
|
||||
if (this.input_ssex !== "") {
|
||||
this.sql_text = this.sql_text + ' and (s.ssex like ' + `'${this.input_ssex}'` + ')';
|
||||
}
|
||||
if (this.input_start_age !== "") {
|
||||
this.sql_text = this.sql_text + ' and (s.sage > ' + `'${this.input_start_age}'` + ')';
|
||||
}
|
||||
if (this.input_end_age !== "") {
|
||||
this.sql_text = this.sql_text + ' and (s.sage < ' + `'${this.input_end_age}'` + ')';
|
||||
}
|
||||
if (this.input_cid !== "") {
|
||||
this.sql_text = this.sql_text + ' and (c.cid like ' + `'${this.input_cid}'` + ')';
|
||||
}
|
||||
if (this.input_cname !== "") {
|
||||
this.sql_text = this.sql_text + ' and (c.cname like ' + `'${this.input_cname}'` + ')';
|
||||
}
|
||||
if (this.input_low_score !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sc.score > ' + `'${this.input_score}'` + ')';
|
||||
}
|
||||
if (this.input_high_score !== "") {
|
||||
this.sql_text = this.sql_text + ' and (sc.score < ' + `'${this.input_score}'` + ')';
|
||||
}
|
||||
if (this.sql_text == "select * from student s join sc on sc.sid=s.sid join course c on c.cid=sc.cid where 1=1"
|
||||
) {
|
||||
this.sql_text = "select * from student s join sc on sc.sid=s.sid join course c on c.cid=sc.cid"
|
||||
} else {
|
||||
this.sql_text = this.sql_text.replace("1=1 and", "")
|
||||
}
|
||||
console.log('this.sql_text='+this.sql_text);
|
||||
|
||||
if (!this.sid_var && !this.sname_var && !this.ssex_var && !this.sage_var && !this.sclass_var && !this.score_var && !this.cid_var && !this.cname_var) {
|
||||
this.columns = ["*"];
|
||||
} else {
|
||||
this.columns = [];
|
||||
if (this.sid_var) {
|
||||
this.columns.push("s.sid");
|
||||
}
|
||||
if (this.sname_var) {
|
||||
this.columns.push("s.sname");
|
||||
}
|
||||
if (this.ssex_var) {
|
||||
this.columns.push("s.ssex");
|
||||
}
|
||||
if (this.sage_var) {
|
||||
this.columns.push("s.sage");
|
||||
}
|
||||
if (this.sclass_var) {
|
||||
this.columns.push("s.sclass");
|
||||
}
|
||||
if (this.score_var) {
|
||||
this.columns.push("sc.score");
|
||||
}
|
||||
if (this.cid_var) {
|
||||
this.columns.push("c.cid");
|
||||
}
|
||||
if (this.cname_var) {
|
||||
this.columns.push("c.cname");
|
||||
}
|
||||
}
|
||||
|
||||
let sqlQuery = `${this.columns.join(', ')}`;
|
||||
|
||||
this.sql_text = this.sql_text.replace('*',sqlQuery)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export default class ThreeTable {
|
||||
sid: number; // 学生ID
|
||||
sname: string; // 姓名
|
||||
ssex: string; // 性别
|
||||
sage: number | null; // 年龄,允许为null
|
||||
sclass: number | null; // 班级,允许为null
|
||||
score: number | null; // 成绩
|
||||
cid: number; // 课程ID
|
||||
cname: string; // 课程名字
|
||||
credit: number | null; // 课程学分
|
||||
chours: number | null; // 课程时长
|
||||
|
||||
constructor() {
|
||||
this.sid = 0;
|
||||
this.sname = '';
|
||||
this.ssex = '';
|
||||
this.sage = 0;
|
||||
this.sclass = 0;
|
||||
this.score = 0;
|
||||
this.cid = 0;
|
||||
this.cname = '';
|
||||
this.credit = 0;
|
||||
this.chours = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export default class Course {
|
||||
cid: number; // 课程ID
|
||||
cname: string; // 课程名字
|
||||
chours: number | null; // 课程时长
|
||||
credit: number | null; // 课程学分
|
||||
|
||||
constructor() {
|
||||
this.cid = 0;
|
||||
this.cname = '';
|
||||
this.chours = 0;
|
||||
this.credit = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export default class Sc {
|
||||
sid: number | null; // 学生ID
|
||||
cid: number | null; // 课程ID
|
||||
score: number | null; // 成绩
|
||||
|
||||
constructor() {
|
||||
this.sid = 0;
|
||||
this.cid = 0;
|
||||
this.score = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export default class Student {
|
||||
sid: number; // 学生ID
|
||||
sname: string; // 姓名
|
||||
ssex: string; // 性别
|
||||
sage: number | null; // 年龄,允许为null
|
||||
sclass: number | null; // 班级,允许为null
|
||||
|
||||
constructor() {
|
||||
this.sid = 0;
|
||||
this.sname = '';
|
||||
this.ssex = '';
|
||||
this.sage = 0;
|
||||
this.sclass = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,521 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
import relationalStore from '@ohos.data.relationalStore'; // 导入模块
|
||||
import Student from '../common/rdbUtils/student'
|
||||
import RdbUtils from '../common/rdbUtils/RdbUtils';
|
||||
import Sc from '../common/rdbUtils/sc'
|
||||
import Course from '../common/rdbUtils/course';
|
||||
import { SQLGenerator } from '../common/rdbUtils/RdbUtils'
|
||||
|
||||
|
||||
@Component
|
||||
export struct left {
|
||||
@State flagCou:boolean =false
|
||||
@State flagStu:boolean =false
|
||||
|
||||
@Link list1:Array<Student>;
|
||||
@Link list2:Array<Course>;
|
||||
@Link list3:Array<Sc>;
|
||||
|
||||
@Builder
|
||||
itemHeadStu(t0: string, t1: string, t2:string ,t3:string,t4:string) {
|
||||
Row() {
|
||||
Text(t0)
|
||||
.fontSize(15)
|
||||
.padding(1)
|
||||
.width(50)
|
||||
.fontColor('#838eb0')
|
||||
|
||||
Text(t1)
|
||||
.fontSize(15)
|
||||
.padding(1)
|
||||
.width(100)
|
||||
.fontColor('#838eb0')
|
||||
|
||||
Text(t2)
|
||||
.fontSize(15)
|
||||
.padding(1)
|
||||
.width(50)
|
||||
.fontColor('#838eb0')
|
||||
|
||||
Text(t3)
|
||||
.fontSize(15)
|
||||
.width(50)
|
||||
.fontColor('#838eb0')
|
||||
.padding(1)
|
||||
|
||||
Text(t4)
|
||||
.fontSize(15)
|
||||
.width(50)
|
||||
.fontColor('#838eb0')
|
||||
.padding(1)
|
||||
}
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
|
||||
@Builder
|
||||
itemHeadCou(t0: string, t1: string, t2:string ,t3:string) {
|
||||
Row() {
|
||||
Text(t0)
|
||||
.fontSize(15)
|
||||
.padding(1)
|
||||
.fontColor('#838eb0')
|
||||
.width(50)
|
||||
|
||||
Text(t1)
|
||||
.fontSize(15)
|
||||
.padding(1)
|
||||
.fontColor('#838eb0')
|
||||
.width(70)
|
||||
|
||||
Text(t2)
|
||||
.fontSize(15)
|
||||
.padding(1)
|
||||
.fontColor('#838eb0')
|
||||
.width(70)
|
||||
|
||||
Text(t3)
|
||||
.fontSize(15)
|
||||
.padding(1)
|
||||
.fontColor('#838eb0')
|
||||
.width(50)
|
||||
}
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
|
||||
@Builder
|
||||
itemHeadSc(t0: string, t1: string, t2:string ) {
|
||||
Row() {
|
||||
Text(t0)
|
||||
.fontSize(15)
|
||||
.fontColor('#838eb0')
|
||||
.padding(1)
|
||||
|
||||
Text(t1)
|
||||
.fontSize(15)
|
||||
.fontColor('#838eb0')
|
||||
.padding(1)
|
||||
|
||||
Text(t2)
|
||||
.fontSize(15)
|
||||
.fontColor('#838eb0')
|
||||
.padding(1)
|
||||
}
|
||||
.backgroundColor(Color.White)
|
||||
.width('100%')
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
|
||||
build() {
|
||||
Column({space:5}) {
|
||||
|
||||
// student表
|
||||
Column() {
|
||||
// 表头行
|
||||
Row({ space: 10 }) {
|
||||
// 表头
|
||||
Column() {
|
||||
Text(' student ')
|
||||
.fontSize(20)
|
||||
.backgroundColor('#f0f5fa')
|
||||
.fontColor('#838eb0')
|
||||
.borderColor('#b9c7da')
|
||||
}
|
||||
|
||||
Column() {
|
||||
Text('装载')
|
||||
.fontColor(Color.White)
|
||||
.fontSize(12)
|
||||
.padding(4)
|
||||
.backgroundColor('#378dfc')
|
||||
.onClick(() => {
|
||||
this.flagStu=true
|
||||
RdbUtils.queryAllStudent()
|
||||
.then((students: Array<Student>) => {
|
||||
this.list1 = students
|
||||
}).catch((error) => {
|
||||
openDialog('error' + error.toString())
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
|
||||
// 表单内容行
|
||||
if (this.flagStu == true) {
|
||||
Scroll() {
|
||||
Column() {
|
||||
List({ space: 5, initialIndex: 0 }) {
|
||||
ListItemGroup({ header: this.itemHeadStu(' sid', ' sname', 'ssex', 'sage', 'sclass') }) {
|
||||
ForEach(this.list1, (item: Student, index) => {
|
||||
ListItem() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(item.sid.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(70)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column() {
|
||||
Text(item.sname)
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(70)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column() {
|
||||
Text(item.ssex)
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(70)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
|
||||
Column() {
|
||||
Text(item.sage.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(40)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column() {
|
||||
Text(item.sclass.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(50)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.sticky(StickyStyle.Header)
|
||||
.height('50%')
|
||||
.listDirection(Axis.Vertical)
|
||||
.scrollBar(BarState.Auto)
|
||||
.backgroundColor('#f0f5fa')
|
||||
}
|
||||
.margin({ top: 5 ,bottom:5})
|
||||
}.scrollable(ScrollDirection.Horizontal)
|
||||
}
|
||||
else {
|
||||
Column() {
|
||||
List({ space: 5, initialIndex: 0 }) {
|
||||
ListItemGroup({ header: this.itemHeadStu('sid', 'sname', 'ssex', 'sage', 'sclass') }) {
|
||||
ForEach(this.list1, (item: Student,index) => {
|
||||
ListItem() {
|
||||
Row() {
|
||||
Column(){
|
||||
Text(item.sid.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(70)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column(){
|
||||
Text(item.sname)
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(70)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column(){
|
||||
Text(item.ssex)
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(30)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column(){
|
||||
Text(item.sage.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(30)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column(){
|
||||
Text(item.sclass.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(50)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.sticky(StickyStyle.Header)
|
||||
.height('50%')
|
||||
.listDirection(Axis.Vertical)
|
||||
.scrollBar(BarState.Auto)
|
||||
.backgroundColor('#f0f5fa')
|
||||
}
|
||||
.margin({ top: 5 })
|
||||
}
|
||||
}
|
||||
.height('30%')
|
||||
|
||||
// course表
|
||||
Column() {
|
||||
// 表头行
|
||||
Row({space:10}) {
|
||||
//表头
|
||||
Column() {
|
||||
Text(' course ')
|
||||
.fontSize(20)
|
||||
.backgroundColor('#f0f5fa')
|
||||
.fontColor('#838eb0')
|
||||
.borderColor('#b9c7da')
|
||||
}
|
||||
|
||||
// 装载
|
||||
Column() {
|
||||
Text('装载')
|
||||
.fontColor(Color.White)
|
||||
.fontSize(12)
|
||||
.padding(4)
|
||||
.backgroundColor('#378dfc')
|
||||
.onClick(() => {
|
||||
this.flagCou=true
|
||||
RdbUtils.queryAllCourse()
|
||||
.then((courses: Array<Course>) => {
|
||||
this.list2 = courses
|
||||
}).catch((error) => {
|
||||
openDialog('error' + error.toString())
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
|
||||
// 表单内容行
|
||||
if (this.flagCou==true) {
|
||||
Scroll() {
|
||||
Column() {
|
||||
List({ space: 5, initialIndex: 0 }) {
|
||||
ListItemGroup({ header: this.itemHeadCou('cid', 'cname', 'chours', 'credit') }) {
|
||||
ForEach(this.list2, (item: Course) => {
|
||||
ListItem() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(item.cid.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(30)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column() {
|
||||
Text(item.cname)
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(100)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
|
||||
Column() {
|
||||
Text(item.chours.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(80)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column() {
|
||||
Text(item.credit.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(30)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.sticky(StickyStyle.Header)
|
||||
.height('50%')
|
||||
.listDirection(Axis.Vertical)
|
||||
.scrollBar(BarState.Auto)
|
||||
.backgroundColor('#f0f5fa')
|
||||
}
|
||||
.margin({ top: 1 })
|
||||
}
|
||||
.scrollable(ScrollDirection.Horizontal)
|
||||
}
|
||||
else{
|
||||
Column() {
|
||||
List({ space: 5, initialIndex: 0 }) {
|
||||
ListItemGroup({ header:this.itemHeadCou('cid','cname','chours','credit') }){
|
||||
ForEach(this.list2, (item: Course) => {
|
||||
ListItem() {
|
||||
Row(){
|
||||
Column(){
|
||||
Text(item.cid.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(30)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column(){
|
||||
Text(item.cname)
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(60)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
|
||||
Column(){
|
||||
Text(item.chours.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(80)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column(){
|
||||
Text(item.credit.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(30)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.sticky(StickyStyle.Header)
|
||||
.height('50%')
|
||||
.listDirection(Axis.Vertical)
|
||||
.scrollBar(BarState.Auto)
|
||||
.backgroundColor('#f0f5fa')
|
||||
}
|
||||
.margin({top:1})
|
||||
}
|
||||
}
|
||||
.height('30%')
|
||||
|
||||
// sc表
|
||||
Column() {
|
||||
Row({space:10}) {
|
||||
Column() {
|
||||
Column() {
|
||||
Text(' sc ')
|
||||
.fontSize(20)
|
||||
.backgroundColor('#f0f5fa')
|
||||
.fontColor('#838eb0')
|
||||
.borderColor('#b9c7da')
|
||||
}
|
||||
}
|
||||
|
||||
Column() {
|
||||
Text('装载')
|
||||
.fontColor(Color.White)
|
||||
.fontSize(12)
|
||||
.padding(4)
|
||||
.backgroundColor('#378dfc')
|
||||
.onClick(() => {
|
||||
RdbUtils.queryAllSc()
|
||||
.then((scs: Array<Sc>) => {
|
||||
this.list3 = scs
|
||||
}).catch((error) => {
|
||||
openDialog('error' + error.toString())
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
|
||||
Column() {
|
||||
Column() {
|
||||
List({ space: 5, initialIndex: 0 }) {
|
||||
ListItemGroup({ header:this.itemHeadSc(' sid',' cid','score') }){
|
||||
ForEach(this.list3, (item: Sc) => {
|
||||
ListItem() {
|
||||
Row(){
|
||||
Column(){
|
||||
Text(item.sid.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(80)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column(){
|
||||
Text(item.cid.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(30)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
Column(){
|
||||
Text(item.score.toString())
|
||||
.fontSize(10)
|
||||
.padding(5)
|
||||
.width(30)
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
|
||||
}
|
||||
.justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.sticky(StickyStyle.Header)
|
||||
.height('40%')
|
||||
.listDirection(Axis.Vertical)
|
||||
.scrollBar(BarState.Auto)
|
||||
.backgroundColor('#f0f5fa')
|
||||
}
|
||||
}
|
||||
}
|
||||
.height('40%')
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openDialog(text: string) {
|
||||
AlertDialog.show(
|
||||
{
|
||||
title: 'title',
|
||||
message: text,
|
||||
autoCancel: true,
|
||||
alignment: DialogAlignment.Bottom,
|
||||
offset: { dx: 0, dy: -20 },
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
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';
|
||||
import relationalStore from '@ohos.data.relationalStore'; // 导入模块
|
||||
import RdbUtils from '../common/rdbUtils/RdbUtils';
|
||||
|
||||
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) ?? '');
|
||||
});
|
||||
|
||||
const STORE_CONFIG = {
|
||||
name: 'RdbTest.db', // 数据库文件名
|
||||
securityLevel: relationalStore.SecurityLevel.S1 // 数据库安全级别
|
||||
};
|
||||
|
||||
relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, store) => {
|
||||
if (err) {
|
||||
console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
|
||||
return;
|
||||
}
|
||||
console.info(`Succeeded in getting RdbStore.`);
|
||||
//保存store, 方便后面我们对数据库的操作
|
||||
RdbUtils.setStore(store)
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
import relationalStore from '@ohos.data.relationalStore'; // 导入模块
|
||||
import Student from '../common/rdbUtils/student'
|
||||
import RdbUtils from '../common/rdbUtils/RdbUtils';
|
||||
import Sc from '../common/rdbUtils/sc'
|
||||
import Course from '../common/rdbUtils/course';
|
||||
import { SQLGenerator } from '../common/rdbUtils/RdbUtils';
|
||||
import { left } from '../components/left';
|
||||
import { right } from '../components/right';
|
||||
import ThreeTable from '../common/rdbUtils/ThreeTable';
|
||||
|
||||
|
||||
const last_names = "李,王,张,刘,陈,杨,黄,赵,周,吴,徐,孙,朱,马,胡,郭,林,何,高,梁,郑,罗,宋,谢,唐,韩,曹,许,邓,萧,冯,曾,程,蔡,彭,潘,袁,于,董,余,苏,叶,吕,魏,蒋,田,杜,丁,沈,姜,范,江,傅,钟,卢,汪,戴,崔,任,陆,廖,姚,方,金,邱,夏,谭,韦,贾,邹,石,熊,孟,秦,阎,薛,侯,雷,白,龙,段,郝,孔,邵,史,毛,常,万,顾,赖,武,康,贺,严,尹,钱,施,牛,洪,龚";
|
||||
const last_names_list = last_names.split(',');
|
||||
const course_names = "语文、数学、外语、历史、思想政治、地理、 化学、物理、生物、体育、美术、音乐、技术、微积分、体育、毛泽东思想概论、思想道德修养、高等数学、线性代数、概率论与数理统计、离散数学、计算机原理、人工智能、程序设计基础、面向对象程序设计、数字逻辑电路、电路电子技术、数据结构与算法、WEB程序设计、计算机组成与结构、操作系统、数据库系统原理、编译原理、计算机网络"
|
||||
const course_names_list = course_names.split("、")
|
||||
const sidList = [];
|
||||
const cidList = [];
|
||||
const MAXAGE = 35;
|
||||
const MINAGE = 15;
|
||||
const MAXSCORE = 100;
|
||||
let NUM = 1;
|
||||
let CLASSID = 1;
|
||||
let CLASSNUM = 1;
|
||||
let issex:boolean = false;
|
||||
let array1 : any = [];
|
||||
let array2 : any = [];
|
||||
let array3 : any = [];let t = 0;
|
||||
function studentRandomRecord() {
|
||||
for (let i = 0; i < 500; i++) {
|
||||
const sid = `${2024}${String(NUM).padStart(4, '0')}`;
|
||||
const sname = `${last_names_list[Math.floor(Math.random() * last_names_list.length)]}${sid}`;
|
||||
const ssex = issex ? '男' : '女';
|
||||
const sage = Math.random() * (MAXAGE - MINAGE) + MINAGE;
|
||||
const sclass = `${2024}${String(CLASSID).padStart(2, '0')}`;
|
||||
|
||||
array1.push({
|
||||
sid,
|
||||
sname,
|
||||
ssex,
|
||||
sage,
|
||||
sclass
|
||||
})
|
||||
|
||||
const obj1:any = array1[i]
|
||||
const valueBucket = {
|
||||
'SID': obj1.sid,
|
||||
'SNAME': obj1.sname,
|
||||
'SSEX': obj1.ssex,
|
||||
'SAGE': obj1.sage,
|
||||
'SCLASS': obj1.sclass,
|
||||
};
|
||||
|
||||
RdbUtils.insert('Student', valueBucket)
|
||||
.then(() => {
|
||||
})
|
||||
|
||||
sidList.push(sid);
|
||||
|
||||
if (CLASSNUM === 30) {
|
||||
CLASSID++;
|
||||
CLASSNUM = 1;
|
||||
}
|
||||
|
||||
issex = !issex;
|
||||
NUM++;
|
||||
CLASSNUM++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function courseRandomRecord() {
|
||||
// hours=8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192
|
||||
const chourss = Array.from({ length: 24 }, (_, i) => 8 * (i + 1));
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
const cid = String(i + 1).padStart(3, '0');
|
||||
const cname = course_names_list[Math.floor(Math.random() * course_names_list.length)];
|
||||
const chours = chourss[Math.floor(Math.random() * chourss.length)];
|
||||
const credit = (chours / 16).toFixed(2);
|
||||
|
||||
array2.push({
|
||||
cid,
|
||||
cname,
|
||||
chours,
|
||||
credit
|
||||
})
|
||||
|
||||
const obj2:any = array2[i]
|
||||
const valueBucket2 = {
|
||||
'CID': obj2.cid,
|
||||
'CNAME': obj2.cname,
|
||||
'CHOURS': obj2.chours,
|
||||
'CREDIT': obj2.credit
|
||||
};
|
||||
|
||||
RdbUtils.insert('Course', valueBucket2)
|
||||
.then(() => {
|
||||
})
|
||||
|
||||
cidList.push(cid);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function scRandomRecord() {
|
||||
for (let i = 0; i < sidList.length; i++) {
|
||||
for (let j = 0; j < 4; j++) {
|
||||
const sid = sidList[i];
|
||||
const cid = cidList[j];
|
||||
const score = Math.random() * MAXSCORE;
|
||||
|
||||
array3.push({
|
||||
sid,
|
||||
cid,
|
||||
score
|
||||
})
|
||||
|
||||
const obj3:any = array3[t]
|
||||
const valueBucket3 = {
|
||||
'SID': obj3.sid,
|
||||
'CID': obj3.cid,
|
||||
'SCORE': obj3.score
|
||||
};
|
||||
|
||||
RdbUtils.insert('Sc', valueBucket3)
|
||||
.then(() => {
|
||||
})
|
||||
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State SQLGenerator:SQLGenerator = new SQLGenerator()
|
||||
@State list1:Array<Student> = [];
|
||||
@State list2:Array<Course> = [];
|
||||
@State list3:Array<Sc> = [];
|
||||
@State list4:Array<Student> = [];
|
||||
@State list5:Array<Course> = [];
|
||||
@State list6:Array<Sc> = [];
|
||||
@State list7:Array<ThreeTable> = [];
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column({space:5}) {
|
||||
left({list1: $list1, list2:$list2, list3:$list3});
|
||||
}
|
||||
.width('20%')
|
||||
.padding(10)
|
||||
|
||||
Column() {
|
||||
right({ SQLGenerator: $SQLGenerator, list4: $list4, list5:$list5, list6:$list6, list7:$list7});
|
||||
}
|
||||
.width('80%')
|
||||
}
|
||||
.alignItems(VerticalAlign.Top)
|
||||
.backgroundColor("#d9e3f1")
|
||||
.height('100%')
|
||||
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
this.initStudentTable();
|
||||
this.initCourseTable();
|
||||
this.initScTable();
|
||||
}
|
||||
|
||||
initStudentTable() {
|
||||
const SQL_CREATE_TABLE_Student = 'CREATE TABLE IF NOT EXISTS Student' +
|
||||
' (SID INTEGER PRIMARY KEY, ' +
|
||||
'SNAME TEXT NOT NULL, ' +
|
||||
'SSEX TEXT NOT NULL, ' +
|
||||
'SAGE INTEGER, ' +
|
||||
'SCLASS INTEGER)'; // 建Student表Sql语句
|
||||
|
||||
RdbUtils.executeSql(SQL_CREATE_TABLE_Student)
|
||||
.then(() =>{
|
||||
console.log('successfully created table_Student');
|
||||
}).catch((err) => {
|
||||
openDialog(err);
|
||||
})
|
||||
|
||||
studentRandomRecord();
|
||||
}
|
||||
|
||||
initCourseTable() {
|
||||
const SQL_CREATE_TABLE_Course = 'CREATE TABLE IF NOT EXISTS Course' +
|
||||
' (CID INTEGER PRIMARY KEY, ' +
|
||||
'CNAME TEXT NOT NULL, ' +
|
||||
'CHOURS INTEGER, ' +
|
||||
'CREDIT INTEGER)'; // 建Course表Sql语句
|
||||
|
||||
RdbUtils.executeSql(SQL_CREATE_TABLE_Course)
|
||||
.then(() =>{
|
||||
console.log('successfully created table_Course');
|
||||
}).catch((err) => {
|
||||
openDialog(err);
|
||||
})
|
||||
|
||||
courseRandomRecord();
|
||||
}
|
||||
|
||||
initScTable() {
|
||||
const SQL_CREATE_TABLE_SC = 'CREATE TABLE IF NOT EXISTS Sc' +
|
||||
'(SID INTEGER, ' +
|
||||
'CID INTEGER, ' +
|
||||
'SCORE INTEGER, ' +
|
||||
'PRIMARY KEY (SID, CID))'; // 建Sc表Sql语句
|
||||
|
||||
RdbUtils.executeSql(SQL_CREATE_TABLE_SC)
|
||||
.then(() =>{
|
||||
console.log('successfully created table_SC');
|
||||
}).catch((err) => {
|
||||
openDialog(err);
|
||||
})
|
||||
|
||||
scRandomRecord()
|
||||
}
|
||||
}
|
||||
|
||||
function openDialog(text: string) {
|
||||
AlertDialog.show(
|
||||
{
|
||||
title: 'title',
|
||||
message: text,
|
||||
autoCancel: true,
|
||||
alignment: DialogAlignment.Bottom,
|
||||
offset: { dx: 0, dy: -20 },
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
@Entry
|
||||
@Component
|
||||
struct Page {
|
||||
@State message: string = 'Hello World'
|
||||
|
||||
/**
|
||||
* In low-code mode, do not add anything to the build function, as it will be
|
||||
* overwritten by the content generated by the .visual file in the build phase.
|
||||
*/
|
||||
build() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": ["default","tablet"],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ts",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon" : "$media:startIcon",
|
||||
"startWindowBackground" : "$color:start_window_background"
|
||||
,
|
||||
"exported": true
|
||||
,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
}
|
||||
,{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"src": [
|
||||
"pages/Index"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
}
|
||||
,{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}]
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "模块描述"
|
||||
}
|
||||
,{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}]
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
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);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import abilityTest from './Ability.test';
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest();
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
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');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State message: string = 'Hello World';
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(50)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
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');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_test_desc",
|
||||
"value": "test ability description"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_desc",
|
||||
"value": "the test ability"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_label",
|
||||
"value": "test label"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 6.6 KiB |
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"src": [
|
||||
"testability/pages/Index"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import localUnitTest from './LocalUnit.test';
|
||||
|
||||
export default function testsuite() {
|
||||
localUnitTest();
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"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 */
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
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. */
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
#!/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}" "$@"
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
@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
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"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=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"license": "",
|
||||
"devDependencies": {
|
||||
"@ohos/hypium": "1.0.11"
|
||||
},
|
||||
"author": "",
|
||||
"name": "database13",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 231 KiB |
|
|
@ -1,21 +0,0 @@
|
|||
# datafiting
|
||||
### 1、项目说明
|
||||
总体思路曲线拟合绘制程序项目开发的总体思路如图所示,以实现交互界面与交互控制和数据结构和数值分析算法等。程序有两个主体功能:(1)对设置的数据集和用户选择的拟合曲线类型进行拟合,并计算出拟合优度和函数表达式;(2)根据拟合得到的函数表达式进行绘制。
|
||||
图1.1 项目开发的总体思路图
|
||||
<img src="figs/overall.png" width=80% /></center>
|
||||
|
||||
|
||||
### 2、开发环境说明
|
||||
(1)系统版本:OpenHarmony 4.0 Release
|
||||
(2)SDK版本:API 10
|
||||
(3)Model类型:Stage
|
||||
(4)DevEco Studio版本:Deveco Studio 4.0 release
|
||||
(5)硬件环境:Unionpi Whale、RK3566开发板
|
||||
(6)预览器参数:(1)DeviceType:default;(2)Resolution:560-1280;(3)DPI:240;其余参数自定。
|
||||
### 3、项目主要函数调用关系图与项目输出界面演进图
|
||||
图3.1 项目主要函数调用关系图
|
||||
<img src="figs/relation.png" width=80% /></center>
|
||||
|
||||
|
||||
图3.2 项目输出界面演进图
|
||||
<img src="figs/evolution.png" width=80% /></center>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
/node_modules
|
||||
/oh_modules
|
||||
/local.properties
|
||||
/.idea
|
||||
**/build
|
||||
/.hvigor
|
||||
.cxx
|
||||
/.clangd
|
||||
/.clang-format
|
||||
/.clang-tidy
|
||||
**/.test
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"app": {
|
||||
"bundleName": "com.test.myapplication",
|
||||
"vendor": "example",
|
||||
"versionCode": 1000000,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "MyApplication"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
"app": {
|
||||
"signingConfigs": [
|
||||
{
|
||||
"name": "default",
|
||||
"material": {
|
||||
"certpath": "C:\\Users\\nInse\\.ohos\\config\\openharmony\\auto_ohos_default_draw2_com.test.myapplication.cer",
|
||||
"storePassword": "0000001B23074682D90DCDA10157D8187E84EC05F50638D319B2E510345811D5FEB541650A0415030813F5",
|
||||
"keyAlias": "debugKey",
|
||||
"keyPassword": "0000001B291E996BCAB68900B133F9F5D394B9749AFD0C20146A22CE85070C1340F65B45506D15A417CC08",
|
||||
"profile": "C:\\Users\\nInse\\.ohos\\config\\openharmony\\auto_ohos_default_draw2_com.test.myapplication.p7b",
|
||||
"signAlg": "SHA256withECDSA",
|
||||
"storeFile": "C:\\Users\\nInse\\.ohos\\config\\openharmony\\auto_ohos_default_draw2_com.test.myapplication.p12"
|
||||
}
|
||||
}
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"compileSdkVersion": 10,
|
||||
"compatibleSdkVersion": 10,
|
||||
"runtimeOS": "OpenHarmony",
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
{
|
||||
"name": "debug",
|
||||
},
|
||||
{
|
||||
"name": "release"
|
||||
}
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": "entry",
|
||||
"srcPath": "./entry",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"applyToProducts": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"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",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
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. */
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"license": "",
|
||||
"devDependencies": {},
|
||||
"author": "",
|
||||
"name": "entry",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
export class COMMON_VALUE{
|
||||
/**
|
||||
* 字体大小(大)
|
||||
*/
|
||||
static readonly BIG_SIZE_FONT = 20
|
||||
/**
|
||||
* 字体大小(小)
|
||||
*/
|
||||
static readonly SMALL_SIZE_FONT = 15
|
||||
/**
|
||||
* 字体大小(超小)
|
||||
*/
|
||||
static readonly SMALLER_SIZE_FONT = 10
|
||||
/**
|
||||
* 浅蓝
|
||||
*/
|
||||
static readonly LIGHT_BLUE = '#87BAD4'
|
||||
/**
|
||||
* 紫色
|
||||
*/
|
||||
static readonly PURPLE = '#BE4AD9'
|
||||
/**
|
||||
* 灰色
|
||||
*/
|
||||
static readonly GREY = '#B8B8B8'
|
||||
/**
|
||||
* 浅白
|
||||
*/
|
||||
static readonly LIGHT_WHITE = '#F2F2F2'
|
||||
}
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import promptAction from '@ohos.promptAction'
|
||||
import { COMMON_VALUE } from '../common/commonValue'
|
||||
import { handle } from '../utils/algorithm/createPotGather'
|
||||
import { BoardInfo, Quadrant } from '../utils/drawBoard/BoardType'
|
||||
import { IPoint, PointType } from '../utils/drawBoard/DrawPoint'
|
||||
import { funcInfo, functionUtilIns } from '../utils/FunctionUtil'
|
||||
|
||||
@Component
|
||||
export struct controlBar {
|
||||
@State func:funcInfo|undefined = undefined
|
||||
|
||||
//TODO
|
||||
@Prop fitFuncList:Array<funcInfo>
|
||||
@Prop selectFitFunc:funcInfo
|
||||
@Prop curFuncIndex:number
|
||||
@Link isStartFit:boolean
|
||||
@Link isShowFunc:boolean
|
||||
@Link quadrant:Quadrant
|
||||
@Link points:Array<IPoint>
|
||||
@Link selectFuncIndex:number
|
||||
|
||||
@Consume board:BoardInfo
|
||||
@Consume isRefreshPoint:boolean
|
||||
@Consume isRefreshFunc:boolean
|
||||
controller:CustomDialogController = new CustomDialogController({
|
||||
builder:addPoints({points:$points,isStartFit:$isStartFit,isShowFunc:$isShowFunc})
|
||||
})
|
||||
build() {
|
||||
Column(){
|
||||
Row({space:5}){
|
||||
|
||||
Row(){
|
||||
Text('坐标轴')
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
Radio({value:"四象限",group:"Quadrant"})
|
||||
.checked(this.quadrant == Quadrant.FOUR)
|
||||
.onClick(()=>{
|
||||
this.quadrant = Quadrant.FOUR
|
||||
AppStorage.setOrCreate("quadrant",Quadrant.FOUR)
|
||||
})
|
||||
Text('四象限')
|
||||
.fontSize(COMMON_VALUE.SMALLER_SIZE_FONT)
|
||||
Radio({value:"一象限",group:"Quadrant"})
|
||||
.checked(this.quadrant == Quadrant.ONE)
|
||||
.onClick(()=>{
|
||||
this.quadrant = Quadrant.ONE
|
||||
AppStorage.setOrCreate("quadrant",Quadrant.ONE)
|
||||
})
|
||||
Text('一象限')
|
||||
.fontSize(COMMON_VALUE.SMALLER_SIZE_FONT)
|
||||
}.backgroundColor(COMMON_VALUE.GREY)
|
||||
|
||||
Row({space:5}){
|
||||
Button('生成数据集')
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
.type(ButtonType.Normal)
|
||||
.onClick(()=>{
|
||||
|
||||
this.isRefreshPoint = !this.isRefreshPoint
|
||||
this.points = this.board.initMap()
|
||||
this.board.drawAxis()
|
||||
this.board.drawPoints()
|
||||
|
||||
})
|
||||
Button('显示数据集')
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
.type(ButtonType.Normal)
|
||||
.onClick(()=>{
|
||||
this.isShowFunc = false
|
||||
})
|
||||
Button('显示数据集与曲线')
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
.type(ButtonType.Normal)
|
||||
.onClick(()=>{
|
||||
if(this.points.length == 0){
|
||||
promptAction.showToast({
|
||||
message:"还未选择样本点!"
|
||||
})
|
||||
return
|
||||
}
|
||||
if(this.selectFuncIndex != this.curFuncIndex){
|
||||
this.isShowFunc = false
|
||||
this.selectFuncIndex = this.curFuncIndex
|
||||
}
|
||||
setTimeout(()=>{
|
||||
this.isStartFit = false
|
||||
if (this.isShowFunc == false) {
|
||||
this.isShowFunc = true
|
||||
}
|
||||
},100)
|
||||
})
|
||||
Button('手动输入数据集')
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
.type(ButtonType.Normal)
|
||||
.onClick(()=>{
|
||||
this.controller.open()
|
||||
})
|
||||
Button('拟合')
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
.type(ButtonType.Normal)
|
||||
.onClick(()=>{
|
||||
if(this.points.length == 0){
|
||||
promptAction.showToast({
|
||||
message:"还未选择样本点!"
|
||||
})
|
||||
return
|
||||
}
|
||||
//TODO
|
||||
this.selectFitFunc = this.fitFuncList[this.curFuncIndex]
|
||||
|
||||
this.func = functionUtilIns.getFitFunc(this.selectFitFunc,this.points)
|
||||
this.isStartFit = true
|
||||
this.isShowFunc = false
|
||||
setTimeout(()=>{
|
||||
this.isShowFunc = true
|
||||
},100)
|
||||
this.selectFuncIndex = this.curFuncIndex
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Row(){
|
||||
Text('结果输出:')
|
||||
Swiper(){
|
||||
if(this.isStartFit){
|
||||
Text('函数形式:' + this.selectFitFunc.name + "\t" + this.selectFitFunc.body)
|
||||
.width('100%').height('100%')
|
||||
Text('函数系数:' + this.func!.body)
|
||||
.width('100%').height('100%')
|
||||
Text('拟合优度R^2:' + this.func!.R!)
|
||||
.width('100%').height('100%')
|
||||
}
|
||||
}.backgroundColor(COMMON_VALUE.GREY).layoutWeight(1).vertical(true).height('100%').autoPlay(false).indicator(false).loop(false)
|
||||
|
||||
}.width('100%').layoutWeight(1).padding(5)
|
||||
}.backgroundColor(COMMON_VALUE.LIGHT_WHITE).width('100%').height('100%')
|
||||
}
|
||||
}
|
||||
|
||||
@CustomDialog
|
||||
struct addPoints{
|
||||
controller:CustomDialogController
|
||||
@State setNum:number = -1
|
||||
@State num:number = 0
|
||||
@State msg:string = ''
|
||||
@Link points:Array<IPoint>
|
||||
@Link isStartFit:boolean
|
||||
@Link isShowFunc:boolean
|
||||
@Consume board:BoardInfo
|
||||
@Consume isRefreshPoint:boolean
|
||||
@Consume isRefreshFunc:boolean
|
||||
build(){
|
||||
Column({space:5}){
|
||||
Row(){
|
||||
if(this.setNum == -1){
|
||||
Text('设置样本点个数')
|
||||
TextInput({text:this.num.toString()})
|
||||
.onChange((value)=>{
|
||||
this.num = Number(value)
|
||||
})
|
||||
}
|
||||
}
|
||||
if(this.setNum == -1){
|
||||
Row(){
|
||||
Button('确定')
|
||||
.onClick(()=>{
|
||||
if(this.num <= 0){
|
||||
promptAction.showToast({
|
||||
message:"必须为正整数"
|
||||
})
|
||||
return
|
||||
}
|
||||
this.points = []
|
||||
this.setNum = this.num
|
||||
})
|
||||
.type(ButtonType.Normal)
|
||||
Button('取消')
|
||||
.onClick(()=>{
|
||||
this.controller.close()
|
||||
})
|
||||
.type(ButtonType.Normal)
|
||||
}.width('100%').justifyContent(FlexAlign.SpaceAround)
|
||||
}else {
|
||||
Column(){
|
||||
if(this.setNum == 0){
|
||||
Text('是否保存数据集')
|
||||
}else{
|
||||
Text("输入" + this.setNum + "个样本点,格式为X,X")
|
||||
TextInput({text:this.msg})
|
||||
.onChange((value)=>{
|
||||
this.msg = value
|
||||
})
|
||||
}
|
||||
Row(){
|
||||
Button('确定')
|
||||
.onClick(()=>{
|
||||
if(this.setNum == 0){
|
||||
this.isRefreshPoint = !this.isRefreshPoint
|
||||
this.board.initMap(this.points)
|
||||
this.board.drawAxis()
|
||||
this.board.drawPoints()
|
||||
this.controller.close()
|
||||
}else{
|
||||
let arr = this.msg.split(',')
|
||||
this.points.push({x:Number(arr[0]),y:Number(arr[1]),pointType:PointType.CONTINUE})
|
||||
this.msg = ''
|
||||
this.setNum--
|
||||
}
|
||||
})
|
||||
.type(ButtonType.Normal)
|
||||
Button('取消')
|
||||
.onClick(()=>{
|
||||
this.controller.close()
|
||||
})
|
||||
.type(ButtonType.Normal)
|
||||
}.width('100%').justifyContent(FlexAlign.SpaceAround)
|
||||
}
|
||||
}
|
||||
}.padding(5)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { COMMON_VALUE } from '../common/commonValue'
|
||||
import { funcInfo } from '../utils/FunctionUtil'
|
||||
|
||||
@Component
|
||||
export struct fitFuncType {
|
||||
@Link fitFuncList:Array<funcInfo>
|
||||
@Link curFuncIndex:number
|
||||
controller:CustomDialogController = new CustomDialogController({
|
||||
builder:addFitFuncType({fitFuncList:$fitFuncList})
|
||||
})
|
||||
build() {
|
||||
Column({space:5}){
|
||||
Text('拟合曲线类型')
|
||||
.height('12%')
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
List(){
|
||||
ForEach(this.fitFuncList,(item:funcInfo,index:number)=>{
|
||||
ListItem(){
|
||||
funcItem({curFuncIndex:$curFuncIndex,func:item,funcIndex:index})
|
||||
}.width('100%').height(30)
|
||||
})
|
||||
}.width('100%').layoutWeight(1).backgroundColor(COMMON_VALUE.LIGHT_BLUE)
|
||||
|
||||
Button('新增拟合曲线类型')
|
||||
.onClick(()=>{
|
||||
this.controller.open()
|
||||
})
|
||||
.type(ButtonType.Normal)
|
||||
.backgroundColor(COMMON_VALUE.PURPLE)
|
||||
}.width('100%').height('100%').padding({top:5,bottom:5,right:5}).backgroundColor(COMMON_VALUE.LIGHT_WHITE)
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
struct funcItem {
|
||||
@Link curFuncIndex:number
|
||||
@Prop func:funcInfo
|
||||
@Prop funcIndex:number
|
||||
build() {
|
||||
Row({space:5}){
|
||||
Radio({value:this.func.name,group:"fitFunc"})
|
||||
.width(20)
|
||||
.height(20)
|
||||
.checked(this.curFuncIndex == this.funcIndex)
|
||||
.onChange((value)=>{
|
||||
if(this.curFuncIndex == this.funcIndex){
|
||||
|
||||
return
|
||||
}
|
||||
this.curFuncIndex = this.funcIndex
|
||||
})
|
||||
Text(this.func.name)
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
Text(this.func.body)
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
}.width('100%').height('100%')
|
||||
}
|
||||
}
|
||||
|
||||
let funcList:Array<funcInfo> = [
|
||||
{name:"对数函数",body:"a*log(x,b)+c"},
|
||||
{name:"指数函数",body:"a*e^(0.01x)+b"}
|
||||
]
|
||||
@CustomDialog
|
||||
struct addFitFuncType{
|
||||
@Link fitFuncList:Array<funcInfo>
|
||||
controller:CustomDialogController
|
||||
@State index:number = 0
|
||||
@Builder item(index:number){
|
||||
Row(){
|
||||
Text(funcList[index].name)
|
||||
.fontColor(this.index == index?Color.Red:Color.Black)
|
||||
Text(funcList[index].body)
|
||||
.fontColor(this.index == index?Color.Red:Color.Black)
|
||||
}.width('100%').onClick(()=>{
|
||||
this.index = index
|
||||
})
|
||||
}
|
||||
build(){
|
||||
Column({space:5}){
|
||||
|
||||
ForEach(funcList,(item:funcInfo,index)=>{
|
||||
this.item(index)
|
||||
})
|
||||
|
||||
Row(){
|
||||
Button('确定')
|
||||
.onClick(()=>{
|
||||
this.fitFuncList.push({name:funcList[this.index].name,body:funcList[this.index].body})
|
||||
funcList.splice(this.index,1)
|
||||
this.controller.close()
|
||||
})
|
||||
.type(ButtonType.Normal)
|
||||
Button('取消')
|
||||
.onClick(()=>{
|
||||
this.controller.close()
|
||||
})
|
||||
.type(ButtonType.Normal)
|
||||
}.width('100%').justifyContent(FlexAlign.SpaceAround)
|
||||
}.width('100%').padding(5)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { COMMON_VALUE } from '../common/commonValue'
|
||||
import { BoardInfo } from '../utils/drawBoard/BoardType'
|
||||
import { IPoint, PointType } from '../utils/drawBoard/DrawPoint'
|
||||
import picker from '@ohos.file.picker';
|
||||
import fs from '@ohos.file.fs';
|
||||
import { createDocument } from '../model/createDocumentModel';
|
||||
import buffer from '@ohos.buffer';
|
||||
|
||||
@Component
|
||||
export struct header {
|
||||
@State filePath:string = ''
|
||||
@Link points:Array<IPoint>
|
||||
@Link isStartFit:boolean
|
||||
@Link isShowFunc:boolean
|
||||
@Consume board:BoardInfo
|
||||
@Consume isRefreshPoint:boolean
|
||||
@Consume isRefreshFunc:boolean
|
||||
context = getContext()
|
||||
build() {
|
||||
Row({space:5}){
|
||||
Text('样本数据集文件')
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
Text(this.filePath)
|
||||
.textOverflow({overflow:TextOverflow.MARQUEE})
|
||||
.layoutWeight(1)
|
||||
.fontSize(COMMON_VALUE.SMALL_SIZE_FONT)
|
||||
.backgroundColor(COMMON_VALUE.LIGHT_BLUE)
|
||||
.height('100%')
|
||||
Button('装载')
|
||||
.type(ButtonType.Normal)
|
||||
.onClick(async ()=>{
|
||||
this.points = []
|
||||
let documentPicker = new picker.DocumentViewPicker()
|
||||
let DocumentSelectOptions = new picker.DocumentSelectOptions();
|
||||
let DocumentSelectResult: Array<string> = await documentPicker.select(DocumentSelectOptions)
|
||||
let uri = DocumentSelectResult[0]
|
||||
let file = fs.openSync(uri,fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
|
||||
//已经获取到选择的文件 进行读取操作
|
||||
let arrayBuffer = new ArrayBuffer(8)
|
||||
let size = 0
|
||||
let dSize = 0
|
||||
let str = fs.readTextSync(file.path)
|
||||
|
||||
|
||||
//解析路径
|
||||
this.filePath = file.path
|
||||
fs.closeSync(file)
|
||||
|
||||
//解析文件样本点
|
||||
let arr = str.split('\n')
|
||||
for (let index = 0; index < arr.length; index++) {
|
||||
this.points.push({x:Number(arr[index].split(' ')[0]),y:Number(arr[index].split(' ')[1]),pointType:PointType.CONTINUE})
|
||||
}
|
||||
|
||||
|
||||
this.isStartFit = false
|
||||
this.isShowFunc = false
|
||||
this.isRefreshPoint = !this.isRefreshPoint
|
||||
this.board.initMap(this.points)
|
||||
this.board.drawPoints()
|
||||
this.board.drawAxis()
|
||||
})
|
||||
}.width('100%').height('100%').padding(5).backgroundColor(COMMON_VALUE.LIGHT_WHITE)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { BoardInfo, CONTEXT, FIT_CONTEXT } from '../utils/drawBoard/BoardType'
|
||||
import { IPoint } from '../utils/drawBoard/DrawPoint'
|
||||
import { funcInfo, functionUtilIns } from '../utils/FunctionUtil'
|
||||
|
||||
@Component
|
||||
export struct imageShow {
|
||||
@Prop loop_board:string
|
||||
@Prop loop_fit:string
|
||||
@Prop isShowFunc:boolean
|
||||
@Prop points:Array<IPoint>
|
||||
@Prop selectFitFunc:funcInfo
|
||||
@Consume board:BoardInfo
|
||||
@Consume isRefreshFunc:boolean
|
||||
build() {
|
||||
Stack(){
|
||||
Canvas(CONTEXT)
|
||||
.width('100%').height(this.loop_board)
|
||||
if(this.isShowFunc){
|
||||
Canvas(FIT_CONTEXT)
|
||||
.width('100%').height(this.loop_fit)
|
||||
.onReady(()=>{
|
||||
//获取到经过拟合后的函数
|
||||
functionUtilIns.getFitFunc(this.selectFitFunc,this.points)
|
||||
//解析函数 获取对应坐标点
|
||||
let points:Array<IPoint> = functionUtilIns.getPoints()
|
||||
this.board.drawFitFunc(points)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
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');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import picker from '@ohos.file.picker';
|
||||
import { BusinessError } from '@ohos.base';
|
||||
import fs from '@ohos.file.fs';
|
||||
|
||||
/**
|
||||
* 创建一个包含样本点的文件 用于读取测试
|
||||
*/
|
||||
export let createDocument = async ()=>{
|
||||
let documentPicker = new picker.DocumentViewPicker();
|
||||
let uris:Array<string> = []
|
||||
let DocumentSaveOptions = new picker.DocumentSaveOptions();
|
||||
DocumentSaveOptions.newFileNames = ['testPoints.txt']
|
||||
uris = await documentPicker.save(DocumentSaveOptions)
|
||||
let uri = uris[0]
|
||||
let file = fs.openSync(uri, fs.OpenMode.WRITE_ONLY);
|
||||
let writeLen = 0
|
||||
writeLen += fs.writeSync(file.fd, '2 2\n100 100\n123 323\n200.99 199.999\n302.8 300.6\n400 400.9\n450 450');//todo必须加结束位 否则多读
|
||||
fs.closeSync(file);
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { controlBar } from '../component/ControlBar'
|
||||
import { fitFuncType } from '../component/FitFuncType'
|
||||
import { header } from '../component/Header'
|
||||
import { imageShow } from '../component/ImageShow'
|
||||
import { createDocument } from '../model/createDocumentModel'
|
||||
import { B1Q2D, B4Q2D, BoardInfo, Quadrant } from '../utils/drawBoard/BoardType'
|
||||
import { IPoint } from '../utils/drawBoard/DrawPoint'
|
||||
import { funcInfo } from '../utils/FunctionUtil'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State fitFuncList:Array<funcInfo> = [
|
||||
{name:"一次函数",body:"a*x+b"},
|
||||
{name:"二次函数",body:"a*x^2+b*x+c"},
|
||||
{name:"三次函数",body:"a*x^3+b*x^2+c*x+d"},
|
||||
{name:"四次函数",body:"a*x^4+b*x^3+c*x^2+d*x+e"}
|
||||
]
|
||||
@State curFuncIndex:number = 0
|
||||
@State selectFuncIndex:number = 0
|
||||
/**
|
||||
* 是否开始拟合 点击拟合按钮改为true
|
||||
* 响应:结果输出栏
|
||||
*/
|
||||
@State isStartFit:boolean = false
|
||||
/**
|
||||
* 是否展示拟合函数 点击显示数据集与曲线改为true
|
||||
* 响应:出现函数图像
|
||||
*/
|
||||
@State isShowFunc:boolean = false
|
||||
|
||||
@State @Watch('refreshBoard')quadrant:Quadrant = Quadrant.FOUR
|
||||
|
||||
@Provide board:BoardInfo = B4Q2D
|
||||
@Provide @Watch('refreshPoint')isRefreshPoint:boolean = false
|
||||
@Provide @Watch('refreshFunc')isRefreshFunc:boolean = false
|
||||
@State loop_board:string = '100%'
|
||||
@State loop_fit:string = '100%'
|
||||
@State virtualPoints:Array<IPoint> = []
|
||||
@State boardPoints:Array<IPoint> = []
|
||||
|
||||
refreshPoint(){
|
||||
if(this.loop_board == '100%'){
|
||||
this.loop_board = '101%'
|
||||
}else {
|
||||
this.loop_board = '100%'
|
||||
}
|
||||
console.log('REFRESH point')
|
||||
this.isStartFit = false
|
||||
this.isShowFunc = false
|
||||
}
|
||||
|
||||
refreshFunc(){
|
||||
if(this.loop_fit == '100%'){
|
||||
this.loop_fit = '101%'
|
||||
}else {
|
||||
this.loop_fit = '100%'
|
||||
}
|
||||
console.log('REFRESH func')
|
||||
}
|
||||
|
||||
refreshBoard(){
|
||||
console.log('REFRESH board')
|
||||
if(this.quadrant == Quadrant.ONE){
|
||||
this.board = B1Q2D
|
||||
}else{
|
||||
this.board = B4Q2D
|
||||
}
|
||||
if(this.virtualPoints.length != 0){
|
||||
this.isRefreshPoint = !this.isRefreshPoint
|
||||
this.isRefreshFunc = !this.isRefreshFunc
|
||||
this.board.initMap(this.virtualPoints)
|
||||
this.board.drawAxis()
|
||||
this.board.drawPoints()
|
||||
this.isStartFit = false
|
||||
}
|
||||
}
|
||||
|
||||
async aboutToAppear(){
|
||||
await createDocument()
|
||||
}
|
||||
|
||||
|
||||
build() {
|
||||
Column(){
|
||||
|
||||
Row(){
|
||||
Column(){
|
||||
|
||||
header({points:$virtualPoints,isShowFunc:$isShowFunc,isStartFit:$isStartFit}).width('100%').height('15%')
|
||||
|
||||
imageShow({points:this.virtualPoints,selectFitFunc:this.fitFuncList[this.curFuncIndex],loop_board:this.loop_board,loop_fit:this.loop_fit,isShowFunc:this.isShowFunc}).width('100%').height('85%')
|
||||
|
||||
}.width('60%').height('100%')
|
||||
|
||||
fitFuncType({fitFuncList:$fitFuncList,curFuncIndex:$curFuncIndex}).width('40%').height('100%')
|
||||
|
||||
}.width('100%').height('75%')
|
||||
|
||||
//TODO
|
||||
controlBar({points:$virtualPoints,isShowFunc:$isShowFunc,quadrant:$quadrant,isStartFit:$isStartFit,selectFitFunc:this.fitFuncList[this.selectFuncIndex],selectFuncIndex:$selectFuncIndex,curFuncIndex:this.curFuncIndex,fitFuncList:this.fitFuncList}).width('100%').layoutWeight(1)
|
||||
|
||||
}.width('100%').height('100%')
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { IPoint, PointType } from './drawBoard/DrawPoint'
|
||||
import { handle } from './algorithm/createPotGather'
|
||||
|
||||
export interface funcInfo {
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* 函数体
|
||||
*/
|
||||
body: string
|
||||
/**
|
||||
* 拟合优度
|
||||
*/
|
||||
R?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供函数拟合的方法
|
||||
*/
|
||||
class FunctionUtil {
|
||||
/**
|
||||
* 根据拟合函数类型和样本点计算出拟合函数
|
||||
* 返回funcInfo
|
||||
*/
|
||||
getFitFunc(fitFunc: funcInfo, points: Array<IPoint>) {
|
||||
handle.fit(fitFunc.body, points);
|
||||
let func: funcInfo = { name: "", body: handle.fitFunc, R: handle.R_squared }
|
||||
return func
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据函数返回xyMap
|
||||
*/
|
||||
getPoints() {
|
||||
//TODO 结合原代码
|
||||
//用来测试的拟合函数
|
||||
handle.compote_curveData();
|
||||
let point: Array<IPoint> = handle.coordinatePoint;
|
||||
// console.log(handle.fitFunc)
|
||||
// for (let i = 0; i < point.length; i++) {
|
||||
// console.log("testTag", "(" + point[i].x + ", " + point[i].y + ")");
|
||||
// }
|
||||
return point
|
||||
}
|
||||
}
|
||||
|
||||
export let functionUtilIns = new FunctionUtil()
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { mathjs } from './evaluate';
|
||||
import {IPoint, PointType} from "../drawBoard/DrawPoint"
|
||||
import {FitRes} from "./fittingResult"
|
||||
import { Matrix } from './least_square';
|
||||
import { Quadrant } from '../drawBoard/BoardType';
|
||||
import { Exponent } from './exponentialFit';
|
||||
import { Logarithm } from './logarithmicFit';
|
||||
|
||||
function arrange(low: number, high: number, step: number): number[] {
|
||||
const rangeArray: number[] = [];
|
||||
if (step <= 0) {
|
||||
throw new Error("Step must be greater than zero.");
|
||||
}
|
||||
for (let i = low; i <= high; i += step) {
|
||||
rangeArray.push(i);
|
||||
}
|
||||
return rangeArray;
|
||||
}
|
||||
|
||||
const replaceVar: Array<string> = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
|
||||
|
||||
class CreatePointGather {
|
||||
coordinatePoint: Array<IPoint>;
|
||||
theta: number[];
|
||||
error: number;
|
||||
R_squared: number;
|
||||
fitFunc: string;
|
||||
funcFormat: string;
|
||||
private m: number;
|
||||
|
||||
constructor() {
|
||||
this.coordinatePoint = [];
|
||||
this.theta = [];
|
||||
this.error = 0;
|
||||
this.R_squared = 0;
|
||||
this.fitFunc = "";
|
||||
this.funcFormat = "";
|
||||
this.m = 0;
|
||||
}
|
||||
|
||||
private judgeWhichM(funcFormat: string) {
|
||||
const index = funcFormat.indexOf("^");
|
||||
if (index === -1) {
|
||||
this.m = 1;
|
||||
} else {
|
||||
this.m = Number(funcFormat[index + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
private getFitFunc(funcFormat: string): void {
|
||||
this.funcFormat = funcFormat;
|
||||
this.fitFunc = funcFormat;
|
||||
if (funcFormat == "a*e^(0.01x)+b") {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
if (this.theta[i] < 0 && this.fitFunc[this.fitFunc.indexOf(replaceVar[i]) - 1] == "+") {
|
||||
this.fitFunc = this.fitFunc.substring(0, this.fitFunc.indexOf(replaceVar[i]) - 1) + this.fitFunc.substring(this.fitFunc.indexOf(replaceVar[i]));
|
||||
}
|
||||
this.fitFunc = this.fitFunc.replace(replaceVar[i], this.theta[i].toFixed(4));
|
||||
}
|
||||
} else if (funcFormat == "a*log(x,b)+c") {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (this.theta[i] < 0 && this.fitFunc[this.fitFunc.indexOf(replaceVar[i]) - 1] == "+") {
|
||||
this.fitFunc = this.fitFunc.substring(0, this.fitFunc.indexOf(replaceVar[i]) - 1) + this.fitFunc.substring(this.fitFunc.indexOf(replaceVar[i]));
|
||||
}
|
||||
this.fitFunc = this.fitFunc.replace(replaceVar[i], this.theta[i].toFixed(4));
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < this.m + 1; i++) {
|
||||
if (this.theta[i] < 0 && this.fitFunc[this.fitFunc.indexOf(replaceVar[i]) - 1] == "+") {
|
||||
this.fitFunc = this.fitFunc.substring(0, this.fitFunc.indexOf(replaceVar[i]) - 1) + this.fitFunc.substring(this.fitFunc.indexOf(replaceVar[i]));
|
||||
}
|
||||
this.fitFunc = this.fitFunc.replace(replaceVar[i], this.theta[i].toFixed(4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private calculate_function(x:number): number {
|
||||
if (this.funcFormat == "a*e^(0.01x)+b") {
|
||||
return Exponent.expFunc(x, this.theta[0], this.theta[1]);
|
||||
} else if (this.funcFormat == "a*log(x,b)+c") {
|
||||
if (x > 0) return Logarithm.logFunc(x, this.theta[0], this.theta[1], this.theta[2]);
|
||||
else return Number.NaN;
|
||||
}
|
||||
return mathjs.evaluate(this.fitFunc, [{char: 'x', value: x}]);
|
||||
}
|
||||
|
||||
compote_curveData(low: number = -500, high: number = 500, step: number = 1): Array<IPoint> {
|
||||
if (AppStorage.get("quadrant") == Quadrant.ONE) {
|
||||
low = 0;
|
||||
high = 1000;
|
||||
}
|
||||
this.coordinatePoint = [];
|
||||
let xValues = arrange(low, high, step);
|
||||
let yValues: number[] = [];
|
||||
let size = xValues.length;
|
||||
yValues = Array<number>(size).fill(0).map((_, index) => {
|
||||
return this.calculate_function(xValues[index]);
|
||||
})
|
||||
for (let i = 0; i < size; i++) {
|
||||
if (!Number.isNaN(yValues[i])) {
|
||||
this.coordinatePoint.push({
|
||||
x: xValues[i],
|
||||
y: yValues[i],
|
||||
pointType: PointType.CONTINUE
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!this.coordinatePoint.length) {
|
||||
this.coordinatePoint.push({
|
||||
x: 0,
|
||||
y: 0,
|
||||
pointType: PointType.CONTINUE
|
||||
})
|
||||
}
|
||||
return this.coordinatePoint;
|
||||
}
|
||||
|
||||
private error_func(sampleData: Array<IPoint>): FitRes {
|
||||
let sx: number[] = sampleData.map(value => value.x);
|
||||
let sy: number[] = sampleData.map(value => value.y);
|
||||
let y_predict: number[] = Array<number>(sx.length).fill(0).map((_, index) => {
|
||||
return this.calculate_function(sx[index]);
|
||||
})
|
||||
let error: number = 0;
|
||||
for (let i = 0; i < sx.length; i++) {
|
||||
error += (sy[i] - y_predict[i]) ** 2;
|
||||
}
|
||||
const mean = sy.reduce((acc, val) => acc + val, 0) / sy.length;
|
||||
let sum: number = sy.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0);
|
||||
let R_squared: number = 1 - (error/sum);
|
||||
if (R_squared <= 0) R_squared = 0;
|
||||
let fitRes: FitRes = {
|
||||
error: error,
|
||||
R_squared: R_squared
|
||||
};
|
||||
return fitRes;
|
||||
}
|
||||
|
||||
fit(funcFormat: string, sampleData: Array<IPoint>): void {
|
||||
let fitRes: FitRes = {};
|
||||
if (funcFormat == "a*e^(0.01x)+b") {
|
||||
this.theta = Exponent.gradientDescentExp(sampleData);
|
||||
} else if (funcFormat == "a*log(x,b)+c") {
|
||||
this.theta = Logarithm.gradientDescentLog(sampleData);
|
||||
} else {
|
||||
this.judgeWhichM(funcFormat);
|
||||
fitRes = Matrix.leastSquareMethod(this.m, sampleData);
|
||||
if (fitRes.theta) this.theta = fitRes.theta;
|
||||
}
|
||||
this.getFitFunc(funcFormat);
|
||||
fitRes = this.error_func(sampleData);
|
||||
if (fitRes.error && fitRes.R_squared) {
|
||||
this.error = fitRes.error;
|
||||
this.R_squared = fitRes.R_squared;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export let handle: CreatePointGather = new CreatePointGather();
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
interface replaceableVar {
|
||||
char: string,
|
||||
value: number
|
||||
}
|
||||
|
||||
class MathExpressionParser {
|
||||
private tokens: string[];
|
||||
private currentTokenIndex: number;
|
||||
private variables: replaceableVar[];
|
||||
|
||||
constructor() {
|
||||
this.tokens = []
|
||||
this.currentTokenIndex = 0
|
||||
this.variables = []
|
||||
}
|
||||
|
||||
private tokenize(expression: string): string[] {
|
||||
const regex: RegExp = new RegExp("(\\d+\\.?\\d*|\\.\\d+|[a-zA-Z]+|\\S)", "g");
|
||||
const originalTokens = expression.match(regex) || [];
|
||||
|
||||
const Tokens: string[] = [];
|
||||
for (let i = 0; i < originalTokens.length; i++) {
|
||||
Tokens.push(originalTokens[i]);
|
||||
if (i < originalTokens.length - 1) {
|
||||
const currentToken = originalTokens[i];
|
||||
const nextToken = originalTokens[i + 1];
|
||||
if ((this.isNumber(currentToken) && this.isVariable(nextToken)) ||
|
||||
(this.isVariable(currentToken) && this.isVariable(nextToken)) ||
|
||||
(currentToken === ')' && (this.isVariable(nextToken) || this.isNumber(nextToken))) ||
|
||||
(this.isNumber(currentToken) && nextToken === '(') ||
|
||||
(this.isVariable(currentToken) && nextToken === '(')) {
|
||||
Tokens.push('*');
|
||||
}
|
||||
}
|
||||
}
|
||||
return Tokens;
|
||||
}
|
||||
|
||||
private existInArr(token: string): number {
|
||||
for (let i: number = 0; i < this.variables.length; i++) {
|
||||
if (this.variables[i].char == token) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private isNumber(token: string): boolean {
|
||||
const num = Number(token);
|
||||
return !Number.isNaN(num) && Number.isFinite(num);
|
||||
}
|
||||
|
||||
private isVariable(token: string): boolean {
|
||||
const temp: RegExp = new RegExp("^[a-zA-Z]+$")
|
||||
return temp.test(token) && !this.isFunction(token) && token !== "π";
|
||||
}
|
||||
|
||||
private isFunction(token: string): boolean {
|
||||
return ['pow', 'sin', 'cos', 'tan', 'ln', 'sqrt', 'log2', 'log10'].includes(token);
|
||||
}
|
||||
|
||||
private getCurrentToken(): string {
|
||||
return this.tokens[this.currentTokenIndex];
|
||||
}
|
||||
|
||||
private getNextToken(): string {
|
||||
this.currentTokenIndex++;
|
||||
return this.getCurrentToken();
|
||||
}
|
||||
|
||||
private parsePrimaryExpression(): number {
|
||||
const token = this.getCurrentToken();
|
||||
if (token === '(') {
|
||||
this.getNextToken(); // consume '('
|
||||
const result = this.parseExpression();
|
||||
if (this.getCurrentToken() !== ')') {
|
||||
throw new Error("Expected ')' after expression");
|
||||
}
|
||||
this.getNextToken(); // consume ')'
|
||||
return result;
|
||||
} else if (token === 'π') {
|
||||
this.getNextToken(); // consume 'π'
|
||||
return Math.PI;
|
||||
} else if (this.isVariable(token)) {
|
||||
if (this.existInArr(token) != -1) {
|
||||
const value = this.variables[this.existInArr(token)].value;
|
||||
this.getNextToken(); // consume variable
|
||||
return value;
|
||||
} else {
|
||||
throw new Error(`Unknown variable: ${token}`);
|
||||
}
|
||||
} else if (this.isFunction(token)) {
|
||||
return this.parseFunction();
|
||||
} else {
|
||||
const num = Number(token);
|
||||
this.getNextToken(); // consume number
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
private parseFunction(): number {
|
||||
const functionName = this.getCurrentToken();
|
||||
this.getNextToken(); // consume function name
|
||||
if (this.getCurrentToken() !== '(') {
|
||||
throw new Error(`Expected '(' after function name ${functionName}`);
|
||||
}
|
||||
this.getNextToken(); // consume '('
|
||||
|
||||
const argument1 = this.parseExpression();
|
||||
|
||||
if (functionName === 'pow') {
|
||||
if (this.getCurrentToken() !== ',') {
|
||||
throw new Error(`Expected ',' between arguments for function ${functionName}`);
|
||||
}
|
||||
this.getNextToken(); // consume ','
|
||||
const argument2 = this.parseExpression();
|
||||
if (this.getCurrentToken() !== ')') {
|
||||
throw new Error(`Expected ')' after arguments for function ${functionName}`);
|
||||
}
|
||||
this.getNextToken(); // consume ')'
|
||||
return Math.pow(argument1, argument2);
|
||||
}
|
||||
|
||||
if (this.getCurrentToken() !== ')') {
|
||||
throw new Error(`Expected ')' after argument for function ${functionName}`);
|
||||
}
|
||||
this.getNextToken(); // consume ')'
|
||||
|
||||
switch (functionName) {
|
||||
case 'sin':
|
||||
return Math.sin(argument1);
|
||||
case 'cos':
|
||||
return Math.cos(argument1);
|
||||
case 'tan':
|
||||
return Math.tan(argument1);
|
||||
case 'ln':
|
||||
return Math.log(argument1);
|
||||
case 'sqrt':
|
||||
return Math.sqrt(argument1);
|
||||
case 'log2':
|
||||
return Math.log2(argument1);
|
||||
case 'log10':
|
||||
return Math.log10(argument1);
|
||||
default:
|
||||
throw new Error(`Unknown function: ${functionName}`);
|
||||
}
|
||||
}
|
||||
|
||||
private parseFactor(): number {
|
||||
// 处理一元负号
|
||||
if (this.getCurrentToken() === '-') {
|
||||
this.getNextToken(); // consume '-'
|
||||
return -this.parseFactor();
|
||||
}
|
||||
// 处理初级表达式
|
||||
let result = this.parsePrimaryExpression();
|
||||
// 处理乘法和除法
|
||||
while (this.getCurrentToken() === '*' || this.getCurrentToken() === '/') {
|
||||
const operator = this.getCurrentToken();
|
||||
this.getNextToken(); // consume operator
|
||||
const operand = this.parsePrimaryExpression();
|
||||
if (operator === '*') {
|
||||
result *= operand;
|
||||
} else if (operator === '/') {
|
||||
if (operand === 0) {
|
||||
throw new Error("Division by zero");
|
||||
}
|
||||
result /= operand;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private parseExpression(): number {
|
||||
let result = this.parseFactor();
|
||||
while (this.getCurrentToken() === '+' || this.getCurrentToken() === '-') {
|
||||
const operator = this.getCurrentToken();
|
||||
this.getNextToken();
|
||||
const operand = this.parseFactor();
|
||||
if (operator === '+') {
|
||||
result += operand;
|
||||
} else if (operator === '-') {
|
||||
result -= operand;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public evaluate(expression: string, variables: replaceableVar[] = []): number {
|
||||
let temp: RegExp = new RegExp("\\s+", "g");
|
||||
expression = expression.trim().replace(temp, "");
|
||||
temp = new RegExp("(\\([^()]*?(?:\\([^()]*?\\)[^()]*?)*\\)|\\w+)(?:\\*\\*|\\^)(\\([^()]*?(?:\\([^()]*?\\)[^()]*?)*\\)|\\w+)", "g");
|
||||
expression = expression.replace(temp, "pow($1, $2)");
|
||||
this.tokens = this.tokenize(expression);
|
||||
this.currentTokenIndex = 0;
|
||||
this.variables = variables;
|
||||
|
||||
const result = this.parseExpression();
|
||||
if (this.currentTokenIndex !== this.tokens.length) {
|
||||
console.log("Token:" + this.tokens);
|
||||
console.log("当前index:" + this.currentTokenIndex + " " + "当前length:" + this.tokens.length);
|
||||
throw new Error("Unexpected token");
|
||||
}
|
||||
return Number(result.toFixed(4));
|
||||
}
|
||||
}
|
||||
|
||||
export let mathjs: MathExpressionParser = new MathExpressionParser();
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {IPoint} from "../drawBoard/DrawPoint"
|
||||
|
||||
export class Exponent {
|
||||
static expFunc(x: number, a: number, b: number): number {
|
||||
return a * Math.exp(0.01 * x) + b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 梯度下降法
|
||||
* @param sampleData
|
||||
* @param learningRate
|
||||
* @param epochs
|
||||
* @returns
|
||||
*/
|
||||
static gradientDescentExp(sampleData: Array<IPoint>, learningRate: number = 0.00001, epochs: number = 100000): number[] {
|
||||
let a = 0.001; // 初始化参数
|
||||
let b = 0.001;
|
||||
|
||||
for (let epoch = 0; epoch < epochs; epoch++) {
|
||||
let aGrad = 0;
|
||||
let bGrad = 0;
|
||||
const n = sampleData.length;
|
||||
for (let i = 0; i < n; i++) {
|
||||
const x = sampleData[i].x;
|
||||
const y = sampleData[i].y;
|
||||
const yPredict = Exponent.expFunc(x, a, b);
|
||||
aGrad += -2 * (y - yPredict) * Math.exp(0.01 * x);
|
||||
bGrad += -2 * (y - yPredict);
|
||||
}
|
||||
|
||||
a -= (aGrad / n) * learningRate;
|
||||
b -= (bGrad / n) * learningRate;
|
||||
|
||||
// 检查参数是否过大或过小,若是则终止训练
|
||||
if (Number.isNaN(a) || Number.isNaN(b) || !Number.isFinite(a) || !Number.isFinite(b) || Math.abs(a) > 1e10 || Math.abs(b) > 1e10) {
|
||||
console.error(`Parameters became unstable at epoch ${epoch + 1}`);
|
||||
break;
|
||||
}
|
||||
|
||||
// 每1000个epoch打印一次当前参数
|
||||
if (epoch % 1000 === 0) {
|
||||
console.log(`Epoch ${epoch + 1}, a: ${a}, b: ${b}`);
|
||||
}
|
||||
}
|
||||
|
||||
return [a, b];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 拟合结果接口类型,包含拟合的函数系数和协方差矩阵
|
||||
*/
|
||||
export interface FitRes {
|
||||
theta?: number[];
|
||||
covarianceMatrix?: number[][];
|
||||
error?: number;
|
||||
R_squared?: number;
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {IPoint} from "../drawBoard/DrawPoint"
|
||||
import {FitRes} from "./fittingResult"
|
||||
|
||||
|
||||
/**
|
||||
* 矩阵运算工具类
|
||||
*/
|
||||
export class Matrix {
|
||||
/**
|
||||
* 矩阵转置
|
||||
* @param matrix
|
||||
* @returns
|
||||
*/
|
||||
static transpose(matrix: number[][]): number[][] {
|
||||
return matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 矩阵乘法
|
||||
* @param a
|
||||
* @param b
|
||||
* @returns
|
||||
*/
|
||||
static multiplyMatrices(a: number[][], b: number[][]): number[][] {
|
||||
const result: number[][] = [];
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
// result[i] = [];
|
||||
result.push([]);
|
||||
for (let j = 0; j < b[0].length; j++) {
|
||||
let sum = 0;
|
||||
for (let k = 0; k < b.length; k++) {
|
||||
sum += a[i][k] * b[k][j];
|
||||
}
|
||||
// result[i][j] = sum;
|
||||
result[i].push(sum);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 矩阵求逆
|
||||
* @param matrix
|
||||
* @returns
|
||||
*/
|
||||
static inverseMatrix(matrix: number[][]): number[][] {
|
||||
const size = matrix.length;
|
||||
const augmented = matrix.map((row, i) => [
|
||||
...row,
|
||||
...Array<number>(size).fill(0).map((_, j) => (i === j ? 1 : 0))
|
||||
]);
|
||||
|
||||
for (let i = 0; i < size; i++) {
|
||||
let maxRow = i;
|
||||
for (let k = i + 1; k < size; k++) {
|
||||
if (Math.abs(augmented[k][i]) > Math.abs(augmented[maxRow][i])) {
|
||||
maxRow = k;
|
||||
}
|
||||
}
|
||||
|
||||
let temp = augmented[i];
|
||||
augmented[i] = augmented[maxRow];
|
||||
augmented[maxRow] = temp;
|
||||
// [augmented[i], augmented[maxRow]] = [augmented[maxRow], augmented[i]];
|
||||
|
||||
const divisor = augmented[i][i];
|
||||
for (let j = 0; j < augmented[0].length; j++) {
|
||||
augmented[i][j] /= divisor;
|
||||
}
|
||||
|
||||
for (let k = 0; k < size; k++) {
|
||||
if (k !== i) {
|
||||
const factor = augmented[k][i];
|
||||
for (let j = 0; j < augmented[0].length; j++) {
|
||||
augmented[k][j] -= factor * augmented[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return augmented.map(row => row.slice(size));
|
||||
}
|
||||
|
||||
/**
|
||||
* 最小二乘法
|
||||
* @param m
|
||||
* @param sampleData
|
||||
* @returns
|
||||
*/
|
||||
static leastSquareMethod(m: number, sampleData: Array<IPoint>): FitRes {
|
||||
const x = sampleData.map(d => d.x);
|
||||
const y = sampleData.map(d => d.y);
|
||||
|
||||
const A = x.map(xi => {
|
||||
const row: number[] = [];
|
||||
for (let i = m; i >= 0; i--) {
|
||||
row.push(Math.pow(xi, i));
|
||||
}
|
||||
return row;
|
||||
});
|
||||
|
||||
const yVec = y.map(yi => [yi]);
|
||||
|
||||
const At = Matrix.transpose(A);
|
||||
const AtA = Matrix.multiplyMatrices(At, A);
|
||||
const Aty = Matrix.multiplyMatrices(At, yVec);
|
||||
|
||||
const invAtA = Matrix.inverseMatrix(AtA);
|
||||
const theta = Matrix.multiplyMatrices(invAtA, Aty);
|
||||
|
||||
const residuals = yVec.map((yi, i) => [yi[0] - A[i].reduce((sum, aij, j) => sum + aij * theta[j][0], 0)]);
|
||||
const residualsSquaredSum = residuals.reduce((sum, ri) => sum + ri[0] ** 2, 0);
|
||||
|
||||
const degreesOfFreedom = y.length - (m + 1);
|
||||
const meanSquaredError = residualsSquaredSum / degreesOfFreedom;
|
||||
|
||||
const covarianceMatrix = invAtA.map(row => row.map(value => value * meanSquaredError));
|
||||
|
||||
const fitRes: FitRes = {
|
||||
theta: theta.map(row => row[0]),
|
||||
covarianceMatrix: covarianceMatrix
|
||||
};
|
||||
|
||||
return fitRes;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {IPoint} from "../drawBoard/DrawPoint"
|
||||
import {Matrix} from "./least_square"
|
||||
|
||||
export class Logarithm {
|
||||
static logFunc(x: number, a: number, b: number, c: number): number {
|
||||
return a * Math.log(x) / Math.log(b) + c;
|
||||
}
|
||||
|
||||
linearRegressionLog(sampleData: Array<IPoint>, base: number): number[] {
|
||||
const A = sampleData.map((value) => [Math.log(value.x) / Math.log(base), 1]);
|
||||
const y = sampleData.map((value) => value.y);
|
||||
|
||||
const At = Matrix.transpose(A);
|
||||
const AtA = Matrix.multiplyMatrices(At, A);
|
||||
const Aty = Matrix.multiplyMatrices(At, y.map(v => [v]));
|
||||
|
||||
const invAtA = Matrix.inverseMatrix(AtA);
|
||||
const theta = Matrix.multiplyMatrices(invAtA, Aty);
|
||||
|
||||
const a: number = theta.map(row => row[0])[0];
|
||||
const c: number = theta.map(row => row[0])[1];
|
||||
|
||||
return [ a, c ];
|
||||
}
|
||||
|
||||
static gradientDescentLog(sampleData: Array<IPoint>, learningRate: number = 0.00001, epochs: number = 100000): number[] {
|
||||
let a = 0.001; // 初始化参数
|
||||
let b = 2; // 初始对数底数,需 > 0 且 ≠ 1
|
||||
let c = 0.001;
|
||||
|
||||
const n = sampleData.length;
|
||||
|
||||
for (let epoch = 0; epoch < epochs; epoch++) {
|
||||
let aGrad = 0;
|
||||
let bGrad = 0;
|
||||
let cGrad = 0;
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
const x = sampleData[i].x;
|
||||
const y = sampleData[i].y;
|
||||
let yPredict = Logarithm.logFunc(x, a, b, c);
|
||||
let logX = Math.log(x);
|
||||
let logB = Math.log(b);
|
||||
if (x > 0 && b > 0 && b != 1) {
|
||||
yPredict = Logarithm.logFunc(x, a, b, c);
|
||||
logX = Math.log(x);
|
||||
logB = Math.log(b);
|
||||
} else continue;
|
||||
aGrad += -2 * (y - yPredict) * (logX / logB);
|
||||
bGrad += -2 * (y - yPredict) * (-a * logX / (logB * logB) * (1 / b)); // 链式法则计算 b 的梯度
|
||||
cGrad += -2 * (y - yPredict);
|
||||
}
|
||||
|
||||
a -= (aGrad / n) * learningRate;
|
||||
c -= (cGrad / n) * learningRate;
|
||||
if (b - (bGrad / n) * learningRate <= 0) break;
|
||||
else b -= (bGrad / n) * learningRate;
|
||||
if (Number.isNaN(a) || Number.isNaN(b) || Number.isNaN(c)) {
|
||||
console.error(`Parameters became NaN at epoch ${epoch + 1}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [ a, b, c ];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,441 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { IPoint, PointType } from './DrawPoint';
|
||||
//标准值
|
||||
/**
|
||||
* imageShow组件的大小(vp)
|
||||
*/
|
||||
export const I_WIDTH = 480;//3568 340
|
||||
/**
|
||||
* imageShow组件的大小(vp)
|
||||
*/
|
||||
export const I_HEIGHT = 250;//3568 160
|
||||
/**
|
||||
* 第一个X刻度对应的值
|
||||
*/
|
||||
const X_VALUE = 100
|
||||
/**
|
||||
* 第一个Y刻度对应的值
|
||||
*/
|
||||
const Y_VALUE = 100
|
||||
|
||||
export const SETTING:RenderingContextSettings = new RenderingContextSettings(true)
|
||||
export const CONTEXT:CanvasRenderingContext2D = new CanvasRenderingContext2D(SETTING)
|
||||
export const FIT_CONTEXT:CanvasRenderingContext2D = new CanvasRenderingContext2D(SETTING)
|
||||
CONTEXT.font = '10px sans-serif'
|
||||
export enum Quadrant{
|
||||
ONE = 1,
|
||||
FOUR = 4
|
||||
}
|
||||
|
||||
export abstract class BoardInfo{
|
||||
/**
|
||||
* x刻度之间的像素距离
|
||||
* 初始化后不允许修改
|
||||
*/
|
||||
XGapLen:number
|
||||
/**
|
||||
* y刻度之间的像素距离
|
||||
* 初始化后不允许修改
|
||||
*/
|
||||
YGapLen:number
|
||||
/**
|
||||
* x刻度个数 (+)
|
||||
* 初始化后不允许修改
|
||||
*/
|
||||
XCount:number
|
||||
/**
|
||||
* y刻度个数 (+)
|
||||
* 初始化后不允许修改
|
||||
*/
|
||||
YCount:number
|
||||
/**
|
||||
* 原点的x坐标
|
||||
* 初始化后不可修改
|
||||
*/
|
||||
X_centre:number = 0
|
||||
/**
|
||||
* 原点的y坐标
|
||||
* 初始化后不可修改
|
||||
*/
|
||||
Y_centre:number = 0
|
||||
/**
|
||||
* canvas组件的margin (不包括箭头)
|
||||
* 初始化后不可修改
|
||||
*/
|
||||
margin:number
|
||||
/**
|
||||
* 显示象限
|
||||
* 初始化后不可修改
|
||||
*/
|
||||
quadrant:Quadrant
|
||||
/**
|
||||
* 画板的宽
|
||||
* 初始化后不可修改
|
||||
*/
|
||||
width:number
|
||||
/**
|
||||
* 画板的高
|
||||
* 初始化后不可修改
|
||||
*/
|
||||
height:number
|
||||
|
||||
//以下属性可修改
|
||||
|
||||
/**
|
||||
* 单位X刻度对应的虚拟像素
|
||||
* 根据倍数动态修正
|
||||
*/
|
||||
XUnit2vp:number
|
||||
/**
|
||||
* 单位Y刻度对应虚拟像素
|
||||
* 根据倍数动态修正
|
||||
*/
|
||||
YUnit2vp:number
|
||||
/**
|
||||
* 第一个X刻度对应的值 (+)
|
||||
* 根据倍数动态修正
|
||||
*/
|
||||
XValue:number = X_VALUE
|
||||
/**
|
||||
* 第一个Y刻度对应的值 (+)
|
||||
* 根据倍数动态修正
|
||||
*/
|
||||
YValue:number = Y_VALUE
|
||||
|
||||
/**
|
||||
* 虚拟点集
|
||||
*/
|
||||
virtualPoints:Array<IPoint> = []
|
||||
|
||||
/**
|
||||
* 拟合后得到的函数的点集
|
||||
*/
|
||||
boardPoints:Array<IPoint> = []
|
||||
|
||||
constructor(margin:number,quadrant:Quadrant,Xgl:number,Ygl:number,XC:number,YC:number) {
|
||||
this.margin = margin
|
||||
this.quadrant = quadrant
|
||||
//画板属性
|
||||
this.width = I_WIDTH - 2 * this.margin
|
||||
this.height = I_HEIGHT - 2 * this.margin
|
||||
//定义单位刻度对应像素
|
||||
this.XGapLen = Xgl
|
||||
this.YGapLen = Ygl
|
||||
this.XUnit2vp = Xgl/X_VALUE
|
||||
this.YUnit2vp = Ygl/Y_VALUE
|
||||
//定义个数
|
||||
this.XCount = XC
|
||||
this.YCount = YC
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制坐标轴
|
||||
*/
|
||||
public abstract drawAxis();
|
||||
|
||||
/**
|
||||
* 设置画板上的xy数对
|
||||
* 同时根据xy数对计算出合适的
|
||||
*
|
||||
* 初始化点集 需要保证xy都有赋值
|
||||
*
|
||||
* 返回virtualPoints
|
||||
*/
|
||||
public initMap(virtualPoints?:Array<IPoint>){
|
||||
this.virtualPoints = []
|
||||
if(virtualPoints){
|
||||
this.virtualPoints = virtualPoints
|
||||
}else{
|
||||
let x = 0;
|
||||
let y = 0
|
||||
if(this.quadrant == Quadrant.ONE){
|
||||
for (let index = 0; index < 20; index++) {
|
||||
x = Math.random()*1000
|
||||
y = Math.random()*1000
|
||||
this.virtualPoints.push({x:x,y:y,pointType:PointType.CONTINUE})
|
||||
}
|
||||
}else{
|
||||
for (let index = 0; index < 20; index++) {
|
||||
x = ((Math.random()*2)-1)*500
|
||||
y = ((Math.random()*2)-1)*500
|
||||
this.virtualPoints.push({x:x,y:y,pointType:PointType.CONTINUE})
|
||||
}
|
||||
}
|
||||
}
|
||||
this.boardPoints = []
|
||||
this.transToBoardPoints()
|
||||
|
||||
return this.virtualPoints
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 绘制拟合函数
|
||||
*/
|
||||
public drawFitFunc(points:Array<IPoint>){
|
||||
this.transToBoardPoints(points)
|
||||
this.drawGraph(FIT_CONTEXT,points)
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制散点图
|
||||
*/
|
||||
public drawPoints(context:CanvasRenderingContext2D = CONTEXT,boardPoints:Array<IPoint> = this.boardPoints){
|
||||
context.beginPath()
|
||||
for (let index = 0; index < boardPoints.length; index++) {
|
||||
context.fillRect(vp2px(boardPoints[index].x-1),vp2px(boardPoints[index].y-1),vp2px(1.5),vp2px(1.5))
|
||||
}
|
||||
context.stroke()
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制折线
|
||||
*/
|
||||
public drawGraph(context:CanvasRenderingContext2D = FIT_CONTEXT,boardPoints:Array<IPoint> = this.boardPoints){
|
||||
FIT_CONTEXT.strokeStyle = 'red'
|
||||
let isMeetDisContinue = false
|
||||
let i = 0
|
||||
while(boardPoints[i].pointType == PointType.DISCONTINUE && i <= boardPoints.length - 1){
|
||||
i++
|
||||
}
|
||||
if(i == boardPoints.length){
|
||||
//全间断点
|
||||
return
|
||||
}
|
||||
if(i != 0){
|
||||
context.fillRect(vp2px(boardPoints[i].x - 1),vp2px(boardPoints[i].y - 1),vp2px(1.5),vp2px(1.5))
|
||||
}
|
||||
context.moveTo(vp2px(boardPoints[i].x),vp2px(boardPoints[i].y))
|
||||
//间断点画圆
|
||||
for (let index = i + 1; index < boardPoints.length ; index++) {
|
||||
if(boardPoints[index].pointType == PointType.DISCONTINUE){
|
||||
isMeetDisContinue = true
|
||||
continue
|
||||
}
|
||||
if(isMeetDisContinue){
|
||||
context.moveTo(vp2px(boardPoints[index].x),vp2px(boardPoints[index].y))
|
||||
context.fillRect(vp2px(boardPoints[index].x - 1),vp2px(boardPoints[index].y - 1),vp2px(1.5),vp2px(1.5))
|
||||
isMeetDisContinue = false
|
||||
}else{
|
||||
context.lineTo(vp2px(boardPoints[index].x),vp2px(boardPoints[index].y))
|
||||
}
|
||||
}
|
||||
context.stroke()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将虚拟点集(二维)转变为画布点集
|
||||
*/
|
||||
protected transToBoardPoints(virtualPoints?:Array<IPoint>){
|
||||
if(virtualPoints){
|
||||
for (let index = 0; index < virtualPoints.length; index++) {
|
||||
virtualPoints[index].x = this.getXPosition(virtualPoints[index].x)
|
||||
virtualPoints[index].y = this.getYPosition(virtualPoints[index].y)
|
||||
virtualPoints[index].pointType = virtualPoints[index].pointType
|
||||
}
|
||||
return
|
||||
}
|
||||
for (let index = 0; index < this.virtualPoints.length; index++) {
|
||||
this.boardPoints.push({x:this.getXPosition(this.virtualPoints[index].x),y:this.getYPosition(this.virtualPoints[index].y),pointType:this.virtualPoints[index].pointType})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将虚拟坐标转变为画布坐标x(二维)
|
||||
*/
|
||||
private getXPosition(x:number){
|
||||
return this.X_centre + this.XUnit2vp*x
|
||||
}
|
||||
/**
|
||||
* 将虚拟坐标转变为画布坐标x(二维)
|
||||
*/
|
||||
private getYPosition(y:number){
|
||||
return this.Y_centre - this.YUnit2vp*y
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class board4Q2D extends BoardInfo{
|
||||
|
||||
constructor() {
|
||||
super(5,Quadrant.FOUR,43,21,5,5);//根据具体环境配置
|
||||
this.X_centre = (2 * this.margin + this.width)/2
|
||||
this.Y_centre = (2 * this.margin + this.height)/2
|
||||
}
|
||||
|
||||
public drawAxis(){
|
||||
CONTEXT.beginPath()
|
||||
CONTEXT.moveTo(vp2px(this.margin),vp2px(this.Y_centre))
|
||||
CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre))
|
||||
CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre + 3))
|
||||
CONTEXT.lineTo(vp2px(this.width + this.margin + 3),vp2px(this.Y_centre))
|
||||
CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre - 3))
|
||||
CONTEXT.lineTo(vp2px(this.width + this.margin),vp2px(this.Y_centre))
|
||||
CONTEXT.moveTo(vp2px(this.X_centre),vp2px(this.height + this.margin))
|
||||
CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin))
|
||||
CONTEXT.lineTo(vp2px(this.X_centre - 3),vp2px(this.margin))
|
||||
CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin - 3))
|
||||
CONTEXT.lineTo(vp2px(this.X_centre + 3),vp2px(this.margin))
|
||||
CONTEXT.lineTo(vp2px(this.X_centre),vp2px(this.margin))
|
||||
CONTEXT.fill()
|
||||
CONTEXT.fillText("0",vp2px(this.X_centre + 2),vp2px(this.Y_centre + 15))
|
||||
let valueX = this.X_centre - this.XValue * this.XUnit2vp * (this.XCount + 1)
|
||||
let valueY = this.Y_centre + 6
|
||||
let value = -this.XValue * this.XCount
|
||||
let count = 2 * this.XCount
|
||||
//绘制X轴
|
||||
while(--count >= 0) {
|
||||
valueX += this.XGapLen
|
||||
if(value == 0){
|
||||
value += this.XValue
|
||||
valueX += this.XGapLen
|
||||
}
|
||||
CONTEXT.moveTo(vp2px(valueX),vp2px(this.Y_centre))
|
||||
CONTEXT.lineTo(vp2px(valueX),vp2px(this.Y_centre - 5))
|
||||
CONTEXT.fillText(value.toString(),vp2px(valueX - this.getXTextBias(value.toString()) - 6),vp2px(valueY + 7))
|
||||
value += this.XValue
|
||||
}
|
||||
//绘制Y轴
|
||||
valueX = this.X_centre
|
||||
valueY = this.Y_centre + this.YValue * this.YUnit2vp * (this.YCount + 1)
|
||||
value = -this.YValue * this.YCount
|
||||
count = 2 * this.YCount
|
||||
while(--count >= 0) {
|
||||
valueY -= this.YGapLen
|
||||
if(value == 0){
|
||||
value += this.YValue
|
||||
valueY -= this.YGapLen
|
||||
}
|
||||
CONTEXT.moveTo(vp2px(this.X_centre),vp2px(valueY))
|
||||
CONTEXT.lineTo(vp2px(this.X_centre + 3),vp2px(valueY))
|
||||
CONTEXT.fillText(value.toString(),vp2px(valueX - this.getYTextBias(value.toString()) + 15),vp2px(valueY + 5))
|
||||
value += this.YValue
|
||||
}
|
||||
CONTEXT.stroke()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取修正后的X刻度对应的文本的显示横向偏移量
|
||||
*/
|
||||
private getXTextBias(value:string){
|
||||
|
||||
let bias = value.length
|
||||
let flag = 1
|
||||
if(value[0] == '-'){
|
||||
flag = -2
|
||||
}
|
||||
return (bias * (bias - 1))/2 + 1 + flag * this.XGapLen/50 ;
|
||||
}
|
||||
/**
|
||||
* 获取修正后的Y刻度对应的文本的显示横向偏移量
|
||||
*/
|
||||
private getYTextBias(value:string){
|
||||
let bias = value.length
|
||||
if(bias == 1){
|
||||
return 1
|
||||
}
|
||||
return bias * 3.5 + 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class board1Q2D extends BoardInfo{
|
||||
|
||||
constructor() {
|
||||
super(20,Quadrant.ONE,42,20,10,10);//根据具体环境配置
|
||||
|
||||
this.X_centre = this.margin
|
||||
this.Y_centre = this.margin + this.height
|
||||
}
|
||||
|
||||
public drawAxis(){
|
||||
CONTEXT.beginPath()
|
||||
CONTEXT.moveTo(vp2px(this.margin),vp2px(this.margin + this.height))
|
||||
CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin))
|
||||
CONTEXT.lineTo(vp2px(this.margin - 3),vp2px(this.margin))
|
||||
CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin - 3))
|
||||
CONTEXT.lineTo(vp2px(this.margin + 3),vp2px(this.margin))
|
||||
CONTEXT.lineTo(vp2px(this.margin),vp2px(this.margin))
|
||||
CONTEXT.fill()
|
||||
CONTEXT.moveTo(vp2px(this.margin),vp2px(this.margin + this.height))
|
||||
CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height))
|
||||
CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height + 3))
|
||||
CONTEXT.lineTo(vp2px(this.margin + this.width + 3),vp2px(this.margin + this.height))
|
||||
CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height - 3))
|
||||
CONTEXT.lineTo(vp2px(this.margin + this.width),vp2px(this.margin + this.height))
|
||||
CONTEXT.fill()
|
||||
CONTEXT.fillText("0",vp2px(this.X_centre - 10),vp2px(this.Y_centre + 10))
|
||||
let valueX = this.X_centre
|
||||
let valueY = this.Y_centre + 6
|
||||
let value = this.XValue
|
||||
let count = this.XCount
|
||||
//x轴
|
||||
while(--count >= 0) {
|
||||
valueX += this.XGapLen
|
||||
CONTEXT.moveTo(vp2px(valueX),vp2px(this.Y_centre))
|
||||
CONTEXT.lineTo(vp2px(valueX),vp2px(this.Y_centre - 5))
|
||||
CONTEXT.fillText(value.toString(),vp2px(valueX-this.getXTextBias(value.toString()) - 10),vp2px(valueY + 10))
|
||||
value += this.XValue
|
||||
}
|
||||
//y轴
|
||||
valueX = this.X_centre
|
||||
valueY = this.Y_centre
|
||||
value = this.YValue
|
||||
count = this.YCount
|
||||
while(--count >= 0) {
|
||||
valueY -= this.YGapLen
|
||||
if(value == 0){
|
||||
value += this.YValue
|
||||
valueY -= this.YGapLen
|
||||
}
|
||||
CONTEXT.moveTo(vp2px(this.X_centre),vp2px(valueY))
|
||||
CONTEXT.lineTo(vp2px(this.X_centre + 5),vp2px(valueY))
|
||||
CONTEXT.fillText(value.toString(),vp2px(valueX + 20 - this.getYTextBias(value.toString())),vp2px(valueY + 3))
|
||||
value += this.YValue
|
||||
}
|
||||
CONTEXT.stroke()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取修正后的X刻度对应的文本的显示横向偏移量
|
||||
*/
|
||||
private getXTextBias(value:string){
|
||||
|
||||
let bias = value.length
|
||||
let flag = 1
|
||||
if(value[0] == '-'){
|
||||
flag = -2
|
||||
}
|
||||
return (bias * (bias - 1))/2 + 1 + flag * this.XGapLen/50;
|
||||
}
|
||||
/**
|
||||
* 获取修正后的Y刻度对应的文本的显示横向偏移量
|
||||
*/
|
||||
private getYTextBias(value:string){
|
||||
let bias = value.length
|
||||
if(bias == 1){
|
||||
return 1
|
||||
}
|
||||
return bias * 3.5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export let B4Q2D:BoardInfo = new board4Q2D()
|
||||
export let B1Q2D:BoardInfo = new board1Q2D()
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
Copyright 2026 LI Meng
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
export enum PointType{
|
||||
DISCONTINUE = 0,
|
||||
CONTINUE = 1
|
||||
}
|
||||
/**
|
||||
* 虚拟点集
|
||||
* 根据函数关系和步长、个数直接得到的点集
|
||||
*/
|
||||
export interface IPoint{
|
||||
x:number
|
||||
|
||||
y:number
|
||||
|
||||
pointType:PointType
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
{
|
||||
"module": {
|
||||
"requestPermissions": [
|
||||
{
|
||||
"name": "ohos.permission.FILE_ACCESS_MANAGER"
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
|
||||
}
|
||||
|
||||
],
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"orientation": "landscape",
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"src": [
|
||||
"pages/Index"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "模块描述"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
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);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import abilityTest from './Ability.test';
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest();
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
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');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State message: string = 'Hello World';
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(50)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
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');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_test_desc",
|
||||
"value": "test ability description"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_desc",
|
||||
"value": "the test ability"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_label",
|
||||
"value": "test label"
|
||||
}
|
||||
]
|
||||
}
|
||||