210 lines
6.1 KiB
Lua
210 lines
6.1 KiB
Lua
-- 计算器插件
|
||
-- author: https://github.com/ChaosAlphard
|
||
local calc = {}
|
||
|
||
function calc.init( env )
|
||
local config = env.engine.schema.config
|
||
env.prefix = config:get_string( 'calculator/prefix' ) or 'cC'
|
||
env.show_prefix = config:get_bool( 'calculator/show_prefix' ) -- set to true to show prefix in preedit area
|
||
-- env.decimalPlaces = config:get_string('calculator/decimalPlaces') or '4'
|
||
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 function yield_calc_cand( seg, cand_text, cand_comment, cand_preedit, show_prefix )
|
||
local cand = Candidate( 'calc', seg.start, seg._end, cand_text, cand_comment )
|
||
cand.quality = 99999
|
||
if not show_prefix then cand.preedit = cand_preedit end
|
||
yield( cand )
|
||
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
|
||
calcPlugin['random'] = 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
|
||
|
||
-- 反正切
|
||
-- 返回以弧度为单位的点相对于x轴的逆时针角度。x是点的横纵坐标比值
|
||
-- 返回范围从−π到π (以弧度为单位),其中负角度表示向下旋转,正角度表示向上旋转
|
||
local function atan( x ) return math.atan( x ) end
|
||
calcPlugin['atan'] = atan
|
||
|
||
-- 反正切
|
||
-- atan( y/x ) = atan2(y, x)
|
||
-- 返回以弧度为单位的点相对于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 )
|
||
local m, e = math.frexp( x )
|
||
return m .. ' * 2^' .. e
|
||
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
|
||
|
||
-- y为底x的对数, 使用换底公式实现
|
||
local function log( y, x )
|
||
-- 不能为负数或0
|
||
if x <= 0 or y <= 0 then return nil end
|
||
|
||
return math.log( x ) / math.log( y )
|
||
end
|
||
calcPlugin['log'] = log
|
||
|
||
-- e为底x的对数
|
||
local function loge( x )
|
||
-- 不能为负数或0
|
||
if x <= 0 then return nil end
|
||
|
||
return math.log( x )
|
||
end
|
||
calcPlugin['loge'] = loge
|
||
|
||
-- 10为底x的对数
|
||
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 calc.func( input, seg, env )
|
||
if not seg:has_tag( 'calculator' ) or input == '' then return end
|
||
-- 提取算式
|
||
local express = truncateFromStart( input, env.prefix )
|
||
if express == '' then return end -- 防止用户写错了正则表达式造成错误
|
||
local code = replaceToFactorial( express )
|
||
local success, result = pcall( load( 'return ' .. code, 'calculate', 't', calcPlugin ) )
|
||
if success and result and (type( result ) == 'string' or type( result ) == 'number') and #tostring( result ) > 0 then
|
||
yield_calc_cand( seg, result, '', express, env.show_prefix )
|
||
yield_calc_cand( seg, express .. '=' .. result, '', express, env.show_prefix )
|
||
else
|
||
yield_calc_cand( seg, express, '解析失败', express, env.show_prefix )
|
||
yield_calc_cand( seg, code, '入参', express, env.show_prefix )
|
||
end
|
||
end
|
||
|
||
return calc
|