System for designing, printing, and scanning paper ballots.
Ballot Studio is designed to be a core piece of an open source voting system.
Ballot Studio is in two parts, a Python back end that draws PDF ballots, and a go middle layer that runs a web app with login and database and editing ballot data and scanning ballot images.
python3 -m venv bsvenv
bsvenv/bin/pip install fonttools Flask mercurial
bsvenv/bin/hg clone https://hg.reportlab.com/hg-public/reportlab
(cd reportlab && ../bsvenv/bin/pip install -e .)
curl -O https://bolson.org/ballotstudio/resources.tar.gz
tar zxvf resources.tar.gz
make
apt-get install -y poppler-utils
yum install -y poppler-utils
git clone https://github.com/brianolson/poppler.git
./ballotstudio -flask bsvenv/bin/flask -sqlite bss -debug
Dependencies:
git clone https://github.com/brianolson/poppler.git
sudo yum install -y cmake3 freetype-devel fontconfig-devel libjpeg-turbo-devel openjpeg2-devel libtiff-devel
(cd poppler/build && cmake3 .. && make pdftoppm)
sudo apt-get install -y libjpeg-dev libopenjp2-7-dev
(cd poppler/build && cmake .. && make pdftoppm)
poppler/build/utils/pdftoppm
to somewhere at head of PATH to be found by cmd/ballotstudio/drawsub.go
ballotstudio
will normally automatically start and stop the draw server.
It can be run on its own with:
FLASK_ENV=development FLASK_APP=draw/app.py bsvenv/bin/flask run
ballotstudio
can be given the option -draw-backend http://127.0.0.1:5000/
to point to that at Flask's default port 5000.
http://127.0.0.1:5000/demo.pdf
- demo ElectionReport drawn to PDFhttp://127.0.0.1:5000/demo.bubbles.json
- bubble positionshttp://127.0.0.1:5000/demo.js
- ElectionReport built by draw/demorace.pyThe draw server should can be run by gunicorn for a production environment. ballotstudio
would be given a -draw-backend http://localhost:port/
option to point at the gunicorn server.
NIST 1500-100 (version 2) is a specification on election results reporting, but is used here because it has all the structural information about candidates and contests and the election as a whole. We extend it with a few additional fields about ballot layout and rendering.
Optional field "PageHeader" is a string that would be rendered at the top of each page. For example:
Header Election Name, YYYY-MM-DD
Precinct 1234, Some Town, Statename, page {PAGE} of {PAGES}
\n
newlines within the text will be rendered.
Templated fields within the text are:
{PAGE}
the current page number{PAGES}
the total number of pages