719 lines
22 KiB
JavaScript
719 lines
22 KiB
JavaScript
/**
|
|
* BangleJS Calculator
|
|
*
|
|
* Original Author: Frederic Rousseau https://github.com/fredericrous
|
|
* Created: April 2020
|
|
*
|
|
* Contributors: thyttan https://github.com/thyttan
|
|
*/
|
|
|
|
g.clear();
|
|
require("FontDylex7x13").add(Graphics);
|
|
|
|
var DEFAULT_SELECTION_NUMBERS = '5';
|
|
var RESULT_HEIGHT = 40;
|
|
var COLORS = {
|
|
// [normal, selected]
|
|
DEFAULT: ['#7F8183', '#A6A6A7'],
|
|
OPERATOR: ['#F99D1C', '#CA7F2A'],
|
|
SPECIAL: ['#65686C', '#7F8183']
|
|
};
|
|
|
|
var KEY_AREA = [0, RESULT_HEIGHT, g.getWidth(), g.getHeight()];
|
|
|
|
var screen, screenColor;
|
|
var globalGrid = [4, 5];
|
|
var swipeEnabled;
|
|
|
|
var numbersGrid = [3, 4];
|
|
var numbers = {
|
|
'0': {grid: [1, 3], globalGrid: [1, 4], trbl: '2.0B'},
|
|
'.': {grid: [2, 3], globalGrid: [2, 4], trbl: '3=.0'},
|
|
'1': {grid: [0, 2], globalGrid: [0, 3], trbl: '42B1'},
|
|
'2': {grid: [1, 2], globalGrid: [1, 3], trbl: '5301'},
|
|
'3': {grid: [2, 2], globalGrid: [2, 3], trbl: '6+.2'},
|
|
'4': {grid: [0, 1], globalGrid: [0, 2], trbl: '7514'},
|
|
'5': {grid: [1, 1], globalGrid: [1, 2], trbl: '8624'},
|
|
'6': {grid: [2, 1], globalGrid: [2, 2], trbl: '9-35'},
|
|
'7': {grid: [0, 0], globalGrid: [0, 1], trbl: 'R847'},
|
|
'8': {grid: [1, 0], globalGrid: [1, 1], trbl: 'N957'},
|
|
'9': {grid: [2, 0], globalGrid: [2, 1], trbl: '%*68'},
|
|
'B': {grid: [0, 3], globalGrid: [0, 4], trbl: '10BB', val: '<-', color: COLORS.SPECIAL},
|
|
};
|
|
|
|
var operatorsGrid = [2, 3];
|
|
var operators = {
|
|
'+': {grid: [0, 0], globalGrid: [3, 3], trbl: '-+=3'},
|
|
'-': {grid: [1, 0], globalGrid: [3, 2], trbl: '*-+6'},
|
|
'*': {grid: [0, 1], globalGrid: [3, 1], trbl: '/*-9'},
|
|
'/': {grid: [1, 1], globalGrid: [3, 0], trbl: '//*%'},
|
|
'=': {grid: [1, 2], globalGrid: [3, 4], trbl: '+==.'},
|
|
};
|
|
|
|
if (process.env.HWVERSION!=1) {
|
|
operatorsGrid = [2, 4];
|
|
operators['='].grid = [1, 3];
|
|
operators.r = {grid: [0, 2], val: 'sqrt'};
|
|
operators.s = {grid: [1, 2], val: 'x^2'};
|
|
operators.i = {grid: [0, 3], val: '1/x'};
|
|
}
|
|
|
|
var scientificOperatorsGrid = [2, 4];
|
|
var scientificOperators = {
|
|
'sin': {grid: [0, 0], val: 'sin'},
|
|
'cos': {grid: [1, 0], val: 'cos'},
|
|
'tan': {grid: [0, 1], val: 'tan'},
|
|
'angleMode': {grid: [1, 1], val: 'deg'},
|
|
'log': {grid: [0, 2], val: 'log'},
|
|
'tenpow': {grid: [1, 2], val: '10^x'},
|
|
'ln': {grid: [0, 3], val: 'ln'},
|
|
'epow': {grid: [1, 3], val: 'e^x'},
|
|
};
|
|
|
|
var specialsGrid = [2, 2];
|
|
var specials = {
|
|
'R': {grid: [0, 0], globalGrid: [0, 0], trbl: 'RN7R', val: 'AC'},
|
|
'N': {grid: [1, 0], globalGrid: [1, 0], trbl: 'N%8R', val: '+/-'},
|
|
'%': {grid: [0, 1], globalGrid: [2, 0], trbl: '%/9N'},
|
|
'send': {grid: [1, 1], val: 'send'},
|
|
};
|
|
|
|
var selected = DEFAULT_SELECTION_NUMBERS;
|
|
var prevSelected = DEFAULT_SELECTION_NUMBERS;
|
|
var prevNumber = null;
|
|
var currNumber = null;
|
|
var operator = null;
|
|
var results = null;
|
|
var isDecimal = false;
|
|
var hasPressedEquals = false;
|
|
var angleMode = 'deg';
|
|
var prevExpression = null;
|
|
var currExpression = "";
|
|
|
|
function prepareScreen(screen, grid, defaultColor) {
|
|
for (var k in screen) {
|
|
if (screen.hasOwnProperty(k)) {
|
|
screen[k].color = screen[k].color || defaultColor;
|
|
var position = [];
|
|
var xGrid = (KEY_AREA[2]-KEY_AREA[0])/grid[0];
|
|
var yGrid = (KEY_AREA[3]-KEY_AREA[1])/grid[1];
|
|
if (swipeEnabled) {
|
|
position[0] = KEY_AREA[0]+xGrid*screen[k].grid[0];
|
|
position[1] = KEY_AREA[1]+yGrid*screen[k].grid[1];
|
|
} else {
|
|
position[0] = KEY_AREA[0]+xGrid*screen[k].globalGrid[0];
|
|
position[1] = KEY_AREA[1]+yGrid*screen[k].globalGrid[1];
|
|
}
|
|
position[2] = position[0]+xGrid-1;
|
|
position[3] = position[1]+yGrid-1;
|
|
screen[k].xy = position;
|
|
}
|
|
}
|
|
}
|
|
|
|
function drawKey(name, k, selected) {
|
|
var color = k.color || COLORS.DEFAULT;
|
|
g.setColor(color[selected ? 1 : 0]);
|
|
g.setFont('Dylex7x13', 2).setFontAlign(0,0);
|
|
g.fillRect(k.xy[0], k.xy[1], k.xy[2], k.xy[3]);
|
|
g.setColor(0);
|
|
g.drawString(k.val || name, (k.xy[0] + k.xy[2])/2, (k.xy[1] + k.xy[3])/2);
|
|
}
|
|
|
|
function drawKeys() {
|
|
g.setColor(screenColor[0]);
|
|
g.fillRect(KEY_AREA[0], KEY_AREA[1], KEY_AREA[2], KEY_AREA[3]);
|
|
for (var k in screen) {
|
|
if (screen.hasOwnProperty(k)) {
|
|
drawKey(k, screen[k], k == selected);
|
|
}
|
|
}
|
|
}
|
|
function drawGlobal() {
|
|
screen = {};
|
|
screenColor = COLORS.DEFAULT;
|
|
prepareScreen(numbers, globalGrid, COLORS.DEFAULT);
|
|
for (var k in numbers) {
|
|
screen[k] = numbers[k];
|
|
}
|
|
prepareScreen(operators, globalGrid, COLORS.OPERATOR);
|
|
for (var k in operators) {
|
|
screen[k] = operators[k];
|
|
}
|
|
prepareScreen(specials, globalGrid, COLORS.SPECIAL);
|
|
for (var k in specials) {
|
|
screen[k] = specials[k];
|
|
}
|
|
drawKeys();
|
|
}
|
|
function drawNumbers() {
|
|
screen = numbers;
|
|
screenColor = COLORS.DEFAULT;
|
|
drawKeys();
|
|
}
|
|
function drawOperators() {
|
|
screen = operators;
|
|
screenColor =COLORS.OPERATOR;
|
|
drawKeys();
|
|
}
|
|
function drawScientificOperators() {
|
|
screen = scientificOperators;
|
|
screenColor =COLORS.OPERATOR;
|
|
drawKeys();
|
|
}
|
|
function drawSpecials() {
|
|
screen = specials;
|
|
screenColor = COLORS.SPECIAL;
|
|
drawKeys();
|
|
}
|
|
|
|
|
|
function toExponential(num, precision) {
|
|
if (num === 0) {
|
|
let z = "0";
|
|
if (precision > 0) z += "." + "0".repeat(precision);
|
|
return z + "e+0";
|
|
}
|
|
var sign = "";
|
|
if (num < 0) {
|
|
sign = "-";
|
|
num = -num;
|
|
}
|
|
var exp = Math.floor(Math.log(num) / Math.LN10);
|
|
var mantissa = num / Math.pow(10, exp);
|
|
|
|
var mantissaFixed = mantissa.toFixed(precision);
|
|
if (parseFloat(mantissaFixed) >= 10) {
|
|
mantissaFixed = (mantissa/10).toFixed(precision);
|
|
exp++;
|
|
}
|
|
|
|
return sign + mantissaFixed + "e" + (exp >= 0 ? "+" : "") + exp;
|
|
}
|
|
|
|
function fixFloat(n) {
|
|
if (Math.abs(n) < 1e-10) return 0;
|
|
return n;
|
|
}
|
|
|
|
function addSeparators(s) {
|
|
var parts = s.split(".");
|
|
var intPart = parts[0];
|
|
var sign = "";
|
|
if (intPart[0] === "-") {
|
|
sign = "-";
|
|
intPart = intPart.slice(1);
|
|
}
|
|
var result = "";
|
|
while (intPart.length > 3) {
|
|
result = "," + intPart.slice(-3) + result;
|
|
intPart = intPart.slice(0, -3);
|
|
}
|
|
result = intPart + result;
|
|
parts[0] = sign + result;
|
|
return parts.join(".");
|
|
}
|
|
|
|
function doMath(x, y, operator) {
|
|
x = parseFloat(x);
|
|
y = parseFloat(y);
|
|
switch (operator) {
|
|
case '/':
|
|
return x / y;
|
|
case '*':
|
|
return x * y;
|
|
case '+':
|
|
return x + y;
|
|
case '-':
|
|
return x - y;
|
|
}
|
|
}
|
|
|
|
function displayOutput(num) {
|
|
g.setBgColor(0).clearRect(0, 0, g.getWidth(), RESULT_HEIGHT-1);
|
|
g.setColor(-1);
|
|
g.setFont('Dylex7x13', 2);
|
|
if (num === Infinity || num === -Infinity || isNaN(num)) {
|
|
// handle division by 0
|
|
if (num === Infinity) {
|
|
num = 'INF';
|
|
} else if (num === -Infinity) {
|
|
num = '-INF';
|
|
} else {
|
|
num = 'NaN';
|
|
}
|
|
currNumber = null;
|
|
results = null;
|
|
isDecimal = false;
|
|
hasPressedEquals = false;
|
|
prevNumber = null;
|
|
operator = null;
|
|
specials.R.val = 'AC';
|
|
if (!swipeEnabled) drawKey('R', specials.R);
|
|
} else {
|
|
// might not be a number due to display of dot "."
|
|
var numNumeric = Number(num);
|
|
|
|
if (typeof num === 'string') {
|
|
if (num.indexOf('.') !== -1) {
|
|
// display a 0 before a lonely dot
|
|
if (numNumeric == 0) {
|
|
num = '0.';
|
|
}
|
|
} else {
|
|
// remove preceding 0
|
|
while (num.length > 1 && num[0] === '0')
|
|
num = num.substr(1);
|
|
}
|
|
}
|
|
var numStr = num.toString();
|
|
var displayStr;
|
|
|
|
if (typeof num === 'number' && (numStr.indexOf('e') > -1 || (num !== 0 && Math.abs(num) < 1e-6))) {
|
|
// try to format as scientific notation
|
|
let precision = 10; // start with high precision
|
|
while (precision >= 0) {
|
|
let scientificStr = toExponential(num, precision).replace("e", "E");
|
|
if (g.stringWidth(scientificStr) <= g.getWidth() - 20) {
|
|
displayStr = scientificStr;
|
|
break;
|
|
}
|
|
precision--;
|
|
}
|
|
if (precision < 0) { // if it still doesn't fit
|
|
displayStr = toExponential(num, 0).replace("e", "E");
|
|
}
|
|
} else {
|
|
displayStr = addSeparators(numStr);
|
|
}
|
|
num = displayStr;
|
|
|
|
// final check for truncation
|
|
if (g.stringWidth(num) > g.getWidth() - 20) {
|
|
while(g.stringWidth(num+'...') > g.getWidth() - 20 && num.length > 1) {
|
|
num = num.slice(0,-1);
|
|
}
|
|
num += '...';
|
|
}
|
|
}
|
|
g.setFontAlign(1,0);
|
|
g.drawString(num, g.getWidth()-20, RESULT_HEIGHT/2);
|
|
if (operator) {
|
|
g.setFont('Dylex7x13', 2).setFontAlign(1,0);
|
|
g.drawString(operator, g.getWidth()-1, RESULT_HEIGHT/2);
|
|
}
|
|
}
|
|
var wasPressedEquals = false;
|
|
var hasPressedNumber = false;
|
|
function calculatorLogic(x) {
|
|
if (wasPressedEquals && hasPressedNumber !== false) {
|
|
prevNumber = null;
|
|
currNumber = hasPressedNumber;
|
|
wasPressedEquals = false;
|
|
hasPressedNumber = false;
|
|
return;
|
|
}
|
|
if (hasPressedEquals) {
|
|
if (hasPressedNumber) {
|
|
prevNumber = null;
|
|
hasPressedNumber = false;
|
|
operator = null;
|
|
} else {
|
|
currNumber = null;
|
|
prevNumber = results;
|
|
}
|
|
hasPressedEquals = false;
|
|
wasPressedEquals = true;
|
|
}
|
|
|
|
if (currNumber == null && operator != null && '/*-+'.indexOf(x) !== -1) {
|
|
operator = x;
|
|
displayOutput(prevNumber);
|
|
} else if (prevNumber != null && currNumber != null && operator != null) {
|
|
// we execute the calculus only when there was a previous number entered before and an operator
|
|
let oldOperator = operator;
|
|
results = doMath(prevNumber, currNumber, operator);
|
|
operator = x;
|
|
prevNumber = results;
|
|
prevExpression = "(" + prevExpression + " " + oldOperator + " " + currExpression + ")";
|
|
currNumber = null;
|
|
currExpression = "";
|
|
displayOutput(results);
|
|
} else if (prevNumber == null && currNumber != null && operator == null) {
|
|
// no operator yet, save the current number for later use when an operator is pressed
|
|
operator = x;
|
|
prevNumber = currNumber;
|
|
prevExpression = currExpression;
|
|
currNumber = null;
|
|
currExpression = "";
|
|
displayOutput(prevNumber);
|
|
} else if (prevNumber == null && currNumber == null && operator == null) {
|
|
displayOutput(0);
|
|
}
|
|
}
|
|
|
|
function buttonPress(val) {
|
|
switch (val) {
|
|
case 'R':
|
|
currNumber = null;
|
|
results = null;
|
|
isDecimal = false;
|
|
hasPressedEquals = false;
|
|
if (specials.R.val == 'AC') {
|
|
prevNumber = null;
|
|
operator = null;
|
|
prevExpression = null;
|
|
currExpression = "";
|
|
} else {
|
|
specials.R.val = 'AC';
|
|
drawKey('R', specials.R, true);
|
|
}
|
|
wasPressedEquals = false;
|
|
hasPressedNumber = false;
|
|
displayOutput(0);
|
|
break;
|
|
case '%':
|
|
if (results != null) {
|
|
displayOutput(results /= 100);
|
|
prevExpression = "(" + prevExpression + ")/100";
|
|
} else if (currNumber != null) {
|
|
displayOutput(currNumber /= 100);
|
|
currExpression = "(" + currExpression + ")/100";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'r':
|
|
if (results != null) {
|
|
results = Math.sqrt(results);
|
|
displayOutput(results);
|
|
prevExpression = "sqrt(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
currNumber = Math.sqrt(currNumber);
|
|
displayOutput(currNumber);
|
|
currExpression = "sqrt(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 's':
|
|
if (results != null) {
|
|
results = results * results;
|
|
displayOutput(results);
|
|
prevExpression = "(" + prevExpression + ")^2";
|
|
} else if (currNumber != null) {
|
|
var num = parseFloat(currNumber);
|
|
currNumber = num * num;
|
|
displayOutput(currNumber);
|
|
currExpression = "(" + currExpression + ")^2";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'sin':
|
|
if (results != null) {
|
|
let angle = results;
|
|
if (angleMode === 'deg') {
|
|
angle = angle * Math.PI / 180;
|
|
}
|
|
results = fixFloat(Math.sin(angle));
|
|
displayOutput(results);
|
|
prevExpression = "sin(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
let angle = currNumber;
|
|
if (angleMode === 'deg') {
|
|
angle = angle * Math.PI / 180;
|
|
}
|
|
currNumber = fixFloat(Math.sin(angle));
|
|
displayOutput(currNumber);
|
|
currExpression = "sin(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'cos':
|
|
if (results != null) {
|
|
let angle = results;
|
|
if (angleMode === 'deg') {
|
|
angle = angle * Math.PI / 180;
|
|
}
|
|
results = fixFloat(Math.cos(angle));
|
|
displayOutput(results);
|
|
prevExpression = "cos(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
let angle = currNumber;
|
|
if (angleMode === 'deg') {
|
|
angle = angle * Math.PI / 180;
|
|
}
|
|
currNumber = fixFloat(Math.cos(angle));
|
|
displayOutput(currNumber);
|
|
currExpression = "cos(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'tan':
|
|
if (results != null) {
|
|
let angle = results;
|
|
if (angleMode === 'deg') {
|
|
angle = angle * Math.PI / 180;
|
|
}
|
|
results = fixFloat(Math.tan(angle));
|
|
displayOutput(results);
|
|
prevExpression = "tan(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
let angle = currNumber;
|
|
if (angleMode === 'deg') {
|
|
angle = angle * Math.PI / 180;
|
|
}
|
|
currNumber = fixFloat(Math.tan(angle));
|
|
displayOutput(currNumber);
|
|
currExpression = "tan(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'log':
|
|
if (results != null) {
|
|
results = Math.log(results) / Math.LN10;
|
|
displayOutput(results);
|
|
prevExpression = "log(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
currNumber = Math.log(currNumber) / Math.LN10;
|
|
displayOutput(currNumber);
|
|
currExpression = "log(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'tenpow':
|
|
if (results != null) {
|
|
results = Math.pow(10, results);
|
|
displayOutput(results);
|
|
prevExpression = "10^(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
currNumber = Math.pow(10, currNumber);
|
|
displayOutput(currNumber);
|
|
currExpression = "10^(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'ln':
|
|
if (results != null) {
|
|
results = Math.log(results);
|
|
displayOutput(results);
|
|
prevExpression = "ln(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
currNumber = Math.log(currNumber);
|
|
displayOutput(currNumber);
|
|
currExpression = "ln(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'epow':
|
|
if (results != null) {
|
|
results = Math.exp(results);
|
|
displayOutput(results);
|
|
prevExpression = "e^(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
currNumber = Math.exp(currNumber);
|
|
displayOutput(currNumber);
|
|
currExpression = "e^(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'angleMode':
|
|
if (angleMode === 'rad') {
|
|
angleMode = 'deg';
|
|
} else {
|
|
angleMode = 'rad';
|
|
}
|
|
scientificOperators.angleMode.val = angleMode;
|
|
drawKey('angleMode', scientificOperators.angleMode);
|
|
break;
|
|
case 'i':
|
|
if (results != null) {
|
|
results = 1 / results;
|
|
displayOutput(results);
|
|
prevExpression = "1/(" + prevExpression + ")";
|
|
} else if (currNumber != null) {
|
|
currNumber = 1 / parseFloat(currNumber);
|
|
displayOutput(currNumber);
|
|
currExpression = "1/(" + currExpression + ")";
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'N':
|
|
if (results != null) {
|
|
displayOutput(results *= -1);
|
|
prevExpression = "-(" + prevExpression + ")";
|
|
} else {
|
|
displayOutput(currNumber *= -1);
|
|
currExpression = "-(" + currExpression + ")";
|
|
}
|
|
break;
|
|
case 'B':
|
|
if (isDecimal) {
|
|
isDecimal = false;
|
|
displayOutput(currNumber);
|
|
break;
|
|
}
|
|
if (currNumber != null) {
|
|
currNumber = currNumber.toString();
|
|
if (currNumber.length > 1) {
|
|
currNumber = currNumber.slice(0, -1);
|
|
} else {
|
|
currNumber = '0';
|
|
}
|
|
// if we removed a decimal point
|
|
if (currNumber.indexOf('.') === -1) {
|
|
isDecimal = false;
|
|
}
|
|
hasPressedNumber = currNumber;
|
|
currExpression = currNumber;
|
|
displayOutput(currNumber);
|
|
}
|
|
break;
|
|
case '/':
|
|
case '*':
|
|
case '-':
|
|
case '+':
|
|
calculatorLogic(val);
|
|
hasPressedNumber = false;
|
|
if (swipeEnabled) drawNumbers();
|
|
break;
|
|
case '.':
|
|
specials.R.val = 'C';
|
|
if (!swipeEnabled) drawKey('R', specials.R);
|
|
isDecimal = true;
|
|
displayOutput(currNumber == null ? 0 + '.' : currNumber + '.');
|
|
break;
|
|
case '=':
|
|
if (prevNumber != null && currNumber != null && operator != null) {
|
|
let cExpr = currExpression;
|
|
if (hasPressedEquals && cExpr === "") {
|
|
cExpr = currNumber.toString();
|
|
}
|
|
prevExpression = prevExpression + " " + operator + " " + cExpr;
|
|
results = doMath(prevNumber, currNumber, operator);
|
|
prevNumber = results;
|
|
currExpression = "";
|
|
displayOutput(results);
|
|
hasPressedEquals = 1;
|
|
}
|
|
hasPressedNumber = false;
|
|
break;
|
|
case 'send':
|
|
let logStr;
|
|
if (hasPressedEquals) {
|
|
logStr = prevExpression + " = " + results;
|
|
} else if (operator && prevExpression) { // Incomplete binary operation, e.g. "5 +" or "5 + 3"
|
|
logStr = prevExpression + " " + operator;
|
|
if (currExpression) {
|
|
logStr += " " + currExpression;
|
|
}
|
|
} else if (results) { // Result of a unary op on a previous result
|
|
logStr = prevExpression + " = " + results;
|
|
} else if (currNumber) { // A number has been entered, or a unary op on it
|
|
if (currExpression && currExpression !== currNumber.toString()) {
|
|
logStr = currExpression + " = " + currNumber;
|
|
} else {
|
|
logStr = currNumber.toString();
|
|
}
|
|
} else {
|
|
logStr = results ? results.toString() : "0";
|
|
}
|
|
console.log(logStr);
|
|
if (Bangle.http){
|
|
const options = {timeout:3000, method: "post", body: logStr};
|
|
Bangle.http("https://tbot.tannercollin.com/banglecalc", options).then(event => {
|
|
Bangle.buzz();
|
|
console.log("Successfully sent");
|
|
}).catch((e)=>{
|
|
g.setBgColor(0).clearRect(0, 0, g.getWidth(), RESULT_HEIGHT-1);
|
|
g.setColor(-1);
|
|
g.setFont('Dylex7x13', 2);
|
|
g.setFontAlign(1,0);
|
|
g.drawString('ERROR', g.getWidth()-20, RESULT_HEIGHT/2);
|
|
if (operator) {
|
|
g.setFont('Dylex7x13', 2).setFontAlign(1,0);
|
|
g.drawString(operator, g.getWidth()-1, RESULT_HEIGHT/2);
|
|
}
|
|
});
|
|
}
|
|
break;
|
|
default: {
|
|
specials.R.val = 'C';
|
|
if (!swipeEnabled) drawKey('R', specials.R);
|
|
const is0Negative = (currNumber === 0 && 1/currNumber === -Infinity);
|
|
if (isDecimal) {
|
|
currNumber = currNumber == null || hasPressedEquals === 1 ? '0.' + val : parseInt(currNumber, 10) + '.' + val;
|
|
isDecimal = false;
|
|
} else {
|
|
currNumber = currNumber == null || hasPressedEquals === 1 ? val : (is0Negative ? '-' + val : currNumber + val);
|
|
}
|
|
if (hasPressedEquals === 1) {
|
|
hasPressedEquals = 2;
|
|
}
|
|
hasPressedNumber = currNumber;
|
|
currExpression = currNumber;
|
|
displayOutput(currNumber);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function moveDirection(d) {
|
|
drawKey(selected, screen[selected]);
|
|
prevSelected = selected;
|
|
selected = (d === 0 && selected == '0' && prevSelected === '1') ? '1' : screen[selected].trbl[d];
|
|
drawKey(selected, screen[selected], true);
|
|
}
|
|
|
|
if (process.env.HWVERSION==1) {
|
|
setWatch(_ => moveDirection(0), BTN1, {repeat: true, debounce: 100});
|
|
setWatch(_ => moveDirection(2), BTN3, {repeat: true, debounce: 100});
|
|
setWatch(_ => moveDirection(3), BTN4, {repeat: true, debounce: 100});
|
|
setWatch(_ => moveDirection(1), BTN5, {repeat: true, debounce: 100});
|
|
setWatch(_ => buttonPress(selected), BTN2, {repeat: true, debounce: 100});
|
|
swipeEnabled = false;
|
|
drawGlobal();
|
|
} else { // touchscreen?
|
|
selected = "NONE";
|
|
swipeEnabled = true;
|
|
prepareScreen(numbers, numbersGrid, COLORS.DEFAULT);
|
|
prepareScreen(operators, operatorsGrid, COLORS.OPERATOR);
|
|
prepareScreen(scientificOperators, scientificOperatorsGrid, COLORS.OPERATOR);
|
|
prepareScreen(specials, specialsGrid, COLORS.SPECIAL);
|
|
drawNumbers();
|
|
|
|
Bangle.setUI({
|
|
mode : 'custom',
|
|
back : load, // Clicking physical button or pressing upper left corner turns off (where red back button would be)
|
|
touch : (n,e)=>{
|
|
for (var key in screen) {
|
|
if (typeof screen[key] == "undefined") break;
|
|
var r = screen[key].xy;
|
|
if (e.x>=r[0] && e.y>=r[1] && e.x<r[2] && e.y<r[3]) {
|
|
//print("Press "+key);
|
|
buttonPress(""+key);
|
|
}
|
|
}
|
|
},
|
|
swipe : (LR, UD) => {
|
|
if (UD !== 0) {
|
|
drawNumbers();
|
|
return;
|
|
}
|
|
if (LR === 1) { // right
|
|
if (screen === scientificOperators) drawOperators();
|
|
else if (screen === operators) drawNumbers();
|
|
else if (screen === numbers) drawSpecials();
|
|
else if (screen === specials) drawNumbers();
|
|
}
|
|
if (LR === -1) { // left
|
|
if (screen === numbers) drawOperators();
|
|
else if (screen === operators) drawScientificOperators();
|
|
else if (screen === specials) drawNumbers();
|
|
else if (screen === scientificOperators) drawNumbers();
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
displayOutput(0);
|