factcircuit
FactCircuit는 불변 출처와 단계별 검증, 제한된 검색, 재현 가능한 평가를 제공하는 감사 가능한 주장·증거 검증 루프입니다
RippleTwin으로 도로 폐쇄가 교통·전차·버스·보행자에 미치는 파급 효과를 사전에 모델링
RippleTwin — model a road closure's ripple effects on traffic, trams, buses and pedestrians before the barriers go out. FEIT Hackathon 2026 · Challenge 5 (RPM Hire).
데이터JavaScript · PythonGitHub @Zemmeng온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Model the road closure before the barriers go out.
Team Uncapped · FEIT Hackathon Festival 2026 · Challenge 5 — RPM Hire, Future Cities: Digital Tool for Temporary Infrastructure
▶ Demo video (1 min 32 sec · 1080p60) · Live demo · Built: 29 Sep 09:30 → 1 Oct 12:00 AEST 2026 · Repo: publicREADME 전문 보기 ↗RippleTwin is a digital twin of the Melbourne CBD for temporary traffic management. A planner closes a lane on a real street, places the barriers, signs and variable message signs (VMS) they would actually hire, and sees the queue, the delay, where drivers detour and what it costs tram and bus riders and pedestrians, before any equipment goes out. A language model reads the signs the way four types of road user would, a deterministic engine in the browser computes the impacts from open data, and Eclipse SUMO cross-checks the main scenario on the real street network.
[!NOTE] Winner of the RPM Hire Prize at the FEIT Hackathon Festival 2026, Faculty of Engineering and Information Technology, University of Melbourne (Challenge 5, Future Cities: Digital Tool for Temporary Infrastructure). Built by Team Uncapped, five people, in about 50 hours from 29 September to 1 October 2026.
scripts/check.sh runs nine checks, from a secret scan and module boundaries to every module's tests (about 2,770 assertions, nothing to install), in the git hooks, in CI and before every deploy. (contributing)The workbench walks a planner through six steps.
| Step | What happens |
|---|---|
| 00 Overview | Pick a street on the map or one of the two demo plans, and see the real data behind the map. |
| 01 Configure | Close one lane or all lanes, choose the hour and the footpath treatment, write the VMS frames and static signs (checked against the sign-text rules as you type) and review the pre-simulation checks. |
| 02 Simulate | Watch the hour play out: a SUMO micro-simulation on the real street network for the Lonsdale demo plan; elsewhere, an in-browser junction animation with assumed signal timing. |
| 03 Impact | Queue, delay, detours, trams and buses, pedestrians, nearby works that clash, how each road-user type read the signs, and which inputs are real and which are assumed. |
| 04 Compare | Read the rule-based advisor's suggestions, then compare three equipment plans (A Minimum, B Standard, C Guided) side by side, with assumed hire costs and an optional plain-language explanation. |
| 05 Export | Choose a plan, record who decided and why, then print a one-page execution pack (equipment list, hire quote, VMS schedule, set-up checks, who to notify) or copy the response playbook. |
Everything is served from one origin. The browser loads the web app, the engine and the open data as static files and computes every engine number locally. The site Worker forwards /api/* to the API Worker (sign reading, plan explanation, worksite register) and, during the event, /api/sumo/* to the SUMO container. The code is split into eight modules, each owning one directory under apps/ with its own README and test.sh:
| Module | What it does | Owner |
|---|---|---|
engine | Deterministic traffic-impact engine: detours, route choice per road-user type, queues, tram, bus and pedestrian impacts, clash cost of overlapping works, equipment options and a rule-based advisor | @Zemmeng |
web | The six-step workbench: canvas map of the CBD, plan editor, simulation playback, impact, comparison and export | @unicornnnnnny |
api | Cloudflare Worker: LLM sign reading with keyword-rule fallback, number-checked plan explanation, worksite register, hire quote and execution pack | @jinmingq |
sumo | Eclipse SUMO in a Cloudflare Container behind a Worker proxy, the browser client and the pre-computed replays | @Zemmeng |
roads | Offline Python pipeline that turns open data into the CBD network, traffic flows, transit, footpaths, buildings, basemap and equipment inventory | @louisxie316-dotcom |
params | Behaviour and valuation parameters, each with a source, a range and a confidence rating | @Unzzip |
site | The single public origin: serves every module's public/ folder and routes /api/* through service bindings | @Zemmeng, @unicornnnnnny |
The architecture overview follows one plan from page load to export and records the key design decisions.
The main demo plan closes the right-hand lane of Lonsdale St westbound, near Swanston St, on a weekday from 08:00 to 09:00. About 1,140 vehicles an hour were counted on that link; with one lane closed, it is assumed to pass 810 an hour (1,800 veh/h × ½ × 0.9). The barriers, arrow board and static sign stay the same in every variant. Only the words on the VMS change.
Standard sign: ROADWORK AHEAD | One more frame: USE RUSSELL ST |
|---|---|
Engine (whole CBD network, one hour, sign readings from the pre-computed DeepSeek answers that ship with the site):
ROADWORK AHEAD | ROADWORK AHEAD ▸ USE RUSSELL ST | |
|---|---|---|
| Drivers who detour | 14% | 35% |
| Queue behind the works at 09:00 | 918 m | 538 m |
| Extra time per affected vehicle | 8.5 min | 4.0 min |
| Extra delay across the network | 10,493 vehicle-minutes | 5,629 vehicle-minutes (−46%) |
| Extra delay for tram and bus riders (15 routes, about 1,900 riders an hour at assumed loads) | 18,693 rider-minutes | 10,991 rider-minutes (−41%) |
SUMO (micro-simulation on the real street network around the works, seed 42, assumed signal timing; read from apps/sumo/public/real/index.json). It compares the original sign with the advisor's wording USE RUSSELL / SAVE 9 MIN, labelled "AI plan" on the page. The share of drivers who detour is an input to SUMO, taken from the engine's result for each wording when the run was made:
Original plan: ROADWORK AHEAD (14% detour) | AI plan: USE RUSSELL / SAVE 9 MIN (53% detour) | |
|---|---|---|
| Vehicles that detoured | 73 | 287 |
| Vehicles held up by the works at 09:00 | 278 | 87 |
| Physical queue on Lonsdale St at 09:00 | 246 m | 260 m |
| Vehicles past the works in the hour | 805 | 788 |
| Extra time per vehicle bound for the works | +533 s | +396 s |
| Extra time per vehicle, all traffic in the area | +38.6 s | +39.8 s |
How to read these numbers:
The page labels which is which, everywhere. No RippleTwin output has been validated against the observed outcome of real roadworks, so every queue, delay and detour figure is a model estimate.
apps/roads/tools/, and no data API is called at runtime.Details, the parameter confidence table and the full reference list (11 sources, each checked on 30 September 2026) are in assumptions and validation. Licences and attribution lines for every dataset are in data sources.
Prerequisites: Node.js 20 or later, Python 3.9 or later and git. Docker is needed only to build the SUMO container image. The tests need no installs at all, and the demo's only dependency, Wrangler, comes in through npm ci.
git clone https://github.com/Zemmeng/rippletwin.git
cd rippletwin
bash scripts/setup.sh # checks the tools, enables the git hooks, creates .env, then runs a quick check
Run the whole demo locally. The site Worker serves the page, the engine, the data, the pre-computed sign readings and the SUMO replays from one origin, exactly as in production:
cd apps/site && npm ci && npm run dev # → http://localhost:8790/web/public/
Sign wordings outside the pre-computed set are read by keyword rules in the browser. To serve /api/* as well, start the API Worker in a second terminal: cd apps/api && npm ci && cp .dev.vars.example .dev.vars && npm run dev. The example keeps MOCK=1, so no LLM is called.
Run the tests:
bash scripts/check.sh --quick # files and modules changed since origin/main; look for "======== Summary 0 ❌"
bash scripts/check.sh # full: all nine checks and every module's tests
bash apps/engine/test.sh # a single module
Optional: a real LLM. In apps/api/.dev.vars (copied from .dev.vars.example), set MOCK=0 and LLM_API_KEY to a key for DeepSeek or any OpenAI-compatible provider (LLM_BASE_URL, LLM_MODEL). The file is git-ignored. See re-enabling the LLM.
.
├── apps/ eight self-contained modules, each with README.md and test.sh
│ ├── engine/ traffic-impact engine (plain JavaScript, browser and Node)
│ ├── web/ six-step workbench UI (src/ → build.py → public/index.html)
│ ├── api/ Worker: sign reading, plan explanation, worksite register, execution pack
│ ├── sumo/ SUMO container service, browser client and pre-computed replays
│ ├── roads/ offline open-data pipeline → public/cbd/*.json
│ ├── params/ sourced behaviour parameters (public/params.json)
│ ├── site/ same-origin gateway Worker
│ └── sim/ first prototype: single-junction micro-simulation
├── docs/
│ ├── architecture/ overview, engine, sign reading, traffic simulation, front end, deployment
│ ├── reference/ module interfaces, data formats and HTTP API
│ ├── data/ data sources, assumptions and validation
│ ├── hackathon/ archive of the event: brief, plan, task board, specs, pitch, handoff notes
│ ├── images/ logos, screenshots, diagrams, award certificate
│ ├── decisions.md decision log with rejected alternatives
│ └── pitfalls.md problems hit during the build and how they were fixed
├── scripts/ setup.sh, check.sh (quality gate), secret-scan.sh, deploy.sh
├── .githooks/ pre-commit and pre-push hooks
├── .github/ CI workflows, CODEOWNERS, issue and pull request templates
├── hackathon.conf event metadata read by the scripts
└── CONTRIBUTING.md SECURITY.md NOTICE.md CITATION.cff LICENSE
Every module has a test.sh that needs no npm install and no network, and ends with the line N passed, M failed. Together they run about 2,770 assertions on small zero-dependency runners built on Node and the Python standard library. One script, scripts/check.sh, is the gate for every change: a secret scan, tracked secret files, branch and module boundaries, module structure, module tests, repository hygiene, the rules block in this README, handoff notes and hackathon.conf. The pre-push hook runs it in quick mode, GitHub Actions runs it in full on every pull request and push to main (with a self-test that proves each gate turns red when it should), and the deploy script runs it before every deploy. See the quality gate for each check and its escape hatches.
The hackathon is over. The project is complete as a demo and is maintained on a best-effort basis.
hackathon-site and hackathon-api Workers, with the build deployed on 1 October 2026. Later commits translate code comments, documentation and developer-facing messages into English without changing behaviour, so some API error messages on the live site are still in Chinese.hackathon-sumo Worker (/api/sumo/* now returns 502 sumo_down), and the DeepSeek API key (/api/health reports llm.mode: "rules").hackathon-final.How to bring SUMO back is in apps/sumo/README.md, and the full deployment picture is in deployment.
| Topic | Where |
|---|---|
| Documentation index | docs/README.md |
| Architecture | Overview · Traffic engine · Sign reading · Traffic simulation · Front end · Deployment |
| Reference | Module interfaces, data formats and HTTP API |
| Data | Data sources · Assumptions and validation |
| Decisions and lessons | Decision log · Pitfalls |
| The event | Hackathon archive · Submission notes |
Team Uncapped. Module ownership is recorded in .github/CODEOWNERS.
| Member | Role | Main work |
|---|---|---|
| @Zemmeng | Team lead, architect and integrator | Traffic engine, SUMO cloud service, same-origin site Worker, first junction prototype, wiring between the UI and the engine, LLM integration, CI and tooling |
| @unicornnnnnny | Front end and UI; designated deployer | The web workbench: CBD map, liquid-glass UI, full-CBD layer, six-step workflow, logo |
| @jinmingq | API and LLM module; pitch | Sign reader, API Worker, worksite register, plan explanation, hire quote and execution pack; comparison and export UI; 4×4 in-browser junction simulation; first native SUMO back end |
| @louisxie316-dotcom | Data engineering | Road network, SCATS flows, signals, PTV transit, walking network and pedestrian counts, buildings, equipment inventory; weather back-test |
| @Unzzip | Research | Behaviour parameters from the literature with confidence ratings; OpenStreetMap vector basemap; first English README and repository clean-up |
The team wrote the specs and made every product decision. AI coding assistants (Claude Code, OpenAI Codex) wrote much of the code, tests and documentation from those specs; how they were used is disclosed in the submission notes.
Team Uncapped won the RPM Hire Prize ($1,000) at the 2026 FEIT Hackathon Festival. RPM Hire sponsored Challenge 5, the challenge RippleTwin was built for.
Full attributions and licences are in NOTICE.md.
Bug reports, fixes and documentation improvements are welcome; open an issue before starting anything large. Three ground rules apply to every change:
main..env files or Wrangler secrets. Never in git, chat, issues or handoff notes; documentation names the variable, never the value.They are enforced by the pre-push hook, by check [3] with .github/CODEOWNERS, and by the pre-commit secret scan and CI. Setup, branch naming, commit format and the full checklist are in CONTRIBUTING.md; to report a vulnerability, see SECURITY.md.
The code is released under the MIT License, copyright 2026 Team Uncapped.
The data files derived from OpenStreetMap, apps/roads/public/cbd/network.json, walk.json, buildings.json and vectormap.json, are distributed under the Open Database License (ODbL) 1.0, not MIT: © OpenStreetMap contributors. Other datasets carry their own licences and attribution lines; see NOTICE.md.
If you use RippleTwin in your work, please cite it using the metadata in CITATION.cff; GitHub's "Cite this repository" button generates APA and BibTeX entries from it.
/api/* to the API Worker (KV cache, Durable Objects) through service bindings. There is no CORS, and the LLM key never reaches the browser. (deployment)sim| The team's first prototype: a micro-simulation of the Swanston St × La Trobe St junction on real counts |
| @Zemmeng |
| Modules | apps/README.md and each module's README |
| Contributing and security | CONTRIBUTING.md · SECURITY.md |