Skip to content

Repository files navigation

ABW HeatMath

A Node.js application for setting LiveHeats round durations from the athlete count in each heat.

The browser renders the interface and calls same-origin /api routes. OAuth authentication, access tokens, GraphQL event queries, calculations, validation, and mutations are handled by the Node server.

Requirements

  • Node.js 20 or newer
  • LiveHeats API client credentials with the required permissions

Run with Docker

With Docker Desktop or Docker Engine and the Compose plugin installed:

docker compose up -d

During the image build, the current Git commit is appended to the local CSS and JavaScript URLs as ?v=<commit>. This invalidates previously cached assets after each committed deployment. The build stage reads .git, but Git metadata is not copied into the final image.

Open http://localhost:3000.

Useful commands:

docker compose logs -f
docker compose down

To expose the application on a different host port:

$env:PORT=8080
docker compose up -d

Then open http://localhost:8080.

The Compose file defaults the public origin to https://heatmath.abw.com.br. To deploy on a different domain, override it:

$env:APP_ORIGIN="https://heatmath.abw.com.br"
docker compose up -d

APP_ORIGIN may contain a comma-separated list when more than one public origin is required. The server also recognizes X-Forwarded-Host and X-Forwarded-Proto from a trusted reverse proxy.

Run locally

npm install
npm start

Open http://localhost:3000.

For automatic server restarts while developing:

npm run dev

Set a different port with the PORT environment variable.

Server API

  • POST /api/connect authenticates with LiveHeats and starts an HTTP-only server session.
  • GET /api/organisations/:shortName/events loads organization details and returns events with scheduled/published events first, then all other statuses; each group is sorted by descending date.
  • GET /api/events/:eventId loads the event, divisions, heats, competitor counts, and configured heat sizes.
  • POST /api/events/:eventId/apply-durations reloads the event, independently validates the requested minutes-per-athlete calculation, applies every eligible round update sequentially, and returns the refreshed event.

LiveHeats behavior

  • OAuth uses https://liveheats.com/oauth/token.
  • GraphQL uses https://liveheats.com/api/graphql.
  • The requested scopes are public events/director organisations/manage.
  • LiveHeats exposes duration changes through updateRound. When athlete counts differ within a division/round, ABW HeatMath calculates each heat's time, averages those times, rounds to the nearest whole minute, and applies that shared duration to every heat in the round. When a future heat has no placed athletes yet, its configured LiveHeats heat size is used instead. An empty heat only blocks the operation when it also has no valid configured size.
  • Event selection uses organisationByShortName; the organization short name defaults to cbeaw and can be changed in the interface.

Security and deployment

  • Client credentials and access tokens are held only in server memory.
  • The browser receives an opaque, HTTP-only, SameSite session cookie.
  • Sessions expire after two hours and disappear whenever the server restarts.
  • State-changing routes reject cross-origin browser requests.
  • API responses never include credentials or access tokens.
  • In production, run the app behind HTTPS and set NODE_ENV=production.
  • Session cookies automatically use the Secure flag when the request arrives over HTTPS. The server trusts one reverse-proxy hop, so an HTTPS proxy should forward X-Forwarded-Proto.

This in-memory session store is appropriate for a small, single-instance operations tool. For multiple Node instances, replace it with a shared encrypted session store.

About

Ferramenta para calcular duração de baterias no LiveHeats baseado no número de atletas

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages