@liangjiehappy/dsh-calc-math 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/cordis.patch.yml +4 -0
- package/lib/index.js +118 -0
- package/package.json +14 -4
package/README.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 数学表达式求值
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
算任意数学表达式:四则、括号、幂、开方、三角函数、对数。比开计算器 App 快。纯本地计算,不联网。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
dsh plugin --profile web add @liangjiehappy/dsh-calc-math
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 用法
|
|
12
|
+
|
|
13
|
+
在会话里说「算 (3+5)*2^3/4 等于多少」,或直接调用工具 `calc_math`。
|
|
14
|
+
|
|
15
|
+
## 许可
|
|
16
|
+
|
|
17
|
+
MIT
|
package/cordis.patch.yml
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数学表达式求值
|
|
3
|
+
*
|
|
4
|
+
* 算任意数学表达式:四则、括号、幂、开方、三角函数、对数。比开计算器 App 快。纯本地计算,不联网。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const name = "dsh-calc-math";
|
|
8
|
+
|
|
9
|
+
export const inject = ["tools"];
|
|
10
|
+
|
|
11
|
+
const TEXT_OUTPUT = {
|
|
12
|
+
schema: {
|
|
13
|
+
type: "object",
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
properties: {
|
|
16
|
+
text: { type: "string" },
|
|
17
|
+
},
|
|
18
|
+
required: ["text"],
|
|
19
|
+
},
|
|
20
|
+
render: (_args, value) => [
|
|
21
|
+
{ type: "text", text: (value && value.text) || "" },
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// ══════════════════════════════════════════════════════════
|
|
26
|
+
// 通用工具函数
|
|
27
|
+
// ══════════════════════════════════════════════════════════
|
|
28
|
+
|
|
29
|
+
const TITLE = "__CALC_TITLE__";
|
|
30
|
+
|
|
31
|
+
function fmt(n, digits) {
|
|
32
|
+
if (!Number.isFinite(n)) return String(n);
|
|
33
|
+
const d = digits == null ? 2 : digits;
|
|
34
|
+
if (Math.abs(n) >= 1e12) return n.toExponential(6);
|
|
35
|
+
let s = n.toFixed(d);
|
|
36
|
+
if (d > 0) s = s.replace(/0+$/, "").replace(/\.$/, "");
|
|
37
|
+
return s;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function money(n) {
|
|
41
|
+
if (!Number.isFinite(n)) return String(n);
|
|
42
|
+
return n.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function num(v, def) {
|
|
46
|
+
const n = Number(v);
|
|
47
|
+
return Number.isFinite(n) ? n : (def == null ? 0 : def);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function line(label, value, unit) {
|
|
51
|
+
const pad = " ";
|
|
52
|
+
return pad + label + ":" + value + (unit ? " " + unit : "");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function head(title) {
|
|
56
|
+
return [title, "=".repeat(52)];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ══════════════════════════════════════════════════════════
|
|
60
|
+
// 工具
|
|
61
|
+
// ══════════════════════════════════════════════════════════
|
|
62
|
+
|
|
63
|
+
export function apply(ctx, config) {
|
|
64
|
+
void config;
|
|
65
|
+
|
|
66
|
+
ctx.tools.register({
|
|
67
|
+
name: "calc_math",
|
|
68
|
+
description:
|
|
69
|
+
"数学表达式求值。支持 + - * / ^ %、括号、sqrt/abs/sin/cos/tan/log/ln/exp、pi/e。",
|
|
70
|
+
parameters: {
|
|
71
|
+
expr: { type: "string", required: true, description: "数学表达式,如 (3+5)*2^3/4" },
|
|
72
|
+
},
|
|
73
|
+
output: TEXT_OUTPUT,
|
|
74
|
+
async execute(args) {
|
|
75
|
+
try {
|
|
76
|
+
const a = args || {};
|
|
77
|
+
const expr = String(a.expr || "").trim();
|
|
78
|
+
if (!expr) return { text: "expr 必填" };
|
|
79
|
+
// 只允许安全字符
|
|
80
|
+
if (!/^[0-9+\-*/^%().,\s a-zA-Z_]+$/.test(expr)) {
|
|
81
|
+
return { text: "表达式里有不允许的字符" };
|
|
82
|
+
}
|
|
83
|
+
let js = expr
|
|
84
|
+
.replace(/\^/g, "**")
|
|
85
|
+
.replace(/\bpi\b/g, "Math.PI")
|
|
86
|
+
.replace(/\be\b/g, "Math.E")
|
|
87
|
+
.replace(/\bsqrt\b/g, "Math.sqrt")
|
|
88
|
+
.replace(/\babs\b/g, "Math.abs")
|
|
89
|
+
.replace(/\bsin\b/g, "Math.sin")
|
|
90
|
+
.replace(/\bcos\b/g, "Math.cos")
|
|
91
|
+
.replace(/\btan\b/g, "Math.tan")
|
|
92
|
+
.replace(/\basin\b/g, "Math.asin")
|
|
93
|
+
.replace(/\bacos\b/g, "Math.acos")
|
|
94
|
+
.replace(/\batan\b/g, "Math.atan")
|
|
95
|
+
.replace(/\blog10\b/g, "Math.log10")
|
|
96
|
+
.replace(/\blog\b/g, "Math.log10")
|
|
97
|
+
.replace(/\bln\b/g, "Math.log")
|
|
98
|
+
.replace(/\bexp\b/g, "Math.exp")
|
|
99
|
+
.replace(/\bfloor\b/g, "Math.floor")
|
|
100
|
+
.replace(/\bceil\b/g, "Math.ceil")
|
|
101
|
+
.replace(/\bround\b/g, "Math.round")
|
|
102
|
+
.replace(/\bmin\b/g, "Math.min")
|
|
103
|
+
.replace(/\bmax\b/g, "Math.max");
|
|
104
|
+
// eslint-disable-next-line no-new-func
|
|
105
|
+
const v = Function('"use strict";return (' + js + ")")();
|
|
106
|
+
if (typeof v !== "number" || !Number.isFinite(v)) throw new Error("结果不是有限数字");
|
|
107
|
+
const L = head("数学表达式");
|
|
108
|
+
L.push(line("表达式", expr));
|
|
109
|
+
L.push(line("结果", fmt(v, 10)));
|
|
110
|
+
L.push("");
|
|
111
|
+
L.push(" 支持: + - * / ^ % ( ) sqrt abs sin cos tan log ln exp pi e");
|
|
112
|
+
return { text: L.join("\n") };
|
|
113
|
+
} catch (e) {
|
|
114
|
+
return { text: "计算失败: " + String((e && e.message) || e) };
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liangjiehappy/dsh-calc-math",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "算任意数学表达式:四则、括号、幂、开方、三角函数、对数。比开计算器 App 快。纯本地计算,不联网。",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"files": ["lib", "cordis.patch.yml", "README.md"],
|
|
8
|
+
"keywords": ["dsh", "dsh-plugin", "calc", "calculator", "math", "计算器"],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/moldkey/dsh-calc-math.git"
|
|
13
|
+
},
|
|
14
|
+
"dsh": { "bundle": { "patch": "./cordis.patch.yml" } },
|
|
15
|
+
"engines": { "dsh": ">=0.2.0-rc.2" }
|
|
16
|
+
}
|