Jump to content

Module:Calculator widget

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Bawolff (talk | contribs) at 01:51, 7 January 2025 (fix some weirdness with the negative button.). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

local p = {}

-- Make a calculator widget using {{calculator}}

local function getDisplay()
	return 'ifzero(displayY,x,y)'
end

local function pressDecimal()
	return {
		{'decimal', 'ifequal(decimal,0,1,decimal)'},
		{ 'y', 'ifzero(equalFlag,y,0)' },
		{ 'x', 'ifzero(displayY,x,0)' },
		{ 'equalFlag', 0 },
		{ 'displayY', '0' }
	}
end

-- This is sketch because x should happen before decimal.
function pressNumber(n)
	return { {'x', 'ifequal(decimal,0,not(displayY)*x*10+(ifpositive(not(displayY)*x,1,-1))*' .. n .. ','
		.. 'x+(ifpositive(x,1,-1))*(' .. n .. '/pow(10,decimal)))'},
		{'decimal','ifzero(decimal,0,decimal+1)'},
		{ 'y', 'ifzero(equalFlag,y,0)' },
		{ 'op', 'ifzero(equalFlag,op,0)' },
		{ 'equalFlag', 0 },
		{ 'displayY', '0' },
	}
end

function getClear()
	return {
		{ 'x', '0' },
		{ 'y', '0' },
		{ 'op', '0' },
		{ 'decimal', '0' },
		{ 'percentFlag', '0' },
		{ 'equalFlag', '0' },
		{ 'displayY', '0' },
	}
end

function compute(op)
	local res = {
		{ 'x', 'ifequal(percentFlag, 1, x*y/100, x)' },
		{ 'y', 'switch(op,0,x+y,1,y-x,2,x*y,3,y/x)' },
		--{ 'x', '0' },
		{ 'decimal', '0' },
		{ 'displayY', '1' },
		{ 'percentFlag', 0 },
		{ 'op', tostring(op) }
	}
	-- After pressing equal, you can either type a new number
	-- or continue using the current value by pressing an operator.
	if op == 'op' then
		res[#res+1] = { 'equalFlag', '1' }
	else
		res[#res+1] = { 'equalFlag', 0 }
	end
	
	return res
end

function p.getWidget( frame )
	local buttons = {
		{ "MC", {{"mem", "0"}} },
		{ "MR", {{"x", "mem"},{"displayY", 0}} },
		{ "M−", {{"mem", "ifzero(displayY,mem-x,mem-y)"}} },
		{ "M+", {{"mem", "ifzero(displayY,mem+x,mem+y)"}} },
		{ "C", getClear() },
		{ "±", {{'x', '0-x'}} },
		{ "%", {{'percentFlag', '1'}} },
		{ "√", {{'x','sqrt(x)'}} },
		{ "7", pressNumber(7) },
		{ "8", pressNumber(8) },
		{ "9", pressNumber(9) },
		{ "÷", compute(3) },
		{ "4", pressNumber(4) },
		{ "5", pressNumber(5) },
		{ "6", pressNumber(6) },
		{ "×", compute(2) },
		{ "1", pressNumber(1) },
		{ "2", pressNumber(2) },
		{ "3", pressNumber(3) },
		{ "−", compute(1) },
		{ "0", pressNumber(0) },
		{ ".", pressDecimal() },
		{ "=", compute('op') },
		{ "+", compute(0) },
	}
	local calc = '<div class="calculatorwidget calculator-container" style="display:grid;grid-template-columns:repeat(4, 1fr);grid-gap:5px;min-width:256px;width:20ch;border:thin solid gray;padding: 5px; background: #eee">'
	-- On Calculator page, we want to show the layout of buttons on print, but
	-- not the answer field.
	.. '<div style="grid-column:1/5;display:none" class="calculatorgadget-enabled">{{Calculator codex text|default=0|id=ans|formula=' .. getDisplay() .. '|style=text-align:right;font-weight:bold;|readonly=1|NaN-text=Error}}</div>'
	for i, v in ipairs(buttons) do
		local calcType, calcWeight
		if v[1] == 'C' then
			calcType = 'destructive'
			calcWeight = 'normal'
		elseif v[1] == '=' then
			calcType = 'progressive'
			calcWeight = 'primary'
		else
			calcType = 'default'
			calcWeight = 'normal'
		end
		-- maybe make "=" be progressive instead of default. Perhaps weight = primary?
		local forVar = ''
		local formula = ''
		for i2, v2 in ipairs( v[2] ) do
			forVar = forVar .. ';' .. v2[1]
			formula = formula .. ';' .. v2[2]
		end
		calc = calc .. '{{calculator button|type='.. calcType ..'|weight='.. calcWeight .. '|for=' .. string.sub(forVar,2) .. '|formula=' .. string.sub(formula,2) .. '|contents='.. v[1] .. '}}'
	end
	calc = calc .. '{{calculator|type=hidden|id=x|default=0}}'
	calc = calc .. '{{calculator|type=hidden|id=y|default=0}}'
	calc = calc .. '{{calculator|type=hidden|id=mem|default=0}}'
	calc = calc .. '{{calculator|type=hidden|id=op|default=0}}'
	calc = calc .. '{{calculator|type=hidden|id=decimal|default=0}}'
	calc = calc .. '{{calculator|type=hidden|id=displayY|default=0}}'
	calc = calc .. '{{calculator|type=hidden|id=percentFlag|default=0}}'
	calc = calc .. '{{calculator|type=hidden|id=equalFlag|default=0}}'
	calc = calc .. '</div>'
	return frame:preprocess(calc)
end

return p