Skip to content
master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
bin
 
 
 
 
 
 
 
 
 
 
 
 

WCA Live


Platform for running WCA competitions and sharing live results with the world.

Actions Status Actions Status

Introduction

Welcome to the WCA Live repository! Here you can find all the source code that helps to run hundreds of official WCA competitions a year. Check out the About page for more background information on where and how this platform is used.

The app is focused on the administrative side of competitions (round management, entering results, calculating ranking, proceeding competitors from round to round), as well as the presentation side (displaying round rankings, records, podiums, real-time updates as results get entered).

Design

Briefly speaking, WCA Live is a WCA-integrated application composed of a web client and a GraphQL API server with a relational database behind, deployed with Nginx on top and using Docker. Let's break it down.

WCA Integration

First of all we use OAuth2 offered by the WCA website, so that users authenticate with their existing WCA accounts. This plays an important role when it comes to granting users access to administrative competition tasks, as we can check if the given user is a delegate, organizer or another staff member at the given competition.

Now to the crucial integration element - data synchronization. At the WCA we developed a standardized format for exchanging competition data between tools/systems, it's called WCIF (WCA Competition Interchange Format) and defines a huge JSON object that contains all relevant competition information (events, rounds, schedule, competitors, results, etc.). The idea behind it is to have a well defined data format and empower developers to build tools working with this data (more on that in the vision document). The WCA website offers endpoints for fetching and saving data in this format and that's exactly what WCA Live uses. When a delegate/organizer imports a competition into the app, we fetch WCIF data for this competition and save all of it into the database. Later, competition admins can trigger synchronization, which works both ways: gets new data from the WCA website saving changes to the local database, and also sends local changes (like results) to the WCA website. Think of the WCA website as the source of truth that many tools read from and save data to. Thanks to this approach delegates/organizers don't have to enter redundant competition information into WCA Live and can also use/build additional tools to help them run their competitions.

Server

The server exposes a GraphQL API allowing the client to fetch the necessary subset of data and subscribe to real-time updates. It is also responsible for authenticating users with WCA OAuth and generating some PDFs. Under the hood it often makes requests to the WCA API in order to fetch/save WCIF data, to get regional records or to list competitions that the current user may import. It also uses a relational database as a primary source of data. See the corresponding README for more details.

Database

The app uses a relational database, specifically PostgreSQL. A bunch of information comes from the WCA website and is fetched during competition import. We get the data in a heavily nested WCIF format and we decompose it into relevant tables. Some objects are an inherent part of their parent object, in which case we just store them in a JSON column (e.g. time limit, cutoff and advancement condition in the rounds table).

Client

The client is a web application built with React. It talks to the server via the GraphQL API, this way it always fetches the necessary subset of data in a single web request. It leverages a library called Apollo that provides a number of valuable features, from basic ones like React hooks for querying/mutating data, to more sophisticated ones like configurable cache with clever updates. The app comes with a basic Service Worker caching static resources, which allows it to be installed as a desktop/mobile application. See the corresponding README for details.

Deployment

Currently we use a single AWS EC2 instance for hosting the app and a RDS instance with the database. To set up a fresh instance we use this tiny script that basically installs Docker and fetches the app. Images for the individual components are hosted on DockerHub and built automatically. We have an automated GitHub Actions workflow that builds the images, pushes them to DockerHub and finally tells the the app to pick up the new images.

In production we use the Nginx web server to serve all the static files, handle TLS and proxy API requests to the Elixir app. The corresponding Docker image handles obtaining an SSL certificate and renewal. It also includes all the custom Nginx configuration that scores A+ in the SSL Labs test. See the corresponding README for details.

Development

There are two options when it comes to setting up your development environment. The Docker based one boils down to running a single command and is most likely what you want, especially when getting started.

Docker based setup

Make sure you have Docker and Docker Compose installed. If you're running Ubuntu/Debian have a look at the production setup script, which contains instructions to install both of these.

To start all the services just run the following Docker Compose command:

docker-compose -f docker-compose.dev.yml up

This starts the client, server and database on ports 3000, 4000 and 5432 respectively. Make sure those ports are free on your machine, so that Docker can bind the relevant services to them. Running it for the first time builds the docker images and installs all dependencies, so it may take a while. Subsequent runs should be relatively quick.

Once everything is up and running you should be able to access the app at localhost:3000.

Having the containers running you can easily execute custom commands inside them, just as you'd do on your machine. A few examples:

# Executing commands in running containers takes the following form:
docker-compose -f docker-compose.dev.yml exec SERVICE COMMAND

# Run client tests
docker-compose -f docker-compose.dev.yml exec client npm test

# Run server tests
docker-compose -f docker-compose.dev.yml exec server mix test

# Run the interactive Elixir shell with all the application modules loaded
docker-compose -f docker-compose.dev.yml exec server iex -S mix

# Run the database shell
docker-compose -f docker-compose.dev.yml exec database psql -U postgres wca_live_dev

Manual setup

This option provides more control over the individual parts, but takes more time to set up and is less reproducible than the Docker based one. Follow the client and server READMEs respectively.

OAuth during development

In the development environment, instead of interacting with the real WCA server we talk to the staging server. It's similar to the production one, but used for testing purposes. In particular there is no sensitive data and every user has the password of wca, so you can sign in as whoever you want.

To have a competition to work on, find an upcoming one with some registered competitors, then sign in as one of the delegates/organizers and import the competition under My competitions.

About

Platform for running WCA competitions and sharing live results with the world

Resources

Contributors 4

  •  
  •  
  •  
  •