--[[Smart Calculator by Cranium]] -- local tX, tY = term.getSize() local calc = {} --equation states calc.mode = false calc.inverse = false calc.hyp = false calc.sqrt = false calc.exp = false calc.asin = false calc.sin = false calc.sinh = false calc.atan = false calc.tan = false calc.tanh = false calc.acos = false calc.cos = false calc.cosh = false calc.log = false calc.pos = false -- characters local charList = { ["0"] = { ".-.", "| |", "'-'" }, ["1"] = { " . ", "'| ", "---" }, ["2"] = { ".-.", ".-'", "'- " }, ["3"] = { " -.", " -|", " -'" }, ["4"] = { ". .", "'-|", " '" }, ["5"] = { ".- ", "'-.", " -'" }, ["6"] = { ".-.", "|-.", "'-'" }, ["7"] = { ".-.", " |", " '" }, ["8"] = { ".-.", "|-|", "'-'" }, ["9"] = { ".-.", "'-|", " -'" }, ["."] = { " ", " ", " . " }, ["-"] = { " ", " --", " " }, } -- lay out the button labels local labels = { ' + ', ' 1 ', ' 2 ', ' 3 ', '<--', 'sin', 'x^y', 'DEG', 'OFF', ' - ', ' 4 ', ' 5 ', ' 6 ', 'CLR', 'cos', 'srt', 'RAD', ' ', ' x ', ' 7 ', ' 8 ', ' 9 ', ' ', 'tan', 'Pi ', 'inv', ' ', ' / ', ' 0 ', '-/+', ' . ', ' = ', 'log', 'exp', 'hyp', ' ' } -- generate the objects local function objGen() local _objects = {} local width = 9 for i = 1, #labels do table.insert(_objects, { x = (((i - 1) % width + 1) * 5) - 1, y = (math.ceil(i / width) * 3) + 4, label = labels[i], -- make operators different colors color = i == 1 and colors.blue or i == 5 and colors.red or i == 6 and colors.yellow or i == 7 and colors.orange or i == 8 and colors.white or i == 9 and colors.red or i == 10 and colors.blue or i == 14 and colors.red or i == 15 and colors.yellow or i == 16 and colors.orange or i == 17 and colors.white or i == 18 and colors.white or i == 19 and colors.blue or i == 24 and colors.yellow or i == 25 and colors.orange or i == 26 and colors.white or i == 27 and colors.white or i == 28 and colors.blue or i == 30 and colors.red or i == 32 and colors.white or i == 33 and colors.yellow or i == 34 and colors.orange or i == 35 and colors.white or i == 36 and colors.white or colors.lightGray, -- controls the highlight colors for operators back = i == 6 and calc.sin == true and colors.red or calc.asin == true and colors.red or calc.sinh == true and colors.red or i == 8 and calc.mode == "deg" and colors.blue or i == 15 and calc.cos == true and colors.red or calc.acos == true and colors.red or calc.cosh == true and colors.red or i == 16 and calc.sqrt == true and colors.lightBlue or i == 17 and calc.mode == "rad" and colors.blue or i == 24 and calc.tan == true and colors.red or calc.atan == true and colors.red or calc.tanh == true and colors.red or i == 26 and calc.inverse == true and colors.blue or i == 30 and calc.pos == true and colors.white or i == 33 and calc.log == true and colors.red or i == 34 and calc.exp == true and colors.lightBlue or i == 35 and calc.hyp == true and colors.blue or colors.black, }) end return _objects end local function draw() term.setBackgroundColor(colors.black) term.clear() local objects = objGen() for i = 1, #objects do local obj = objects[i] term.setTextColor(colors.gray) term.setBackgroundColor(colors.black) --draw the grid for num, line in pairs { '+---+', '| |', '+---+' } do term.setCursorPos(obj.x, obj.y + num - 1) write(line) end --draw the button text and colors term.setCursorPos(obj.x + 1, obj.y + 1) term.setTextColor(obj.color) term.setBackgroundColor(obj.back) write(obj.label) end end --draw border and screen local function display() term.setBackgroundColor(colors.black) term.setTextColor(colors.gray) term.setCursorPos(2, 1) write("+" .. string.rep("-", tX - 4) .. "+") for i = 2, tY - 1 do term.setCursorPos(2, i) write("|") term.setCursorPos(tX - 1, i) write("|") end term.setCursorPos(2, tY) write("+" .. string.rep("-", tX - 4) .. "+") term.setBackgroundColor(colors.lightGray) for i = 2, 6 do term.setCursorPos(4, i) write(string.rep(" ", tX - 6)) end end --run the equation passed by the user. local function calculate(eq) if table.concat(eq) == "()" then eq = { "0" } elseif table.concat(eq) == "(.)" then eq = { "0" } end local sExpr = table.concat(eq) local fnMath, sErr = loadstring("return " .. sExpr) if not fnMath then return "ERROR! Check syntax!" end --setfenv(fnMath, math) local bSucc, vRes = pcall(fnMath) if not bSucc then return "ERROR! Check syntax!" else return vRes end end -- function loop local equation = { "(", ")" } local result = "0" while true do local rLen = 0 draw() display() term.setBackgroundColor(colors.lightGray) term.setTextColor(colors.white) term.setCursorPos(4, 2) --write the equation write(table.concat(equation)) --write the result if tonumber(result) ~= inf then if string.len(result) >= 15 then term.setCursorPos(5, 4) term.setTextColor(colors.black) write("= ") for num in string.gmatch(result, ".") do rLen = rLen + 1 local pX, pY = term.getCursorPos() if pX >= 4 and pX <= 48 then term.setCursorPos(rLen + 5, 4) write(num) else term.setCursorPos(rLen + 5 - 48, 5) write(num) end end else for num in string.gmatch(result, ".") do rLen = rLen + 1 for i = 1, #charList[num] do term.setTextColor(colors.black) term.setCursorPos((rLen * 3) + 1, i + 3) write(charList[num][i]) end end end elseif result == nil then term.setCursorPos(5, 4) term.setTextColor(colors.black) write("= ERROR") else term.setCursorPos(5, 4) term.setTextColor(colors.black) write("= INFINITY") end local events = { os.pullEvent() } --mouse click filter if events[1] == "mouse_click" and events[2] == 1 then if events[3] >= 44 and events[3] <= 48 then if events[4] >= 7 and events[4] <= 9 then term.setBackgroundColor(colors.black) term.clear() term.setCursorPos(1, 1) os.reboot() end elseif events[3] >= 39 and events[3] <= 43 then if events[4] >= 7 and events[4] <= 9 then if calc.mode == false then table.remove(equation, 1) calc.mode = "deg" table.insert(equation, 1, "math.deg(") elseif calc.mode == "deg" then table.remove(equation, 1) calc.mode = false elseif calc.mode == "rad" then table.remove(equation, 1) calc.mode = "deg" table.insert(equation, 1, "math.deg(") end elseif events[4] >= 10 and events[4] <= 12 then if calc.mode == false then table.remove(equation, 1) calc.mode = "rad" table.insert(equation, 1, "math.rad(") elseif calc.mode == "rad" then table.remove(equation, 1) calc.mode = false elseif calc.mode == "deg" then table.remove(equation, 1) calc.mode = "rad" table.insert(equation, 1, "math.rad(") end elseif events[4] >= 13 and events[4] <= 15 then if calc.inverse == true and calc.hyp == false then calc.inverse = false elseif calc.inverse == false and calc.hyp == true then calc.inverse = true calc.hyp = false elseif calc.inverse == false and calc.hyp == false then calc.inverse = true end elseif events[4] >= 16 and events[4] <= 18 then if calc.hyp == true and calc.inverse == false then calc.hyp = false elseif calc.hyp == false and calc.inverse == true then calc.hyp = true calc.inverse = false elseif calc.hyp == false and calc.inverse == false then calc.hyp = true end end elseif events[3] >= 34 and events[3] <= 38 then if events[4] >= 7 and events[4] <= 9 then table.insert(equation, #equation, "^") elseif events[4] >= 10 and events[4] <= 12 then if calc.sqrt == false then table.insert(equation, #equation, "math.sqrt(") calc.sqrt = true elseif calc.sqrt == true then table.insert(equation, #equation, ")") calc.sqrt = false end elseif events[4] >= 13 and events[4] <= 15 then table.insert(equation, #equation, "math.pi") elseif events[4] >= 16 and events[4] <= 18 then if calc.exp == false then table.insert(equation, #equation, "math.exp(") calc.exp = true elseif calc.exp == true then table.insert(equation, #equation, ")") calc.exp = false end end elseif events[3] >= 29 and events[3] <= 33 then if events[4] >= 7 and events[4] <= 9 then if calc.inverse == true and calc.asin == false then table.insert(equation, #equation, "math.asin(") calc.asin = true elseif calc.inverse == false and calc.hyp == false and calc.sin == false then table.insert(equation, #equation, "math.sin(") calc.sin = true elseif calc.hyp == true and calc.sinh == false then table.insert(equation, #equation, "math.sinh(") calc.sinh = true elseif calc.asin == true then table.insert(equation, #equation, ")") calc.asin = false elseif calc.sin == true then table.insert(equation, #equation, ")") calc.sin = false elseif calc.sinh == true then table.insert(equation, #equation, ")") calc.sinh = false end elseif events[4] >= 10 and events[4] <= 12 then if calc.inverse == true and calc.acos == false then table.insert(equation, #equation, "math.acos(") calc.acos = true elseif calc.inverse == false and calc.hyp == false and calc.cos == false then table.insert(equation, #equation, "math.cos(") calc.cos = true elseif calc.hyp == true and calc.cosh == false then table.insert(equation, #equation, "math.cosh(") calc.cosh = true elseif calc.acos == true then table.insert(equation, #equation, ")") calc.acos = false elseif calc.cos == true then table.insert(equation, #equation, ")") calc.cos = false elseif calc.cosh == true then table.insert(equation, #equation, ")") calc.cosh = false end elseif events[4] >= 13 and events[4] <= 15 then if calc.inverse == true and calc.atan == false then table.insert(equation, #equation, "math.atan(") calc.atan = true elseif calc.inverse == false and calc.hyp == false and calc.tan == false then table.insert(equation, #equation, "math.tan(") calc.tan = true elseif calc.hyp == true and calc.tanh == false then table.insert(equation, #equation, "math.tanh(") calc.tanh = true elseif calc.atan == true then table.insert(equation, #equation, ")") calc.atan = false elseif calc.tan == true then table.insert(equation, #equation, ")") calc.tan = false elseif calc.tanh == true then table.insert(equation, #equation, ")") calc.tanh = false end elseif events[4] >= 16 and events[4] <= 18 then if calc.log == false then table.insert(equation, #equation, "math.log10(") calc.log = true elseif calc.log == true then table.insert(equation, ")") calc.log = false end end -- backspace, clear, equals elseif events[3] >= 24 and events[3] <= 28 then if events[4] >= 7 and events[4] <= 9 then if table.concat(equation) ~= "()" then table.remove(equation, #equation - 1) end elseif events[4] >= 10 and events[4] <= 12 then calc.mode = false calc.inverse = false calc.hyp = false calc.sqrt = false calc.exp = false calc.asin = false calc.sin = false calc.sinh = false calc.atan = false calc.tan = false calc.tanh = false calc.acos = false calc.cos = false calc.cosh = false calc.log = false calc.pos = false equation = { "(", ")" } result = "0" elseif events[4] >= 16 and events[4] <= 18 then if equation[#equation - 1] == "+" or equation[#equation - 1] == "-" or equation[#equation - 1] == "*" or equation[#equation - 1] == "/" then table.insert(equation, #equation, "0") elseif equation[#equation - 1] == "^" then table.insert(equation, #equation, "1") end for i, v in pairs(calc) do if calc[i] == true then table.insert(equation, #equation, ")") calc[i] = false end end result = tostring(calculate(equation)) end -- 3, 6, 9, decimal elseif events[3] >= 19 and events[3] <= 23 then if events[4] >= 7 and events[4] <= 9 then table.insert(equation, #equation, "3") elseif events[4] >= 10 and events[4] <= 12 then table.insert(equation, #equation, "6") elseif events[4] >= 13 and events[4] <= 15 then table.insert(equation, #equation, "9") elseif events[4] >= 16 and events[4] <= 18 then table.insert(equation, #equation, ".") end -- 2, 5, 8, positive/negative elseif events[3] >= 14 and events[3] <= 18 then if events[4] >= 7 and events[4] <= 9 then table.insert(equation, #equation, "2") elseif events[4] >= 10 and events[4] <= 12 then table.insert(equation, #equation, "5") elseif events[4] >= 13 and events[4] <= 15 then table.insert(equation, #equation, "8") elseif events[4] >= 16 and events[4] <= 18 then if calc.pos == false then table.insert(equation, #equation, "(-") calc.pos = true elseif calc.pos == true then table.insert(equation, #equation, ")") calc.pos = false end end -- 1, 4, 7, 0 elseif events[3] >= 9 and events[3] <= 13 then if events[4] >= 7 and events[4] <= 9 then table.insert(equation, #equation, "1") elseif events[4] >= 10 and events[4] <= 12 then table.insert(equation, #equation, "4") elseif events[4] >= 13 and events[4] <= 15 then table.insert(equation, #equation, "7") elseif events[4] >= 16 and events[4] <= 18 then table.insert(equation, #equation, "0") end -- add, subtract, multiply, divide elseif events[3] >= 4 and events[3] <= 8 then if events[4] >= 7 and events[4] <= 9 then table.insert(equation, #equation, "+") elseif events[4] >= 10 and events[4] <= 12 then table.insert(equation, #equation, "-") elseif events[4] >= 13 and events[4] <= 15 then table.insert(equation, #equation, "*") elseif events[4] >= 16 and events[4] <= 18 then table.insert(equation, #equation, "/") end end -- filter for keyboard presses elseif events[1] == "key" then if events[2] == 79 then table.insert(equation, #equation, "1") elseif events[2] == 80 then table.insert(equation, #equation, "2") elseif events[2] == 81 then table.insert(equation, #equation, "3") elseif events[2] == 75 then table.insert(equation, #equation, "4") elseif events[2] == 76 then table.insert(equation, #equation, "5") elseif events[2] == 77 then table.insert(equation, #equation, "6") elseif events[2] == 71 then table.insert(equation, #equation, "7") elseif events[2] == 72 then table.insert(equation, #equation, "8") elseif events[2] == 73 then table.insert(equation, #equation, "9") elseif events[2] == 82 then table.insert(equation, #equation, "0") elseif events[2] == 83 then table.insert(equation, #equation, ".") elseif events[2] == 78 then table.insert(equation, #equation, "+") elseif events[2] == 74 then table.insert(equation, #equation, "-") elseif events[2] == 55 then table.insert(equation, #equation, "*") elseif events[2] == 181 then table.insert(equation, #equation, "/") elseif events[2] == 14 then if table.concat(equation) ~= "()" then table.remove(equation, #equation - 1) end elseif events[2] == 28 or events[2] == 156 then if equation[#equation - 1] == "+" or equation[#equation - 1] == "-" or equation[#equation - 1] == "*" or equation[#equation - 1] == "/" then table.insert(equation, #equation, "0") elseif equation[#equation - 1] == "^" then table.insert(equation, #equation, "1") end for i, v in pairs(calc) do if calc[i] == true then table.insert(equation, #equation, ")") calc[i] = false end end result = tostring(calculate(equation)) end end end