{"id":16060825,"url":"https://github.com/geerlingguy/beast-challenge","last_synced_at":"2025-10-19T06:54:48.069Z","repository":{"id":226270208,"uuid":"608333443","full_name":"geerlingguy/beast-challenge","owner":"geerlingguy","description":"A control system for MrBeast's 1-100 challenge","archived":false,"fork":false,"pushed_at":"2024-02-27T04:00:31.000Z","size":18432,"stargazers_count":26,"open_issues_count":2,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-16T17:11:47.880Z","etag":null,"topics":["flask","python","youtube"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geerlingguy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-01T19:58:34.000Z","updated_at":"2024-07-15T01:46:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"1b797cd2-f06a-4c90-8989-c94229db4fd0","html_url":"https://github.com/geerlingguy/beast-challenge","commit_stats":null,"previous_names":["geerlingguy/beast-challenge"],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geerlingguy%2Fbeast-challenge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geerlingguy%2Fbeast-challenge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geerlingguy%2Fbeast-challenge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geerlingguy%2Fbeast-challenge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geerlingguy","download_url":"https://codeload.github.com/geerlingguy/beast-challenge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244164475,"owners_count":20408942,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","python","youtube"],"created_at":"2024-10-09T04:06:40.960Z","updated_at":"2025-10-19T06:54:43.002Z","avatar_url":"https://github.com/geerlingguy.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Beast Challenge\n\nA control system for the buttons and in-room LEDs in MrBeast's [Ages 1 - 100 Fight For $500,000](https://www.youtube.com/watch?v=FM7Z-Xq8Drc) video.\n\nThere's a 'leader' app that runs on a 'farmer' node, which controls the challenge mechanics. It manages state (e.g. how many rooms voted for a certain choice), allows round configuration. Then 'Room' apps running on individual room nodes manage the room's state and transmits button inputs to the leader.\n\nMy [behind-the-scenes video about the 1-100 challenge](https://www.youtube.com/watch?v=wsV_C9cMf8A) contains a lot more detail:\n\n\u003cp align=\"center\"\u003e\u003ca href=\"https://www.youtube.com/watch?v=wsV_C9cMf8A\"\u003e\u003cimg alt=\"Jeff Geerling with a relay board on MrBeast set\" src=\"/resources/jeff-mrbeast-set-relays.jpg\" height=\"auto\" width=\"610\"\u003e\u003c/a\u003e\u003c/p\u003e\n\nThere's also a blog post: [100 SBCs, Python Flask, and two NUCs for MrBeast](https://www.jeffgeerling.com/blog/2023/100-sbcs-python-flask-and-two-nucs-mrbeast).\n\n## Screenshots\n\n![Overview UI](/resources/screenshots/overview-example.png)\n\n![Room Votes UI](/resources/screenshots/room-votes-example.png)\n\n![Room Lights UI](/resources/screenshots/room-lights-example.png)\n\n![Tally Page Example](/resources/screenshots/tally-example.png)\n\n![Bar Graph Example](/resources/screenshots/bar-graph-example.png)\n\n![Test Mode UI](/resources/screenshots/test-mode-example.png)\n\n## Leader app\n\nThe Leader app (inside `leader-app/`) runs on a central server that manages state, provides output for a display, and provides controls to manage state (e.g. starting/ending a round, advancing to a new round).\n\nThe Leader app is a Flask app built with Python.\n\nTo develop it locally, run:\n\n  1. `cd leader-app`\n  2. `pipenv shell` (requires `pipenv`, install with `pip3 install pipenv`)\n  3. `pip install -r requirements.txt`\n  4. Initialize the database: `python3 init_db.py`\n  5. Run app: `FLASK_APP=app FLASK_DEBUG=true flask run` (add `--host=0.0.0.0` to make it accessible over the network)\n\nVisit the app at http://127.0.0.1:5000\n\n## Countdown app\n\nThe Countdown app (inside `countdown-app/`) runs on a central server that manages state, provides output for a display, and provides controls to manage state (e.g. setting the time interval for a button press, resetting timers).\n\nThe Countdown app is a Flask app built with Python.\n\nTo develop it locally, run:\n\n  1. `cd countdown-app`\n  2. `pipenv shell` (requires `pipenv`, install with `pip3 install pipenv`)\n  3. `pip install -r requirements.txt`\n  4. Initialize the database: `python3 init_db.py`\n  5. Run app: `FLASK_APP=app FLASK_DEBUG=true flask run` (add `--host=0.0.0.0` to make it accessible over the network)\n\nVisit the app at http://127.0.0.1:5000\n\n## Production 'Farmer' Deployment (Leader and Button apps)\n\nThe Leader and Button apps will run on the main server NUC, with a hot spare backup server available should the need arise.\n\nThe `automation/farmer-control.yml` file contains the Ansible playbook to set up the server, install the app, and run it.\n\nMake sure you have Ansible installed on a machine on the same network: `pip3 install ansible`.\n\nThen make sure the leader and spare's IP addresses are both entered in the `[leader]` section of the `hosts.ini` file. For SSH authentication, the private key is available inside the Notion doc—you should add it to your `ssh` keychain with `ssh-add ~/path/to/private_key`\n\nThen run the Ansible playbook:\n\n```\nansible-playbook farmer-control.yml\n```\n\n\u003e For testing, bring up a Docker Ubuntu container with `docker run -d --volume=/sys/fs/cgroup:/sys/fs/cgroup:rw --cgroupns=host --privileged --name farmer geerlingguy/docker-ubuntu2204-ansible:latest /usr/sbin/init`, then set the hostname line for the farmer to:\n\u003e\n\u003e ```\n\u003e farmer ansible_connection=community.general.docker role=leader\n\u003e ```\n\u003e\n\u003e Then run the playbook: `ansible-playbook farmer-control.yml`\n\n### Initializing the Database\n\nTo initialize (or reset) the database, run the Ansible playbook:\n\n```\nansible-playbook farmer-reset-database.yml\n```\n\nTo _manually_ initialize the database (e.g. the first time you run the application in production), log into the server and run:\n\n```\n# For leader app\ndocker exec beast-challenge_leader_1 python3 init_db.py\n\n# For countdown app\ndocker exec countdown-app_countdown_1 python3 init_db.py\n```\n\n### Running the Apps on a Potato\n\nIf you want to test things on a Potato running Armbian instead of a NUC running Ubuntu, you can do that too! Just change the `[farmer]` section inside `hosts.ini` to have a line for the Potato where you want the server running.\n\nRun the Ansible `farmer-control.yml` playbook, initialize the database, and away you go!\n\nIf you want to plug an HDMI display into the Potato and use Firefox to browse the web UI, you can install the LXDE Desktop (Armbian doesn't come with a desktop environment out of the box):\n\n```\nsudo apt install lxdm vanilla-gnome-desktop firefox\n```\n\nIf you get a popup asking you to select a default display manager, choose `gdm3` then continue. See [this post](https://forum.armbian.com/topic/5298-le-potato-general-topics/page/3/#comment-125790) for more info.\n\n\u003e Note: During testing, some things need tweaking depending on your setup. For example, one Le Potato I was using to demo some button functionality didn't have the relay HAT attached. The default 'Live Colors' configuration resulted in an exception, because the Potato couldn't find the I2C relay HAT to control! So... you might have to do a little Python spelunking if you want to do things out of the norm. In my case, I just had to disable 'Live Colors' in that test round.\n\n## Room app\n\nThe Room app (inside `room-app`) runs on every one of the 100x rooms where SBCs are set up to run the room controls.\n\nThe app controls the following:\n\n  1. Buttons and Button LEDs (GPIO digital inputs)\n  2. RGBW LED light strip control (GPIO digital outputs)\n\nTo deploy the app, see the _Automation for Controlling the Potatoes_ section below.\n\n### 52Pi EP-0099 Relay Considerations\n\nThe [52Pi EP-0099 Relay](https://amzn.to/49wu65O) is a 4-channel I2C-controlled relay HAT that works with Le Potato. We bought it for two reasons:\n\n  1. It is easy to install (as a HAT)\n  2. It was available on short notice\n\nThe relays used are [`HK4100F-DC5V-SHG`](https://www.lcsc.com/product-detail/Power-Relays_Ningbo-Keke-New-Era-Appliance-HK4100F-DC5V-SHG_C12072.html), and according to the datasheet, they can only handle 3A at 30V, so they are not rated for the current we'll be drawing.\n\nBecause of that, we daisy chained another set of relays rated at 10A at 30V. The relays are controlled via code in the Room app scripts.\n\nThere is also a convenient `light.py` script which allows for setting a room color directly on the device, e.g. `./light.py white`. Note that you may need to temporarily stop the lighting control script: `sudo systemctl stop light-control`.\n\n## Automation for Controlling the Potatoes\n\nThe `automation` directory contains Ansible configuration for managing both the main server (`farmer`) and the fleet of 100 room nodes (`potatoes`, sometimes referred to as `spuds`). We have to use something like Ansible because managing 100 nodes by hand would be insane.\n\nMake sure you have Ansible installed on a machine on the same network: `pip3 install ansible`\n\n### Initializing a Le Potato (the 'Spud')\n\nFor first-time setup of a new Le Potato (assuming you've already booted it and set up the `admin` user account following Armbian's wizard), do the following:\n\n  1. `cd automation`\n  2. `ansible-playbook spud-control.yml -k -K -e '{\"run_upgrades\": true}'`\n  3. Enter the default `admin` password (and then press enter to re-use it for `BECOME`).\n  4. Wait for the playbook to complete.\n\n#### Re-running the `spud-control.yml` playbook\n\nFor future runs, assuming you have the private key in your agent (`ssh-add [path-to-key]`), you can just run the following:\n\n```\nansible-playbook spud-control.yml\n```\n\nThe playbook is configured to be idempotent, so we should be able to run it live if we need to quickly patch all 100 rooms!\n\n#### Maintaining the Potato farm\n\nThere are a variety of maintenance tasks in the maintenance playbook:\n\n```\n# Reboot spuds:\nansible-playbook spud-maintain.yml -e '{\"spud_reboot\":true}'\n\n# Stop all services on the spuds:\nansible-playbook spud-maintain.yml -e '{\"service_stop\":true}'\n\n# Start all services on the spuds:\nansible-playbook spud-maintain.yml -e '{\"service_start\":true}'\n```\n\n### Initializing the Farmer\n\nAssuming either Ubuntu Desktop or Ubuntu Server is installed on the Farmer, make sure you have SSH access, and install your SSH key on the `beast-admin` or `admin` account. Then run the Ansible playbook to set it up:\n\n```\nansible-playbook farmer-control.yml\n```\n\nYou may need to add `-K` the first time the playbook runs, to supply the sudo password (since by default Ubuntu doesn't allow passwordless sudo).\n\n### Switching modes\n\nIf you need to switch from the `leader` app to `countdown` (or vice-versa), run the `switch-modes.yml` playbook. For example, if the `leader` app is running, and you would like to switch to `countdown`:\n\n```\nansible-playbook switch-modes.yml -e challenge_mode=countdown\n```\n\n## Critical Test Scenarios\n\n  1. Live round is open, accepts multiple votes, make sure multiple votes can be made per room.\n  2. Live round is open, doesn't accept multiple votes, make sure only first vote is accepted.\n  3. Live round is closed, make sure no votes are accepted.\n\n## License\n\nGPLv3 or later (as of version 4.0.0)\n\nAll prior versions are not released under an open source license and are provided for historical context only.\n\nAny MrBeast trademarks and references are all rights reserved and must be removed if redistributing or re-using this software outside of the MrBeast organization.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeerlingguy%2Fbeast-challenge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeerlingguy%2Fbeast-challenge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeerlingguy%2Fbeast-challenge/lists"}