The consistency problem.
A numerical teaching tool can look convincing while two implementations quietly disagree about interval counts, signed area or invalid functions. IntegraDraw had a Java desktop history and needed a modern browser edition without turning them into unrelated calculators.
The rebuild makes the mathematical contract explicit: exactly the requested number of intervals, signed results, visible approximation error and clear rejection of non-finite inputs.
What both runtimes must agree on.
The interface is useful only when the numerical rules stay stable:
- Midpoint and trapezoidal methods use exactly the segment count entered by the user.
- Negative area remains negative instead of being silently converted to geometric area.
- The comparison value is labelled a Simpson reference, never an exact symbolic result.
- The browser expression parser must not use eval or Function.
A contract above the implementation.
Sharing source code between Java and TypeScript would create an awkward runtime bridge without proving much. Sharing expected behaviour is the more useful boundary.
I introduced a versioned golden corpus consumed by JUnit and Vitest. Runtime-specific tolerances and limits remain explicit, so a mismatch cannot disappear behind a generic loose equality helper.
Two interfaces, one numerical record.
The Java application packages a Swing interface and numerical core in an executable JAR. The web application uses a dependency-free expression parser, TypeScript integration routines and a responsive Canvas plot. Both verify against the shared corpus.
Decisions that improve mathematical clarity.
The workbench labels approximation as approximation.
Use a bounded expression language
The browser accepts x, constants, arithmetic, parentheses and a documented set of functions through its own parser.
It is safer and easier to reason about than arbitrary JavaScript, but deliberately less expressive.
Name the reference correctly
The web comparison uses composite Simpson’s rule with 8,192 subintervals and calls it a reference rather than an exact result.
Some discontinuous or non-finite functions are rejected; the project is not a symbolic proof system.
Cross-check observable behaviour
Java and TypeScript tests consume the same versioned cases while keeping their numeric tolerances visible.
The corpus must evolve deliberately whenever the supported mathematical contract changes.
Packaging both applications.
CI compiles Java 17, runs JUnit, packages and smoke-tests the executable JAR, then type-checks, tests and builds the TypeScript application. Release candidates also include the web bundle and SBOMs for both runtimes.
Publication compares independent builds, validates dependency inventories and checks SHA-256 manifests and GitHub attestations before making a stable release visible.
What the workbench makes visible.
Users can change a function, interval and segment count, then see how midpoint and trapezoidal estimates relate to the plotted curve and Simpson reference.
The desktop and web applications remain useful independently, while the shared corpus gives maintainers one place to review the numerical behaviour they promise.
Evidence ledger.
The numerical contract is small enough to enumerate:
- Golden corpus
- Six integral cases, three invalid-expression cases and seven validation cases under schema version 1.
- Verification
- 22 JUnit and 80 TypeScript test declarations in the audited release.
- Reference
- The browser’s composite Simpson comparison uses 8,192 subintervals.
- Boundary
- The reference is not exact; discontinuities and non-finite expressions can be rejected, and runtime limits intentionally differ.