252 lines
5.5 KiB
Lua
252 lines
5.5 KiB
Lua
-- author: https://github.com/ChaosAlphard
|
||
-- 说明 https://github.com/gaboolic/rime-shuangpin-fuzhuma/pull/41
|
||
local M = {}
|
||
|
||
function M.init(env)
|
||
local config = env.engine.schema.config
|
||
env.name_space = env.name_space:gsub('^*', '')
|
||
M.prefix = config:get_string(env.name_space .. '/trigger') or 'V'
|
||
end
|
||
|
||
local function startsWith(str, start)
|
||
return string.sub(str, 1, string.len(start)) == start
|
||
end
|
||
|
||
local function truncateFromStart(str, truncateStr)
|
||
return string.sub(str, string.len(truncateStr) + 1)
|
||
end
|
||
|
||
-- 函数表
|
||
local calcPlugin = {
|
||
-- e, exp(1) = e^1 = e
|
||
e = math.exp(1),
|
||
-- π
|
||
pi = math.pi
|
||
}
|
||
|
||
-- random([m [,n ]]) 返回m-n之间的随机数, n为空则返回1-m之间, 都为空则返回0-1之间的小数
|
||
local function random(...)
|
||
return math.random(...)
|
||
end
|
||
-- 注册到函数表中
|
||
calcPlugin["rdm"] = random
|
||
|
||
-- 正弦
|
||
local function sin(x)
|
||
return math.sin(x)
|
||
end
|
||
calcPlugin["sin"] = sin
|
||
|
||
-- 双曲正弦
|
||
local function sinh(x)
|
||
return math.sinh(x)
|
||
end
|
||
calcPlugin["sinh"] = sinh
|
||
|
||
-- 反正弦
|
||
local function asin(x)
|
||
return math.asin(x)
|
||
end
|
||
calcPlugin["asin"] = asin
|
||
|
||
-- 余弦
|
||
local function cos(x)
|
||
return math.cos(x)
|
||
end
|
||
calcPlugin["cos"] = cos
|
||
|
||
-- 双曲余弦
|
||
local function cosh(x)
|
||
return math.cosh(x)
|
||
end
|
||
calcPlugin["cosh"] = cosh
|
||
|
||
-- 反余弦
|
||
local function acos(x)
|
||
return math.acos(x)
|
||
end
|
||
calcPlugin["acos"] = acos
|
||
|
||
-- 正切
|
||
local function tan(x)
|
||
return math.tan(x)
|
||
end
|
||
calcPlugin["tan"] = tan
|
||
|
||
-- 双曲正切
|
||
local function tanh(x)
|
||
return math.tanh(x)
|
||
end
|
||
calcPlugin["tanh"] = tanh
|
||
|
||
-- 反正切
|
||
local function atan(x)
|
||
return math.atan(x)
|
||
end
|
||
calcPlugin["atan"] = atan
|
||
|
||
-- 返回以弧度为单位的点(x,y)相对于x轴的逆时针角度。y是点的纵坐标,x是点的横坐标
|
||
-- 返回范围从−π到π (以弧度为单位),其中负角度表示向下旋转,正角度表示向上旋转
|
||
-- 它与传统的 math.atan(y/x) 函数相比,具有更好的数学定义,因为它能够正确处理边界情况(例如x=0)
|
||
local function atan2(y, x)
|
||
return math.atan2(y, x)
|
||
end
|
||
calcPlugin["atan2"] = atan2
|
||
|
||
-- 将角度从弧度转换为度 e.g. deg(π) = 180
|
||
local function deg(x)
|
||
return math.deg(x)
|
||
end
|
||
calcPlugin["deg"] = deg
|
||
|
||
-- 将角度从度转换为弧度 e.g. rad(180) = π
|
||
local function rad(x)
|
||
return math.rad(x)
|
||
end
|
||
calcPlugin["rad"] = rad
|
||
|
||
-- 返回两个值, 无法参与运算后续
|
||
-- 返回m,e 使得x = m*2^e
|
||
-- local function frexp(x)
|
||
-- return math.frexp(x)
|
||
-- end
|
||
-- calcPlugin["frexp"] = frexp
|
||
|
||
-- 返回 x*2^y
|
||
local function ldexp(x, y)
|
||
return math.ldexp(x, y)
|
||
end
|
||
calcPlugin["ldexp"] = ldexp
|
||
|
||
-- 返回 e^x
|
||
local function exp(x)
|
||
return math.exp(x)
|
||
end
|
||
calcPlugin["exp"] = exp
|
||
|
||
-- 返回x的平方根 e.g. sqrt(x) = x^0.5
|
||
local function sqrt(x)
|
||
return math.sqrt(x)
|
||
end
|
||
calcPlugin["sqrt"] = sqrt
|
||
|
||
-- x为底的对数, log(10, 100) = log(100) / log(10) = 2
|
||
local function log(x, y)
|
||
-- 不能为负数或0
|
||
if x <= 0 or y <= 0 then return nil end
|
||
|
||
return math.log(y) / math.log(x)
|
||
end
|
||
calcPlugin["log"] = log
|
||
|
||
-- 自然数e为底的对数
|
||
local function loge(x)
|
||
-- 不能为负数或0
|
||
if x <= 0 then return nil end
|
||
|
||
return math.log(x)
|
||
end
|
||
calcPlugin["loge"] = loge
|
||
|
||
-- 10为底的对数
|
||
local function log10(x)
|
||
-- 不能为负数或0
|
||
if x <= 0 then return nil end
|
||
|
||
return math.log10(x)
|
||
end
|
||
calcPlugin["log10"] = log10
|
||
|
||
-- 平均值
|
||
local function avg(...)
|
||
local data = {...}
|
||
local n = select("#", ...)
|
||
-- 样本数量不能为0
|
||
if n == 0 then return nil end
|
||
|
||
-- 计算总和
|
||
local sum = 0
|
||
for _, value in ipairs(data) do
|
||
sum = sum + value
|
||
end
|
||
|
||
return sum / n
|
||
end
|
||
calcPlugin["avg"] = avg
|
||
|
||
-- 方差
|
||
local function variance(...)
|
||
local data = {...}
|
||
local n = select("#", ...)
|
||
-- 样本数量不能为0
|
||
if n == 0 then return nil end
|
||
|
||
-- 计算均值
|
||
local sum = 0
|
||
for _, value in ipairs(data) do
|
||
sum = sum + value
|
||
end
|
||
local mean = sum / n
|
||
|
||
-- 计算方差
|
||
local sum_squared_diff = 0
|
||
for _, value in ipairs(data) do
|
||
sum_squared_diff = sum_squared_diff + (value - mean)^2
|
||
end
|
||
|
||
return sum_squared_diff / n
|
||
end
|
||
calcPlugin["var"] = variance
|
||
|
||
-- 阶乘
|
||
local function factorial(x)
|
||
-- 不能为负数
|
||
if x < 0 then return nil end
|
||
if x == 0 or x == 1 then return 1 end
|
||
|
||
local result = 1
|
||
for i = 1, x do
|
||
result = result * i
|
||
end
|
||
|
||
return result
|
||
end
|
||
calcPlugin["fact"] = factorial
|
||
|
||
-- 实现阶乘计算(!)
|
||
local function replaceToFactorial(str)
|
||
-- 替换[0-9]!字符为fact([0-9])以实现阶乘
|
||
return str:gsub("([0-9]+)!", "fact(%1)")
|
||
end
|
||
|
||
-- 简单计算器
|
||
function M.func(input, seg, env)
|
||
if not startsWith(input, M.prefix) then return end
|
||
-- 提取算式
|
||
local express = truncateFromStart(input, M.prefix)
|
||
-- 算式长度 < 2 直接终止(没有计算意义)
|
||
if (string.len(express) < 2) then return end
|
||
-- pcall()的原因需要控制一下 . 符号的位置
|
||
-- 现在不需要了
|
||
-- if (string.match(express, "[^0-9]%.")) then
|
||
-- yield(Candidate(input, seg.start, seg._end, express, "小数点不能在非数字字符后面"))
|
||
-- return
|
||
-- end
|
||
local code = replaceToFactorial(express)
|
||
|
||
local success, result = pcall(load("return " .. code, "calculate", "t", calcPlugin))
|
||
if success then
|
||
yield(Candidate(input, seg.start, seg._end, result, ""))
|
||
yield(Candidate(input, seg.start, seg._end, express .. "=" .. result, ""))
|
||
else
|
||
yield(Candidate(input, seg.start, seg._end, express, "解析失败"))
|
||
yield(Candidate(input, seg.start, seg._end, code, "入参"))
|
||
-- TODO: 错误信息记录到日志中
|
||
-- print("express: " .. express)
|
||
-- print("code: " .. code)
|
||
-- print("result: " .. result)
|
||
end
|
||
end
|
||
|
||
return M
|