The hardest part of any communications exercise is having something to talk about or to do. This application is designed to help with that by generating need/resource pairs for users (i.e. participants/operators) to find and fulfill during an exercise. One user is assigned the need, and another one is assigned the matching resource. It's then the responsibility of "need" user (and the necessary net control stations) to then find the "resource" user. The app works with three scopes: stakes, regions, and storehouse (the top level, i.e. global). The app spreads the pairs across scopes as configured per exercise.
The application is built to handle only one exercise at a time. If more than one exercise needs to happen at a time, you should create separate instances.
This application is built on PocketBase, which provides authentication, user management, a SQLite database, and realtime updates to the frontend via server-sent events (SSE). The frontend is built with jQuery, the PocketBase JS SDK and Bootstrap.
Note that these setup instructions are geared toward Linux hosts. You'll have to adjust and refactor stuff as necessary for other platforms.
- Get this repo on your host.
- Before proceeding, consider the point in Production-ready Setup regarding a reverse proxy.
- Start the server (e.g.
systemctl start pocketbase-erc
if you setup the systemd service, or./pocketbase serve
to just do it manually). - Create your admin user in the PocketBase Admin UI at
/_
(e.g. if running locally, go tohttp://127.0.0.1:8090/_
). - Set your application URL in the PocketBase Admin UI at
/_
:- Go to the "Settings" tab (the tools icon in the left sidebar).
- Click the "Application" section if it's not already selected.
- Set the "Application URL" to the URL where your application will be accessible (e.g.
https://exercise.idahoerc.org
, orhttp://127.0.0.1:8090
if developing locally).
- (Optional) If you want to enable password reset requests, you'll need to set up the SMTP settings in the PocketBase Admin UI. If you skip this step, users will not be able to reset their passwords, and the "Forgot Password" link will not be shown on the login page.
- Go to the "Settings" tab (the tools icon in the left sidebar).
- Click the "Mail settings" section.
- Set the Sender and SMTP settings to your email provider's SMTP server, port, username, and password.
Congrats! The application is functional!
In the Exercise Admin UI (at /admin
, this is different than the PocketBase Admin UI at /_
), you can manage individual Exercises, Regions, Stakes, and Items. You can also upload Regions, Stakes, and Items from CSV files to bulk-add them. The CSV uploading is especially helpful when getting started.
To import from CSV files:
- Review the CSV files in the
csv_examples
directory. There are three categories:regions
andstakes
: Regions are groups of Stakes, and users indicate which Stake they're participating from/in.items
: Contains the items that can be used in assignments during the exercise.
- Edit the CSV files as necessary, or create your own. The file should include headers (i.e. the first row being the column names). The headers are case-sensitive, but they can be in any order. The column names depend on the category:
regions
:- Name
stakes
:- Name
- Region (the name of an existing Region)
items
:- Description
- Quantity (can be more than just a number, e.g. "pack of 80")
- Priority (one of: Emergency, Priority, Welfare, Routine)
- Log in to the Exercise Admin UI.
- Click the "Upload CSV" button for a category, then select the desired file for that category.
That's it! You should have a complete ERC Exercise site ready to go.
Just a few more things to get you ready for go-time.
- (Optional, but highly recommended) Consider using a reverse proxy so you can use a nice domain and HTTPS. e.g., if using Apache2/httpd, you could create a config like this:
Make sure to adjust the
<VirtualHost *:80> ServerName exercise.idahoerc.org ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined RedirectMatch permanent "(.*)" "https://exercise.idahoerc.org$1" </VirtualHost> <IfModule mod_ssl.c> <VirtualHost *:443> ServerName exercise.idahoerc.org DocumentRoot /var/www/pocketbase-erc-exercise/pb_public <Directory /var/www/pocketbase-erc-exercise> Options -Indexes +FollowSymLinks +Includes AllowOverride All Order allow,deny Allow from All </Directory> ErrorLog ${APACHE_LOG_DIR}/exercise.idahoerc.org/error.log CustomLog ${APACHE_LOG_DIR}/exercise.idahoerc.org/access.log vhost_combined # enable SSL with LetsEncrypt SSLCertificateFile /etc/letsencrypt/live/exercise.idahoerc.org/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/exercise.idahoerc.org/privkey.pem # main proxy stuff ProxyPass / http://127.0.0.1:8090/ connectiontimeout=5 timeout=600 ProxyPassReverse / http://127.0.0.1:8090/ # special stuff for SSE <Location /api/realtime> # enables chunked responses from upstream to support streaming SetEnv proxy-sendchunked # ensures HTTP/1.0 is used from Apache to upstream (some versions of Apache have issues with HTTP/1.1 + chunking) SetEnv force-proxy-request-1.0 # no gzip SetEnvIfNoCase Request_URI "^/api/realtime" no-gzip ProxyPass http://127.0.0.1:8090/api/realtime connectiontimeout=5 timeout=600 ProxyPassReverse http://127.0.0.1:8090/api/realtime </Location> </VirtualHost> </IfModule>
ServerName
value, and theDocumentRoot
path to point to the public directory of the repo. Also, make sure to enable the necessary Apache modules (e.g.proxy
,proxy_http
,ssl
,rewrite
, etc.) and restart the service. - (Optional, but highly recommended) Create a system service for the application. e.g. for a systemd service on a Linux host, create
/etc/systemd/system/pocketbase-erc.service
:[Unit] Description=Pocketbase - ERC Exercise After=network.target [Service] User=www-data Group=www-data ExecStart=/your/repo/path/pocketbase serve Restart=always [Install] WantedBy=multi-user.target
This was built and used with Pocketbase v0.28.3, which is also the version included in the repo. To update it, you'll need to head over to https://pocketbase.io/docs/ for the executable, and https://github.com/pocketbase/js-sdk for the browser SDK. Make sure to test to make sure the update doesn't require additional changes in the code!
Good question!
Users can signup at any time at the /signup
URL. They log in at the /login
URL. They can also click the button to indicate they're ready for needs assignments, but nothing much will happen there until you take the next steps to setup the exercise.
For the real magic to happen, you'll need to create an exercises in the admin portal (at /admin
). Once this is created, and as long as it's in the future, the countdown timer will start. The start
timestamp is only for informational purposes; the exercise will not automatically start at that time. When you're ready to actually start the exercise, use the respective button for the exercise on the admin portal. Because the start
timestamp does not really affect anything, if you decide to start early, the application will go for it. However, the monitoring and reporting will only show stats for the time between the start
and end
timestamps of the exercise.
When an exercise is changed from not started to started, the application will find all users who currently have their ready
status set to true
, and will start working on their needs assignments. If users indicate they're ready after the exercise is started, the application will immediately start working on their needs assignments.
As soon as the end
timestamp is reached for an exercise, the countdown timer will update accordingly, and the application will stop making new assignments, even if the started
field is still set to true
.
For each needs assignment (or task), a random item is selected (priorizing the least used items first), then a random scope (stake, region, storehouse) will be chosen based on the weights/distributions defined for the exercise, and finally a user from the scope's pool is selected as the resource user. The record is created, and then the application waits between 2 - 3 minutes for the resource user to accept the resource assignment. If the user does not accept (either by lack of response, or by explicitly rejecting the assignment), then the process repeats for selecting another user as the resource. Once a resource user accepts the assignment, then the task shows up for both the need user and the resource user.
The application counts the number of times that a user rejects a resource (again, eith by lack of response, or by explicitly rejecting the assignment), and will not assign them another resource for the remainder of the exercise if a user's rejection count reaches 3 or more. This is to avoid unnecessary delays in users receiving their needs assignments. For example, if a user signs up and immediately clicks the "Ready" button, but then never joins the exercise when it starts. The rejection count can be reset by an admin user in the admin portal.
Once the need user finds the resource user and has received their callsign, the need user can then enter the callsign in the respective field in the web app and submit it. If the callsign is correct, the need user gets a visual confirmation, and then the need/resource is moved into the respective statistics column for each user. If it's incorrect, they are informed and allowed to retry as many times as they want until it's correct.
If the user decides they are unable to find the resource user, they can click the respective button for the need assignment, and then it will be cancelled after confirmation. It is then hidden from both the need and resource users.
The application has a monitoring page at /monitor
that shows information about the current exercise, including various details about the participating users and needs/resource assignments. This page is accessible publicly. Optionally, you can query for a specific exercise by adding the exercise_id
query parameter to the URL. e.g. /monitor?exercise_id=ID_FROM_THE_COLLECTION
. The button on the admin portal will also redirect to the monitoring page for the respective exercise.
A JSON report is available publicly at the /report
URL. This includes details about task success/failure rates per scope, a list of items that have been used in more than one task/assignment, the top users for needs and resources, and a participation head count. By default, the report shows stats for the timeframe of the most recent exercise for which the start time has passed (irrespective of the started
status). Optionally, you can query for a specific exercise by adding the exercise_id
query parameter to the URL. e.g. /report?exercise_id=ID_FROM_THE_COLLECTION
. The button on the admin portal will also redirect to the report page for the respective exercise.