Module:Calculator widget
Appearance
Lua error at line 76: attempt to call global 'regFull' (a nil value).
Creates an interactive 4-function calculator widget (See right). Requires the calculator gadget to work.
Usage
{{#invoke:Calculator widget|getWidget}}
Optional parameter fallback to determine what to do for users without javascript (or calculator gadget enabled). Default "all" to show full thing, "keypad" to show only keypad and "none" to make calculator invisible
local p = {}
-- Make a calculator widget using {{calculator}}
-- As a work around to the fact that buttons can only affect one field, store everything in a single number
-- layout (status = bits 0-2)
-- 9 bits mem, 2 bits memexp, 17 bits x reg, 2 bits exp, 17 bits y reg, 2 bits exp, 1 bit decimal flag, 2 bit status.
-- Negative means show Y reg instead of X reg.
-- status:
-- 0 = Add
-- 1 = sub
-- 2 = mul
-- 3 = div
local ALL_START = 0
local STATUS_START = 0
local STATUS_END = 2
local DECIMAL_START = 2
local DECIMAL_END = 3
local Y_EXP_START = 3
local Y_EXP_END = 5
local Y_START = 5
local Y_END = 22
local X_EXP_START = 22
local X_EXP_END = 24
local X_START = 24
local X_END = 41
local MEM_EXP_START = 41
local MEM_EXP_END = 43
local MEM_START = 43
local MEM_END = 52
local ALL_END = 52
-- These functions return {{calculator}} formulas
-- that are evaled client side.
-- Get value of packed variable
local function unpack(startIndex, endIndex)
local s = 2^startIndex
local e = 2^(endIndex-startIndex)
return "floor((reg/"..s..")%"..e..")"
end
local function pack( value, offset, endOffset )
local maxLen = 2^(endOffset-offset)
offsetMul = 2^offset
return 'ifgreaterorequal( value, ' .. maxLen .. ',NaN,' .. offsetMul .. '*' .. value .. ')'
end
-- select some bits with rest set to 0.
local function selectBits(startIndex, endIndex)
return '('..unpack(startIndex,endIndex) .. '*' .. (2^startIndex).. ')'
end
local function get(reg)
local main_start, main_end, exp_start, exp_end
if reg == 'X' then
main_start = X_START
main_end = X_END
exp_start = X_EXP_START
exp_end = X_EXP_END
else
error( "unknown register" )
end
return '(' .. unpack( X_START, X_END ) ..
'*(pow(10,' .. unpack( X_EXP_START, X_EXP_END ) .. ')))'
end
-- User presses a number.
-- If status
local function pressNumber(x)
return selectBits( ALL_START, X_EXP_START ) .. '+' ..
selectBits( X_END, ALL_END ) .. '+' ..
'ifzero( '
.. regFull("X") .. ',' ..
-- we are not full, so add something
pack(
unpack( X_START, X_END ) .. '*10+' .. x,
X_START,
X_END
) .. '+' ..
pack(
unpack( X_EXP_START, X_EXP_END )
.. '+' .. unpack( DECIMAL_START, DECIMAL_END )
) ..
',' ..
-- Overflow, do not allow additional digits
selectBits( X_EXP_START, X_END )
.. ')'
end
function p.getWidget( frame )
local buttons = {
{ "MC", "" },
{ "MR", "" },
{ "M−", "" },
{ "M+", "" },
{ "C", "" },
{ "±", "" },
{ "%", "" },
{ "√", "" },
{ "7", pressNumber(7) },
{ "8", pressNumber(8) },
{ "9", pressNumber(9) },
{ "÷", "" },
{ "4", pressNumber(4) },
{ "5", pressNumber(5) },
{ "6", pressNumber(6) },
{ "×", "" },
{ "1", pressNumber(1) },
{ "2", pressNumber(2) },
{ "3", pressNumber(3) },
{ "−", "" },
{ "0", pressNumber(0) },
{ ".", "" },
{ "=", "" },
{ "+", "" },
}
local calc = '<div class="calculator" style="display:grid;grid-template-columns:repeat(4, 1fr);grid-gap:5px;min-width:256px;width:20ch;border:thin solid gray"><div style="grid-column:1/5;">{{Calculator codex text|default=0|id=ans|style=text-align:right|readonly=1}}</div>'
for i, v in ipairs(buttons) do
local type = v[1] == 'C' and 'destructive' or 'default'
-- maybe make "=" be progressive instead of default. Perhaps weight = primary?
calc = calc .. '{{calculator button|type='.. type ..'|weight=normal|for=reg|formula=' .. v[2] .. '|contents='.. v[1] .. '}}'
end
calc = calc .. '</div>'
return frame:preprocess(calc)
end
return p