RPGJS Studio
플레이 가능한 세계를 선택하고 지도·이벤트를 시각적으로 편집한 뒤 재생, 브라우저에서 무료 시작·RPGJS 소스 내보내기
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Gran Turismo 7 Balance of Performance radar for Gr.1, Gr.2, Gr.3 and Gr.4 cars — live at https://francmarra.github.io/bop-radar/
Every BoP update since version 1.15, with a verdict per car (buff / nerf / mixed) and a short performance context: which track type it suits (high-, mid- or low-speed BoP), strengths and weaknesses, estimated tyre wear and fuel use. Cars are ranked by real Daily Race pace, and a Daily Race guide shows the best cars for each race, from this week's live leaderboards when available. A balance index (how many cars really share the Daily Race top 100) rates each BoP update. English and Portuguese UI.
src/gt7bop/ — Python (stdlib only) pipeline: fetch → parse → build history → assess → JSONsite/ — static SPA source (vanilla JS, no build step) reading site/data/dist/ — deploy build: site/ + one pre-rendered page per URL (car/<id>/, update/<v>/, week/…), sitemap, share imagesdata/leaderboards/<board>.json — per-car pace aggregates of finished Daily Races (no player data)data/notes/<car-id>.toml — optional hand-written notes shown on a car's page (text = "...")data/car_images.toml — car id → GT7 car id, used to fetch the official car pictures at build timeapi/ — ASP.NET Core 9 read-only REST API over site/data (PostgreSQL, Docker, xUnit)web/ — React + TypeScript car comparator (Vite) on top of the API, see Car comparator (React)flowchart LR
subgraph sources[External sources]
GE[GT ENG!NE<br/>BoP pages]
LB[gtsh-rank.com<br/>Daily Race leaderboards]
end
subgraph action[GitHub Action, daily]
P[Python pipeline<br/>fetch → parse → build → assess]
C{gt7bop check}
end
GE --> P
LB --> P
P --> D[(site/data/*.json<br/>in git)]
D --> C
C -- ok --> R[render: pre-rendered pages,<br/>sitemap, share images]
C -- error --> I[action-alert issue]
R --> GP[GitHub Pages<br/>static SPA]
D --> IM[importer] --> PG[(PostgreSQL)] --> API[ASP.NET Core API<br/>/api/v1]
API --> W[React comparator<br/>types from OpenAPI]
The Python pipeline is the single source of truth; the site is static and free to host. The .NET API and the React comparator are an optional query layer on top of the same data and can be rebuilt from it at any time.
Recorded as short ADRs in docs/adr/:
Changes are summarised in CHANGELOG.md.
I built this project with an AI coding assistant (Claude Code), and most commits are co-authored by it. The workflow, the decisions and the review are mine:
docs/superpowers/specs/
that I review and approve (data sources, rules, what is out of scope).docs/superpowers/plans/
with explicit constraints and a "review focus" (e.g. an import from an empty folder must fail before touching the
database).fix: final-review … commits).gt7bop check.What I take from it: the assistant is fast at writing code, so the work that matters is specifying the problem, choosing trade-offs, and checking the result — which is what the specs, tests and ADRs here record.
uv sync
uv run gt7bop update # fetch missing pages, rebuild site/data
uv run gt7bop update --refresh # re-download the live pages (new game version)
uv run gt7bop update --offline # rebuild from cache only
uv run gt7bop leaderboards --pages 26 # aggregate the last ~52 weeks of Daily Races (incremental)
uv run pytest
py -m http.server -d site 8765 # quick dev: http://127.0.0.1:8765 (SPA only)
uv run --extra render gt7bop render --out dist --site-url http://127.0.0.1:8765/ # full build: pages, sitemap, share images
uv run --extra render gt7bop render --out dist --images # same, plus the official car pictures (see below)
py -m http.server -d dist 8765
uv run gt7bop images # map new cars to GT7 ids -> data/car_images.toml (prints the ones still unmapped)
uv run gt7bop evaluate # backtest the ranking on unseen Daily Races
uv run gt7bop check --baseline <old site/data> --max-age 2 # sanity checks the Action runs before committing data
The scheduled Action stops before committing or deploying when check finds broken, missing, shrinking or regressing
data (the live site keeps its last good data), and opens an action-alert issue on any failure or stale-data warning;
the next healthy run closes it.
| Output | Method |
|---|---|
| Rank / level | per class and BoP track type: real pace from Daily Race leaderboards on every layout of that type (≥ 2 layouts with ≥ 10 laps under the current BoP; same 70/30 blend as the per-track rating; unproven cars capped at the median), otherwise the model estimate; S top 10 %, A ≤35 %, B ≤70 %, C rest. PP rank is kept for reference |
| Verdict | average power-to-weight change over the BoP sets that changed: > +0.25 % buff, < −0.25 % nerf |
| Track fit | ½ PP rank + ½ the traits each track type rewards (PS/t, rotational G at 60/120/240 km/h, 100–150 km/h acceleration) |
| Strengths | top / bottom quarter of the group |
| Per-track rating | 70 % leaderboard pace on that layout (median of a car's best 20 laps vs. the event's 20 fastest, top 1000 laps; 6-month half-life, ×0.4 if the car's BoP changed since) + 30 % track-type fit; no data → fit × 0.85 |
| Tyre wear, fuel | heuristic estimates from weight, torque, drivetrain and power relative to the group |
uv run gt7bop evaluate predicts each Gr.3/Gr.4 Daily Race (≥ 8 matched cars) using only earlier races and BoP
changes already released at the time, then compares the predicted order with the real one (Spearman ρ):
| Ranking | mean ρ (40 events) | better in |
|---|---|---|
| Real-pace ranking (this site) | +0.25 | 65 % of events |
| PP under BoP (the usual proxy) | +0.14 | 35 % |
Rules (chosen up front, then checked against 17 alternatives — none scored higher): a layout counts as evidence with ≥ 10 laps under the car's current BoP; "real pace" needs ≥ 2 layouts; cars with no evidence are capped at the median real-pace score. Caveats: 40 events is a small, noisy sample; car model fit and PP ranks in the backtest are today's values, not the historical ones; in the top 1000 laps a few meta cars hold most laps, so many cars have little evidence. Deeper and older leaderboard data is the main lever for accuracy.
render --images, into the git-ignored cache/car-images/), converted to WebP inside dist/ and never
committed to this repository. Building without --images removes every picture (cars fall back to a neutral
silhouette) — that is the kill switch if the rights holder asks: drop the flag from the workflow.Tracked as issues and milestones:
MIT licence.
Read-only REST API over the generated data (ASP.NET Core 9, EF Core, PostgreSQL, Docker, xUnit):
Python pipeline → site/data/*.json → importer → PostgreSQL → ASP.NET Core API
cd api && cp .env.example .env && docker compose up
Then open http://localhost:8080 — /health, interactive docs at http://localhost:8080/docs, endpoints under /api/v1:
curl "http://localhost:8080/api/v1/cars?group=gr3"
curl "http://localhost:8080/api/v1/cars/155-2-5-v6-ti-93/history?set=m"
curl "http://localhost:8080/api/v1/compare?ids=155-2-5-v6-ti-93,963-24"
Tests (need Docker, they start PostgreSQL with Testcontainers):
dotnet test api
Local-only React + TypeScript app (web/, Vite) that compares 2–4 cars side by side using the API: best-value highlights
per stat and a PP-over-BoP-versions chart. Selection lives in the URL (?ids=…&set=m&version=…).
cd api && cp .env.example .env && docker compose up # API on http://localhost:8080
# in a second terminal (docker compose up keeps running in the first):
cd web && npm install && npm run dev # http://localhost:5173
API types are generated from the OpenAPI document (API running), and CI fails if the committed file drifts:
cd web && npm run gen:api
Tests:
cd web && npm test -- --run && npm run lint && npm run typecheck