diff --git a/README.md b/README.md index 7c28e16..4213c58 100644 --- a/README.md +++ b/README.md @@ -1,267 +1,91 @@ -# Dash - Marvin +# Dash Competition Framework -## Overview - -**Dash** is a Go-based framework designed to facilitate the launch and management of programming competitions. It automates repository creation, manages participants, handles submissions, and provides tools for analysis and visualization of results. +Dash is a competition framework designed to run and visualize programming-based challenges. It supports multiple competitions, with current implementations for **Beacon** and **Marvin**. ## Table of Contents - -- [Features](#features) +- [Overview](#overview) - [Prerequisites](#prerequisites) - [Installation](#installation) - [Configuration](#configuration) - - [.env File](#env-file) - - [participants.json](#participantsjson) - - [maps.json](#mapsjson) -- [Usage](#usage) - - [CLI Menu](#cli-menu) -- [Running the Visualizer](#running-the-visualizer) -- [Project Structure](#project-structure) -- [Go Version & Dependencies](#go-version--dependencies) -- [Taskfile](#taskfile) - -## Features +- [Running the Competition](#running-the-competition) +- [Results & Logs](#results--logs) +- [Visualization](#visualization) +- [Scripts](#scripts) +- [License](#license) -- **Automated Repository Management:** Create GitHub repositories from a template. -- **Participant Handling:** Manage teams and their associated competitions. -- **Submission Analysis:** Clone and evaluate participant submissions. -- **Trace Uploading:** Push test traces to specific branches for review. -- **Result Generation:** Compile logs into comprehensive JSON results for visualization. -- **Docker Integration:** Safe execution of user programs in isolated environments. -- **Interactive CLI:** User-friendly menu for managing various tasks. -- **Visualizer:** JavaScript-based tool for displaying competition results. +## Overview +Dash enables participants to compete in programming challenges by providing executable solutions. The framework supports: +- Multiple competitions with modular grading +- Configuration-driven execution +- Automated logging and result storage +- Visualization tools for performance analysis ## Prerequisites - -- **Go:** Version 1.22 -- **Docker:** For running the visualizer and executing user programs securely. -- **GitHub Access Token:** Must have permissions to create repositories and manage access. -- **Organization:** The GitHub organization where repositories will be created must already exist and contain a `template-marvin` repository. +Ensure you have the following installed before proceeding: +- **Taskfile** - Required for running compilation tasks (*optional*) +- **Docker** - Used for containerized execution +- **Git** - Necessary for managing participant repositories +- **GitHub Organization** – A dedicated organization where all repositories will be created +- **template-{competition}** Repository – A template repository inside *the dedicated organization* used for initializing participant repositories + +### API Token +For authentication and repository management, a valid **GitHub Personal Access Token (PAT)** is required. The token must have the following scopes: +- `admin:org` +- `repo` +- `delete_repo` ## Installation - -1. **Clone the Repository:** - ```bash - git clone https://github.com/your_org/dashinette.git - cd dashinette - ``` - -2. **Install Dependencies:** - ```bash - go mod download - ``` - -## Configuration - -### `.env` File - -Create a `.env` file in the root directory based on the `.env.example`: - -```env -ORGANIZATION_NAME=your_github_org -GITHUB_ACCESS_TOKEN=your_access_token -``` - -- **ORGANIZATION_NAME:** Name of the GitHub organization where repositories will be created. -- **GITHUB_ACCESS_TOKEN:** Token with permissions to create repositories and manage collaborators. - -#### `participants.json` configuration file -Defines the teams participating in the competition. - -```json -{ - "teams": [ - { - "name": "The-Avengers", - "members": ["IronMan", "Thor777"], - "league": "open" - }, - { - "name": "Pirates-of-the-Caribbean", - "members": ["jack-sparrow", "wturner"], - "league": "open" - }, - { - "name": "The-Justice-League", - "members": ["BatmanIsHere", "SuPeRmAn"], - "league": "rookie" - } - ] -} -``` -- **name:** Team name. -- **members:** List of team members. -- **league:** Competition league (`open` or `rookie`). - -#### `maps.json` configuration file -Specifies the maps used for generating traces for tests and final submittions. - -```json -{ - "rookieleague": [ - { - "path": "dashes/marvin/maps/rookieleague/amongus.txt", - "name": "Impostor", - "timeout": 2 - }, - ... - ], - "openleague": [ - { - "path": "dashes/marvin/maps/openleague/sipmson.txt", - "name": "You know him", - "timeout": 3 - }, - ... - ] -} -``` - -- **path:** File path to the map. -- **name:** Map name. -- **timeout:** Execution timeout in seconds. - -## Usage -### CLI Menu -Launch the CLI with: -```bash -go run main.go -``` - -#### Menu Options: - -1. **Create GitHub Repositories by template:** Initializes repositories for each team based on the `template-marvin` repo. -2. **Update README files with Subjects:** Pushes updated subjects to team repositories. -3. **Grant Collaborator Write Access:** Adds collaborators with write permissions to repositories. -4. **Configure Repositories as Read-Only:** Sets repositories to read-only access. -5. **Clone and Analyze Submissions to Generate Traces:** Clones student submissions and generates trace data. -6. **Parse and Upload Traces to 'traces' Branch:** Uploads generated traces to the `traces` branch of each repository. -7. **Parse Logs and Generate results.json:** Compiles logs into a `results.json` file for visualization. -8. **Exit:** Closes the CLI. - -### Example Workflow - -1. Create Repositories: - - Select "Create GitHub Repositories by template." -2. Add collaborators: - - Select "Grant Collaborator Write Access." -3. Analyze Submissions and give feedback - - Select "Clone and Analyze Submissions to Generate Traces." - - Select "Parse and Upload Traces to 'traces' Branch." -4. Analyze Submissions and prepare results for visualization: - - Select "Clone and Analyze Submissions to Generate Traces." - - Select "Parse Logs and Generate results.json." - -All actions are logged in `app.log` for detailed tracking. - -### Running the Visualizer -The visualizer is a Dockerized JavaScript application that displays competition results. - -1. **Launch the Visualizer:** -```bash -go run scripts/marvin/visualiser/start/main.go generated_results.json +Clone the repository: +```sh +# Clone the repository +git clone https://github.com/42-Dash/dashinette.git +cd dashinette ``` -2. **Access the Visualizer:** Open your browser and navigate to `http://localhost:8080`. -```bash -. -├── README.md -├── Dockerfile -├── Taskfile.yml -├── app.log -├── cmd -│ └── marvin -│ ├── tester -│ ├── tests -│ └── marvin -├── config -│ ├── .env -│ ├── maps.json -│ └── participants.json -├── dashes -│ └── marvin -│ ├── README.md -│ ├── maps -│ ├── repos -│ ├── solutions -│ ├── traces -│ └── visualiser -│ ├── Dockerfile -│ ├── images -│ ├── index.html -│ ├── libraries -│ ├── results.json -│ └── src -├── go.mod -├── go.sum -├── internals -│ ├── cli -│ ├── grader -│ └── traces -├── main.go -├── pkg -│ ├── constants -│ ├── containerization -│ ├── github -│ ├── logger -│ └── parser -└── scripts +## Configuration +All configuration files are stored in the `config/` directory: +- **`maps.json`** – Defines competition maps +- **`participants.json`** – Lists participating teams +- **`.env`** – Stores environment variables + +### `.env` Example +Create a `.env` file in `config/` with the following format: +```sh +GITHUB_ACCESS=your_github_access_token +GITHUB_ORGANISATION=your_github_organisation ``` -## Go Version & Dependencies -- Go Version: 1.22 - -**Dependencies:** -```go -module dashinette - -go 1.22 - -require ( - github.com/docker/docker v27.3.1+incompatible - github.com/joho/godotenv v1.5.1 - github.com/manifoldco/promptui v0.9.0 -) +## Running the Competition +Dash competitions are compiled and executed using Taskfile: +```sh +# Run the contest using Taskfile +task {competition to start} +# Or run the contest directly +go run cmd/{competition}/{competition}/main.go ``` - -## Taskfile - -The project utilizes a [`Taskfile.yml`](Taskfile.yml) to automate various development tasks. [Task](https://taskfile.dev/) is a simple task runner that helps streamline your workflow. - -### Prerequisites - -- **Task:** Ensure Task is installed on your system. Follow the [Task installation guide](https://taskfile.dev/installation/) to set it up. - -### Available Tasks - -- **marvin:** Build the marvin project. -- **marvin-tester:** Build the marvin project tester (for development). -- **marvin-docker:** Rebuild the Docker image for the marvin project. -- **clean:** Clean up the repository by removing build artifacts and logs. -- **delete-repos:** Remove the organization repositories. **Use with caution.** -- **test:** Run all tests and clean up afterwards. - -### Usage - -To execute a task, use the following command: - -```bash -task +This launches a CLI menu allowing you to: +- Initialize repositories +- Analyze submissions +- Run grading and visualization +- Manage collaborators + +## Results & Logs +Competition results and logs are stored in the root directory: +- `app.log` – Stores execution logs +- `open_results.json` – Results for Open League +- `rookie_results.json` – Results for Rookie League + +## Visualization +Each competition has a dedicated visualizer located in: +```sh +dashes/{competition}/visualiser/ ``` +Detailed documentation for visualizers can be found in the respective `README.md` files. -### Examples: - -- **Build the marvin project:** - -```bash -task marvin -``` - -### Viewing Help -To view available commands and their descriptions: - -```bash -task help -``` +## Scripts +Additional scripts are available in `scripts/general/`: +- **`delete_repos.sh`** – Deletes all competition repositories +- **`reshuffle_config.sh`** – Randomizes participant order for fairness -This will display all available tasks with their respective descriptions. +## License +The project license will be added soon. See `LICENSE` for more details. diff --git a/config/maps_marvin.json b/config/maps_marvin.json deleted file mode 100644 index 3d68bfd..0000000 --- a/config/maps_marvin.json +++ /dev/null @@ -1,236 +0,0 @@ -{ - "rookieleague": [ - { - "path": "dashes/marvin/maps/rookieleague/level_0.txt", - "name": "0", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_1.txt", - "name": "1", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_2.txt", - "name": "2", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_3.txt", - "name": "3", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_4.txt", - "name": "4", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_5.txt", - "name": "5", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_6.txt", - "name": "6", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_7.txt", - "name": "7", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_8.txt", - "name": "8", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_9.txt", - "name": "9", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_0.txt", - "name": "10", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_1.txt", - "name": "11", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_2.txt", - "name": "12", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_3.txt", - "name": "13", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_4.txt", - "name": "14", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_5.txt", - "name": "15", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_6.txt", - "name": "16", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_7.txt", - "name": "17", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_8.txt", - "name": "18", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_9.txt", - "name": "19", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_0.txt", - "name": "20", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_1.txt", - "name": "21", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/rookieleague/level_2.txt", - "name": "22", - "timeout": 5 - } - ], - "openleague": [ - { - "path": "dashes/marvin/maps/openleague/level_0.txt", - "name": "0", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_1.txt", - "name": "1", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_2.txt", - "name": "2", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_3.txt", - "name": "3", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_4.txt", - "name": "4", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_5.txt", - "name": "5", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_6.txt", - "name": "6", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_7.txt", - "name": "7", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_8.txt", - "name": "8", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_9.txt", - "name": "9", - "timeout": 1 - }, - { - "path": "dashes/marvin/maps/openleague/level_0.txt", - "name": "10", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/openleague/level_1.txt", - "name": "11", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/openleague/level_2.txt", - "name": "12", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/openleague/level_3.txt", - "name": "13", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/openleague/level_4.txt", - "name": "14", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/openleague/level_5.txt", - "name": "15", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/openleague/level_6.txt", - "name": "16", - "timeout": 2 - }, - { - "path": "dashes/marvin/maps/openleague/level_7.txt", - "name": "17", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/openleague/level_8.txt", - "name": "18", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/openleague/level_9.txt", - "name": "19", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/openleague/level_0.txt", - "name": "20", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/openleague/level_1.txt", - "name": "21", - "timeout": 5 - }, - { - "path": "dashes/marvin/maps/openleague/level_2.txt", - "name": "22", - "timeout": 5 - } - ] -} diff --git a/config/maps_main.json b/config/maps_marvin_main.json similarity index 67% rename from config/maps_main.json rename to config/maps_marvin_main.json index 3d68bfd..85a7d21 100644 --- a/config/maps_main.json +++ b/config/maps_marvin_main.json @@ -51,67 +51,67 @@ "timeout": 1 }, { - "path": "dashes/marvin/maps/rookieleague/level_0.txt", + "path": "dashes/marvin/maps/rookieleague/level_10.txt", "name": "10", "timeout": 2 }, { - "path": "dashes/marvin/maps/rookieleague/level_1.txt", + "path": "dashes/marvin/maps/rookieleague/level_11.txt", "name": "11", "timeout": 2 }, { - "path": "dashes/marvin/maps/rookieleague/level_2.txt", + "path": "dashes/marvin/maps/rookieleague/level_12.txt", "name": "12", "timeout": 2 }, { - "path": "dashes/marvin/maps/rookieleague/level_3.txt", + "path": "dashes/marvin/maps/rookieleague/level_13.txt", "name": "13", "timeout": 2 }, { - "path": "dashes/marvin/maps/rookieleague/level_4.txt", + "path": "dashes/marvin/maps/rookieleague/level_14.txt", "name": "14", "timeout": 2 }, { - "path": "dashes/marvin/maps/rookieleague/level_5.txt", + "path": "dashes/marvin/maps/rookieleague/level_15.txt", "name": "15", "timeout": 2 }, { - "path": "dashes/marvin/maps/rookieleague/level_6.txt", + "path": "dashes/marvin/maps/rookieleague/level_16.txt", "name": "16", "timeout": 2 }, { - "path": "dashes/marvin/maps/rookieleague/level_7.txt", + "path": "dashes/marvin/maps/rookieleague/level_17.txt", "name": "17", "timeout": 5 }, { - "path": "dashes/marvin/maps/rookieleague/level_8.txt", + "path": "dashes/marvin/maps/rookieleague/level_18.txt", "name": "18", "timeout": 5 }, { - "path": "dashes/marvin/maps/rookieleague/level_9.txt", + "path": "dashes/marvin/maps/rookieleague/level_19.txt", "name": "19", "timeout": 5 }, { - "path": "dashes/marvin/maps/rookieleague/level_0.txt", + "path": "dashes/marvin/maps/rookieleague/level_20.txt", "name": "20", "timeout": 5 }, { - "path": "dashes/marvin/maps/rookieleague/level_1.txt", + "path": "dashes/marvin/maps/rookieleague/level_21.txt", "name": "21", "timeout": 5 }, { - "path": "dashes/marvin/maps/rookieleague/level_2.txt", + "path": "dashes/marvin/maps/rookieleague/level_22.txt", "name": "22", "timeout": 5 } @@ -168,67 +168,67 @@ "timeout": 1 }, { - "path": "dashes/marvin/maps/openleague/level_0.txt", + "path": "dashes/marvin/maps/openleague/level_10.txt", "name": "10", "timeout": 2 }, { - "path": "dashes/marvin/maps/openleague/level_1.txt", + "path": "dashes/marvin/maps/openleague/level_11.txt", "name": "11", "timeout": 2 }, { - "path": "dashes/marvin/maps/openleague/level_2.txt", + "path": "dashes/marvin/maps/openleague/level_12.txt", "name": "12", "timeout": 2 }, { - "path": "dashes/marvin/maps/openleague/level_3.txt", + "path": "dashes/marvin/maps/openleague/level_13.txt", "name": "13", "timeout": 2 }, { - "path": "dashes/marvin/maps/openleague/level_4.txt", + "path": "dashes/marvin/maps/openleague/level_14.txt", "name": "14", "timeout": 2 }, { - "path": "dashes/marvin/maps/openleague/level_5.txt", + "path": "dashes/marvin/maps/openleague/level_15.txt", "name": "15", "timeout": 2 }, { - "path": "dashes/marvin/maps/openleague/level_6.txt", + "path": "dashes/marvin/maps/openleague/level_16.txt", "name": "16", "timeout": 2 }, { - "path": "dashes/marvin/maps/openleague/level_7.txt", + "path": "dashes/marvin/maps/openleague/level_17.txt", "name": "17", "timeout": 5 }, { - "path": "dashes/marvin/maps/openleague/level_8.txt", + "path": "dashes/marvin/maps/openleague/level_18.txt", "name": "18", "timeout": 5 }, { - "path": "dashes/marvin/maps/openleague/level_9.txt", + "path": "dashes/marvin/maps/openleague/level_19.txt", "name": "19", "timeout": 5 }, { - "path": "dashes/marvin/maps/openleague/level_0.txt", + "path": "dashes/marvin/maps/openleague/level_20.txt", "name": "20", "timeout": 5 }, { - "path": "dashes/marvin/maps/openleague/level_1.txt", + "path": "dashes/marvin/maps/openleague/level_21.txt", "name": "21", "timeout": 5 }, { - "path": "dashes/marvin/maps/openleague/level_2.txt", + "path": "dashes/marvin/maps/openleague/level_22.txt", "name": "22", "timeout": 5 } diff --git a/config/maps_marvin_traces.json b/config/maps_marvin_traces.json new file mode 100644 index 0000000..00e0870 --- /dev/null +++ b/config/maps_marvin_traces.json @@ -0,0 +1,36 @@ +{ + "rookieleague": [ + { + "path": "dashes/marvin/maps/rookieleague/level_0.txt", + "name": "0", + "timeout": 1 + }, + { + "path": "dashes/marvin/maps/rookieleague/level_1.txt", + "name": "1", + "timeout": 1 + }, + { + "path": "dashes/marvin/maps/rookieleague/level_2.txt", + "name": "2", + "timeout": 1 + } + ], + "openleague": [ + { + "path": "dashes/marvin/maps/openleague/level_0.txt", + "name": "0", + "timeout": 1 + }, + { + "path": "dashes/marvin/maps/openleague/level_1.txt", + "name": "1", + "timeout": 1 + }, + { + "path": "dashes/marvin/maps/openleague/level_2.txt", + "name": "2", + "timeout": 1 + } + ] +} diff --git a/dashes/beacon/visualiser/README.md b/dashes/beacon/visualiser/README.md new file mode 100644 index 0000000..46bebf6 --- /dev/null +++ b/dashes/beacon/visualiser/README.md @@ -0,0 +1,80 @@ +# Dash Visualizer + +## Overview +The **Dash Visualizer** is a tool designed to display the results of the Dash-Beacon programming competition. It provides a graphical representation of how teams performed by rendering their beacon placements on a map. The visualizer supports two leagues: + +- **Rookie League**: Participants must place beacons on a single plastic board to maximize coverage of nodes. +- **Open League**: Participants select the best configuration of four maps to achieve optimal node coverage. + +## Installation and Usage + +### Prerequisites +- [Node.js](https://nodejs.org/) installed on your system. + +### Important Note +- The results file **`result.json`** must be placed in the **root directory** for the visualizer to function correctly. + +### Installation using npm +Run the following command to install dependencies: + +```sh +npm install +``` + +### Running the Visualizer +Start the visualizer using: + +```sh +npm start +``` + +This will launch the visualizer on **localhost:8080**. + +### Installation using Docker +Alternatively, you can run the visualizer using Docker: + +```sh +docker build -t dash-visualizer . +docker run -p 8080:8080 dash-visualizer +``` + +This method ensures a consistent environment for running the visualizer. + +## JSON File Requirements +- The results file must be placed in the **root directory**. +- The JSON file must include a **league property** indicating either `Rookie League` or `Open League`. +- The file should follow a predefined structure, including beacon placements and their sizes. +- Example JSON file structures can be found in the `test-data/` directory. + +## Visualizer Interface +- The **left side** of the interface displays the competition map. +- The **right side** shows the leaderboard and participant details. +- White dots represent **nodes** that need to be covered. +- Squares represent **beacon coverage areas**. +- Beacons positions **cannot overlap**. + +### Controls +- **Next** button: Moves to the next level or result. +- **Start** button: Resets and starts from the first result. + +## Dependencies +- **p5.js**: Used for rendering graphics. +- **Prettier**: Enforces consistent code formatting. + +## Notes +- Positions update automatically as new results are loaded. +- The project enforces formatting using **Prettier**. + +## Project Structure +``` +/ (Root Directory) +│── result.json (Required results file) +│── server.js +│── README.md +│── package.json +│── index.html +│── Dockerfile +│── /test-data (Sample data for testing, including example result.json files) +│── /src (Source code) +``` + diff --git a/dashes/beacon/visualiser/src/index.js b/dashes/beacon/visualiser/src/index.js index c1b290a..bb2250d 100644 --- a/dashes/beacon/visualiser/src/index.js +++ b/dashes/beacon/visualiser/src/index.js @@ -52,5 +52,7 @@ customElements.define("dash-leaderboard", Leaderboard); // load the json file and start the main function when the DOM is loaded window.addEventListener("DOMContentLoaded", () => { - loadGameData("results.json").then(main).catch(console.error); + loadGameData("results.json") + .then(main) + .catch(() => console.log("Cant find results.json")); });