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 .)
- get the resources blob (images and fonts):
curl -O https://bolson.org/ballotstudio/resources.tar.gz
tar zxvf resources.tar.gz
- Liberation fonts may have newer versions available at https://github.com/liberationfonts/liberation-fonts/releases
- Install Go from https://golang.org/dl
make
- install poppler-utils to rasterize pdf, one of:
apt-get install -y poppler-utils
yum install -y poppler-utils
git clone https://github.com/brianolson/poppler.git
- See Development dependencies below
./ballotstudio -flask bsvenv/bin/flask -sqlite bss -debug
- open the login link shown in initial status log lines
Dependencies:
- https://github.com/brianolson/login
- Local user/pass and oauth2 login
- https://github.com/brianolson/httpcache
- Simple local http cached used by login
- https://github.com/brianolson/poppler
- Fork of poppler with pdftoppm that does multiple pages in one operation
git clone https://github.com/brianolson/poppler.git
- `(cd poppler && git checkout png-multi-block && mkdir build)``
- redhatish:
sudo yum install -y cmake3 freetype-devel fontconfig-devel libjpeg-turbo-devel openjpeg2-devel libtiff-devel
(cd poppler/build && cmake3 .. && make pdftoppm)
- debianish:
sudo apt-get install -y libjpeg-dev libopenjp2-7-dev
(cd poppler/build && cmake .. && make pdftoppm)
- redhatish:
- copy
poppler/build/utils/pdftoppm
to somewhere at head of PATH to be found bycmd/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.py
The 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