Skip to content

D0bledore/code-math

Repository files navigation

Learning Exercise Generator

An interactive web-based exercise generator for students, covering Math and Physics problems with real-time scoring.

Usage

Web App

Open index.html in a browser to see the dashboard. Choose Mathe-Übungen or Physik-Übungen. A random problem appears — type your answer, press Enter (or click Prüfen) to check it, then press Enter again for the next problem. Your score updates after each attempt.

Legacy CLI

python logic.py

The original Python version is kept for reference. Press Enter for the next problem, type q to quit.

Problem Types

Math

Type Description Example
add 4-digit addition 3456 + 7891 =
sub Subtraction (positive results) 12000 − 3500 =
mul 3-digit × single digit 456 × 7 =
div Division (whole number results) 1440 ÷ 12 =
dec_add Decimal addition 12.45 + 8.32 =
dec_sub Decimal subtraction 25.67 − 4.23 =
dec_mul Decimal multiplication 5.5 × 3.2 =
dec_div Decimal division 45 ÷ 2.5 =
frac_add Fraction addition 3/4 + 2/5 =
frac_sub Fraction subtraction 7/3 − 2/5 =
dreisatz Direct proportion (Rule of Three) 5 Äpfel kosten 15€. Was kosten 8 Äpfel?
dreisatz_inv Inverse proportion 4 Arbeiter brauchen 6 Tage. Wie viele Tage brauchen 3 Arbeiter?
umrechnung Unit conversion (length, weight, volume, time) Rechne 3500 g in kg um.

Physics — Ohmsches Gesetz (Ohm's Law)

Type Given Find Example
ohm_u R (Ω), I (A) U (V) R = 47 Ω, I = 2,5 A. Berechne U.
ohm_r U (V), I (A) R (Ω) U = 120 V, I = 3 A. Berechne R.
ohm_i U (V), R (Ω) I (A) U = 230 V, R = 46 Ω. Berechne I.

Project Structure

code-math/
├── index.html              # Dashboard (landing page)
├── math.html               # Math exercises page
├── physics.html            # Physics exercises page
├── style.css               # App styling (shared)
├── js/
│   ├── problems.js         # Math problem generation, answer checking, formatting
│   ├── app.js              # Math UI event handling and state management
│   ├── physics-problems.js # Physics problem generation, answer checking, formatting
│   └── physics-app.js      # Physics UI event handling and state management
├── tests.html              # Browser test page
├── run-tests.js            # Server-side test runner (Node.js)
├── logic.py                # Legacy Python CLI version
└── package.json            # NPM config

API Reference

MathProblems module

js/problems.js exports three functions via the MathProblems global:

generateTask()

Returns an object with:

Field Type Description
display string Problem text ending with = or ? (word problems)
hint string Hint for fraction and Dreisatz problems (empty string otherwise)
type string One of the 13 problem types listed above
answer number or {num, den} Correct answer (fraction object for frac_* types)
isFraction boolean true for frac_add / frac_sub
answer number or {num, den} For Dreisatz: always a whole number

checkAnswer(answer, isFraction, userStr)

Returns boolean — whether the user's input is correct.

Parameter Type Description
answer number or {num, den} The correct answer from generateTask()
isFraction boolean Whether the problem is a fraction type
userStr string The user's raw input

Key behaviors:

  • Decimal inputs: both , and . are accepted as decimal separators
  • Numeric tolerance: answers within ±0.005 of the correct value are accepted
  • Fraction equivalence: checked via cross-multiplication (uNum * answer.den === uDen * answer.num), so any equivalent fraction is accepted (e.g. 6/8 for 3/4)
  • Rejects empty/whitespace-only input, non-numeric text, and zero denominators

formatAnswer(answer, isFraction)

Returns string — the answer formatted for display.

  • Numbers: converted to string directly
  • Fractions: reduced to lowest terms using GCD (e.g. {num:6, den:4}"3/2")

Features

  • Dashboard landing page with subject selection (Math / Physics)
  • German-language UI
  • Real-time scoring (Richtig/Falsch counter)
  • Keyboard support — Enter to submit answer or advance to next problem
  • Comma and dot decimal separators accepted
  • Fraction equivalence checking (any equivalent fraction is correct)
  • Hints for fraction problems ("Antwort als Bruch"), Dreisatz problems ("Antwort in €" / "Antwort in Tagen"), unit conversions ("Antwort in km" etc.), and physics problems ("Antwort in V" / "Antwort in Ω" / "Antwort in A")
  • Answers auto-reduced to lowest terms on display
  • Back navigation from exercise pages to dashboard

Ensuring Valid Results

Subtraction: The first operand (5000–15000) is always larger than the second (1000–4999), preventing negative results.

Division: The dividend is adjusted with a = a - (a % b) to guarantee whole number results.

Fraction Subtraction: Operands are compared and swapped if necessary to ensure non-negative results:

if (num1/den1 < num2/den2) {
    // swap (num1,den1) with (num2,den2)
}

PhysicsProblems module

js/physics-problems.js exports three functions via the PhysicsProblems global, following the same interface as MathProblems:

generateTask()

Returns an object with display, hint, type, answer, isFraction (always false).

Generation ensures clean answers:

  • ohm_u: R and I are generated directly, U = R × I
  • ohm_r: R (integer) is chosen first, I is generated, U = R × I is computed. Given U and I, the student solves for R (always a whole number)
  • ohm_i: I (1 decimal) is chosen first, R is generated, U = R × I is computed. Given U and R, the student solves for I (at most 1 decimal place)

checkAnswer(answer, isFraction, userStr)

Same tolerance-based approach as MathProblems (±0.005), accepts both comma and dot decimal separators.

formatAnswer(answer)

Returns the answer as a plain string.

Design Decisions

Decimal Division

Generated by computing the answer first, then deriving the dividend:

var ans = randFloat(2, 20, 1);           // Clean answer: 2.0–20.0
var b = randFloat(0.5, 5, 1);            // Divisor: 0.5–5.0
var a = parseFloat((ans * b).toFixed(2)); // Dividend = answer × divisor

This guarantees every problem has an exact, mentally-computable answer (e.g., 15.5 ÷ 2.5 = 6.2).

Dreisatz (Rule of Three)

Direct proportion (dreisatz): Generates word problems where more items cost proportionally more. The price per item is generated first, ensuring whole number answers:

var pricePerItem = randInt(2, 10);
var b = a * pricePerItem;  // Total cost is always a multiple
answer = c * pricePerItem; // Answer is always whole

Inverse proportion (dreisatz_inv): Generates word problems where more workers means fewer days. Total work-days is computed first, and the target worker count is chosen to divide evenly. The initial worker count b must differ from a to guarantee a valid c exists:

var bVal = randInt(2, 8);
while (bVal === a) bVal = randInt(2, 8);  // Ensure b ≠ a
var totalWork = a * bVal;
while (totalWork % c !== 0 || c === a) c = randInt(2, 8);  // Ensure clean division
answer = totalWork / c;

Testing

node run-tests.js

71 tests across 9 suites. See TESTS.md for details.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors