aboutsummaryrefslogtreecommitdiff
path: root/modules/ext/calc.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ext/calc.js')
-rw-r--r--modules/ext/calc.js77
1 files changed, 77 insertions, 0 deletions
diff --git a/modules/ext/calc.js b/modules/ext/calc.js
new file mode 100644
index 0000000..e28079e
--- /dev/null
+++ b/modules/ext/calc.js
@@ -0,0 +1,77 @@
+class CalcModule {
+ constructor() {
+ this.commands = {};
+ this.terminal = null;
+ this.units = {
+ 'km': { to: { 'miles': 0.621371, 'meters': 1000, 'feet': 3280.84 } },
+ 'miles': { to: { 'km': 1.60934, 'meters': 1609.34, 'feet': 5280 } },
+ 'meters': { to: { 'km': 0.001, 'miles': 0.000621371, 'feet': 3.28084 } },
+ 'feet': { to: { 'km': 0.0003048, 'miles': 0.000189394, 'meters': 0.3048 } },
+ 'kg': { to: { 'pounds': 2.20462, 'grams': 1000, 'ounces': 35.274 } },
+ 'pounds': { to: { 'kg': 0.453592, 'grams': 453.592, 'ounces': 16 } },
+ 'grams': { to: { 'kg': 0.001, 'pounds': 0.00220462, 'ounces': 0.035274 } },
+ 'ounces': { to: { 'kg': 0.0283495, 'pounds': 0.0625, 'grams': 28.3495 } },
+ 'celsius': { to: { 'fahrenheit': 'c2f', 'kelvin': 'c2k' } },
+ 'fahrenheit': { to: { 'celsius': 'f2c', 'kelvin': 'f2k' } },
+ 'kelvin': { to: { 'celsius': 'k2c', 'fahrenheit': 'k2f' } },
+ 'inch': { to: { 'cm': 2.54, 'mm': 25.4, 'feet': 0.0833333 } },
+ 'cm': { to: { 'inch': 0.393701, 'mm': 10, 'm': 0.01 } },
+ 'mm': { to: { 'cm': 0.1, 'inch': 0.0393701, 'm': 0.001 } },
+ 'liters': { to: { 'gallons': 0.264172, 'ml': 1000, 'cups': 4.22675 } },
+ 'gallons': { to: { 'liters': 3.78541, 'ml': 3785.41, 'cups': 16 } }
+ };
+ }
+ getHelpInfo() {
+ return { 'calc': 'calc <expression> or calc <value> <from-unit> to <to-unit> — Evaluate expressions or convert between units' };
+ }
+ registerCommands() {
+ this.commands['calc'] = (args) => this.calc(args);
+ }
+ calc(args) {
+ if (!args[0]) return this.terminal.print('Usage: calc <expression> or calc <value> <from-unit> to <to-unit>', 'warning');
+ const input = args.join(' ');
+ const convertMatch = input.match(/^([+-]?\d*\.?\d+)\s*(\w+)\s+(?:to|in|->)\s+(\w+)$/i);
+ if (convertMatch) {
+ return this.convert(parseFloat(convertMatch[1]), convertMatch[2].toLowerCase(), convertMatch[3].toLowerCase());
+ }
+ this.evaluate(input);
+ }
+ evaluate(expr) {
+ const sanitized = expr.replace(/[^0-9+\-*/.()%eE\s]/g, '');
+ if (!sanitized) return this.terminal.print('Invalid expression', 'error');
+ try {
+ const result = new Function('return (' + sanitized + ')')();
+ if (typeof result === 'number' && !isNaN(result)) {
+ this.terminal.print(`${sanitized} = ${result}`, 'success');
+ } else {
+ this.terminal.print('Invalid result', 'error');
+ }
+ } catch (e) {
+ this.terminal.print(`Error: ${e.message}`, 'error');
+ }
+ }
+ convert(value, from, to) {
+ if (!this.units[from]) return this.terminal.print(`Unknown unit: ${from}`, 'error');
+ if (!this.units[from].to[to]) {
+ const avail = Object.keys(this.units[from].to).join(', ');
+ return this.terminal.print(`Cannot convert ${from} to ${to}. Available: ${avail}`, 'warning');
+ }
+ const factor = this.units[from].to[to];
+ if (typeof factor === 'string') {
+ let result;
+ if (factor === 'c2f') result = value * 9/5 + 32;
+ else if (factor === 'c2k') result = value + 273.15;
+ else if (factor === 'f2c') result = (value - 32) * 5/9;
+ else if (factor === 'f2k') result = (value - 32) * 5/9 + 273.15;
+ else if (factor === 'k2c') result = value - 273.15;
+ else if (factor === 'k2f') result = (value - 273.15) * 9/5 + 32;
+ else return this.terminal.print('Conversion not implemented', 'error');
+ this.terminal.print(`${value} ${from} = ${result.toFixed(4)} ${to}`, 'success');
+ } else {
+ this.terminal.print(`${value} ${from} = ${(value * factor).toFixed(4)} ${to}`, 'success');
+ }
+ }
+}
+if (typeof window.webx11 !== 'undefined' && window.webx11) {
+ webx11.moduleManager.registerModule(new CalcModule(), 'https://webx11.duckdns.org/spaces/chatstudio/newos4/modules/calc.js');
+}