6 Modi: Standard, Scientific, Unit-Converter, Satisfactory, Factorio, Stationeers. Tab-basierte Architektur, Registrierungs-Pattern, erweiteter Shunting-Yard Parser. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
16 KiB
Hellion NewTab — Calculator Upgrade Design
Datum: 2026-04-16 Autor: Florian Wathling / Claude Code Status: Approved Scope: Calculator erweitern um Scientific, Unit-Converter und Game-Rechner (Satisfactory, Factorio, Stationeers) Ziel-Version: v2.1.0
Kontext
Der Calculator ist aktuell ein reiner Grundrechenarten-Taschenrechner (720 Zeilen, Shunting-Yard Parser, 4x5 Button-Grid, History). Das Upgrade macht ihn zum zentralen Tool-Widget mit 6 Modi:
- Standard (bestehend)
- Scientific (Wurzel, Potenz, Pi, Formel-Helfer)
- Unit-Converter (Länge, Gewicht, Temperatur, Volumen, Geschwindigkeit, Fläche)
- Satisfactory (Items/Min, Overclock-Power, Maschinen-Rechner)
- Factorio (Assembler-Ratios, Belt-Throughput, Maschinen-Rechner)
- Stationeers (Idealgas, Furnace/Verbrennung, Solar/Batterie, Atmosphäre)
Sektion 1: Architektur und Dateistruktur
Datei-Aufteilung
src/js/
├── calculator.js # Core: Tab-System, Standard-Modus, erweiterter Shunting-Yard Parser
├── calc-scientific.js # Scientific-Modus
├── calc-converter.js # Unit-Converter
├── calc-satisfactory.js # Satisfactory Calculator
├── calc-factorio.js # Factorio Calculator
└── calc-stationeers.js # Stationeers Calculator
Load-Order in newtab.html
... → widgets.js → notes.js → calculator.js → calc-scientific.js → calc-converter.js →
calc-satisfactory.js → calc-factorio.js → calc-stationeers.js → timer.js → ...
Alle Mode-Dateien laden nach calculator.js und vor timer.js. Kein zirkulärer Dependency-Konflikt.
Registrierungs-Pattern
Jede Mode-Datei registriert sich beim Calculator-Objekt:
Calculator.registerMode('scientific', {
label: '\uD83D\uDCD0', // Icon
shortName: 'Sci', // Tab-Label (3 Zeichen)
titleKey: 'calculator.tab.scientific', // i18n-Key
render(bodyEl) { /* UI aufbauen */ },
destroy() { /* Cleanup, Event-Listener entfernen */ }
});
calculator.js bekommt:
_modes: new Map(),
_activeMode: 'standard',
registerMode(name, config) {
this._modes.set(name, config);
},
Die Tab-Leiste wird dynamisch aus _modes gebaut. Standard-Modus ist immer registriert (intern, nicht per externer Datei). Die anderen Modi kommen dazu wenn ihre Script-Datei geladen ist.
Tab-Wechsel
switchMode(name) {
const mode = this._modes.get(name);
if (!mode) return;
this._activeMode = name;
const body = WidgetManager.getBody(this.WIDGET_ID);
if (!body) return;
// Alten Modus aufräumen
const oldMode = this._modes.get(this._previousMode);
if (oldMode && oldMode.destroy) oldMode.destroy();
// Neuen Modus rendern
body.textContent = '';
mode.render(body);
// Tab-UI aktualisieren
this._updateTabBar();
// State speichern
this.save();
}
Storage
Jeder Modus speichert seinen State als Sub-Key unter calculator im bestehenden widgetStates:
{
calculator: {
x: 400, y: 120, width: 320, height: 480,
open: true,
activeMode: 'standard',
history: [{ expr: '42 × 7', result: '294' }],
converter: { lastCategory: 'length', fromUnit: 'cm', toUnit: 'in' },
satisfactory: { lastSubMode: 'itemsPerMin' },
factorio: { lastSubMode: 'ratio', lastAssembler: 'asm3' },
stationeers: { lastSubMode: 'gas' }
}
}
Read-before-write Pattern bleibt: const data = await Store.get(this.STORAGE_KEY) || {};
Sektion 2: Standard-Modus (Änderungen)
Parser-Erweiterung
Der Shunting-Yard Parser wird um zwei Operationen erweitert:
Potenz-Operator ^:
- Binärer Operator mit höchster Precedence (über
*und/) - Rechts-assoziativ:
2^3^2=2^(3^2)= 512 - Tokenizer erkennt
^als{ type: 'op', value: '^' } - parseFactor() → parsePower() → parseFactor() (neue Precedence-Stufe)
Wurzel-Funktion sqrt:
- Wird vom Scientific-Modus als
sqrt(in die Expression eingefügt - Tokenizer erkennt
sqrtals{ type: 'func', value: 'sqrt' } - parseFactor() prüft auf Functions vor Numbers
Die bestehende Operator-Hierarchie wird:
parseExpr: + -
parseTerm: * / %
parsePower: ^ ← NEU
parseFactor: number | (expr) | func(expr) ← func NEU
Keine Änderungen am Standard-UI
Das 4x5 Button-Grid, History-Panel und Keyboard-Support bleiben identisch. Die Parser-Erweiterung ist rückwärtskompatibel (keine bestehende Expression bricht).
Sektion 3: Scientific-Modus
Zusätzliche Buttons
2 neue Reihen über dem Standard-Grid:
| Button | Wert | Aktion |
|---|---|---|
| √ | sqrt( |
Unäre Funktion, öffnet Klammer |
| x² | ^2 |
Hängt ^2 an Expression |
| xⁿ | ^ |
Fügt Potenz-Operator ein |
| π | 3.14159265359 |
Konstante einfügen |
| e | 2.71828182846 |
Konstante einfügen |
| ± | toggle | Vorzeichen des letzten Werts wechseln |
Darunter das Standard 4x5-Grid (C, Klammern, %, ÷, 0-9, Operatoren, =). Der Scientific-Modus nutzt den gleichen _handleKey()/_calculate()-Flow.
Formel-Helfer
Ein Dropdown unter dem Button-Grid mit vorgefertigten Formeln:
| Formel | Eingabefelder | Berechnung |
|---|---|---|
| Kreis-Fläche | Radius (r) | π × r² |
| Kreis-Umfang | Radius (r) | 2 × π × r |
| °C → °F | Temperatur | (C × 9/5) + 32 |
| °F → °C | Temperatur | (F - 32) × 5/9 |
| Pythagoras | a, b | √(a² + b²) |
| Prozent-Wert | Wert, Prozent | Wert × Prozent / 100 |
Jede Formel öffnet inline Eingabefelder + Live-Ergebnis. Nutzt _formatResult() für einheitliche Zahlenformatierung.
Keyboard
Gleicher Keyboard-Support wie Standard-Modus, plus:
p→ Pi einfügene→ Euler einfügen (kein Konflikt:eist im Standard nicht belegt, nurc/CundEscapesind Clear)
Sektion 4: Unit-Converter
UI-Aufbau
┌──────────────────────────┐
│ [Kategorie-Dropdown ▼]│
│ │
│ [123.45 ] [cm ▼] │
│ ⇅ (Swap-Button) │
│ [48.622 ] [in ▼] │
│ │
│ Schnellreferenz: │
│ 1 cm = 0.3937 in │
│ 1 in = 2.54 cm │
└──────────────────────────┘
Kategorien und Einheiten
| Kategorie | Einheiten | Basis-Einheit |
|---|---|---|
| Länge | mm, cm, m, km, in, ft, yd, mi | m |
| Gewicht | mg, g, kg, t, oz, lb | g |
| Temperatur | °C, °F, K | (Spezialfunktionen) |
| Volumen | ml, L, m³, gal(US), gal(UK), ft³ | ml |
| Geschwindigkeit | m/s, km/h, mph, kn | m/s |
| Fläche | mm², cm², m², km², ha, acre, ft², in² | m² |
Konvertierungs-Logik
Jede Einheit hat toBase(value) und fromBase(value):
const LENGTH_UNITS = {
mm: { toBase: v => v / 1000, fromBase: v => v * 1000 },
cm: { toBase: v => v / 100, fromBase: v => v * 100 },
m: { toBase: v => v, fromBase: v => v },
km: { toBase: v => v * 1000, fromBase: v => v / 1000 },
in: { toBase: v => v * 0.0254, fromBase: v => v / 0.0254 },
ft: { toBase: v => v * 0.3048, fromBase: v => v / 0.3048 },
yd: { toBase: v => v * 0.9144, fromBase: v => v / 0.9144 },
mi: { toBase: v => v * 1609.344, fromBase: v => v / 1609.344 }
};
Temperatur bekommt eigene Funktionen (nicht linear):
const TEMP_CONVERSIONS = {
'C_F': v => (v * 9/5) + 32,
'C_K': v => v + 273.15,
'F_C': v => (v - 32) * 5/9,
'F_K': v => (v - 32) * 5/9 + 273.15,
'K_C': v => v - 273.15,
'K_F': v => (v - 273.15) * 9/5 + 32
};
Verhalten
- Live-Update bei Eingabe (kein "Berechnen"-Button)
- Swap-Button (⇅) tauscht Quell- und Ziel-Einheit
- Schnellreferenz zeigt
1 [from] = x [to]und umgekehrt - Kein Keyboard-Override (native
<input>Felder)
Storage
converter: { lastCategory: 'length', fromUnit: 'cm', toUnit: 'in' }
Sektion 5: Satisfactory Calculator
Sub-Modi
Drei Buttons oben wählen den aktiven Rechner:
5a: Items/Min
Eingabefelder:
- Items per Craft (default: 1)
- Craft Time in Sekunden (default: 4)
- Clock Speed in % (default: 100)
Formel:
Output = (ItemsPerCraft × 60) / CraftTime × (ClockSpeed / 100)
Ausgabe: X.XX items/min
5b: Overclock Power
Eingabefelder:
- Base Power in MW (default: 30)
- Clock Speed in % (default: 100)
Formeln:
PowerUsage = BasePower × (ClockSpeed / 100) ^ 1.321928
EnergyPerItem = (ClockSpeed / 100) ^ 0.321928
Ausgabe:
Power Usage: X.X MWEfficiency: ↓ X.X% per item(nur bei ClockSpeed > 100)
5c: Maschinen
Eingabefelder:
- Target Output/Min (default: 60)
- Items per Craft (default: 1)
- Craft Time in Sekunden (default: 4)
- Clock Speed in % (default: 100)
- Base Power in MW (default: 30)
Formeln:
ItemsPerMin = (ItemsPerCraft × 60) / CraftTime × (ClockSpeed / 100)
Machines = ceil(TargetOutput / ItemsPerMin)
TotalPower = Machines × BasePower × (ClockSpeed / 100) ^ 1.321928
Ausgabe:
Machines needed: XTotal Power: X.X MW
Verhalten
Alle Felder berechnen live. <input type="number"> mit step-Attribut für sinnvolle Schrittweiten.
Sektion 6: Factorio Calculator
Sub-Modi
6a: Assembler-Ratio
Eingabefelder:
- Assembler-Dropdown: Assembler 1 (0.5), Assembler 2 (0.75), Assembler 3 (1.25)
- Recipe Output Count (default: 1)
- Recipe Time in Sekunden (default: 1)
Formel:
OutputPerSecond = RecipeOutput × CraftingSpeed / RecipeTime
OutputPerMinute = OutputPerSecond × 60
Ausgabe:
X.XX items/sX.XX items/min
6b: Belt-Throughput
Eingabefelder:
- Belt-Dropdown: Yellow (15/s), Red (30/s), Blue (45/s)
- Items consumed per second per machine (default: 1)
Feste Werte:
| Belt | Total (items/s) | Per Side (items/s) |
|---|---|---|
| Yellow | 15 | 7.5 |
| Red | 30 | 15 |
| Blue | 45 | 22.5 |
Formel:
MachinesPerBelt = floor(BeltThroughput / ItemsConsumedPerSec)
Utilization = (ItemsConsumedPerSec × MachinesPerBelt) / BeltThroughput × 100
Ausgabe:
Machines per belt: XBelt utilization: X%
6c: Maschinen
Eingabefelder:
- Assembler-Dropdown
- Target Output/s (default: 10)
- Recipe Output Count (default: 1)
- Recipe Time in Sekunden (default: 1)
Formel:
OutputPerMachine = RecipeOutput × CraftingSpeed / RecipeTime
Machines = ceil(TargetOutput / OutputPerMachine)
TotalThroughput = Machines × OutputPerMachine
BeltNeeded = kleinster Belt der TotalThroughput schafft
Ausgabe:
Machines needed: XBelt needed: [Color] (X% utilization)
Sektion 7: Stationeers Calculator
Sub-Modi
Vier Buttons oben (statt drei wie bei den anderen Game-Rechnern).
7a: Gas (Idealgas PV=nRT)
Eingabefelder:
- Dropdown: Gesucht = P, V, n oder T
- Die drei anderen Variablen als Eingabefelder
Konstante: R = 8314.46261815324 (Stationeers-spezifisch, Einheit: L·Pa / mol·K)
Formeln:
P = nRT / V
V = nRT / P
n = PV / RT
T = PV / nR
Eingabe-Einheiten:
- P in kPa (wird intern × 1000 zu Pa)
- V in Litern
- T in Kelvin (Hilfstext zeigt °C-Äquivalent)
- n in mol
7b: Furnace / Verbrennung
Eingabefelder:
- Fuel Ratio (0 bis 1, Anteil Brennstoff am Gesamtgas)
- Start-Temperatur in Kelvin
- Start-Druck in kPa
Formeln:
T_nach = (T_vor × specificHeat + fuel × 563452) / (specificHeat + fuel × 172.615)
P_nach = P_vor × T_nach × (1 + 5.7 × fuel) / T_vor
Wobei:
fuel = min(ratioO2, ratioVolatile / 2)specificHeat= gewichtete Summe der Gas-Wärmekapazitäten- Vereinfachung: Fuel Ratio als einzelner Wert (0-1),
specificHeat(before)wird aus reinem Fuel berechnet (61.9 J/mol·K für 1:2 O₂:H₂ Mischung) - 563452 = Energie pro Mol bei 95% Effizienz
- 172.615 = 0.95 × (243.6 - 61.9)
Validierung:
- Warnung wenn Fuel < 0.05 (unter 5% Minimum)
- Warnung wenn Start-Druck < 10 kPa
Ausgabe:
T after ignition: X K (X °C)P after ignition: X kPa
7c: Solar / Batterie
Eingabefelder:
- Anzahl Panels (default: 12)
- Watt pro Panel (default: 500, Mond-Wert)
- Tag-Länge in Sekunden (default: 600)
- Nacht-Länge in Sekunden (default: 600)
- Verbrauch in Watt (default: 2000)
Formeln:
Generation = Panels × WattsPerPanel
Surplus = Generation - Consumption
NightEnergy = Consumption × NightLength (in Watt-Sekunden)
BatteriesNeeded = ceil(NightEnergy / 50000) (Station Battery = 50.000 Ws)
Ausgabe:
Generation: X WSurplus: X W(rot wenn negativ)Night Energy: X WsBatteries needed: X
7d: Atmosphäre / Gas-Mischer
Eingabefelder:
- Target Temperatur in Kelvin
- Gas 1 Temperatur in Kelvin
- Gas 2 Temperatur in Kelvin
Formel:
M1 = |T2 - T0| / (|T1 - T0| + |T2 - T0|)
M2 = 1 - M1
Ausgabe:
Mixer Input 1: X.X%Mixer Input 2: X.X%
Aufklappbare Wärmekapazität-Referenz:
| Gas | Cp (J/mol·K) |
|---|---|
| O₂ | 21.1 |
| H₂ | 20.4 |
| CO₂ | 28.2 |
| N₂ | 20.6 |
| H₂O | 72.0 |
| N₂O | 23.0 |
| Pollutant | 24.8 |
Sektion 8: UI, i18n und Widget-Sizing
Tab-Leiste
Horizontale Leiste direkt unter dem Widget-Header. Immer sichtbar (kein Scrollen).
| Tab | Icon | Label |
|---|---|---|
| Standard | 🔢 | Std |
| Scientific | 📐 | Sci |
| Converter | ⚖️ | Unit |
| Satisfactory | ⚙️ | SAT |
| Factorio | 🏭 | FAC |
| Stationeers | 🚀 | STA |
Aktiver Tab: border-bottom: 2px solid var(--accent), Text in var(--accent).
Inaktive Tabs: color: rgba(255,255,255,0.5).
CSS-Klasse: .calc-tab-bar und .calc-tab.
Widget-Sizing
- Standard-Modus Minimum: 280 × 400 px
- Komplexe Modi (Scientific, Game-Rechner): Auto-Resize auf 320 × 480 px (falls aktuell kleiner)
- User-Resize überschreibt Auto-Resize
- Widget-System-Minimum bleibt 200 × 150 px
i18n
Geschätzt ~100 neue Keys in STRINGS.de und STRINGS.en:
- 6 Tab-Labels
- 6 Kategorie-Namen (Converter)
- ~48 Einheiten-Langformen (Converter)
- ~30 Feld-Labels (Game-Rechner)
- ~10 Ergebnis-Labels
Einheiten-Abkürzungen (cm, kg, °C, kPa) werden nicht übersetzt.
Keyboard
- Standard-Modus: Bestehender Keyboard-Support (0-9, +, -, *, /, Enter, Backspace, Escape)
- Scientific-Modus: Gleicher Support +
p(Pi),^(Potenz) - Converter und Game-Modi: Kein Custom-Keyboard (native
<input>Felder)
Betroffene Dateien (Gesamt)
| Datei | Änderung |
|---|---|
src/js/calculator.js |
Tab-System, registerMode(), switchMode(), Parser-Erweiterung (^, sqrt) |
src/js/calc-scientific.js |
NEU: Scientific-Modus |
src/js/calc-converter.js |
NEU: Unit-Converter |
src/js/calc-satisfactory.js |
NEU: Satisfactory Calculator |
src/js/calc-factorio.js |
NEU: Factorio Calculator |
src/js/calc-stationeers.js |
NEU: Stationeers Calculator |
src/css/main.css |
Tab-Bar Styles, Mode-spezifische Styles |
src/js/i18n.js |
~100 neue Keys (DE + EN) |
newtab.html |
5 neue <script> Tags in Load-Order |
manifest.json |
Version → 2.1.0 |
manifest.firefox.json |
Version → 2.1.0 |
manifest.opera.json |
Version → 2.1.0 |
CHANGELOG.md |
v2.1.0 Eintrag |
Implementierungsreihenfolge
- Calculator Core — Tab-System, registerMode(), switchMode(), Tab-Bar CSS
- Parser-Erweiterung —
^Operator undsqrtFunktion - Scientific-Modus — Buttons, Formel-Helfer, Registrierung
- Unit-Converter — Kategorien, Einheiten, Konvertierungs-Logik, UI
- Satisfactory Calculator — 3 Sub-Modi, Formeln, UI
- Factorio Calculator — 3 Sub-Modi, Formeln, UI
- Stationeers Calculator — 4 Sub-Modi, Formeln, UI
- i18n — Alle neuen Keys (DE + EN)
- Version Bump — Manifests, CHANGELOG