commit
11c8f63ae4
|
|
@ -0,0 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: New Results menu item to show the formula and values used.
|
||||
0.03: Adds haptics to Input screen and long press "C" to go back.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# Ohm's Law Calculator
|
||||
|
||||
This is a simple and intuitive Ohm's Law Calculator application designed for the Bangle.js 2 Smartwatch. The calculator focuses on providing an easy-to-navigate user interface with automatic calculation logic, allowing you to quickly and efficiently calculate electrical measurements, including Voltage, Current, Resistance, and Power.
|
||||
|
||||
## Usage Guide
|
||||
|
||||
* __Select the Electrical Measurement:__ On the main menu, select the electrical measurement that you wish to calculate (Voltage, Current, Resistance, or Power).
|
||||
* __Enter Known Values:__ You will then be prompted to enter the known values. The application will present a menu listing the remaining electrical measurements. Select one and you will be taken to a numeric input screen. Repeat this step for the second known value.
|
||||
* __View Results:__ Once the two known values have been entered, the application will automatically calculate and display the value of the selected electrical measurement. The Results menu will show the calculated value, the unit of measurement, and the formula used for calculation.
|
||||
* __Navigation:__ Whether you're deep in calculations or perusing the results, the power to navigate the app remains in your hands. While the 'Back' button is present in most scenarios, it isn't available in the Results menu and the Input screen. However, you can always return to the beginning by selecting 'Main Menu' from the Results menu. And if you're on the numeric Input screen, simply hold down the 'Clear' button to navigate back.
|
||||
|
||||
## Compatibility
|
||||
|
||||
This app was built and tested with Bangle.js 2.
|
||||
|
||||
## Feedback
|
||||
|
||||
If you have any issues or suggestions, please open an issue on this GitHub repository. Contributions to improve the application are also welcomed.
|
||||
|
||||
## Creator
|
||||
|
||||
[stweedo](https://github.com/stweedo)
|
||||
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwxH+AH4AyQBIvmnM/AAk5F8pWBFwoABMDweGgEHF48HCAw2VE4MGDAgvCRIIACSoIvFgEGG4wuPKAYZCgENn8UgFVqsAik/hoNDC4ouUAAMOLAYoBF4Ok0gGEFwUOTJQuPAAM4DIIJCFAI2GRYM4ZRguNg7pIh0NhpXDAwIVIGBguFdwJlHABbTCgwwPCIgQB1V6dYSXGQ4zzCvWqIwhNBMBwvBvVPbokUKQQADg7BBSQUAp5FBDojANFAQmCAoTxCgEsmc0mkzlgxCMoQwBFwYFBFxgvBgAaCcYcUgEBmdfAA0zCoJiCegc4BIIvNeQwuCg4qEg8rAwowDdhwvLI4IuFLIIHFGAT4EF5rdEJAkHgImHF41fI4p2BAAYtIg8HhpGECwK7FXAQvHBQJIEikNEYIxGgE5UQh2FLw0rlYvHMAwAEnIvDGgIJDigABAwUAlhTGwAvBmgABnQMDlgfDDwRVDMAYvETocOAwSOFLwPVp6wEGAY8BC4MOBgYvMqukgENXwU0Lw3V5+kAALDFBoLaBhsA0lVF6U4F4rFBFgXP6uANoovVR5U6RQlP6ryGR6jvMnTqCYQJeGd6AwBBIYAFRIIiEeQheGr7FBDxE5FwZgCCQMHhqkBIwZTGYYYKGRwJ4DDIMNEYIoCF4YxEAAIWEMBAIBLxhIBAAYtFGYwXEnAmHF4JeFA4J4EAwIrLF5JICGAq9GE4J2EF6JsBI4UNhx5EYY67CFwcOhp3DGB0AFQTQCAoU4AwUsmYAClgHBg5EChwGCAoaNQE4N6p4wDMQIxCAAcHRYYoBp96DoouLgyjE1QZBPYQAEnDmEAAUNIoOqbYkGGBTsFCIL0GABhsCJoZgOFAkHFxEOAASZDNwYVFFxgwHdogJCii+DXoIGCgyXGFxwwHboIoG0mkAwgWBgBnDFyIwFVYQICQgIoBqtVF4TrBBoQXFFyAwDeAI4GnJmDnImGSYIuUJQbKMKxAXGAC4eBF44oeGBCJBAAiVBF0hgCAA4vlGI4tnADg="))
|
||||
|
|
@ -0,0 +1,373 @@
|
|||
let Layout = require("Layout");
|
||||
|
||||
// Definitions for units and formulas for electrical measurements.
|
||||
const UNITS = {
|
||||
"Voltage (V)": "Volts",
|
||||
"Current (I)": "Amps",
|
||||
"Resistance (R)": "Ohms",
|
||||
"Power (P)": "Watts",
|
||||
};
|
||||
|
||||
const FORMULAS = {
|
||||
'Voltage (V)': {
|
||||
'Current (I), Resistance (R)': { equation: "{0} * {1}", display: "V = I * R" },
|
||||
'Power (P), Current (I)': { equation: "{0} / {1}", display: "V = P / I" },
|
||||
'Power (P), Resistance (R)': { equation: "Math.sqrt({0} * {1})", display: "V = sqrt(P * R)" }
|
||||
},
|
||||
'Current (I)': {
|
||||
'Voltage (V), Resistance (R)': { equation: "{0} / {1}", display: "I = V / R" },
|
||||
'Power (P), Voltage (V)': { equation: "{0} / {1}", display: "I = P / V" },
|
||||
'Power (P), Resistance (R)': { equation: "Math.sqrt({0} / {1})", display: "I = sqrt(P / R)" }
|
||||
},
|
||||
'Resistance (R)': {
|
||||
'Voltage (V), Current (I)': { equation: "{0} / {1}", display: "R = V / I" },
|
||||
'Power (P), Current (I)': { equation: "{0} / (Math.pow({1}, 2))", display: "R = P / I^2" },
|
||||
'Power (P), Voltage (V)': { equation: "(Math.pow({1}, 2)) / {0}", display: "R = V^2 / P" }
|
||||
},
|
||||
'Power (P)': {
|
||||
'Voltage (V), Current (I)': { equation: "{0} * {1}", display: "P = V * I" },
|
||||
'Current (I), Resistance (R)': { equation: "(Math.pow({0}, 2)) * {1}", display: "P = I^2 * R" },
|
||||
'Voltage (V), Resistance (R)': { equation: "(Math.pow({0}, 2)) / {1}", display: "P = V^2 / R" }
|
||||
},
|
||||
};
|
||||
|
||||
// Screen positioning settings
|
||||
let btnSize = 23;
|
||||
let xCenter = g.getWidth() / 2;
|
||||
let yCenter = g.getHeight() / 2;
|
||||
|
||||
// Variables to hold state
|
||||
let lastStringWidth = 0;
|
||||
let halfStringWidth = lastStringWidth / 2;
|
||||
let calculatedVariable;
|
||||
let selectedVariable;
|
||||
let variableValues = {};
|
||||
let inputStr = "";
|
||||
let invalidInput = false;
|
||||
|
||||
// Function references
|
||||
let handleEnter;
|
||||
let showVariableSelectionMenu;
|
||||
let showInputMenu;
|
||||
let resultsMenu;
|
||||
let mainMenu;
|
||||
|
||||
// Setup the layout for input buttons
|
||||
let layout = new Layout({
|
||||
type: "v",
|
||||
c: [
|
||||
{ type: "txt", font: "6x8:3", label: "", id: "label" },
|
||||
{ type: "h", c: "123".split("").map(i => ({ type: "btn", font: "6x8:3", label: i, cb: () => { handleButtonPress(i); }, fillx: 1, filly: 1 })) },
|
||||
{ type: "h", c: "456".split("").map(i => ({ type: "btn", font: "6x8:3", label: i, cb: () => { handleButtonPress(i); }, fillx: 1, filly: 1 })) },
|
||||
{ type: "h", c: "789".split("").map(i => ({ type: "btn", font: "6x8:3", label: i, cb: () => { handleButtonPress(i); }, fillx: 1, filly: 1 })) },
|
||||
{ type: "h", c: ".0C".split("").map(i => ({ type: "btn", font: "6x8:3", label: i, cb: () => { handleButtonPress(i); }, cbl: i === "C" ? () => { showVariableSelectionMenu(); Bangle.buzz(20); } : undefined, fillx: 1, filly: 1 })) },
|
||||
{ type: "h", c: [{ type: "btn", font: "6x8:2", label: "Enter", cb: () => { handleEnter(); }, fillx: 1, filly: 1 }] }
|
||||
]
|
||||
}, { lazy: false });
|
||||
|
||||
// Clears area at the top of the screen where the text is displayed
|
||||
function clearTextArea() { // Except Back Button
|
||||
let x2 = g.getWidth();
|
||||
g.clearRect(0, 0, x2, btnSize);
|
||||
}
|
||||
|
||||
// Function to clear the entire screen, except for the Back button
|
||||
function clearScreen() {
|
||||
let x2 = g.getWidth();
|
||||
let y2 = g.getHeight();
|
||||
g.clearRect(btnSize, 0, x2, btnSize);
|
||||
g.clearRect(0, btnSize, x2, y2);
|
||||
}
|
||||
|
||||
// Function to set up and display the calculator input screen
|
||||
function showCalculatorInputScreen(variable) {
|
||||
selectedVariable = variable;
|
||||
layout.setUI();
|
||||
layout.render();
|
||||
}
|
||||
|
||||
// Function to set and display the current value of the input
|
||||
// Adjusts the font size to fit the screen width
|
||||
function setValue(newStr) {
|
||||
clearTextArea();
|
||||
inputStr = newStr;
|
||||
|
||||
// Here we check the width of the string and adjust the font size
|
||||
// Start with a standard font size and increase if the string is too wide
|
||||
let fontSize = "6x8:3"; // start with a standard size
|
||||
g.setFont(fontSize);
|
||||
|
||||
// If the string is too long to fit on the screen, adjust the font size
|
||||
while (g.stringWidth(inputStr) > g.getWidth() - 10 && fontSize !== "6x8:1") {
|
||||
fontSize = "6x8:" + (Number(fontSize.split(":")[1]) - 1).toString();
|
||||
g.setFont(fontSize);
|
||||
}
|
||||
|
||||
layout.label.label = inputStr;
|
||||
g.drawString(inputStr, layout.label.x, layout.label.y + 11);
|
||||
lastStringWidth = g.stringWidth(inputStr);
|
||||
}
|
||||
|
||||
// Function to handle the press of a button and append its value to the current input
|
||||
function handleButtonPress(value) {
|
||||
Bangle.buzz(20);
|
||||
if (invalidInput) {
|
||||
return; // Don't allow input if an invalid input error message is displayed
|
||||
}
|
||||
inputStr = value === 'C' ? '' : inputStr + value;
|
||||
setValue(inputStr);
|
||||
}
|
||||
|
||||
// Function to format the unit of measurement
|
||||
function formatUnit(unit, value) {
|
||||
return parseFloat(value) === 1 ? unit.slice(0, -1) : unit;
|
||||
}
|
||||
|
||||
// Calculates the value of the selected variable based on the entered values
|
||||
// Also handles rounding and trimming of long decimal numbers
|
||||
function calculateValue(calculatedVariable, variableValues) {
|
||||
let formulas = FORMULAS[calculatedVariable];
|
||||
let formulaKeys = Object.keys(formulas);
|
||||
for (let i = 0; i < formulaKeys.length; i++) {
|
||||
let formulaKey = formulaKeys[i];
|
||||
let variables = formulaKey.split(', ');
|
||||
if (variables.every(variable => variableValues.hasOwnProperty(variable))) {
|
||||
let formulaData = formulas[formulaKey];
|
||||
let formula = formulaData.equation;
|
||||
let formulaDisplay = formulaData.display;
|
||||
let formulaValues = variables.map(variable => variableValues[variable]);
|
||||
let calculatedValue = eval(formula.replace(/\{(\d+)\}/g, (_, index) => formulaValues[index]));
|
||||
|
||||
// Check if the number is an integer
|
||||
let isInteger = Math.floor(calculatedValue) === calculatedValue;
|
||||
|
||||
// Round and trim long decimal numbers
|
||||
if (!isInteger) {
|
||||
calculatedValue = calculatedValue.toFixed(3);
|
||||
calculatedValue = calculatedValue.replace(/\.0+$/, '').replace(/(\.\d*[1-9])0+$/, '$1');
|
||||
}
|
||||
|
||||
let result = Object.entries(variableValues).map(function (entry) {
|
||||
let variable = entry[0];
|
||||
let value = entry[1];
|
||||
return [variable, `${value} ${formatUnit(UNITS[variable], value.toString())}`];
|
||||
});
|
||||
result.push([calculatedVariable, `${calculatedValue} ${formatUnit(UNITS[calculatedVariable], calculatedValue.toString())}`]);
|
||||
return {
|
||||
formula: formulaDisplay.replace(/\{(\d+)\}/g, (_, index) => formulaValues[index]),
|
||||
value: calculatedValue,
|
||||
unit: formatUnit(UNITS[calculatedVariable], calculatedValue),
|
||||
result: result,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main function to initialize the application and setup the main menu
|
||||
(function () {
|
||||
mainMenu = {
|
||||
'': { 'title': 'Ohm\'s Law Calc' },
|
||||
'< Back': () => Bangle.showClock()
|
||||
};
|
||||
|
||||
Object.keys(UNITS).forEach(unit => {
|
||||
mainMenu[unit] = () => handleUnitSelection(unit);
|
||||
});
|
||||
|
||||
// Function to present the menu for selecting the variable
|
||||
// Filters out the calculated variable and already set variables from the menu
|
||||
showVariableSelectionMenu = function () {
|
||||
clearScreen();
|
||||
let variableSelectionMenu = {
|
||||
'': { 'title': 'Select Variable' },
|
||||
'< Back': () => {
|
||||
E.showMenu(mainMenu);
|
||||
variableValues = {};
|
||||
}
|
||||
};
|
||||
let variables = Object.keys(UNITS);
|
||||
let remainingVariables = variables.filter(v => v !== calculatedVariable && !variableValues[v]);
|
||||
remainingVariables.forEach(variable => {
|
||||
variableSelectionMenu[variable] = function () {
|
||||
showInputMenu(variable);
|
||||
};
|
||||
});
|
||||
E.showMenu(variableSelectionMenu);
|
||||
};
|
||||
|
||||
// Function to handle the input of variable values
|
||||
// It sets the current selected variable and displays the calculator input screen
|
||||
showInputMenu = function (variable) {
|
||||
setValue("");
|
||||
selectedVariable = variable;
|
||||
let inputMenu = {
|
||||
'': { 'title': variable },
|
||||
};
|
||||
E.showMenu(inputMenu);
|
||||
showCalculatorInputScreen(variable);
|
||||
};
|
||||
|
||||
// Function to handle the event of pressing 'Enter'
|
||||
// It checks if the input is valid, if so, it saves the value and
|
||||
// either calculates the result (if enough variables are present) or opens variable selection menu
|
||||
handleEnter = function () {
|
||||
// Check if the input is valid
|
||||
if (inputStr === "" || isNaN(inputStr) || (inputStr.match(/\./g) || []).length > 1) {
|
||||
// Show error message
|
||||
setValue("Invalid Input");
|
||||
invalidInput = true; // Prevent further input
|
||||
// Clear error message after 2 seconds
|
||||
setTimeout(() => {
|
||||
setValue('');
|
||||
invalidInput = false; // Allow input again
|
||||
}, 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (calculatedVariable === null) {
|
||||
return;
|
||||
}
|
||||
variableValues[selectedVariable] = parseFloat(inputStr);
|
||||
if (Object.keys(variableValues).length === 2) {
|
||||
let result = calculateValue(calculatedVariable, variableValues);
|
||||
showResultsScreen(result);
|
||||
calculatedVariable = null;
|
||||
variableValues = {};
|
||||
} else {
|
||||
setValue("");
|
||||
showVariableSelectionMenu();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
// Function to handle the selection of a unit of electical measurement
|
||||
function handleUnitSelection(unit) {
|
||||
calculatedVariable = unit;
|
||||
showVariableSelectionMenu();
|
||||
}
|
||||
|
||||
// Function to display the results screen with the calculated value
|
||||
function drawValueScreen
|
||||
(result) {
|
||||
let drawPage = function () {
|
||||
clearScreen();
|
||||
let fontSize = g.getHeight() / 3;
|
||||
g.setFontVector(fontSize);
|
||||
|
||||
// Reduce the font size until both the value and unit fit on the screen
|
||||
while (g.stringWidth(result.value) > g.getWidth() - 10 || g.getFontHeight() > g.getHeight() / 2) {
|
||||
fontSize--;
|
||||
g.setFontVector(fontSize);
|
||||
}
|
||||
|
||||
let valueY = yCenter - g.getFontHeight() / 2;
|
||||
let unitY = yCenter + g.getFontHeight() / 2;
|
||||
let valueWidth = g.stringWidth(result.value);
|
||||
let unitWidth = g.stringWidth(result.unit);
|
||||
let valueX = (g.getWidth() - valueWidth) / 2;
|
||||
let unitX = (g.getWidth() - unitWidth) / 2;
|
||||
|
||||
g.drawString(result.value, valueX, valueY);
|
||||
g.drawString(result.unit, unitX, unitY);
|
||||
g.flip();
|
||||
};
|
||||
|
||||
// Shows the back button on the value screen
|
||||
return function () {
|
||||
clearScreen();
|
||||
let valueMenu = {
|
||||
'': { 'title': 'Results' },
|
||||
'< Back': function () {
|
||||
E.showMenu(resultsMenu);
|
||||
}
|
||||
};
|
||||
E.showMenu(valueMenu);
|
||||
drawPage();
|
||||
};
|
||||
}
|
||||
|
||||
// Function to display the results screen with the values from the result.result array
|
||||
function drawResultScreen(result) {
|
||||
let drawPage = function() {
|
||||
clearScreen();
|
||||
let fontSize = 30; // Initial font size
|
||||
let lineSpacing = 15; // Space between lines
|
||||
|
||||
// Define the vertical positions of the titles
|
||||
let titlePositions = [10, 72, 132];
|
||||
|
||||
for (let i = 0; i < result.result.length; i++) {
|
||||
let currentResult = result.result[i];
|
||||
let resultTitle = currentResult[0];
|
||||
let resultValue = currentResult[1];
|
||||
|
||||
// Draw title
|
||||
g.setFontVector(fontSize / 2); // Small font for title
|
||||
let titleX = (g.getWidth() - g.stringWidth(resultTitle)) / 2;
|
||||
let titleY = titlePositions[i]; // Get the vertical position for the title
|
||||
g.drawString(resultTitle, titleX, titleY); // Draw at the desired position
|
||||
|
||||
let underlineYPosition = titleY + g.getFontHeight() - 3;
|
||||
g.drawLine(titleX, underlineYPosition, titleX + g.stringWidth(resultTitle), underlineYPosition); // Draw underline
|
||||
|
||||
let valueX;
|
||||
let valueY = titleY + g.getFontHeight(); // Draw below the title
|
||||
|
||||
// Calculate the font size for value dynamically
|
||||
g.setFontVector(fontSize);
|
||||
while (g.stringWidth(resultValue) > g.getWidth() - 10) {
|
||||
fontSize--; // Reduce the font size by 1
|
||||
g.setFontVector(fontSize);
|
||||
}
|
||||
|
||||
valueY += g.getFontHeight() / 2 + 2;
|
||||
valueX = (g.getWidth() - g.stringWidth(resultValue)) / 2;
|
||||
g.drawString(resultValue, valueX, valueY); // Draw at the desired position
|
||||
|
||||
// Move down for the next entry
|
||||
let nextTitleY = (i + 1 < titlePositions.length) ? titlePositions[i + 1] : titleY + 1.5 * fontSize + lineSpacing;
|
||||
yPosition = nextTitleY;
|
||||
}
|
||||
g.flip();
|
||||
};
|
||||
|
||||
// Shows the back button on the result screen
|
||||
return function() {
|
||||
clearScreen();
|
||||
let resultMenu = {
|
||||
'': { 'title': 'Results' },
|
||||
'< Back': function() {
|
||||
E.showMenu(resultsMenu);
|
||||
}
|
||||
};
|
||||
E.showMenu(resultMenu);
|
||||
drawPage();
|
||||
};
|
||||
}
|
||||
|
||||
// Shows the results menu with the calculated results and options
|
||||
function showResultsScreen(result) {
|
||||
let backButton = function () {
|
||||
clearScreen();
|
||||
E.showMenu(resultsMenu);
|
||||
};
|
||||
g.clear();
|
||||
resultsMenu = {
|
||||
'': { 'title': 'Results' },
|
||||
'Main Menu': function () {
|
||||
E.showMenu(mainMenu);
|
||||
},
|
||||
};
|
||||
resultsMenu[result.value + ' ' + result.unit] = drawValueScreen(result);
|
||||
resultsMenu[result.formula] = drawResultScreen(result);
|
||||
resultsMenu['Exit'] = function () {
|
||||
Bangle.showClock();
|
||||
};
|
||||
E.showMenu(resultsMenu);
|
||||
}
|
||||
|
||||
clearTextArea();
|
||||
E.showMenu(mainMenu);
|
||||
|
||||
})();
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"id": "ohmcalc",
|
||||
"name": "Ohm's Law Calculator",
|
||||
"shortName": "Ohm's Law Calc",
|
||||
"version": "0.03",
|
||||
"description": "A smart and simple calculator for Ohm's Law calculations, designed specifically for Bangle.js 2 smartwatches. Handles voltage, current, resistance, and power calculations with smart logic to prevent invalid inputs.",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
"tags": "calculator, utilities, electric",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [{
|
||||
"name": "ohmcalc.app.js",
|
||||
"url": "app.js"
|
||||
},
|
||||
{
|
||||
"name": "ohmcalc.img",
|
||||
"url": "app-icon.js",
|
||||
"evaluate": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +1,2 @@
|
|||
0.01: New App!
|
||||
0.02: Fixes colors not matching user input from color menu in some cases, 3 bands are now shown larger, various code improvements.
|
||||
|
|
@ -3,75 +3,19 @@
|
|||
// https://icons8.com/icon/ISAVBnskZod0/resistor
|
||||
|
||||
let colorData = {
|
||||
black: {
|
||||
value: 0,
|
||||
multiplier: Math.pow(10, 0),
|
||||
hex: '#000'
|
||||
},
|
||||
brown: {
|
||||
value: 1,
|
||||
multiplier: Math.pow(10, 1),
|
||||
tolerance: 1,
|
||||
hex: '#8B4513'
|
||||
},
|
||||
red: {
|
||||
value: 2,
|
||||
multiplier: Math.pow(10, 2),
|
||||
tolerance: 2,
|
||||
hex: '#f00'
|
||||
},
|
||||
orange: {
|
||||
value: 3,
|
||||
multiplier: Math.pow(10, 3),
|
||||
hex: '#FF9900'
|
||||
},
|
||||
yellow: {
|
||||
value: 4,
|
||||
multiplier: Math.pow(10, 4),
|
||||
hex: '#ff0'
|
||||
},
|
||||
green: {
|
||||
value: 5,
|
||||
multiplier: Math.pow(10, 5),
|
||||
tolerance: 0.5,
|
||||
hex: '#0f0'
|
||||
},
|
||||
blue: {
|
||||
value: 6,
|
||||
multiplier: Math.pow(10, 6),
|
||||
tolerance: 0.25,
|
||||
hex: '#00f'
|
||||
},
|
||||
violet: {
|
||||
value: 7,
|
||||
multiplier: Math.pow(10, 7),
|
||||
tolerance: 0.1,
|
||||
hex: '#f0f'
|
||||
},
|
||||
grey: {
|
||||
value: 8,
|
||||
multiplier: Math.pow(10, 8),
|
||||
tolerance: 0.05,
|
||||
hex: '#808080'
|
||||
},
|
||||
white: {
|
||||
value: 9,
|
||||
multiplier: Math.pow(10, 9),
|
||||
hex: '#fff'
|
||||
},
|
||||
gold: {
|
||||
multiplier: Math.pow(10, -1),
|
||||
tolerance: 5,
|
||||
hex: '#FFD700'
|
||||
},
|
||||
silver: {
|
||||
multiplier: Math.pow(10, -2),
|
||||
tolerance: 10,
|
||||
hex: '#C0C0C0'
|
||||
},
|
||||
none: {
|
||||
tolerance: 20
|
||||
},
|
||||
black: { value: 0, multiplier: 1, hex: '#000' },
|
||||
brown: { value: 1, multiplier: 10, tolerance: 1, hex: '#8B4513' },
|
||||
red: { value: 2, multiplier: 100, tolerance: 2, hex: '#f00' },
|
||||
orange: { value: 3, multiplier: 1000, hex: '#FF9900' },
|
||||
yellow: { value: 4, multiplier: 10000, hex: '#ff0' },
|
||||
green: { value: 5, multiplier: 100000, tolerance: 0.5, hex: '#0f0' },
|
||||
blue: { value: 6, multiplier: 1000000, tolerance: 0.25, hex: '#00f' },
|
||||
violet: { value: 7, multiplier: 10000000, tolerance: 0.1, hex: '#f0f' },
|
||||
grey: { value: 8, multiplier: 100000000, tolerance: 0.05, hex: '#808080' },
|
||||
white: { value: 9, multiplier: 1000000000, hex: '#fff' },
|
||||
gold: { multiplier: 0.1, tolerance: 5, hex: '#FFD700' },
|
||||
silver: { multiplier: 0.01, tolerance: 10, hex: '#C0C0C0' },
|
||||
none: { tolerance: 20 },
|
||||
};
|
||||
|
||||
function clearScreen() { // Except Back Button
|
||||
|
|
@ -91,38 +35,55 @@ function colorBandsToResistance(colorBands) {
|
|||
return [resistance, tolerance];
|
||||
}
|
||||
|
||||
function log10(val) {
|
||||
return Math.log(val) / Math.log(10);
|
||||
}
|
||||
|
||||
function resistanceToColorBands(resistance, tolerance) {
|
||||
let multiplier = Math.floor(log10(resistance));
|
||||
let firstDigit = Math.floor(resistance / Math.pow(10, multiplier));
|
||||
resistance -= firstDigit * Math.pow(10, multiplier);
|
||||
multiplier--; // for the next digit
|
||||
let secondDigit = Math.floor(resistance / Math.pow(10, multiplier));
|
||||
resistance -= secondDigit * Math.pow(10, multiplier);
|
||||
console.log("First Digit: " + firstDigit);
|
||||
console.log("Second Digit: " + secondDigit);
|
||||
console.log("Multiplier: " + multiplier);
|
||||
let firstBandEntry = Object.entries(colorData).find(function(entry) {
|
||||
let firstDigit, secondDigit, multiplier;
|
||||
if (resistance < 1) {
|
||||
// The resistance is less than 1, so we need to handle this case specially
|
||||
let count = 0;
|
||||
while (resistance < 1) {
|
||||
resistance *= 10;
|
||||
count++;
|
||||
}
|
||||
// Now, resistance is a whole number and count is how many times we had to multiply by 10
|
||||
let resistanceStr = resistance.toString();
|
||||
firstDigit = 0; // Set the first band color to be black
|
||||
secondDigit = Number(resistanceStr.charAt(0)); // Set the second band color to be the significant digit
|
||||
// Use count to determine the multiplier
|
||||
multiplier = count === 1 ? 0.1 : 0.01;
|
||||
} else {
|
||||
// Convert the resistance to a string so we can manipulate it easily
|
||||
let resistanceStr = resistance.toString();
|
||||
if (resistanceStr.length === 1) { // Check if resistance is a single digit
|
||||
firstDigit = 0;
|
||||
secondDigit = Number(resistanceStr.charAt(0));
|
||||
multiplier = 1; // Set multiplier to 1 for single digit resistance values
|
||||
} else {
|
||||
// Extract the first two digits from the resistance value
|
||||
firstDigit = Number(resistanceStr.charAt(0));
|
||||
secondDigit = Number(resistanceStr.charAt(1));
|
||||
// Calculate the multiplier by matching it directly with the length of digits
|
||||
multiplier = resistanceStr.length - 2 >= 0 ? Math.pow(10, resistanceStr.length - 2) : Math.pow(10, resistanceStr.length - 1);
|
||||
}
|
||||
}
|
||||
let firstBandEntry = Object.entries(colorData).find(function (entry) {
|
||||
return entry[1].value === firstDigit;
|
||||
});
|
||||
let firstBand = firstBandEntry ? firstBandEntry[1].hex : undefined;
|
||||
let secondBandEntry = Object.entries(colorData).find(function(entry) {
|
||||
let secondBandEntry = Object.entries(colorData).find(function (entry) {
|
||||
return entry[1].value === secondDigit;
|
||||
});
|
||||
let secondBand = secondBandEntry ? secondBandEntry[1].hex : undefined;
|
||||
let multiplierBandEntry = Object.entries(colorData).find(function(entry) {
|
||||
return entry[1].multiplier === Math.pow(10, multiplier);
|
||||
let multiplierBandEntry = Object.entries(colorData).find(function (entry) {
|
||||
return entry[1].multiplier === multiplier;
|
||||
});
|
||||
let multiplierBand = multiplierBandEntry ? multiplierBandEntry[1].hex : undefined;
|
||||
let toleranceBandEntry = Object.entries(colorData).find(function(entry) {
|
||||
let toleranceBandEntry = Object.entries(colorData).find(function (entry) {
|
||||
return entry[1].tolerance === tolerance;
|
||||
});
|
||||
let toleranceBand = toleranceBandEntry ? toleranceBandEntry[1].hex : undefined;
|
||||
console.log("Color bands: " + [firstBand, secondBand, multiplierBand, toleranceBand]);
|
||||
return [firstBand, secondBand, multiplierBand, toleranceBand];
|
||||
let bands = [firstBand, secondBand, multiplierBand];
|
||||
if (toleranceBand) bands.push(toleranceBand);
|
||||
return bands;
|
||||
}
|
||||
|
||||
function drawResistor(colorBands, tolerance) {
|
||||
|
|
@ -130,32 +91,27 @@ function drawResistor(colorBands, tolerance) {
|
|||
let resistorBodyWidth = 51;
|
||||
let resistorBodyHeight = 43;
|
||||
let resistorStartX = 52;
|
||||
var bandColors = colorBands;
|
||||
var numcolorBands = bandColors.length;
|
||||
var resistorStartY = ((g.getHeight() - resistorBodyHeight) / 2) + 48;
|
||||
let bandColors = colorBands;
|
||||
let numColorBands = bandColors.length;
|
||||
let resistorStartY = ((g.getHeight() - resistorBodyHeight) / 2) + 48;
|
||||
clearScreen();
|
||||
g.drawImage(img, 0, 112);
|
||||
var bandWidth = (resistorBodyWidth - (numcolorBands * 2 - 1)) / numcolorBands; // width of each band, accounting for the spacing
|
||||
var bandHeight = resistorBodyHeight; // height of each band
|
||||
var currentX = resistorStartX; // starting point for the first band
|
||||
let bandWidth = (resistorBodyWidth - (numColorBands * 2 - 1)) / numColorBands; // width of each band, accounting for the spacing
|
||||
let bandHeight = resistorBodyHeight; // height of each band
|
||||
let currentX = resistorStartX; // starting point for the first band
|
||||
// Define the tolerance values that will trigger the fourth band
|
||||
var validTolerances = [1, 2, 0.5, 0.25, 0.1, 0.05, 5, 10];
|
||||
|
||||
for (var i = 0; i < numcolorBands; i++) {
|
||||
let validTolerances = [1, 2, 0.5, 0.25, 0.1, 0.05, 5, 10];
|
||||
for (let i = 0; i < numColorBands; i++) {
|
||||
// Skip the fourth band and its outlines if the tolerance is not in the valid list
|
||||
if (i === 3 && !validTolerances.includes(tolerance)) continue;
|
||||
|
||||
var bandX = currentX; // calculate the x-coordinate of the band
|
||||
var bandY = resistorStartY; // y-coordinate of the band
|
||||
|
||||
let bandX = currentX; // calculate the x-coordinate of the band
|
||||
let bandY = resistorStartY; // y-coordinate of the band
|
||||
g.setColor(bandColors[i]); // set the color for the band
|
||||
g.fillRect(bandX, bandY, bandX + bandWidth, bandY + bandHeight);
|
||||
|
||||
// Draw band outlines
|
||||
g.setColor('#000'); // set the color for the outline
|
||||
g.drawLine(bandX, bandY, bandX, bandY + bandHeight); // left outline
|
||||
g.drawLine(bandX + bandWidth, bandY, bandX + bandWidth, bandY + bandHeight); // right outline
|
||||
|
||||
// if it's the fourth band, shift it over by an additional 12 pixels
|
||||
if (i === 2) {
|
||||
currentX = bandX + bandWidth + 5 + 12; // update the current X position for the next band, accounting for the spacing
|
||||
|
|
@ -170,14 +126,14 @@ function omega() {
|
|||
}
|
||||
|
||||
function formatResistance(resistance) {
|
||||
var units = ["", "k", "M", "G"];
|
||||
var unitIndex = 0;
|
||||
let units = ["", "k", "M", "G"];
|
||||
let unitIndex = 0;
|
||||
while (resistance >= 1000 && unitIndex < units.length - 1) {
|
||||
resistance /= 1000;
|
||||
unitIndex++;
|
||||
}
|
||||
// Convert to string and truncate unnecessary zeroes
|
||||
var resistanceStr = String(resistance);
|
||||
let resistanceStr = String(resistance);
|
||||
if (resistanceStr.length > 5) { // if length is more than 5 including decimal point
|
||||
resistanceStr = resistance.toFixed(2);
|
||||
}
|
||||
|
|
@ -188,49 +144,40 @@ function formatResistance(resistance) {
|
|||
}
|
||||
|
||||
function drawResistance(resistance, tolerance) {
|
||||
var x = g.getWidth() / 2;
|
||||
var y = 40;
|
||||
var formattedResistance = formatResistance(resistance);
|
||||
var resistanceStr = formattedResistance.value;
|
||||
var unit = formattedResistance.unit;
|
||||
let x = g.getWidth() / 2;
|
||||
let y = 40;
|
||||
let formattedResistance = formatResistance(resistance);
|
||||
let resistanceStr = formattedResistance.value;
|
||||
let unit = formattedResistance.unit;
|
||||
g.reset();
|
||||
|
||||
// draw resistance value
|
||||
g.setFontAlign(0, 0).setFont("Vector", 54);
|
||||
g.clearRect(0, y - 15, g.getWidth(), y + 25); // clear the background
|
||||
g.drawString(resistanceStr, x + 4, y);
|
||||
|
||||
// draw unit, symbol and tolerance
|
||||
// draw unit, symbol, and tolerance
|
||||
y += 46;
|
||||
g.setFontAlign(-1, 0).setFont("Vector", 27);
|
||||
|
||||
var toleranceShift = tolerance.toString().replace('.', '').length > 2 ? 8 : 0;
|
||||
var unitX = ((unit === "M" || unit === "G") ? 0 : 8) - toleranceShift;
|
||||
var omegaX = (unit ? 46 : 36) - toleranceShift; // Shift the Omega symbol to the left if there is no unit
|
||||
|
||||
let toleranceShift = tolerance.toString().replace('.', '').length > 2 ? 8 : 0;
|
||||
let unitX = ((unit === "M" || unit === "G") ? 0 : 8) - toleranceShift;
|
||||
let omegaX = (unit ? 46 : 36) - toleranceShift; // Shift the Omega symbol to the left if there is no unit
|
||||
g.drawString(unit.padStart(3), unitX, y);
|
||||
|
||||
// Draw the Ohm symbol to the right of the unit
|
||||
g.drawImage(omega(), omegaX, y - 13, {
|
||||
scale: 0.45
|
||||
});
|
||||
|
||||
g.drawImage(omega(), omegaX, y - 13, { scale: 0.45 });
|
||||
g.setFontAlign(1, 0).setFont("Vector", 27);
|
||||
|
||||
// Define the tolerance values that will trigger the fourth band
|
||||
var validTolerances = [1, 2, 0.5, 0.25, 0.1, 0.05, 5, 10];
|
||||
|
||||
let validTolerances = [1, 2, 0.5, 0.25, 0.1, 0.05, 5, 10];
|
||||
// Check if the tolerance is not in the valid list, and if it's not, set it to 20
|
||||
if (!validTolerances.includes(tolerance)) {
|
||||
tolerance = 20;
|
||||
}
|
||||
|
||||
var toleranceStr = "±" + tolerance + "%";
|
||||
var toleranceX = tolerance.toString().replace('.', '').length > 2 ? 10 : 14;
|
||||
let toleranceStr = "±" + tolerance + "%";
|
||||
let toleranceX = tolerance.toString().replace('.', '').length > 2 ? 10 : 14;
|
||||
g.drawString(toleranceStr.padEnd(4), 176 - toleranceX, y);
|
||||
}
|
||||
|
||||
(function() {
|
||||
(function () {
|
||||
let colorBands;
|
||||
let inputColorBands;
|
||||
let settings = {
|
||||
resistance: 0,
|
||||
tolerance: 0,
|
||||
|
|
@ -244,6 +191,8 @@ function drawResistance(resistance, tolerance) {
|
|||
colorBands: ["", "", "", ""]
|
||||
};
|
||||
settings = emptySettings;
|
||||
colorBands = null;
|
||||
inputColorBands = null;
|
||||
}
|
||||
|
||||
function showColorBandMenu(bandNumber) {
|
||||
|
|
@ -251,7 +200,7 @@ function drawResistance(resistance, tolerance) {
|
|||
'': {
|
||||
'title': `Band ${bandNumber}`
|
||||
},
|
||||
'< Back': function() {
|
||||
'< Back': function () {
|
||||
E.showMenu(colorEntryMenu);
|
||||
},
|
||||
};
|
||||
|
|
@ -260,24 +209,24 @@ function drawResistance(resistance, tolerance) {
|
|||
for (let color in colorData) {
|
||||
if (bandNumber === 1 || bandNumber === 2) {
|
||||
if (color !== 'none' && color !== 'gold' && color !== 'silver') {
|
||||
(function(color) {
|
||||
colorBandMenu[color.charAt(0).toUpperCase() + color.slice(1)] = function() {
|
||||
(function (color) {
|
||||
colorBandMenu[color.charAt(0).toUpperCase() + color.slice(1)] = function () {
|
||||
setBandColor(bandNumber, color);
|
||||
};
|
||||
})(color);
|
||||
}
|
||||
} else if (bandNumber === 3) {
|
||||
if (color !== 'none') {
|
||||
(function(color) {
|
||||
colorBandMenu[color.charAt(0).toUpperCase() + color.slice(1)] = function() {
|
||||
(function (color) {
|
||||
colorBandMenu[color.charAt(0).toUpperCase() + color.slice(1)] = function () {
|
||||
setBandColor(bandNumber, color);
|
||||
};
|
||||
})(color);
|
||||
}
|
||||
} else if (bandNumber === 4) {
|
||||
if (colorData[color].hasOwnProperty('tolerance')) {
|
||||
(function(color) {
|
||||
colorBandMenu[color.charAt(0).toUpperCase() + color.slice(1)] = function() {
|
||||
(function (color) {
|
||||
colorBandMenu[color.charAt(0).toUpperCase() + color.slice(1)] = function () {
|
||||
setBandColor(bandNumber, color);
|
||||
};
|
||||
})(color);
|
||||
|
|
@ -289,11 +238,8 @@ function drawResistance(resistance, tolerance) {
|
|||
|
||||
function setBandColor(bandNumber, color) {
|
||||
settings.colorBands[bandNumber - 1] = color; // arrays are 0-indexed
|
||||
console.log(`Band ${bandNumber} color set to ${color}`);
|
||||
|
||||
// Update the color band in the colorEntryMenu
|
||||
colorEntryMenu[`${bandNumber}:`].value = color;
|
||||
|
||||
showColorEntryMenu();
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +248,7 @@ function drawResistance(resistance, tolerance) {
|
|||
'': {
|
||||
'title': 'Band Color'
|
||||
},
|
||||
'< Back': function() {
|
||||
'< Back': function () {
|
||||
clearScreen();
|
||||
E.showMenu(mainMenu);
|
||||
},
|
||||
|
|
@ -338,9 +284,9 @@ function drawResistance(resistance, tolerance) {
|
|||
setTimeout(() => showColorBandMenu(4), 5);
|
||||
}
|
||||
},
|
||||
'Draw Resistor': function() {
|
||||
let colorBands = settings.colorBands;
|
||||
let values = colorBandsToResistance(colorBands);
|
||||
'Draw Resistor': function () {
|
||||
inputColorBands = settings.colorBands;
|
||||
let values = colorBandsToResistance(inputColorBands);
|
||||
settings.resistance = values[0];
|
||||
settings.tolerance = values[1];
|
||||
showDrawingMenu();
|
||||
|
|
@ -355,7 +301,7 @@ function drawResistance(resistance, tolerance) {
|
|||
'': {
|
||||
'title': 'Multiplier'
|
||||
},
|
||||
'< Back': function() {
|
||||
'< Back': function () {
|
||||
showResistanceEntryMenu();
|
||||
}
|
||||
};
|
||||
|
|
@ -367,9 +313,8 @@ function drawResistance(resistance, tolerance) {
|
|||
let formattedMultiplier = formatMultiplier(multiplierValue);
|
||||
multiplierMenu[`${formattedMultiplier}`] = () => {
|
||||
settings.multiplier = multiplierValue;
|
||||
console.log(`Multiplier changed to: ${settings.multiplier}`);
|
||||
// Update the value of 'Multiplier' in resistanceEntryMenu
|
||||
resistanceEntryMenu["Multiplier"] = function() {
|
||||
resistanceEntryMenu["Multiplier"] = function () {
|
||||
showMultiplierMenu();
|
||||
};
|
||||
showResistanceEntryMenu();
|
||||
|
|
@ -395,7 +340,7 @@ function drawResistance(resistance, tolerance) {
|
|||
'': {
|
||||
'title': 'Tolerance'
|
||||
},
|
||||
'< Back': function() {
|
||||
'< Back': function () {
|
||||
showResistanceEntryMenu();
|
||||
}
|
||||
};
|
||||
|
|
@ -406,22 +351,29 @@ function drawResistance(resistance, tolerance) {
|
|||
let tolerance = parseFloat(colorData[color].tolerance); // Parse the tolerance as a float
|
||||
toleranceMenu[`${tolerance}%`] = () => {
|
||||
settings.tolerance = tolerance;
|
||||
console.log(settings.tolerance);
|
||||
// Update the value of 'Tolerance (%)' in resistanceEntryMenu
|
||||
resistanceEntryMenu["Tolerance (%)"] = function() {
|
||||
resistanceEntryMenu["Tolerance (%)"] = function () {
|
||||
showToleranceMenu();
|
||||
};
|
||||
showResistanceEntryMenu();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
E.showMenu(toleranceMenu);
|
||||
}
|
||||
|
||||
function drawResistorAndResistance(resistance, tolerance, multipliedResistance) {
|
||||
console.log('Draw Resistor clicked');
|
||||
let colorBands = resistanceToColorBands(multipliedResistance || resistance, tolerance);
|
||||
function drawResistorAndResistance(resistance, tolerance) {
|
||||
if (inputColorBands) {
|
||||
colorBands = inputColorBands.map(color => {
|
||||
if (colorData.hasOwnProperty(color)) {
|
||||
return colorData[color].hex;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
colorBands = resistanceToColorBands(resistance, tolerance);
|
||||
}
|
||||
drawResistor(colorBands, tolerance);
|
||||
drawResistance(resistance, tolerance);
|
||||
resetSettings();
|
||||
|
|
@ -431,7 +383,7 @@ function drawResistance(resistance, tolerance) {
|
|||
'': {
|
||||
'title': 'Resistance'
|
||||
},
|
||||
'< Back': function() {
|
||||
'< Back': function () {
|
||||
clearScreen();
|
||||
E.showMenu(mainMenu);
|
||||
},
|
||||
|
|
@ -441,15 +393,15 @@ function drawResistance(resistance, tolerance) {
|
|||
max: 99,
|
||||
wrap: true,
|
||||
format: v => '',
|
||||
onchange: v => {}
|
||||
onchange: v => { }
|
||||
},
|
||||
'Multiplier': function() {
|
||||
'Multiplier': function () {
|
||||
showMultiplierMenu();
|
||||
},
|
||||
'Tolerance (%)': function() {
|
||||
'Tolerance (%)': function () {
|
||||
showToleranceMenu();
|
||||
},
|
||||
'Draw Resistor': function() {
|
||||
'Draw Resistor': function () {
|
||||
showDrawingMenu();
|
||||
}
|
||||
};
|
||||
|
|
@ -469,25 +421,21 @@ function drawResistance(resistance, tolerance) {
|
|||
};
|
||||
resistanceEntryMenu['Ohms'].onchange = v => {
|
||||
settings.resistance = v || 0;
|
||||
console.log('Resistance changed to: ', settings.resistance);
|
||||
};
|
||||
|
||||
E.showMenu(resistanceEntryMenu);
|
||||
}
|
||||
|
||||
function showDrawingMenu() {
|
||||
let drawingMenu = {
|
||||
'': {
|
||||
'title': 'Resistor Drawing'
|
||||
'title': ''
|
||||
},
|
||||
'< Back': function() {
|
||||
'< Back': function () {
|
||||
clearScreen();
|
||||
E.showMenu(mainMenu);
|
||||
},
|
||||
};
|
||||
|
||||
E.showMenu(drawingMenu);
|
||||
|
||||
let resistance = settings.resistance * (settings.multiplier || 1);
|
||||
let tolerance = settings.tolerance;
|
||||
drawResistorAndResistance(resistance, tolerance);
|
||||
|
|
@ -498,14 +446,14 @@ function drawResistance(resistance, tolerance) {
|
|||
'title': 'Resistor Calc'
|
||||
},
|
||||
'< Back': () => Bangle.showClock(), // return to the clock app
|
||||
'Resistance': function() {
|
||||
'Resistance': function () {
|
||||
resetSettings();
|
||||
showResistanceEntryMenu();
|
||||
},
|
||||
'Colors': function() {
|
||||
'Colors': function () {
|
||||
resetSettings();
|
||||
showColorEntryMenu();
|
||||
},
|
||||
};
|
||||
E.showMenu(mainMenu);
|
||||
})();
|
||||
})();
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
"name": "Resistor Calculator",
|
||||
"shortName": "Resistor Calc",
|
||||
"icon": "rescalc.png",
|
||||
"version":"0.01",
|
||||
"version":"0.02",
|
||||
"screenshots": [
|
||||
{"url": "screenshot.png"},
|
||||
{"url": "screenshot-1.png"},
|
||||
|
|
|
|||
Loading…
Reference in New Issue