Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證開源 iRacing 賽季行事曆與排程器。瀏覽所有系列,依類別篩選,並檢查您擁有的賽道以規劃您的賽季。加入您的內容以查看在單一賽季錦標賽中有多少賽道符合資格。
AI 翻譯
Open-source iRacing season calendar and scheduler. Browse all series, filter by category, and check which tracks you own to plan your season. Add your content to see how many tracks are eligible in one season tournament.
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
A Next.js web application for browsing iRacing season schedules. Includes a PDF extraction script to generate structured data from official iRacing season PDFs.
Open http://localhost:3000 to view the calendar.
Use the extraction script to convert an iRacing season PDF into the JSON data file:
The script parses the PDF, extracts series and track data, and writes iracing-season-data.json to the project root. The app reads this file at build time.
Keeping the calendar up to date (automatic)檢視完整 README ↗A Next.js web application for browsing iRacing season schedules. Includes a PDF extraction script to generate structured data from official iRacing season PDFs.
npm install
npm run dev
Open http://localhost:3000 to view the calendar.
Use the extraction script to convert an iRacing season PDF into the JSON data file:
# Basic usage
node extract-season-data.js path/to/iracing-season.pdf
# Custom output path
node extract-season-data.js path/to/iracing-season.pdf --output data/custom-output.json
The script parses the PDF, extracts series and track data, and writes iracing-season-data.json to the project root. The app reads this file at build time.
data/iracing-season-data.json is refreshed automatically from the official
iRacing season schedule PDF, which iRacing publishes at a stable, public,
unauthenticated URL:
https://members-assets.iracing.com/public/schedulepdf/SeasonSchedule.pdf
The filename contains no season, so the same URL always serves the current one — the calendar rolls over on its own when a new season starts. No iRacing credentials are involved.
# Download, parse, validate, and update the data file if anything changed
npm run sync-pdf
# See what would change without writing
npm run sync-pdf -- --dry-run
# Parse a PDF you already have
npm run sync-pdf -- --pdf path/to/SeasonSchedule.pdf
.github/workflows/update-season-data.yml runs this daily and commits the data
file when it changes.
Because PDF parsing is more brittle than a JSON API, sync-season-pdf.js
refuses to write when the result looks wrong — too few series, series with no
schedule, unparseable dates, a sudden collapse in series count, or a season
that moves backwards. A layout change fails the workflow loudly instead of
committing a broken calendar.
The canonical source of truth for series and schedules is the official
iRacing Data API. sync-season-data.js can
pull the current season directly from it instead of parsing a PDF by hand.
Heads up — OAuth required. iRacing retired legacy username/password authentication with the 2026 Season 1 release (2025-12-09); the old
members-ng.iracing.com/authendpoint now returns HTTP 405. API access now requires an OAuth2 client (client_id+client_secret) registered at oauth.iracing.com/accountmanagement. iRacing has temporarily paused issuing new client IDs while they review third-party usage. This path is therefore dormant — the project syncs from the public schedule PDF instead, which needs no credentials.sync-season-data.jsis kept ready for the day registration reopens.
# Fetch the current season and update data/iracing-season-data.json if changed
IRACING_CLIENT_ID=... IRACING_CLIENT_SECRET=... \
[email protected] IRACING_PASSWORD=secret \
npm run sync-data
# Just check whether anything changed (no write)
npm run sync-data -- --dry-run
# Transform a previously-saved API response (no credentials needed — handy for testing)
npm run sync-data -- --from-json path/to/series-seasons.json
How it works:
password_limited grant against
POST https://oauth.iracing.com/oauth2/token. Secrets are never sent in
clear text — each is masked as base64(sha256(secret + id)) (the
client_secret with the client_id, the password with the email).GET /data/series/seasons?include_series=true (and /data/carclass/get
for car names) with the resulting Bearer token, following the signed S3
link each endpoint returns..github/workflows/update-season-data.yml no longer uses this path — it syncs
from the public PDF instead. To switch back once you have a client, set these
repository secrets (Settings → Secrets and variables → Actions) and point the
workflow's sync step at sync-season-data.js:
| Secret | Description |
|---|---|
IRACING_CLIENT_ID | OAuth client id |
IRACING_CLIENT_SECRET | OAuth client secret |
IRACING_EMAIL | iRacing account email |
IRACING_PASSWORD | iRacing account password |
Because iRacing announces the reopening only on their forums and in release
notes, .github/workflows/watch-iracing-oauth.yml polls the two doc pages that
carry the pause notice every Monday and opens an issue when the notice
disappears. Run it by hand any time:
npm run check-oauth
Exit codes: 0 still paused, 3 notice gone (may be open), 1 indeterminate
(page moved or unreachable). The check is text-based, so confirm on
oauth.iracing.com/accountmanagement
before acting — iRacing may simply have reworded the page.
Normally you don't need this — npm run sync-pdf fetches the current PDF for
you. Use this only to parse a PDF the public URL doesn't serve (an older
season, or a copy from the forums):
npm run extract-data -- path/to/season.pdfdata/iracing-season-data.jsonNote this writes the data file directly, with none of the validation guards
sync-season-pdf.js applies.
iracing-calendar/
├── extract-season-data.js # PDF parsing script
├── iracing-season-data.json # Generated season data (committed)
├── src/
│ ├── app/
│ │ ├── layout.tsx # Root layout
│ │ ├── page.tsx # Series list (home page)
│ │ ├── not-found.tsx # 404 page
│ │ ├── globals.css # Global styles
│ │ └── series/
│ │ └── [id]/
│ │ └── page.tsx # Series detail page
│ ├── components/
│ │ ├── Header.tsx # Navigation header
│ │ ├── Footer.tsx # Page footer
│ │ ├── SearchBar.tsx # Search input + category filters + view toggle
│ │ ├── SeriesCard.tsx # Individual series card (grid & list)
│ │ ├── SeriesList.tsx # Series grid/list container
│ │ └── SeriesDetail.tsx # Full schedule view for a series
│ └── lib/
│ ├── types.ts # TypeScript type definitions
│ ├── data.ts # Data loading and filtering
│ └── utils.ts # Date formatting, week status, colors
├── package.json
├── next.config.ts
├── tsconfig.json
└── tailwind.config.ts (if present)
| Command | Description |
|---|---|
npm run dev | Start development server |
npm run build | Build for production |
npm start | Start production server |
npm run lint | Run ESLint |
npm run extract-data -- <pdf> | Extract data from a season PDF |
npm run sync-data | Sync data from the official iRacing Data API |