pgx
PGX — Lightweight Postgres for AI agents. Written in Rust. Thousands of isolated databases in one runtime. 🐘
Translation pending
Analyze War Thunder match logs to split battles by type and calculate RP goals
Translation pending
AI summary · website and README
DataJavaScript · HTMLGitHub @ApoloxDragonOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
⚠️ Development version. This is the Dev branch — used for testing in-progress changes before they reach the stable release. Features here may be incomplete, broken, or change without notice, and data-affecting bugs are more likely than on the stable version. For the stable release, use the main branch / production site instead. This project was built with the assistance of Claude (Anthropic). Code changes — including the parsing logic, bug fixes, and this README — were written collaboratively with Claude rather than entirely by hand.Read the full README ↗
This project is written almost entirely by AI (primarily Claude, by Anthropic), under the owner's guidance, review and corrections. That is intentional: AI-written code is welcome here — it is held to the same rules as any other contribution (see below), and the owner, Apolox, decides what ships. AI assistants working on the repository should read AGENTS.md; contributors should read CONTRIBUTING.md.
clientside suite) and enforced by the pages' Content-Security-Policy.example data/ come from Apolox (the project owner), from their own War Thunder matches; they are not anyone else's data. See example data/README.md.War Thunder and its names belong to their respective owners; this project is independent and unofficial.
A single-page, client-side tool for analyzing pasted War Thunder match-log text. Paste one or more match reports and it will:
Everything runs locally in the browser — no server, no account, no data leaves your machine (except when you explicitly export a file). The match archive is stored in your browser only (IndexedDB) and is never uploaded.
Live demo: https://apoloxdragon.github.io/WarThunder-Tool/
Two builds. The stable release (site, repo) and the dev build (site, repo), where in-progress changes are tried first, so expect rough edges there. They keep separate saved data in your browser.
Open wt-log-analyzer.html in a browser (or use one of the demos above). Keep it in the same folder as css/, javascript/ and dist/ if running locally — it loads its stylesheet and scripts as relative paths. (Opened straight from disk with file://, everything works except loading the example data, the offline cache and background compression (it falls back to the main thread); a local web server avoids all three.)
Paste one or more match reports — from "Victory/Defeat in the [Mode] ... mission!" through the "Session:" and "Total:" lines — into the text box and click Analyze. No local data? Click Load Example Data to try it with the sample log in example data/matches.txt (this only works on a server/hosted page, not when the file is opened directly from disk, since browsers block that fetch over file://).
Each match report ends with a line like:
Session: 73cba8e001d7c28
Total: 25493 SL, 7388 CRP, 14776 RP
The tool uses the CRP figure as "Total RP" for the match, not the trailing "RP" figure. That third field is CRP plus whatever "Researching progress" (a module on a different vehicle) earned in the same match added together — the same battle performance credited toward two research targets at once, not two separate payouts. Using it as-is would inflate every average and every "expected RP per match" figure in the goal calculator.
By default, anything with "Tank Assault" in its mode name is split into its own category; everything else falls into "Random Battles". Add your own keyword → label rules (e.g. for Arcade or event modes) via the "Battle-type categories" section.
.json.gz (small) — or .json from the Advanced view. This is the lossless backup: importing it rebuilds every summary and per-event detail from scratch, so an old export keeps getting richer as the parser improves..txt match logs. Raw files are re-parsed and validated on import; anything that isn't a recognisable match is ignored. Already-archived matches are skipped (matched by Session ID).Open it with Advanced view → in the top bar (advanced.html); ← Basic view takes you back. The two views share the same saved settings and archive.
Each match's raw text is gzip-compressed (native CompressionStream, no library) and stored in IndexedDB under its Session ID, together with a small summary. Because of that summary the Advanced view lists your whole library without unpacking a single match; a match is only decompressed when you open it, and the vehicle / event-type insights read the archive only when you open those sections. If IndexedDB is unavailable a small localStorage fallback (about 5 MB) is used, and if neither works the tool still runs — it just can't save detail. The Clear button only resets the current session; the archive is managed from the Advanced view's storage panel.
The archive exists only in your browser on this device: clearing site data deletes it and it doesn't sync. Export Raw regularly as your backup. The dev build uses its own database name, so it can't touch the stable site's data.
Pick one of eight colour presets with the swatches in the top bar — Blue, Amber, Slate, Forest, Crimson, Violet, Teal and the light Daylight — or open Customise… for the full panel (available in both views):
Everything applies instantly and is remembered in this browser — your saved look is applied before the page first paints, so reloading or switching between the Basic and Advanced views never flashes the default Blue; exported HTML reports use your colours. An optional tour ("? How this works" in the panel) explains each part. Design notes: docs/colour-customisation.md.
The tool reads text you paste or import, so nothing from a log or file is trusted:
<base> tags and form posts, and only allows this site's own files — so even a missed escape could not run code. Exported HTML reports carry their own policy with a fresh random nonce per export..gz import may unpack to at most 128 MB (a tiny "gzip bomb" is refused while unpacking, without being expanded). Real logs are far below all of these (longest line 175 characters, largest match 8.5 KB).constructor is just a name.Full user documentation — getting started, every feature, tips and tricks, troubleshooting, privacy, how it works — is in docs/. For a single page with a sidebar open docs/index.html (on the hosted site: the docs/ address next to the app). It is generated from the Markdown pages with node tools/build-docs.js; the test suite fails if it is out of date.
tests/ holds a Playwright-based suite (parser, Basic view, Advanced view, storage, security, colours, theme flash, offline, build, performance) plus a pre-change baseline recorded before the security and performance work, and a comparison report of the current code against it. See tests/README.md. The app itself stays dependency-free.
wt-log-analyzer.html Basic view markup
advanced.html Advanced view markup
css/styles.css Styling (both views)
dist/app-basic.js GENERATED bundle: the whole Basic view (do not edit; see Development)
dist/app-advanced.js GENERATED bundle: the whole Advanced view
dist/extras.js GENERATED bundle: colour panel, phone menu, tutorials, service-worker registration (loaded after the core)
sw.js GENERATED service worker (offline use, instant return visits)
tools/build.js The build: concatenates javascript/ into dist/, stamps ?v= hashes, writes sw.js
tools/sw.template.js Source of the service worker
assets/ Tab / touch icons (icon.svg is the source art; the PNGs are rendered from it) and the GitHub logo
javascript/load-guard.js Tiny ES5 guard: "still loading" / "part of this page didn't load" notes with a Reload button
javascript/archive-worker.js Web Worker: compresses / decompresses the archive and builds insight summaries off the main thread
javascript/sw-register.js Registers the service worker and offers "New version ready — Reload"
javascript/dev-mode.js Dev-site marker (banner, [DEV] title, dev icon, dev-repo link); loaded by appearance-core.js on the dev URL only
javascript/util.js Shared helpers: HTML escaping, limits, input sanitising (loaded first)
javascript/storage.js localStorage persistence helpers
javascript/appearance-core.js Look data (presets, validation) + applies the saved look; loaded in the <head>, before the stylesheet
javascript/themes.js Appearance state, readability maths, saved presets, swatches (builds on the core)
javascript/categories.js Battle-type category rules editor
javascript/detail-parser.js Per-match detail parsing (parseDetail), no DOM access
javascript/db.js Compressed raw-match archive (IndexedDB, localStorage fallback)
javascript/raw-export.js Raw export / import, shared by both views
javascript/parser.js Raw log parsing (parseLog)
javascript/math.js Pure stat/goal math, no DOM access
javascript/goal-calculator.js Goal calculator DOM wiring (Basic view)
javascript/import-export.js File import + HTML/JSON export (Basic view)
javascript/main.js App state, analyze() orchestration (Basic view)
javascript/advanced.js Library, match detail, insights, storage panel (Advanced view)
javascript/appearance-panel.js The Customise panel (colours, font, text size, my presets)
javascript/nav-menu.js Phone menu: folds the top bar behind a Menu button on narrow screens, with jump-to-section links
javascript/tutorial.js Step-by-step tutorials (both views + the colour panel)
AGENTS.md, CLAUDE.md Guidance for AI agents working on the repository
CONTRIBUTING.md, SECURITY.md How to contribute; how to report a security issue
tests/ Test suite, pre-change baseline and comparison reports (dev only)
docs/ User documentation (Markdown pages + generated single-page index.html) and the colour design record
tools/build-docs.js Builds docs/index.html from the Markdown pages
tools/make-chart-report.js Dev tool: makes the chart PDF (5 charts + glossary pages, docs/examples/) from a sample log, using the app itself; Spanish by default, `--en` for the English (watermarked) edition
example data/ Sample logs and exports for testing (all from the project owner, Apolox):
matches.txt raw match-log text (84 matches)
wt-session-data.json minimal export (summaries only)
wt-session-report-*.html HTML report export (201 matches, summaries only)
index.html Redirects to wt-log-analyzer.html (for GitHub Pages' root URL)
Still vanilla HTML/CSS/JS with no dependencies and no package.json, but the pages now load bundles (dist/) instead of ~15 separate scripts, because on a slow connection every file is a round trip (see the low-end report). The bundles are plain concatenations of javascript/*.js — nothing is minified or rewritten.
node tools/build.js # after editing anything in javascript/: rebuild dist/, the ?v= hashes in the HTML, and sw.js
node tools/build.js --watch # rebuild automatically while you edit
node tools/build.js --check # change nothing; exit 1 if dist/ is out of date (what the tests use)
Commit dist/ and sw.js with your change — GitHub Pages serves them as they are. The test runner rebuilds them first and the build suite fails if they were stale, so forgetting is caught. (The order of files in each bundle is in tools/build.js: classic scripts share one scope, so order matters.)
The service worker caches the app after the first visit so return visits are instant on any connection and the app works offline. It is off on localhost (so edits are never hidden behind a cache) unless you run localStorage.setItem('wtSessionReadout.enableServiceWorkerLocally','true') in the console. A new version installs quietly and waits; the page shows "A new version is ready — Reload" and nothing changes mid-session. It only touches its own site's caches (wt-tool- on the stable site, wt-tool-dev- on the dev site), so the two never clean up each other.
Stable and dev are told apart by the URL, not by the files. Both sites live on one origin (apoloxdragon.github.io), so a browser would share their storage. WT_DEV (in javascript/appearance-core.js) is true when the path contains /WT-Tool-Dev/; merging Dev into main therefore cannot turn the stable site into the dev one, or the reverse. The dev site uses its own localStorage keys (wtSessionReadoutDev.…), IndexedDB database (wtSessionReadoutDev) and service-worker caches, and adds a banner, a [DEV] tab title, a red-cornered icon and a link to the dev repo (javascript/dev-mode.js, which only the dev site loads). Stable keeps the original names, so saved data stays put. To move data between them, use the raw export / import in the Advanced view.
Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) — see LICENSE.