There’s a desktop application called DeLCoPA — the Desert Locust Contingency Planning Assistant. It helps national and regional actors in North Africa and the Middle East assess their readiness to respond to desert locust outbreaks. It evaluates organizational components, risk prevention, preparedness, and control capacity through a guided questionnaire powered by a fuzzy logic engine.

It’s written in Delphi. It runs on Windows. The people who need it are in the field, often with tablets and unreliable internet. It needed to become a web app.

The constraints

Offline-first. This isn’t a nice-to-have. Field workers in the Sahel can’t count on connectivity. The app must work entirely offline and sync when a connection becomes available.

Three languages. English, French, and Arabic — with full RTL layout support for Arabic. Every label, question, help text, and result explanation exists in all three languages.

Identical results. The fuzzy logic engine produces confidence scores that inform real planning decisions. The web version must produce the exact same numbers as the desktop version for the same inputs. There’s no room for “close enough.”

One developer. The developer has decades of Pascal experience. A TypeScript rewrite would mean learning a new language while simultaneously porting 35,000 lines of mathematical logic. Node.js was ruled out — it can’t run offline.

TMS Web Core was the only viable path: compile the existing Pascal to JavaScript that runs in the browser.

The engine

NWEng (NetWeaver Engine) is the computation core — 35,000 lines of Pascal implementing a probabilistic reasoning system. Think of it as a directed graph where:

  • Variable nodes accept user input (discrete choices or fuzzy values)
  • Calculated nodes combine inputs through operators (fuzzy AND/OR/NOT, math, comparisons)
  • Goal nodes produce the final assessments
  • Every value carries a data quality metric (0.0 to 1.0) that propagates through the chain

The engine uses lazy evaluation with dirty flags. Change one input and only the downstream nodes recalculate. It’s elegant, mathematically rigorous, and deeply dependent on Delphi-specific features like pointer-to-integer casts, binary stream serialization, and an embedded JavaScript interpreter (BESEN) for dynamic scripting.

All of which are illegal in pas2js, the transpiler that TMS Web Core uses.

The compilation campaign

Getting the engine to compile was a multi-session battle against hundreds of errors. Each one required understanding whether the failing code was essential to the web target or could be guarded out with {$IFNDEF WEBLIB}.

Enums with explicit values. The engine uses an enum (NW_NodeCodes) as binary format identifiers. pas2js rejects explicit enum values. The entire enum — dozens of entries — had to be converted to an Integer type with a const block. Mechanical but error-prone.

Pointer-to-integer casts. The undo/clipboard system stored object pointers as Longint, then cast them back. In native Delphi, this is a common pattern. In pas2js (which compiles to JavaScript where objects are references, not memory addresses), it’s meaningless. Every cast required a WEBLIB guard.

Binary serialization. The knowledge base (.nw2 file) is a compressed binary stream. The desktop app reads it with Delphi file streams. The web version fetches it via HTTP, decompresses with pako.js, and parses the binary with a custom stream reader. Same format, completely different plumbing.

The embedded JavaScript engine. NWEng includes BESEN, a Pascal implementation of ECMAScript, for dynamic scripting within knowledge bases. In the browser, this is redundant — JavaScript is native. The entire BESEN integration (hundreds of lines) was stubbed out for WEBLIB.

The UI

Once the engine compiled, the UI was built as a single-page Bootstrap 5 application in about 1,200 lines of Pascal:

  • Home page with module cards showing completion percentages
  • Three-column analysis layout: variable list sidebar (sorted by influence on current results), center panel for questions and results, right panel for data entry
  • Guided data entry: questions ranked by which answer would most change the assessment, with numbered choice buttons and skip/clear options
  • Results display: color-coded cards with progress bars, sorted weakest-first, with explanatory text
  • Session management: save/load as JSON, import historical sessions

The Arabic RTL support required careful CSS — direction: rtl on the body, mirrored margins and paddings, right-aligned text. Bootstrap handles most of it, but custom components needed manual attention.

The content pipeline

DeLCoPA’s content is 2,261 files — text files, INI configurations, TSV data structures, HTML documentation, images. A Python script (export_content.py) reads the content folders and generates a single texts.json with 953 entries across three languages.

The knowledge base binary is served as a static file, fetched and decompressed on load. No server-side processing required — the entire application runs client-side.

The validation question

How do you prove that 35,000 lines of transpiled fuzzy logic produce the same results as the native version? We extracted 74 historical sessions from the desktop app’s SQLite database, loaded each one into the web version, and compared the output scores. The same inputs produce the same confidence percentages, data quality metrics, and goal rankings.

The engine is mathematically correct across the compilation boundary. That’s the sentence that justified the entire effort.

The outcome

The app is deployed as a demo and works offline as a PWA. The developer can show it to field coordinators on a tablet with no internet connection. The same Pascal source compiles to both the Windows desktop app and the browser version. Changes to the engine propagate to both targets.

As a bonus, the engine was also packaged as two standalone JavaScript libraries — a read-only version (3.5MB) and a full read-write version (3.6MB) — that can be embedded in any web application. The knowledge engine that started as a Windows-only Delphi library now runs anywhere JavaScript does.