😸 Tabbycat User Guide¶

Tabbycat is a draw tabulation system for two-team parliamentary debate tournaments. It supports the Australs, NZ Easters, Australian Easters, Joynt Scroll, UADC and WSDC formats, and is highly configurable, supporting many custom variations of the above formats too.

Installing on Heroku¶

When running Tabbycat on the internet, we set it up on Heroku. The project is set up to be good to go on Heroku, and it works well for us, so if you’d like to run it online, we recommend that you do the same. Naturally, this requires you to have a Heroku account.

Installation—the short way¶

Click this button:

https://www.herokucdn.com/deploy/button.svg

If you don’t already have a Heroku account, it’ll prompt you to create one. Once you’re logged in to Heroku, choose a name for your installation, then scroll down and click Deploy. Once it’s finished, click View and follow the prompts.

This is the easiest way to deploy an instance of Tabbycat online. It requires no technical background. You can import data using the data importer in the user interface.

Note

Heroku may ask you to attach a credit/debit card to your account. From what we understand this is to provide proof of identity — Tabbycat installations will not charge your card unless you specifically opt in to a paid upgrade.

If you have a background in programming, you might prefer the below longer, more traditional method.

Installation—the long way¶

The long way sets you up with more control over your environment. Because you’ll clone our GitHub repository, it’ll be easier for you to pull and contribute updates to the source code. We recommend it if you have experience with Git. It’s also easier with this method to import CSV files using the command-line importer, so if you have a very large tournament, this might make importing initial data easier.

We’ve tested these instructions successfully on Windows, Linux and Mac OS.

Requisite technical background¶

You need to have at least a passing familiarity with command-line interfaces to get through the longer traditional method. We’ll talk you through the rest.

When we say “command shell”, on Windows we mean Command Prompt, and on Linux and OS X we mean Terminal (or your favourite command shell).

Advanced users

Tabbycat is a Django project. As such, it can be installed on any web platform that supports Django, using any SQL system that Django supports. Just be aware that we haven’t tried any other platform.

Short version¶

git clone https://github.com/czlee/tabbycat.git
git checkout v1.1.7                               # or master
cd tabbycat
python deploy_heroku.py <yourappname>

If you want to import tournament data from CSV files, put them in data/<yourtournamentname>, then:

git commit -am "Add data for <yourtournamentname>"
git push heroku master
heroku run tabbycat/manage.py importtournament <yourdatadirectoryname> --slug <slug> --name <Your Awesome Tournament> --short-name <Awesome>

1. Install dependencies¶

Note

Linux and OS X users probably already have Python installed. There is no need to install Python 3 specifically. Although Tabbycat uses Python 3, installing it on Heroku relies only on the deployment script, which is compatible with both Python 2 and Python 3.

2. Get the source code¶

Open a command shell. Navigate to an appropriate directory on your computer using cd (creating directories using mkdir as appropriate), then run:

git clone https://github.com/czlee/tabbycat.git
git checkout v1.1.7                               # or master

Tip

If this is your second time creating a Tabbycat instance on Heroku from this computer, you don’t need to clone the repository a second time. Just run git pull to update the code to the latest version, and press ahead to step 3: Deploy to Heroku.

3. Deploy to Heroku¶

  1. Navigate to your Tabbycat directory:

    cd path/to/my/tabbycat/directory
    
  2. Run the script to deploy the app to Heroku. Replace <yourappname> with your preferred URL. Your website will be at <yourname>.herokuapp.com.

python deploy_heroku.py <yourappname>

This script has other options that you might find useful. Run python deploy_heroku.py --help for details.

Note

If you’d prefer to import tournament data locally and push the database to Heroku using heroku pg:push, use the --no-init-db option to prevent deploy_heroku.py from running initial migrations on the database.

Note

If this isn’t your first tournament, the heroku Git remote might already be pointing to your first tournament. In this case, you should use the --git-remote <new_remote_name> option to get the script to create a new git remote for you, so you can use when importing tournament data.

When this script finishes, it will open the app in your browser. It should look something like this:

_images/tabbycat-bare.png

4. Import tournament data¶

Note

This step is optional and there are other methods of importing data. However the following method is most useful for large tournaments where manual entry would be tedious.

In order to use the importtournament command directly on the server, your data also needs to be on the server. The easiest way to get this data on to the server is to make a Git commit and git push it to the server.

  1. Place your CSV files in data/yourtournamentname, as described in Importing Initial Data.

  2. Commit and push:

    git commit -am "Add data for <yourtournamentname>"
    git push heroku master
    

Note

If you use --git-remote in step 3 to create your own Git remote, you should use that remote name instead of heroku in the last command above.

Advanced users

You might like to create a new branch to keep this data off your master branch.

  1. Run this command, replacing <fields> with your own names:

    heroku run tabbycat/manage.py importtournament <yourdatadirectoryname> --slug <slug> --name <Your Awesome Tournament> --short-name <Awesome>
    

Addons¶

For Australs 2014, we found that the hobby-dev plan of Heroku Postgres didn’t allow for more than 10,000 database rows, so we upgraded to hobby-basic, which was enough (and costs a few dollars). At the end of that tournament, we had about 20,000 rows. For similar-sized tournaments (84 teams, 8 prelim rounds), you’ll probably find your usage about the same, wheras small tournaments should fit within the 10,000 row limit easily.

If you’re not sure, you can always start at hobby-dev—just be prepared to upgrade during the tournament if you run close to capacity.

Custom domain names¶

Your Heroku app will be available at yourappname.herokuapp.com. You may want it to be a subdomain of your tournament’s website, like tab.australasians2015.org. Instructions for this are in the Heroku documentation. Basically there are two things to do:

  1. Add a DNS entry to your website, with record CNAME, name tab (or whatever you prefer) and target yourappname.herokuapp.com. You’ll need to figure out how to do this with your tournament website hosting service (which is probably not Heroku).

  2. Add a custom subdomain to Heroku, like this:

    heroku domains:add tab.yourwebsite.com
    

Local Installations¶

What is a local installation?¶

Tabbycat is a web-based system: it’s designed to run as a web site. However, instead of installing it on a web server, you can install it on your computer, serving web pages to yourself. This is called a local installation.

Then, when you open your browser, you can use Tabbycat like any other web site. The only difference is that this one is on your computer, not some computer in a data centre in a far-away land.

In effect, you are getting your computer to behave like a web server. For this reason, the process is more complicated than what you’re probably used to with most installations. Basically, there are more pieces to put together to get everything working.

Should I use a local installation, or one on the internet?¶

In most cases, you should use one on the internet by setting up an instance on Heroku. This has a number of major advantages:

  • The Heroku installation process is much, much, much easier.
  • You can enter ballots and manage your tournament from multiple computers.
  • Participants can access the draw, motions, results and more online.
  • Amazon’s data centres (where Heroku is hosted) are less likely to fail than your computer is.

In some cases, you might have a good reason to use a local installation. We can think of just one such reason: If you won’t have access to the internet at your tournament, or if internet access will be flaky, then you should use a local installation.

Attention

You’ll need internet access to download dependencies during the local installation process. So if you’re not expecting to have reliable internet access at your tournament, be sure to have Tabbycat installed before you get there!

Advanced users

Tabbycat is a Django project, so if you have your own preferred method of running Django projects, you can also do that. Just be aware that we haven’t tried it.

Developers

If you’re involved in or interested in developing Tabbycat, you’ll want to set up a local installation, because it’s much faster to test your code that way.

Advanced uses¶

Can others access my local install?¶

Local installations can also take advantage of multiple-computer site access, including data entry—it’s just takes more work than a Heroku installation to set up.

Since a local installation is just having your computer run a web server, it can serve other computers too. You can make this work even if you don’t have internet access: all you need is a router that you can use to connect a few computers together. Then other computers on your local network can access the Tabbycat site hosted on your computer. We did this at Victoria Australs 2012.

We don’t provide detailed instructions for this; we leave it for advanced users to set up themselves. As a rough guide:

  • You need to pass in your computer’s IP address and port to the runserver command, for example, if your computer (the one acting as a server) is 196.168.0.2 and you want to run it on port 8000: dj runserver 192.168.0.2:8000
  • You need to configure your firewall settings to allow incoming connections on the IP address and port you specified in that command.
  • Be aware that local installs use the Django development server, whose security is not tested. Therefore, it’s a good idea to make sure your firewall only lets in computers on your local network (or, if you’re really paranoid, isolate the network from the internet completely).

Can I run an internet-accessible website from a local installation?¶

Probably not. Even if you disable your firewall, chances are your home router (or university router) will block any connections from the outside world to you. Even if you can though, you really shouldn’t. The local installation uses the Django development server, which is a lightweight server designed for developers. Specifically, Django does not test the security of its development server in the way that proper web servers do. That is: It’s a security risk to run a local installation as an internet-accessible site. Don’t do it. Install Tabbycat on Heroku instead.

Alternatively, if you have a background in web development, you might choose to install Tabbycat on your own production server. It’s a Django project, so any means of supporting Django projects should work fine.

It’s safe to run on a small, isolated network (see above) with your firewall correctly configured because you presumably trust everyone you let on the network!

Installing Locally on Linux¶

Before you start, be sure to read our page on local installations to help you understand what’s going on, particularly this section: Should I use a local installation, or one on the internet?

Requisite technical background¶

You need to be familiar with command-line interfaces to get through this comfortably. While a background in the specific tools (Python, etc.) we use will make things easier for you, it’s not necessary: we’ll talk you through the rest.

Advanced users

Tabbycat is a Django project, so can be installed in any manner that Django projects can normally be installed. For example, if you prefer some SQL system other than PostgreSQL, you can use it so long as it’s Django-compatible. Just be aware that we haven’t tried it.

Short version¶

curl -sL https://deb.nodesource.com/setup_5.x | sudo -E bash -    # add Node.js source repository
sudo apt-get install python3-dev python3-venv postgresql-9.4 postgresql-server-dev-9.4 nodejs

# either
wget https://github.com/czlee/tabbycat/archive/v1.1.7.tar.gz
tar xf v1.1.7.tar.gz
cd tabbycat-1.1.7
# or
git clone https://github.com/czlee/tabbycat.git
git checkout v1.1.7                                         # or master

sudo -u postgres createuser myusername --pwprompt           # skip if not first time
sudo -u postgres createdb mydatabasename --owner myusername

Then create local_settings.py as described below, then:

pyvenv venv                                                 # or virtualenv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements_common.txt
npm install
cd tabbycat
dj migrate
dj collectstatic
dj createsuperuser
waitress-serve wsgi:application

1. Install dependencies¶

First, you need to install all of the software on which Tabbycat depends, if you don’t already have it installed.

Advanced users

These instructions are for Ubuntu 14.10 and higher. If you have another distribution of Linux, we trust you’ll know how to navigate the package manager for your distribution to install the dependencies.

1(a). Python¶

As of version 0.8, Tabbycat requires Python 3.4 or later. You probably already have Python 3.4, but you’ll also need the development package in order to install Psycopg2 later. The pyvenv command will come in handy too. Install:

$ sudo apt-get install python3-dev

Check the version:

$ python3 --version
Python 3.4.4

Warning

As of version 0.8, Python 2 is not supported. You must use Python 3.4 or higher.

Advanced users

If you prefer, you can use Virtualenv instead of Python’s built-in pyvenv.

1(b). PostgreSQL¶

PostgreSQL is a database management system.

You’ll need the server-dev package in order to install Psycopg2 later. As per the PostgreSQL installation instructions:

$ sudo apt-get install postgresql-9.4 postgresql-server-dev-9.4

If using Ubuntu <14.10 substitute “postgresql-9.3” for “postgresql-9.4” in the above commands.

1(c). Node.js/NPM¶

Node.js is a JavaScript runtime.

Tabbycat requires Node and its package manager to compile front-end dependencies. Install using:

$ sudo apt-get install curl
$ curl -sL https://deb.nodesource.com/setup_5.x | sudo -E bash -
$ sudo apt-get install -y nodejs
$ sudo ln -s /usr/bin/nodejs /usr/bin/node

2. Get the source code¶

Download and extract:

$ wget https://github.com/czlee/tabbycat/archive/v1.1.7.tar.gz
$ tar xf v1.1.7.tar.gz
$ cd tabbycat-1.1.7

If you’ve used Git before, you might prefer to clone our GitHub repository instead:

$ git clone https://github.com/czlee/tabbycat.git
$ git checkout v1.1.7                              # or master

Tip

You might like to fork the repository first, to give yourself a little more freedom to make code changes on the fly (and potentially contribute them to the project).

3. Set up a new database¶

Hint

You can skip step 1 if this is not your first installation. Every Tabbycat installation requires its own database, but they can use the same login role if you like.

  1. Create a new user account with a password, replacing myusername with whatever name you prefer. If you don’t know what username to pick, use tabbycat.
$ sudo -u postgres createuser myusername --pwprompt

Tip

If you’ll be running multiple instances of Tabbycat, developing, or diving into the database yourself, you might find it convenient to set up client authentication so that you don’t need to do all manual operations from sudo -u postgres. See the PostgreSQL documentation on client authentication for more information. For example, you could add a local all myusername md5 line to the pg_hba.conf file, or you could define a mapping in pg_ident.conf and append the map= option to the local all all peer line in pg_hba.conf. If you want your new PostgreSQL account to be able to create databases, add --createdb to the above command.

  1. Create a new database, replacing mydatabasename with whatever name you prefer, probably the name of the tournament you’re running:

    $ sudo -u postgres createdb mydatabasename --owner myusername
    

4. Install Tabbycat¶

Almost there!

  1. Navigate to your Tabbycat directory:

    $ cd path/to/my/tabbycat/directory
    
  1. Start a new virtual environment. We suggest the name venv, though it can be any name you like:
$ python3 -m venv venv
  1. Run the activate script. This puts you “into” the virtual environment:

    $ source venv/bin/activate
    
  2. Install Tabbycat’s requirements into your virtual environment:

    $ pip install --upgrade pip
    $ pip install -r requirements_common.txt
    $ npm install
    
  3. Navigate to the tabbycat sub folder and copy local_settings.example to local_settings.py. Find this part in your new local_settings.py, and fill in the blanks as indicated:

DATABASES = {
    'default': {
        'ENGINE'  : 'django.db.backends.postgresql_psycopg2',
        'NAME'    : '',  # put your PostgreSQL database's name in here
        'USER'    : '',  # put your PostgreSQL login role's user name in here
        'PASSWORD': '',  # put your PostgreSQL login role's password in here
        'HOST':     'localhost',
        'PORT':     '5432',
    }
}
  1. Navigate to the tabbycat sub folder in the terminal, initialize the database, compile the assets, and create a user account for yourself:

    $ cd tabbycat
    $ dj migrate
    $ dj collectstatic
    $ dj createsuperuser
    
  2. Start Tabbycat!

$ waitress-serve wsgi:application

It should show something like this:

serving on http://0.0.0.0:8080
  1. Open your browser and go to the URL printed above. (In the above example, it’s http://0.0.0.0:8080.) It should look something like the screenshot below. If it does, great! You’ve successfully installed Tabbycat.
Bare Tabbycat installation

Naturally, your database is currently empty, so proceed to importing initial data.

Starting up an existing Tabbycat instance¶

To start your Tabbycat instance up again next time you use your computer:

$ cd path/to/my/tabbycat/directory
$ source venv/bin/activate
$ cd tabbycat
$ waitress-serve wsgi:application

Installing Locally on OS X¶

Before you start, be sure to read our page on local installations to help you understand what’s going on, particularly this section: Should I use a local installation, or one on the internet?

Requisite technical knowledge¶

You need to be familiar with command-line interfaces to get through this comfortably. While a background in the specific tools (Python, etc.) we use will make things easier for you, it’s not necessary: we’ll talk you through the rest. You just need to be prepared to bear with us. It’ll take a while the first time, but it gets easier after that.

Every line in the instructions that begins with $ is a command that you need to run in a Terminal, but without the $: that sign is a convention used in instructions to make it clear that it is a command you need to run.

Advanced users

Tabbycat is a Django project, so can be installed in any manner that Django projects can normally be installed. For example, if you prefer some SQL system other than PostgreSQL, you can use it so long as it’s Django-compatible. Just be aware that we haven’t tried it.

1. Install dependencies¶

First, you need to install all of the software on which Tabbycat depends, if you don’t already have it installed.

1(a). Python¶

As of version 0.8, Tabbycat requires Python 3.4 or later. OS X only comes with Python 2.7, so you’ll need to install this. You can download the latest version from the Python website.

The executable will probably be called python3, rather than python. Check:

$ python3 --version
Python 3.4.4

Warning

As of version 0.8, Python 2 is not supported. You must use Python 3.4 or higher.

Advanced users

These instructions will use the pyvenv module. If you prefer, you can use Virtualenv instead.

1(b). PostgreSQL¶

Download postgres.app, move it to your Applications folder, and open it. This should place an icon in your menu bar, showing that the postgres database is running. Whenever you are running Tabbycat you’ll need to have this app running.

1(c). Node.js/NPM¶

Download and run the node.js Mac OS X Installer (.pkg)

2. Get the source code¶

  1. Go to the page for our latest release.
  2. Download the zip or tar.gz file.
  3. Extract all files in it to a folder of your choice.

Advanced users

If you’ve used Git before, you might prefer to clone our GitHub repository instead. Don’t forget to check out the v1.1.7 tag or the master branch.

Even better, you might like to fork the repository first, to give yourself a little more freedom to make code changes on the fly (and potentially contribute them to the project).

3. Set up a new database¶

Hint

You can skip step 1 if this is not your first installation. Every Tabbycat installation requires its own database, but they can use the same login role if you like.

  1. Create a new user account with a password, replacing myusername with whatever name you prefer. If you don’t know what username to pick, use tabbycat.
$ createuser myusername --pwprompt

Tip

If you’ll be running multiple instances of Tabbycat, developing, or diving into the database yourself, you might find it convenient to set up client authentication so that you don’t need to do all manual operations from sudo -u postgres. See the PostgreSQL documentation on client authentication for more information. For example, you could add a local all myusername md5 line to the pg_hba.conf file, or you could define a mapping in pg_ident.conf and append the map= option to the local all all peer line in pg_hba.conf. If you want your new PostgreSQL account to be able to create databases, add --createdb to the above command.

  1. Create a new database, replacing mydatabasename with whatever name you prefer, probably the name of the tournament you’re running:

    $ createdb mydatabasename --owner myusername
    
  2. In terminal type in:

    $ PATH="/Applications/Postgres.app/Contents/Versions/9.5/bin:$PATH"
    

4. Install Tabbycat¶

Almost there!

  1. Navigate to your Tabbycat directory:

    $ cd path/to/my/tabbycat/directory
    
  2. Copy local_settings.example to local_settings.py. Find this part in your new local_settings.py, and fill in the blanks as indicated:

DATABASES = {
    'default': {
        'ENGINE'  : 'django.db.backends.postgresql_psycopg2',
        'NAME'    : '',  # put your PostgreSQL database's name in here
        'USER'    : '',  # put your PostgreSQL login role's user name in here
        'PASSWORD': '',  # put your PostgreSQL login role's password in here
        'HOST':     'localhost',
        'PORT':     '5432',
    }
}
  1. Start a new virtual environment. We suggest the name venv, though it can be any name you like:

    $ pyvenv venv
    
  2. Run the activate script. This puts you “into” the virtual environment:

    $ source venv/bin/activate
    
  3. Install Tabbycat’s requirements into your virtual environment:

    $ pip install --upgrade pip
    $ pip install -r requirements_common.txt
    $ npm install
    
  4. Navigate to the tabbycat sub folder, initialize the database, compile the assets, and create a user account for yourself:

    $ cd tabbycat
    $ dj migrate
    $ dj collectstatic
    $ dj createsuperuser
    
  5. Start Tabbycat!

$ waitress-serve wsgi:application

It should show something like this:

serving on http://0.0.0.0:8080
  1. Open your browser and go to the URL printed above. (In the above example, it’s http://0.0.0.0:8080/.) It should look something like the screenshot below. If it does, great! You’ve successfully installed Tabbycat.
Bare Tabbycat installation

Naturally, your database is currently empty, so proceed to importing initial data.

Starting up an existing Tabbycat instance¶

To start your Tabbycat instance up again next time you use your computer:

$ cd path/to/my/tabbycat/directory
$ source venv/bin/activate
$ cd tabbycat
$ waitress-serve wsgi:application

Installing Locally on Windows¶

Before you start, be sure to read our page on local installations to help you understand what’s going on, particularly this section: Should I use a local installation, or one on the internet?

Requisite technical background¶

You need to be familiar with command-line interfaces to get through this comfortably. While a background in the specific tools (Python, etc.) we use will make things easier for you, it’s not necessary: we’ll talk you through the rest. You just need to be prepared to bear with us. It’ll take a while the first time, but it gets easier after that.

In these instructions, we’ll use Windows PowerShell, a command-line interface that comes with every installation of Windows (since XP). The easiest way to find it (on Windows 7 and later) is to search for it in your Start Menu. Every line in the instructions that begins with > is a command that you need to run in PowerShell, but without the >: that sign is a convention used in instructions to make it clear that it is a command you need to run.

Advanced users

Tabbycat is a Django project, so can be installed in any manner that Django projects can normally be installed. For example, if you prefer some SQL system other than PostgreSQL, you can use it so long as it’s Django-compatible. Just be aware that we haven’t tried it.

1. Install dependencies¶

First, you need to install all of the software on which Tabbycat depends, if you don’t already have it installed.

1(a). Python¶

Python is a popular programming language, and the language in which the core of Tabbycat is coded.

Download and install Python 3.5 (or later) from the Python website. In the installer, check the box to add Python to your PATH (see box below).

Hint

Which file should I download?

  • If you have 32-bit Windows, choose the “Windows x86 executable installer”.
  • If you have 64-bit Windows (and not an Itanium processor), it’s better to choose the “Windows x86-64 executable installer”.
  • If you’re not sure whether you have 32-bit or 64-bit Windows, consult “About your PC” or “System Properties” in your Start Menu.

Attention

Please take note: Just after you open the installer, check the “Add Python 3.5 to PATH” box:

_images/python-windows-path.png

To check that Python is installed correctly, open Windows PowerShell, type python and press Enter. It should look something like this. If you installed the 32-bit version, it will say 32 bit instead of 64 bit.

_images/python-windows-installed.png

(To exit Python, type exit() then press Enter.)

Note

If you already have Python, great! Some things to double-check:

  • You must have at least Python 3.4, though we recommend Python 3.5.
  • Your installation path must not have any spaces in it.
  • If that doesn’t work, note that the following must be part of your PATH environment variable: C:\Python35;C:\Python35\Scripts (or as appropriate for your installation directory). Follow the instructions here to add this to your path.

1(b). PostgreSQL¶

PostgreSQL is a database management system.

Go to the PostgreSQL downloads page, then follow the link through to EnterpriseDB to download and install the latest version of PostgreSQL.

Tip

Once PostgreSQL is installed, the PostgreSQL service will run on your computer whenever you are using it. You might prefer to configure it so that it only runs when you want to run Tabbycat. To do this, open “Services” in your Control Panel on Windows, find the PostgreSQL service, and change its startup type to “Manual”. This will tell it not to start whenever you log in. Then, if you want to run the server (so you can use Tabbycat), you can do so from “Services” by selecting the PostgreSQL service and clicking “Start the service”.

1(c). Git¶

Git is a version control system.

We won’t use Git directly, but Node.js (which we install in the next step) requires Git to work. So, install the latest version for Windows from the Git website.

Advanced users

If you already have GitHub Desktop installed, you might think that this would be good enough. Unfortunately, it’s not—GitHub Desktop installs a portable version of Git. Node.js, on the other hand, requires the git to be in the PATH, so it can call it directly. The easiest (but not only) way to do this is just to install Git from the link above.

1(d). Node.js/NPM¶

Node.js is a JavaScript runtime.

Download and run the node.js Windows Installer (.msi)

2. Get the source code¶

  1. Go to the page for our latest release.
  2. Download the zip file.
  3. Extract all files in it to a folder of your choice.

Advanced users

If you’ve used Git before, you might prefer to clone our GitHub repository instead. Don’t forget to check out the v1.1.7 tag or the master branch.

Even better, you might like to fork the repository first, to give yourself a little more freedom to make code changes on the fly (and potentially contribute them to the project).

3. Set up a new database¶

Hint

You can skip steps 2 and 3 if this is not your first installation. Every Tabbycat installation requires its own database, but they can use the same login role if you like.

  1. Open the pgAdmin tool, which you installed as part of installing PostgreSQL. In the object browser on the left, double-click the server marked “(localhost:5432)”. Log in using the password you set during installation.
  2. Right-click Login Roles, and click “New Login Role…”
_images/pgadmin-new-login-role-menu.png
  1. Fill in the New Login Role box as follows (everything not listed below can be left as-is):

    • In the Properties tab, in Role Name, choose a user account name. (If you don’t know what to pick, we suggest “tabbycat”.)
    • In the Definition tab, choose a Password and type it in Password (again).

    Then click OK. (Remember this user name and password, you’ll need it later.)

  2. Right-click Databases, and click “New Database…”

_images/pgadmin-new-database-menu.png
  1. Fill in the New Database box as follows (everything not listed below can be left as-is):

    • In the Properties tab, in Name, choose a database name (with no spaces in it).
    • In the Properties tab, in Owner, type the name of the login role you just created.

    Then click OK. (Remember the database name, you’ll need it later.)

4. Install Tabbycat¶

Almost there!

  1. Open a Windows PowerShell. Navigate to the folder where you cloned/extracted Tabbycat. For example, if you installed it in C:\Users\myusername\Documents\GitHub\tabbycat, then run:

    > Set-Location C:\Users\myusername\Documents\GitHub\tabbycat
    
  2. Make a copy of local_settings.example and rename it to local_settings.py. Open your new local_settings.py. Find this part, and fill in the blanks (the empty quotation marks) as indicated:

DATABASES = {
    'default': {
        'ENGINE'  : 'django.db.backends.postgresql_psycopg2',
        'NAME'    : '',  # put your PostgreSQL database's name in here
        'USER'    : '',  # put your PostgreSQL login role's user name in here
        'PASSWORD': '',  # put your PostgreSQL login role's password in here
        'HOST':     'localhost',
        'PORT':     '5432',
    }
}
  1. Start a new virtual environment. We suggest the name venv, though it can be any name you like:

    > python -m venv venv
    
  2. Run the Activate.ps1 script. This puts you “into” the virtual environment:

    > .\venv\Scripts\Activate.ps1
    

Attention

If you get an error message saying that the script isn’t digitally signed, open a PowerShell with administrator privileges by right-clicking PowerShell in the Start meny and clicking “Run as administrator”. Then run this command:

> Set-ExecutionPolicy RemoteSigned

Read the warning message, then type y to confirm. By default, the execution policy on Windows is Restricted, which does not permit scripts like activate to be run. Changing it to RemoteSigned relaxes it to allow local scripts to be run without checking the signature.

  1. Install Tabbycat’s requirements.

If you installed 32-bit Python:

> python -m pip install --upgrade pip
> easy_install http://www.stickpeople.com/projects/python/win-psycopg/2.6.1/psycopg2-2.6.1.win32-py3.5.exe
> pip install -r requirements_common.txt
> npm install

If you installed 64-bit Python:

> python -m pip install --upgrade pip
> easy_install http://www.stickpeople.com/projects/python/win-psycopg/2.6.1/psycopg2-2.6.1.win-amd64-py3.5.exe
> pip install -r requirements_common.txt
> npm install

If you’re using a version of Python other than 3.5, replace the URL in the second line with the appropriate link from the win-psycopg page.

Note

The second line above is an extra step just for Windows. It installs the Windows version of psycopg2, win-psycopg, and must be done before pip install -r requirements_common.txt so that the latter doesn’t try to install the Unix version.

Hint

You might be wondering: I thought I already installed the requirements. Why am I installing more? And the answer is: Before, you were installing the requirements to create a Python virtual environment for Tabbycat to live in. Now, you’re in the virtual environment, and you’re installing everything required for Tabbycat to operate.

  1. Initialize the database and create a user account for yourself:

    > cd tabbycat
    > dj migrate
    > npm run gulp build
    > dj collectstatic
    > dj createsuperuser
    
  2. Start Tabbycat!

> waitress-serve wsgi:application

It should show something like this:

serving on http://0.0.0.0:8080
  1. Open your browser and go to the URL printed above. (In the above example, it’s http://0.0.0.0:8080/.) It should look something like this:
_images/tabbycat-bare-windows.png

If it does, great! You’ve successfully installed Tabbycat.

Naturally, your database is currently empty, so proceed to importing initial data.

Starting up an existing Tabbycat instance¶

To start your Tabbycat instance up again next time you use your computer, open a PowerShell and:

> Set-Location C:\Users\myusername\Documents\GitHub\tabbycat # or wherever your installation is
> .\venv\Scripts\activate
> cd tabbycat
> waitress-serve wsgi:application

Importing Initial Data¶

Once you’ve got Tabbycat installed, the next step is to import data for the tournament. The initial import requires details of all institutions, teams, speakers and adjudicators, and specifications for how many rounds and their properties. We don’t currently have a way of doing this from the web interface. There are a few ways to do it.

Note

With any method, the objective is to create one Tournament object, and Round, Venue, Institution, Team, Speaker, Adjudicator, AdjudicatorConflict and AdjudicatorInstitutionConflict objects for each round, venue, and so on

Manual setup¶

For sufficiently small tournaments, you might just choose to edit the database via the Django administrative interface (under Setup > Edit Database).

Caution

The Django administrative interface is very powerful, and naturally if you mess things up, you can insert potentially catastrophic inconsistencies into the database. When you’re setting up a tournament for the first time, this is highly unlikely to happen, but it’s worth keeping in mind.

  1. Open up your the admin area of your site by going to the URL with /admin/ on the end, e.g. if your URL root is 127.0.0.1:8000, then http://127.0.0.1:8000/admin/.
  2. Then click Tournaments and then Tournaments in the sidebar.
  3. Create a new Tournament object, and input all of its rounds
  4. Create the Venues (under Venues > Venues)
  5. Create the Institutions (under Participants > Institutions)
  6. Create the Teams, and input their speakers (under Participants > Teams)
  7. Create the Adjudicators, and input their conflicts (under Participants > Adjudicators)

Visual importer¶

For medium sized tournaments there are a number of tools that allow you to import information by copy and pasting from spreadsheets. Or by adding data in bulk and editing key information later.

  1. Open the “Import Data” area of the site under the Setup link in the menu (once your have created a tournament and logged in)
  2. Follow the instructions for each particular section

Note

If copy-pasting from a spreadsheet, it is often easiest to make values be separated by commas by saving the spreadsheet as a *.csv file, then opening said file in a plain text editor (such as Notepad or TextEdit) and copy/pasting from there.

The importtournament command¶

We’ve written a management command called importtournament to help automate the tournament set-up. The script, however, is neither foolproof nor comprehensive, so you might find you need to modify things slightly if your tournament structure is different from ours. Be prepared to try this a few times to get it to work. Nonetheless, this is probably the fastest way to set up a tournament.

  1. Copy and rename the data/demo folder
  2. See the CSV files in the new folder, and add/replace the data as per your tournament. Note that the institutions (i.e. first column) in the speakers.csv and adjudicators.csv files must match the institutions in the second column of the institutions.csv file. And that all CSV files must end with a blank line.
  3. Use this command, replacing YOUR_DATA_DIR with your new folder’s name. (Square brackets indicate optional arguments; if you use them, omit the square brackets. All of them relate to the name of your tournament.)
$ ./manage.py importtournament YOUR_DATA_DIR [--slug SLUG] [--short-name SHORT_NAME] [--name FULL_NAME]

This script has a number of options. They’re worth taking a look at before you run the script. For details, see:

$ ./manage.py importtournament --help
  1. Assuming the command completes successfully without errors, you should double check the data in the Django interface, as described above in Manual setup. In particular you should check that the Rounds have the correct draw types and that silent rounds have been marked correctly.

importtournament on Heroku installs¶

The importtournament script can be run on Heroku directly; you just need to commit and push your new data directory to your server first. See Installing on Heroku for details. If you have a local installation ready, you might like to iron out all the errors in your data until you can import locally without error, before pushing your data files to your server to be imported there.

If you want to import locally and push the database to the server, you can use the heroku pg:push command. We assume that, if you want to use this method, you know what you’re doing or are comfortable reading the Heroku documentation to find out. We’re happy to help if you have questions about this, but for most tournaments, committing the data to the server and running the script on the server directly will be easier.

Writing your own importer¶

If our suggested file formats cause you headaches, it might be easier to write your own importer. We have a generic importer framework that should make this easier, so for some tournaments it might (very conceivably) be faster to write your own importer to conform to your data, than it is to make your data conform to our importer. You need a background in Python in order to do this. For more details, see Tournament Data Importers.

Starting a Tournament¶

This page outlines a few things you should do at the start of a tournament, after you’ve imported the initial data. Once you’ve done these, proceed to running a tournament.

Caution

Tabbycat is developed for — and tested on — modern web browsers. If you are using Internet Explorer versions 8, 7, or 6 the interface may look odd or not function properly. Switch to a newer browser if possible.

Tournament configuration¶

After importing all your data you can log into the site as an administrator by loading up the homepage and then using the Login button in the lower-right. From there you should go to the administration section of your tournament, and then go to the tournament configuration page by clicking Setup then Configuration in the menu.

Here you can adjust the debate rules and interface options to your liking then hit Save when finished. We also offer a number of presets that apply particular rule sets (such as the Australs rules) or feature sets (such as displaying information normally released during briefs on the website).

Special data types and options¶

There are a few optional fields that are not covered in the initial data templates, in the visual importer, or that may only be relevant in particular scenarios. It’s worth going over these quickly to see if they are needed for your tournament. You can view and edit these fields in the Edit Database area (link is in the menu under Setup).

Adjudicator Feedback > Adj Feedback Questions
  • As described in Adjudicator Feedback, the types of questions that can be posed for adjudicator feedback are able to be heavily customised. If you are customising your feedback form it should be done here, and before the tournament starts.
Authentication and Authorisation > Users
  • Here you can add new admin users (those with full access) as well as new assistant users those (who can only do common data-entry tasks but not edit or view the full tab interface). See User Accounts for information on how to do this.

Note

The people you’re adding accounts for should be physically present when you do this, so that they can enter their password.

Participants > Regions
  • Optionally, each institution may belong to a Region. An institution’s region is used within the adjudicator allocation process to visually identify teams and adjudicators for the purposes of highlighting diversity issues. These have traditionally been used for geographic regions (such as Oceania), although could be repurposed as arbitrary markers of information — for example they could be used to denote teams from a particular State, institutional size, or circuit.
Participants > Adjudicators
  • An adjudicators Test Score represents their relative ability to judge important rooms, where adjudicators with higher numbers will, relative to the other adjudicators, be placed in better roles (ie as Chairs) and in the rooms you deem most important in each round. If you are running a small tournament, and plan to do your allocations manually, you can set everyone’s number to the same amount.
  • For larger tournaments, particularly those that collect feedback, see the Adjudicator Feedback section for more information on how test scores and other variables influence the automated allocation process.
  • Regardless of how you score the adjs, if you have changed the minimimum chairing score in settings, you’ll want to make sure there are enough adjudicators that meet this minimum threshold or the automated allocator may not function effectively.
  • All types of conflicts are assigned to the relevant adjudicator. Adjudicator’s can be conflicted against particular teams, particular institutions, and other adjudicators. Each of these is a located in a tab at the top of the page.
  • Each adjudicator’s gender is optional and is not displayed publicly; it is only shown in the adjudicator allocation interface
  • Each adjudicator’s pronoun is optional, and is only displayed if you use tabbycat to print the ballots and feedback sheets for each round.
Participants > Teams
  • Note the distinction here between full name and short name. The latter is used on pages where space is tight, such as the draw displays or the adjudicator allocation interface.
  • Note that “Uses institutional prefix” option. With this option on, a team from the ‘MUDS’ insttution named ‘1’ or ‘Gold’ would be displayed as ‘MUDS 1’ or ‘MUDS Gold’.
  • At present, setting a team’s type to Bye, Swing, or Composite only affects very particular circumstances, and should be considered unnecessary.
  • If you do have composite teams, and wish to have them be conflicted by adjudicators from each respective instutution, you’ll need to add a new team conflict to each adjudicator from each institution.
  • If you do have swing teams, or teams that are otherwise ineligible for breaking, this is typically handled through the breaks interface in the main site
Participants > Speakers
  • Each speaker’s gender is optional and is not displayed publicly; it is only shown in the adjudicator allocation interface
  • Each speaker’s pronoun is optional, and is only displayed if you use tabbycat to print the ballots and feedback sheets for each round.
Tournaments > Divisions
  • At the moment divisions are only useful for running tournaments that use round-robin style draws. Here, each division represents a draw pool within a round. Division support here is under development and not tested in many scenarios.
Tournaments > Tournaments
  • Note that tournaments can have a welcome message (useful for displaying maps and other information on the homepage).
Venues > Venues
  • A venue’s priority determines its priority in being allocated. If there are 20 debates, and 30 rooms, the 20 rooms with the highest priorities will be chosen. Furthermore, if particular debates are marked as important during the draw process, those debates will receive the rooms with the highest priorities. In this way you can give close rooms to members of the adj core, or give larger rooms to debates that will draw a large audience.
Venues > Venue Groups
  • Venue groups are not needed for most kinds of tournaments. Their purpose is to organise tournaments (mostly high school leagues) where debates take place across a number of different locations (ie at different schools).

Information for the briefing¶

If you’re using the online submissions feature, some things you should probably mention in the briefing:

  • Adjudicators must fill out ballots completely, including motions and venues—they are entered into the system.
  • There is a static URL for each person’s ballots and feedback forms. It can be bookmarked, or the page can refreshed after each round.
  • If people submit a result or feedback online, they should indicate that they have done so on the paper copy of their ballot.

Running a Tournament¶

Once you’ve finished the steps in Starting a Tournament, you’re ready to go! This page outlines what you would do for each round during the tournament. After the tournament, proceed to Finishing a Tournament.

The menu is on the side of the page. In the admin interface, tournament-wide pages (feedback, standings, and break) are at the top, while round-specific pages (check-ins, draw, and results) are in dropdown’s organised by each round;s abbreviation.

The workflow for each round is:

  1. Generate the draw
  2. Release the draw
  3. Have the debates
  4. Enter results
  5. Advance to the next round

Generating the draw¶

This is all done from an admin interface (i.e., by the tab director or adjudication core member):

  1. Set availability. For each round, you need to set the venue, team and adjudicator availability. To do this, click the round in the menu, then click Check-Ins. Here you can then go to the availability pages for venue, teams, and adjudicators, or check in everything at once. If going to the team/venues/adjudicators page, you would edit the availability and click Save changes then return to the overview page.
_images/checkins-page.png
  1. Generate the draw. Hit the Generate Draw button on the Check-Ins page. Follow the instructions to generate the draw.
_images/draft-draw.png

Note

Tabbycat will show you a draft draw before you confirm it. In the draft draw, it’ll show you details so that you can understand how it came up with the draw, pointing out pull-ups and conflict swaps and the like. This is for you to double-check. While there are some basic tests on the draw algorithm, it never hurts to sanity-check it again.

If you do find something wrong with a draft draw, you can edit the match-ups, but please also let us know what the problem was! You can find our contact details in the Authors section.

  1. After the draft draw has been confirmed, it will show the confirmed draw page.
_images/draw-without-adjs.png
  1. Click Edit Adjudicators and allocate adjudicators. It’s a good idea to save periodically, in case something goes wrong or you want to revert. See adjudicator allocation for more details about this process.
_images/adj-allocation1.png

Releasing the draw¶

Once you’re happy with your adjudicator allocation, you’re ready to start the round.

  1. Release to general assembly. From the (confirmed) Draw page, go to Show by Venue or Show by Team (whichever you prefer). Then put it up on the projector. There are automatic scroll buttons and buttons for changing text sizing.
_images/draw-by-venue.png

Caution

The main Draw page shows a ranked draw, i.e. teams can infer their position on the tab from the version on the admin interface. Unless you want to spare teams the fun of backtabbing, you probably don’t want them to see this. So you should turn the projector off before you log in to Tabbycat on the projected computer, and only turn it on once you have the Show by Venue or Show by Team draw up.

Tip

To avoid the site from being overloaded by anxious refreshers, we recommend not releasing the draw to the public until after it’s been seen by general assembly.

  1. Release to public. If you’re using the public draw function, use the Release to Public button to publicly display the draw page.
  2. Release motions to general assembly. Release the motions however you would normally release the motions. (Tabbycat won’t do this for you.)
  3. Enter and release motions. Enter the motion(s) for each round using the Edit Motions link, then use the Release Motions to Public button to publicly display them.

Note

Currently, it’s mandatory to enter motions into the system. (You don’t have to release them, just enter them.) We eventually intend to make it optional, but this is low priority. If you’d like it to be optional, please get in touch with us and we’ll accord it higher priority.

  1. Entering results. See Entering Ballots and Feedback for more details about this process.
  2. Enter debate results and feedback as they come in (and/or allow online entry of results and feedback).
  3. Both results and feedback entered in the tab room or online need to be confirmed before the results are counted. To confirm a debate ballot and the debate as a whole, the confirmed checkbox under Ballot Status should be ticket in addition to the Debate Status being set to Confirmed.

You can track data entry from the Overview page in an admin account (get there by clicking the tournament’s name in the menu).

Warning

For major tournaments, we don’t recommend entering any data from an admin’s account. This is because the admin interface (intentionally) does not enforce the data confirmation procedure.

Advancing to the next round¶

Once you’ve got all the results entered and confirmed, you’re ready to progress to the next round. This can be done by going to the Results area, and then using the Advance to Next Round button.

_images/results-page.png

Warning

When you advance to the next round, if you’ve enabled public results, the results for the current round (which is now the previous round) will be release to the public unless the round is marked as “silent” in the database. So if you’re careful about when results should be released, don’t change the current round until you’re ready to release those results.

Note

There is a design assumption that you will always want to release results for non-silent rounds before you start working on the draw for the next round. If this isn’t true for you, please get in touch with us so that we know. The workaround is to make all rounds silent, then unsilent them when you’re ready to release results.

Finishing a Tournament¶

This page outlines some final steps after the preliminary rounds.

Wrapping up¶

Tabs can be released using the Tab released option under Setup > Configuration.

Note that you probably want to turn off the Public ballots, Public feedback, Feedback progress, and Public draw features under Configuration at this stage as they no longer have any use.

You also want to go into the Edit Database area, find the tournament and hit “release all” so that the results for the final round can be released.

Adjudicator Feedback¶

You can set the questions that are used on adjudicator feedback forms. The only field that is permanently there is the score field, which is an overall score assessing the adjudicator. All other questions (including a generic comments section) must be defined if you want them to be on the form.

Currently, there are two methods of setting questions:

Most of what you need to know is explained in help text in the edit database area. (Even if you’re using importtournament, you might find the field descriptions in the edit database area helpful.) Some more details are here.

Answer types and options¶

Type Relevant options Appearance
checkbox - _images/checkbox.png
yes/no (dropdown) - _images/yesnodropdown.png
integer (textbox) min_value, max_value _images/integer-textbox.png
integer scale min_value, max_value _images/integer-scale.png
float min_value, max_value _images/float.png
text - _images/text.png
long text - _images/longtext.png
select one choices _images/select-one.png
select multiple choices _images/select-multiple.png

Options:

  • min_value and max_value specify the minimum and maximum allowable values in the field. Mandatory for “integer scale” types and optional for “integer (textbox)” and “float” types.

  • choices is used with “select one” and “select multiple” types, and is a //-delimited list of possible answers, e.g. biased//clear//concise//rambly//attentive//inattentive

  • required specifies whether users must fill out the field before clicking “submit”. This requirement is only enforced on public submission forms. It is not enforced on forms entered by tab room assistants.

    The exception to this is the “checkbox” type. For checkboxes, “required” means that the user cannot submit the form unless the box is checked. Think of it like an “I agree to the terms” checkbox. This isn’t a deliberate design decision—it’s just a quirk of how checkboxes work on web forms.

Want another answer type?¶

We don’t really intend to add any further complexity to the built-in feedback system. If the above answer types don’t cover your needs, we suggest using a third-party feedback system. You might be able to adapt SurveyMonkey, Google Forms or Qualtrics to your needs.

We may be persuaded to make an exception if the new question type you have in mind is easy to add: that is, if it is straightforward to implement using standard web page elements and fits into the existing questionnaire framework (see Different questionnaires below). If you think there is such a case, please contact us using the contact details in the Authors section.

Different questionnaires¶

Tabbycat allows you to specify two questionnaires: one for feedback submitted by teams, and one for feedback submitted by adjudicators. You must specify in each question whether to include the question in each questionnaire.

  • from_team, if checked, includes the question in feedback submitted by teams
  • from_adj, if checked, includes the question in feedback submitted by adjudicators

Who gives feedback on whom?¶

Tabbycat allows for three choices for which adjudicators give feedback on which other adjudicators:

  • Chairs give feedback on panellists and trainees
  • Chairs give feedback on panellists and trainees, and panellists give feedback on chairs
  • All adjudicators, including trainees, give feedback on all other adjudicators they have adjudicated with

You can set this in the feedback paths option under Setup > Configuration > Feedback. Your choice affects each of the following:

  • The options presented to adjudicators in the online feedback form
  • The printable feedback forms
  • The submissions expected when calculating feedback progress and highlighting missing feedback

The feedback paths option only affects feedback from adjudicators. Teams are always assumed to give feedback on the orallist, and they are encouraged to do so through hints on the online and printable feedback forms, but there is nothing technically preventing them from submitting feedback from any adjudicator on their panel.

Advanced users

If you need a different setting, you need to edit the source code. Specifically, you should edit the function expected_feedback_targets in tabbycat/adjfeedback/utils.py.

Unless we can be convinced that they are very common, we don’t intend to add any further choices to the feedback paths option. If your needs are specific enough that you need to differ from the available settings, they are probably also beyond what is sensible for a built-in feedback system, and we recommend using a third-party feedback system instead.

How is an adjudicator’s score determined?¶

For the purpose of the automated allocation, an adjudicator’s overall score is a function of their test score, the current round’s feedback weight, and their average feedback score. This number is calculated according to the following formula:

\textrm{score} = (1-w)\times\textrm{test score} + w\times\textrm{average feedback score}

where w is the feedback weight for the round.

Under this formula, each round’s feedback weight can be used to determine the relative influence of the test score vs feedback in determining the overall score. As an example, say that an adjudicator received 5.0 as their test score, but their average feedback rating has thus far been 2.0. If the current rounds’ feedback weight is set to 0.75, then their overall score would be 2.75. If the current round’s feedback weight is set to 0.5 their score would be 3.5. If the weight was 0, their score will always be their test score; if the weight was 1 it will always be their average feedback value.

It is common to set rounds with a low feedback weight value early on in the tournament (when feedback is scant) and to increase the feedback weight as the tournament progresses.

Note

A participant’s test score can, in conjunction with feedback weight, also be used as a manual override for an adjudicator’s overall ranking. At several tournaments, adjudication cores have set every round’s feedback weight to 0, and manually adjusted an adjudicator’s test score in response to feedback they have received and reviewed. In this way complete control over every adjudicator’s overall score can be exerted.

Note

If feedback from trainee adjudicators is enabled, any scores that they submit in their feedback are not counted towards that adjudicator’s overall score.

Adjudicator Allocation¶

The adjudicator allocation screen offers the ability to automatically generate an allocation and/or allow you to create an edit an allocation manually.

Creating an automatic allocation is as simple as hitting the Auto Allocate button. Before you do so however, you may want to change the ‘importance’ value of the debates — as defined in the column with the fire symbol. Debates with a higher importance value will receive a stronger panel.

Adjudicators can be dragged into position, or into the Unused section on the right. Dragging an adjudicator into the chair position, when an adjudicator is already there, will swap the pair.

_images/adj-allocation.png

Various kinds of information are displayed using different colour codes. When hovering over, or dragging an adjudicator:

  • Their conflicts with other adjudicators and teams will show as red highlights
  • Their institutional conflicts with other ajdudicators and teams will show as orange highlights
  • Teams and adjudicators they have previously seen will highlight blue.

These colors are also used when adjudicators are in positions where any of the above apply. IE, in a panel where the team and adjudicator are conflicted, each will be highlighted red. In addition, panels with odd numbers of adjudicators, or that are missing a chair will be highlighted purple.

In addition, if you have importer gender, regional, and/or assigned multiple break categories to the teams, you can turn on the toggles that display this information in the draw (it will also display a color key).

Backups¶

The backup utility isn’t part of Tabbycat. Heroku provides a very good backup utility for all sites hosted on Heroku, and for Heroku-based Tabbycat sites, we strongly recommend it.

You should always back up the database before deleting any data while in the Edit Database area, because deleting data cannot be undone. It is also a good idea to back up the database before doing anything in the Edit Database area, unless you’re very familiar and confident with editing the Tabbycat database directly.

You may, as a matter of standard practice at large tournaments, wish to back up the database twice per round: Once just after you’ve generated the draw and allocated adjudicators, and once just after you’ve finished entering results.

Installations on Heroku¶

Heroku provides a utility to easily back up and restore the entire site database.

If you don’t have the Heroku CLI¶

You can capture backups from the Heroku Dashboard:

  1. Go to the Heroku Dashboard and click on your app.
  2. Under Installed add-ons, go to Heroku Postgres.
  3. Scroll down, and click on the Capture Backup button.

You can’t restore a backup without the Heroku Command Line Interface (CLI), so if you end up needing your backup, you’ll need to install the Heroku CLI, and then follow the instructions below.

If you have the Heroku CLI¶

The best guide to backing up databases is the Heroku Dev Center’s PGBackups guide.

To capture a backup:

$ heroku pg:backups:capture

To restore a backup:

$ heroku pg:backups:restore

If you have multiple Tabbycat sites, you’ll need to specify which one by adding --app mytournamentname to the end of the command.

Local installations¶

There are lots of ways to back up local PostgreSQL databases, but we’d suggest using the pg_dump and pg_restore commands.

Breaks and Break Rounds¶

In Tabbycat, elimination rounds (sometimes called outrounds or the final series) are called “break rounds”, and the qualification of teams to compete in the elimination phase of a tournament is called the “break”.

About break categories¶

Tabbycat supports multiple and arbitrarily-named break categories. Most tournaments will have just one category, typically called “Open”, leading to the grand final. Some tournaments also have restricted-eligibility break categories, for example, for novice teams or teams for whom English is a second language.

Having multiple break categories is intended for tournaments where multiple parallel elimination phases derive from the same preliminary rounds (inrounds). It’s not for parallel but distinct competitions—for those, you should create distinct tournaments.

Break qualification rules¶

Tabbycat supports several break qualification rules, and each break category must be configured to use one of them. Most tournaments will use “Standard”, which is the default.

Rule name (string to use in importtournament CSV files) Description
Standard (standard) The top n teams break. This is the default, and most tournaments use this rule.
AIDA 1996 (aida-1996) The top n teams that are also in the top three teams from their institution break.
AIDA 2016 (Australs) (aida-2016-australs)

The top n teams that fulfil either of these criteria break:

  • They are in the top n teams overall, and in the top three teams from their institution.
  • They have at least as many wins as the nth-ranked team, and they are the top team from their institution.

If fewer than n teams fulfil either criterion, then the best teams not fulfilling the criteria are added to make n teams.

AIDA 2016 (Easters) (aida-2016-easters) As for AIDA 2016 (Australs), except that if fewer than n teams fulfil either criterion, then only the best teams who are in the top three teams from their institution are added to make n teams.
WADL division winners first (wadl-div-first) The division winners are taken first, then the best teams who did not win their division are added to make n teams.
WADL division winners guaranteed (wadl-div-guaranteed) The division winners are guaranteed to break, and the best teams who did not win their division are added to make n teams. (Teams are sorted in their original rankings, unlike the “division winners first” rule.)

Note

The break generators are somewhat more complex than described in the above table: among other things, they also handle cases where there is a tie for the last place in the break, and for those break categories marked “general”, they will show where ineligible teams would have broken, had they been eligible.

Setting up break categories and rounds¶

For each break category in your tournament, you need to do three things:

  1. Create (and name) a break category
  2. Create break rounds for the category
  3. Set the eligibility of teams to compete in the category

If you only have one break category (open) and you create your tournament using the “Create New Tournament” page, simply enter the number of teams in the break (e.g., 8 if you’re breaking to quarterfinals). Tabbycat will create the break category and break rounds for you. You’ll still need to set the eligibility of teams though, as in (3) below. For any further break categories, you’ll need to do all three steps yourself.

If you create your tournament using the importtournament command or in Edit Database, you’ll need to do all three steps above yourself.

1. Creating break categories¶

If using the importtournament command, there is an example file, break_categories.csv, that you can copy and adjust. If using Edit Database, add categories under Break Qualification > Break categories.

Most of the fields are self-explanatory or described on the Edit Database form, except for one: “rule”, which sets the break qualification rule. Permissible values are described in Break qualification rules above. If using importtournament, be sure to use the correct string (in brackets in the table). The rule defaults to “Standard” (standard).

Note

The “institution cap” field was removed in Tabbycat 1.0. All Australs break qualification rules are now hard-coded to a cap of three teams per institution.

2. Creating break rounds¶

You should create a round for every break round you intend to hold, including it in rounds.csv if using importtournament, or adding them under Tournaments > Rounds if using Edit Database. Be careful to set the following fields correctly:

  • Break category must be set to the relevant break category.
  • Stage must be set to “Elimination”.
  • The first elimination round must have its draw type set to “First elimination”.
  • All other elimination rounds must have their draw types set to “Subsequent elimination”.

3. Setting break eligibility¶

Once a break category has been created it will not have any teams eligible for it, even if it was marked as “Is general”. To edit the eligibility of teams for any break round go to the Breaks item in the left-hand menu for a particular tournament and then click Edit Eligiblity.

Here you can select “all” or “none” to toggle all team eligiblities or edit them using the tick boxes. Once you save it should return you to the main break page which will display the number of teams marked eligible.

Note

Adjudicators can be marked as “breaking” on the Feedback page; clicking Adjudicators on the breaks page will take you straight there.

Generating the break¶

Unlike team or speaker standings, each category’s break (and the break ranks of teams) are not determined automatically and updated continuously. Instead each can be generated (and regenerated) as desired.

To do so go to the Breaks item in the left-hand menu and then click the white button that corresponds to the break category you’d like to determine the rankings for. When prompted, select Generate the break for all categories to display the list of breaking teams.

From this page you can update the breaking teams list for this break category (or all categories) as well as view and edit ‘remarks’ that account for cases in which a team may not break (such as being capped or losing a coin toss).

Caution

Please double-check the generated break before announcing or releasing it. Although the break generation code is designed to handle edge cases, we don’t test the code for such cases.

Creating draws for break rounds¶

Creating a draw for a break round proceeds as normal, except that the team check-in process is skipped. Instead, when you visit the check-ins page for that round it will have automatically determined which teams should be debating based upon the determined break for that category. Once a draw has been generated it will then use the relevant break ranks to create the matchups (ie 1st-breaking vs 16th-breaking, 2nd vs 15th, etc.). Subsequent break rounds will then also automatically determine matchups based on the previous round’s results and the initial break ranks of each team.

If the “break size” of a break category is not a power of 2, it will treat the first break round as a partial-elimination draw and only create a draw for the teams not skipping the partial-elimination round. Subsequent break rounds will then process as described above.

Entering Ballots and Feedback¶

Ballot check-in¶

For tournaments that require it, there is a “ballot check-in” page that can be used to record the arrival of ballots to the tab room. When there’s a missing ballot, it can help establish whether the ballot never made it to the tab room, or whether it’s probably floating around in the room forgotten. Also, it can help enforce early checks that panels return the correct number of ballots to the room.

To get to the ballot check-in, click the relevant round in the menu of the admin interface, and then click “Results” and then “Ballot Check-In”. This requires superuser privileges.

There’s no adverse effect from not using the ballot check-in. Data enterers will still be able to enter and confirmed ballots, even if not checked in.

Tip

  • Since the ballot check-in tends to require a dedicated computer or two, it can be worth creating a separate superuser account for ballot check-in, so that it doesn’t appear on the action logs as being by a particular person.
  • Don’t forget to provision a computer or two for this if you’re planning to use it.
  • Ballot check-ins can be a bottleneck, so you might decide they’re not worth using. Alternatively, you might have multiple computers for this purpose, or you might dedicate a tab room helper to driving the process (since this is probably faster than runners doing the typing in turn).

Ballot entry¶

_images/ballot-entry.png

Most tab rooms run some sort of check system to ensure data is entered accurately. In Tabbycat, this is built into the system, which also helps speed it up.

As a general principle, Tabbycat requires all ballots to be looked at by two people. The first person enters the data from the ballot, and the second person checks it. The second person isn’t allowed to modify the data—they either confirm it or reject it, and if they reject it, then the whole process starts again. This is by design: to be confirmed, the same data must have been seen by at least two people.

Caution

The Tabbycat admin interface does not work like this. It’s designed to be flexible, so allows you to edit, confirm or unconfirm any ballot at any time. For this reason, you should not use the Tabbycat admin interface for general data entry. If a tab director or adjudication core member will be entering data, they should have a separate account for this purpose.

Tip

  • Don’t forget to check the totals against the ballot—they’re a useful integrity check too.
  • Don’t forget to check the winner against the ballot! If the adjudicator gets it wrong, it’s worth asking to clarify.
  • It can be helpful to think about the room layout to maximize efficiency.
  • Some tab rooms like to assign some to data entry and some to verification. This isn’t really necessary, since Tabbycat doesn’t let the same person enter and verify the same ballot. (This is one of many reasons why every person should have their own account.)

Speakers who speak twice¶

Note that the ballot entry interface will not let you have a single person speak in more than one position. If a speaker is ‘iron manning’ the best approach is to go into the Edit Database section (under Setup in the admin area’s menu) and add a new speaker to that team for this purpose. Once in the Edit Data section, go to Participants then Teams then the Speakers tab. Typically it is best practice to indicate in their name they are delivering a second speech (ie “Jane Smith Repeat”) and to assign them the position that received the lower of the two scores.

Tip

There is a option under Standings in the Config section that specifies the number of debates that you can miss before you will not show on the tab. By default it is set to 1, but if need be this can be increased to hide these ‘fake’ speakers from the final speaker tab.

Feedback entry¶

_images/adding-feedback.png

Feedback doesn’t have the same verification process as ballots. Feedback that is entered by the tab room is assumed to be confirmed. If feedback is entered multiple times, all copies are retained but only the last one “counts” (is considered confirmed).

Online ballot submissions¶

Todo

We haven’t written this documentation yet.

Online feedback submissions¶

Todo

We haven’t written this documentation yet.

Draw Generation¶

The draw generator is quite flexible. You can specify a number of settings to suit different tournaments’ rules.

Options¶

The options discussed here are set in the Config page as described in starting a tournament.

Caution

The valid options for intermediate bubbles change depending on whether sides are pre-allocated, but these are not checked for validity. If you choose an invalid combination, Tabbycat will just crash. This won’t corrupt the database, but it might be momentarily annoying.

Summary¶

Option Description Allowable values
Draw odd brackets How to resolve odd brackets
  • Pull up from top
  • Pull up from bottom
  • Pull up at random

If sides are Random or Balance:

  • Intermediate
  • Intermediate with bubble-up-bubble-down

If sides are Pre-allocated:

  • Intermediate 1
  • Intermediate 2
Draw side allocations How to allocate aff/neg
  • Random
  • Balance
  • Pre-allocated
  • Manual ballot
Draw pairing method How to pair teams within brackets
  • Slide
  • Fold
  • Random
  • Adjacent
Draw avoid conflicts How to avoid history/institution conflicts
  • Off
  • One-up-one-down

Odd bracket resolution¶

The draw odd brackets option specifies what you do when a bracket has an odd number of teams. (Obviously you have to do something, otherwise you can’t pair off teams within the bracket.) There are two groups of methods: pull-up and intermediate bubbles.

  • Pull-up methods take one or more teams from the next bracket down, and move them into the odd bracket to fill the bracket.
  • Intermediate bubbles take the excess teams from the odd bracket and move them down into a new bubble, which sits between the odd bracket and the next one down (hence the name “intermediate”). It then takes one or more teams from the next bracket down and moves them to fill the new intermediate bubble.

The exact mechanics depend on whether or not sides are pre-allocated.

When sides are not pre-allocated¶

Pull-up methods take a team from the next bracket down, and add them to the odd bracket to form an even bracket. You might pull up the top team from the next bracket, or the bottom team, or a randomly chosen team.

Intermediate bubbles take the bottom team from the odd bracket and match them against the top team from the next bracket. An intermediate bubble always has two teams.

If you’re using conflict avoidance and intermediate bubbles, you will probably want to use Intermediate with bubble-up-bubble-down instead. This uses the “bubble-up-bubble-down” rule to swap teams out of an intermediate bubble if there is a history or institution conflict. This is defined in the Australs constitution and is analogous to the “one-up-one-down” rule.

Caution

Using Intermediate with One-up-one-down does not imply Intermediate with bubble-up-bubble-down. You must enable Intermediate with bubble-up-bubble-down specifically.

When sides are pre-allocated¶

When sides are pre-allocated, an “odd bracket” is one that has an uneven number of affirmative and negative teams. (So odd brackets can have an even number of teams, e.g. 4 affs and 2 negs.)

Pull-up methods take as many teams from the next bracket down as necessary to fill the bracket. If there aren’t enough teams in the next bracket down, it will take teams from the bracket after that, and so on, until the (original) odd bracket is filled. Higher brackets are always filled first. You might pull up the top teams from the next bracket, the bottom teams, or a random selection of teams.

Intermediate bubbles take the unpaired teams in a bracket, and move them down to a new intermediate bubble. It then takes the number of teams necessary from the opposite side, from the next bracket down, to fill the next bubble.

Intermediate 1 and Intermediate 2 differ only in what happens if there aren’t enough teams in the next bracket to fill the intermediate bubble. In Intermediate 1, it will just take teams from the bracket after that, and so on, until the intermediate bubble is filled. In Intermediate 2, it will split the intermediate bubble: the teams that can be paired with the next bracket form the first intermediate bubble, and then the teams that aren’t form a new (unfilled) intermediate bubble, to be filled from teams from the bubble after that. This keeps going, splitting into as many intermediate bubbles as necessary, until all excess teams from the original odd bracket are paired.

Side allocations¶

There are four methods:

  • Random allocates randomly. Some tournaments might like this, but most will probably want to use balance, because Random doesn’t guarantee that a team won’t be (say) affirming the entire tournament.
  • Balance assigns the team that has affirmed less so far the affirmative side (and, therefore, the team that has negated less the negative side). If both teams have affirmed the same number of times, it assigns sides randomly.
  • Preallocated is used for pre-allocated sides. If used, you must enter data for pre-allocated sides into the database, as specified below.
  • Manually enter from ballot is used for tournaments where the sides of the teams involved are not assigned in advance, but are instead determined by the teams themselves
Pre-allocated sides¶

There isn’t currently any way to edit side allocations from the front end. To do so from the back end, you need to create one TeamPositionAllocation entry for each team in each round. All teams must have an allocation for every round. There are a few ways to do this, take your pick:

  • If you’re using the importtournament command, it reads sides from the file sides.csv.
  • You can do this from the Django admin interface (under Setup > Edit Database) by going to the relevant team and adding a team position allocation entry. That is:
    1. Click Admin on the bottom right of any page after logging into an account with superuser access.
    2. Next to Teams, click Change.
    3. Click on the name of the team you want to edit side allocations for.
    4. Add or edit the entry or entries in the Team position allocations table at the bottom.
  • You can also do this by writing a script that creates TeamPositionAllocation objects and saves them. Have a look at data/utils/add_random_side_allocations.py for an example.

Pairing method¶

It’s easiest to describe these by example, using a ten-team bracket:

  • Fold: 1 vs 10, 2 vs 9, 3 vs 8, 4 vs 7, 5 vs 6. (Also known as high-low pairing.)
  • Slide: 1 vs 6, 2 vs 7, 3 vs 8, 4 vs 9, 5 vs 10.
  • Random: paired at random within bracket.
  • Adjacent: 1 vs 2, 3 vs 4, 5 vs 6, 7 vs 8, 9 vs 10. (Also known as high-high pairing.)

Teams are always paired within their brackets, after resolving odd brackets.

Conflict avoidance method¶

A conflict is when two teams would face each other that have seen each other before, or are from the same institutions. Some tournaments have a preference against allowing this if it’s avoidable within certain limits. The draw avoid conflicts option allows you to specify how.

You can turn this off by using Off. Other than this, there is currently one conflict avoidance method implemented.

The One-up-one-down method is the method specified in the Australs constitution. Broadly speaking, if there is a debate with a conflict:

  • It tries to swap teams with the debate “one up” from it in the draw.
  • If that doesn’t work, it tries to swap teams with the debate “one down” from it in the draw.
  • If neither of those works, it accepts the original conflicted debate.

It’s a bit more complicated than that, for two reasons:

  • History conflicts are prioritised over (i.e., “worse than”) institution conflicts. So it’s fine to resolve a history conflict by creating an institution conflict, but not the vice versa.
  • Each swap obviously affects the debates around it, so it’s not legal to have two adjacent swaps. (Otherwise, in theory, a team could “one down” all the way to the bottom of the draw!) So there is an optimization algorithm that finds the best combination of swaps, i.e. the one that minimises conflict, and if there are two profiles that have the same least conflict, then it chooses the one with fewer swaps.

Known tournaments draw options¶

The settings that should be used for some tournaments are as follows:

Tournament Setting Suggested value
Australs Odd brackets Intermediate with bubble-up-bubble-down or Pull up from top
  Side resolution Balance
  Pairing method Slide
  Avoid conflicts One-up-one-down
Joynt Scroll Odd brackets Intermediate 1 or Intermediate 2
  Side resolution Pre-allocated
  Pairing method Fold
  Avoid conflicts Off

What do I do if the draw looks wrong?¶

You can edit match-ups directly from the draw page. Technically, you can do anything you want. Of course, operationally, you should only edit the draw when you know that the draw algorithm got something wrong. If you need to do this, even just once, please file a bug report by creating a new issue on our issues page on GitHub.

Technical notes¶

Note

The information in this section should be read in conjunction with the source code documentation.

The draw module is based around DrawGenerator, a factory function that returns a subclass of BaseDrawGenerator. DrawGenerator takes two mandatory arguments: draw_type, a string, and teams, a list of Team-like objects.

As a design principle, the draw module does not rely on internal knowledge of models.py. Rather, to enforce abstraction and to ease unit testing, it is written as a stand-alone module that could, in principle, be used by other applications. Therefore, it defines an interface and uses duck-typing to work with inputs.

Team-like objects are the main part of this interface. The draw module doesn’t provide a base object for Team-like objects, nor does it expect them to be a Django model or be called Team. Rather, it merely expects Team-like objects to have certain attributes, depending on the options passed to DrawGenerator. For example, for power-paired draws, Team-like objects must have the points attribute. (For further details, refer to the source code.) Because DrawGenerator returns the same objects in some methods, Team-like objects must be hashable.

The make_draw() method returns a list of Pairing objects. The Pairing class is defined in the draw module. Its teams attribute (and all attributes derived from it) contain the same Team-like objects that were passed to DrawGenerator.

Printing Ballots and Feedback¶

Tabbycat offers the ability to print scoresheets and feedback sheets on a per-round basis. This means that each scoresheet is customised to match the draw, and so will display:

  • The motion or possible motions that could have been chosen from
  • The teams, and a list of speakers for each team
  • The room number, and name of the adjudicators present

Feedback sheets will also be customised in this manner; displaying:

  • A ‘from’ source. Sheet will be printed for each possible piece of feedback in that room: ie adjudicators will each get a sheet for their panellists and trainees while teams and panellists will get sheets for the chair.
  • The specific questions you established when configuring the adjudicator feedback questions
  • The room number

To print the ballots for each round, you would go to the Draw page for that round, the click one of the two print links above the table. This opens a new window. In each window, you then use your browser’s print function (CTRL-P). In the print window you’ll want to turn background graphics on, header/footers off, and set the layout to portrait (feedback sheets) or landscape (score sheets).

Typically you’d save these to PDF for printing, although you should be able to print straight from this dialouge box.

Caution

Printing works best in Safari and Firefox; use those if possible.

Team Standings Rules¶

In Tabbycat, you can choose how teams are ranked in the team standings. For example, at Australs, teams are ranked first on the number of wins, and second on their total speaker score. The setting that specifies how teams are ranked is called the team standings precedence. The team standings precedence is used

  • when displaying the team tab,
  • whenever a power-paired draw is generated, and
  • when computing which teams are in the break.

When you choose the team standings precedence, you choose from a list of metrics. Then, in the standings, teams will be sorted first by the first metric, then by the second metric, and so on. You must choose at least one metric, and you can choose up to eight. Teams tied on all metrics will have the same rank.

Metric Description
Wins How many debates the team has won.
Points How many points the team has. Currently, this is just a synonym for wins, and differs only in column labelling.
Points (2/1/0) How many points the team has, where teams earn 2 points for a win, 1 point for a loss and 0 points for a forfeit.
Total speaker score The sum of all speaker scores attained in all debates.
Average speaker score The average total speaker score over all debates the team has had, not counting debates where they or their opponents forfeited.
Sum of margins The sum of all margins. Wins are positive, losses are negative.
Average margin The average margin over all debates the team has had, not counting debates where they or their opponents forfeited.
Draw strength

The sum of the number of wins of every team this team has faced so far.

This is also known in some circuits as win points, opp wins or opp strength.

Votes/ballots carried

The number of adjudicators that gave this team a win across all of their debates. Also known as the number of ballots or judges a team has.

In cases where the panel is smaller or larger than 3, this number is normalised to be out of 3. For example, if a panel of five splits 3–2, then the winning team is recorded as gaining 1.8 votes, and the losing team is recorded as gaining 1.2. This also means that solo adjudicators are always worth three votes.

Who-beat-whom

If there are exactly two teams tied on all metrics earlier in the precedence than this one, then check if the teams have faced each other. If they have, the team that won their encounter is ranked higher. If they have seen each other more than once, the team that has won more of their encounters is ranked higher.

If there are more than two teams tied, this metric is not applied.

This metric can be specified multiple times. Each time who-beat-whom occurs, it applies to all the metrics earlier in the precedence than the occurrence in question.

Who-beat-whom (in divisions) As for who-beat-whom, but only compares for teams in the same division. That is, the metric applies whenever there are exactly two teams from the same division exactly tied.

Note

Some debugging information is printed to the logs when some of these metrics are invoked.

Tournament Data Importers¶

This page describes how to write your own tournament data importer. It is aimed at an audience that is familiar with programming in Python, and may be willing to get their head around the Django model if necessary.

The tournament data importer is the class that imports data from one or more files (usually CSV files) into the database. A base class BaseTournamentDataImporter is in importer/base.py. An example of a data importer is in importer/anorak.py.

Todo

This page is incomplete. If you’re finding this information insufficient, please contact Chuan-Zheng using the contact details in the Authors section.

Why write your own?¶

While Tabbycat has standard import formats, you might find that none of them fit the data that you need to import.

It’s not possible to devise a single, universally-convenient import file format. Tabbycat supports way too many permutations of configurations for this to be workable. Instead, we provide the ones that have been useful before and are therefore likely to be useful again—but if your tournament has different needs, you might decide that it’s easier to write an importer to conform to you, rather than conform to the importer.

A base importer class abstracts away most of the nitty-gritty of parsing files, allowing new importers to focus on their interpretation with as little code as possible.

To allow new importers to be written with as little code as possible, most of the work is abstracted to the base class. The flipside of this abstraction is that it induces a learning curve.

Basic workflow¶

  1. Choose a name. We name importers after items of clothing in alphabetical order (starting at ‘Anorak’).
  2. Write a subclass of BaseTournamentDataImporter.
  3. Write the front-end interface. This will probably be a Django management command.

A basic example¶

It’s easiest to start with an example. Here’s a basic importer with just one import method, which imports adjudicators.

from .base import BaseTournamentDataImporter, make_lookup, make_interpreter
from participants.models import Person, Adjudicator

class ExampleTournamentDataImporter(BaseTournamentDataImporter):

    lookup_gender = make_lookup("gender", {
        ("male", "m"): Person.GENDER_MALE,
        ("female", "f"): Person.GENDER_FEMALE,
        ("other", "o"): Person.GENDER_OTHER,
    })

    def import_adjudicators(self, f):
        """Imports adjudicators. `f` is a file object."""
        interpreter = make_interpreter(
            institution=Institution.objects.lookup,
            gender=self.lookup_gender,
            tournament=self.tournament
        )
        counts, errors = self._import(f, Adjudicator, interpreter)
        return counts, errors

Let’s break this down. The method import_adjudicators() takes a single argument, a file object representing the CSV file. Most of the work is passed off to self._import(). This helper method is defined in BaseTournamentDataImporter and is where most of the intelligence lies.

When called, self._import(f, model, interpreter) does the following:

  1. It reads the CSV file using a csv.DictReader. A DictReader iterates through the CSV file, yielding a dict for each line, whose keys are given by the column header names in the first row of the file.
  2. On each line:
  1. It passes the dict given by the DictReader to interpreter. The interpreter modifies the dict (or creates a new one) to prepare it for the model constructor, and returns it.
  2. The dict returned by interpreter is then passed as keyword arguments to the model constructor.

So in very simplified form, self._import(f, model, interpreter) does this:

def _import(self, f, model, interpreter):
    reader = csv.DictReader(f)
    for line in reader:
        kwargs = interpreter(line)
        inst = model(**kwargs)
        inst.save()

(There’s a lot more to it than that, but that’s the basic idea.)

Important

A consequence of relying on column headers to identify fields is that the header names in CSV files must match model field names exactly, unless they are deleted by the interpreter using the DELETE keyword (see below).

Interpreters¶

The main task of an importer, then, is to provide interpreters so that self._import knows how to interpret the data in a CSV file. An interpreter takes a dict and returns a dict. For example:

def interpreter(line):
    line['institution'] = Institution.objects.lookup(line['institution'])
    line['gender'] = self.lookup_gender(line['gender'])
    line['tournament'] = self.tournament
    return line

This interpreter does the following:

  • Replaces line['institution'] with an Institution object, by looking up the original value by name.
  • Replaces line['gender'] with a Person.GENDER_* constant. We’ll come back to how this works later.
  • Adds a new line['tournament'] entry to the dict, being the Tournament object represented by self.tournament, the tournament that was passed to the importer’s constructor.
  • Leaves all other entries in the dict unchanged.

This looks simple enough, but it’s very robust. What if a cell in the CSV file is blank, or what if the file omits a column? (For example, some tournaments might not collect information about participant gender, so Tabbycat doesn’t require it.) We could deal with these scenarios on a case-by-case basis, but that’s cumbersome.

Instead, we provide a make_interpreter method that returns an interpreter method which, in turn, takes care of all these details. This way, all you have to do is provide the functions that transform fields. So the following is equivalent to the above, but better:

interpreter = make_interpreter(
    institution=Institution.objects.lookup,
    gender=self.lookup_gender,
    tournament=self.tournament
)

Notice that we provided a callable in two of these keyword arguments, and a (non-callable) Tournament object to the third. make_interpreter is smart enough to tell the difference, and treat them differently. What it does with each field depends on (a) whether a value exists in the CSV file and (b) what transformation function was provided, as summarised in the following table:

Value in CSV file Transformation Action
  provided and not callable populate model field with interpreter value
does not exist or blank callable or not provided do not pass to model constructor
exists and not blank callable call interpreter on column value, pass result to model constructor
exists and not blank not provided pass column value directly to model constructor

Tip

  • If a transformation isn’t an existing method, you might find lambda functions useful. For example: lambda x: Speaker.objects.get(name=x).
  • You shouldn’t check for mandatory fields. If a mandatory field is omitted, the model constructor will throw an error, and self._import() will catch the error and pass a useful message on to the caller. On the other hand, if it’s an optional field in the model, it should optional in the importer, too. Similarly, interpreters generally shouldn’t specify defaults; these should be left to model definitions.
  • You don’t need to include interpreter transformations for things like converting strings to integers, floats or booleans. Django converts strings to appropriate values when it instantiates models. So, for example, adding test_score=float to the above interpreter would be redundant.

More complicated interpreters¶

If you have a column in the CSV file that shouldn’t be passed to the model constructor, you can tell the interpreter to remove it by using the special DELETE argument:

interpreter = make_interpreter(
    institution=Institution.objects.lookup,
    DELETE=['unwanted_column_1', 'unwanted_column_2']
)

The make_interpreter can only deal with modifications where each field is modified separately of the others (or not at all). If you want to combine information from multiple fields, you need to write your interpreter the long way (perhaps calling a function returned by make_interpreter to do some of the work).

On the other hand, if you don’t need to do any transformations involving some sort of object or constant lookup, then you can just omit the interpreter argument of self._lookup(), and it’ll just leave the fields as-is.

Lookup functions¶

In the above example, we used a function self.lookup_gender to convert from the text in the CSV file to a Person.GENDER_* constant. To make this easier, the importer provides a convenience function to define such lookup functions. Let’s look at the relevant lines again:

lookup_gender = make_lookup("gender", {
    ("male", "m"): Person.GENDER_MALE,
    ("female", "f"): Person.GENDER_FEMALE,
    ("other", "o"): Person.GENDER_OTHER,
})

This should be a member of your subclass, in our case, ExampleTournamentDataImporter. It generates a function that looks something like:

@staticmethod
def lookup_gender(val):
    if val in ("male", "m"):
        return Person.GENDER_MALE
    elif val in ("female", "m"):
        return Person.GENDER_FEMALE
    elif val in ("other", "o"):
        return Person.GENDER_OTHER
    else:
        raise ValueError("Unrecognised value for gender: %s" % val)

The make_lookup function takes two arguments. The first is a text description of what it’s looking up; this is used for the error message if the value in the CSV file isn’t recognised. The second is a dict mapping tuples of valid strings to constants.

Debugging output¶

The BaseTournamentDataImporter constructor accepts a loglevel argument:

importer = MyTournamentDataImporter(tournament, loglevel=logging.DEBUG)

If loglevel is set to logging.DEBUG, the importer will print information about every instance it creates.

You can also pass in a logger for it to use (instead of the default one) with the logger argument.

User Accounts¶

For obvious reasons, user logins are required to data entry and administrative functions. There are (conceptually) four levels of access:

Access Should be used by Grants access to Is capable of
Public The public Publicly available information. Viewing things, and submitting new ballots/feedback if that function is enabled.
Assistant Data entry helpers Specialised data entry (ballots and feedback). Entering and confirming ballots and feedback.
Superuser Adjudication core The Tabbycat admin interface. Generating draws, editing ballots, feedback and adjudicator scores, checking in ballots and people.
Staff Tab director The Tabbycat and edit database interfaces. Editing the database directly.

Account roles¶

If the adjudication core and tab directors will be helping with data entry, you should create a “assistant” account for them as well. These people will then have two accounts each: one with assistant access, which is used for data entry, and one with superuser access, which is used for everything else.

Specifically, the Tabbycat admin interface should not, in general, actually be used for data entry. That interface doesn’t include some checks that are important for data integrity assurance. It should be used only to override the normal data entry procedure, for example, to unconfirm a ballot or edit a score.

The Edit Database interface should certainly not be used except where it is actually necessary. There are a few functions which require this, but as a principle, it shouldn’t be used as a matter of course.

Adding accounts¶

To add an account:

  1. Go to BASE_URL/admin/auth/user/ and click “Add user” in the top right.
  2. Ask the user to enter a username and password.
    • Only they should know what the password is.
    • If you’re hosting on the internet, all passwords should be at least moderately strong!
    • Passwords are stored as hashes, not as raw passwords, so it’s (in theory, practically) impossible for you to figure out what their password is.
  3. What you do next depends on what sort of account you’re creating:
    • If this is an assistant account, click “Save” or “Save and add another”. (Any account not marked staff or superuser is an assistant account.)
    • If they’re being assigned superuser and/or staff privileges, then click “Save and continue editing”, and check the appropriate boxes before clicking “Save”.
    • If you also wanted their names to be associated with their accounts, click “Save and continue editing” and fill out the relevant fields. But their names etc. aren’t used for anything by Tabbycat.

Venue Constraints¶

Tabbycat supports a basic form of venue constraints. A venue constraint is a requirement that a particular team, adjudicator, institution or division be assigned to a venue in a particular venue group. Typical uses would include:

  • Meeting venue accessibility requirements of particular teams (e.g. step-free access)
  • Placing adjudication core and tab team members close to the tab room
  • Keeping all debates in a division in one location

Constraints apply to venue groups, not individual venues. That is, you specify that (say) a team should be given a venue from a particular list of venues. Of course, it’s permissible for a venue group to have only one venue in it.

The algorithm used to satisfy venue constraints is not guaranteed to be optimal. In some rare cases, it may propose an allocation that fails some constraints, even though some other allocation would have satisfied all (or more) constraints. In almost all practical circumstances, however, it should work, and save human effort (and time) in specially allocating rooms.

Adding venue constraints¶

To add a venue constraint, go to the Edit Database section (under Setup), scroll down to “Venues”, and you will see four times of venue constraints:

  • Adjudicator venue constraints
  • Division venue constraints
  • Institution venue constraints (apply to teams, not adjudicators)
  • Team venue constraints

Click the type of constraint you’re like to add, then click the + Add [type] venue constraint button in the top-right of the page.

For each constraint, you need to specify three things:

  • The adjudicator, division, institution or team demanding the constraint
  • A venue group
  • A priority

The priority is only used to resolve conflicts between constraints. If none of your constraints will ever conflict, then the priority is arbitrary.

Applying venue constraints¶

Venue constraints are applied automatically when the draw is generated. However, at this point, only team, institution and division constraints can be accounted for. Generating the draw doesn’t generate an adjudicator allocation, so if there are any adjudicator venue constraints, they won’t be taken into account.

If after you allocate adjudicators, or at any other point (say, after adding a new venue constraint), you would like to re-run the venue allocation algorithm, you can do so under Edit Venues (while looking at the draw), then in the screen where you can edit venues, click the Auto Allocate button.

If a venue constraint couldn’t be met, a message will show in the “conflicts/flags” column of the draw. A constraint might not be met for a number of reasons:

  • It could be that constraints of different parties (say, one team and one adjudicator) conflicted, so only one could be fulfilled.
  • It could be that all available rooms in the relevant venue group were already taken by other, higher-priority constraints.
  • It could just be one of those edge cases that’s too hard for the naïve algorithm to handle.

Currently, Tabbycat doesn’t tell you which of these happened, so if the venue allocation fails to meet all your constraints, it’s on you to figure out why. In most scenarios, we imagine you’ll have few enough constraints that this will be obvious; for example, if the chief adjudicator is judging a team with accessibility requirements, it might be obvious that the latter’s constraint took priority. We might in future add support for more useful guidance on conflicting constraints, but we currently consider this to be of low priority.

Support¶

There are a number of ways to report bugs, ask for help, or submit feedback.

Facebook¶

Our Facebook group is a good place to ask for help. It’s also a good place to keep up with new releases and participate in more general discussions of features and ideas.

GitHub¶

Adding an issue to our GitHub repository is a great way to let us know about bugs or writeup suggestions for how to improve Tabbycat. Pull requests are also encouraged!

When submitting bugs or reporting errors please let us know your site address (if installed online) or operating system (if local) along with a complete description of the problem along with any error messages.

Email¶

Feel free to contact the maintainers directly if you are not able to access Facebook or GitHub.

Authors¶

Tabbycat was authored by Qi-Shan Lim for Auckland Australs 2010. The current active developers are:

Please don’t hesitate to contact us with any suggestions, expressions of interest or generally anything relating to Tabbycat.

Change Log¶

1.1.7¶

  • Yet more minor bug fixes
  • The auto-allocation UI will now detail your minimum rating setting better

1.1.6¶

  • A number of minor bug fixes

1.1.5¶

  • A number of minor bug fixes and improvements to documentation

1.1.4¶

  • Redesigned the footer area to better describe Tabbycat and to promote donations and related projects
  • Slight tweaks to the site homepage and main menus to better accomodate the login/log out links
  • A few minor bug fixes and improvements to error reporting

1.1.3¶

  • Fixed bug affecting some migrations from earlier versions
  • Made latest results show question mark rather than crash if a team is missing
  • Fixed bug affecting the ability to save motions
  • Fixed bug preventing draw flags from being displayed

1.1.2¶

  • Allow panels with even number of adjudicators (with warnings), by giving chair the casting vote
  • Removed defunct person check-in, which hasn’t been used since 2010
  • Collapsed availability database models into a single model with Django content types
  • Collapsed optional fields in action log entries into a single generic field using Django content types
  • Added better warnings when attempting to create an elimination round draw with fewer than two teams
  • Added warnings in Edit Database view when editing debate teams
  • Renamed “AIDA pre-2015” break rule to “AIDA 1996”

1.1.1¶

  • Fixed a bug where the team standings and team tab would crash when some emoji were not set

1.1.0 (Egyptian Mau)¶

  • Added support for the United Asian Debating Championships style
  • Added support for the World Schools Debating Championships style
  • Made Windows 8+ Emoji more colourful
  • Fixed an incompatability between Vue and IE 10-11 which caused tables to not render
  • Minor bug fixes and dependency updates

1.0.1¶

  • Fixed a minor bug with the visual importer affecting similarly named institutions
  • Fixed error message when user tries to auto-allocate adjudicators on unconfirmed or released draw
  • Minor docs edits

1.0.0 (Devon Rex)¶

Redesigned and redeveloped adjudicator allocation page
  • Redesigned interface, featuring clearer displays of conflict and diversity information
  • Changes to importances and panels are now automatically saved
  • Added debate “liveness” to help identify critical rooms—many thanks to Thevesh Theva
  • Panel score calculations performed live to show strength of voting majorities
New features
  • Added record pages for teams and adjudicators
  • Added a diversity tab to display demographic information about participants and scoring
Significant general improvements
  • Shifted most table rendering to Vue.js to improve performance and design
  • Drastically reduced number of SQL queries in large tables, e.g. draw, results, tab
Break round management
  • Completed support for break round draws
  • Simplified procedure for adding remarks to teams and updating break
  • Reworked break generation code to be class-based, to improve future extensibility
  • Added support for break qualification rules: AIDA Australs, AIDA Easters, WADL
Feedback
  • Changed Boolean fields in AdjudicatorFeedbackQuestion to reflect what they actually do
  • Changed “panellist feedback enabled” option to “feedback paths”, a choice of three options
  • Dropped “/t/” from tournament URLs and moved “/admin/” to “/database/”, with 301 redirects
  • Added basic code linting to the continuous integration tests
  • Many other small bug fixes, refactors, optimisations, and documentation updates

0.9.0 (Chartreux)¶

  • Added a beta implementation of the break rounds workflow
  • Added venue constraints, to allow participants or divisions to preferentially be given venues from predefined groups
  • Added a button to regenerate draws
  • Refactored speaker standings implementation to match team standings implementation
  • New standings metrics, draw methods, and interface settings for running small tournaments and division-based tournaments
  • Improved support for multiple tournaments
  • Improved user-facing error messages in some scenarios
  • Most frontend dependencies now handled by Bower
  • Static file compilation now handled by Gulp
  • Various bug fixes, optimisations, and documentation edits

0.8.3¶

  • Restored and reworking printing functionality for scoresheets/feedback
  • Restored Edit Venues and Edit Matchups on the draw pages
  • Reworked tournament data importers to use csv.DictReader, so that column order in files doesn’t matter
  • Improved dashboard and feedback graphs
  • Add separate pro speakers tab
  • Various bug fixes, optimisations, and documentation edits

0.8.2¶

  • Fixed issue where scores from individual ballots would be deleted when any other panel in the round was edited
  • Fixed issue where page crashes for URLs with “tab” in it but that aren’t recognized tab pages

0.8.1¶

  • Fixed a bug where editing a Team in the admin section could cause an error
  • Added instructions on how to account for speakers speaking twice to docs
  • Venues Importer wont show VenueGroup import info unless that option is enabled

0.8.0 (Bengal)¶

  • Upgraded to Python 3.4, dropped support for Python 2
  • Restructured directories and, as a consequence, changed database schema
  • Added Django migrations to the release (they were previously generated by the user)
  • Migrated documentation to Read The Docs
  • New user interface design and workflow
  • Overhauled tournament preferences to use django-dynamic-preferences
  • Added new visual data importer
  • Improved flexibility of team standings rules
  • Moved data utility scripts to Django management commands
  • Changed emoji to Unicode characters
  • Various other fixes and refinements

0.7.0 (Abyssinian)¶

  • Support for multiple tournaments
  • Improved and extensible tournament data importer
  • Display gender, region, and break category in adjudicator allocation
  • New views for online adjudicator feedback
  • Customisable adjudicator feedback forms
  • Randomised URLs for public submission
  • Customisable break categories
  • Computerised break generation (break round draws not supported)
  • Lots of fixes, interface touch-ups and performance enhancements
  • Now requires Django 1.8 (and other package upgrades)

Contributing¶

Contributions are welcome, and are greatly appreciated! Every little bit helps, and credit will be given. Join our Facebook group if you have any questions about how to get started contributing.

Bug reports¶

Please report bugs by opening a new issue in our GitHub repository. It is most helpful if you can include:

  • How Tabbycat was installed (on Heroku, locally on OS X, etc.)
  • Any details about your tournament and setup that might be helpful in troubleshooting
  • Detailed steps for how to reproduce the bug

Getting started¶

Important

We are using the git-flow workflow, so please submit any pull requests against the develop branch (and not master).

  • Generally we prefer that features and bug fixes are submitted as pull requests on their own branch (as described in the git-flow process)
  • We use Django’s testing tools — it would be great if new features came with unit tests
  • TODO: more detail on tests and pull request checklist/guidelines

Style guide¶

We use flake8 to check for a non-strict series of style rules. Warnings will trigger a Travis CI build to fail. The entire codebase can be checked by using:

$ flake8 .

While in the base directory

Versioning convention¶

Our convention is to increment the minor version whenever we add new functionality, and to increment the major version whenever

  • the database can’t be migrated forwards using python manage.py migrate --no-input, or
  • there is a major change to how the tournament workflow goes, or
  • we make some other change that is, in our opinion, significant enough to warrant a milestone.

Most of the time, we write data migrations to allow existing systems to be upgraded easily. However, we don’t always support backward database migrations. Our expectation is that long-lived installations keep up with our latest version.

One day, we hope to have a public API in place to facilitate the integration with other debating tournament software, like registration or adjudicator feedback systems. If and when that happens, we’ll probably revise this convention to be more in line with Semantic Versioning.

Starting from version 0.7.0, we use code names for versions, being breeds of cats in alphabetical order.

Documentation¶

Documentation is created using Sphinx and hosted at Read The Docs. Pushes to develop will update the latest documentation set, while pushes to master will update the stable documentation set.

To preview the documentation locally, install the docs-specific requirements (from the base folder):

$ pip install -r 'docs/requirements.txt'

Then start the server:

$ sphinx-autobuild docs docs/_build/html --port 7999

You should then be able to preview the docs at 127.0.0.1:7999.

Licence Information¶

We haven’t released Tabbycat under an open-source licence, so there is no formal and general right to use this software. Nonetheless, you’re welcome to use Tabbycat to help run a debating tournament if it is a not-for-profit activity. Using Tabbycat at tournaments where an individual or institution is making a profit requires our express permission. Modifying Tabbycat for profit, or using a version of Tabbycat that has been modified for profit, also requires our express permission.

If you’re using Tabbycat to run a tournament we would appreciate it if you would let us know that you’re doing so and how it went. Our Facebook group is a great place to do so, or you could e-mail us at the contact details in the Authors section.

We work on this software in our spare time and make it available for not-for-profit use in the hope that it will benefit the debating community. It is provided “as is”, without any warranty, and we disclaim all legal liability.

Tournament History¶

A list of tournaments (that we know of) which have used Tabbycat.

2016¶

2014¶

2012¶

  • Wellington Australs

2010¶

  • Auckland Australs