diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000000..4580b984652 --- /dev/null +++ b/.flake8 @@ -0,0 +1,22 @@ +[flake8] +# Idea is to remove these over time +# +# E203 = whitespace before ':' +# E221 = multiple spaces before operator +# E241 = multiple spaces after ',' +# E231 = missing whitespace after ',' + +# E261 = at least two spaces before inline comment +# E126 = continuation line over-indented for hanging indent +# E128 = continuation line under-indented for visual indent +# I100 = Imported names are in the wrong order. + +# Q000 = double quotes + +ignore = E126,E128,E221,E226,E261,E203,E231,E241,Q000,I100 + +max-line-length = 200 + +exclude = docs, migrations, node_modules, bower_components, venv, */__init__.py + +import-order-style = google diff --git a/.gitignore b/.gitignore index ca9071369c4..33d5d7f1885 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,13 @@ # Django Related -local_settings.py +tabbycat/local_settings.py .gitmodules/ __pycache__/ # Compilation -staticfiles/ -static/css/ -static/js/ -static/fonts/ +tabbycat/staticfiles/ +tabbycat/static/css/ +tabbycat/static/js/ +tabbycat/static/fonts/ # Dependencies node_modules @@ -22,10 +22,10 @@ data/* !data/sandbox/ !data/test/ !data/presets/ -!data/fixtues/ +!data/fixtures/ # Docs -site/ +docs/site/ # Tags tags diff --git a/.travis.yml b/.travis.yml index eab4209b971..a0d50cc4afe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,5 @@ services: install: - pip install -r requirements_common.txt script: - - dj test -v 2 + - flake8 tabbycat + - cd tabbycat && dj test -v 2 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c14502d4166..31733b6d34f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,32 @@ Change Log ========== +1.0.0 +----- +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 ----- - Added a beta implementation of the break rounds workflow diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index ad00e68b29e..16a8bfe8bea 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -2,16 +2,12 @@ Contributing ============ -.. important:: We are using the `git-flow workflow `_, so please submit any pull requests against the **develop branch** (and not master). - -Contributions are welcome, and are greatly appreciated! Every little bit helps, and credit will be given. `Join our Facebook group `_. +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: +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 @@ -20,10 +16,20 @@ It is most helpful if you can include: Getting started =============== -- Insert general setup instructions -- Insert instructions on how to make a feature/bug branch -- Maybe insert instructions on how to run tests / flake8 -- Insert pull request checklist/guidelines +.. 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 Semantic versioning convention ============================== @@ -48,14 +54,11 @@ 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. -Previewing Locally ------------------- - -Install the docs-specific requirements (from the base folder):: +To preview the documentation locally, install the docs-specific requirements (from the base folder):: $ pip install -r 'docs/requirements.txt' -Start the server:: +Then start the server:: $ sphinx-autobuild docs docs/_build/html --port 7999 diff --git a/Gulpfile.js b/Gulpfile.js index 95c7b3c55ae..9c1932b241e 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -1,4 +1,5 @@ var gulp = require('gulp'); +var gutil = require('gulp-util'); // Error logging + NoOop // Compilation var sass = require('gulp-sass'); @@ -6,78 +7,137 @@ var rename = require('gulp-rename'); var concat = require('gulp-concat'); // Compression -var minifyCSS = require('gulp-minify-css'); +var cleanCSS = require('gulp-clean-css'); var uglify = require('gulp-uglify'); +// Browserify +var browserify = require('browserify'); // Bundling modules +var babelify = require('babelify'); // Use ES syntax +var vueify = require('vueify'); +var source = require('vinyl-source-stream'); // Use browserify in gulp +var es = require('event-stream'); // Browserify multiple files at once +var streamify = require('gulp-streamify'); +// Debug & Config +var livereload = require('gulp-livereload'); +var outputDir = 'tabbycat/static/'; +var isProduction = (gutil.env.development === true) ? false: true; +if (isProduction === true) { + console.log('GULP: Building for production'); +} else if (isProduction === false) { + console.log('GULP: Building for development'); +} + +// Tasks gulp.task('fonts-compile', function() { gulp.src([ - 'bower_components/**/*.eot', - 'bower_components/**/*.svg', - 'bower_components/**/*.ttf', - 'bower_components/**/*.woff', - 'bower_components/**/*.woff2', + 'node_modules/bootstrap-sass/assets/fonts/**/*.eot', + 'node_modules/bootstrap-sass/assets/fonts/**/*.svg', + 'node_modules/bootstrap-sass/assets/fonts/**/*.ttf', + 'node_modules/bootstrap-sass/assets/fonts/**/*.woff', + 'node_modules/bootstrap-sass/assets/fonts/**/*.woff2', + 'node_modules/lato-font/fonts/**/*.eot', + 'node_modules/lato-font/fonts/**/*.svg', + 'node_modules/lato-font/fonts/**/*.ttf', + 'node_modules/lato-font/fonts/**/*.woff', + 'node_modules/lato-font/fonts/**/*.woff2', ]) .pipe(rename({dirname: ''})) // Remove folder structure - .pipe(gulp.dest('static/fonts/vendor/')); + .pipe(gulp.dest(outputDir + 'fonts/')); }); gulp.task('styles-compile', function() { - gulp.src(['templates/scss/printables.scss', 'templates/scss/style.scss']) + gulp.src([ + 'tabbycat/templates/scss/allocation-old.scss', + 'tabbycat/templates/scss/printables.scss', + 'tabbycat/templates/scss/style.scss']) .pipe(sass().on('error', sass.logError)) - .pipe(minifyCSS()) - .pipe(rename(function (path) { - path.basename += ".min"; - })) - .pipe(gulp.dest('static/css/')); + // '*' compatability = IE9+ + .pipe(isProduction ? cleanCSS({compatibility: '*'}) : gutil.noop()) + .pipe(gulp.dest(outputDir + '/css/')) + .pipe(isProduction ? gutil.noop() : livereload()); }); -// Creates task for collecting dependencies -gulp.task('js-compile', function() { - gulp.src(['templates/js/*.js']) - .pipe(uglify()) - .pipe(rename(function (path) { - path.basename += ".min"; - })) - .pipe(rename({dirname: ''})) // Remove folder structure - .pipe(gulp.dest('static/js/')); +gulp.task("js-vendor-compile", function() { + gulp.src([ + 'node_modules/jquery/dist/jquery.js', // For Debug Toolbar + 'node_modules/datatables.net/js/jquery.dataTables.js', // Deprecate, + 'node_modules/jquery-validation/dist/jquery.validate.js', // Deprecate, + 'tabbycat/templates/js-vendor/jquery-ui.min.js', // Deprecate, + ]) + .pipe(isProduction ? uglify() : gutil.noop()) // Doesnt crash + .pipe(gulp.dest(outputDir + '/js/vendor/')); }); -// Creates task for collecting dependencies -gulp.task('js-main-vendor-compile', function() { - gulp.src(['bower_components/jquery/dist/jquery.js', - 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', - 'templates/js/vendor/jquery.dataTables.min.js', - 'templates/js/vendor/fixed-header.js', - ]) - .pipe(concat('vendor.js')) - .pipe(uglify()) - .pipe(rename(function (path) { - path.basename += ".min"; - })) - .pipe(rename({dirname: ''})) // Remove folder structure - .pipe(gulp.dest('static/js/vendor/')); +gulp.task("js-compile", function() { + gulp.src([ + 'tabbycat/templates/js-standalones/*.js', + ]) + // Can't run uglify() until django logic is out of standalone js files + // .pipe(isProduction ? uglify() : gutil.noop()) + .pipe(gulp.dest(outputDir + '/js/')) + .pipe(isProduction ? gutil.noop() : livereload()); }); -// Creates task for collecting dependencies -gulp.task('js-alt-vendor-compile', function() { - gulp.src(['bower_components/jquery/dist/jquery.min.js', // Redundant but needed for debug toolbar - 'bower_components/d3/d3.min.js', - 'bower_components/jquery-ui/jquery-ui.min.js', - 'bower_components/jquery-validation/dist/jquery.validate.min.js', - 'bower_components/vue/dist/vue.min.js', - 'bower_components/vue/dist/vue.js', // For when debug is on - ]) - .pipe(uglify()) - .pipe(rename({dirname: ''})) // Remove folder structure - .pipe(gulp.dest('static/js/vendor/')); +gulp.task("js-browserify", function() { + // With thanks to https://fettblog.eu/gulp-browserify-multiple-bundles/ + // We define our input files, which we want to have bundled + var files = [ + 'tabbycat/templates/js-bundles/public.js', + 'tabbycat/templates/js-bundles/admin.js' + ]; + // map them to our stream function + var tasks = files.map(function(entry) { + return browserify({ entries: [entry] }) + .transform(vueify) + .on('error', gutil.log) + .transform([babelify, { + presets: ["es2015"], + plugins: ['transform-runtime'] + }]) + .on('error', gutil.log) + .bundle().on('error', gutil.log) + .on('error', function() { + gutil.log + this.emit('end'); + }) + .pipe(source(entry)) + .on('error', gutil.log) + .pipe(isProduction ? streamify(uglify()) : gutil.noop()) + .on('error', gutil.log) + .pipe(rename({ + extname: '.bundle.js', + dirname: '' + })) + .pipe(gulp.dest(outputDir + '/js/')); + // .pipe(isProduction ? gutil.noop() : livereload()); + // TODO: get proper hot reloading going? + }); + // create a merged stream + return es.merge.apply(null, tasks); }); -// Automatically build and watch the CSS folder for when a file changes -gulp.task('default', ['build'], function() { - gulp.watch('templates/scss/**/*.scss', ['styles-compile']); - gulp.watch('templates/js/**/*.js', ['js-compress']); +gulp.task("html-reload", function() { + return gulp.src('') + .pipe(livereload()); }); -// Build task for production -gulp.task('build', ['fonts-compile', 'styles-compile', 'js-compile', 'js-main-vendor-compile', 'js-alt-vendor-compile' ]); \ No newline at end of file +// Runs with --production if debug is false or there's no local settings +gulp.task('build', [ + 'fonts-compile', + 'styles-compile', + 'js-vendor-compile', + 'js-compile', + 'js-browserify', + ]); + +// Runs when debug is True and when runserver/collectstatic is called +// Watch the CSS/JS for changes and copy over to static AND static files when done +gulp.task('watch', ['build'], function() { + livereload.listen(); + gulp.watch('tabbycat/templates/scss/**/*.scss', ['styles-compile']); + gulp.watch('tabbycat/templates/js-standalones/*.js', ['js-compile']); + gulp.watch('tabbycat/templates/js-bundles/*.js', ['js-browserify']); + gulp.watch('tabbycat/templates/**/*.vue', ['js-browserify']); + gulp.watch('tabbycat/**/*.html', ['html-reload']); +}); diff --git a/Procfile b/Procfile index 0c1a04e6715..fbd46315ebc 100644 --- a/Procfile +++ b/Procfile @@ -1,4 +1,5 @@ # production -web: waitress-serve --port=$PORT wsgi:application +web: sh -c 'cd ./tabbycat/ && waitress-serve --port=$PORT wsgi:application' + # debug -#web: waitress-serve --port=$PORT --expose-tracebacks wsgi:application +web: sh -c 'cd tabbycat && waitress-serve --port=$PORT --expose-tracebacks wsgi:application' diff --git a/README.md b/README.md index 3ce73229f12..b67518ff8b9 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Tabbycat -[![Docs](https://readthedocs.org/projects/tabbycat/badge/?version=latest)](http://tabbycat.readthedocs.io/en/latest/) [![Docs](https://readthedocs.org/projects/tabbycat/badge/?version=stable)](http://tabbycat.readthedocs.io/en/stable/) [![Build Status](https://travis-ci.org/czlee/tabbycat.svg?branch=develop)](https://travis-ci.org/czlee/tabbycat) [![Dependency Status](https://www.versioneye.com/user/projects/574bd0dace8d0e00473733b5/badge.svg?style=flat)](https://www.versioneye.com/user/projects/574bd0dace8d0e00473733b5) +[![Docs](https://readthedocs.org/projects/tabbycat/badge/?version=latest)](http://tabbycat.readthedocs.io/en/latest/) [![Docs](https://readthedocs.org/projects/tabbycat/badge/?version=stable)](http://tabbycat.readthedocs.io/en/stable/) [![Build Status](https://travis-ci.org/czlee/tabbycat.svg?branch=develop)](https://travis-ci.org/czlee/tabbycat) [![Dependency Status](https://gemnasium.com/badges/github.com/czlee/tabbycat.svg)](https://gemnasium.com/github.com/czlee/tabbycat) [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) -Tabbycat is a draw tabulation system for 3 vs 3 debating tournaments. It was used at Auckland Australs 2010, [Victoria Australs 2012](https://www.facebook.com/Australs2012), [Otago Australs 2014](http://australs2014.herokuapp.com), [Daejeon Australs 2015](http://australs2015.herokuapp.com) and [many other tournaments of all sizes](http://tabbycat.readthedocs.io/en/stable/about/tournament-history.html). +Tabbycat is a draw tabulation system for 3 vs 3 debating tournaments. It was used at Australs in Auckland 2010, [Wellington 2012](https://www.facebook.com/Australs2012), [Dunedin 2014](http://australs2014.herokuapp.com), [Daejeon 2015](http://australs2015.herokuapp.com) and [Perth 2016](http://australs2016.herokuapp.com), as well as [many other tournaments of all sizes](http://tabbycat.readthedocs.io/en/stable/about/tournament-history.html). -Our **demo site** is at [tabbycatdebate.herokuapp.com](http://tabbycatdebate.herokuapp.com/). It's normally up, but its form will vary from time to time as we set up new feature demos for people. If it's down and you'd like to see it, or if you want to play with it as if you were running a tournament, [contact us](#authors-and-contacts). To see a post-tournament website, have a look at the [Daejeon Australs 2015 tab website](http://australs2015.herokuapp.com). +Our **demo site** is at [tabbycatdebate.herokuapp.com](http://tabbycatdebate.herokuapp.com/). It's normally up, but its form will vary from time to time as we set up new feature demos for people. If it's down and you'd like to see it, or if you want to play with it as if you were running a tournament, [contact us](#authors-and-contacts). To see a post-tournament website, have a look at the [WAustrals 2016 tab website](http://australs2016.herokuapp.com). ## Features diff --git a/actionlog/urls.py b/actionlog/urls.py deleted file mode 100644 index af1e7dcab24..00000000000 --- a/actionlog/urls.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.conf.urls import url - -from . import views - -urlpatterns = [ - url(r'^latest_actions/$', views.latest_actions, name='latest_actions'), -] diff --git a/actionlog/views.py b/actionlog/views.py deleted file mode 100644 index 0c7b80cf67f..00000000000 --- a/actionlog/views.py +++ /dev/null @@ -1,24 +0,0 @@ -from django.template import Template, Context -import json - -from .models import ActionLogEntry -from utils.views import * -import datetime - -@login_required -@tournament_view -def latest_actions(request, t): - action_objects = [] - actions = ActionLogEntry.objects.filter(tournament=t).order_by( - '-timestamp')[:15].select_related('user', 'debate', 'ballot_submission') - - timestamp_template = Template("{% load humanize %}{{ t|naturaltime }}") - for a in actions: - action_objects.append({ - 'user': a.user.username if a.user else a.ip_address or "anonymous", - 'type': a.get_type_display(), - 'param': a.get_parameters_display(), - 'timestamp': timestamp_template.render(Context({'t': a.timestamp})), - }) - - return HttpResponse(json.dumps(action_objects), content_type="text/json") diff --git a/adjallocation/admin.py b/adjallocation/admin.py deleted file mode 100644 index afdcbb87897..00000000000 --- a/adjallocation/admin.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.contrib import admin - -from .models import DebateAdjudicator - -# ============================================================================== -# Debate Adjudicators -# ============================================================================== - -class DebateAdjudicatorAdmin(admin.ModelAdmin): - list_display = ('debate', 'adjudicator', 'type') - search_fields = ('adjudicator__name', 'type') - raw_id_fields = ('debate',) - -admin.site.register(DebateAdjudicator, DebateAdjudicatorAdmin) diff --git a/adjallocation/models.py b/adjallocation/models.py deleted file mode 100644 index 870057cf656..00000000000 --- a/adjallocation/models.py +++ /dev/null @@ -1,111 +0,0 @@ -from django.db import models - -from tournaments.models import SRManager -from participants.models import Adjudicator - -class DebateAdjudicator(models.Model): - TYPE_CHAIR = 'C' - TYPE_PANEL = 'P' - TYPE_TRAINEE = 'T' - - TYPE_CHOICES = ( - (TYPE_CHAIR, 'chair'), - (TYPE_PANEL, 'panellist'), - (TYPE_TRAINEE, 'trainee'), - ) - - objects = SRManager() - - debate = models.ForeignKey('draw.Debate') - adjudicator = models.ForeignKey('participants.Adjudicator') - type = models.CharField(max_length=2, choices=TYPE_CHOICES) - timing_confirmed = models.NullBooleanField(verbose_name="Available? ") - - def __str__(self): - return '{} in {}'.format(self.adjudicator, self.debate) - - class Meta: - unique_together = ('debate', 'adjudicator') - - -class AdjudicatorConflict(models.Model): - adjudicator = models.ForeignKey('participants.Adjudicator') - team = models.ForeignKey('participants.Team') - - class Meta: - verbose_name = "adjudicator-team conflict" - -class AdjudicatorAdjudicatorConflict(models.Model): - adjudicator = models.ForeignKey('participants.Adjudicator', related_name="source_adjudicator") - conflict_adjudicator = models.ForeignKey('participants.Adjudicator', related_name="target_adjudicator", verbose_name="Adjudicator") - - class Meta: - verbose_name = "adjudicator-adjudicator conflict" - -class AdjudicatorInstitutionConflict(models.Model): - adjudicator = models.ForeignKey('participants.Adjudicator') - institution = models.ForeignKey('participants.Institution') - - class Meta: - verbose_name = "adjudicator-institution conflict" - -class AdjudicatorAllocation: - """Not a model, just a container object for the adjudicators on a panel.""" - - def __init__(self, debate, chair=None, panel=None): - self.debate = debate - self.chair = chair - self.panel = panel or [] - self.trainees = [] - - @property - def list(self): - """Panel only, excludes trainees.""" - a = [self.chair] - a.extend(self.panel) - return a - - def __str__(self): - items = [str(getattr(x, "name", x)) for x in self.list] - return ", ".join(items) - - def __iter__(self): - """Iterates through all, including trainees.""" - if self.chair is not None: - yield DebateAdjudicator.TYPE_CHAIR, self.chair - for a in self.panel: - yield DebateAdjudicator.TYPE_PANEL, a - for a in self.trainees: - yield DebateAdjudicator.TYPE_TRAINEE, a - - def __contains__(self, item): - return item == self.chair or item in self.panel or item in self.trainees - - def __eq__(self, other): - return self.debate == other.debate and self.chair == other.chair and \ - set(self.panel) == set(other.panel) and set(self.trainees) == set(other.trainees) - - def delete(self): - """Delete existing, current allocation""" - self.debate.debateadjudicator_set.all().delete() - self.chair = None - self.panel = [] - self.trainees = [] - - @property - def has_chair(self): - return self.chair is not None - - @property - def is_panel(self): - return len(self.panel) > 0 - - @property - def valid(self): - return self.has_chair and len(self.panel) % 2 == 0 - - def save(self): - self.debate.debateadjudicator_set.all().delete() - for t, adj in self: - if adj: - DebateAdjudicator(debate=self.debate, adjudicator=adj, type=t).save() diff --git a/adjfeedback/templates/adjudicator_source_list.html b/adjfeedback/templates/adjudicator_source_list.html deleted file mode 100644 index 9d5ba33109b..00000000000 --- a/adjfeedback/templates/adjudicator_source_list.html +++ /dev/null @@ -1,111 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} -{% load static %} - -{% block head-title %}View Feedback by Source{% endblock %} -{% block page-title %}View Feedback by Source{% endblock %} - -{% block page-subnav-sections %} - - Feedback Overview - - - Latest Feedback - - - Find Feedback - - {% if pref.public_ballots_randomised or pref.public_feedback_randomised %} - - Randomised URLs - - {% endif %} - - Unsubmitted Ballots - - {% include "tables/table_search.html" %} -{% endblock %} - -{% block page-subnav-actions %} - Add Feedback -{% endblock %} - -{% block content %} -
- -
-
-
-

From Teams

-
-
- - - - -
-
-
- -
-
-
-

From Adjudicators

-
-
- - - - -
-
-
- -
- -{% endblock content %} - -{% block extra-js %} - - {% include "vue/import-vue.html" %} - {% include "vue/table.vue" %} - - - {{ block.super }} - -{% endblock extra-js %} diff --git a/adjfeedback/templates/feedback_latest.html b/adjfeedback/templates/feedback_latest.html deleted file mode 100644 index b75171b18dd..00000000000 --- a/adjfeedback/templates/feedback_latest.html +++ /dev/null @@ -1,53 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} - -{% block head-title %}Latest Feedback{% endblock %} -{% block page-title %}Latest Feedback{% endblock %} - -{% block page-subnav-sections %} - - Feedback Overview - - - Latest Feedback - - - Find Feedback - - {% if pref.public_ballots_randomised or pref.public_feedback_randomised %} - - Randomised URLs - - {% endif %} - - Unsubmitted Ballots - - {% include "tables/table_search.html" %} -{% endblock %} - -{% block page-subnav-actions %} - Add Feedback -{% endblock %} - -{% block content %} -
- - {% for feedback in feedbacks %} - -
- - {% include 'feedback_card.html' %} - -
- - {% if forloop.counter|divisibleby:3 %} -
- {% endif %} - - {% empty %} -
No feedback has been submitted yet.
- - {% endfor %} - -
-{% endblock content %} diff --git a/adjfeedback/templates/feedback_overview.html b/adjfeedback/templates/feedback_overview.html deleted file mode 100644 index bb06575bdae..00000000000 --- a/adjfeedback/templates/feedback_overview.html +++ /dev/null @@ -1,321 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} -{% load static %} - -{% block page-title %}Adjudicator Feedback Summary{% endblock %} -{% block head-title %} - 🙅Adjudicator Feedback Summary -{% endblock %} -{% block sub-title %} - {{ breaking_count }} marked as breaking -{% endblock %} -{% block body-id %}feedbackOverview{% endblock %} - -{% block page-subnav-sections %} - - Feedback Overview - - - Latest Feedback - - - Find Feedback - - {% if pref.public_ballots_randomised or pref.public_feedback_randomised or pref.allocation_confirmations %} - - Randomised URLs - - {% endif %} - - Unsubmitted Ballots - - {% include "tables/table_search.html" %} -{% endblock %} - -{% block page-subnav-actions %} - Add Feedback -{% endblock %} - - -{% block content %} - -
-
- - - - - - - - - {% if pref.show_unaccredited %} - - {% endif %} - - {% if pref.enable_adj_notes > 0 %} - - {% endif %} - - - - - - - - {% for adj in adjudicators %} - - - - - - - {% if pref.show_unaccredited %} - - {% endif %} - - {% if pref.enable_adj_notes > 0 %} - - {% endif %} - - - - - - {% endfor %} - - -
NameScoreTestFeedbackTrend (Chair, Panellist, Trainee)
- {{ adj.name }}
- {{ adj.institution.code }} -
- {{ adj.score|stringformat:".2f" }} - - {{ adj.test_score }} - {{ adj.feedback_score|stringformat:".2f" }} - - - {% if adj.novice %} - - {% endif %} - - View
Feedback
-
- Edit Note - - - - - - {{ adj.debates }} - - {{ adj.avg_margin|stringformat:".1f" }} - - {{ adj.avg_score|stringformat:".1f" }} -
-
-
- - - - - - {% if pref.enable_adj_notes > 0 %} - - {% endif %} -{% endblock content %} - -{% block extra-js %} - - -{% include "vue/import-vue.html" %} -{% include "vue/feedback-trend.vue" %} - - -{% endblock extra-js %} diff --git a/adjfeedback/templates/feedback_progress.html b/adjfeedback/templates/feedback_progress.html deleted file mode 100644 index 6a127c18657..00000000000 --- a/adjfeedback/templates/feedback_progress.html +++ /dev/null @@ -1,196 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} - -{% block head-title %}🆘Missing Feedback Ballots{% endblock %} -{% block page-title %}🆘Missing Feedback Ballots{% endblock %} - -{% block page-subnav-sections %} - - Feedback Overview - - - Latest Feedback - - - Find Feedback - - {% if pref.public_ballots_randomised or pref.public_feedback_randomised %} - - Randomised URLs - - {% endif %} - - Unsubmitted Ballots - - {% include "tables/table_search.html" %} -{% endblock %} - -{% block page-subnav-actions %} - Add Feedback -{% endblock %} - -{% block content %} -
- -
-
-
-

From Teams

-
-
- - - - - - - - - {% if pref.show_institutions %} - - {% endif %} - - - - {% for team in teams %} - - - - - - {% if pref.show_institutions %} - - {% endif %} - - {% endfor %} - -
TeamInstitution
- {{ team.coverage }} % - - {{ team.owed_ballots }} - - {{ team.submitted_ballots }} - - {% include "tables/team.html" with team=team %} - - {{ team.institution.code }} -
- -
-
-
- -
-
-
-

From Adjudicators

-
-
- - - - - - - - - - - - {% for entity in adjudicators %} - {% if entity.total_ballots > 0 %} - - - - - - - - {% endif %} - {% endfor %} - -
AdjudicatorInstititution
- {{ entity.coverage }} % - - {{ entity.owed_ballots }} - - {{ entity.submitted_ballots }} - - {{ entity.name }} - - {{ entity.institution.name }} {{ entity.test }} -
- -
-
-
- -
- - - - - - -{% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/adjfeedback/templates/public_feedback_progress.html b/adjfeedback/templates/public_feedback_progress.html deleted file mode 100644 index 3fd03ae8101..00000000000 --- a/adjfeedback/templates/public_feedback_progress.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "feedback_progress.html" %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} - -{% block page-subnav-actions %} -{% endblock %} diff --git a/adjfeedback/templates/vue/feedback-trend.vue b/adjfeedback/templates/vue/feedback-trend.vue deleted file mode 100644 index e11d419fcf0..00000000000 --- a/adjfeedback/templates/vue/feedback-trend.vue +++ /dev/null @@ -1,164 +0,0 @@ - - - - diff --git a/adjfeedback/utils.py b/adjfeedback/utils.py deleted file mode 100644 index 30f0b1934f6..00000000000 --- a/adjfeedback/utils.py +++ /dev/null @@ -1,66 +0,0 @@ - - -def gather_adj_feedback(adj, all_rounds, adj_feedbacks, all_debate_adjudicators): - - # Start off with their test scores - feedback_data = [{ 'x': 0, 'y': adj.test_score, 'position': "Test Score"}] - - for r in all_rounds: - # Filter all the feedback to focus on this particular rouond - adj_round_feedbacks = [f for f in adj_feedbacks if (f.source_adjudicator and f.source_adjudicator.debate.round == r)] - adj_round_feedbacks.extend([f for f in adj_feedbacks if (f.source_team and f.source_team.debate.round == r)]) - - if len(adj_round_feedbacks) > 0: - debates = [fb.source_team.debate for fb in adj_round_feedbacks if fb.source_team] - debates.extend([fb.source_adjudicator.debate for fb in adj_round_feedbacks if fb.source_adjudicator]) - adj_da = next((da for da in all_debate_adjudicators if (da.adjudicator == adj and da.debate == debates[0])), None) - if adj_da: - if adj_da.type == adj_da.TYPE_CHAIR: - adj_type = "Chair" - elif adj_da.type == adj_da.TYPE_PANEL: - adj_type = "Panellist" - elif adj_da.type == adj_da.TYPE_TRAINEE: - adj_type = "Trainee" - - total_score = [f.score for f in adj_round_feedbacks] - average_score = round(sum(total_score) / len(total_score), 2) - - # Creating the object list for the graph - feedback_data.append({ - 'x': r.seq, - 'y': average_score, - 'position': adj_type, - }) - - return feedback_data - - -def gather_adj_scores(adj, adj_scores, debate_adjudications): - # Processing scores to get average margins - adj.debates = len(debate_adjudications) - - if len(adj_scores) > 0: - adj.avg_score = sum(s.score for s in adj_scores) / len(adj_scores) - - # ballot_ids = [score.ballot_submission for score in adj_scores] - # ballot_ids = sorted(set([b.id for b in ballot_ids])) # Deduplication of ballot IDS - # ballot_margins = [] - # - # for ballot_id in ballot_ids: - # # For each unique ballot id total its scores - # print(ballot_id) - # print([a.id for a in adj_scores]) - # single_round = adj_scores.filter(ballot_submission=ballot_id) - # scores = [s.score for s in single_round] # TODO this is slow - should be prefetched - # slice_end = len(scores) - # teamA = sum(scores[:len(scores)/2]) - # teamB = sum(scores[len(scores)/2:]) - # ballot_margins.append(max(teamA, teamB) - min(teamA, teamB)) - # - # adj.avg_margin = sum(ballot_margins) / len(ballot_margins) - return adj - - else: - adj.avg_score = None - adj.avg_margin = None - return adj diff --git a/adjfeedback/views.py b/adjfeedback/views.py deleted file mode 100644 index 7852ac58e73..00000000000 --- a/adjfeedback/views.py +++ /dev/null @@ -1,537 +0,0 @@ -import json - -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib import messages -from django.core.exceptions import ObjectDoesNotExist -from django.core.urlresolvers import reverse -from django.views.generic.base import TemplateView -from django.views.generic.detail import SingleObjectMixin -from django.views.generic.edit import FormView - -from actionlog.mixins import LogActionMixin -from actionlog.models import ActionLogEntry -from adjallocation.models import DebateAdjudicator -from participants.models import Adjudicator, Team -from results.mixins import TabroomSubmissionFieldsMixin, PublicSubmissionFieldsMixin -from results.models import SpeakerScoreByAdj -from tournaments.mixins import TournamentMixin, PublicTournamentPageMixin -from tournaments.models import Round -from utils.misc import reverse_tournament -from utils.mixins import SingleObjectFromTournamentMixin, SingleObjectByRandomisedUrlMixin, PublicCacheMixin, SuperuserRequiredMixin, SuperuserOrTabroomAssistantTemplateResponseMixin, PostOnlyRedirectView -from utils.urlkeys import populate_url_keys -from utils.views import * - -from .models import AdjudicatorFeedback, AdjudicatorTestScoreHistory -from .forms import make_feedback_form_class -from .utils import gather_adj_feedback, gather_adj_scores - -@admin_required -@tournament_view -def adj_scores(request, t): - data = {} - - #TODO: make round-dependent - for adj in Adjudicator.objects.all().select_related('tournament','tournament__current_round'): - data[adj.id] = adj.score - - return HttpResponse(json.dumps(data), content_type="text/json") - - -@admin_required -@tournament_view -def feedback_overview(request, t): - breaking_count = 0 - - - if t.pref('share_adjs'): - adjudicators = Adjudicator.objects.filter(tournament=t).select_related( - 'tournament','tournament__current_round') | Adjudicator.objects.filter(tournament=None) - else: - adjudicators = Adjudicator.objects.filter(tournament=t).select_related( - 'tournament','tournament__current_round') - - all_debate_adjudicators = list(DebateAdjudicator.objects.select_related('adjudicator').all()) - all_adj_feedbacks = list(AdjudicatorFeedback.objects.filter( - confirmed=True).exclude(source_adjudicator__type=DebateAdjudicator.TYPE_TRAINEE).select_related( - 'adjudicator', 'source_adjudicator__debate__round', 'source_team__debate__round')) - all_adj_scores = list(SpeakerScoreByAdj.objects.select_related('debate_adjudicator','ballot_submission').filter( - ballot_submission__confirmed=True)) - - feedback_data = {} - for adj in adjudicators: - if adj.breaking: breaking_count += 1 - # Gather feedback scores for graphs - adj_feedbacks = [f for f in all_adj_feedbacks if f.adjudicator == adj] - feedback_data[adj.id] = gather_adj_feedback(adj, t.prelim_rounds(until=t.current_round), adj_feedbacks, all_debate_adjudicators) - # Gather awarded scores for stats - debate_adjudications = [a for a in all_debate_adjudicators if a.adjudicator.id is adj.id] - scores = [s for s in all_adj_scores if s.debate_adjudicator.id is adj.id] - adj = gather_adj_scores(adj, scores, debate_adjudications) - - context = { - 'adjudicators' : adjudicators, - 'breaking_count' : breaking_count, - 'feedback_headings' : [q.name for q in t.adj_feedback_questions], - 'feedback_data' : json.dumps(feedback_data), - } - return render(request, 'feedback_overview.html', context) - - -class FeedbackBySourceView(LoginRequiredMixin, TournamentMixin, TemplateView): - - template_name = "adjudicator_source_list.html" - - def get_context_data(self, **kwargs): - tournament = self.get_tournament() - teams_data = [] - for team in Team.objects.filter(tournament=tournament): - feedbacks = AdjudicatorFeedback.objects.filter(source_team__team=team).select_related( - 'source_team__team').count() - teams_data.append({ - 'name': team.short_name, - 'institution': team.institution.name, - 'feedbacks': "%s Feedbacks" % feedbacks, - 'rowLink': reverse_tournament('adjfeedback-view-from-team', tournament, kwargs={'pk': team.pk}), - }) - - adjs_data = [] - for adj in Adjudicator.objects.filter(tournament=tournament): - feedbacks = AdjudicatorFeedback.objects.filter(source_adjudicator__adjudicator=adj).select_related( - 'source_adjudicator__adjudicator').count(), - adjs_data.append({ - 'name': adj.name, - 'institution': adj.institution.name, - 'feedbacks': "%s Feedbacks" % feedbacks, - 'rowLink': reverse_tournament('adjfeedback-view-from-adjudicator', tournament, kwargs={'pk': adj.pk}), - }) - kwargs['teams'] = teams_data - kwargs['adjs'] = adjs_data - return super().get_context_data(**kwargs) - - -class FeedbackCardsView(LoginRequiredMixin, TournamentMixin, TemplateView): - """Base class for views displaying feedback as cards.""" - - def get_score_thresholds(self): - tournament = self.get_tournament() - min_score = tournament.pref('adj_min_score') - max_score = tournament.pref('adj_max_score') - score_range = max_score - min_score - return { - 'low_score' : min_score + score_range / 10, - 'medium_score' : min_score + score_range / 5, - 'high_score' : max_score - score_range / 10, - } - - def get_feedbacks(self): - questions = self.get_tournament().adj_feedback_questions - feedbacks = self.get_feedback_queryset() - for feedback in feedbacks: - feedback.items = [] - for question in questions: - try: - answer = question.answer_set.get(feedback=feedback).answer - except ObjectDoesNotExist: - continue - feedback.items.append({'question': question, 'answer': answer}) - return feedbacks - - def get_feedback_queryset(self): - raise NotImplementedError() - - def get_context_data(self, **kwargs): - kwargs['feedbacks'] = self.get_feedbacks() - kwargs['score_thresholds'] = self.get_score_thresholds() - return super().get_context_data(**kwargs) - - -class LatestFeedbackView(FeedbackCardsView): - """View displaying the latest feedback.""" - - template_name = "feedback_latest.html" - - def get_feedback_queryset(self): - return AdjudicatorFeedback.objects.order_by('-timestamp')[:50].select_related( - 'adjudicator', 'source_adjudicator__adjudicator', 'source_team__team') - - -class FeedbackFromSourceView(SingleObjectMixin, FeedbackCardsView): - """Base class for views displaying feedback from a given team or adjudicator.""" - # SingleObjectFromTournamentMixin doesn't work great here, it induces an MRO - # conflict between TournamentMixin and ContextMixin. - - template_name = "feedback_by_source.html" - source_name_attr = None - adjfeedback_filter_field = None - - def get_context_data(self, **kwargs): - kwargs['source_name'] = getattr(self.object, self.source_name_attr, '') - return super().get_context_data(**kwargs) - - def get(self, request, *args, **kwargs): - self.object = self.get_object() - return super().get(request, *args, **kwargs) - - def get_queryset(self): - # from SingleObjectFromTournamentMixin - return super().get_queryset().filter(tournament=self.get_tournament()) - - def get_feedback_queryset(self): - kwargs = {self.adjfeedback_filter_field: self.object} - return AdjudicatorFeedback.objects.filter(**kwargs).order_by('-timestamp') - - -class FeedbackFromTeamView(FeedbackFromSourceView): - """View displaying feedback from a given source.""" - model = Team - source_name_attr = 'short_name' - adjfeedback_filter_field = 'source_team__team' - - -class FeedbackFromAdjudicatorView(FeedbackFromSourceView): - """View displaying feedback from a given adjudicator.""" - model = Adjudicator - source_name_attr = 'name' - adjfeedback_filter_field = 'source_adjudicator__adjudicator' - - -@login_required -@tournament_view -def get_adj_feedback(request, t): - - adj = get_object_or_404(Adjudicator, pk=int(request.GET['id'])) - feedback = adj.get_feedback().filter(confirmed=True) - questions = t.adj_feedback_questions - def _parse_feedback(f): - - if f.source_team: - source_annotation = " (" + f.source_team.result + ")" - elif f.source_adjudicator: - source_annotation = " (" + f.source_adjudicator.get_type_display() + ")" - else: - source_annotation = "" - - data = [ - str(f.round.abbreviation), - str(str(f.version) + (f.confirmed and "*" or "")), - f.debate.bracket, - f.debate.matchup, - str(str(f.source) + source_annotation), - f.score, - ] - for question in questions: - try: - data.append(question.answer_set.get(feedback=f).answer) - except ObjectDoesNotExist: - data.append("-") - data.append(f.confirmed) - return data - data = [_parse_feedback(f) for f in feedback] - return HttpResponse(json.dumps({'aaData': data}), content_type="text/json") - - -class BaseAddFeedbackIndexView(TournamentMixin, TemplateView): - - def get_context_data(self, **kwargs): - tournament = self.get_tournament() - kwargs['adjudicators'] = tournament.adjudicator_set.all() if not tournament.pref('share_adjs') \ - else Adjudicator.objects.all() - kwargs['teams'] = tournament.team_set.all() - return super().get_context_data(**kwargs) - - -class TabroomAddFeedbackIndexView(SuperuserOrTabroomAssistantTemplateResponseMixin, BaseAddFeedbackIndexView): - """View for the index page for tabroom officials to add feedback. The index - page lists all possible sources; officials should then choose the author - of the feedback.""" - - superuser_template_name = 'add_feedback.html' - assistant_template_name = 'assistant_add_feedback.html' - - -class PublicAddFeedbackIndexView(PublicCacheMixin, PublicTournamentPageMixin, BaseAddFeedbackIndexView): - """View for the index page for public users to add feedback. The index page - lists all possible sources; public users should then choose themselves.""" - - template_name = 'public_add_feedback.html' - public_page_preference = 'public_feedback' - - -class BaseAddFeedbackView(LogActionMixin, SingleObjectFromTournamentMixin, FormView): - """Base class for views that allow users to add feedback. - Subclasses must also subclass SingleObjectMixin, directly or indirectly.""" - - template_name = "enter_feedback.html" - pk_url_kwarg = 'source_id' - - def get_form_class(self): - return make_feedback_form_class(self.object, self.get_submitter_fields(), - **self.feedback_form_class_kwargs) - - def get_action_log_fields(self, **kwargs): - kwargs['adjudicator_feedback'] = self.adj_feedback - return super().get_action_log_fields(**kwargs) - - def form_valid(self, form): - self.adj_feedback = form.save() - return super().form_valid(form) - - def get_context_data(self, **kwargs): - source = self.object - if isinstance(source, Adjudicator): - kwargs['source_type'] = "adj" - elif isinstance(source, Team): - kwargs['source_type'] = "team" - kwargs['source_name'] = self.source_name - return super().get_context_data(**kwargs) - - def _populate_source(self): - self.object = self.get_object() # for compatibility with SingleObjectMixin - if isinstance(self.object, Adjudicator): - self.source_name = self.object.name - elif isinstance(self.object, Team): - self.source_name = self.object.short_name - else: - self.source_name = "" - - def get(self, request, *args, **kwargs): - self._populate_source() - return super().get(request, *args, **kwargs) - - def post(self, request, *args, **kwargs): - self._populate_source() - return super().post(request, *args, **kwargs) - - -class TabroomAddFeedbackView(TabroomSubmissionFieldsMixin, LoginRequiredMixin, BaseAddFeedbackView): - """View for tabroom officials to add feedback.""" - - action_log_type = ActionLogEntry.ACTION_TYPE_FEEDBACK_SAVE - feedback_form_class_kwargs = { - 'confirm_on_submit': True, - 'enforce_required': False, - 'include_unreleased_draws': True, - } - - def form_valid(self, form): - result = super().form_valid(form) - messages.success(self.request, "Feedback from {} on {} added.".format( - self.source_name, self.adj_feedback.adjudicator.name)) - return result - - def get_success_url(self): - return reverse_tournament('adjfeedback-add-index', self.get_tournament()) - - -class PublicAddFeedbackView(PublicSubmissionFieldsMixin, PublicTournamentPageMixin, BaseAddFeedbackView): - """Base class for views for public users to add feedback.""" - - action_log_type = ActionLogEntry.ACTION_TYPE_FEEDBACK_SUBMIT - feedback_form_class_kwargs = { - 'confirm_on_submit': True, - 'enforce_required': True, - 'include_unreleased_draws': False, - } - - def form_valid(self, form): - result = super().form_valid(form) - messages.success(self.request, "Thanks, your feedback on has been recorded.") - return result - - def get_success_url(self): - return reverse_tournament('tournament-public-index', self.get_tournament()) - - -class PublicAddFeedbackByRandomisedUrlView(SingleObjectByRandomisedUrlMixin, PublicAddFeedbackView): - """View for public users to add feedback, where the URL is a randomised one.""" - public_page_preference = 'public_feedback_randomised' - - -class PublicAddFeedbackByIdUrlView(PublicAddFeedbackView): - """View for public users to add feedback, where the URL is by object ID.""" - public_page_preference = 'public_feedback' - - -class AdjudicatorActionError(RuntimeError): - pass - - -class BaseAdjudicatorActionView(LogActionMixin, SuperuserRequiredMixin, TournamentMixin, PostOnlyRedirectView): - - def get_action_log_fields(self, **kwargs): - kwargs['adjudicator'] = self.adjudicator - return super().get_action_log_fields(**kwargs) - - def get_redirect_url(self): - return reverse_tournament('adjfeedback-overview', self.get_tournament()) - - def get_adjudicator(self, request): - try: - adj_id = int(request.POST["adj_id"]) - adjudicator = Adjudicator.objects.get(id=adj_id) - except (ValueError, Adjudicator.DoesNotExist, Adjudicator.MultipleObjectsReturned): - raise AdjudicatorActionError("Whoops! I didn't recognise that adjudicator: {}".format(adj_id)) - return adjudicator - - def post(self, request, *args, **kwargs): - try: - self.adjudicator = self.get_adjudicator(request) - self.modify_adjudicator(request, self.adjudicator) - self.log_action() # need to call explicitly, since this isn't a form view - except AdjudicatorActionError as e: - messages.error(request, str(e)) - - return super().post(request, *args, **kwargs) - - -class SetAdjudicatorTestScoreView(BaseAdjudicatorActionView): - - action_log_type = ActionLogEntry.ACTION_TYPE_TEST_SCORE_EDIT - - def get_action_log_fields(self, **kwargs): - kwargs['adjudicator_test_score_history'] = self.atsh - return super(BaseAdjudicatorActionView, self).get_action_log_fields(**kwargs) # skip BaseAdjudicatorActionView - - def modify_adjudicator(self, request, adjudicator): - try: - score = float(request.POST["test_score"]) - except ValueError as e: - raise AdjudicatorActionError("Whoops! The value \"{}\" isn't a valid test score.".format(score_text)) - - adjudicator.test_score = score - adjudicator.save() - - atsh = AdjudicatorTestScoreHistory(adjudicator=adjudicator, - round=self.get_tournament().current_round, score=score) - atsh.save() - self.atsh = atsh - - -class SetAdjudicatorBreakingStatusView(BaseAdjudicatorActionView): - - action_log_type = ActionLogEntry.ACTION_TYPE_ADJUDICATOR_BREAK_SET - - def modify_adjudicator(self, request, adjudicator): - adjudicator.breaking = (str(request.POST["adj_breaking_status"]) == "true") - adjudicator.save() - - def post(self, request, *args, **kwargs): - super().post(request, *args, **kwargs) # discard redirect - return HttpResponse("ok") - - -class SetAdjudicatorNoteView(BaseAdjudicatorActionView): - - action_log_type = ActionLogEntry.ACTION_TYPE_ADJUDICATOR_NOTE_SET - - def modify_adjudicator(self, request, adjudicator): - try: - note = str(request.POST["note"]) - except ValueError as e: - raise AdjudicatorActionError("Whoop! There was an error interpreting that string: " + str(e)) - - adjudicator.notes = note - adjudicator.save() - - -def get_feedback_progress(request, t): - def calculate_coverage(submitted, total): - if total == 0 or submitted == 0: - return 0 # avoid divide-by-zero error - else: - return int(submitted / total * 100) - - feedback = AdjudicatorFeedback.objects.select_related( - 'source_adjudicator__adjudicator','source_team__team').all() - adjudicators = Adjudicator.objects.filter(tournament=t) - adjudications = list(DebateAdjudicator.objects.select_related('adjudicator','debate').filter( - debate__round__stage=Round.STAGE_PRELIMINARY)) - teams = Team.objects.filter(tournament=t) - - # Teams only owe feedback on non silent rounds - rounds_owed = t.round_set.filter(silent=False, stage=Round.STAGE_PRELIMINARY, draw_status=t.current_round.STATUS_RELEASED).count() - - for adj in adjudicators: - adj.total_ballots = 0 - adj.submitted_feedbacks = feedback.filter(source_adjudicator__adjudicator = adj) - adjs_adjudications = [a for a in adjudications if a.adjudicator == adj] - - for item in adjs_adjudications: - # Finding out the composition of their panel, tallying owed ballots - if item.type == item.TYPE_CHAIR: - adj.total_ballots += len(item.debate.adjudicators.trainees) - adj.total_ballots += len(item.debate.adjudicators.panel) - - if item.type == item.TYPE_PANEL: - # Panelists owe on chairs - adj.total_ballots += 1 - - if item.type == item.TYPE_TRAINEE: - # Trainees owe on chairs - adj.total_ballots += 1 - - adj.submitted_ballots = max(adj.submitted_feedbacks.count(), 0) - adj.owed_ballots = max((adj.total_ballots - adj.submitted_ballots), 0) - adj.coverage = min(calculate_coverage(adj.submitted_ballots, adj.total_ballots), 100) - - for team in teams: - team.submitted_ballots = max(feedback.filter(source_team__team = team).count(), 0) - team.owed_ballots = max((rounds_owed - team.submitted_ballots), 0) - team.coverage = min(calculate_coverage(team.submitted_ballots, rounds_owed), 100) - - return { 'teams': teams, 'adjs': adjudicators } - - -@admin_required -@tournament_view -def feedback_progress(request, t): - progress = get_feedback_progress(request, t) - return render(request, 'feedback_progress.html', - dict(teams=progress['teams'], adjudicators=progress['adjs'])) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('feedback_progress') -def public_feedback_progress(request, t): - progress = get_feedback_progress(request, t) - return render(request, 'public_feedback_progress.html', - dict(teams=progress['teams'], adjudicators=progress['adjs'])) - - - -class RandomisedUrlsView(SuperuserRequiredMixin, TournamentMixin, TemplateView): - - template_name = 'randomised_urls.html' - - def get_context_data(self, **kwargs): - tournament = self.get_tournament() - kwargs['teams'] = tournament.team_set.all() - if not tournament.pref('share_adjs'): - kwargs['adjs'] = tournament.adjudicator_set.all() - else: - kwargs['adjs'] = Adjudicator.objects.all() - kwargs['exists'] = tournament.adjudicator_set.filter(url_key__isnull=False).exists() or \ - tournament.team_set.filter(url_key__isnull=False).exists() - kwargs['tournament_slug'] = tournament.slug - return super().get_context_data(**kwargs) - - -class GenerateRandomisedUrlsView(SuperuserRequiredMixin, TournamentMixin, PostOnlyRedirectView): - - def get_redirect_url(self): - return reverse_tournament('randomised-urls-view', self.get_tournament()) - - def post(self, request, *args, **kwargs): - tournament = self.get_tournament() - - # Only works if there are no randomised URLs now - if tournament.adjudicator_set.filter(url_key__isnull=False).exists() or \ - tournament.team_set.filter(url_key__isnull=False).exists(): - messages.error(self.request, "There are already randomised URLs. " - "You must use the Django management commands to populate or delete randomised URLs.") - else: - populate_url_keys(tournament.adjudicator_set.all()) - populate_url_keys(tournament.team_set.all()) - messages.success(self.request, "Randomised URLs were generated for all teams and adjudicators.") - - return super().post(request, *args, **kwargs) diff --git a/availability/templates/adjudicator_availability.html b/availability/templates/adjudicator_availability.html deleted file mode 100644 index 033205f1ab8..00000000000 --- a/availability/templates/adjudicator_availability.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends "base_availability.html" %} -{% load debate_tags %} - -{% block update-url %}{% round_url update_adjudicator_availability %}{% endblock %} -{% block draw-url %}{% round_url availability_index %}{% endblock %} - -{% block page-title %}Adjudicator Availability for {{ round.name }}{% endblock %} -{% block head-title %} - 👂📍Adjudicator Availability -{% endblock %} -{% block sub-title %}for {{ round.name }}{% endblock %} - -{% block table-contents %} - - - Adjudicator - {% if pref.show_institutions %} - Institution - {% endif %} - Score - {% if pref.enable_adj_notes > 0 %} - Notes - {% endif %} - {% if pref.share_adjs %} - - Shared - - {% endif %} - Breaking - Active - - - - {% for adj in adjudicators %} - - - {{ adj.name }} - - {% if pref.show_institutions %} - - {{ adj.institution.code }} - - {% endif %} - - {{ adj.score|stringformat:".2f" }} - - {% if pref.enable_adj_notes > 0 %} - - {% if adj.notes %} - View - {% endif %} - - {% endif %} - {% if pref.share_adjs %} - - {% if not adj.tournament %} - - {% endif %} - - {% endif %} - - {% if adj.breaking %}{% endif %} - - - - - - {% endfor %} - -{% endblock %} diff --git a/availability/templates/base_availability.html b/availability/templates/base_availability.html deleted file mode 100644 index bc313bde90e..00000000000 --- a/availability/templates/base_availability.html +++ /dev/null @@ -1,192 +0,0 @@ -{% extends "base.html" %} - -{% block page-subnav-sections %} - {% if round.seq > 1 %} - {% block copy_btn %} - - {% endblock %} - {% endif %} - - {% if adjudicators %} - - {% endif %} - - {% include "tables/table_search.html" %} -{% endblock %} - -{% block page-subnav-actions %} - -{% endblock %} - -{% block content %} -
-
- {% csrf_token %} -
-
- - - {% block table-contents %} - {% endblock table-contents %} -
-
- -
-
-
-{% endblock content %} - -{% block extra-js %} - - -{% endblock %} diff --git a/availability/templates/checkin_progress.html b/availability/templates/checkin_progress.html deleted file mode 100644 index e25c2130739..00000000000 --- a/availability/templates/checkin_progress.html +++ /dev/null @@ -1,38 +0,0 @@ -{% load debate_tags %} - -
-
-

{{ checkin_type.type }} Check-Ins

-
-
-
- -
- {{ round.abbreviation }} -
-
-
-
- {{ checkin_type.in_now }}/{{ checkin_type.total }} -
-
-
- - {% if round.prev %} -
- {{ round.prev.abbreviation }} -
-
-
-
- {{ checkin_type.in_before }}/{{ checkin_type.total }} -
-
-
- {% endif %} - -
-
-
diff --git a/availability/templates/team_availability.html b/availability/templates/team_availability.html deleted file mode 100644 index 8340c2f38d4..00000000000 --- a/availability/templates/team_availability.html +++ /dev/null @@ -1,50 +0,0 @@ -{% extends "base_availability.html" %} -{% load debate_tags %} - -{% block update-url %}{% round_url update_team_availability %}{% endblock %} -{% block draw-url %}{% round_url availability_index %}{% endblock %} - -{% block page-title %}Team Checkins for {{ round.name }}{% endblock %} -{% block head-title %} - 📍Team Checkins -{% endblock %} -{% block sub-title %}for {{ round.name }}{% endblock %} - -{% block table-contents %} - - - Team - {% if pref.show_emoji %} - - {% endif %} - {% if pref.enable_divisions %} - - {% endif %} - {% if pref.show_institutions %} - Institution - {% endif %} - Active - - - - {% for team in teams %} - - - {% include "tables/team.html" with team=team %} - - {% if pref.show_emoji %} - {{ team.emoji }} - {% endif %} - {% if pref.enable_divisions %} - {{ team.division.name }} - {% endif %} - {% if pref.show_institutions %} - {{ team.institution.code }} - {% endif %} - - - - - {% endfor %} - -{% endblock table-contents %} diff --git a/availability/templates/venue_availability.html b/availability/templates/venue_availability.html deleted file mode 100644 index 1e190d9bb01..00000000000 --- a/availability/templates/venue_availability.html +++ /dev/null @@ -1,50 +0,0 @@ -{% extends "base_availability.html" %} -{% load debate_tags %} - -{% block update-url %}{% round_url update_venue_availability %}{% endblock %} -{% block draw-url %}{% round_url availability_index %}{% endblock %} - -{% block page-title %}Venue Checkins for {{ round.name }}{% endblock %} -{% block head-title %} - 🎪Venue Checkins -{% endblock %} -{% block sub-title %}for {{ round.name }}{% endblock %} - -{% block table-contents %} - - - {% if pref.enable_venue_groups %} - Group - {% endif %} - Name - {% if pref.share_venues %} - Shared - {% endif %} - Priority - Active - - - - {% for venue in venues %} - - {% if pref.enable_venue_groups %} - - {% if venue.group %}{{ venue.group }} {% endif %} - - {% endif %} - {{ venue.name }} - {% if pref.share_venues %} - - {% if not venue.tournament %} - - {% endif %} - - {% endif %} - {{ venue.priority }} - - - - - {% endfor %} - -{% endblock table-contents %} diff --git a/availability/urls.py b/availability/urls.py deleted file mode 100644 index 53627af9b2b..00000000000 --- a/availability/urls.py +++ /dev/null @@ -1,79 +0,0 @@ -from django.conf.urls import url - -from . import views -from .models import ActiveTeam, ActiveVenue, ActiveAdjudicator - -urlpatterns = [ - - # Overview - url(r'^$', - views.availability_index, - name='availability_index'), - - # All - url(r'all/update/$', - views.update_availability_all, - name='update_availability_all'), - url(r'all/update_previous/$', - views.update_availability_previous, - name='update_availability_previous'), - - # People - url(r'people/$', - views.checkin_results, - {'model': 'person', - 'context_name': 'people'}, - name='people_availability'), - url(r'people/update/$', - views.checkin_update, - {'active_attr': None, - 'active_model': None, - 'update_method': 'set_available_people'}, - name='update_people_availability'), - - # Teams - url(r'teams/$', - views.availability, - {'model': 'team', - 'context_name': 'teams'}, - name='team_availability'), - url(r'teams/update/$', - views.update_availability, - {'active_attr': 'team', - 'active_model': ActiveTeam, - 'update_method': 'set_available_teams'}, - name='update_team_availability'), - url(r'teams/update/breaking/$', - views.update_availability_breaking_teams, - name='update_availability_breaking_teams'), - url(r'teams/update/advancing/$', - views.update_availability_advancing_teams, - name='update_availability_advancing_teams'), - - # Venues - url(r'venues/$', views.availability, {'model': 'venue', - 'context_name': 'venues'}, - 'venue_availability'), - url(r'venues/update/$', - views.update_availability, - {'active_attr': 'venue', - 'active_model': ActiveVenue, - 'update_method': 'set_available_venues'}, - name='update_venue_availability'), - - # Adjs - url(r'adjudicators/$', - views.availability, - {'model': 'adjudicator', - 'context_name': 'adjudicators'}, - name='adjudicator_availability'), - url(r'adjudicators/update/$', - views.update_availability, - {'active_attr': 'adjudicator', - 'active_model': ActiveAdjudicator, - 'update_method': 'set_available_adjudicators'}, - name='update_adjudicator_availability'), - url(r'adjudicators/update/breaking/$', - views.update_availability_breaking_adjs, - name='update_availability_breaking_adjs'), -] diff --git a/availability/views.py b/availability/views.py deleted file mode 100644 index f9c159b3bb7..00000000000 --- a/availability/views.py +++ /dev/null @@ -1,197 +0,0 @@ -from tournaments.models import Round -from participants.models import Person, Adjudicator -from venues.models import Venue -from actionlog.models import ActionLogEntry -from .models import ActiveVenue, ActiveTeam, ActiveAdjudicator - -from utils.views import * - -@admin_required -@round_view -def availability_index(request, round): - from draw.models import Debate - if round.prev: - previous_unconfirmed = round.prev.get_draw().filter( - result_status__in=[Debate.STATUS_NONE, Debate.STATUS_DRAFT]).count() - else: - previous_unconfirmed = None - - t = round.tournament - - total_adjs = round.tournament.adjudicator_set.count() - if t.pref('share_adjs'): - total_adjs += Adjudicator.objects.filter(tournament=None).count() - - total_venues = round.tournament.venue_set.count() - if t.pref('share_venues'): - total_venues += Venue.objects.filter(tournament=None).count() - - checks = [{ - 'type' : 'Team', - 'total' : t.teams.count(), - 'in_now' : ActiveTeam.objects.filter(round=round).count(), - 'in_before' : ActiveTeam.objects.filter(round=round.prev).count() if round.prev else None, - }, { - 'type' : 'Adjudicator', - 'total' : total_adjs, - 'in_now' : ActiveAdjudicator.objects.filter(round=round).count(), - 'in_before' : ActiveAdjudicator.objects.filter(round=round.prev).count() if round.prev else None, - }, { - 'type' : 'Venue', - 'total' : total_venues, - 'in_now' : ActiveVenue.objects.filter(round=round).count(), - 'in_before' : ActiveVenue.objects.filter(round=round.prev).count() if round.prev else None, - }] - - # Basic check before enable the button to advance - if all([checks[0]['in_now'] > 1, checks[1]['in_now'] > 0, checks[2]['in_now'] > 0]): - can_advance = True - else: - can_advance = False - - min_adjudicators = int(checks[0]['in_now'] / 2) - min_venues = int(checks[0]['in_now'] / 2) - - return render(request, 'availability_index.html', dict( - checkin_types=checks, can_advance=can_advance, previous_unconfirmed=previous_unconfirmed, - min_adjudicators=min_adjudicators, min_venues=min_venues)) - - -@admin_required -@round_view -def update_availability_all(request, round): - round.activate_all() - messages.add_message(request, messages.SUCCESS, - 'Checked in all teams, adjudicators, and venues') - return redirect_round('availability_index', round) - -@admin_required -@round_view -def update_availability_previous(request, round): - round.activate_previous() - messages.add_message(request, messages.SUCCESS, - 'Checked in all teams, adjudicators, and venues from previous round') - return redirect_round('availability_index', round) - - -@admin_required -@round_view -def update_availability_breaking_adjs(request, round): - round.activate_all_breaking_adjs() - messages.add_message(request, messages.SUCCESS, - 'Checked in all breaking adjudicators') - return redirect_round('availability_index', round) - - -@admin_required -@round_view -def update_availability_breaking_teams(request, round): - round.activate_all_breaking_teams() - messages.add_message(request, messages.SUCCESS, - 'Checked in all breaking teams') - return redirect_round('availability_index', round) - - -@admin_required -@round_view -def update_availability_advancing_teams(request, round): - round.activate_all_advancing_teams() - messages.add_message(request, messages.SUCCESS, - 'Checked in all advancing teams') - return redirect_round('availability_index', round) - -def _availability(request, round, model, context_name): - items = getattr(round, '%s_availability' % model)() - context = { context_name: items } - return render(request, '%s_availability.html' % model, context) - -# public (for barcode checkins) -@round_view -def checkin(request, round): - context = {} - if request.method == 'POST': - v = request.POST.get('barcode_id') - try: - barcode_id = int(v) - p = Person.objects.get(barcode_id=barcode_id) - ch, created = Checkin.objects.get_or_create( - person = p, - round = round - ) - context['person'] = p - - except (ValueError, Person.DoesNotExist): - context['unknown_id'] = v - - return render(request, 'person_checkin.html', context) - -# public (for barcode checkins) -# public -@round_view -def post_checkin(request, round): - v = request.POST.get('barcode_id') - try: - barcode_id = int(v) - p = Person.objects.get(barcode_id=barcode_id) - ch, created = Checkin.objects.get_or_create( - person = p, - round = round - ) - - message = p.checkin_message - - if not message: - message = "Checked in %s" % p.name - return HttpResponse(message) - - except (ValueError, Person.DoesNotExist): - return HttpResponse("Unknown Id: %s" % v) - - -@round_view -def checkin_results(request, round, model, context_name): - return _availability(request, round, model, context_name) - -@admin_required -@round_view -def availability(request, round, model, context_name): - return _availability(request, round, model, context_name) - -def _update_availability(request, round, update_method, active_model, active_attr): - if request.POST.get('copy'): - prev_round = Round.objects.get(tournament=round.tournament, - seq=round.seq-1) - - prev_objects = active_model.objects.filter(round=prev_round) - available_ids = [getattr(o, '%s_id' % active_attr) for o in prev_objects] - getattr(round, update_method)(available_ids) - - return HttpResponseRedirect(request.path.replace('update/', '')) - - available_ids = [int(a.replace("check_", "")) for a in list(request.POST.keys()) - if a.startswith("check_")] - - # Calling the relevenat update method as defined in Round - getattr(round, update_method)(available_ids) - - ACTION_TYPES = { - ActiveVenue: ActionLogEntry.ACTION_TYPE_AVAIL_VENUES_SAVE, - ActiveTeam: ActionLogEntry.ACTION_TYPE_AVAIL_TEAMS_SAVE, - ActiveAdjudicator: ActionLogEntry.ACTION_TYPE_AVAIL_ADJUDICATORS_SAVE, - } - if active_model in ACTION_TYPES: - ActionLogEntry.objects.log(type=ACTION_TYPES[active_model], - user=request.user, round=round, tournament=round.tournament) - - return HttpResponse("ok") - -@admin_required -@expect_post -@round_view -def update_availability(request, round, update_method, active_model, active_attr): - return _update_availability(request, round, update_method, active_model, active_attr) - -@expect_post -@round_view -def checkin_update(request, round, update_method, active_model, active_attr): - return _update_availability(request, round, update_method, active_model, active_attr) diff --git a/bin/post_compile b/bin/post_compile index 1f90fd9c085..6c88f67d4df 100755 --- a/bin/post_compile +++ b/bin/post_compile @@ -2,10 +2,14 @@ set -eo pipefail echo "-----> I'm post-compile hook" +cd ./tabbycat/ echo "-----> Running database migration" python manage.py migrate --noinput +echo "-----> Clearing application cache" +python manage.py clearcache + echo "-----> Running dynamic preferences checks" python manage.py checkpreferences diff --git a/bin/serve_local b/bin/serve_local new file mode 100755 index 00000000000..fd921cc886c --- /dev/null +++ b/bin/serve_local @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -eo pipefail + +cd ./tabbycat/ +waitress-serve --threads=12 --host=127.0.0.1 --port=8000 wsgi:application diff --git a/bower.json b/bower.json deleted file mode 100644 index 62ddfc0ba0e..00000000000 --- a/bower.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "tabby-cat", - "description": "Debating tabulation software for two-team parliamentary formats", - "main": "index.js", - "private": true, - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - "dependencies": { - "jquery": "^2.2.3", - "d3": "^3.5.17", - "vue": "^1.0.22", - "jquery-validation": "^1.15.0", - "jquery-ui": "^1.11.4", - "lato": "^0.3.0", - "bootstrap-sass": "^3.3.6" - } -} diff --git a/breakqual/__init__.py b/breakqual/__init__.py deleted file mode 100644 index 87dbf3f8e73..00000000000 --- a/breakqual/__init__.py +++ /dev/null @@ -1 +0,0 @@ -default_app_config = 'breakqual.apps.BreakQualConfig' \ No newline at end of file diff --git a/breakqual/breaking.py b/breakqual/breaking.py deleted file mode 100644 index 30bc40490b7..00000000000 --- a/breakqual/breaking.py +++ /dev/null @@ -1,199 +0,0 @@ -"""Module to compute the teams breaking in a BreakCategory.""" - -from collections import Counter -from standings.teams import TeamStandingsGenerator - -from .models import BreakingTeam - -def get_breaking_teams(category, include_all=False, include_categories=False): - """Returns a list of Teams, with additional attributes. For each Team t in - the returned list: - t.rank is the rank of the team, including ineligible teams. - t.break_rank is the rank of the team out of those that are in the break. - 'category' must be a BreakCategory instance. - - If 'include_all' is True: - - Teams that would break but for the institution cap are included in the - returned list, with t.break_rank set to the string "(capped)". - - If category.is_general is True, then teams that would break but for - being ineligible for this category are included in the returned list, - but with t.break_rank set to the string "(ineligible)". - Note that in no circumstances are teams that broke in a higher priority - category included in the list of returned teams. - - If 'include_all' is False, the capped and ineligible teams are excluded, - but t.rank is still the rank including those teams. - - If 'include_categories' is True, t.categories_for_display will be a comma- - delimited list of category names that are not this category, and lower - or equal priority to this category. - """ - teams = category.breaking_teams.all() - if not include_all: - teams = teams.filter(break_rank__isnull=False) - - metrics = category.tournament.pref('team_standings_precedence') - generator = TeamStandingsGenerator(metrics, ('rank',)) - standings = generator.generate(teams) - - for standing in standings: - - bt = standing.team.breakingteam_set.get(break_category=category) - standing.rank = bt.rank - if bt.break_rank is None: - if bt.remark: - standing.break_rank = "(" + bt.get_remark_display().lower() + ")" - else: - standing.break_rank = "" - else: - standing.break_rank = bt.break_rank - - if include_categories: - categories = standing.team.break_categories_nongeneral.exclude(id=category.id).exclude(priority__lt=category.priority) - standing.categories_for_display = "(" + ", ".join(c.name for c in categories) + ")" if categories else "" - else: - standing.categories_for_display = "" - - return standings - -def generate_all_breaking_teams(tournament): - """Deletes all breaking teams information, then generates breaking teams - from scratch according to update_breaking_teams().""" - for category in tournament.breakcategory_set.all(): - category.breakingteam_set.all().delete() - update_all_breaking_teams(tournament) - -def update_all_breaking_teams(tournament): - """Runs update_breaking_teams for all categories, taking taking break - category priorities into account appropriately. - """ - teams_broken_higher_priority = set() - teams_broken_cur_priority = set() - cur_priority = None - - for category in tournament.breakcategory_set.order_by('priority'): - - # If this is a new priority level, reset the current list - if cur_priority != category.priority: - teams_broken_higher_priority |= teams_broken_cur_priority - teams_broken_cur_priority = set() - cur_priority = category.priority - - eligible_teams = _eligible_team_set(category) - this_break = _generate_breaking_teams(category, eligible_teams, teams_broken_higher_priority) - teams_broken_cur_priority.update(this_break) - -def update_breaking_teams(category): - """Computes the breaking teams and stores them in the database as - BreakingTeam objects. Each BreakingTeam bt has: - bt.rank set to the rank of the team, including ineligible teams - bt.break_rank set to the rank of the team out of those that are in the - break, or None if the team is ineligible - bt.remark set to - - BreakingTeam.REMARK_CAPPED if the team would break but for the - institution cap, or - - BreakingTeam.REMARK_INELIGIBLE if category.is_general is True and - the team would break but for being ineligible for this category. - - BreakingTeam.REMARK_DIFFERENT_BREAK if the team broke in a - different category. - - If a breaking team entry already exists and there is a remark associated - with it, it retains the remark and skips that team. - """ - higher_breakingteams = BreakingTeam.objects.filter(break_category__priority__lt=category.priority, break_rank__isnull=False).select_related('team') - higher_teams = {bt.team for bt in higher_breakingteams} - eligible_teams = _eligible_team_set(category) - _generate_breaking_teams(category, eligible_teams, higher_teams) - -def _eligible_team_set(category): - if category.is_general: - return category.tournament.team_set.all() # all in tournament - else: - return category.team_set.all() - -def _generate_breaking_teams(category, eligible_teams, teams_broken_higher_priority=set()): - """Generates a list of breaking teams for the given category and returns - a list of teams in the (actual) break, i.e. excluding teams that are - ineligible, capped, broke in a different break, and so on.""" - - metrics = category.tournament.pref('team_standings_precedence') - generator = TeamStandingsGenerator(metrics, ('rank',)) - standings = generator.generate(eligible_teams) - - break_size = category.break_size - institution_cap = category.institution_cap or None - - prev_rank_value = tuple([None] * len(standings.metric_keys)) - prev_break_rank_value = tuple([None] * len(standings.metric_keys)) - cur_rank = 0 - breaking_teams = list() - breaking_teams_to_create = list() - - # Variables for institutional caps and non-breaking teams - cur_break_rank = 0 # actual break rank - cur_break_seq = 0 # sequential count of breaking teams - teams_from_institution = Counter() - - for i, standing in enumerate(standings, start=1): - - team = standing.team - - try: - bt = BreakingTeam.objects.get(break_category=category, team=team) - existing = True - except BreakingTeam.DoesNotExist: - bt = BreakingTeam(break_category=category, team=team) - existing = False - - # Compute overall rank - rank_value = tuple(standing.itermetrics()) - if rank_value != prev_rank_value: - # if we have enough teams, we're done - if len(breaking_teams) >= break_size: - break - cur_rank = i - prev_rank_value = rank_value - bt.rank = cur_rank - - # If there is an existing remark, scrub the break rank and skip - if existing and bt.remark: - bt.break_rank = None - - # Check if ineligible - elif not team.break_categories.filter(pk=category.pk).exists(): - bt.remark = bt.REMARK_INELIGIBLE - - # Check if capped out by institution cap - elif institution_cap is not None and teams_from_institution[team.institution] >= institution_cap: - bt.remark = bt.REMARK_CAPPED - - # Check if already broken to a higher category - elif team in teams_broken_higher_priority: - bt.remark = bt.REMARK_DIFFERENT_BREAK - - # If neither, this team is in the break - else: - # Compute break rank - cur_break_seq += 1 - if rank_value != prev_break_rank_value: - cur_break_rank = cur_break_seq - prev_break_rank_value = rank_value - bt.break_rank = cur_break_rank - - breaking_teams.append(team) - - # Take note of the institution - teams_from_institution[team.institution] += 1 - - bt.full_clean() - if existing: - bt.save() - else: - breaking_teams_to_create.append(bt) - - BreakingTeam.objects.bulk_create(breaking_teams_to_create) - BreakingTeam.objects.filter(break_category=category, break_rank__isnull=False).exclude( - team_id__in=[t.id for t in breaking_teams]).delete() - - - return breaking_teams \ No newline at end of file diff --git a/breakqual/templates/breaking_adjs.html b/breakqual/templates/breaking_adjs.html deleted file mode 100644 index 5b1060571bb..00000000000 --- a/breakqual/templates/breaking_adjs.html +++ /dev/null @@ -1,67 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} - -{% block head-title %}🎉Breaking Adjudicators{% endblock %} -{% block page-title %}🎉Breaking Adjudicators{% endblock %} - -{% block page-subnav-sections %} - {% if adjs.all.count == 0 %} -

Breaking adjudicators can be set in the Feedback section.

- {% endif %} - {% if adjs.all.count > 0 %} - {% include "tables/table_search.html" %} - {% endif %} -{% endblock %} - -{% block content %} - {% if adjs.all.count > 0 %} -
-
- - - - - {% if pref.show_institutions %} - - {% endif %} - - - - {% for adj in adjs %} - - - {% if pref.show_institutions %} - - {% endif %} - - {% endfor %} - -
NameInstitution
{{ adj.name }} - {{ adj.institution }} - {% if person.independent %} - (Independent) - {% endif %} - {% if person.adj_core %} - (Adj Core) - {% endif %} -
-
-
- {% endif %} -{% endblock content %} - -{% block extra-js %} - {{ block.super }} - -{% endblock extra-js %} diff --git a/breakqual/templates/breaking_index.html b/breakqual/templates/breaking_index.html deleted file mode 100644 index 3b775ceb7ac..00000000000 --- a/breakqual/templates/breaking_index.html +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} - -{% block head-title %}👑Breaks{% endblock %} -{% block page-title %}Breaks{% endblock %} - -{% block page-subnav-sections %} - {% for category in tournament.breakcategory_set.all %} - {{ category.name }} Break - {% endfor %} - Adjudicators -{% endblock %} - -{% block page-subnav-actions %} - Edit Eligibility -{% endblock %} - -{% block content %} - -
-
- - {% for category in tournament.breakcategory_set.all %} -
-
-

Teams Eligible for the {{ category }} Break

-
-
-
-
- {{ category.team_set.count }}/{{ tournament.teams.count }} -
-
-
-
- {% empty %} - - {% endfor %} - -
-
- -{% endblock content %} diff --git a/breakqual/templates/breaking_teams.html b/breakqual/templates/breaking_teams.html deleted file mode 100644 index 0f5401ec78a..00000000000 --- a/breakqual/templates/breaking_teams.html +++ /dev/null @@ -1,181 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} -{% load add_field_css %} -{% load metricformat %} - -{% block head-title %}👑{{ category.name }} Break{% endblock %} -{% block sub-title %}{{ pref.public_breaking_teams|yesno:",not "}}publicly visible{% endblock %} -{% block page-title %}👑{{ category.name }} Break{% endblock %} - -{% block page-subnav-sections %} - {% if generated %} -
- {% csrf_token %} - -
-
- {% csrf_token %} - -
-
- {% csrf_token %} - -
- {% else %} -
-
- {% csrf_token %} - -
-
- {% endif %} -{% endblock %} - -{% block page-alerts %} - {% if generated %} -
- Please double-check this before announcing the break or releasing it to the - public. The code that generates the break has not been robustly tested for - corner cases. If there are errors, please take a snapshot of the database - and a screenshot and send it to the developers. -
-
-

- How to edit the break: You can edit the remarks in the - right-hand column. Any team with a remark is considered ineligible for this - break. (The algorithm will sometimes insert its own remarks where appropriate, - based on the break size, institution cap and break category priorities.) After you do this, you must save the remarks - before proceeding (otherwise your changes will be not be saved). Then, - click the appropriate update button below. -

-

- The procedure isn't perfect; if you have complicated break category rules - (for example, if some teams are allowed to choose their preferred category) - then you may have to iterate through remark editing and saving a few times - for the algorithm to get what you want. As a last resort, you can edit the - breaking teams list directly in the database through the - Edit Data section (under Setup in the menu). -

-
- {% else %} - {% if pref.public_breaking_teams %} -
- The public breaking teams configuration setting is - enabled. As soon as you click the button, the breaking teams list will - be visible on the public site, before you have a chance to - double-check it! It is strongly recommended that you disable this - setting on the - tournament configuration page before generating the team - breaks. -
- {% else %} -
-

- The break hasn't yet been generated. Would you like to generate - the break for all categories? -

-

- (It's safe to generate the break before all preliminary rounds are - complete, if you're curious. You can regenerate it later.) -

-
- {% endif %} - {% endif %} -{% endblock %} - -{% block content %} - {% if generated %} -
- {% csrf_token %} -
-
- - - - - - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for info in form.metrics_info %} - - {% endfor %} - - - - - {% for standing, edit_remark in form.team_iter %} - - - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for metric in standing.itermetrics %} - - {% endfor %} - - - {% endfor %} - -
RankBreakTeamInst - {% if info.glyphicon %} - - {% else %} - - {{ info.abbr }} - {% endif %} - Edit remark
{{ standing.rank }}{{ standing.break_rank|default_if_none:"–" }}{{ standing.team.emoji }} - {% include "tables/team.html" with team=standing.team %} - {{ standing.team.categories_for_display }} - {{ standing.team.institution.code }}{{ metric|metricformat }} - {{ edit_remark|addcss:"form-control" }} -
- -
-
- -
-
- -
-
- -
- {% endif %} -{% endblock content %} - -{% block extra-js %} - {{ block.super }} - -{% endblock extra-js %} diff --git a/breakqual/templates/public_breaking_adjs.html b/breakqual/templates/public_breaking_adjs.html deleted file mode 100644 index 43f65a553f4..00000000000 --- a/breakqual/templates/public_breaking_adjs.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "breaking_adjs.html" %} -{% load static %} -{% load debate_tags %} - -{% block page-subnav-sections %} - {% if adjs.all.count == 0 %} -

The breaking adjudicators have not been released yet.

- {% endif %} - {% include "tables/table_search.html" %} -{% endblock %} diff --git a/breakqual/templates/public_breaking_teams.html b/breakqual/templates/public_breaking_teams.html deleted file mode 100644 index 5eb7962bcdd..00000000000 --- a/breakqual/templates/public_breaking_teams.html +++ /dev/null @@ -1,71 +0,0 @@ -{% extends "breaking_teams.html" %} -{% load static %} -{% load debate_tags %} -{% load metricformat %} - -{% block head-title %}👑{{ category.name }} Break{% endblock %} -{% block page-subnav-sections %}{% include "tables/table_search.html" %}{% endblock %} - -{% block page-alerts %} -{# Don't show the break notes to the public #} -{% endblock %} -{% block sub-title %} - {# Don't show the publicity status to the public #} -{% endblock %} - -{% block content %} -
-
- {% if generated %} - - - - - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for info in standings.metrics_info %} - - {% endfor %} - - - - {% for standing in standings %} - - - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for metric in standing.itermetrics %} - - {% endfor %} - - {% endfor %} - -
RankBreakTeamInst - {% if info.glyphicon %} - - {% else %} - - {{ info.abbr }} - {% endif %} -
{{ standing.rank }}{{ standing.break_rank|default_if_none:"–" }}{{ standing.team.emoji }} - {% include "tables/team.html" with team=standing.team %} - {{ standing.team.categories_for_display }} - {{ standing.team.institution.code }}{{ metric|metricformat }}
- {% else %} -

The break has yet to be released.

- {% endif %} -
-
-{% endblock %} diff --git a/breakqual/urls_admin.py b/breakqual/urls_admin.py deleted file mode 100644 index 093cb9235d7..00000000000 --- a/breakqual/urls_admin.py +++ /dev/null @@ -1,29 +0,0 @@ -from django.conf.urls import url - -from . import views - -urlpatterns = [ - # Display - url(r'^$', - views.breaking_index, - name='breaking_index'), - url(r'^teams/(?P\w+)/$', - views.breaking_teams, - name='breaking_teams'), - url(r'^adjudicators/$', - views.breaking_adjs, - name='breaking_adjs'), - # Create/Update - url(r'^generate_all/(?P\w+)/$', - views.generate_all_breaking_teams, - name='generate_breaking_teams'), - url(r'^update_all/(?P\w+)/$', - views.update_all_breaking_teams, - name='update_all_breaking_teams'), - url(r'^update/(?P\w+)/$', - views.update_breaking_teams, - name='update_breaking_teams'), - url(r'^eligibility/$', - views.edit_eligibility, - name='edit_eligibility'), -] diff --git a/breakqual/urls_public.py b/breakqual/urls_public.py deleted file mode 100644 index 06ea404c8b6..00000000000 --- a/breakqual/urls_public.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.conf.urls import url - -from . import views - -urlpatterns = [ - url(r'^$', - views.public_break_index, - name='public_break_index'), - url(r'^teams/(?P\w+)/$', - views.public_breaking_teams, - name='public_breaking_teams'), - url(r'^adjudicators/$', - views.public_breaking_adjs, - name='public_breaking_adjs'), -] diff --git a/breakqual/views.py b/breakqual/views.py deleted file mode 100644 index ceb4ae97043..00000000000 --- a/breakqual/views.py +++ /dev/null @@ -1,108 +0,0 @@ -from participants.models import Adjudicator -from actionlog.models import ActionLogEntry -from utils.misc import get_ip_address - -from .models import BreakCategory, BreakingTeam -from . import forms -from . import breaking - -from utils.views import * - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('public_results') -def public_break_index(request, t): - return render(request, "public_break_index.html") - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('public_breaking_teams') -def public_breaking_teams(request, t, category): - bc = get_object_or_404(BreakCategory, slug=category, tournament=t) - standings = breaking.get_breaking_teams(bc, include_all=True, include_categories=t.pref('public_break_categories')) - generated = BreakingTeam.objects.filter(break_category__tournament=t).exists() - return render(request, 'public_breaking_teams.html', dict(category=bc, generated=generated, standings=standings)) - -@admin_required -@tournament_view -def breaking_index(request, t): - return render(request, 'breaking_index.html') - -@admin_required -@tournament_view -def breaking_teams(request, t, category): - bc = get_object_or_404(BreakCategory, slug=category, tournament=t) - - if request.method == "POST": - form = forms.BreakingTeamsForm(bc, request.POST) - if form.is_valid(): - form.save() - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_BREAK_EDIT_REMARKS, - user=request.user, tournament=t, ip_address=get_ip_address(request)) - messages.success(request, "Changes to breaking team remarks saved.") - - else: - form = forms.BreakingTeamsForm(bc) - - generated = BreakingTeam.objects.filter(break_category__tournament=t).exists() - return render(request, 'breaking_teams.html', dict(form=form, category=bc, generated=generated)) - - -@expect_post -@tournament_view -def generate_all_breaking_teams(request, t, category): - """Generates for all break categories; 'category' is used only for the redirect""" - breaking.generate_all_breaking_teams(t) - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_BREAK_GENERATE_ALL, - user=request.user, tournament=t, ip_address=get_ip_address(request)) - messages.success(request, "Teams break generated for all break categories.") - return redirect_tournament('breaking_teams', t, category=category) - -@expect_post -@tournament_view -def update_all_breaking_teams(request, t, category): - """Generates for all break categories; 'category' is used only for the redirect""" - breaking.update_all_breaking_teams(t) - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_BREAK_UPDATE_ALL, - user=request.user, tournament=t, ip_address=get_ip_address(request)) - messages.success(request, "Teams break updated for all break categories.") - return redirect_tournament('breaking_teams', t, category=category) - -@expect_post -@tournament_view -def update_breaking_teams(request, t, category): - bc = get_object_or_404(BreakCategory, slug=category, tournament=t) - breaking.update_breaking_teams(bc) - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_BREAK_UPDATE_ONE, - user=request.user, tournament=t, ip_address=get_ip_address(request), - break_category=bc) - messages.success(request, "Teams break updated for break category %s." % bc.name) - return redirect_tournament('breaking_teams', t, category=category) - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('public_breaking_adjs') -def public_breaking_adjs(request, t): - adjs = Adjudicator.objects.filter(breaking=True, tournament=t) - return render(request, 'public_breaking_adjs.html', dict(adjs=adjs)) - -@admin_required -@tournament_view -def breaking_adjs(request, t): - adjs = Adjudicator.objects.filter(breaking=True, tournament=t) - return render(request, 'breaking_adjs.html', dict(adjs=adjs)) - -@admin_required -@tournament_view -def edit_eligibility(request, t): - context = dict() - if request.method == "POST": - form = forms.BreakEligibilityForm(t, request.POST) - if form.is_valid(): - form.save() - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_BREAK_ELIGIBILITY_EDIT, - user=request.user, tournament=t, ip_address=get_ip_address(request)) - messages.success(request, "Break eligibility saved.") - return redirect_tournament('breaking_index', t) - else: - form = forms.BreakEligibilityForm(t) - - context['form'] = form - return render(request, 'edit_eligibility.html', context) diff --git a/data/demo/break_categories.csv b/data/demo/break_categories.csv index 0794c0c3f39..31b27a43c1e 100644 --- a/data/demo/break_categories.csv +++ b/data/demo/break_categories.csv @@ -1,4 +1,4 @@ -name,slug,seq,break_size,is_general,priority,institution_cap -Open,open,10,8,1,10,2 -ESL,esl,20,4,0,20,2 -EFL,efl,30,2,0,30,1 \ No newline at end of file +name,slug,seq,break_size,is_general,priority,rule +Open,open,10,8,1,10,standard +ESL,esl,20,4,0,20,standard +EFL,efl,30,2,0,30,standard \ No newline at end of file diff --git a/data/demo/judges.csv b/data/demo/judges.csv index 6f827d55b16..3e4f20de8b8 100644 --- a/data/demo/judges.csv +++ b/data/demo/judges.csv @@ -1,28 +1,28 @@ -name,institution,test_score,institution_conflicts,team_conflicts,gender,pronoun,independent,novice,phone,email,notes -Levi Flores,Yale University,5,,,M,he,0,0,(400) 258-4262,leviflores@gmail.com, -Boyd Pierce,Stanford University,5,,,M,he,1,0,(645) 106-7743,boydpierce@yahoo.com, -Eunice Mcbride,University of Toronto,5,,,F,she,0,0,(549) 309-9187,eunicemcbride@outlook.com, -Ramona Cobb,California Institute of Technology,1,Princeton,,F,she,1,0,(440) 487-5776,ramonacobb@yahoo.com, -Justin Ford,California Institute of Technology,5,,Caltech 1,M,he,0,0,(618) 921-9188,justinford@outlook.com, -Luis Bennett,Columbia University,2,,,M,he,0,0,(730) 097-8797,luisbennett@gmail.com, -Mandy Estrada,Cornell University,5,,,F,she,1,0,(559) 299-0471,mandyestrada@gmail.com, -Leigh Mcgee,Harvard University,4,,,F,she,0,0,(844) 760-9302,leighmcgee@gmail.com, -Jacqueline Freeman,Harvard University,5,Toronto,Caltech 2,F,she,1,0,(297) 916-1716,jacquelinefreeman@yahoo.com, -Holly Howard,University of Toronto,5,Harvard,,F,she,1,0,(958) 783-2610,hollyhoward@gmail.com, -Pedro Burgess,University of Toronto,4,,,,,0,,(854) 441-0104,pedroburgess@yahoo.com, -Kristy Carr,Stanford University,4,,MIT 2,M,he,0,1,(644) 607-3297,kristycarr@yahoo.com, -Wilma Vaughn,Johns Hopkins University,4,,,F,she,1,1,(398) 759-9537,wilmavaughn@outlook.com, -Virginia Mccarthy,Johns Hopkins University,2,,,F,she,0,1,(455) 177-0459,virginiamccarthy@gmail.com, -Tasha Jenkins,Massachusetts Institute of Technology,2,"Cornell,Penn,Yale",Stan 1,,,1,,(875) 519-9891,tashajenkins@outlook.com, -Toby Wong,Massachusetts Institute of Technology,5,Berkeley,,M,he,0,0,(404) 641-5999,tobywong@gmail.com, -Jo Allen,Princeton University,2,,MIT 2,M,he,0,0,(761) 993-2983,joallen@yahoo.com, -Billy Griffin,Princeton University,2,,,M,he,0,0,(430) 532-2939,billygriffin@outlook.com, -Angela Reed,Stanford University,1,,Chicago 1,F,she,0,0,(936) 500-1228,angelareed@yahoo.com, -Hugo Lewis,Stanford University,2,,,M,they,0,0,(422) 585-9609,hugolewis@outlook.com, -Cassandra Wilson,"University of California, Berkeley",4,,Yale 2,F,she,,0,(604) 306-2084,cassandrawilson@gmail.com, -George Willis,University of Chicago,2,Johns Hopkins University,,M,he,0,0,(222) 204-5944,georgewillis@yahoo.com, -Jamie Hodges,University of Chicago,3,,,F,she,0,,(737) 122-6102,jamiehodges@outlook.com, -Bennie Rodriguez,University of Pennsylvania,2,Stan,,F,she,0,,(537) 641-2175,bennierodriguez@gmail.com, -Allison Martin,Yale University,4,,,F,she,,0,(525) 384-2715,allisonmartin@outlook.com, -Kristi Elliott,Yale University,3,,,F,she,0,0,(790) 289-5430,kristielliott@gmail.com, -Pearl Graves,Johns Hopkins University,5,,,F,she,,0,(317) 721-2439,pearlgraves@outlook.com, +name,institution,test_score,institution_conflicts,team_conflicts,adj_conflicts,gender,pronoun,adj_core,independent,novice,phone,email,notes +Levi Flores,Yale University,5,,,"Justin Ford, Jo Allen",M,he,1,0,0,(400) 258-4262,leviflores@fakemail.com, +Boyd Pierce,Stanford University,5,,,,M,he,1,1,0,(645) 106-7743,boydpierce@fakemail.com, +Eunice Mcbride,University of Toronto,5,,,,F,she,,0,0,(549) 309-9187,eunicemcbride@fakemail.com, +Ramona Cobb,California Institute of Technology,1,Princeton,,,F,she,,1,0,(440) 487-5776,ramonacobb@fakemail.com, +Justin Ford,California Institute of Technology,,,"Custom Team Name, Yale 2",,M,he,,0,0,(618) 921-9188,justinford@fakemail.com, +Luis Bennett,Columbia University,2,,,,M,he,,0,0,(730) 097-8797,luisbennett@fakemail.com, +Mandy Estrada,Cornell University,5,,,,F,she,,1,0,(559) 299-0471,mandyestrada@fakemail.com, +Leigh Mcgee,Harvard University,4,,,,F,she,,0,0,(844) 760-9302,leighmcgee@fakemail.com, +Jacqueline Freeman,Harvard University,5,Toronto,Caltech 2,,F,she,1,1,0,(297) 916-1716,jacquelinefreeman@fakemail.com, +Holly Howard,University of Toronto,,Harvard,,,F,she,,1,0,(958) 783-2610,, +Pedro Burgess,University of Toronto,4,,,,,,,0,,(854) 441-0104,pedroburgess@fakemail.com, +Kristy Carr,Stanford University,4,,MIT 2,,M,he,,0,1,(644) 607-3297,kristycarr@fakemail.com, +Wilma Vaughn,Johns Hopkins University,4,,,Virginia Mccarthy,F,she,,1,1,(398) 759-9537,wilmavaughn@fakemail.com, +Virginia Mccarthy,Johns Hopkins University,2,,,Wilma Vaughn,F,she,,0,1,(455) 177-0459,virginiamccarthy@fakemail.com, +Tasha Jenkins,Massachusetts Institute of Technology,2,"Cornell,Penn,Yale",Stanford 1,,,,,1,,(875) 519-9891,tashajenkins@fakemail.com, +Toby Wong,Massachusetts Institute of Technology,5,Berkeley,,,M,he,,0,0,(404) 641-5999,, +Jo Allen,Princeton University,2,,MIT 2,,M,he,,0,0,(761) 993-2983,joallen@fakemail.com, +Billy Griffin,Princeton University,2,,,,M,he,0,0,0,(430) 532-2939,billygriffin@fakemail.com, +Angela Reed,Stanford University,1,,Chicago 1,,F,she,0,0,0,(936) 500-1228,angelareed@fakemail.com, +Hugo Lewis,Stanford University,,,,,M,they,0,0,0,(422) 585-9609,hugolewis@fakemail.com, +Cassandra Wilson,"University of California, Berkeley",4,,Yale 2,,F,she,,,0,(604) 306-2084,cassandrawilson@fakemail.com, +George Willis,University of Chicago,2,Johns Hopkins University,,,M,he,,0,0,(222) 204-5944,georgewillis@fakemail.com, +Jamie Hodges,University of Chicago,3,,,,F,she,,0,,(737) 122-6102,jamiehodges@fakemail.com, +Bennie Rodriguez,University of Pennsylvania,2,Stan,,,F,she,,0,,(537) 641-2175,bennierodriguez@fakemail.com, +Allison Martin,Yale University,4,,,,F,she,,,0,(525) 384-2715,allisonmartin@fakemail.com, +Kristi Elliott,Yale University,3,,,,F,she,,0,0,(790) 289-5430,kristielliott@fakemail.com, +Pearl Graves,Johns Hopkins University,5,,,Allison Martin,F,she,,,0,(317) 721-2439,, \ No newline at end of file diff --git a/data/demo/questions.csv b/data/demo/questions.csv index 93fdb2d41bb..29b5c1d3d20 100644 --- a/data/demo/questions.csv +++ b/data/demo/questions.csv @@ -1,12 +1,12 @@ -"seq","reference","name","text","answer_type","required","team_on_orallist","chair_on_panellist","panellist_on_chair","panellist_on_panellist","min_value","max_value","choices" -10,"agree","Agree","Did you agree with the decision?","yesno",1,1,0,0,0 -11,"concur","Concur","Did this judge's decision concur with yours?","yesno",1,0,1,1,1 -20,"adjustment","Adjustment","What adjustment should be applied to this judge's speaker scores?","float",1,0,1,1,1,-20,20 -30,"word","One word","Choose one word to describe this adjudicator.","text",1,1,1,1,1 -40,"promote","Promote","Do you think this adjudicator should be promoted?","checkbox",0,1,1,1,1 -50,"demote","Demote","Do you think this adjudicator should be demoted?","checkbox",0,1,1,1,1 -60,"explanation","Explanation","How well was this adjudicator's reasoning explained?","scale",1,1,1,1,1,0,10 -70,"impartial","Impartial","How impartial did you think this adjudicator was?","scale",1,1,1,1,1,0,10 -80,"again","Again","Would you like to see this adjudicator again?","single select",0,1,0,0,0,,,"Absolutely!//Sure, why not//If I have to//Please don't" -90,"adjectives","Adjectives","How would you describe this adjudicator?","select multiple",0,1,0,0,0,,,"biased//clear//concise//rambly//attentive//inattentive" -1000,"comments","Comments","Other comments:","textbox",0,1,1,1,1 +"seq","reference","name","text","answer_type","required","from_team","from_adj","min_value","max_value","choices" +10,"agree","Agree","Did you agree with the decision?","yesno",1,1,0 +11,"concur","Concur","Did this judge's decision concur with yours?","yesno",1,0,1 +20,"adjustment","Adjustment","What adjustment should be applied to this judge's speaker scores?","float",1,0,1,-20,20 +30,"word","One word","Choose one word to describe this adjudicator.","text",1,1,1 +40,"promote","Promote","Do you think this adjudicator should be promoted?","checkbox",0,1,1 +50,"demote","Demote","Do you think this adjudicator should be demoted?","checkbox",0,1,1 +60,"explanation","Explanation","How well was this adjudicator's reasoning explained?","scale",1,1,1,0,10 +70,"impartial","Impartial","How impartial did you think this adjudicator was?","scale",1,1,1,0,10 +80,"again","Again","Would you like to see this adjudicator again?","single select",0,1,0,,,"Absolutely!//Sure, why not//If I have to//Please don't" +90,"adjectives","Adjectives","How would you describe this adjudicator?","select multiple",0,1,0,,,"biased//clear//concise//rambly//attentive//inattentive" +1000,"comments","Comments","Other comments:","textbox",0,1,1 diff --git a/data/demo/speakers.csv b/data/demo/speakers.csv index 87594b84d89..f5b898700da 100644 --- a/data/demo/speakers.csv +++ b/data/demo/speakers.csv @@ -1,73 +1,73 @@ -name,institution,team_name,use_institution_prefix,gender,pronoun,novice -Georgia Crawford,California Institute of Technology,1,1,F,she,0 -Wanda Griffin,California Institute of Technology,1,1,F,she,1 -Helen Keller,California Institute of Technology,1,1,F,she,0 -Russell Warren,California Institute of Technology,2,1,M,he,0 -Angel Rhodes,California Institute of Technology,2,1,,they,1 -Terry Henderson,California Institute of Technology,2,1,M,he,0 -Kyle Ruiz,California Institute of Technology,3,1,M,he,0 -Randolph Lambert,California Institute of Technology,3,1,M,,1 -Sergio Pittman,California Institute of Technology,3,1,M,he,0 -Earnest Becker,Columbia University,1,1,M,he,0 -Ellis Rowe,Columbia University,1,1,M,he,0 -Robin Roberson,Columbia University,1,1,M,he,1 -Gwen Newman,Cornell University,1,1,F,she,1 -Robyn Caldwell,Cornell University,1,1,F,,0 -Angie Holt,Cornell University,1,1,F,she,1 -Melvin Jordan,Harvard University,1,1,M,he, -Gladys Burke,Harvard University,1,1,F,, -Patty Saunders,Harvard University,1,1,M,he, -Thomas Pierce,Harvard University,2,1,M,he,1 -Stella Lindsey,Harvard University,2,1,F,she,1 -Adrian May,Harvard University,2,1,M,he,1 -Taylor Brown,Johns Hopkins University,1,1,M,,0 -Bethany Chambers,Johns Hopkins University,1,1,M,he,1 -Pamela Bryan,Johns Hopkins University,1,1,F,she,1 -Janet Nunez,Massachusetts Institute of Technology,1,1,F,she,1 -Owen Chandler,Massachusetts Institute of Technology,1,1,M,,1 -Lillie Rodriquez,Massachusetts Institute of Technology,1,1,F,she,1 -Rufus Dennis,Massachusetts Institute of Technology,2,1,M,he,0 -Marty Love,Massachusetts Institute of Technology,2,1,M,he,1 -Shelia Wright,Massachusetts Institute of Technology,2,1,F,she,0 -Clark Mills,Princeton University,1,1,M,he,1 -Randy Carroll,Princeton University,1,1,M,he,1 -Casey Sparks,Princeton University,1,1,M,he,1 -Candace Bowen,Princeton University,2,1,F,she,1 -Jaime Long,Princeton University,2,1,M,he,1 -Leon Hall,Princeton University,2,1,M,he,0 -Morris Nichols,Stanford University,1,1,M,he,0 -Benjamin Padilla,Stanford University,1,1,M,he,1 -Phil Lyons,Stanford University,1,1,M,he,1 -Clay Holland,Stanford University,2,1,M,he,1 -Elena Cobb,Stanford University,2,1,F,she,0 -Shawn Torres,Stanford University,2,1,M,he,0 -Willis Carson,Stanford University,3,1,M,he,1 -Wendell Nelson,Stanford University,3,1,F,she,1 -Felicia Welch,Stanford University,3,1,F,she,1 -Cory Meyer,"University of California, Berkeley",1,1,M,he,1 -Stacy Frazier,"University of California, Berkeley",1,1,F,she,1 -Claire Dunn,"University of California, Berkeley",1,1,F,she,0 -Eloise Munoz,University of Chicago,1,1,M,he,1 -Patricia Palmer,University of Chicago,1,1,M,he,1 -Stewart Day,University of Chicago,1,1,M,he,1 -Timmy Craig,University of Chicago,2,1,M,he,1 -Patrick Kelly,University of Chicago,2,1,M,he,0 -Kristopher Hayes,University of Chicago,2,1,M,he,1 -Andy Lane,University of Chicago,3,1,M,he,1 -Scott Mcdonald,University of Chicago,3,1,M,he,1 -Charlene Cortez,University of Chicago,3,1,M,he,1 -Leigh Holmes,University of Pennsylvania,1,1,F,,0 -Alma Spencer,University of Pennsylvania,1,1,F,she,0 -Winston Castro,University of Pennsylvania,1,1,M,he,1 -Emilio Simmons,University of Pennsylvania,2,1,M,he,0 -Ron Delgado,University of Pennsylvania,2,1,,he,1 -Nadine Barber,University of Pennsylvania,2,1,M,he,0 -Gail Adkins,Yale University,1,1,,he,0 -Willard Walton,Yale University,1,1,M,,0 -Jackie Peterson,Yale University,1,1,M,he,1 -Terry Thornton,Yale University,2,1,,they,1 -Norman Rodgers,Yale University,2,1,M,he,0 -Mattie Lee,Yale University,2,1,,they,0 -Woodrow Harvey,Yale University,3,1,M,he,1 -Javier Chavez,Yale University,3,1,,,0 -Janie Daniels,Yale University,3,1,F,she,0 +name,institution,team_name,use_institution_prefix,gender,pronoun,novice,email +Georgia Crawford,California Institute of Technology,Custom Team Name,0,F,she,0,georgiacrawford@fakemail.com +Wanda Griffin,California Institute of Technology,Custom Team Name,0,F,she,1,wandagriffin@fakemail.com +Helen Keller,California Institute of Technology,Custom Team Name,0,F,she,0,helenkeller@fakemail.com +Russell Warren,California Institute of Technology,2,1,M,he,0,russellwarren@fakemail.com +Angel Rhodes,California Institute of Technology,2,1,,they,1,angelrhodes@fakemail.com +Terry Henderson,California Institute of Technology,2,1,M,he,0,terryhenderson@fakemail.com +Kyle Ruiz,California Institute of Technology,3,1,M,he,0,kyleruiz@fakemail.com +Randolph Lambert,California Institute of Technology,3,1,M,,1,randolphlambert@fakemail.com +Sergio Pittman,California Institute of Technology,3,1,M,he,0,sergiopittman@fakemail.com +Earnest Becker,Columbia University,1,1,M,he,0,earnestbecker@fakemail.com +Ellis Rowe,Columbia University,1,1,M,he,0,ellisrowe@fakemail.com +Robin Roberson,Columbia University,1,1,M,he,1,robinroberson@fakemail.com +Gwen Newman,Cornell University,1,1,F,she,1,gwennewman@fakemail.com +Robyn Caldwell,Cornell University,1,1,F,,0,robyncaldwell@fakemail.com +Angie Holt,Cornell University,1,1,F,she,1,angieholt@fakemail.com +Melvin Jordan,Harvard University,1,1,M,he,,melvinjordan@fakemail.com +Gladys Burke,Harvard University,1,1,F,,,gladysburke@fakemail.com +Patty Saunders,Harvard University,1,1,M,he,,pattysaunders@fakemail.com +Thomas Pierce,Harvard University,2,1,M,he,1, +Stella Lindsey,Harvard University,2,1,F,she,1,stellalindsey@fakemail.com +Adrian May,Harvard University,2,1,M,he,1,adrianmay@fakemail.com +Taylor Brown,Johns Hopkins University,1,1,M,,0,taylorbrown@fakemail.com +Bethany Chambers,Johns Hopkins University,1,1,M,he,1,bethanychambers@fakemail.com +Pamela Bryan,Johns Hopkins University,1,1,F,she,1,pamelabryan@fakemail.com +Janet Nunez,Massachusetts Institute of Technology,1,1,F,she,1,janetnunez@fakemail.com +Owen Chandler,Massachusetts Institute of Technology,1,1,M,,1,owenchandler@fakemail.com +Lillie Rodriquez,Massachusetts Institute of Technology,1,1,F,she,1,lillierodriquez@fakemail.com +Rufus Dennis,Massachusetts Institute of Technology,2,1,M,he,0,rufusdennis@fakemail.com +Marty Love,Massachusetts Institute of Technology,2,1,M,he,1,martylove@fakemail.com +Shelia Wright,Massachusetts Institute of Technology,2,1,F,she,0,sheliawright@fakemail.com +Clark Mills,Princeton University,1,1,M,he,1,clarkmills@fakemail.com +Randy Carroll,Princeton University,1,1,M,he,1,randycarroll@fakemail.com +Casey Sparks,Princeton University,1,1,M,he,1,caseysparks@fakemail.com +Candace Bowen,Princeton University,2,1,F,she,1,candacebowen@fakemail.com +Jaime Long,Princeton University,2,1,M,he,1,jaimelong@fakemail.com +Leon Hall,Princeton University,2,1,M,he,0,leonhall@fakemail.com +Morris Nichols,Stanford University,1,1,M,he,0,morrisnichols@fakemail.com +Benjamin Padilla,Stanford University,1,1,M,he,1,benjaminpadilla@fakemail.com +Phil Lyons,Stanford University,1,1,M,he,1,phillyons@fakemail.com +Clay Holland,Stanford University,2,1,M,he,1,clayholland@fakemail.com +Elena Cobb,Stanford University,2,1,F,she,0,elenacobb@fakemail.com +Shawn Torres,Stanford University,2,1,M,he,0,shawntorres@fakemail.com +Willis Carson,Stanford University,3,1,M,he,1,williscarson@fakemail.com +Wendell Nelson,Stanford University,3,1,F,she,1,wendellnelson@fakemail.com +Felicia Welch,Stanford University,3,1,F,she,1,feliciawelch@fakemail.com +Cory Meyer,"University of California, Berkeley",1,1,M,he,1,corymeyer@fakemail.com +Stacy Frazier,"University of California, Berkeley",1,1,F,she,1,stacyfrazier@fakemail.com +Claire Dunn,"University of California, Berkeley",1,1,F,she,0,clairedunn@fakemail.com +Eloise Munoz,University of Chicago,1,1,M,he,1, +Patricia Palmer,University of Chicago,1,1,M,he,1,patriciapalmer@fakemail.com +Stewart Day,University of Chicago,1,1,M,he,1,stewartday@fakemail.com +Timmy Craig,University of Chicago,2,1,M,he,1,timmycraig@fakemail.com +Patrick Kelly,University of Chicago,2,1,M,he,0,patrickkelly@fakemail.com +Kristopher Hayes,University of Chicago,2,1,M,he,1, +Andy Lane,University of Chicago,3,1,M,he,1,andylane@fakemail.com +Scott Mcdonald,University of Chicago,3,1,M,he,1,scottmcdonald@fakemail.com +Charlene Cortez,University of Chicago,3,1,M,he,1,charlenecortez@fakemail.com +Leigh Holmes,University of Pennsylvania,1,1,F,,0,leighholmes@fakemail.com +Alma Spencer,University of Pennsylvania,1,1,F,she,0,almaspencer@fakemail.com +Winston Castro,University of Pennsylvania,1,1,M,he,1, +Emilio Simmons,University of Pennsylvania,2,1,M,he,0,emiliosimmons@fakemail.com +Ron Delgado,University of Pennsylvania,2,1,,he,1,rondelgado@fakemail.com +Nadine Barber,University of Pennsylvania,2,1,M,he,0,nadinebarber@fakemail.com +Gail Adkins,Yale University,Special Name,,,he,0,gailadkins@fakemail.com +Willard Walton,Yale University,Special Name,,M,,0,willardwalton@fakemail.com +Jackie Peterson,Yale University,Special Name,,M,he,1,jackiepeterson@fakemail.com +Terry Thornton,Yale University,2,1,,they,1,terrythornton@fakemail.com +Norman Rodgers,Yale University,2,1,M,he,0,normanrodgers@fakemail.com +Mattie Lee,Yale University,2,1,,they,0,mattielee@fakemail.com +Woodrow Harvey,Yale University,3,1,M,he,1,woodrowharvey@fakemail.com +Javier Chavez,Yale University,3,1,,,0,javierchavez@fakemail.com +Janie Daniels,Yale University,3,1,F,she,0,janiedaniels@fakemail.com \ No newline at end of file diff --git a/data/demo_simple/institutions.csv b/data/demo_simple/institutions.csv index b7e30cdb9f4..7b9696721e2 100644 --- a/data/demo_simple/institutions.csv +++ b/data/demo_simple/institutions.csv @@ -1,7 +1,7 @@ name,code,abbreviation -California Institute of Technology,Caltech,Calt -Columbia University,Columbia,Colum -Cornell University,Cornell,Corn -Harvard University,Harvard,Harv -Johns Hopkins University,Johns Hopkins,JHU -Massachusetts Institute of Technology,MIT,MIT \ No newline at end of file +RMIT University,RMIT,RAD +Melbourne University,Melbourne,MUDS +Monash University,Monash,MAD +Victoria University,Victoria,VIC +Auckland University,Auckland,AKL +Otago University,Otago,OUDCS \ No newline at end of file diff --git a/data/demo_simple/judges.csv b/data/demo_simple/judges.csv index 8a979d5f057..ce9c1062190 100644 --- a/data/demo_simple/judges.csv +++ b/data/demo_simple/judges.csv @@ -1,12 +1,12 @@ -name,institution,rating,institution_conflicts,team_conflicts -Ramona Cobb,California Institute of Technology,1,Harvard University, -Justin Ford,California Institute of Technology,5,, -Luis Bennett,Columbia University,2,, -Mandy Estrada,Cornell University,5,,Caltech 1 -Leigh Mcgee,Harvard University,4,, -Jacqueline Freeman,Harvard University,5,,Caltech 2 -Wilma Vaughn,Johns Hopkins University,4,, -Virginia Mccarthy,Johns Hopkins University,2,, -Pearl Graves,Johns Hopkins University,5,, -Tasha Jenkins,Massachusetts Institute of Technology,2,"Johns Hopkins University, Harvard University",MIT 1 -Toby Wong,Massachusetts Institute of Technology,5,California Institute of Technology, \ No newline at end of file +name,institution,test_score,institution_conflicts,team_conflicts +Ramona Cobb,RMIT University,1,Victoria University, +Justin Ford,RMIT University,5,, +Luis Bennett,Melbourne University,2,, +Mandy Estrada,Monash University,5,,Caltech 1 +Leigh Mcgee,Victoria University,4,, +Jacqueline Freeman,Victoria University,5,,Caltech 2 +Wilma Vaughn,Auckland University,4,, +Virginia Mccarthy,Auckland University,2,, +Pearl Graves,Auckland University,5,, +Tasha Jenkins,Otago University,2,"Auckland University, Victoria University",MIT 1 +Toby Wong,Otago University,5,RMIT University, \ No newline at end of file diff --git a/data/demo_simple/rounds.csv b/data/demo_simple/rounds.csv index 4f22d20a1b6..a260bc441b0 100644 --- a/data/demo_simple/rounds.csv +++ b/data/demo_simple/rounds.csv @@ -1,4 +1,4 @@ -seq,name,abbv,stage,type,is_silent +seq,name,abbreviation,stage,draw_type,silent 1,Round 1,R1,P,R,0 2,Round 2,R2,P,P,0 3,Round 3,R3,P,P,0 diff --git a/data/demo_simple/speakers.csv b/data/demo_simple/speakers.csv index 4ceec07722c..5043b7fd339 100644 --- a/data/demo_simple/speakers.csv +++ b/data/demo_simple/speakers.csv @@ -1,31 +1,31 @@ -name,institution,team_name,use_team_name_as_prefix -Georgia Crawford,California Institute of Technology,1,1 -Wanda Griffin,California Institute of Technology,1,1 -Helen Keller,California Institute of Technology,1,1 -Russell Warren,California Institute of Technology,2,1 -Angel Rhodes,California Institute of Technology,2,1 -Terry Henderson,California Institute of Technology,2,1 -Kyle Ruiz,California Institute of Technology,3,1 -Randolph Lambert,California Institute of Technology,3,1 -Sergio Pittman,California Institute of Technology,3,1 -Earnest Becker,Columbia University,1,1 -Ellis Rowe,Columbia University,1,1 -Robin Roberson,Columbia University,1,1 -Gwen Newman,Cornell University,1,1 -Robyn Caldwell,Cornell University,1,1 -Angie Holt,Cornell University,1,1 -Melvin Jordan,Harvard University,1, -Gladys Burke,Harvard University,1, -Patty Saunders,Harvard University,1, -Thomas Pierce,Harvard University,2,1 -Stella Lindsey,Harvard University,2,1 -Adrian May,Harvard University,2,1 -Taylor Brown,Johns Hopkins University,1,1 -Bethany Chambers,Johns Hopkins University,1,1 -Pamela Bryan,Johns Hopkins University,1,1 -Janet Nunez,Massachusetts Institute of Technology,1,1 -Owen Chandler,Massachusetts Institute of Technology,1,1 -Lillie Rodriquez,Massachusetts Institute of Technology,1,1 -Rufus Dennis,Massachusetts Institute of Technology,2,1 -Marty Love,Massachusetts Institute of Technology,2,1 -Shelia Wright,Massachusetts Institute of Technology,2,1 \ No newline at end of file +name,institution,team_name,use_institution_prefix +Georgia Crawford,RMIT University,1,1 +Wanda Griffin,RMIT University,1,1 +Helen Keller,RMIT University,1,1 +Russell Warren,RMIT University,2,1 +Angel Rhodes,RMIT University,2,1 +Terry Henderson,RMIT University,2,1 +Kyle Ruiz,RMIT University,3,1 +Randolph Lambert,RMIT University,3,1 +Sergio Pittman,RMIT University,3,1 +Earnest Becker,Melbourne University,1,1 +Ellis Rowe,Melbourne University,1,1 +Robin Roberson,Melbourne University,1,1 +Gwen Newman,Monash University,1,1 +Robyn Caldwell,Monash University,1,1 +Angie Holt,Monash University,1,1 +Melvin Jordan,Victoria University,1,1 +Gladys Burke,Victoria University,1,1 +Patty Saunders,Victoria University,1,1 +Thomas Pierce,Victoria University,2,1 +Stella Lindsey,Victoria University,2,1 +Adrian May,Victoria University,2,1 +Taylor Brown,Auckland University,1,1 +Bethany Chambers,Auckland University,1,1 +Pamela Bryan,Auckland University,1,1 +Janet Nunez,Otago University,1,1 +Owen Chandler,Otago University,1,1 +Lillie Rodriquez,Otago University,1,1 +Rufus Dennis,Otago University,2,1 +Marty Love,Otago University,2,1 +Shelia Wright,Otago University,2,1 \ No newline at end of file diff --git a/data/demo_simple/venues.csv b/data/demo_simple/venues.csv index 21dd5dbb3ca..4918cfc1880 100644 --- a/data/demo_simple/venues.csv +++ b/data/demo_simple/venues.csv @@ -1,12 +1,12 @@ name,priority -M04,10, -M05,10, -M10,10, -M11,10, -G01,10, -G02,10, -G03,10, -G04,10, -G05,10, -G06,10, -G07,10, \ No newline at end of file +M04,10 +M05,10 +M10,10 +M11,10 +H01,10 +H02,10 +H03,10 +H04,10 +H05,10 +H06,10 +H07,10 \ No newline at end of file diff --git a/data/fixtures/completed_demo.json b/data/fixtures/completed_demo.json index 32e09fac862..f4d1864558b 100644 --- a/data/fixtures/completed_demo.json +++ b/data/fixtures/completed_demo.json @@ -1,30339 +1 @@ -[ - { - "model": "contenttypes.contenttype", - "pk": 1, - "fields": { - "app_label": "jet", - "model": "bookmark" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 2, - "fields": { - "app_label": "jet", - "model": "pinnedapplication" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 3, - "fields": { - "app_label": "admin", - "model": "logentry" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 4, - "fields": { - "app_label": "auth", - "model": "permission" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 5, - "fields": { - "app_label": "auth", - "model": "group" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 6, - "fields": { - "app_label": "auth", - "model": "user" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 7, - "fields": { - "app_label": "contenttypes", - "model": "contenttype" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 8, - "fields": { - "app_label": "sessions", - "model": "session" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 9, - "fields": { - "app_label": "actionlog", - "model": "actionlogentry" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 10, - "fields": { - "app_label": "adjallocation", - "model": "debateadjudicator" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 11, - "fields": { - "app_label": "adjallocation", - "model": "adjudicatorconflict" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 12, - "fields": { - "app_label": "adjallocation", - "model": "adjudicatoradjudicatorconflict" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 13, - "fields": { - "app_label": "adjallocation", - "model": "adjudicatorinstitutionconflict" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 14, - "fields": { - "app_label": "adjfeedback", - "model": "adjudicatortestscorehistory" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 15, - "fields": { - "app_label": "adjfeedback", - "model": "adjudicatorfeedbackbooleananswer" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 16, - "fields": { - "app_label": "adjfeedback", - "model": "adjudicatorfeedbackintegeranswer" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 17, - "fields": { - "app_label": "adjfeedback", - "model": "adjudicatorfeedbackfloatanswer" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 18, - "fields": { - "app_label": "adjfeedback", - "model": "adjudicatorfeedbackstringanswer" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 19, - "fields": { - "app_label": "adjfeedback", - "model": "adjudicatorfeedbackquestion" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 20, - "fields": { - "app_label": "adjfeedback", - "model": "adjudicatorfeedback" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 21, - "fields": { - "app_label": "availability", - "model": "checkin" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 22, - "fields": { - "app_label": "availability", - "model": "activevenue" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 23, - "fields": { - "app_label": "availability", - "model": "activeteam" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 24, - "fields": { - "app_label": "availability", - "model": "activeadjudicator" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 25, - "fields": { - "app_label": "breakqual", - "model": "breakcategory" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 26, - "fields": { - "app_label": "breakqual", - "model": "breakingteam" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 27, - "fields": { - "app_label": "draw", - "model": "debate" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 28, - "fields": { - "app_label": "draw", - "model": "debateteam" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 29, - "fields": { - "app_label": "draw", - "model": "teampositionallocation" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 30, - "fields": { - "app_label": "draw", - "model": "teamvenuepreference" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 31, - "fields": { - "app_label": "draw", - "model": "institutionvenuepreference" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 32, - "fields": { - "app_label": "motions", - "model": "motion" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 33, - "fields": { - "app_label": "motions", - "model": "debateteammotionpreference" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 34, - "fields": { - "app_label": "options", - "model": "tournamentpreferencemodel" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 35, - "fields": { - "app_label": "participants", - "model": "region" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 36, - "fields": { - "app_label": "participants", - "model": "institution" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 37, - "fields": { - "app_label": "participants", - "model": "person" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 38, - "fields": { - "app_label": "participants", - "model": "team" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 39, - "fields": { - "app_label": "participants", - "model": "speaker" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 40, - "fields": { - "app_label": "participants", - "model": "adjudicator" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 41, - "fields": { - "app_label": "results", - "model": "ballotsubmission" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 42, - "fields": { - "app_label": "results", - "model": "speakerscorebyadj" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 43, - "fields": { - "app_label": "results", - "model": "teamscore" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 44, - "fields": { - "app_label": "results", - "model": "speakerscore" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 45, - "fields": { - "app_label": "tournaments", - "model": "tournament" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 46, - "fields": { - "app_label": "tournaments", - "model": "division" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 47, - "fields": { - "app_label": "tournaments", - "model": "round" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 48, - "fields": { - "app_label": "venues", - "model": "venuegroup" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 49, - "fields": { - "app_label": "venues", - "model": "venue" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 50, - "fields": { - "app_label": "dynamic_preferences", - "model": "globalpreferencemodel" - } - }, - { - "model": "contenttypes.contenttype", - "pk": 51, - "fields": { - "app_label": "dynamic_preferences", - "model": "userpreferencemodel" - } - }, - { - "model": "sessions.session", - "pk": "3kzdlji0npevxk7uujhpg6ocnlpke250", - "fields": { - "session_data": "YzE1NWYzNDdlMDUxNWMwN2QyYzM0N2JlOWRlMTQ0YzRhYmMzNGU2Mjp7Il9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfaWQiOiIxIn0=", - "expire_date": "2016-04-28T16:19:17.170" - } - }, - { - "model": "sessions.session", - "pk": "648deqcslg5wx5i2agvsp7rfjlhbqg4v", - "fields": { - "session_data": "YjUxNGU0YzM4YTBmOWJhMTIwYzIwOGI0YTZkZDQ3NGU1NWVlMTEwMDp7Il9hdXRoX3VzZXJfaWQiOiIxIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIn0=", - "expire_date": "2016-05-28T16:58:28.716" - } - }, - { - "model": "sessions.session", - "pk": "69lhou3tdnhxtfex06cr68ihj1tuy8p2", - "fields": { - "session_data": "MGYwYzNkMzZlMTVhY2MyZDQxY2E0NDYyMGZlZWFkZTgxN2M3NjFhMTp7Il9hdXRoX3VzZXJfaGFzaCI6Ijg5ZTc1OGNiZmNjMTU1NDc0NzQ4ODgxN2Q1NjU2OGQ3NTk5N2RlZTMiLCJfYXV0aF91c2VyX2lkIjoiMSIsIl9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIn0=", - "expire_date": "2016-05-08T12:32:35.030" - } - }, - { - "model": "sessions.session", - "pk": "6aechawxkmrasqseatjcfd2zxj5slwb6", - "fields": { - "session_data": "YjUxNGU0YzM4YTBmOWJhMTIwYzIwOGI0YTZkZDQ3NGU1NWVlMTEwMDp7Il9hdXRoX3VzZXJfaWQiOiIxIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIn0=", - "expire_date": "2016-05-28T16:58:07.718" - } - }, - { - "model": "sessions.session", - "pk": "6fbut6mbiit1tfkzbqtjapcjuctpdcvv", - "fields": { - "session_data": "YjUxNGU0YzM4YTBmOWJhMTIwYzIwOGI0YTZkZDQ3NGU1NWVlMTEwMDp7Il9hdXRoX3VzZXJfaWQiOiIxIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIn0=", - "expire_date": "2016-04-28T13:20:41.699" - } - }, - { - "model": "sessions.session", - "pk": "bqwyapn3vremp75w22ynm88lqshclum4", - "fields": { - "session_data": "YjUxNGU0YzM4YTBmOWJhMTIwYzIwOGI0YTZkZDQ3NGU1NWVlMTEwMDp7Il9hdXRoX3VzZXJfaWQiOiIxIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIn0=", - "expire_date": "2016-05-28T16:36:55.367" - } - }, - { - "model": "sessions.session", - "pk": "cmyd5qqnezh4u61vysl3npkjyqtmf1so", - "fields": { - "session_data": "YzE1NWYzNDdlMDUxNWMwN2QyYzM0N2JlOWRlMTQ0YzRhYmMzNGU2Mjp7Il9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfaWQiOiIxIn0=", - "expire_date": "2016-05-08T22:50:35.539" - } - }, - { - "model": "sessions.session", - "pk": "cyvaamc4sn4vv7d7t1tfpigzbf5ubf1j", - "fields": { - "session_data": "ZDFkZjg2Y2VlOTRjMTk4NWM5MDkyMjFlMDQ0MzI2NmI3ZjY3MWY3NDp7Il9hdXRoX3VzZXJfaGFzaCI6Ijg5ZTc1OGNiZmNjMTU1NDc0NzQ4ODgxN2Q1NjU2OGQ3NTk5N2RlZTMiLCJfYXV0aF91c2VyX2JhY2tlbmQiOiJkamFuZ28uY29udHJpYi5hdXRoLmJhY2tlbmRzLk1vZGVsQmFja2VuZCIsIl9hdXRoX3VzZXJfaWQiOiIxIn0=", - "expire_date": "2016-05-21T09:16:32.293" - } - }, - { - "model": "sessions.session", - "pk": "g2g4kyr4umbsllrkglr3qidbtpuqbo9b", - "fields": { - "session_data": "YzE1NWYzNDdlMDUxNWMwN2QyYzM0N2JlOWRlMTQ0YzRhYmMzNGU2Mjp7Il9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfaWQiOiIxIn0=", - "expire_date": "2016-05-09T12:38:46.072" - } - }, - { - "model": "sessions.session", - "pk": "jgnznk07anj9me9dcw87t3ixpusngzh1", - "fields": { - "session_data": "YjUxNGU0YzM4YTBmOWJhMTIwYzIwOGI0YTZkZDQ3NGU1NWVlMTEwMDp7Il9hdXRoX3VzZXJfaWQiOiIxIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIn0=", - "expire_date": "2016-05-30T13:49:56.604" - } - }, - { - "model": "sessions.session", - "pk": "q8259m5oe4mqcn8k8vrm1s2k6m6vzfh2", - "fields": { - "session_data": "ZDFkZjg2Y2VlOTRjMTk4NWM5MDkyMjFlMDQ0MzI2NmI3ZjY3MWY3NDp7Il9hdXRoX3VzZXJfaGFzaCI6Ijg5ZTc1OGNiZmNjMTU1NDc0NzQ4ODgxN2Q1NjU2OGQ3NTk5N2RlZTMiLCJfYXV0aF91c2VyX2JhY2tlbmQiOiJkamFuZ28uY29udHJpYi5hdXRoLmJhY2tlbmRzLk1vZGVsQmFja2VuZCIsIl9hdXRoX3VzZXJfaWQiOiIxIn0=", - "expire_date": "2016-05-28T16:58:49.334" - } - }, - { - "model": "sessions.session", - "pk": "rfpjjdr10tki6y3bmvkwqibdxfa3pjpb", - "fields": { - "session_data": "YzE1NWYzNDdlMDUxNWMwN2QyYzM0N2JlOWRlMTQ0YzRhYmMzNGU2Mjp7Il9hdXRoX3VzZXJfYmFja2VuZCI6ImRqYW5nby5jb250cmliLmF1dGguYmFja2VuZHMuTW9kZWxCYWNrZW5kIiwiX2F1dGhfdXNlcl9oYXNoIjoiODllNzU4Y2JmY2MxNTU0NzQ3NDg4ODE3ZDU2NTY4ZDc1OTk3ZGVlMyIsIl9hdXRoX3VzZXJfaWQiOiIxIn0=", - "expire_date": "2016-05-29T18:59:19.973" - } - }, - { - "model": "sessions.session", - "pk": "sl8xweg5on3100dxn1t67rfdpt8qerly", - "fields": { - "session_data": "ZDFkZjg2Y2VlOTRjMTk4NWM5MDkyMjFlMDQ0MzI2NmI3ZjY3MWY3NDp7Il9hdXRoX3VzZXJfaGFzaCI6Ijg5ZTc1OGNiZmNjMTU1NDc0NzQ4ODgxN2Q1NjU2OGQ3NTk5N2RlZTMiLCJfYXV0aF91c2VyX2JhY2tlbmQiOiJkamFuZ28uY29udHJpYi5hdXRoLmJhY2tlbmRzLk1vZGVsQmFja2VuZCIsIl9hdXRoX3VzZXJfaWQiOiIxIn0=", - "expire_date": "2016-05-26T00:15:26.146" - } - }, - { - "model": "sessions.session", - "pk": "zuadykl2w7c49i3pz1co4i4tiarp80l5", - "fields": { - "session_data": "ZDFkZjg2Y2VlOTRjMTk4NWM5MDkyMjFlMDQ0MzI2NmI3ZjY3MWY3NDp7Il9hdXRoX3VzZXJfaGFzaCI6Ijg5ZTc1OGNiZmNjMTU1NDc0NzQ4ODgxN2Q1NjU2OGQ3NTk5N2RlZTMiLCJfYXV0aF91c2VyX2JhY2tlbmQiOiJkamFuZ28uY29udHJpYi5hdXRoLmJhY2tlbmRzLk1vZGVsQmFja2VuZCIsIl9hdXRoX3VzZXJfaWQiOiIxIn0=", - "expire_date": "2016-05-28T19:54:17.448" - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 1, - "fields": { - "debate": 12, - "adjudicator": 77, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 2, - "fields": { - "debate": 11, - "adjudicator": 79, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 3, - "fields": { - "debate": 10, - "adjudicator": 75, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 4, - "fields": { - "debate": 9, - "adjudicator": 82, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 5, - "fields": { - "debate": 8, - "adjudicator": 88, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 6, - "fields": { - "debate": 7, - "adjudicator": 74, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 7, - "fields": { - "debate": 6, - "adjudicator": 99, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 8, - "fields": { - "debate": 5, - "adjudicator": 93, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 9, - "fields": { - "debate": 5, - "adjudicator": 83, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 10, - "fields": { - "debate": 5, - "adjudicator": 96, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 11, - "fields": { - "debate": 4, - "adjudicator": 95, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 12, - "fields": { - "debate": 4, - "adjudicator": 87, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 13, - "fields": { - "debate": 4, - "adjudicator": 94, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 14, - "fields": { - "debate": 3, - "adjudicator": 73, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 15, - "fields": { - "debate": 3, - "adjudicator": 80, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 16, - "fields": { - "debate": 3, - "adjudicator": 78, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 17, - "fields": { - "debate": 2, - "adjudicator": 81, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 18, - "fields": { - "debate": 2, - "adjudicator": 97, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 19, - "fields": { - "debate": 2, - "adjudicator": 90, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 20, - "fields": { - "debate": 1, - "adjudicator": 98, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 21, - "fields": { - "debate": 1, - "adjudicator": 89, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 22, - "fields": { - "debate": 1, - "adjudicator": 92, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 23, - "fields": { - "debate": 19, - "adjudicator": 74, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 24, - "fields": { - "debate": 23, - "adjudicator": 75, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 25, - "fields": { - "debate": 13, - "adjudicator": 99, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 26, - "fields": { - "debate": 17, - "adjudicator": 79, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 27, - "fields": { - "debate": 18, - "adjudicator": 88, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 28, - "fields": { - "debate": 15, - "adjudicator": 73, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 29, - "fields": { - "debate": 16, - "adjudicator": 77, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 30, - "fields": { - "debate": 20, - "adjudicator": 81, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 31, - "fields": { - "debate": 20, - "adjudicator": 82, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 32, - "fields": { - "debate": 20, - "adjudicator": 78, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 33, - "fields": { - "debate": 24, - "adjudicator": 97, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 34, - "fields": { - "debate": 24, - "adjudicator": 90, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 35, - "fields": { - "debate": 24, - "adjudicator": 92, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 36, - "fields": { - "debate": 22, - "adjudicator": 93, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 37, - "fields": { - "debate": 22, - "adjudicator": 95, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 38, - "fields": { - "debate": 22, - "adjudicator": 89, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 39, - "fields": { - "debate": 21, - "adjudicator": 80, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 40, - "fields": { - "debate": 21, - "adjudicator": 83, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 41, - "fields": { - "debate": 21, - "adjudicator": 96, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 42, - "fields": { - "debate": 14, - "adjudicator": 98, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 43, - "fields": { - "debate": 14, - "adjudicator": 94, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 44, - "fields": { - "debate": 14, - "adjudicator": 87, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 45, - "fields": { - "debate": 31, - "adjudicator": 77, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 46, - "fields": { - "debate": 33, - "adjudicator": 81, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 47, - "fields": { - "debate": 26, - "adjudicator": 74, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 48, - "fields": { - "debate": 25, - "adjudicator": 99, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 49, - "fields": { - "debate": 32, - "adjudicator": 73, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 50, - "fields": { - "debate": 30, - "adjudicator": 82, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 51, - "fields": { - "debate": 36, - "adjudicator": 88, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 52, - "fields": { - "debate": 27, - "adjudicator": 97, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 53, - "fields": { - "debate": 27, - "adjudicator": 98, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 54, - "fields": { - "debate": 27, - "adjudicator": 87, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 55, - "fields": { - "debate": 28, - "adjudicator": 83, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 56, - "fields": { - "debate": 28, - "adjudicator": 93, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 57, - "fields": { - "debate": 28, - "adjudicator": 92, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 58, - "fields": { - "debate": 35, - "adjudicator": 75, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 59, - "fields": { - "debate": 35, - "adjudicator": 95, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 60, - "fields": { - "debate": 35, - "adjudicator": 90, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 61, - "fields": { - "debate": 34, - "adjudicator": 79, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 62, - "fields": { - "debate": 34, - "adjudicator": 78, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 63, - "fields": { - "debate": 34, - "adjudicator": 94, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 64, - "fields": { - "debate": 29, - "adjudicator": 80, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 65, - "fields": { - "debate": 29, - "adjudicator": 96, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 66, - "fields": { - "debate": 29, - "adjudicator": 89, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 67, - "fields": { - "debate": 38, - "adjudicator": 88, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 68, - "fields": { - "debate": 46, - "adjudicator": 81, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 69, - "fields": { - "debate": 48, - "adjudicator": 79, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 70, - "fields": { - "debate": 47, - "adjudicator": 99, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 71, - "fields": { - "debate": 44, - "adjudicator": 82, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 72, - "fields": { - "debate": 45, - "adjudicator": 73, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 73, - "fields": { - "debate": 37, - "adjudicator": 74, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 74, - "fields": { - "debate": 40, - "adjudicator": 95, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 75, - "fields": { - "debate": 40, - "adjudicator": 87, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 76, - "fields": { - "debate": 40, - "adjudicator": 90, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 77, - "fields": { - "debate": 39, - "adjudicator": 98, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 78, - "fields": { - "debate": 39, - "adjudicator": 96, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 79, - "fields": { - "debate": 39, - "adjudicator": 78, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 80, - "fields": { - "debate": 41, - "adjudicator": 77, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 81, - "fields": { - "debate": 41, - "adjudicator": 80, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 82, - "fields": { - "debate": 41, - "adjudicator": 94, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 83, - "fields": { - "debate": 43, - "adjudicator": 75, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 84, - "fields": { - "debate": 43, - "adjudicator": 93, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 85, - "fields": { - "debate": 43, - "adjudicator": 92, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 86, - "fields": { - "debate": 42, - "adjudicator": 83, - "type": "C", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 87, - "fields": { - "debate": 42, - "adjudicator": 97, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.debateadjudicator", - "pk": 88, - "fields": { - "debate": 42, - "adjudicator": 89, - "type": "P", - "timing_confirmed": null - } - }, - { - "model": "adjallocation.adjudicatorconflict", - "pk": 1, - "fields": { - "adjudicator": 77, - "team": 1 - } - }, - { - "model": "adjallocation.adjudicatorconflict", - "pk": 2, - "fields": { - "adjudicator": 81, - "team": 2 - } - }, - { - "model": "adjallocation.adjudicatorconflict", - "pk": 3, - "fields": { - "adjudicator": 84, - "team": 10 - } - }, - { - "model": "adjallocation.adjudicatorconflict", - "pk": 4, - "fields": { - "adjudicator": 87, - "team": 13 - } - }, - { - "model": "adjallocation.adjudicatorconflict", - "pk": 5, - "fields": { - "adjudicator": 89, - "team": 10 - } - }, - { - "model": "adjallocation.adjudicatorconflict", - "pk": 6, - "fields": { - "adjudicator": 91, - "team": 17 - } - }, - { - "model": "adjallocation.adjudicatorconflict", - "pk": 7, - "fields": { - "adjudicator": 93, - "team": 23 - } - }, - { - "model": "adjallocation.adjudicatorconflict", - "pk": 8, - "fields": { - "adjudicator": 89, - "team": 7 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 1, - "fields": { - "adjudicator": 73, - "institution": 13 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 2, - "fields": { - "adjudicator": 74, - "institution": 8 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 3, - "fields": { - "adjudicator": 75, - "institution": 12 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 4, - "fields": { - "adjudicator": 76, - "institution": 1 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 5, - "fields": { - "adjudicator": 77, - "institution": 1 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 6, - "fields": { - "adjudicator": 78, - "institution": 2 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 7, - "fields": { - "adjudicator": 79, - "institution": 3 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 8, - "fields": { - "adjudicator": 80, - "institution": 4 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 9, - "fields": { - "adjudicator": 81, - "institution": 4 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 10, - "fields": { - "adjudicator": 82, - "institution": 12 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 11, - "fields": { - "adjudicator": 83, - "institution": 12 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 12, - "fields": { - "adjudicator": 84, - "institution": 8 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 13, - "fields": { - "adjudicator": 85, - "institution": 5 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 14, - "fields": { - "adjudicator": 86, - "institution": 5 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 15, - "fields": { - "adjudicator": 87, - "institution": 6 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 16, - "fields": { - "adjudicator": 88, - "institution": 6 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 17, - "fields": { - "adjudicator": 89, - "institution": 7 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 18, - "fields": { - "adjudicator": 90, - "institution": 7 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 19, - "fields": { - "adjudicator": 91, - "institution": 8 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 20, - "fields": { - "adjudicator": 92, - "institution": 8 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 21, - "fields": { - "adjudicator": 93, - "institution": 9 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 22, - "fields": { - "adjudicator": 94, - "institution": 10 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 23, - "fields": { - "adjudicator": 95, - "institution": 10 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 24, - "fields": { - "adjudicator": 96, - "institution": 11 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 25, - "fields": { - "adjudicator": 97, - "institution": 13 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 26, - "fields": { - "adjudicator": 98, - "institution": 13 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 27, - "fields": { - "adjudicator": 99, - "institution": 5 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 28, - "fields": { - "adjudicator": 76, - "institution": 7 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 29, - "fields": { - "adjudicator": 81, - "institution": 12 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 30, - "fields": { - "adjudicator": 82, - "institution": 4 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 31, - "fields": { - "adjudicator": 87, - "institution": 3 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 32, - "fields": { - "adjudicator": 87, - "institution": 11 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 33, - "fields": { - "adjudicator": 87, - "institution": 13 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 34, - "fields": { - "adjudicator": 88, - "institution": 9 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 35, - "fields": { - "adjudicator": 94, - "institution": 5 - } - }, - { - "model": "adjallocation.adjudicatorinstitutionconflict", - "pk": 36, - "fields": { - "adjudicator": 96, - "institution": 8 - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 1, - "fields": { - "adjudicator": 73, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.407" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 2, - "fields": { - "adjudicator": 74, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.409" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 3, - "fields": { - "adjudicator": 75, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.410" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 4, - "fields": { - "adjudicator": 76, - "round": null, - "score": 1.0, - "timestamp": "2016-04-14T13:19:04.411" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 5, - "fields": { - "adjudicator": 77, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.412" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 6, - "fields": { - "adjudicator": 78, - "round": null, - "score": 2.0, - "timestamp": "2016-04-14T13:19:04.413" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 7, - "fields": { - "adjudicator": 79, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.414" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 8, - "fields": { - "adjudicator": 80, - "round": null, - "score": 4.0, - "timestamp": "2016-04-14T13:19:04.415" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 9, - "fields": { - "adjudicator": 81, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.416" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 10, - "fields": { - "adjudicator": 82, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.417" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 11, - "fields": { - "adjudicator": 83, - "round": null, - "score": 4.0, - "timestamp": "2016-04-14T13:19:04.417" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 12, - "fields": { - "adjudicator": 84, - "round": null, - "score": 4.0, - "timestamp": "2016-04-14T13:19:04.418" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 13, - "fields": { - "adjudicator": 85, - "round": null, - "score": 4.0, - "timestamp": "2016-04-14T13:19:04.419" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 14, - "fields": { - "adjudicator": 86, - "round": null, - "score": 2.0, - "timestamp": "2016-04-14T13:19:04.420" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 15, - "fields": { - "adjudicator": 87, - "round": null, - "score": 2.0, - "timestamp": "2016-04-14T13:19:04.421" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 16, - "fields": { - "adjudicator": 88, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.422" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 17, - "fields": { - "adjudicator": 89, - "round": null, - "score": 2.0, - "timestamp": "2016-04-14T13:19:04.423" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 18, - "fields": { - "adjudicator": 90, - "round": null, - "score": 2.0, - "timestamp": "2016-04-14T13:19:04.424" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 19, - "fields": { - "adjudicator": 91, - "round": null, - "score": 1.0, - "timestamp": "2016-04-14T13:19:04.425" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 20, - "fields": { - "adjudicator": 92, - "round": null, - "score": 2.0, - "timestamp": "2016-04-14T13:19:04.425" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 21, - "fields": { - "adjudicator": 93, - "round": null, - "score": 4.0, - "timestamp": "2016-04-14T13:19:04.426" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 22, - "fields": { - "adjudicator": 94, - "round": null, - "score": 2.0, - "timestamp": "2016-04-14T13:19:04.427" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 23, - "fields": { - "adjudicator": 95, - "round": null, - "score": 3.0, - "timestamp": "2016-04-14T13:19:04.428" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 24, - "fields": { - "adjudicator": 96, - "round": null, - "score": 2.0, - "timestamp": "2016-04-14T13:19:04.429" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 25, - "fields": { - "adjudicator": 97, - "round": null, - "score": 4.0, - "timestamp": "2016-04-14T13:19:04.430" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 26, - "fields": { - "adjudicator": 98, - "round": null, - "score": 3.0, - "timestamp": "2016-04-14T13:19:04.430" - } - }, - { - "model": "adjfeedback.adjudicatortestscorehistory", - "pk": 27, - "fields": { - "adjudicator": 99, - "round": null, - "score": 5.0, - "timestamp": "2016-04-14T13:19:04.431" - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 1, - "fields": { - "tournament": 1, - "seq": 10, - "text": "Did you agree with the decision?", - "name": "Agree", - "reference": "agree", - "chair_on_panellist": false, - "panellist_on_chair": false, - "panellist_on_panellist": false, - "team_on_orallist": true, - "answer_type": "bs", - "required": true, - "min_value": null, - "max_value": null, - "choices": null - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 2, - "fields": { - "tournament": 1, - "seq": 11, - "text": "Did this judge's decision concur with yours?", - "name": "Concur", - "reference": "concur", - "chair_on_panellist": true, - "panellist_on_chair": true, - "panellist_on_panellist": true, - "team_on_orallist": false, - "answer_type": "bs", - "required": true, - "min_value": null, - "max_value": null, - "choices": null - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 3, - "fields": { - "tournament": 1, - "seq": 20, - "text": "What adjustment should be applied to this judge's speaker scores?", - "name": "Adjustment", - "reference": "adjustment", - "chair_on_panellist": true, - "panellist_on_chair": true, - "panellist_on_panellist": true, - "team_on_orallist": false, - "answer_type": "f", - "required": true, - "min_value": -20.0, - "max_value": 20.0, - "choices": null - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 4, - "fields": { - "tournament": 1, - "seq": 30, - "text": "Choose one word to describe this adjudicator.", - "name": "One word", - "reference": "word", - "chair_on_panellist": true, - "panellist_on_chair": true, - "panellist_on_panellist": true, - "team_on_orallist": true, - "answer_type": "t", - "required": true, - "min_value": null, - "max_value": null, - "choices": null - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 5, - "fields": { - "tournament": 1, - "seq": 40, - "text": "Do you think this adjudicator should be promoted?", - "name": "Promote", - "reference": "promote", - "chair_on_panellist": true, - "panellist_on_chair": true, - "panellist_on_panellist": true, - "team_on_orallist": true, - "answer_type": "bc", - "required": false, - "min_value": null, - "max_value": null, - "choices": null - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 6, - "fields": { - "tournament": 1, - "seq": 50, - "text": "Do you think this adjudicator should be demoted?", - "name": "Demote", - "reference": "demote", - "chair_on_panellist": true, - "panellist_on_chair": true, - "panellist_on_panellist": true, - "team_on_orallist": true, - "answer_type": "bc", - "required": false, - "min_value": null, - "max_value": null, - "choices": null - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 7, - "fields": { - "tournament": 1, - "seq": 60, - "text": "How well was this adjudicator's reasoning explained?", - "name": "Explanation", - "reference": "explanation", - "chair_on_panellist": true, - "panellist_on_chair": true, - "panellist_on_panellist": true, - "team_on_orallist": true, - "answer_type": "is", - "required": true, - "min_value": 0.0, - "max_value": 10.0, - "choices": null - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 8, - "fields": { - "tournament": 1, - "seq": 70, - "text": "How impartial did you think this adjudicator was?", - "name": "Impartial", - "reference": "impartial", - "chair_on_panellist": true, - "panellist_on_chair": true, - "panellist_on_panellist": true, - "team_on_orallist": true, - "answer_type": "is", - "required": true, - "min_value": 0.0, - "max_value": 10.0, - "choices": null - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 9, - "fields": { - "tournament": 1, - "seq": 80, - "text": "Would you like to see this adjudicator again?", - "name": "Again", - "reference": "again", - "chair_on_panellist": false, - "panellist_on_chair": false, - "panellist_on_panellist": false, - "team_on_orallist": true, - "answer_type": "ss", - "required": false, - "min_value": null, - "max_value": null, - "choices": "Absolutely!//Sure, why not//If I have to//Please don't" - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 10, - "fields": { - "tournament": 1, - "seq": 90, - "text": "How would you describe this adjudicator?", - "name": "Adjectives", - "reference": "adjectives", - "chair_on_panellist": false, - "panellist_on_chair": false, - "panellist_on_panellist": false, - "team_on_orallist": true, - "answer_type": "ms", - "required": false, - "min_value": null, - "max_value": null, - "choices": "biased//clear//concise//rambly//attentive//inattentive" - } - }, - { - "model": "adjfeedback.adjudicatorfeedbackquestion", - "pk": 11, - "fields": { - "tournament": 1, - "seq": 1000, - "text": "Other comments:", - "name": "Comments", - "reference": "comments", - "chair_on_panellist": true, - "panellist_on_chair": true, - "panellist_on_panellist": true, - "team_on_orallist": true, - "answer_type": "tl", - "required": false, - "min_value": null, - "max_value": null, - "choices": null - } - }, - { - "model": "availability.activevenue", - "pk": 1, - "fields": { - "venue": 1, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 2, - "fields": { - "venue": 2, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 3, - "fields": { - "venue": 3, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 4, - "fields": { - "venue": 4, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 5, - "fields": { - "venue": 5, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 6, - "fields": { - "venue": 6, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 7, - "fields": { - "venue": 7, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 8, - "fields": { - "venue": 8, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 9, - "fields": { - "venue": 9, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 10, - "fields": { - "venue": 10, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 11, - "fields": { - "venue": 11, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 12, - "fields": { - "venue": 12, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 13, - "fields": { - "venue": 13, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 14, - "fields": { - "venue": 14, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 15, - "fields": { - "venue": 15, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 16, - "fields": { - "venue": 16, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 17, - "fields": { - "venue": 17, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 18, - "fields": { - "venue": 18, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 19, - "fields": { - "venue": 19, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 20, - "fields": { - "venue": 20, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 21, - "fields": { - "venue": 21, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 22, - "fields": { - "venue": 22, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 23, - "fields": { - "venue": 23, - "round": 4 - } - }, - { - "model": "availability.activevenue", - "pk": 24, - "fields": { - "venue": 1, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 25, - "fields": { - "venue": 2, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 26, - "fields": { - "venue": 3, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 27, - "fields": { - "venue": 4, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 28, - "fields": { - "venue": 5, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 29, - "fields": { - "venue": 6, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 30, - "fields": { - "venue": 7, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 31, - "fields": { - "venue": 8, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 32, - "fields": { - "venue": 9, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 33, - "fields": { - "venue": 10, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 34, - "fields": { - "venue": 11, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 35, - "fields": { - "venue": 12, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 36, - "fields": { - "venue": 13, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 37, - "fields": { - "venue": 14, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 38, - "fields": { - "venue": 15, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 39, - "fields": { - "venue": 16, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 40, - "fields": { - "venue": 17, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 41, - "fields": { - "venue": 18, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 42, - "fields": { - "venue": 19, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 43, - "fields": { - "venue": 20, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 44, - "fields": { - "venue": 21, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 45, - "fields": { - "venue": 22, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 46, - "fields": { - "venue": 23, - "round": 3 - } - }, - { - "model": "availability.activevenue", - "pk": 47, - "fields": { - "venue": 1, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 48, - "fields": { - "venue": 2, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 49, - "fields": { - "venue": 3, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 50, - "fields": { - "venue": 4, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 51, - "fields": { - "venue": 5, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 52, - "fields": { - "venue": 6, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 53, - "fields": { - "venue": 7, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 54, - "fields": { - "venue": 8, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 55, - "fields": { - "venue": 9, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 56, - "fields": { - "venue": 10, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 57, - "fields": { - "venue": 11, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 58, - "fields": { - "venue": 12, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 59, - "fields": { - "venue": 13, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 60, - "fields": { - "venue": 14, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 61, - "fields": { - "venue": 15, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 62, - "fields": { - "venue": 16, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 63, - "fields": { - "venue": 17, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 64, - "fields": { - "venue": 18, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 65, - "fields": { - "venue": 19, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 66, - "fields": { - "venue": 20, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 67, - "fields": { - "venue": 21, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 68, - "fields": { - "venue": 22, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 69, - "fields": { - "venue": 23, - "round": 2 - } - }, - { - "model": "availability.activevenue", - "pk": 93, - "fields": { - "venue": 1, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 94, - "fields": { - "venue": 2, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 95, - "fields": { - "venue": 3, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 96, - "fields": { - "venue": 4, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 97, - "fields": { - "venue": 5, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 98, - "fields": { - "venue": 6, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 99, - "fields": { - "venue": 7, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 100, - "fields": { - "venue": 8, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 101, - "fields": { - "venue": 9, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 102, - "fields": { - "venue": 10, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 103, - "fields": { - "venue": 11, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 104, - "fields": { - "venue": 12, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 105, - "fields": { - "venue": 13, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 106, - "fields": { - "venue": 14, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 107, - "fields": { - "venue": 15, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 108, - "fields": { - "venue": 16, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 109, - "fields": { - "venue": 17, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 110, - "fields": { - "venue": 18, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 111, - "fields": { - "venue": 19, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 112, - "fields": { - "venue": 20, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 113, - "fields": { - "venue": 21, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 114, - "fields": { - "venue": 22, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 115, - "fields": { - "venue": 23, - "round": 5 - } - }, - { - "model": "availability.activevenue", - "pk": 116, - "fields": { - "venue": 1, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 117, - "fields": { - "venue": 2, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 118, - "fields": { - "venue": 3, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 119, - "fields": { - "venue": 4, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 120, - "fields": { - "venue": 5, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 121, - "fields": { - "venue": 6, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 122, - "fields": { - "venue": 7, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 123, - "fields": { - "venue": 8, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 124, - "fields": { - "venue": 9, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 125, - "fields": { - "venue": 10, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 126, - "fields": { - "venue": 11, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 127, - "fields": { - "venue": 12, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 128, - "fields": { - "venue": 13, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 129, - "fields": { - "venue": 14, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 130, - "fields": { - "venue": 15, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 131, - "fields": { - "venue": 16, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 132, - "fields": { - "venue": 17, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 133, - "fields": { - "venue": 18, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 134, - "fields": { - "venue": 19, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 135, - "fields": { - "venue": 20, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 136, - "fields": { - "venue": 21, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 137, - "fields": { - "venue": 22, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 138, - "fields": { - "venue": 23, - "round": 6 - } - }, - { - "model": "availability.activevenue", - "pk": 139, - "fields": { - "venue": 16, - "round": 7 - } - }, - { - "model": "availability.activevenue", - "pk": 140, - "fields": { - "venue": 9, - "round": 7 - } - }, - { - "model": "availability.activevenue", - "pk": 141, - "fields": { - "venue": 12, - "round": 7 - } - }, - { - "model": "availability.activevenue", - "pk": 142, - "fields": { - "venue": 6, - "round": 7 - } - }, - { - "model": "availability.activevenue", - "pk": 152, - "fields": { - "venue": 1, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 153, - "fields": { - "venue": 3, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 154, - "fields": { - "venue": 4, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 155, - "fields": { - "venue": 5, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 156, - "fields": { - "venue": 6, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 157, - "fields": { - "venue": 7, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 158, - "fields": { - "venue": 8, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 159, - "fields": { - "venue": 9, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 160, - "fields": { - "venue": 10, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 161, - "fields": { - "venue": 11, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 162, - "fields": { - "venue": 12, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 163, - "fields": { - "venue": 13, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 164, - "fields": { - "venue": 14, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 165, - "fields": { - "venue": 15, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 166, - "fields": { - "venue": 16, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 167, - "fields": { - "venue": 17, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 168, - "fields": { - "venue": 18, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 169, - "fields": { - "venue": 19, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 170, - "fields": { - "venue": 20, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 171, - "fields": { - "venue": 21, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 172, - "fields": { - "venue": 22, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 173, - "fields": { - "venue": 23, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 174, - "fields": { - "venue": 24, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 175, - "fields": { - "venue": 25, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 176, - "fields": { - "venue": 26, - "round": 1 - } - }, - { - "model": "availability.activevenue", - "pk": 177, - "fields": { - "venue": 27, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 1, - "fields": { - "team": 1, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 2, - "fields": { - "team": 2, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 3, - "fields": { - "team": 3, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 4, - "fields": { - "team": 4, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 5, - "fields": { - "team": 5, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 6, - "fields": { - "team": 6, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 7, - "fields": { - "team": 7, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 8, - "fields": { - "team": 8, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 9, - "fields": { - "team": 9, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 10, - "fields": { - "team": 10, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 11, - "fields": { - "team": 11, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 12, - "fields": { - "team": 12, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 13, - "fields": { - "team": 13, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 14, - "fields": { - "team": 14, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 15, - "fields": { - "team": 15, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 16, - "fields": { - "team": 16, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 17, - "fields": { - "team": 17, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 18, - "fields": { - "team": 18, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 19, - "fields": { - "team": 19, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 20, - "fields": { - "team": 20, - "round": 4 - } - }, - { - "model": "availability.activeteam", - "pk": 160, - "fields": { - "team": 9, - "round": 6 - } - }, - { - "model": "availability.activeteam", - "pk": 161, - "fields": { - "team": 10, - "round": 6 - } - }, - { - "model": "availability.activeteam", - "pk": 162, - "fields": { - "team": 5, - "round": 6 - } - }, - { - "model": "availability.activeteam", - "pk": 163, - "fields": { - "team": 6, - "round": 6 - } - }, - { - "model": "availability.activeteam", - "pk": 164, - "fields": { - "team": 19, - "round": 9 - } - }, - { - "model": "availability.activeteam", - "pk": 165, - "fields": { - "team": 1, - "round": 5 - } - }, - { - "model": "availability.activeteam", - "pk": 173, - "fields": { - "team": 4, - "round": 5 - } - }, - { - "model": "availability.activeteam", - "pk": 174, - "fields": { - "team": 7, - "round": 5 - } - }, - { - "model": "availability.activeteam", - "pk": 175, - "fields": { - "team": 11, - "round": 5 - } - }, - { - "model": "availability.activeteam", - "pk": 176, - "fields": { - "team": 12, - "round": 5 - } - }, - { - "model": "availability.activeteam", - "pk": 177, - "fields": { - "team": 17, - "round": 5 - } - }, - { - "model": "availability.activeteam", - "pk": 178, - "fields": { - "team": 18, - "round": 5 - } - }, - { - "model": "availability.activeteam", - "pk": 179, - "fields": { - "team": 20, - "round": 5 - } - }, - { - "model": "availability.activeteam", - "pk": 180, - "fields": { - "team": 18, - "round": 7 - } - }, - { - "model": "availability.activeteam", - "pk": 181, - "fields": { - "team": 12, - "round": 7 - } - }, - { - "model": "availability.activeteam", - "pk": 182, - "fields": { - "team": 4, - "round": 7 - } - }, - { - "model": "availability.activeteam", - "pk": 183, - "fields": { - "team": 20, - "round": 7 - } - }, - { - "model": "availability.activeteam", - "pk": 184, - "fields": { - "team": 1, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 185, - "fields": { - "team": 2, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 186, - "fields": { - "team": 3, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 187, - "fields": { - "team": 4, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 188, - "fields": { - "team": 5, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 189, - "fields": { - "team": 6, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 190, - "fields": { - "team": 7, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 191, - "fields": { - "team": 8, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 192, - "fields": { - "team": 9, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 193, - "fields": { - "team": 10, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 194, - "fields": { - "team": 11, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 195, - "fields": { - "team": 12, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 196, - "fields": { - "team": 13, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 197, - "fields": { - "team": 14, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 198, - "fields": { - "team": 15, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 199, - "fields": { - "team": 16, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 200, - "fields": { - "team": 17, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 201, - "fields": { - "team": 18, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 202, - "fields": { - "team": 19, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 203, - "fields": { - "team": 20, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 204, - "fields": { - "team": 21, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 205, - "fields": { - "team": 22, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 206, - "fields": { - "team": 23, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 207, - "fields": { - "team": 24, - "round": 2 - } - }, - { - "model": "availability.activeteam", - "pk": 213, - "fields": { - "team": 1, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 214, - "fields": { - "team": 2, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 215, - "fields": { - "team": 3, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 216, - "fields": { - "team": 4, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 217, - "fields": { - "team": 5, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 218, - "fields": { - "team": 6, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 219, - "fields": { - "team": 7, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 220, - "fields": { - "team": 8, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 221, - "fields": { - "team": 9, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 222, - "fields": { - "team": 10, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 223, - "fields": { - "team": 11, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 224, - "fields": { - "team": 12, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 225, - "fields": { - "team": 13, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 226, - "fields": { - "team": 14, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 227, - "fields": { - "team": 15, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 228, - "fields": { - "team": 16, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 229, - "fields": { - "team": 17, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 230, - "fields": { - "team": 18, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 231, - "fields": { - "team": 19, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 232, - "fields": { - "team": 20, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 233, - "fields": { - "team": 21, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 234, - "fields": { - "team": 22, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 235, - "fields": { - "team": 23, - "round": 1 - } - }, - { - "model": "availability.activeteam", - "pk": 236, - "fields": { - "team": 24, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 1, - "fields": { - "adjudicator": 73, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 2, - "fields": { - "adjudicator": 74, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 3, - "fields": { - "adjudicator": 75, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 4, - "fields": { - "adjudicator": 76, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 5, - "fields": { - "adjudicator": 77, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 6, - "fields": { - "adjudicator": 78, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 7, - "fields": { - "adjudicator": 79, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 8, - "fields": { - "adjudicator": 80, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 9, - "fields": { - "adjudicator": 81, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 10, - "fields": { - "adjudicator": 82, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 11, - "fields": { - "adjudicator": 83, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 12, - "fields": { - "adjudicator": 84, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 13, - "fields": { - "adjudicator": 85, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 14, - "fields": { - "adjudicator": 86, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 15, - "fields": { - "adjudicator": 87, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 16, - "fields": { - "adjudicator": 88, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 17, - "fields": { - "adjudicator": 89, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 18, - "fields": { - "adjudicator": 90, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 19, - "fields": { - "adjudicator": 91, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 20, - "fields": { - "adjudicator": 92, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 21, - "fields": { - "adjudicator": 93, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 22, - "fields": { - "adjudicator": 94, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 23, - "fields": { - "adjudicator": 95, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 24, - "fields": { - "adjudicator": 96, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 25, - "fields": { - "adjudicator": 97, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 26, - "fields": { - "adjudicator": 98, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 27, - "fields": { - "adjudicator": 99, - "round": 4 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 28, - "fields": { - "adjudicator": 73, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 29, - "fields": { - "adjudicator": 74, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 30, - "fields": { - "adjudicator": 75, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 31, - "fields": { - "adjudicator": 76, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 32, - "fields": { - "adjudicator": 77, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 33, - "fields": { - "adjudicator": 78, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 34, - "fields": { - "adjudicator": 79, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 35, - "fields": { - "adjudicator": 80, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 36, - "fields": { - "adjudicator": 81, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 37, - "fields": { - "adjudicator": 82, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 38, - "fields": { - "adjudicator": 83, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 39, - "fields": { - "adjudicator": 84, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 40, - "fields": { - "adjudicator": 85, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 41, - "fields": { - "adjudicator": 86, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 42, - "fields": { - "adjudicator": 87, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 43, - "fields": { - "adjudicator": 88, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 44, - "fields": { - "adjudicator": 89, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 45, - "fields": { - "adjudicator": 90, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 46, - "fields": { - "adjudicator": 91, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 47, - "fields": { - "adjudicator": 92, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 48, - "fields": { - "adjudicator": 93, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 49, - "fields": { - "adjudicator": 94, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 50, - "fields": { - "adjudicator": 95, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 51, - "fields": { - "adjudicator": 96, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 52, - "fields": { - "adjudicator": 97, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 53, - "fields": { - "adjudicator": 98, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 54, - "fields": { - "adjudicator": 99, - "round": 3 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 55, - "fields": { - "adjudicator": 73, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 56, - "fields": { - "adjudicator": 74, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 57, - "fields": { - "adjudicator": 75, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 58, - "fields": { - "adjudicator": 76, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 59, - "fields": { - "adjudicator": 77, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 60, - "fields": { - "adjudicator": 78, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 61, - "fields": { - "adjudicator": 79, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 62, - "fields": { - "adjudicator": 80, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 63, - "fields": { - "adjudicator": 81, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 64, - "fields": { - "adjudicator": 82, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 65, - "fields": { - "adjudicator": 83, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 66, - "fields": { - "adjudicator": 84, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 67, - "fields": { - "adjudicator": 85, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 68, - "fields": { - "adjudicator": 86, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 69, - "fields": { - "adjudicator": 87, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 70, - "fields": { - "adjudicator": 88, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 71, - "fields": { - "adjudicator": 89, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 72, - "fields": { - "adjudicator": 90, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 73, - "fields": { - "adjudicator": 91, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 74, - "fields": { - "adjudicator": 92, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 75, - "fields": { - "adjudicator": 93, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 76, - "fields": { - "adjudicator": 94, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 77, - "fields": { - "adjudicator": 95, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 78, - "fields": { - "adjudicator": 96, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 79, - "fields": { - "adjudicator": 97, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 80, - "fields": { - "adjudicator": 98, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 81, - "fields": { - "adjudicator": 99, - "round": 2 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 136, - "fields": { - "adjudicator": 98, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 137, - "fields": { - "adjudicator": 74, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 138, - "fields": { - "adjudicator": 78, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 139, - "fields": { - "adjudicator": 87, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 140, - "fields": { - "adjudicator": 88, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 141, - "fields": { - "adjudicator": 89, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 142, - "fields": { - "adjudicator": 90, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 145, - "fields": { - "adjudicator": 95, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 146, - "fields": { - "adjudicator": 92, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 147, - "fields": { - "adjudicator": 94, - "round": 5 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 148, - "fields": { - "adjudicator": 98, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 149, - "fields": { - "adjudicator": 74, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 150, - "fields": { - "adjudicator": 78, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 151, - "fields": { - "adjudicator": 87, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 152, - "fields": { - "adjudicator": 88, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 153, - "fields": { - "adjudicator": 89, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 154, - "fields": { - "adjudicator": 90, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 155, - "fields": { - "adjudicator": 92, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 156, - "fields": { - "adjudicator": 94, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 157, - "fields": { - "adjudicator": 95, - "round": 6 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 158, - "fields": { - "adjudicator": 98, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 159, - "fields": { - "adjudicator": 74, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 160, - "fields": { - "adjudicator": 78, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 161, - "fields": { - "adjudicator": 87, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 162, - "fields": { - "adjudicator": 88, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 163, - "fields": { - "adjudicator": 89, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 164, - "fields": { - "adjudicator": 90, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 165, - "fields": { - "adjudicator": 92, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 166, - "fields": { - "adjudicator": 94, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 167, - "fields": { - "adjudicator": 95, - "round": 7 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 174, - "fields": { - "adjudicator": 73, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 175, - "fields": { - "adjudicator": 74, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 176, - "fields": { - "adjudicator": 75, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 177, - "fields": { - "adjudicator": 76, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 178, - "fields": { - "adjudicator": 77, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 179, - "fields": { - "adjudicator": 78, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 180, - "fields": { - "adjudicator": 79, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 181, - "fields": { - "adjudicator": 80, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 182, - "fields": { - "adjudicator": 81, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 183, - "fields": { - "adjudicator": 82, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 184, - "fields": { - "adjudicator": 83, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 185, - "fields": { - "adjudicator": 84, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 186, - "fields": { - "adjudicator": 85, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 187, - "fields": { - "adjudicator": 86, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 188, - "fields": { - "adjudicator": 87, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 189, - "fields": { - "adjudicator": 88, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 190, - "fields": { - "adjudicator": 89, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 191, - "fields": { - "adjudicator": 90, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 192, - "fields": { - "adjudicator": 91, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 193, - "fields": { - "adjudicator": 92, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 194, - "fields": { - "adjudicator": 93, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 195, - "fields": { - "adjudicator": 94, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 196, - "fields": { - "adjudicator": 95, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 197, - "fields": { - "adjudicator": 96, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 198, - "fields": { - "adjudicator": 97, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 199, - "fields": { - "adjudicator": 98, - "round": 1 - } - }, - { - "model": "availability.activeadjudicator", - "pk": 200, - "fields": { - "adjudicator": 99, - "round": 1 - } - }, - { - "model": "breakqual.breakcategory", - "pk": 1, - "fields": { - "tournament": 1, - "name": "Open", - "slug": "open", - "seq": 10, - "break_size": 8, - "is_general": true, - "institution_cap": 2, - "priority": 10 - } - }, - { - "model": "breakqual.breakcategory", - "pk": 2, - "fields": { - "tournament": 1, - "name": "ESL", - "slug": "esl", - "seq": 20, - "break_size": 4, - "is_general": false, - "institution_cap": 2, - "priority": 20 - } - }, - { - "model": "breakqual.breakcategory", - "pk": 3, - "fields": { - "tournament": 1, - "name": "EFL", - "slug": "efl", - "seq": 30, - "break_size": 2, - "is_general": false, - "institution_cap": 1, - "priority": 30 - } - }, - { - "model": "breakqual.breakingteam", - "pk": 44, - "fields": { - "break_category": 1, - "team": 7, - "rank": 1, - "break_rank": 1, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 45, - "fields": { - "break_category": 1, - "team": 18, - "rank": 2, - "break_rank": 2, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 46, - "fields": { - "break_category": 1, - "team": 17, - "rank": 3, - "break_rank": 3, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 47, - "fields": { - "break_category": 1, - "team": 1, - "rank": 4, - "break_rank": 4, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 48, - "fields": { - "break_category": 1, - "team": 12, - "rank": 5, - "break_rank": 5, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 49, - "fields": { - "break_category": 1, - "team": 20, - "rank": 6, - "break_rank": 6, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 50, - "fields": { - "break_category": 1, - "team": 11, - "rank": 7, - "break_rank": 7, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 51, - "fields": { - "break_category": 1, - "team": 4, - "rank": 8, - "break_rank": 8, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 52, - "fields": { - "break_category": 2, - "team": 18, - "rank": 1, - "break_rank": null, - "remark": "D" - } - }, - { - "model": "breakqual.breakingteam", - "pk": 53, - "fields": { - "break_category": 2, - "team": 17, - "rank": 2, - "break_rank": null, - "remark": "D" - } - }, - { - "model": "breakqual.breakingteam", - "pk": 54, - "fields": { - "break_category": 2, - "team": 4, - "rank": 3, - "break_rank": null, - "remark": "D" - } - }, - { - "model": "breakqual.breakingteam", - "pk": 55, - "fields": { - "break_category": 2, - "team": 10, - "rank": 4, - "break_rank": 1, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 56, - "fields": { - "break_category": 2, - "team": 6, - "rank": 5, - "break_rank": 2, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 57, - "fields": { - "break_category": 2, - "team": 5, - "rank": 6, - "break_rank": 3, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 58, - "fields": { - "break_category": 2, - "team": 9, - "rank": 7, - "break_rank": 4, - "remark": null - } - }, - { - "model": "breakqual.breakingteam", - "pk": 59, - "fields": { - "break_category": 3, - "team": 4, - "rank": 1, - "break_rank": null, - "remark": "D" - } - }, - { - "model": "breakqual.breakingteam", - "pk": 60, - "fields": { - "break_category": 3, - "team": 6, - "rank": 2, - "break_rank": null, - "remark": "D" - } - }, - { - "model": "breakqual.breakingteam", - "pk": 61, - "fields": { - "break_category": 3, - "team": 5, - "rank": 3, - "break_rank": null, - "remark": "D" - } - }, - { - "model": "breakqual.breakingteam", - "pk": 62, - "fields": { - "break_category": 3, - "team": 19, - "rank": 4, - "break_rank": 1, - "remark": null - } - }, - { - "model": "draw.debate", - "pk": 1, - "fields": { - "round": 1, - "venue": 21, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 2, - "fields": { - "round": 1, - "venue": 23, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 3, - "fields": { - "round": 1, - "venue": 14, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 4, - "fields": { - "round": 1, - "venue": 18, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 5, - "fields": { - "round": 1, - "venue": 1, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 6, - "fields": { - "round": 1, - "venue": 19, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 7, - "fields": { - "round": 1, - "venue": 22, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 8, - "fields": { - "round": 1, - "venue": 17, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 9, - "fields": { - "round": 1, - "venue": 16, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 10, - "fields": { - "round": 1, - "venue": 20, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 11, - "fields": { - "round": 1, - "venue": 13, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 12, - "fields": { - "round": 1, - "venue": 15, - "division": null, - "bracket": 0.0, - "room_rank": 0, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 13, - "fields": { - "round": 2, - "venue": 17, - "division": null, - "bracket": 1.0, - "room_rank": 3, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 14, - "fields": { - "round": 2, - "venue": 20, - "division": null, - "bracket": 0.0, - "room_rank": 12, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 15, - "fields": { - "round": 2, - "venue": 1, - "division": null, - "bracket": 1.0, - "room_rank": 6, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 16, - "fields": { - "round": 2, - "venue": 22, - "division": null, - "bracket": 0.0, - "room_rank": 7, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 17, - "fields": { - "round": 2, - "venue": 23, - "division": null, - "bracket": 1.0, - "room_rank": 4, - "time": null, - "flags": "1u1d_inst", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 18, - "fields": { - "round": 2, - "venue": 15, - "division": null, - "bracket": 1.0, - "room_rank": 5, - "time": null, - "flags": "1u1d_other", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 19, - "fields": { - "round": 2, - "venue": 14, - "division": null, - "bracket": 1.0, - "room_rank": 1, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 20, - "fields": { - "round": 2, - "venue": 19, - "division": null, - "bracket": 0.0, - "room_rank": 8, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 21, - "fields": { - "round": 2, - "venue": 13, - "division": null, - "bracket": 0.0, - "room_rank": 11, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 22, - "fields": { - "round": 2, - "venue": 18, - "division": null, - "bracket": 0.0, - "room_rank": 10, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 23, - "fields": { - "round": 2, - "venue": 16, - "division": null, - "bracket": 1.0, - "room_rank": 2, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 24, - "fields": { - "round": 2, - "venue": 21, - "division": null, - "bracket": 0.0, - "room_rank": 9, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 25, - "fields": { - "round": 3, - "venue": 20, - "division": null, - "bracket": 1.0, - "room_rank": 4, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 26, - "fields": { - "round": 3, - "venue": 14, - "division": null, - "bracket": 2.0, - "room_rank": 3, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 27, - "fields": { - "round": 3, - "venue": 16, - "division": null, - "bracket": 1.0, - "room_rank": 8, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 28, - "fields": { - "round": 3, - "venue": 18, - "division": null, - "bracket": 1.0, - "room_rank": 9, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 29, - "fields": { - "round": 3, - "venue": 21, - "division": null, - "bracket": 0.0, - "room_rank": 12, - "time": null, - "flags": "1u1d_other", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 30, - "fields": { - "round": 3, - "venue": 17, - "division": null, - "bracket": 1.0, - "room_rank": 6, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 31, - "fields": { - "round": 3, - "venue": 23, - "division": null, - "bracket": 2.0, - "room_rank": 1, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 32, - "fields": { - "round": 3, - "venue": 1, - "division": null, - "bracket": 1.0, - "room_rank": 5, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 33, - "fields": { - "round": 3, - "venue": 19, - "division": null, - "bracket": 2.0, - "room_rank": 2, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 34, - "fields": { - "round": 3, - "venue": 22, - "division": null, - "bracket": 0.0, - "room_rank": 11, - "time": null, - "flags": "1u1d_inst", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 35, - "fields": { - "round": 3, - "venue": 13, - "division": null, - "bracket": 0.0, - "room_rank": 10, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 36, - "fields": { - "round": 3, - "venue": 15, - "division": null, - "bracket": 1.0, - "room_rank": 7, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 37, - "fields": { - "round": 4, - "venue": 23, - "division": null, - "bracket": 1.0, - "room_rank": 7, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 38, - "fields": { - "round": 4, - "venue": 16, - "division": null, - "bracket": 3.0, - "room_rank": 1, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 39, - "fields": { - "round": 4, - "venue": 18, - "division": null, - "bracket": 1.0, - "room_rank": 9, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 40, - "fields": { - "round": 4, - "venue": 15, - "division": null, - "bracket": 1.0, - "room_rank": 8, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 41, - "fields": { - "round": 4, - "venue": 21, - "division": null, - "bracket": 1.0, - "room_rank": 10, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 42, - "fields": { - "round": 4, - "venue": 13, - "division": null, - "bracket": 0.0, - "room_rank": 12, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 43, - "fields": { - "round": 4, - "venue": 17, - "division": null, - "bracket": 0.5, - "room_rank": 11, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 44, - "fields": { - "round": 4, - "venue": 1, - "division": null, - "bracket": 2.0, - "room_rank": 5, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 45, - "fields": { - "round": 4, - "venue": 19, - "division": null, - "bracket": 2.0, - "room_rank": 6, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 46, - "fields": { - "round": 4, - "venue": 22, - "division": null, - "bracket": 2.5, - "room_rank": 2, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 47, - "fields": { - "round": 4, - "venue": 14, - "division": null, - "bracket": 2.0, - "room_rank": 4, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 48, - "fields": { - "round": 4, - "venue": 20, - "division": null, - "bracket": 2.0, - "room_rank": 3, - "time": null, - "flags": "", - "importance": 2, - "result_status": "C", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 61, - "fields": { - "round": 6, - "venue": 23, - "division": null, - "bracket": 0.0, - "room_rank": 1, - "time": null, - "flags": "", - "importance": 2, - "result_status": "N", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 62, - "fields": { - "round": 6, - "venue": 22, - "division": null, - "bracket": 0.0, - "room_rank": 2, - "time": null, - "flags": "", - "importance": 2, - "result_status": "N", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 67, - "fields": { - "round": 7, - "venue": 9, - "division": null, - "bracket": 0.0, - "room_rank": 2, - "time": null, - "flags": "", - "importance": 2, - "result_status": "N", - "ballot_in": false - } - }, - { - "model": "draw.debate", - "pk": 68, - "fields": { - "round": 7, - "venue": 16, - "division": null, - "bracket": 0.0, - "room_rank": 1, - "time": null, - "flags": "", - "importance": 2, - "result_status": "N", - "ballot_in": false - } - }, - { - "model": "draw.debateteam", - "pk": 1, - "fields": { - "debate": 1, - "team": 3, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 2, - "fields": { - "debate": 1, - "team": 21, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 3, - "fields": { - "debate": 2, - "team": 20, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 4, - "fields": { - "debate": 2, - "team": 9, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 5, - "fields": { - "debate": 3, - "team": 2, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 6, - "fields": { - "debate": 3, - "team": 13, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 7, - "fields": { - "debate": 4, - "team": 7, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 8, - "fields": { - "debate": 4, - "team": 24, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 9, - "fields": { - "debate": 5, - "team": 6, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 10, - "fields": { - "debate": 5, - "team": 22, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 11, - "fields": { - "debate": 6, - "team": 5, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 12, - "fields": { - "debate": 6, - "team": 10, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 13, - "fields": { - "debate": 7, - "team": 12, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 14, - "fields": { - "debate": 7, - "team": 16, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 15, - "fields": { - "debate": 8, - "team": 19, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 16, - "fields": { - "debate": 8, - "team": 15, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 17, - "fields": { - "debate": 9, - "team": 17, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 18, - "fields": { - "debate": 9, - "team": 1, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 19, - "fields": { - "debate": 10, - "team": 23, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 20, - "fields": { - "debate": 10, - "team": 11, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 21, - "fields": { - "debate": 11, - "team": 4, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 22, - "fields": { - "debate": 11, - "team": 8, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 23, - "fields": { - "debate": 12, - "team": 14, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 24, - "fields": { - "debate": 12, - "team": 18, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 25, - "fields": { - "debate": 13, - "team": 16, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 26, - "fields": { - "debate": 13, - "team": 2, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 27, - "fields": { - "debate": 14, - "team": 13, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 28, - "fields": { - "debate": 14, - "team": 12, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 29, - "fields": { - "debate": 15, - "team": 15, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 30, - "fields": { - "debate": 15, - "team": 7, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 31, - "fields": { - "debate": 16, - "team": 22, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 32, - "fields": { - "debate": 16, - "team": 4, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 33, - "fields": { - "debate": 17, - "team": 18, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 34, - "fields": { - "debate": 17, - "team": 3, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 35, - "fields": { - "debate": 18, - "team": 1, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 36, - "fields": { - "debate": 18, - "team": 6, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 37, - "fields": { - "debate": 19, - "team": 11, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 38, - "fields": { - "debate": 19, - "team": 5, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 39, - "fields": { - "debate": 20, - "team": 24, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 40, - "fields": { - "debate": 20, - "team": 21, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 41, - "fields": { - "debate": 21, - "team": 17, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 42, - "fields": { - "debate": 21, - "team": 23, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 43, - "fields": { - "debate": 22, - "team": 14, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 44, - "fields": { - "debate": 22, - "team": 20, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 45, - "fields": { - "debate": 23, - "team": 9, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 46, - "fields": { - "debate": 23, - "team": 8, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 47, - "fields": { - "debate": 24, - "team": 10, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 48, - "fields": { - "debate": 24, - "team": 19, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 49, - "fields": { - "debate": 25, - "team": 3, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 50, - "fields": { - "debate": 25, - "team": 4, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 51, - "fields": { - "debate": 26, - "team": 1, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 52, - "fields": { - "debate": 26, - "team": 18, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 53, - "fields": { - "debate": 27, - "team": 15, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 54, - "fields": { - "debate": 27, - "team": 6, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 55, - "fields": { - "debate": 28, - "team": 21, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 56, - "fields": { - "debate": 28, - "team": 12, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 57, - "fields": { - "debate": 29, - "team": 24, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 58, - "fields": { - "debate": 29, - "team": 19, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 59, - "fields": { - "debate": 30, - "team": 10, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 60, - "fields": { - "debate": 30, - "team": 2, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 61, - "fields": { - "debate": 31, - "team": 9, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 62, - "fields": { - "debate": 31, - "team": 7, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 63, - "fields": { - "debate": 32, - "team": 20, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 64, - "fields": { - "debate": 32, - "team": 5, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 65, - "fields": { - "debate": 33, - "team": 16, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 66, - "fields": { - "debate": 33, - "team": 11, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 67, - "fields": { - "debate": 34, - "team": 23, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 68, - "fields": { - "debate": 34, - "team": 14, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 69, - "fields": { - "debate": 35, - "team": 22, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 70, - "fields": { - "debate": 35, - "team": 13, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 71, - "fields": { - "debate": 36, - "team": 8, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 72, - "fields": { - "debate": 36, - "team": 17, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 73, - "fields": { - "debate": 37, - "team": 19, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 74, - "fields": { - "debate": 37, - "team": 22, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 75, - "fields": { - "debate": 38, - "team": 11, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 76, - "fields": { - "debate": 38, - "team": 7, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 77, - "fields": { - "debate": 39, - "team": 8, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 78, - "fields": { - "debate": 39, - "team": 5, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 79, - "fields": { - "debate": 40, - "team": 3, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 80, - "fields": { - "debate": 40, - "team": 23, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 81, - "fields": { - "debate": 41, - "team": 21, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 82, - "fields": { - "debate": 41, - "team": 15, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 83, - "fields": { - "debate": 42, - "team": 13, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 84, - "fields": { - "debate": 42, - "team": 14, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 85, - "fields": { - "debate": 43, - "team": 2, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 86, - "fields": { - "debate": 43, - "team": 24, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 87, - "fields": { - "debate": 44, - "team": 12, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 88, - "fields": { - "debate": 44, - "team": 9, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 89, - "fields": { - "debate": 45, - "team": 16, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 90, - "fields": { - "debate": 45, - "team": 1, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 91, - "fields": { - "debate": 46, - "team": 4, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 92, - "fields": { - "debate": 46, - "team": 18, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 93, - "fields": { - "debate": 47, - "team": 6, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 94, - "fields": { - "debate": 47, - "team": 20, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 95, - "fields": { - "debate": 48, - "team": 17, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 96, - "fields": { - "debate": 48, - "team": 10, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 121, - "fields": { - "debate": 61, - "team": 10, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 122, - "fields": { - "debate": 61, - "team": 9, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 123, - "fields": { - "debate": 62, - "team": 6, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 124, - "fields": { - "debate": 62, - "team": 5, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 133, - "fields": { - "debate": 67, - "team": 12, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 134, - "fields": { - "debate": 67, - "team": 20, - "position": "N" - } - }, - { - "model": "draw.debateteam", - "pk": 135, - "fields": { - "debate": 68, - "team": 18, - "position": "A" - } - }, - { - "model": "draw.debateteam", - "pk": 136, - "fields": { - "debate": 68, - "team": 4, - "position": "N" - } - }, - { - "model": "motions.motion", - "pk": 1, - "fields": { - "seq": 1, - "text": "This House would abolish national days", - "reference": "National days", - "flagged": false, - "round": 1, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 2, - "fields": { - "seq": 2, - "text": "This House regrets the existence of Valentine's Day", - "reference": "Valentine’s Day", - "flagged": false, - "round": 1, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 3, - "fields": { - "seq": 3, - "text": "This House would rename Christmas with a name that is religiously neutral", - "reference": "Christmas", - "flagged": false, - "round": 1, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 4, - "fields": { - "seq": 1, - "text": "This House would not buy Apple", - "reference": "Apple", - "flagged": false, - "round": 2, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 5, - "fields": { - "seq": 2, - "text": "This House would end all research and development tax credits for highly profitable technology companies", - "reference": "R&D tax credit", - "flagged": false, - "round": 2, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 6, - "fields": { - "seq": 3, - "text": "This House regrets the rise of computer science at the expense of the humanities", - "reference": "Computer science", - "flagged": false, - "round": 2, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 7, - "fields": { - "seq": 1, - "text": "This House would favour creativity over intelligence", - "reference": "Creativity and intelligence", - "flagged": false, - "round": 3, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 8, - "fields": { - "seq": 2, - "text": "This House believes that field hockey is better than ice hockey", - "reference": "Hockey", - "flagged": false, - "round": 3, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 9, - "fields": { - "seq": 3, - "text": "This House would rather play with Lego than Barbie", - "reference": "Lego and Barbie", - "flagged": false, - "round": 3, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 10, - "fields": { - "seq": 1, - "text": "This House would stop importing bananas from Latin America", - "reference": "Bananas", - "flagged": false, - "round": 4, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 11, - "fields": { - "seq": 2, - "text": "This House believes that tomatoes are a fruit", - "reference": "Tomatoes", - "flagged": false, - "round": 4, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 12, - "fields": { - "seq": 3, - "text": "This House would require all fruit to carry labels noting what pesticides are used on them", - "reference": "Pesticide labelling", - "flagged": false, - "round": 4, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 13, - "fields": { - "seq": 1, - "text": "This House would make an exception to laws forbidding indecent exposure for days with hot temperatures", - "reference": "Indecent exposure", - "flagged": false, - "round": 7, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 14, - "fields": { - "seq": 2, - "text": "This House regrets the development of different fashion lines for men and women", - "reference": "Gender and fashion", - "flagged": false, - "round": 7, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 15, - "fields": { - "seq": 3, - "text": "This House believes that it is unprofessional to wear flip-flops (jandals, thongs) to work", - "reference": "Flip-flops", - "flagged": false, - "round": 7, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 16, - "fields": { - "seq": 1, - "text": "This House would stop using cash", - "reference": "Cash", - "flagged": false, - "round": 10, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 17, - "fields": { - "seq": 2, - "text": "This House supports Bitcoin", - "reference": "Bitcoin", - "flagged": false, - "round": 10, - "divisions": [] - } - }, - { - "model": "motions.motion", - "pk": 18, - "fields": { - "seq": 3, - "text": "This House would allow private organisations to compete in providing currency", - "reference": "Private currency", - "flagged": false, - "round": 10, - "divisions": [] - } - }, - { - "model": "participants.region", - "pk": 1, - "fields": { - "name": "NY", - "tournament": 1 - } - }, - { - "model": "participants.region", - "pk": 2, - "fields": { - "name": "MA", - "tournament": 1 - } - }, - { - "model": "participants.region", - "pk": 3, - "fields": { - "name": "MD", - "tournament": 1 - } - }, - { - "model": "participants.region", - "pk": 4, - "fields": { - "name": "CT", - "tournament": 1 - } - }, - { - "model": "participants.region", - "pk": 5, - "fields": { - "name": "PA", - "tournament": 1 - } - }, - { - "model": "participants.region", - "pk": 6, - "fields": { - "name": "CA", - "tournament": 1 - } - }, - { - "model": "participants.region", - "pk": 7, - "fields": { - "name": "Other", - "tournament": 1 - } - }, - { - "model": "participants.institution", - "pk": 1, - "fields": { - "name": "California Institute of Technology", - "code": "Caltech", - "abbreviation": "Calt", - "region": 6 - } - }, - { - "model": "participants.institution", - "pk": 2, - "fields": { - "name": "Columbia University", - "code": "Columbia", - "abbreviation": "Colum", - "region": 1 - } - }, - { - "model": "participants.institution", - "pk": 3, - "fields": { - "name": "Cornell University", - "code": "Cornell", - "abbreviation": "Corn", - "region": 1 - } - }, - { - "model": "participants.institution", - "pk": 4, - "fields": { - "name": "Harvard University", - "code": "Harvard", - "abbreviation": "Harv", - "region": 2 - } - }, - { - "model": "participants.institution", - "pk": 5, - "fields": { - "name": "Johns Hopkins University", - "code": "Johns Hopkins", - "abbreviation": "JHU", - "region": 3 - } - }, - { - "model": "participants.institution", - "pk": 6, - "fields": { - "name": "Massachusetts Institute of Technology", - "code": "MIT", - "abbreviation": "MIT", - "region": 2 - } - }, - { - "model": "participants.institution", - "pk": 7, - "fields": { - "name": "Princeton University", - "code": "Princeton", - "abbreviation": "Prin", - "region": null - } - }, - { - "model": "participants.institution", - "pk": 8, - "fields": { - "name": "Stanford University", - "code": "Stanford", - "abbreviation": "Stan", - "region": 6 - } - }, - { - "model": "participants.institution", - "pk": 9, - "fields": { - "name": "University of California, Berkeley", - "code": "Berkeley", - "abbreviation": "Cal", - "region": 6 - } - }, - { - "model": "participants.institution", - "pk": 10, - "fields": { - "name": "University of Chicago", - "code": "Chicago", - "abbreviation": "Chic", - "region": null - } - }, - { - "model": "participants.institution", - "pk": 11, - "fields": { - "name": "University of Pennsylvania", - "code": "Pennsylvania", - "abbreviation": "Penn", - "region": 5 - } - }, - { - "model": "participants.institution", - "pk": 12, - "fields": { - "name": "University of Toronto", - "code": "Toronto", - "abbreviation": "Toron", - "region": null - } - }, - { - "model": "participants.institution", - "pk": 13, - "fields": { - "name": "Yale University", - "code": "Yale", - "abbreviation": "Yale", - "region": 4 - } - }, - { - "model": "participants.person", - "pk": 1, - "fields": { - "name": "Georgia Crawford", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 2, - "fields": { - "name": "Wanda Griffin", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 3, - "fields": { - "name": "Helen Keller", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 4, - "fields": { - "name": "Russell Warren", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 5, - "fields": { - "name": "Angel Rhodes", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": "they" - } - }, - { - "model": "participants.person", - "pk": 6, - "fields": { - "name": "Terry Henderson", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 7, - "fields": { - "name": "Kyle Ruiz", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 8, - "fields": { - "name": "Randolph Lambert", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 9, - "fields": { - "name": "Sergio Pittman", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 10, - "fields": { - "name": "Earnest Becker", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 11, - "fields": { - "name": "Ellis Rowe", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 12, - "fields": { - "name": "Robin Roberson", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 13, - "fields": { - "name": "Gwen Newman", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 14, - "fields": { - "name": "Robyn Caldwell", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 15, - "fields": { - "name": "Angie Holt", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 16, - "fields": { - "name": "Melvin Jordan", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 17, - "fields": { - "name": "Gladys Burke", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 18, - "fields": { - "name": "Patty Saunders", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 19, - "fields": { - "name": "Thomas Pierce", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 20, - "fields": { - "name": "Stella Lindsey", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 21, - "fields": { - "name": "Adrian May", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 22, - "fields": { - "name": "Taylor Brown", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 23, - "fields": { - "name": "Bethany Chambers", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 24, - "fields": { - "name": "Pamela Bryan", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 25, - "fields": { - "name": "Janet Nunez", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 26, - "fields": { - "name": "Owen Chandler", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 27, - "fields": { - "name": "Lillie Rodriquez", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 28, - "fields": { - "name": "Rufus Dennis", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 29, - "fields": { - "name": "Marty Love", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 30, - "fields": { - "name": "Shelia Wright", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 31, - "fields": { - "name": "Clark Mills", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 32, - "fields": { - "name": "Randy Carroll", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 33, - "fields": { - "name": "Casey Sparks", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 34, - "fields": { - "name": "Candace Bowen", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 35, - "fields": { - "name": "Jaime Long", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 36, - "fields": { - "name": "Leon Hall", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 37, - "fields": { - "name": "Morris Nichols", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 38, - "fields": { - "name": "Benjamin Padilla", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 39, - "fields": { - "name": "Phil Lyons", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 40, - "fields": { - "name": "Clay Holland", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 41, - "fields": { - "name": "Elena Cobb", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 42, - "fields": { - "name": "Shawn Torres", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 43, - "fields": { - "name": "Willis Carson", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 44, - "fields": { - "name": "Wendell Nelson", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 45, - "fields": { - "name": "Felicia Welch", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 46, - "fields": { - "name": "Cory Meyer", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 47, - "fields": { - "name": "Stacy Frazier", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 48, - "fields": { - "name": "Claire Dunn", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 49, - "fields": { - "name": "Eloise Munoz", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 50, - "fields": { - "name": "Patricia Palmer", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 51, - "fields": { - "name": "Stewart Day", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 52, - "fields": { - "name": "Timmy Craig", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 53, - "fields": { - "name": "Patrick Kelly", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 54, - "fields": { - "name": "Kristopher Hayes", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 55, - "fields": { - "name": "Andy Lane", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 56, - "fields": { - "name": "Scott Mcdonald", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 57, - "fields": { - "name": "Charlene Cortez", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 58, - "fields": { - "name": "Leigh Holmes", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 59, - "fields": { - "name": "Alma Spencer", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 60, - "fields": { - "name": "Winston Castro", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 61, - "fields": { - "name": "Emilio Simmons", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 62, - "fields": { - "name": "Ron Delgado", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 63, - "fields": { - "name": "Nadine Barber", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 64, - "fields": { - "name": "Gail Adkins", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 65, - "fields": { - "name": "Willard Walton", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 66, - "fields": { - "name": "Jackie Peterson", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 67, - "fields": { - "name": "Terry Thornton", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": "they" - } - }, - { - "model": "participants.person", - "pk": 68, - "fields": { - "name": "Norman Rodgers", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 69, - "fields": { - "name": "Mattie Lee", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": "they" - } - }, - { - "model": "participants.person", - "pk": 70, - "fields": { - "name": "Woodrow Harvey", - "barcode_id": null, - "email": null, - "phone": null, - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 71, - "fields": { - "name": "Javier Chavez", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 72, - "fields": { - "name": "Janie Daniels", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 73, - "fields": { - "name": "Levi Flores", - "barcode_id": null, - "email": "leviflores@gmail.com", - "phone": "(400) 258-4262", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 74, - "fields": { - "name": "Boyd Pierce", - "barcode_id": null, - "email": "boydpierce@yahoo.com", - "phone": "(645) 106-7743", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 75, - "fields": { - "name": "Eunice Mcbride", - "barcode_id": null, - "email": "eunicemcbride@outlook.com", - "phone": "(549) 309-9187", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 76, - "fields": { - "name": "Ramona Cobb", - "barcode_id": null, - "email": "ramonacobb@yahoo.com", - "phone": "(440) 487-5776", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 77, - "fields": { - "name": "Justin Ford", - "barcode_id": null, - "email": "justinford@outlook.com", - "phone": "(618) 921-9188", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 78, - "fields": { - "name": "Luis Bennett", - "barcode_id": null, - "email": "luisbennett@gmail.com", - "phone": "(730) 097-8797", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 79, - "fields": { - "name": "Mandy Estrada", - "barcode_id": null, - "email": "mandyestrada@gmail.com", - "phone": "(559) 299-0471", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 80, - "fields": { - "name": "Leigh Mcgee", - "barcode_id": null, - "email": "leighmcgee@gmail.com", - "phone": "(844) 760-9302", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 81, - "fields": { - "name": "Jacqueline Freeman", - "barcode_id": null, - "email": "jacquelinefreeman@yahoo.com", - "phone": "(297) 916-1716", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 82, - "fields": { - "name": "Holly Howard", - "barcode_id": null, - "email": "hollyhoward@gmail.com", - "phone": "(958) 783-2610", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 83, - "fields": { - "name": "Pedro Burgess", - "barcode_id": null, - "email": "pedroburgess@yahoo.com", - "phone": "(854) 441-0104", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 84, - "fields": { - "name": "Kristy Carr", - "barcode_id": null, - "email": "kristycarr@yahoo.com", - "phone": "(644) 607-3297", - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 85, - "fields": { - "name": "Wilma Vaughn", - "barcode_id": null, - "email": "wilmavaughn@outlook.com", - "phone": "(398) 759-9537", - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 86, - "fields": { - "name": "Virginia Mccarthy", - "barcode_id": null, - "email": "virginiamccarthy@gmail.com", - "phone": "(455) 177-0459", - "novice": true, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 87, - "fields": { - "name": "Tasha Jenkins", - "barcode_id": null, - "email": "tashajenkins@outlook.com", - "phone": "(875) 519-9891", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 88, - "fields": { - "name": "Toby Wong", - "barcode_id": null, - "email": "tobywong@gmail.com", - "phone": "(404) 641-5999", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 89, - "fields": { - "name": "Jo Allen", - "barcode_id": null, - "email": "joallen@yahoo.com", - "phone": "(761) 993-2983", - "novice": false, - "checkin_message": "", - "notes": "", - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 90, - "fields": { - "name": "Billy Griffin", - "barcode_id": null, - "email": "billygriffin@outlook.com", - "phone": "(430) 532-2939", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 91, - "fields": { - "name": "Angela Reed", - "barcode_id": null, - "email": "angelareed@yahoo.com", - "phone": "(936) 500-1228", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 92, - "fields": { - "name": "Hugo Lewis", - "barcode_id": null, - "email": "hugolewis@outlook.com", - "phone": "(422) 585-9609", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "they" - } - }, - { - "model": "participants.person", - "pk": 93, - "fields": { - "name": "Cassandra Wilson", - "barcode_id": null, - "email": "cassandrawilson@gmail.com", - "phone": "(604) 306-2084", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 94, - "fields": { - "name": "George Willis", - "barcode_id": null, - "email": "georgewillis@yahoo.com", - "phone": "(222) 204-5944", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "M", - "pronoun": "he" - } - }, - { - "model": "participants.person", - "pk": 95, - "fields": { - "name": "Jamie Hodges", - "barcode_id": null, - "email": "jamiehodges@outlook.com", - "phone": "(737) 122-6102", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 96, - "fields": { - "name": "Bennie Rodriguez", - "barcode_id": null, - "email": "bennierodriguez@gmail.com", - "phone": "(537) 641-2175", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 97, - "fields": { - "name": "Allison Martin", - "barcode_id": null, - "email": "allisonmartin@outlook.com", - "phone": "(525) 384-2715", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 98, - "fields": { - "name": "Kristi Elliott", - "barcode_id": null, - "email": "kristielliott@gmail.com", - "phone": "(790) 289-5430", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 99, - "fields": { - "name": "Pearl Graves", - "barcode_id": null, - "email": "pearlgraves@outlook.com", - "phone": "(317) 721-2439", - "novice": false, - "checkin_message": "", - "notes": null, - "gender": "F", - "pronoun": "she" - } - }, - { - "model": "participants.person", - "pk": 159, - "fields": { - "name": "New Adjudicator Shared", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": null - } - }, - { - "model": "participants.person", - "pk": 160, - "fields": { - "name": "New Adjudicator Shared", - "barcode_id": null, - "email": null, - "phone": null, - "novice": false, - "checkin_message": "", - "notes": null, - "gender": null, - "pronoun": null - } - }, - { - "model": "participants.team", - "pk": 1, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🌩", - "institution": 1, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 2, - "fields": { - "reference": "2", - "short_reference": "2", - "emoji": "🎃", - "institution": 1, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 3, - "fields": { - "reference": "3", - "short_reference": "3", - "emoji": "🆒", - "institution": 1, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 4, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🍌", - "institution": 2, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1, - 2, - 3 - ] - } - }, - { - "model": "participants.team", - "pk": 5, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🆘", - "institution": 3, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1, - 2, - 3 - ] - } - }, - { - "model": "participants.team", - "pk": 6, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "💎", - "institution": 4, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1, - 2, - 3 - ] - } - }, - { - "model": "participants.team", - "pk": 7, - "fields": { - "reference": "2", - "short_reference": "2", - "emoji": "🕯", - "institution": 4, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 8, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🎖", - "institution": 5, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 9, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🖨", - "institution": 6, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1, - 2 - ] - } - }, - { - "model": "participants.team", - "pk": 10, - "fields": { - "reference": "2", - "short_reference": "2", - "emoji": "😴", - "institution": 6, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1, - 2 - ] - } - }, - { - "model": "participants.team", - "pk": 11, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🌶", - "institution": 7, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 12, - "fields": { - "reference": "2", - "short_reference": "2", - "emoji": "🙌", - "institution": 7, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 13, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🖖", - "institution": 8, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 14, - "fields": { - "reference": "2", - "short_reference": "2", - "emoji": "🖕", - "institution": 8, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 15, - "fields": { - "reference": "3", - "short_reference": "3", - "emoji": "⛏", - "institution": 8, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 16, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🐦", - "institution": 9, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 17, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "😮", - "institution": 10, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1, - 2 - ] - } - }, - { - "model": "participants.team", - "pk": 18, - "fields": { - "reference": "2", - "short_reference": "2", - "emoji": "🌷", - "institution": 10, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1, - 2 - ] - } - }, - { - "model": "participants.team", - "pk": 19, - "fields": { - "reference": "3", - "short_reference": "3", - "emoji": "🕵", - "institution": 10, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1, - 2, - 3 - ] - } - }, - { - "model": "participants.team", - "pk": 20, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "🚬", - "institution": 11, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 21, - "fields": { - "reference": "2", - "short_reference": "2", - "emoji": "👠", - "institution": 11, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 22, - "fields": { - "reference": "1", - "short_reference": "1", - "emoji": "👓", - "institution": 13, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 23, - "fields": { - "reference": "2", - "short_reference": "2", - "emoji": "👊", - "institution": 13, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.team", - "pk": 24, - "fields": { - "reference": "3", - "short_reference": "3", - "emoji": "🍓", - "institution": 13, - "tournament": 1, - "division": null, - "use_institution_prefix": true, - "url_key": null, - "type": "N", - "break_categories": [ - 1 - ] - } - }, - { - "model": "participants.speaker", - "pk": 21, - "fields": { - "team": 7 - } - }, - { - "model": "participants.speaker", - "pk": 59, - "fields": { - "team": 20 - } - }, - { - "model": "participants.speaker", - "pk": 55, - "fields": { - "team": 19 - } - }, - { - "model": "participants.speaker", - "pk": 5, - "fields": { - "team": 2 - } - }, - { - "model": "participants.speaker", - "pk": 15, - "fields": { - "team": 5 - } - }, - { - "model": "participants.speaker", - "pk": 38, - "fields": { - "team": 13 - } - }, - { - "model": "participants.speaker", - "pk": 23, - "fields": { - "team": 8 - } - }, - { - "model": "participants.speaker", - "pk": 34, - "fields": { - "team": 12 - } - }, - { - "model": "participants.speaker", - "pk": 33, - "fields": { - "team": 11 - } - }, - { - "model": "participants.speaker", - "pk": 57, - "fields": { - "team": 19 - } - }, - { - "model": "participants.speaker", - "pk": 48, - "fields": { - "team": 16 - } - }, - { - "model": "participants.speaker", - "pk": 31, - "fields": { - "team": 11 - } - }, - { - "model": "participants.speaker", - "pk": 40, - "fields": { - "team": 14 - } - }, - { - "model": "participants.speaker", - "pk": 46, - "fields": { - "team": 16 - } - }, - { - "model": "participants.speaker", - "pk": 10, - "fields": { - "team": 4 - } - }, - { - "model": "participants.speaker", - "pk": 41, - "fields": { - "team": 14 - } - }, - { - "model": "participants.speaker", - "pk": 11, - "fields": { - "team": 4 - } - }, - { - "model": "participants.speaker", - "pk": 49, - "fields": { - "team": 17 - } - }, - { - "model": "participants.speaker", - "pk": 61, - "fields": { - "team": 21 - } - }, - { - "model": "participants.speaker", - "pk": 45, - "fields": { - "team": 15 - } - }, - { - "model": "participants.speaker", - "pk": 64, - "fields": { - "team": 22 - } - }, - { - "model": "participants.speaker", - "pk": 1, - "fields": { - "team": 1 - } - }, - { - "model": "participants.speaker", - "pk": 17, - "fields": { - "team": 6 - } - }, - { - "model": "participants.speaker", - "pk": 13, - "fields": { - "team": 5 - } - }, - { - "model": "participants.speaker", - "pk": 3, - "fields": { - "team": 1 - } - }, - { - "model": "participants.speaker", - "pk": 66, - "fields": { - "team": 22 - } - }, - { - "model": "participants.speaker", - "pk": 35, - "fields": { - "team": 12 - } - }, - { - "model": "participants.speaker", - "pk": 25, - "fields": { - "team": 9 - } - }, - { - "model": "participants.speaker", - "pk": 72, - "fields": { - "team": 24 - } - }, - { - "model": "participants.speaker", - "pk": 71, - "fields": { - "team": 24 - } - }, - { - "model": "participants.speaker", - "pk": 54, - "fields": { - "team": 18 - } - }, - { - "model": "participants.speaker", - "pk": 7, - "fields": { - "team": 3 - } - }, - { - "model": "participants.speaker", - "pk": 58, - "fields": { - "team": 20 - } - }, - { - "model": "participants.speaker", - "pk": 36, - "fields": { - "team": 12 - } - }, - { - "model": "participants.speaker", - "pk": 27, - "fields": { - "team": 9 - } - }, - { - "model": "participants.speaker", - "pk": 29, - "fields": { - "team": 10 - } - }, - { - "model": "participants.speaker", - "pk": 69, - "fields": { - "team": 23 - } - }, - { - "model": "participants.speaker", - "pk": 16, - "fields": { - "team": 6 - } - }, - { - "model": "participants.speaker", - "pk": 37, - "fields": { - "team": 13 - } - }, - { - "model": "participants.speaker", - "pk": 63, - "fields": { - "team": 21 - } - }, - { - "model": "participants.speaker", - "pk": 68, - "fields": { - "team": 23 - } - }, - { - "model": "participants.speaker", - "pk": 26, - "fields": { - "team": 9 - } - }, - { - "model": "participants.speaker", - "pk": 24, - "fields": { - "team": 8 - } - }, - { - "model": "participants.speaker", - "pk": 50, - "fields": { - "team": 17 - } - }, - { - "model": "participants.speaker", - "pk": 53, - "fields": { - "team": 18 - } - }, - { - "model": "participants.speaker", - "pk": 18, - "fields": { - "team": 6 - } - }, - { - "model": "participants.speaker", - "pk": 39, - "fields": { - "team": 13 - } - }, - { - "model": "participants.speaker", - "pk": 8, - "fields": { - "team": 3 - } - }, - { - "model": "participants.speaker", - "pk": 32, - "fields": { - "team": 11 - } - }, - { - "model": "participants.speaker", - "pk": 12, - "fields": { - "team": 4 - } - }, - { - "model": "participants.speaker", - "pk": 14, - "fields": { - "team": 5 - } - }, - { - "model": "participants.speaker", - "pk": 62, - "fields": { - "team": 21 - } - }, - { - "model": "participants.speaker", - "pk": 28, - "fields": { - "team": 10 - } - }, - { - "model": "participants.speaker", - "pk": 4, - "fields": { - "team": 2 - } - }, - { - "model": "participants.speaker", - "pk": 56, - "fields": { - "team": 19 - } - }, - { - "model": "participants.speaker", - "pk": 9, - "fields": { - "team": 3 - } - }, - { - "model": "participants.speaker", - "pk": 42, - "fields": { - "team": 14 - } - }, - { - "model": "participants.speaker", - "pk": 30, - "fields": { - "team": 10 - } - }, - { - "model": "participants.speaker", - "pk": 47, - "fields": { - "team": 16 - } - }, - { - "model": "participants.speaker", - "pk": 20, - "fields": { - "team": 7 - } - }, - { - "model": "participants.speaker", - "pk": 51, - "fields": { - "team": 17 - } - }, - { - "model": "participants.speaker", - "pk": 22, - "fields": { - "team": 8 - } - }, - { - "model": "participants.speaker", - "pk": 6, - "fields": { - "team": 2 - } - }, - { - "model": "participants.speaker", - "pk": 67, - "fields": { - "team": 23 - } - }, - { - "model": "participants.speaker", - "pk": 19, - "fields": { - "team": 7 - } - }, - { - "model": "participants.speaker", - "pk": 52, - "fields": { - "team": 18 - } - }, - { - "model": "participants.speaker", - "pk": 2, - "fields": { - "team": 1 - } - }, - { - "model": "participants.speaker", - "pk": 44, - "fields": { - "team": 15 - } - }, - { - "model": "participants.speaker", - "pk": 65, - "fields": { - "team": 22 - } - }, - { - "model": "participants.speaker", - "pk": 43, - "fields": { - "team": 15 - } - }, - { - "model": "participants.speaker", - "pk": 60, - "fields": { - "team": 20 - } - }, - { - "model": "participants.speaker", - "pk": 70, - "fields": { - "team": 24 - } - }, - { - "model": "participants.adjudicator", - "pk": 97, - "fields": { - "institution": 13, - "tournament": 1, - "test_score": 4.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 91, - "fields": { - "institution": 8, - "tournament": 1, - "test_score": 1.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 96, - "fields": { - "institution": 11, - "tournament": 1, - "test_score": 2.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 90, - "fields": { - "institution": 7, - "tournament": 1, - "test_score": 2.0, - "url_key": null, - "breaking": true, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 74, - "fields": { - "institution": 8, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": true, - "independent": true, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 93, - "fields": { - "institution": 9, - "tournament": 1, - "test_score": 4.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 75, - "fields": { - "institution": 12, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 94, - "fields": { - "institution": 10, - "tournament": 1, - "test_score": 2.0, - "url_key": null, - "breaking": true, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 82, - "fields": { - "institution": 12, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": false, - "independent": true, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 92, - "fields": { - "institution": 8, - "tournament": 1, - "test_score": 2.0, - "url_key": null, - "breaking": true, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 81, - "fields": { - "institution": 4, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": false, - "independent": true, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 95, - "fields": { - "institution": 10, - "tournament": 1, - "test_score": 3.0, - "url_key": null, - "breaking": true, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 89, - "fields": { - "institution": 7, - "tournament": 1, - "test_score": 2.0, - "url_key": null, - "breaking": true, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 77, - "fields": { - "institution": 1, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 98, - "fields": { - "institution": 13, - "tournament": 1, - "test_score": 3.0, - "url_key": null, - "breaking": true, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 84, - "fields": { - "institution": 8, - "tournament": 1, - "test_score": 4.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 80, - "fields": { - "institution": 4, - "tournament": 1, - "test_score": 4.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 73, - "fields": { - "institution": 13, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 78, - "fields": { - "institution": 2, - "tournament": 1, - "test_score": 2.0, - "url_key": null, - "breaking": true, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 79, - "fields": { - "institution": 3, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": false, - "independent": true, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 159, - "fields": { - "institution": 1, - "tournament": null, - "test_score": 2.5, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 160, - "fields": { - "institution": 2, - "tournament": null, - "test_score": 2.5, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 99, - "fields": { - "institution": 5, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 83, - "fields": { - "institution": 12, - "tournament": 1, - "test_score": 4.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 76, - "fields": { - "institution": 1, - "tournament": 1, - "test_score": 1.0, - "url_key": null, - "breaking": false, - "independent": true, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 87, - "fields": { - "institution": 6, - "tournament": 1, - "test_score": 2.0, - "url_key": null, - "breaking": true, - "independent": true, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 88, - "fields": { - "institution": 6, - "tournament": 1, - "test_score": 5.0, - "url_key": null, - "breaking": true, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 86, - "fields": { - "institution": 5, - "tournament": 1, - "test_score": 2.0, - "url_key": null, - "breaking": false, - "independent": false, - "adj_core": false - } - }, - { - "model": "participants.adjudicator", - "pk": 85, - "fields": { - "institution": 5, - "tournament": 1, - "test_score": 4.0, - "url_key": null, - "breaking": false, - "independent": true, - "adj_core": false - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 1, - "fields": { - "ballot_submission": 1, - "debate_adjudicator": 1, - "debate_team": 23, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 2, - "fields": { - "ballot_submission": 1, - "debate_adjudicator": 1, - "debate_team": 23, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 3, - "fields": { - "ballot_submission": 1, - "debate_adjudicator": 1, - "debate_team": 23, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 4, - "fields": { - "ballot_submission": 1, - "debate_adjudicator": 1, - "debate_team": 23, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 5, - "fields": { - "ballot_submission": 1, - "debate_adjudicator": 1, - "debate_team": 24, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 6, - "fields": { - "ballot_submission": 1, - "debate_adjudicator": 1, - "debate_team": 24, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 7, - "fields": { - "ballot_submission": 1, - "debate_adjudicator": 1, - "debate_team": 24, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 8, - "fields": { - "ballot_submission": 1, - "debate_adjudicator": 1, - "debate_team": 24, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 9, - "fields": { - "ballot_submission": 2, - "debate_adjudicator": 2, - "debate_team": 21, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 10, - "fields": { - "ballot_submission": 2, - "debate_adjudicator": 2, - "debate_team": 21, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 11, - "fields": { - "ballot_submission": 2, - "debate_adjudicator": 2, - "debate_team": 21, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 12, - "fields": { - "ballot_submission": 2, - "debate_adjudicator": 2, - "debate_team": 21, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 13, - "fields": { - "ballot_submission": 2, - "debate_adjudicator": 2, - "debate_team": 22, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 14, - "fields": { - "ballot_submission": 2, - "debate_adjudicator": 2, - "debate_team": 22, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 15, - "fields": { - "ballot_submission": 2, - "debate_adjudicator": 2, - "debate_team": 22, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 16, - "fields": { - "ballot_submission": 2, - "debate_adjudicator": 2, - "debate_team": 22, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 17, - "fields": { - "ballot_submission": 3, - "debate_adjudicator": 3, - "debate_team": 19, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 18, - "fields": { - "ballot_submission": 3, - "debate_adjudicator": 3, - "debate_team": 19, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 19, - "fields": { - "ballot_submission": 3, - "debate_adjudicator": 3, - "debate_team": 19, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 20, - "fields": { - "ballot_submission": 3, - "debate_adjudicator": 3, - "debate_team": 19, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 21, - "fields": { - "ballot_submission": 3, - "debate_adjudicator": 3, - "debate_team": 20, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 22, - "fields": { - "ballot_submission": 3, - "debate_adjudicator": 3, - "debate_team": 20, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 23, - "fields": { - "ballot_submission": 3, - "debate_adjudicator": 3, - "debate_team": 20, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 24, - "fields": { - "ballot_submission": 3, - "debate_adjudicator": 3, - "debate_team": 20, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 25, - "fields": { - "ballot_submission": 4, - "debate_adjudicator": 4, - "debate_team": 17, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 26, - "fields": { - "ballot_submission": 4, - "debate_adjudicator": 4, - "debate_team": 17, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 27, - "fields": { - "ballot_submission": 4, - "debate_adjudicator": 4, - "debate_team": 17, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 28, - "fields": { - "ballot_submission": 4, - "debate_adjudicator": 4, - "debate_team": 17, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 29, - "fields": { - "ballot_submission": 4, - "debate_adjudicator": 4, - "debate_team": 18, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 30, - "fields": { - "ballot_submission": 4, - "debate_adjudicator": 4, - "debate_team": 18, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 31, - "fields": { - "ballot_submission": 4, - "debate_adjudicator": 4, - "debate_team": 18, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 32, - "fields": { - "ballot_submission": 4, - "debate_adjudicator": 4, - "debate_team": 18, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 33, - "fields": { - "ballot_submission": 5, - "debate_adjudicator": 5, - "debate_team": 15, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 34, - "fields": { - "ballot_submission": 5, - "debate_adjudicator": 5, - "debate_team": 15, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 35, - "fields": { - "ballot_submission": 5, - "debate_adjudicator": 5, - "debate_team": 15, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 36, - "fields": { - "ballot_submission": 5, - "debate_adjudicator": 5, - "debate_team": 15, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 37, - "fields": { - "ballot_submission": 5, - "debate_adjudicator": 5, - "debate_team": 16, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 38, - "fields": { - "ballot_submission": 5, - "debate_adjudicator": 5, - "debate_team": 16, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 39, - "fields": { - "ballot_submission": 5, - "debate_adjudicator": 5, - "debate_team": 16, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 40, - "fields": { - "ballot_submission": 5, - "debate_adjudicator": 5, - "debate_team": 16, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 41, - "fields": { - "ballot_submission": 6, - "debate_adjudicator": 6, - "debate_team": 13, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 42, - "fields": { - "ballot_submission": 6, - "debate_adjudicator": 6, - "debate_team": 13, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 43, - "fields": { - "ballot_submission": 6, - "debate_adjudicator": 6, - "debate_team": 13, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 44, - "fields": { - "ballot_submission": 6, - "debate_adjudicator": 6, - "debate_team": 13, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 45, - "fields": { - "ballot_submission": 6, - "debate_adjudicator": 6, - "debate_team": 14, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 46, - "fields": { - "ballot_submission": 6, - "debate_adjudicator": 6, - "debate_team": 14, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 47, - "fields": { - "ballot_submission": 6, - "debate_adjudicator": 6, - "debate_team": 14, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 48, - "fields": { - "ballot_submission": 6, - "debate_adjudicator": 6, - "debate_team": 14, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 49, - "fields": { - "ballot_submission": 7, - "debate_adjudicator": 7, - "debate_team": 11, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 50, - "fields": { - "ballot_submission": 7, - "debate_adjudicator": 7, - "debate_team": 11, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 51, - "fields": { - "ballot_submission": 7, - "debate_adjudicator": 7, - "debate_team": 11, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 52, - "fields": { - "ballot_submission": 7, - "debate_adjudicator": 7, - "debate_team": 11, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 53, - "fields": { - "ballot_submission": 7, - "debate_adjudicator": 7, - "debate_team": 12, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 54, - "fields": { - "ballot_submission": 7, - "debate_adjudicator": 7, - "debate_team": 12, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 55, - "fields": { - "ballot_submission": 7, - "debate_adjudicator": 7, - "debate_team": 12, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 56, - "fields": { - "ballot_submission": 7, - "debate_adjudicator": 7, - "debate_team": 12, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 57, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 10, - "debate_team": 9, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 58, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 10, - "debate_team": 9, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 59, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 10, - "debate_team": 9, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 60, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 10, - "debate_team": 9, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 61, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 10, - "debate_team": 10, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 62, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 10, - "debate_team": 10, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 63, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 10, - "debate_team": 10, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 64, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 10, - "debate_team": 10, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 65, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 9, - "debate_team": 9, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 66, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 9, - "debate_team": 9, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 67, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 9, - "debate_team": 9, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 68, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 9, - "debate_team": 9, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 69, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 9, - "debate_team": 10, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 70, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 9, - "debate_team": 10, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 71, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 9, - "debate_team": 10, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 72, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 9, - "debate_team": 10, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 73, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 8, - "debate_team": 9, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 74, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 8, - "debate_team": 9, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 75, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 8, - "debate_team": 9, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 76, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 8, - "debate_team": 9, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 77, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 8, - "debate_team": 10, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 78, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 8, - "debate_team": 10, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 79, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 8, - "debate_team": 10, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 80, - "fields": { - "ballot_submission": 8, - "debate_adjudicator": 8, - "debate_team": 10, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 81, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 12, - "debate_team": 7, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 82, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 12, - "debate_team": 7, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 83, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 12, - "debate_team": 7, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 84, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 12, - "debate_team": 7, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 85, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 12, - "debate_team": 8, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 86, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 12, - "debate_team": 8, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 87, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 12, - "debate_team": 8, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 88, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 12, - "debate_team": 8, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 89, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 13, - "debate_team": 7, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 90, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 13, - "debate_team": 7, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 91, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 13, - "debate_team": 7, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 92, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 13, - "debate_team": 7, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 93, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 13, - "debate_team": 8, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 94, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 13, - "debate_team": 8, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 95, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 13, - "debate_team": 8, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 96, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 13, - "debate_team": 8, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 97, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 11, - "debate_team": 7, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 98, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 11, - "debate_team": 7, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 99, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 11, - "debate_team": 7, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 100, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 11, - "debate_team": 7, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 101, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 11, - "debate_team": 8, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 102, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 11, - "debate_team": 8, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 103, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 11, - "debate_team": 8, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 104, - "fields": { - "ballot_submission": 9, - "debate_adjudicator": 11, - "debate_team": 8, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 105, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 15, - "debate_team": 5, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 106, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 15, - "debate_team": 5, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 107, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 15, - "debate_team": 5, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 108, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 15, - "debate_team": 5, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 109, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 15, - "debate_team": 6, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 110, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 15, - "debate_team": 6, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 111, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 15, - "debate_team": 6, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 112, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 15, - "debate_team": 6, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 113, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 14, - "debate_team": 5, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 114, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 14, - "debate_team": 5, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 115, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 14, - "debate_team": 5, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 116, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 14, - "debate_team": 5, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 117, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 14, - "debate_team": 6, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 118, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 14, - "debate_team": 6, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 119, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 14, - "debate_team": 6, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 120, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 14, - "debate_team": 6, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 121, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 16, - "debate_team": 5, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 122, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 16, - "debate_team": 5, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 123, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 16, - "debate_team": 5, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 124, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 16, - "debate_team": 5, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 125, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 16, - "debate_team": 6, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 126, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 16, - "debate_team": 6, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 127, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 16, - "debate_team": 6, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 128, - "fields": { - "ballot_submission": 10, - "debate_adjudicator": 16, - "debate_team": 6, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 129, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 17, - "debate_team": 3, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 130, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 17, - "debate_team": 3, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 131, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 17, - "debate_team": 3, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 132, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 17, - "debate_team": 3, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 133, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 17, - "debate_team": 4, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 134, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 17, - "debate_team": 4, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 135, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 17, - "debate_team": 4, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 136, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 17, - "debate_team": 4, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 137, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 19, - "debate_team": 3, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 138, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 19, - "debate_team": 3, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 139, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 19, - "debate_team": 3, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 140, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 19, - "debate_team": 3, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 141, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 19, - "debate_team": 4, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 142, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 19, - "debate_team": 4, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 143, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 19, - "debate_team": 4, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 144, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 19, - "debate_team": 4, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 145, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 18, - "debate_team": 3, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 146, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 18, - "debate_team": 3, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 147, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 18, - "debate_team": 3, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 148, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 18, - "debate_team": 3, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 149, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 18, - "debate_team": 4, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 150, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 18, - "debate_team": 4, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 151, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 18, - "debate_team": 4, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 152, - "fields": { - "ballot_submission": 11, - "debate_adjudicator": 18, - "debate_team": 4, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 153, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 21, - "debate_team": 1, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 154, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 21, - "debate_team": 1, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 155, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 21, - "debate_team": 1, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 156, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 21, - "debate_team": 1, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 157, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 21, - "debate_team": 2, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 158, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 21, - "debate_team": 2, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 159, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 21, - "debate_team": 2, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 160, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 21, - "debate_team": 2, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 161, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 20, - "debate_team": 1, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 162, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 20, - "debate_team": 1, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 163, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 20, - "debate_team": 1, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 164, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 20, - "debate_team": 1, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 165, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 20, - "debate_team": 2, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 166, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 20, - "debate_team": 2, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 167, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 20, - "debate_team": 2, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 168, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 20, - "debate_team": 2, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 169, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 22, - "debate_team": 1, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 170, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 22, - "debate_team": 1, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 171, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 22, - "debate_team": 1, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 172, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 22, - "debate_team": 1, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 173, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 22, - "debate_team": 2, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 174, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 22, - "debate_team": 2, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 175, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 22, - "debate_team": 2, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 176, - "fields": { - "ballot_submission": 12, - "debate_adjudicator": 22, - "debate_team": 2, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 177, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 33, - "debate_team": 47, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 178, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 33, - "debate_team": 47, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 179, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 33, - "debate_team": 47, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 180, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 33, - "debate_team": 47, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 181, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 33, - "debate_team": 48, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 182, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 33, - "debate_team": 48, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 183, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 33, - "debate_team": 48, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 184, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 33, - "debate_team": 48, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 185, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 34, - "debate_team": 47, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 186, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 34, - "debate_team": 47, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 187, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 34, - "debate_team": 47, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 188, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 34, - "debate_team": 47, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 189, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 34, - "debate_team": 48, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 190, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 34, - "debate_team": 48, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 191, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 34, - "debate_team": 48, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 192, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 34, - "debate_team": 48, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 193, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 35, - "debate_team": 47, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 194, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 35, - "debate_team": 47, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 195, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 35, - "debate_team": 47, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 196, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 35, - "debate_team": 47, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 197, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 35, - "debate_team": 48, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 198, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 35, - "debate_team": 48, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 199, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 35, - "debate_team": 48, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 200, - "fields": { - "ballot_submission": 13, - "debate_adjudicator": 35, - "debate_team": 48, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 201, - "fields": { - "ballot_submission": 14, - "debate_adjudicator": 24, - "debate_team": 45, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 202, - "fields": { - "ballot_submission": 14, - "debate_adjudicator": 24, - "debate_team": 45, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 203, - "fields": { - "ballot_submission": 14, - "debate_adjudicator": 24, - "debate_team": 45, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 204, - "fields": { - "ballot_submission": 14, - "debate_adjudicator": 24, - "debate_team": 45, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 205, - "fields": { - "ballot_submission": 14, - "debate_adjudicator": 24, - "debate_team": 46, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 206, - "fields": { - "ballot_submission": 14, - "debate_adjudicator": 24, - "debate_team": 46, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 207, - "fields": { - "ballot_submission": 14, - "debate_adjudicator": 24, - "debate_team": 46, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 208, - "fields": { - "ballot_submission": 14, - "debate_adjudicator": 24, - "debate_team": 46, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 209, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 38, - "debate_team": 43, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 210, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 38, - "debate_team": 43, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 211, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 38, - "debate_team": 43, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 212, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 38, - "debate_team": 43, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 213, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 38, - "debate_team": 44, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 214, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 38, - "debate_team": 44, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 215, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 38, - "debate_team": 44, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 216, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 38, - "debate_team": 44, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 217, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 36, - "debate_team": 43, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 218, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 36, - "debate_team": 43, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 219, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 36, - "debate_team": 43, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 220, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 36, - "debate_team": 43, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 221, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 36, - "debate_team": 44, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 222, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 36, - "debate_team": 44, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 223, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 36, - "debate_team": 44, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 224, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 36, - "debate_team": 44, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 225, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 37, - "debate_team": 43, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 226, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 37, - "debate_team": 43, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 227, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 37, - "debate_team": 43, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 228, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 37, - "debate_team": 43, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 229, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 37, - "debate_team": 44, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 230, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 37, - "debate_team": 44, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 231, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 37, - "debate_team": 44, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 232, - "fields": { - "ballot_submission": 15, - "debate_adjudicator": 37, - "debate_team": 44, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 233, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 39, - "debate_team": 41, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 234, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 39, - "debate_team": 41, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 235, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 39, - "debate_team": 41, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 236, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 39, - "debate_team": 41, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 237, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 39, - "debate_team": 42, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 238, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 39, - "debate_team": 42, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 239, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 39, - "debate_team": 42, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 240, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 39, - "debate_team": 42, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 241, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 41, - "debate_team": 41, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 242, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 41, - "debate_team": 41, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 243, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 41, - "debate_team": 41, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 244, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 41, - "debate_team": 41, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 245, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 41, - "debate_team": 42, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 246, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 41, - "debate_team": 42, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 247, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 41, - "debate_team": 42, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 248, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 41, - "debate_team": 42, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 249, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 40, - "debate_team": 41, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 250, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 40, - "debate_team": 41, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 251, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 40, - "debate_team": 41, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 252, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 40, - "debate_team": 41, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 253, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 40, - "debate_team": 42, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 254, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 40, - "debate_team": 42, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 255, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 40, - "debate_team": 42, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 256, - "fields": { - "ballot_submission": 16, - "debate_adjudicator": 40, - "debate_team": 42, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 257, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 30, - "debate_team": 39, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 258, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 30, - "debate_team": 39, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 259, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 30, - "debate_team": 39, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 260, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 30, - "debate_team": 39, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 261, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 30, - "debate_team": 40, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 262, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 30, - "debate_team": 40, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 263, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 30, - "debate_team": 40, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 264, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 30, - "debate_team": 40, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 265, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 31, - "debate_team": 39, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 266, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 31, - "debate_team": 39, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 267, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 31, - "debate_team": 39, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 268, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 31, - "debate_team": 39, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 269, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 31, - "debate_team": 40, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 270, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 31, - "debate_team": 40, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 271, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 31, - "debate_team": 40, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 272, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 31, - "debate_team": 40, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 273, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 32, - "debate_team": 39, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 274, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 32, - "debate_team": 39, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 275, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 32, - "debate_team": 39, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 276, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 32, - "debate_team": 39, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 277, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 32, - "debate_team": 40, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 278, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 32, - "debate_team": 40, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 279, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 32, - "debate_team": 40, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 280, - "fields": { - "ballot_submission": 17, - "debate_adjudicator": 32, - "debate_team": 40, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 281, - "fields": { - "ballot_submission": 18, - "debate_adjudicator": 23, - "debate_team": 37, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 282, - "fields": { - "ballot_submission": 18, - "debate_adjudicator": 23, - "debate_team": 37, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 283, - "fields": { - "ballot_submission": 18, - "debate_adjudicator": 23, - "debate_team": 37, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 284, - "fields": { - "ballot_submission": 18, - "debate_adjudicator": 23, - "debate_team": 37, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 285, - "fields": { - "ballot_submission": 18, - "debate_adjudicator": 23, - "debate_team": 38, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 286, - "fields": { - "ballot_submission": 18, - "debate_adjudicator": 23, - "debate_team": 38, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 287, - "fields": { - "ballot_submission": 18, - "debate_adjudicator": 23, - "debate_team": 38, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 288, - "fields": { - "ballot_submission": 18, - "debate_adjudicator": 23, - "debate_team": 38, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 289, - "fields": { - "ballot_submission": 19, - "debate_adjudicator": 27, - "debate_team": 35, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 290, - "fields": { - "ballot_submission": 19, - "debate_adjudicator": 27, - "debate_team": 35, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 291, - "fields": { - "ballot_submission": 19, - "debate_adjudicator": 27, - "debate_team": 35, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 292, - "fields": { - "ballot_submission": 19, - "debate_adjudicator": 27, - "debate_team": 35, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 293, - "fields": { - "ballot_submission": 19, - "debate_adjudicator": 27, - "debate_team": 36, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 294, - "fields": { - "ballot_submission": 19, - "debate_adjudicator": 27, - "debate_team": 36, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 295, - "fields": { - "ballot_submission": 19, - "debate_adjudicator": 27, - "debate_team": 36, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 296, - "fields": { - "ballot_submission": 19, - "debate_adjudicator": 27, - "debate_team": 36, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 297, - "fields": { - "ballot_submission": 20, - "debate_adjudicator": 26, - "debate_team": 33, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 298, - "fields": { - "ballot_submission": 20, - "debate_adjudicator": 26, - "debate_team": 33, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 299, - "fields": { - "ballot_submission": 20, - "debate_adjudicator": 26, - "debate_team": 33, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 300, - "fields": { - "ballot_submission": 20, - "debate_adjudicator": 26, - "debate_team": 33, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 301, - "fields": { - "ballot_submission": 20, - "debate_adjudicator": 26, - "debate_team": 34, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 302, - "fields": { - "ballot_submission": 20, - "debate_adjudicator": 26, - "debate_team": 34, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 303, - "fields": { - "ballot_submission": 20, - "debate_adjudicator": 26, - "debate_team": 34, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 304, - "fields": { - "ballot_submission": 20, - "debate_adjudicator": 26, - "debate_team": 34, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 305, - "fields": { - "ballot_submission": 21, - "debate_adjudicator": 29, - "debate_team": 31, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 306, - "fields": { - "ballot_submission": 21, - "debate_adjudicator": 29, - "debate_team": 31, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 307, - "fields": { - "ballot_submission": 21, - "debate_adjudicator": 29, - "debate_team": 31, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 308, - "fields": { - "ballot_submission": 21, - "debate_adjudicator": 29, - "debate_team": 31, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 309, - "fields": { - "ballot_submission": 21, - "debate_adjudicator": 29, - "debate_team": 32, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 310, - "fields": { - "ballot_submission": 21, - "debate_adjudicator": 29, - "debate_team": 32, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 311, - "fields": { - "ballot_submission": 21, - "debate_adjudicator": 29, - "debate_team": 32, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 312, - "fields": { - "ballot_submission": 21, - "debate_adjudicator": 29, - "debate_team": 32, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 313, - "fields": { - "ballot_submission": 22, - "debate_adjudicator": 28, - "debate_team": 29, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 314, - "fields": { - "ballot_submission": 22, - "debate_adjudicator": 28, - "debate_team": 29, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 315, - "fields": { - "ballot_submission": 22, - "debate_adjudicator": 28, - "debate_team": 29, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 316, - "fields": { - "ballot_submission": 22, - "debate_adjudicator": 28, - "debate_team": 29, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 317, - "fields": { - "ballot_submission": 22, - "debate_adjudicator": 28, - "debate_team": 30, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 318, - "fields": { - "ballot_submission": 22, - "debate_adjudicator": 28, - "debate_team": 30, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 319, - "fields": { - "ballot_submission": 22, - "debate_adjudicator": 28, - "debate_team": 30, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 320, - "fields": { - "ballot_submission": 22, - "debate_adjudicator": 28, - "debate_team": 30, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 321, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 42, - "debate_team": 27, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 322, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 42, - "debate_team": 27, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 323, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 42, - "debate_team": 27, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 324, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 42, - "debate_team": 27, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 325, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 42, - "debate_team": 28, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 326, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 42, - "debate_team": 28, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 327, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 42, - "debate_team": 28, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 328, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 42, - "debate_team": 28, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 329, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 43, - "debate_team": 27, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 330, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 43, - "debate_team": 27, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 331, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 43, - "debate_team": 27, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 332, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 43, - "debate_team": 27, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 333, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 43, - "debate_team": 28, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 334, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 43, - "debate_team": 28, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 335, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 43, - "debate_team": 28, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 336, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 43, - "debate_team": 28, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 337, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 44, - "debate_team": 27, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 338, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 44, - "debate_team": 27, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 339, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 44, - "debate_team": 27, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 340, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 44, - "debate_team": 27, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 341, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 44, - "debate_team": 28, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 342, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 44, - "debate_team": 28, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 343, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 44, - "debate_team": 28, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 344, - "fields": { - "ballot_submission": 23, - "debate_adjudicator": 44, - "debate_team": 28, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 345, - "fields": { - "ballot_submission": 24, - "debate_adjudicator": 25, - "debate_team": 25, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 346, - "fields": { - "ballot_submission": 24, - "debate_adjudicator": 25, - "debate_team": 25, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 347, - "fields": { - "ballot_submission": 24, - "debate_adjudicator": 25, - "debate_team": 25, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 348, - "fields": { - "ballot_submission": 24, - "debate_adjudicator": 25, - "debate_team": 25, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 349, - "fields": { - "ballot_submission": 24, - "debate_adjudicator": 25, - "debate_team": 26, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 350, - "fields": { - "ballot_submission": 24, - "debate_adjudicator": 25, - "debate_team": 26, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 351, - "fields": { - "ballot_submission": 24, - "debate_adjudicator": 25, - "debate_team": 26, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 352, - "fields": { - "ballot_submission": 24, - "debate_adjudicator": 25, - "debate_team": 26, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 353, - "fields": { - "ballot_submission": 25, - "debate_adjudicator": 48, - "debate_team": 49, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 354, - "fields": { - "ballot_submission": 25, - "debate_adjudicator": 48, - "debate_team": 49, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 355, - "fields": { - "ballot_submission": 25, - "debate_adjudicator": 48, - "debate_team": 49, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 356, - "fields": { - "ballot_submission": 25, - "debate_adjudicator": 48, - "debate_team": 49, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 357, - "fields": { - "ballot_submission": 25, - "debate_adjudicator": 48, - "debate_team": 50, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 358, - "fields": { - "ballot_submission": 25, - "debate_adjudicator": 48, - "debate_team": 50, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 359, - "fields": { - "ballot_submission": 25, - "debate_adjudicator": 48, - "debate_team": 50, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 360, - "fields": { - "ballot_submission": 25, - "debate_adjudicator": 48, - "debate_team": 50, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 361, - "fields": { - "ballot_submission": 26, - "debate_adjudicator": 47, - "debate_team": 51, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 362, - "fields": { - "ballot_submission": 26, - "debate_adjudicator": 47, - "debate_team": 51, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 363, - "fields": { - "ballot_submission": 26, - "debate_adjudicator": 47, - "debate_team": 51, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 364, - "fields": { - "ballot_submission": 26, - "debate_adjudicator": 47, - "debate_team": 51, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 365, - "fields": { - "ballot_submission": 26, - "debate_adjudicator": 47, - "debate_team": 52, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 366, - "fields": { - "ballot_submission": 26, - "debate_adjudicator": 47, - "debate_team": 52, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 367, - "fields": { - "ballot_submission": 26, - "debate_adjudicator": 47, - "debate_team": 52, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 368, - "fields": { - "ballot_submission": 26, - "debate_adjudicator": 47, - "debate_team": 52, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 369, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 52, - "debate_team": 53, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 370, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 52, - "debate_team": 53, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 371, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 52, - "debate_team": 53, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 372, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 52, - "debate_team": 53, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 373, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 52, - "debate_team": 54, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 374, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 52, - "debate_team": 54, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 375, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 52, - "debate_team": 54, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 376, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 52, - "debate_team": 54, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 377, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 53, - "debate_team": 53, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 378, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 53, - "debate_team": 53, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 379, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 53, - "debate_team": 53, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 380, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 53, - "debate_team": 53, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 381, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 53, - "debate_team": 54, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 382, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 53, - "debate_team": 54, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 383, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 53, - "debate_team": 54, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 384, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 53, - "debate_team": 54, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 385, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 54, - "debate_team": 53, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 386, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 54, - "debate_team": 53, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 387, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 54, - "debate_team": 53, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 388, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 54, - "debate_team": 53, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 389, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 54, - "debate_team": 54, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 390, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 54, - "debate_team": 54, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 391, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 54, - "debate_team": 54, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 392, - "fields": { - "ballot_submission": 27, - "debate_adjudicator": 54, - "debate_team": 54, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 393, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 55, - "debate_team": 55, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 394, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 55, - "debate_team": 55, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 395, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 55, - "debate_team": 55, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 396, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 55, - "debate_team": 55, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 397, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 55, - "debate_team": 56, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 398, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 55, - "debate_team": 56, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 399, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 55, - "debate_team": 56, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 400, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 55, - "debate_team": 56, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 401, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 57, - "debate_team": 55, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 402, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 57, - "debate_team": 55, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 403, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 57, - "debate_team": 55, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 404, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 57, - "debate_team": 55, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 405, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 57, - "debate_team": 56, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 406, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 57, - "debate_team": 56, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 407, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 57, - "debate_team": 56, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 408, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 57, - "debate_team": 56, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 409, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 56, - "debate_team": 55, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 410, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 56, - "debate_team": 55, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 411, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 56, - "debate_team": 55, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 412, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 56, - "debate_team": 55, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 413, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 56, - "debate_team": 56, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 414, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 56, - "debate_team": 56, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 415, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 56, - "debate_team": 56, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 416, - "fields": { - "ballot_submission": 28, - "debate_adjudicator": 56, - "debate_team": 56, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 417, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 64, - "debate_team": 57, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 418, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 64, - "debate_team": 57, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 419, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 64, - "debate_team": 57, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 420, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 64, - "debate_team": 57, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 421, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 64, - "debate_team": 58, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 422, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 64, - "debate_team": 58, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 423, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 64, - "debate_team": 58, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 424, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 64, - "debate_team": 58, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 425, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 66, - "debate_team": 57, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 426, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 66, - "debate_team": 57, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 427, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 66, - "debate_team": 57, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 428, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 66, - "debate_team": 57, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 429, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 66, - "debate_team": 58, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 430, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 66, - "debate_team": 58, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 431, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 66, - "debate_team": 58, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 432, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 66, - "debate_team": 58, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 433, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 65, - "debate_team": 57, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 434, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 65, - "debate_team": 57, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 435, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 65, - "debate_team": 57, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 436, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 65, - "debate_team": 57, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 437, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 65, - "debate_team": 58, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 438, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 65, - "debate_team": 58, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 439, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 65, - "debate_team": 58, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 440, - "fields": { - "ballot_submission": 29, - "debate_adjudicator": 65, - "debate_team": 58, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 441, - "fields": { - "ballot_submission": 30, - "debate_adjudicator": 50, - "debate_team": 59, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 442, - "fields": { - "ballot_submission": 30, - "debate_adjudicator": 50, - "debate_team": 59, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 443, - "fields": { - "ballot_submission": 30, - "debate_adjudicator": 50, - "debate_team": 59, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 444, - "fields": { - "ballot_submission": 30, - "debate_adjudicator": 50, - "debate_team": 59, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 445, - "fields": { - "ballot_submission": 30, - "debate_adjudicator": 50, - "debate_team": 60, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 446, - "fields": { - "ballot_submission": 30, - "debate_adjudicator": 50, - "debate_team": 60, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 447, - "fields": { - "ballot_submission": 30, - "debate_adjudicator": 50, - "debate_team": 60, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 448, - "fields": { - "ballot_submission": 30, - "debate_adjudicator": 50, - "debate_team": 60, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 449, - "fields": { - "ballot_submission": 31, - "debate_adjudicator": 45, - "debate_team": 61, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 450, - "fields": { - "ballot_submission": 31, - "debate_adjudicator": 45, - "debate_team": 61, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 451, - "fields": { - "ballot_submission": 31, - "debate_adjudicator": 45, - "debate_team": 61, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 452, - "fields": { - "ballot_submission": 31, - "debate_adjudicator": 45, - "debate_team": 61, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 453, - "fields": { - "ballot_submission": 31, - "debate_adjudicator": 45, - "debate_team": 62, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 454, - "fields": { - "ballot_submission": 31, - "debate_adjudicator": 45, - "debate_team": 62, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 455, - "fields": { - "ballot_submission": 31, - "debate_adjudicator": 45, - "debate_team": 62, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 456, - "fields": { - "ballot_submission": 31, - "debate_adjudicator": 45, - "debate_team": 62, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 457, - "fields": { - "ballot_submission": 32, - "debate_adjudicator": 49, - "debate_team": 63, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 458, - "fields": { - "ballot_submission": 32, - "debate_adjudicator": 49, - "debate_team": 63, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 459, - "fields": { - "ballot_submission": 32, - "debate_adjudicator": 49, - "debate_team": 63, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 460, - "fields": { - "ballot_submission": 32, - "debate_adjudicator": 49, - "debate_team": 63, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 461, - "fields": { - "ballot_submission": 32, - "debate_adjudicator": 49, - "debate_team": 64, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 462, - "fields": { - "ballot_submission": 32, - "debate_adjudicator": 49, - "debate_team": 64, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 463, - "fields": { - "ballot_submission": 32, - "debate_adjudicator": 49, - "debate_team": 64, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 464, - "fields": { - "ballot_submission": 32, - "debate_adjudicator": 49, - "debate_team": 64, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 465, - "fields": { - "ballot_submission": 33, - "debate_adjudicator": 46, - "debate_team": 65, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 466, - "fields": { - "ballot_submission": 33, - "debate_adjudicator": 46, - "debate_team": 65, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 467, - "fields": { - "ballot_submission": 33, - "debate_adjudicator": 46, - "debate_team": 65, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 468, - "fields": { - "ballot_submission": 33, - "debate_adjudicator": 46, - "debate_team": 65, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 469, - "fields": { - "ballot_submission": 33, - "debate_adjudicator": 46, - "debate_team": 66, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 470, - "fields": { - "ballot_submission": 33, - "debate_adjudicator": 46, - "debate_team": 66, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 471, - "fields": { - "ballot_submission": 33, - "debate_adjudicator": 46, - "debate_team": 66, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 472, - "fields": { - "ballot_submission": 33, - "debate_adjudicator": 46, - "debate_team": 66, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 473, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 63, - "debate_team": 67, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 474, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 63, - "debate_team": 67, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 475, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 63, - "debate_team": 67, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 476, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 63, - "debate_team": 67, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 477, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 63, - "debate_team": 68, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 478, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 63, - "debate_team": 68, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 479, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 63, - "debate_team": 68, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 480, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 63, - "debate_team": 68, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 481, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 62, - "debate_team": 67, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 482, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 62, - "debate_team": 67, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 483, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 62, - "debate_team": 67, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 484, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 62, - "debate_team": 67, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 485, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 62, - "debate_team": 68, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 486, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 62, - "debate_team": 68, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 487, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 62, - "debate_team": 68, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 488, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 62, - "debate_team": 68, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 489, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 61, - "debate_team": 67, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 490, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 61, - "debate_team": 67, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 491, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 61, - "debate_team": 67, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 492, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 61, - "debate_team": 67, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 493, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 61, - "debate_team": 68, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 494, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 61, - "debate_team": 68, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 495, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 61, - "debate_team": 68, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 496, - "fields": { - "ballot_submission": 34, - "debate_adjudicator": 61, - "debate_team": 68, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 497, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 60, - "debate_team": 69, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 498, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 60, - "debate_team": 69, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 499, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 60, - "debate_team": 69, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 500, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 60, - "debate_team": 69, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 501, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 60, - "debate_team": 70, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 502, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 60, - "debate_team": 70, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 503, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 60, - "debate_team": 70, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 504, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 60, - "debate_team": 70, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 505, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 58, - "debate_team": 69, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 506, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 58, - "debate_team": 69, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 507, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 58, - "debate_team": 69, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 508, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 58, - "debate_team": 69, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 509, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 58, - "debate_team": 70, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 510, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 58, - "debate_team": 70, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 511, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 58, - "debate_team": 70, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 512, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 58, - "debate_team": 70, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 513, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 59, - "debate_team": 69, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 514, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 59, - "debate_team": 69, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 515, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 59, - "debate_team": 69, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 516, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 59, - "debate_team": 69, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 517, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 59, - "debate_team": 70, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 518, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 59, - "debate_team": 70, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 519, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 59, - "debate_team": 70, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 520, - "fields": { - "ballot_submission": 35, - "debate_adjudicator": 59, - "debate_team": 70, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 521, - "fields": { - "ballot_submission": 36, - "debate_adjudicator": 51, - "debate_team": 71, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 522, - "fields": { - "ballot_submission": 36, - "debate_adjudicator": 51, - "debate_team": 71, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 523, - "fields": { - "ballot_submission": 36, - "debate_adjudicator": 51, - "debate_team": 71, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 524, - "fields": { - "ballot_submission": 36, - "debate_adjudicator": 51, - "debate_team": 71, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 525, - "fields": { - "ballot_submission": 36, - "debate_adjudicator": 51, - "debate_team": 72, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 526, - "fields": { - "ballot_submission": 36, - "debate_adjudicator": 51, - "debate_team": 72, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 527, - "fields": { - "ballot_submission": 36, - "debate_adjudicator": 51, - "debate_team": 72, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 528, - "fields": { - "ballot_submission": 36, - "debate_adjudicator": 51, - "debate_team": 72, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 529, - "fields": { - "ballot_submission": 37, - "debate_adjudicator": 73, - "debate_team": 73, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 530, - "fields": { - "ballot_submission": 37, - "debate_adjudicator": 73, - "debate_team": 73, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 531, - "fields": { - "ballot_submission": 37, - "debate_adjudicator": 73, - "debate_team": 73, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 532, - "fields": { - "ballot_submission": 37, - "debate_adjudicator": 73, - "debate_team": 73, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 533, - "fields": { - "ballot_submission": 37, - "debate_adjudicator": 73, - "debate_team": 74, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 534, - "fields": { - "ballot_submission": 37, - "debate_adjudicator": 73, - "debate_team": 74, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 535, - "fields": { - "ballot_submission": 37, - "debate_adjudicator": 73, - "debate_team": 74, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 536, - "fields": { - "ballot_submission": 37, - "debate_adjudicator": 73, - "debate_team": 74, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 537, - "fields": { - "ballot_submission": 38, - "debate_adjudicator": 67, - "debate_team": 75, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 538, - "fields": { - "ballot_submission": 38, - "debate_adjudicator": 67, - "debate_team": 75, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 539, - "fields": { - "ballot_submission": 38, - "debate_adjudicator": 67, - "debate_team": 75, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 540, - "fields": { - "ballot_submission": 38, - "debate_adjudicator": 67, - "debate_team": 75, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 541, - "fields": { - "ballot_submission": 38, - "debate_adjudicator": 67, - "debate_team": 76, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 542, - "fields": { - "ballot_submission": 38, - "debate_adjudicator": 67, - "debate_team": 76, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 543, - "fields": { - "ballot_submission": 38, - "debate_adjudicator": 67, - "debate_team": 76, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 544, - "fields": { - "ballot_submission": 38, - "debate_adjudicator": 67, - "debate_team": 76, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 545, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 78, - "debate_team": 77, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 546, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 78, - "debate_team": 77, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 547, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 78, - "debate_team": 77, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 548, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 78, - "debate_team": 77, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 549, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 78, - "debate_team": 78, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 550, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 78, - "debate_team": 78, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 551, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 78, - "debate_team": 78, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 552, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 78, - "debate_team": 78, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 553, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 77, - "debate_team": 77, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 554, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 77, - "debate_team": 77, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 555, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 77, - "debate_team": 77, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 556, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 77, - "debate_team": 77, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 557, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 77, - "debate_team": 78, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 558, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 77, - "debate_team": 78, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 559, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 77, - "debate_team": 78, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 560, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 77, - "debate_team": 78, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 561, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 79, - "debate_team": 77, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 562, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 79, - "debate_team": 77, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 563, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 79, - "debate_team": 77, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 564, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 79, - "debate_team": 77, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 565, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 79, - "debate_team": 78, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 566, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 79, - "debate_team": 78, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 567, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 79, - "debate_team": 78, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 568, - "fields": { - "ballot_submission": 39, - "debate_adjudicator": 79, - "debate_team": 78, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 569, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 76, - "debate_team": 79, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 570, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 76, - "debate_team": 79, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 571, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 76, - "debate_team": 79, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 572, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 76, - "debate_team": 79, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 573, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 76, - "debate_team": 80, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 574, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 76, - "debate_team": 80, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 575, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 76, - "debate_team": 80, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 576, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 76, - "debate_team": 80, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 577, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 75, - "debate_team": 79, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 578, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 75, - "debate_team": 79, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 579, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 75, - "debate_team": 79, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 580, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 75, - "debate_team": 79, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 581, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 75, - "debate_team": 80, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 582, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 75, - "debate_team": 80, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 583, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 75, - "debate_team": 80, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 584, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 75, - "debate_team": 80, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 585, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 74, - "debate_team": 79, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 586, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 74, - "debate_team": 79, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 587, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 74, - "debate_team": 79, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 588, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 74, - "debate_team": 79, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 589, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 74, - "debate_team": 80, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 590, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 74, - "debate_team": 80, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 591, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 74, - "debate_team": 80, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 592, - "fields": { - "ballot_submission": 40, - "debate_adjudicator": 74, - "debate_team": 80, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 593, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 81, - "debate_team": 81, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 594, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 81, - "debate_team": 81, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 595, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 81, - "debate_team": 81, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 596, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 81, - "debate_team": 81, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 597, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 81, - "debate_team": 82, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 598, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 81, - "debate_team": 82, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 599, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 81, - "debate_team": 82, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 600, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 81, - "debate_team": 82, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 601, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 80, - "debate_team": 81, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 602, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 80, - "debate_team": 81, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 603, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 80, - "debate_team": 81, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 604, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 80, - "debate_team": 81, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 605, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 80, - "debate_team": 82, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 606, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 80, - "debate_team": 82, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 607, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 80, - "debate_team": 82, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 608, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 80, - "debate_team": 82, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 609, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 82, - "debate_team": 81, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 610, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 82, - "debate_team": 81, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 611, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 82, - "debate_team": 81, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 612, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 82, - "debate_team": 81, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 613, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 82, - "debate_team": 82, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 614, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 82, - "debate_team": 82, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 615, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 82, - "debate_team": 82, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 616, - "fields": { - "ballot_submission": 41, - "debate_adjudicator": 82, - "debate_team": 82, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 617, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 88, - "debate_team": 83, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 618, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 88, - "debate_team": 83, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 619, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 88, - "debate_team": 83, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 620, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 88, - "debate_team": 83, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 621, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 88, - "debate_team": 84, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 622, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 88, - "debate_team": 84, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 623, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 88, - "debate_team": 84, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 624, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 88, - "debate_team": 84, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 625, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 86, - "debate_team": 83, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 626, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 86, - "debate_team": 83, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 627, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 86, - "debate_team": 83, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 628, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 86, - "debate_team": 83, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 629, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 86, - "debate_team": 84, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 630, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 86, - "debate_team": 84, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 631, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 86, - "debate_team": 84, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 632, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 86, - "debate_team": 84, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 633, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 87, - "debate_team": 83, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 634, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 87, - "debate_team": 83, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 635, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 87, - "debate_team": 83, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 636, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 87, - "debate_team": 83, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 637, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 87, - "debate_team": 84, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 638, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 87, - "debate_team": 84, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 639, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 87, - "debate_team": 84, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 640, - "fields": { - "ballot_submission": 42, - "debate_adjudicator": 87, - "debate_team": 84, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 641, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 83, - "debate_team": 85, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 642, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 83, - "debate_team": 85, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 643, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 83, - "debate_team": 85, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 644, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 83, - "debate_team": 85, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 645, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 83, - "debate_team": 86, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 646, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 83, - "debate_team": 86, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 647, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 83, - "debate_team": 86, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 648, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 83, - "debate_team": 86, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 649, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 85, - "debate_team": 85, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 650, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 85, - "debate_team": 85, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 651, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 85, - "debate_team": 85, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 652, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 85, - "debate_team": 85, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 653, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 85, - "debate_team": 86, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 654, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 85, - "debate_team": 86, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 655, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 85, - "debate_team": 86, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 656, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 85, - "debate_team": 86, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 657, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 84, - "debate_team": 85, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 658, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 84, - "debate_team": 85, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 659, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 84, - "debate_team": 85, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 660, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 84, - "debate_team": 85, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 661, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 84, - "debate_team": 86, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 662, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 84, - "debate_team": 86, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 663, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 84, - "debate_team": 86, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 664, - "fields": { - "ballot_submission": 43, - "debate_adjudicator": 84, - "debate_team": 86, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 665, - "fields": { - "ballot_submission": 44, - "debate_adjudicator": 71, - "debate_team": 87, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 666, - "fields": { - "ballot_submission": 44, - "debate_adjudicator": 71, - "debate_team": 87, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 667, - "fields": { - "ballot_submission": 44, - "debate_adjudicator": 71, - "debate_team": 87, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 668, - "fields": { - "ballot_submission": 44, - "debate_adjudicator": 71, - "debate_team": 87, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 669, - "fields": { - "ballot_submission": 44, - "debate_adjudicator": 71, - "debate_team": 88, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 670, - "fields": { - "ballot_submission": 44, - "debate_adjudicator": 71, - "debate_team": 88, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 671, - "fields": { - "ballot_submission": 44, - "debate_adjudicator": 71, - "debate_team": 88, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 672, - "fields": { - "ballot_submission": 44, - "debate_adjudicator": 71, - "debate_team": 88, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 673, - "fields": { - "ballot_submission": 45, - "debate_adjudicator": 72, - "debate_team": 89, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 674, - "fields": { - "ballot_submission": 45, - "debate_adjudicator": 72, - "debate_team": 89, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 675, - "fields": { - "ballot_submission": 45, - "debate_adjudicator": 72, - "debate_team": 89, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 676, - "fields": { - "ballot_submission": 45, - "debate_adjudicator": 72, - "debate_team": 89, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 677, - "fields": { - "ballot_submission": 45, - "debate_adjudicator": 72, - "debate_team": 90, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 678, - "fields": { - "ballot_submission": 45, - "debate_adjudicator": 72, - "debate_team": 90, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 679, - "fields": { - "ballot_submission": 45, - "debate_adjudicator": 72, - "debate_team": 90, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 680, - "fields": { - "ballot_submission": 45, - "debate_adjudicator": 72, - "debate_team": 90, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 681, - "fields": { - "ballot_submission": 46, - "debate_adjudicator": 68, - "debate_team": 91, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 682, - "fields": { - "ballot_submission": 46, - "debate_adjudicator": 68, - "debate_team": 91, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 683, - "fields": { - "ballot_submission": 46, - "debate_adjudicator": 68, - "debate_team": 91, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 684, - "fields": { - "ballot_submission": 46, - "debate_adjudicator": 68, - "debate_team": 91, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 685, - "fields": { - "ballot_submission": 46, - "debate_adjudicator": 68, - "debate_team": 92, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 686, - "fields": { - "ballot_submission": 46, - "debate_adjudicator": 68, - "debate_team": 92, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 687, - "fields": { - "ballot_submission": 46, - "debate_adjudicator": 68, - "debate_team": 92, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 688, - "fields": { - "ballot_submission": 46, - "debate_adjudicator": 68, - "debate_team": 92, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 689, - "fields": { - "ballot_submission": 47, - "debate_adjudicator": 70, - "debate_team": 93, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 690, - "fields": { - "ballot_submission": 47, - "debate_adjudicator": 70, - "debate_team": 93, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 691, - "fields": { - "ballot_submission": 47, - "debate_adjudicator": 70, - "debate_team": 93, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 692, - "fields": { - "ballot_submission": 47, - "debate_adjudicator": 70, - "debate_team": 93, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 693, - "fields": { - "ballot_submission": 47, - "debate_adjudicator": 70, - "debate_team": 94, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 694, - "fields": { - "ballot_submission": 47, - "debate_adjudicator": 70, - "debate_team": 94, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 695, - "fields": { - "ballot_submission": 47, - "debate_adjudicator": 70, - "debate_team": 94, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 696, - "fields": { - "ballot_submission": 47, - "debate_adjudicator": 70, - "debate_team": 94, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 697, - "fields": { - "ballot_submission": 48, - "debate_adjudicator": 69, - "debate_team": 95, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 698, - "fields": { - "ballot_submission": 48, - "debate_adjudicator": 69, - "debate_team": 95, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 699, - "fields": { - "ballot_submission": 48, - "debate_adjudicator": 69, - "debate_team": 95, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 700, - "fields": { - "ballot_submission": 48, - "debate_adjudicator": 69, - "debate_team": 95, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 701, - "fields": { - "ballot_submission": 48, - "debate_adjudicator": 69, - "debate_team": 96, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 702, - "fields": { - "ballot_submission": 48, - "debate_adjudicator": 69, - "debate_team": 96, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 703, - "fields": { - "ballot_submission": 48, - "debate_adjudicator": 69, - "debate_team": 96, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscorebyadj", - "pk": 704, - "fields": { - "ballot_submission": 48, - "debate_adjudicator": 69, - "debate_team": 96, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.teamscore", - "pk": 1, - "fields": { - "ballot_submission": 1, - "debate_team": 23, - "points": 0, - "margin": -2.5, - "win": false, - "score": 259.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 2, - "fields": { - "ballot_submission": 1, - "debate_team": 24, - "points": 1, - "margin": 2.5, - "win": true, - "score": 261.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 3, - "fields": { - "ballot_submission": 2, - "debate_team": 21, - "points": 0, - "margin": -0.5, - "win": false, - "score": 266.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 4, - "fields": { - "ballot_submission": 2, - "debate_team": 22, - "points": 1, - "margin": 0.5, - "win": true, - "score": 267.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 5, - "fields": { - "ballot_submission": 3, - "debate_team": 19, - "points": 0, - "margin": -3.5, - "win": false, - "score": 261.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 6, - "fields": { - "ballot_submission": 3, - "debate_team": 20, - "points": 1, - "margin": 3.5, - "win": true, - "score": 265.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 7, - "fields": { - "ballot_submission": 4, - "debate_team": 17, - "points": 0, - "margin": -4.5, - "win": false, - "score": 257.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 8, - "fields": { - "ballot_submission": 4, - "debate_team": 18, - "points": 1, - "margin": 4.5, - "win": true, - "score": 262.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 9, - "fields": { - "ballot_submission": 5, - "debate_team": 15, - "points": 0, - "margin": -0.5, - "win": false, - "score": 260.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 10, - "fields": { - "ballot_submission": 5, - "debate_team": 16, - "points": 1, - "margin": 0.5, - "win": true, - "score": 261.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 11, - "fields": { - "ballot_submission": 6, - "debate_team": 13, - "points": 0, - "margin": -7.5, - "win": false, - "score": 255.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 12, - "fields": { - "ballot_submission": 6, - "debate_team": 14, - "points": 1, - "margin": 7.5, - "win": true, - "score": 263.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 13, - "fields": { - "ballot_submission": 7, - "debate_team": 11, - "points": 1, - "margin": 2.5, - "win": true, - "score": 267.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 14, - "fields": { - "ballot_submission": 7, - "debate_team": 12, - "points": 0, - "margin": -2.5, - "win": false, - "score": 264.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 15, - "fields": { - "ballot_submission": 8, - "debate_team": 9, - "points": 1, - "margin": 4.66666666666669, - "win": true, - "score": 266.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 16, - "fields": { - "ballot_submission": 8, - "debate_team": 10, - "points": 0, - "margin": -4.66666666666669, - "win": false, - "score": 261.333333333333, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 17, - "fields": { - "ballot_submission": 9, - "debate_team": 7, - "points": 1, - "margin": 5.0, - "win": true, - "score": 266.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 18, - "fields": { - "ballot_submission": 9, - "debate_team": 8, - "points": 0, - "margin": -5.0, - "win": false, - "score": 261.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 19, - "fields": { - "ballot_submission": 10, - "debate_team": 5, - "points": 1, - "margin": 5.33333333333331, - "win": true, - "score": 266.833333333333, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 20, - "fields": { - "ballot_submission": 10, - "debate_team": 6, - "points": 0, - "margin": -5.33333333333331, - "win": false, - "score": 261.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 21, - "fields": { - "ballot_submission": 11, - "debate_team": 3, - "points": 0, - "margin": -2.75, - "win": false, - "score": 261.75, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 22, - "fields": { - "ballot_submission": 11, - "debate_team": 4, - "points": 1, - "margin": 2.75, - "win": true, - "score": 264.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 23, - "fields": { - "ballot_submission": 12, - "debate_team": 1, - "points": 1, - "margin": 1.25, - "win": true, - "score": 266.25, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 24, - "fields": { - "ballot_submission": 12, - "debate_team": 2, - "points": 0, - "margin": -1.25, - "win": false, - "score": 265.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 25, - "fields": { - "ballot_submission": 13, - "debate_team": 47, - "points": 1, - "margin": 1.83333333333331, - "win": true, - "score": 264.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 26, - "fields": { - "ballot_submission": 13, - "debate_team": 48, - "points": 0, - "margin": -1.83333333333331, - "win": false, - "score": 262.166666666667, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 27, - "fields": { - "ballot_submission": 14, - "debate_team": 45, - "points": 1, - "margin": 0.5, - "win": true, - "score": 261.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 28, - "fields": { - "ballot_submission": 14, - "debate_team": 46, - "points": 0, - "margin": -0.5, - "win": false, - "score": 261.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 29, - "fields": { - "ballot_submission": 15, - "debate_team": 43, - "points": 0, - "margin": -1.75, - "win": false, - "score": 261.25, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 30, - "fields": { - "ballot_submission": 15, - "debate_team": 44, - "points": 1, - "margin": 1.75, - "win": true, - "score": 263.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 31, - "fields": { - "ballot_submission": 16, - "debate_team": 41, - "points": 1, - "margin": 2.0, - "win": true, - "score": 263.666666666667, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 32, - "fields": { - "ballot_submission": 16, - "debate_team": 42, - "points": 0, - "margin": -2.0, - "win": false, - "score": 261.666666666667, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 33, - "fields": { - "ballot_submission": 17, - "debate_team": 39, - "points": 0, - "margin": -2.0, - "win": false, - "score": 260.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 34, - "fields": { - "ballot_submission": 17, - "debate_team": 40, - "points": 1, - "margin": 2.0, - "win": true, - "score": 262.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 35, - "fields": { - "ballot_submission": 18, - "debate_team": 37, - "points": 1, - "margin": 0.5, - "win": true, - "score": 263.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 36, - "fields": { - "ballot_submission": 18, - "debate_team": 38, - "points": 0, - "margin": -0.5, - "win": false, - "score": 262.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 37, - "fields": { - "ballot_submission": 19, - "debate_team": 35, - "points": 1, - "margin": 3.0, - "win": true, - "score": 265.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 38, - "fields": { - "ballot_submission": 19, - "debate_team": 36, - "points": 0, - "margin": -3.0, - "win": false, - "score": 262.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 39, - "fields": { - "ballot_submission": 20, - "debate_team": 33, - "points": 1, - "margin": 2.0, - "win": true, - "score": 261.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 40, - "fields": { - "ballot_submission": 20, - "debate_team": 34, - "points": 0, - "margin": -2.0, - "win": false, - "score": 259.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 41, - "fields": { - "ballot_submission": 21, - "debate_team": 31, - "points": 0, - "margin": -0.5, - "win": false, - "score": 264.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 42, - "fields": { - "ballot_submission": 21, - "debate_team": 32, - "points": 1, - "margin": 0.5, - "win": true, - "score": 265.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 43, - "fields": { - "ballot_submission": 22, - "debate_team": 29, - "points": 0, - "margin": -6.0, - "win": false, - "score": 260.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 44, - "fields": { - "ballot_submission": 22, - "debate_team": 30, - "points": 1, - "margin": 6.0, - "win": true, - "score": 266.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 45, - "fields": { - "ballot_submission": 23, - "debate_team": 27, - "points": 0, - "margin": -1.5, - "win": false, - "score": 261.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 46, - "fields": { - "ballot_submission": 23, - "debate_team": 28, - "points": 1, - "margin": 1.5, - "win": true, - "score": 262.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 47, - "fields": { - "ballot_submission": 24, - "debate_team": 25, - "points": 1, - "margin": 7.5, - "win": true, - "score": 262.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 48, - "fields": { - "ballot_submission": 24, - "debate_team": 26, - "points": 0, - "margin": -7.5, - "win": false, - "score": 254.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 49, - "fields": { - "ballot_submission": 25, - "debate_team": 49, - "points": 0, - "margin": -2.5, - "win": false, - "score": 261.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 50, - "fields": { - "ballot_submission": 25, - "debate_team": 50, - "points": 1, - "margin": 2.5, - "win": true, - "score": 264.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 51, - "fields": { - "ballot_submission": 26, - "debate_team": 51, - "points": 0, - "margin": -2.5, - "win": false, - "score": 259.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 52, - "fields": { - "ballot_submission": 26, - "debate_team": 52, - "points": 1, - "margin": 2.5, - "win": true, - "score": 262.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 53, - "fields": { - "ballot_submission": 27, - "debate_team": 53, - "points": 0, - "margin": -4.0, - "win": false, - "score": 259.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 54, - "fields": { - "ballot_submission": 27, - "debate_team": 54, - "points": 1, - "margin": 4.0, - "win": true, - "score": 263.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 55, - "fields": { - "ballot_submission": 28, - "debate_team": 55, - "points": 0, - "margin": -3.25, - "win": false, - "score": 260.75, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 56, - "fields": { - "ballot_submission": 28, - "debate_team": 56, - "points": 1, - "margin": 3.25, - "win": true, - "score": 264.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 57, - "fields": { - "ballot_submission": 29, - "debate_team": 57, - "points": 0, - "margin": -5.25, - "win": false, - "score": 262.25, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 58, - "fields": { - "ballot_submission": 29, - "debate_team": 58, - "points": 1, - "margin": 5.25, - "win": true, - "score": 267.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 59, - "fields": { - "ballot_submission": 30, - "debate_team": 59, - "points": 1, - "margin": 7.0, - "win": true, - "score": 266.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 60, - "fields": { - "ballot_submission": 30, - "debate_team": 60, - "points": 0, - "margin": -7.0, - "win": false, - "score": 259.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 61, - "fields": { - "ballot_submission": 31, - "debate_team": 61, - "points": 0, - "margin": -5.5, - "win": false, - "score": 260.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 62, - "fields": { - "ballot_submission": 31, - "debate_team": 62, - "points": 1, - "margin": 5.5, - "win": true, - "score": 266.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 63, - "fields": { - "ballot_submission": 32, - "debate_team": 63, - "points": 1, - "margin": 5.5, - "win": true, - "score": 258.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 64, - "fields": { - "ballot_submission": 32, - "debate_team": 64, - "points": 0, - "margin": -5.5, - "win": false, - "score": 253.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 65, - "fields": { - "ballot_submission": 33, - "debate_team": 65, - "points": 0, - "margin": -6.5, - "win": false, - "score": 255.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 66, - "fields": { - "ballot_submission": 33, - "debate_team": 66, - "points": 1, - "margin": 6.5, - "win": true, - "score": 262.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 67, - "fields": { - "ballot_submission": 34, - "debate_team": 67, - "points": 1, - "margin": 7.75, - "win": true, - "score": 266.75, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 68, - "fields": { - "ballot_submission": 34, - "debate_team": 68, - "points": 0, - "margin": -7.75, - "win": false, - "score": 259.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 69, - "fields": { - "ballot_submission": 35, - "debate_team": 69, - "points": 1, - "margin": 4.25, - "win": true, - "score": 261.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 70, - "fields": { - "ballot_submission": 35, - "debate_team": 70, - "points": 0, - "margin": -4.25, - "win": false, - "score": 257.25, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 71, - "fields": { - "ballot_submission": 36, - "debate_team": 71, - "points": 0, - "margin": -1.5, - "win": false, - "score": 261.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 72, - "fields": { - "ballot_submission": 36, - "debate_team": 72, - "points": 1, - "margin": 1.5, - "win": true, - "score": 262.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 73, - "fields": { - "ballot_submission": 37, - "debate_team": 73, - "points": 0, - "margin": -5.5, - "win": false, - "score": 259.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 74, - "fields": { - "ballot_submission": 37, - "debate_team": 74, - "points": 1, - "margin": 5.5, - "win": true, - "score": 264.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 75, - "fields": { - "ballot_submission": 38, - "debate_team": 75, - "points": 0, - "margin": -4.0, - "win": false, - "score": 258.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 76, - "fields": { - "ballot_submission": 38, - "debate_team": 76, - "points": 1, - "margin": 4.0, - "win": true, - "score": 262.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 77, - "fields": { - "ballot_submission": 39, - "debate_team": 77, - "points": 0, - "margin": -6.0, - "win": false, - "score": 256.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 78, - "fields": { - "ballot_submission": 39, - "debate_team": 78, - "points": 1, - "margin": 6.0, - "win": true, - "score": 262.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 79, - "fields": { - "ballot_submission": 40, - "debate_team": 79, - "points": 0, - "margin": -2.33333333333337, - "win": false, - "score": 261.833333333333, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 80, - "fields": { - "ballot_submission": 40, - "debate_team": 80, - "points": 1, - "margin": 2.33333333333337, - "win": true, - "score": 264.166666666667, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 81, - "fields": { - "ballot_submission": 41, - "debate_team": 81, - "points": 0, - "margin": -4.25, - "win": false, - "score": 262.25, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 82, - "fields": { - "ballot_submission": 41, - "debate_team": 82, - "points": 1, - "margin": 4.25, - "win": true, - "score": 266.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 83, - "fields": { - "ballot_submission": 42, - "debate_team": 83, - "points": 1, - "margin": 3.16666666666669, - "win": true, - "score": 264.666666666667, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 84, - "fields": { - "ballot_submission": 42, - "debate_team": 84, - "points": 0, - "margin": -3.16666666666669, - "win": false, - "score": 261.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 85, - "fields": { - "ballot_submission": 43, - "debate_team": 85, - "points": 0, - "margin": -5.83333333333331, - "win": false, - "score": 260.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 86, - "fields": { - "ballot_submission": 43, - "debate_team": 86, - "points": 1, - "margin": 5.83333333333331, - "win": true, - "score": 266.333333333333, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 87, - "fields": { - "ballot_submission": 44, - "debate_team": 87, - "points": 1, - "margin": 10.0, - "win": true, - "score": 267.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 88, - "fields": { - "ballot_submission": 44, - "debate_team": 88, - "points": 0, - "margin": -10.0, - "win": false, - "score": 257.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 89, - "fields": { - "ballot_submission": 45, - "debate_team": 89, - "points": 0, - "margin": -1.0, - "win": false, - "score": 262.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 90, - "fields": { - "ballot_submission": 45, - "debate_team": 90, - "points": 1, - "margin": 1.0, - "win": true, - "score": 263.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 91, - "fields": { - "ballot_submission": 46, - "debate_team": 91, - "points": 0, - "margin": -1.0, - "win": false, - "score": 268.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 92, - "fields": { - "ballot_submission": 46, - "debate_team": 92, - "points": 1, - "margin": 1.0, - "win": true, - "score": 269.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 93, - "fields": { - "ballot_submission": 47, - "debate_team": 93, - "points": 0, - "margin": -7.5, - "win": false, - "score": 258.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 94, - "fields": { - "ballot_submission": 47, - "debate_team": 94, - "points": 1, - "margin": 7.5, - "win": true, - "score": 266.0, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 95, - "fields": { - "ballot_submission": 48, - "debate_team": 95, - "points": 1, - "margin": 8.0, - "win": true, - "score": 266.5, - "forfeit": false - } - }, - { - "model": "results.teamscore", - "pk": 96, - "fields": { - "ballot_submission": 48, - "debate_team": 96, - "points": 0, - "margin": -8.0, - "win": false, - "score": 258.5, - "forfeit": false - } - }, - { - "model": "results.speakerscore", - "pk": 1, - "fields": { - "ballot_submission": 1, - "debate_team": 23, - "speaker": 40, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 2, - "fields": { - "ballot_submission": 1, - "debate_team": 23, - "speaker": 41, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 3, - "fields": { - "ballot_submission": 1, - "debate_team": 23, - "speaker": 42, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 4, - "fields": { - "ballot_submission": 1, - "debate_team": 23, - "speaker": 40, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 5, - "fields": { - "ballot_submission": 1, - "debate_team": 24, - "speaker": 54, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 6, - "fields": { - "ballot_submission": 1, - "debate_team": 24, - "speaker": 53, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 7, - "fields": { - "ballot_submission": 1, - "debate_team": 24, - "speaker": 52, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 8, - "fields": { - "ballot_submission": 1, - "debate_team": 24, - "speaker": 54, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 9, - "fields": { - "ballot_submission": 2, - "debate_team": 21, - "speaker": 10, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 10, - "fields": { - "ballot_submission": 2, - "debate_team": 21, - "speaker": 11, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 11, - "fields": { - "ballot_submission": 2, - "debate_team": 21, - "speaker": 12, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 12, - "fields": { - "ballot_submission": 2, - "debate_team": 21, - "speaker": 10, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 13, - "fields": { - "ballot_submission": 2, - "debate_team": 22, - "speaker": 23, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 14, - "fields": { - "ballot_submission": 2, - "debate_team": 22, - "speaker": 24, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 15, - "fields": { - "ballot_submission": 2, - "debate_team": 22, - "speaker": 22, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 16, - "fields": { - "ballot_submission": 2, - "debate_team": 22, - "speaker": 23, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 17, - "fields": { - "ballot_submission": 3, - "debate_team": 19, - "speaker": 69, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 18, - "fields": { - "ballot_submission": 3, - "debate_team": 19, - "speaker": 68, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 19, - "fields": { - "ballot_submission": 3, - "debate_team": 19, - "speaker": 67, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 20, - "fields": { - "ballot_submission": 3, - "debate_team": 19, - "speaker": 69, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 21, - "fields": { - "ballot_submission": 3, - "debate_team": 20, - "speaker": 33, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 22, - "fields": { - "ballot_submission": 3, - "debate_team": 20, - "speaker": 31, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 23, - "fields": { - "ballot_submission": 3, - "debate_team": 20, - "speaker": 32, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 24, - "fields": { - "ballot_submission": 3, - "debate_team": 20, - "speaker": 33, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 25, - "fields": { - "ballot_submission": 4, - "debate_team": 17, - "speaker": 49, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 26, - "fields": { - "ballot_submission": 4, - "debate_team": 17, - "speaker": 50, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 27, - "fields": { - "ballot_submission": 4, - "debate_team": 17, - "speaker": 51, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 28, - "fields": { - "ballot_submission": 4, - "debate_team": 17, - "speaker": 49, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 29, - "fields": { - "ballot_submission": 4, - "debate_team": 18, - "speaker": 1, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 30, - "fields": { - "ballot_submission": 4, - "debate_team": 18, - "speaker": 3, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 31, - "fields": { - "ballot_submission": 4, - "debate_team": 18, - "speaker": 2, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 32, - "fields": { - "ballot_submission": 4, - "debate_team": 18, - "speaker": 1, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 33, - "fields": { - "ballot_submission": 5, - "debate_team": 15, - "speaker": 55, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 34, - "fields": { - "ballot_submission": 5, - "debate_team": 15, - "speaker": 57, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 35, - "fields": { - "ballot_submission": 5, - "debate_team": 15, - "speaker": 56, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 36, - "fields": { - "ballot_submission": 5, - "debate_team": 15, - "speaker": 55, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 37, - "fields": { - "ballot_submission": 5, - "debate_team": 16, - "speaker": 45, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 38, - "fields": { - "ballot_submission": 5, - "debate_team": 16, - "speaker": 44, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 39, - "fields": { - "ballot_submission": 5, - "debate_team": 16, - "speaker": 43, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 40, - "fields": { - "ballot_submission": 5, - "debate_team": 16, - "speaker": 45, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 41, - "fields": { - "ballot_submission": 6, - "debate_team": 13, - "speaker": 34, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 42, - "fields": { - "ballot_submission": 6, - "debate_team": 13, - "speaker": 35, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 43, - "fields": { - "ballot_submission": 6, - "debate_team": 13, - "speaker": 36, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 44, - "fields": { - "ballot_submission": 6, - "debate_team": 13, - "speaker": 34, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 45, - "fields": { - "ballot_submission": 6, - "debate_team": 14, - "speaker": 48, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 46, - "fields": { - "ballot_submission": 6, - "debate_team": 14, - "speaker": 46, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 47, - "fields": { - "ballot_submission": 6, - "debate_team": 14, - "speaker": 47, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 48, - "fields": { - "ballot_submission": 6, - "debate_team": 14, - "speaker": 48, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 49, - "fields": { - "ballot_submission": 7, - "debate_team": 11, - "speaker": 15, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 50, - "fields": { - "ballot_submission": 7, - "debate_team": 11, - "speaker": 13, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 51, - "fields": { - "ballot_submission": 7, - "debate_team": 11, - "speaker": 14, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 52, - "fields": { - "ballot_submission": 7, - "debate_team": 11, - "speaker": 15, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 53, - "fields": { - "ballot_submission": 7, - "debate_team": 12, - "speaker": 29, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 54, - "fields": { - "ballot_submission": 7, - "debate_team": 12, - "speaker": 28, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 55, - "fields": { - "ballot_submission": 7, - "debate_team": 12, - "speaker": 30, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 56, - "fields": { - "ballot_submission": 7, - "debate_team": 12, - "speaker": 29, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 57, - "fields": { - "ballot_submission": 8, - "debate_team": 9, - "speaker": 17, - "score": 76.6666666666667, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 58, - "fields": { - "ballot_submission": 8, - "debate_team": 9, - "speaker": 16, - "score": 75.6666666666667, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 59, - "fields": { - "ballot_submission": 8, - "debate_team": 9, - "speaker": 18, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 60, - "fields": { - "ballot_submission": 8, - "debate_team": 9, - "speaker": 17, - "score": 37.6666666666667, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 61, - "fields": { - "ballot_submission": 8, - "debate_team": 10, - "speaker": 64, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 62, - "fields": { - "ballot_submission": 8, - "debate_team": 10, - "speaker": 66, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 63, - "fields": { - "ballot_submission": 8, - "debate_team": 10, - "speaker": 65, - "score": 74.3333333333333, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 64, - "fields": { - "ballot_submission": 8, - "debate_team": 10, - "speaker": 64, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 65, - "fields": { - "ballot_submission": 9, - "debate_team": 7, - "speaker": 21, - "score": 77.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 66, - "fields": { - "ballot_submission": 9, - "debate_team": 7, - "speaker": 20, - "score": 74.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 67, - "fields": { - "ballot_submission": 9, - "debate_team": 7, - "speaker": 19, - "score": 76.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 68, - "fields": { - "ballot_submission": 9, - "debate_team": 7, - "speaker": 21, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 69, - "fields": { - "ballot_submission": 9, - "debate_team": 8, - "speaker": 72, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 70, - "fields": { - "ballot_submission": 9, - "debate_team": 8, - "speaker": 71, - "score": 73.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 71, - "fields": { - "ballot_submission": 9, - "debate_team": 8, - "speaker": 70, - "score": 74.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 72, - "fields": { - "ballot_submission": 9, - "debate_team": 8, - "speaker": 72, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 73, - "fields": { - "ballot_submission": 10, - "debate_team": 5, - "speaker": 5, - "score": 75.6666666666667, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 74, - "fields": { - "ballot_submission": 10, - "debate_team": 5, - "speaker": 4, - "score": 77.6666666666667, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 75, - "fields": { - "ballot_submission": 10, - "debate_team": 5, - "speaker": 6, - "score": 75.6666666666667, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 76, - "fields": { - "ballot_submission": 10, - "debate_team": 5, - "speaker": 5, - "score": 37.8333333333333, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 77, - "fields": { - "ballot_submission": 10, - "debate_team": 6, - "speaker": 38, - "score": 75.3333333333333, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 78, - "fields": { - "ballot_submission": 10, - "debate_team": 6, - "speaker": 37, - "score": 74.3333333333333, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 79, - "fields": { - "ballot_submission": 10, - "debate_team": 6, - "speaker": 39, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 80, - "fields": { - "ballot_submission": 10, - "debate_team": 6, - "speaker": 38, - "score": 36.8333333333333, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 81, - "fields": { - "ballot_submission": 11, - "debate_team": 3, - "speaker": 59, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 82, - "fields": { - "ballot_submission": 11, - "debate_team": 3, - "speaker": 58, - "score": 74.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 83, - "fields": { - "ballot_submission": 11, - "debate_team": 3, - "speaker": 60, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 84, - "fields": { - "ballot_submission": 11, - "debate_team": 3, - "speaker": 59, - "score": 36.25, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 85, - "fields": { - "ballot_submission": 11, - "debate_team": 4, - "speaker": 25, - "score": 76.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 86, - "fields": { - "ballot_submission": 11, - "debate_team": 4, - "speaker": 27, - "score": 74.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 87, - "fields": { - "ballot_submission": 11, - "debate_team": 4, - "speaker": 26, - "score": 75.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 88, - "fields": { - "ballot_submission": 11, - "debate_team": 4, - "speaker": 25, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 89, - "fields": { - "ballot_submission": 12, - "debate_team": 1, - "speaker": 7, - "score": 77.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 90, - "fields": { - "ballot_submission": 12, - "debate_team": 1, - "speaker": 8, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 91, - "fields": { - "ballot_submission": 12, - "debate_team": 1, - "speaker": 9, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 92, - "fields": { - "ballot_submission": 12, - "debate_team": 1, - "speaker": 7, - "score": 37.75, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 93, - "fields": { - "ballot_submission": 12, - "debate_team": 2, - "speaker": 61, - "score": 77.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 94, - "fields": { - "ballot_submission": 12, - "debate_team": 2, - "speaker": 63, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 95, - "fields": { - "ballot_submission": 12, - "debate_team": 2, - "speaker": 62, - "score": 75.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 96, - "fields": { - "ballot_submission": 12, - "debate_team": 2, - "speaker": 61, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 97, - "fields": { - "ballot_submission": 13, - "debate_team": 47, - "speaker": 29, - "score": 74.6666666666667, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 98, - "fields": { - "ballot_submission": 13, - "debate_team": 47, - "speaker": 28, - "score": 76.3333333333333, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 99, - "fields": { - "ballot_submission": 13, - "debate_team": 47, - "speaker": 30, - "score": 76.3333333333333, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 100, - "fields": { - "ballot_submission": 13, - "debate_team": 47, - "speaker": 29, - "score": 36.6666666666667, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 101, - "fields": { - "ballot_submission": 13, - "debate_team": 48, - "speaker": 55, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 102, - "fields": { - "ballot_submission": 13, - "debate_team": 48, - "speaker": 57, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 103, - "fields": { - "ballot_submission": 13, - "debate_team": 48, - "speaker": 56, - "score": 76.3333333333333, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 104, - "fields": { - "ballot_submission": 13, - "debate_team": 48, - "speaker": 55, - "score": 37.8333333333333, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 105, - "fields": { - "ballot_submission": 14, - "debate_team": 45, - "speaker": 25, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 106, - "fields": { - "ballot_submission": 14, - "debate_team": 45, - "speaker": 27, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 107, - "fields": { - "ballot_submission": 14, - "debate_team": 45, - "speaker": 26, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 108, - "fields": { - "ballot_submission": 14, - "debate_team": 45, - "speaker": 25, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 109, - "fields": { - "ballot_submission": 14, - "debate_team": 46, - "speaker": 23, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 110, - "fields": { - "ballot_submission": 14, - "debate_team": 46, - "speaker": 24, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 111, - "fields": { - "ballot_submission": 14, - "debate_team": 46, - "speaker": 22, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 112, - "fields": { - "ballot_submission": 14, - "debate_team": 46, - "speaker": 23, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 113, - "fields": { - "ballot_submission": 15, - "debate_team": 43, - "speaker": 40, - "score": 73.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 114, - "fields": { - "ballot_submission": 15, - "debate_team": 43, - "speaker": 41, - "score": 72.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 115, - "fields": { - "ballot_submission": 15, - "debate_team": 43, - "speaker": 42, - "score": 77.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 116, - "fields": { - "ballot_submission": 15, - "debate_team": 43, - "speaker": 40, - "score": 37.75, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 117, - "fields": { - "ballot_submission": 15, - "debate_team": 44, - "speaker": 59, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 118, - "fields": { - "ballot_submission": 15, - "debate_team": 44, - "speaker": 58, - "score": 74.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 119, - "fields": { - "ballot_submission": 15, - "debate_team": 44, - "speaker": 60, - "score": 75.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 120, - "fields": { - "ballot_submission": 15, - "debate_team": 44, - "speaker": 59, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 121, - "fields": { - "ballot_submission": 16, - "debate_team": 41, - "speaker": 49, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 122, - "fields": { - "ballot_submission": 16, - "debate_team": 41, - "speaker": 50, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 123, - "fields": { - "ballot_submission": 16, - "debate_team": 41, - "speaker": 51, - "score": 75.6666666666667, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 124, - "fields": { - "ballot_submission": 16, - "debate_team": 41, - "speaker": 49, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 125, - "fields": { - "ballot_submission": 16, - "debate_team": 42, - "speaker": 69, - "score": 75.3333333333333, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 126, - "fields": { - "ballot_submission": 16, - "debate_team": 42, - "speaker": 68, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 127, - "fields": { - "ballot_submission": 16, - "debate_team": 42, - "speaker": 67, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 128, - "fields": { - "ballot_submission": 16, - "debate_team": 42, - "speaker": 69, - "score": 37.3333333333333, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 129, - "fields": { - "ballot_submission": 17, - "debate_team": 39, - "speaker": 72, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 130, - "fields": { - "ballot_submission": 17, - "debate_team": 39, - "speaker": 71, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 131, - "fields": { - "ballot_submission": 17, - "debate_team": 39, - "speaker": 70, - "score": 74.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 132, - "fields": { - "ballot_submission": 17, - "debate_team": 39, - "speaker": 72, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 133, - "fields": { - "ballot_submission": 17, - "debate_team": 40, - "speaker": 61, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 134, - "fields": { - "ballot_submission": 17, - "debate_team": 40, - "speaker": 63, - "score": 75.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 135, - "fields": { - "ballot_submission": 17, - "debate_team": 40, - "speaker": 62, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 136, - "fields": { - "ballot_submission": 17, - "debate_team": 40, - "speaker": 61, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 137, - "fields": { - "ballot_submission": 18, - "debate_team": 37, - "speaker": 33, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 138, - "fields": { - "ballot_submission": 18, - "debate_team": 37, - "speaker": 31, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 139, - "fields": { - "ballot_submission": 18, - "debate_team": 37, - "speaker": 32, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 140, - "fields": { - "ballot_submission": 18, - "debate_team": 37, - "speaker": 33, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 141, - "fields": { - "ballot_submission": 18, - "debate_team": 38, - "speaker": 15, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 142, - "fields": { - "ballot_submission": 18, - "debate_team": 38, - "speaker": 13, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 143, - "fields": { - "ballot_submission": 18, - "debate_team": 38, - "speaker": 14, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 144, - "fields": { - "ballot_submission": 18, - "debate_team": 38, - "speaker": 15, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 145, - "fields": { - "ballot_submission": 19, - "debate_team": 35, - "speaker": 1, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 146, - "fields": { - "ballot_submission": 19, - "debate_team": 35, - "speaker": 3, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 147, - "fields": { - "ballot_submission": 19, - "debate_team": 35, - "speaker": 2, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 148, - "fields": { - "ballot_submission": 19, - "debate_team": 35, - "speaker": 1, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 149, - "fields": { - "ballot_submission": 19, - "debate_team": 36, - "speaker": 17, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 150, - "fields": { - "ballot_submission": 19, - "debate_team": 36, - "speaker": 16, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 151, - "fields": { - "ballot_submission": 19, - "debate_team": 36, - "speaker": 18, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 152, - "fields": { - "ballot_submission": 19, - "debate_team": 36, - "speaker": 17, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 153, - "fields": { - "ballot_submission": 20, - "debate_team": 33, - "speaker": 54, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 154, - "fields": { - "ballot_submission": 20, - "debate_team": 33, - "speaker": 53, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 155, - "fields": { - "ballot_submission": 20, - "debate_team": 33, - "speaker": 52, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 156, - "fields": { - "ballot_submission": 20, - "debate_team": 33, - "speaker": 54, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 157, - "fields": { - "ballot_submission": 20, - "debate_team": 34, - "speaker": 7, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 158, - "fields": { - "ballot_submission": 20, - "debate_team": 34, - "speaker": 8, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 159, - "fields": { - "ballot_submission": 20, - "debate_team": 34, - "speaker": 9, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 160, - "fields": { - "ballot_submission": 20, - "debate_team": 34, - "speaker": 7, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 161, - "fields": { - "ballot_submission": 21, - "debate_team": 31, - "speaker": 64, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 162, - "fields": { - "ballot_submission": 21, - "debate_team": 31, - "speaker": 66, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 163, - "fields": { - "ballot_submission": 21, - "debate_team": 31, - "speaker": 65, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 164, - "fields": { - "ballot_submission": 21, - "debate_team": 31, - "speaker": 64, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 165, - "fields": { - "ballot_submission": 21, - "debate_team": 32, - "speaker": 10, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 166, - "fields": { - "ballot_submission": 21, - "debate_team": 32, - "speaker": 11, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 167, - "fields": { - "ballot_submission": 21, - "debate_team": 32, - "speaker": 12, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 168, - "fields": { - "ballot_submission": 21, - "debate_team": 32, - "speaker": 10, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 169, - "fields": { - "ballot_submission": 22, - "debate_team": 29, - "speaker": 45, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 170, - "fields": { - "ballot_submission": 22, - "debate_team": 29, - "speaker": 44, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 171, - "fields": { - "ballot_submission": 22, - "debate_team": 29, - "speaker": 43, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 172, - "fields": { - "ballot_submission": 22, - "debate_team": 29, - "speaker": 45, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 173, - "fields": { - "ballot_submission": 22, - "debate_team": 30, - "speaker": 21, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 174, - "fields": { - "ballot_submission": 22, - "debate_team": 30, - "speaker": 20, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 175, - "fields": { - "ballot_submission": 22, - "debate_team": 30, - "speaker": 19, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 176, - "fields": { - "ballot_submission": 22, - "debate_team": 30, - "speaker": 21, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 177, - "fields": { - "ballot_submission": 23, - "debate_team": 27, - "speaker": 38, - "score": 74.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 178, - "fields": { - "ballot_submission": 23, - "debate_team": 27, - "speaker": 37, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 179, - "fields": { - "ballot_submission": 23, - "debate_team": 27, - "speaker": 39, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 180, - "fields": { - "ballot_submission": 23, - "debate_team": 27, - "speaker": 38, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 181, - "fields": { - "ballot_submission": 23, - "debate_team": 28, - "speaker": 34, - "score": 76.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 182, - "fields": { - "ballot_submission": 23, - "debate_team": 28, - "speaker": 35, - "score": 74.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 183, - "fields": { - "ballot_submission": 23, - "debate_team": 28, - "speaker": 36, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 184, - "fields": { - "ballot_submission": 23, - "debate_team": 28, - "speaker": 34, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 185, - "fields": { - "ballot_submission": 24, - "debate_team": 25, - "speaker": 48, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 186, - "fields": { - "ballot_submission": 24, - "debate_team": 25, - "speaker": 46, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 187, - "fields": { - "ballot_submission": 24, - "debate_team": 25, - "speaker": 47, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 188, - "fields": { - "ballot_submission": 24, - "debate_team": 25, - "speaker": 48, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 189, - "fields": { - "ballot_submission": 24, - "debate_team": 26, - "speaker": 5, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 190, - "fields": { - "ballot_submission": 24, - "debate_team": 26, - "speaker": 4, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 191, - "fields": { - "ballot_submission": 24, - "debate_team": 26, - "speaker": 6, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 192, - "fields": { - "ballot_submission": 24, - "debate_team": 26, - "speaker": 5, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 193, - "fields": { - "ballot_submission": 25, - "debate_team": 49, - "speaker": 7, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 194, - "fields": { - "ballot_submission": 25, - "debate_team": 49, - "speaker": 8, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 195, - "fields": { - "ballot_submission": 25, - "debate_team": 49, - "speaker": 9, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 196, - "fields": { - "ballot_submission": 25, - "debate_team": 49, - "speaker": 7, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 197, - "fields": { - "ballot_submission": 25, - "debate_team": 50, - "speaker": 10, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 198, - "fields": { - "ballot_submission": 25, - "debate_team": 50, - "speaker": 11, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 199, - "fields": { - "ballot_submission": 25, - "debate_team": 50, - "speaker": 12, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 200, - "fields": { - "ballot_submission": 25, - "debate_team": 50, - "speaker": 10, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 201, - "fields": { - "ballot_submission": 26, - "debate_team": 51, - "speaker": 1, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 202, - "fields": { - "ballot_submission": 26, - "debate_team": 51, - "speaker": 3, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 203, - "fields": { - "ballot_submission": 26, - "debate_team": 51, - "speaker": 2, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 204, - "fields": { - "ballot_submission": 26, - "debate_team": 51, - "speaker": 1, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 205, - "fields": { - "ballot_submission": 26, - "debate_team": 52, - "speaker": 54, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 206, - "fields": { - "ballot_submission": 26, - "debate_team": 52, - "speaker": 53, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 207, - "fields": { - "ballot_submission": 26, - "debate_team": 52, - "speaker": 52, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 208, - "fields": { - "ballot_submission": 26, - "debate_team": 52, - "speaker": 54, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 209, - "fields": { - "ballot_submission": 27, - "debate_team": 53, - "speaker": 45, - "score": 74.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 210, - "fields": { - "ballot_submission": 27, - "debate_team": 53, - "speaker": 44, - "score": 73.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 211, - "fields": { - "ballot_submission": 27, - "debate_team": 53, - "speaker": 43, - "score": 72.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 212, - "fields": { - "ballot_submission": 27, - "debate_team": 53, - "speaker": 45, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 213, - "fields": { - "ballot_submission": 27, - "debate_team": 54, - "speaker": 17, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 214, - "fields": { - "ballot_submission": 27, - "debate_team": 54, - "speaker": 16, - "score": 77.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 215, - "fields": { - "ballot_submission": 27, - "debate_team": 54, - "speaker": 18, - "score": 73.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 216, - "fields": { - "ballot_submission": 27, - "debate_team": 54, - "speaker": 17, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 217, - "fields": { - "ballot_submission": 28, - "debate_team": 55, - "speaker": 61, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 218, - "fields": { - "ballot_submission": 28, - "debate_team": 55, - "speaker": 63, - "score": 73.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 219, - "fields": { - "ballot_submission": 28, - "debate_team": 55, - "speaker": 62, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 220, - "fields": { - "ballot_submission": 28, - "debate_team": 55, - "speaker": 61, - "score": 36.25, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 221, - "fields": { - "ballot_submission": 28, - "debate_team": 56, - "speaker": 34, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 222, - "fields": { - "ballot_submission": 28, - "debate_team": 56, - "speaker": 35, - "score": 75.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 223, - "fields": { - "ballot_submission": 28, - "debate_team": 56, - "speaker": 36, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 224, - "fields": { - "ballot_submission": 28, - "debate_team": 56, - "speaker": 34, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 225, - "fields": { - "ballot_submission": 29, - "debate_team": 57, - "speaker": 72, - "score": 75.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 226, - "fields": { - "ballot_submission": 29, - "debate_team": 57, - "speaker": 71, - "score": 72.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 227, - "fields": { - "ballot_submission": 29, - "debate_team": 57, - "speaker": 70, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 228, - "fields": { - "ballot_submission": 29, - "debate_team": 57, - "speaker": 72, - "score": 38.25, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 229, - "fields": { - "ballot_submission": 29, - "debate_team": 58, - "speaker": 55, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 230, - "fields": { - "ballot_submission": 29, - "debate_team": 58, - "speaker": 57, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 231, - "fields": { - "ballot_submission": 29, - "debate_team": 58, - "speaker": 56, - "score": 75.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 232, - "fields": { - "ballot_submission": 29, - "debate_team": 58, - "speaker": 55, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 233, - "fields": { - "ballot_submission": 30, - "debate_team": 59, - "speaker": 29, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 234, - "fields": { - "ballot_submission": 30, - "debate_team": 59, - "speaker": 28, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 235, - "fields": { - "ballot_submission": 30, - "debate_team": 59, - "speaker": 30, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 236, - "fields": { - "ballot_submission": 30, - "debate_team": 59, - "speaker": 29, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 237, - "fields": { - "ballot_submission": 30, - "debate_team": 60, - "speaker": 5, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 238, - "fields": { - "ballot_submission": 30, - "debate_team": 60, - "speaker": 4, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 239, - "fields": { - "ballot_submission": 30, - "debate_team": 60, - "speaker": 6, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 240, - "fields": { - "ballot_submission": 30, - "debate_team": 60, - "speaker": 5, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 241, - "fields": { - "ballot_submission": 31, - "debate_team": 61, - "speaker": 25, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 242, - "fields": { - "ballot_submission": 31, - "debate_team": 61, - "speaker": 27, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 243, - "fields": { - "ballot_submission": 31, - "debate_team": 61, - "speaker": 26, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 244, - "fields": { - "ballot_submission": 31, - "debate_team": 61, - "speaker": 25, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 245, - "fields": { - "ballot_submission": 31, - "debate_team": 62, - "speaker": 21, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 246, - "fields": { - "ballot_submission": 31, - "debate_team": 62, - "speaker": 20, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 247, - "fields": { - "ballot_submission": 31, - "debate_team": 62, - "speaker": 19, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 248, - "fields": { - "ballot_submission": 31, - "debate_team": 62, - "speaker": 21, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 249, - "fields": { - "ballot_submission": 32, - "debate_team": 63, - "speaker": 59, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 250, - "fields": { - "ballot_submission": 32, - "debate_team": 63, - "speaker": 58, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 251, - "fields": { - "ballot_submission": 32, - "debate_team": 63, - "speaker": 60, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 252, - "fields": { - "ballot_submission": 32, - "debate_team": 63, - "speaker": 59, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 253, - "fields": { - "ballot_submission": 32, - "debate_team": 64, - "speaker": 15, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 254, - "fields": { - "ballot_submission": 32, - "debate_team": 64, - "speaker": 13, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 255, - "fields": { - "ballot_submission": 32, - "debate_team": 64, - "speaker": 14, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 256, - "fields": { - "ballot_submission": 32, - "debate_team": 64, - "speaker": 15, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 257, - "fields": { - "ballot_submission": 33, - "debate_team": 65, - "speaker": 48, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 258, - "fields": { - "ballot_submission": 33, - "debate_team": 65, - "speaker": 46, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 259, - "fields": { - "ballot_submission": 33, - "debate_team": 65, - "speaker": 47, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 260, - "fields": { - "ballot_submission": 33, - "debate_team": 65, - "speaker": 48, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 261, - "fields": { - "ballot_submission": 33, - "debate_team": 66, - "speaker": 33, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 262, - "fields": { - "ballot_submission": 33, - "debate_team": 66, - "speaker": 31, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 263, - "fields": { - "ballot_submission": 33, - "debate_team": 66, - "speaker": 32, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 264, - "fields": { - "ballot_submission": 33, - "debate_team": 66, - "speaker": 33, - "score": 37.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 265, - "fields": { - "ballot_submission": 34, - "debate_team": 67, - "speaker": 69, - "score": 75.5, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 266, - "fields": { - "ballot_submission": 34, - "debate_team": 67, - "speaker": 68, - "score": 76.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 267, - "fields": { - "ballot_submission": 34, - "debate_team": 67, - "speaker": 67, - "score": 76.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 268, - "fields": { - "ballot_submission": 34, - "debate_team": 67, - "speaker": 69, - "score": 38.25, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 269, - "fields": { - "ballot_submission": 34, - "debate_team": 68, - "speaker": 40, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 270, - "fields": { - "ballot_submission": 34, - "debate_team": 68, - "speaker": 41, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 271, - "fields": { - "ballot_submission": 34, - "debate_team": 68, - "speaker": 42, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 272, - "fields": { - "ballot_submission": 34, - "debate_team": 68, - "speaker": 40, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 273, - "fields": { - "ballot_submission": 35, - "debate_team": 69, - "speaker": 64, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 274, - "fields": { - "ballot_submission": 35, - "debate_team": 69, - "speaker": 66, - "score": 76.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 275, - "fields": { - "ballot_submission": 35, - "debate_team": 69, - "speaker": 65, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 276, - "fields": { - "ballot_submission": 35, - "debate_team": 69, - "speaker": 64, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 277, - "fields": { - "ballot_submission": 35, - "debate_team": 70, - "speaker": 38, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 278, - "fields": { - "ballot_submission": 35, - "debate_team": 70, - "speaker": 37, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 279, - "fields": { - "ballot_submission": 35, - "debate_team": 70, - "speaker": 39, - "score": 72.5, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 280, - "fields": { - "ballot_submission": 35, - "debate_team": 70, - "speaker": 38, - "score": 36.75, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 281, - "fields": { - "ballot_submission": 36, - "debate_team": 71, - "speaker": 23, - "score": 73.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 282, - "fields": { - "ballot_submission": 36, - "debate_team": 71, - "speaker": 24, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 283, - "fields": { - "ballot_submission": 36, - "debate_team": 71, - "speaker": 22, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 284, - "fields": { - "ballot_submission": 36, - "debate_team": 71, - "speaker": 23, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 285, - "fields": { - "ballot_submission": 36, - "debate_team": 72, - "speaker": 49, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 286, - "fields": { - "ballot_submission": 36, - "debate_team": 72, - "speaker": 50, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 287, - "fields": { - "ballot_submission": 36, - "debate_team": 72, - "speaker": 51, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 288, - "fields": { - "ballot_submission": 36, - "debate_team": 72, - "speaker": 49, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 289, - "fields": { - "ballot_submission": 37, - "debate_team": 73, - "speaker": 55, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 290, - "fields": { - "ballot_submission": 37, - "debate_team": 73, - "speaker": 57, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 291, - "fields": { - "ballot_submission": 37, - "debate_team": 73, - "speaker": 56, - "score": 78.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 292, - "fields": { - "ballot_submission": 37, - "debate_team": 73, - "speaker": 55, - "score": 36.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 293, - "fields": { - "ballot_submission": 37, - "debate_team": 74, - "speaker": 64, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 294, - "fields": { - "ballot_submission": 37, - "debate_team": 74, - "speaker": 66, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 295, - "fields": { - "ballot_submission": 37, - "debate_team": 74, - "speaker": 65, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 296, - "fields": { - "ballot_submission": 37, - "debate_team": 74, - "speaker": 64, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 297, - "fields": { - "ballot_submission": 38, - "debate_team": 75, - "speaker": 33, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 298, - "fields": { - "ballot_submission": 38, - "debate_team": 75, - "speaker": 31, - "score": 72.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 299, - "fields": { - "ballot_submission": 38, - "debate_team": 75, - "speaker": 32, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 300, - "fields": { - "ballot_submission": 38, - "debate_team": 75, - "speaker": 33, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 301, - "fields": { - "ballot_submission": 38, - "debate_team": 76, - "speaker": 21, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 302, - "fields": { - "ballot_submission": 38, - "debate_team": 76, - "speaker": 20, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 303, - "fields": { - "ballot_submission": 38, - "debate_team": 76, - "speaker": 19, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 304, - "fields": { - "ballot_submission": 38, - "debate_team": 76, - "speaker": 21, - "score": 39.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 305, - "fields": { - "ballot_submission": 39, - "debate_team": 77, - "speaker": 23, - "score": 73.6666666666667, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 306, - "fields": { - "ballot_submission": 39, - "debate_team": 77, - "speaker": 24, - "score": 73.3333333333333, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 307, - "fields": { - "ballot_submission": 39, - "debate_team": 77, - "speaker": 22, - "score": 73.3333333333333, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 308, - "fields": { - "ballot_submission": 39, - "debate_team": 77, - "speaker": 23, - "score": 36.1666666666667, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 309, - "fields": { - "ballot_submission": 39, - "debate_team": 78, - "speaker": 15, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 310, - "fields": { - "ballot_submission": 39, - "debate_team": 78, - "speaker": 13, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 311, - "fields": { - "ballot_submission": 39, - "debate_team": 78, - "speaker": 14, - "score": 73.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 312, - "fields": { - "ballot_submission": 39, - "debate_team": 78, - "speaker": 15, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 313, - "fields": { - "ballot_submission": 40, - "debate_team": 79, - "speaker": 7, - "score": 75.6666666666667, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 314, - "fields": { - "ballot_submission": 40, - "debate_team": 79, - "speaker": 8, - "score": 73.3333333333333, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 315, - "fields": { - "ballot_submission": 40, - "debate_team": 79, - "speaker": 9, - "score": 75.3333333333333, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 316, - "fields": { - "ballot_submission": 40, - "debate_team": 79, - "speaker": 7, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 317, - "fields": { - "ballot_submission": 40, - "debate_team": 80, - "speaker": 69, - "score": 76.6666666666667, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 318, - "fields": { - "ballot_submission": 40, - "debate_team": 80, - "speaker": 68, - "score": 74.3333333333333, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 319, - "fields": { - "ballot_submission": 40, - "debate_team": 80, - "speaker": 67, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 320, - "fields": { - "ballot_submission": 40, - "debate_team": 80, - "speaker": 69, - "score": 38.1666666666667, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 321, - "fields": { - "ballot_submission": 41, - "debate_team": 81, - "speaker": 61, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 322, - "fields": { - "ballot_submission": 41, - "debate_team": 81, - "speaker": 63, - "score": 73.5, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 323, - "fields": { - "ballot_submission": 41, - "debate_team": 81, - "speaker": 62, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 324, - "fields": { - "ballot_submission": 41, - "debate_team": 81, - "speaker": 61, - "score": 37.75, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 325, - "fields": { - "ballot_submission": 41, - "debate_team": 82, - "speaker": 45, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 326, - "fields": { - "ballot_submission": 41, - "debate_team": 82, - "speaker": 44, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 327, - "fields": { - "ballot_submission": 41, - "debate_team": 82, - "speaker": 43, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 328, - "fields": { - "ballot_submission": 41, - "debate_team": 82, - "speaker": 45, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 329, - "fields": { - "ballot_submission": 42, - "debate_team": 83, - "speaker": 38, - "score": 74.6666666666667, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 330, - "fields": { - "ballot_submission": 42, - "debate_team": 83, - "speaker": 37, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 331, - "fields": { - "ballot_submission": 42, - "debate_team": 83, - "speaker": 39, - "score": 75.3333333333333, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 332, - "fields": { - "ballot_submission": 42, - "debate_team": 83, - "speaker": 38, - "score": 37.6666666666667, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 333, - "fields": { - "ballot_submission": 42, - "debate_team": 84, - "speaker": 40, - "score": 76.3333333333333, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 334, - "fields": { - "ballot_submission": 42, - "debate_team": 84, - "speaker": 41, - "score": 74.3333333333333, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 335, - "fields": { - "ballot_submission": 42, - "debate_team": 84, - "speaker": 42, - "score": 73.6666666666667, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 336, - "fields": { - "ballot_submission": 42, - "debate_team": 84, - "speaker": 40, - "score": 37.1666666666667, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 337, - "fields": { - "ballot_submission": 43, - "debate_team": 85, - "speaker": 5, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 338, - "fields": { - "ballot_submission": 43, - "debate_team": 85, - "speaker": 4, - "score": 76.3333333333333, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 339, - "fields": { - "ballot_submission": 43, - "debate_team": 85, - "speaker": 6, - "score": 72.3333333333333, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 340, - "fields": { - "ballot_submission": 43, - "debate_team": 85, - "speaker": 5, - "score": 36.8333333333333, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 341, - "fields": { - "ballot_submission": 43, - "debate_team": 86, - "speaker": 72, - "score": 76.6666666666667, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 342, - "fields": { - "ballot_submission": 43, - "debate_team": 86, - "speaker": 71, - "score": 75.6666666666667, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 343, - "fields": { - "ballot_submission": 43, - "debate_team": 86, - "speaker": 70, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 344, - "fields": { - "ballot_submission": 43, - "debate_team": 86, - "speaker": 72, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 345, - "fields": { - "ballot_submission": 44, - "debate_team": 87, - "speaker": 34, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 346, - "fields": { - "ballot_submission": 44, - "debate_team": 87, - "speaker": 35, - "score": 77.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 347, - "fields": { - "ballot_submission": 44, - "debate_team": 87, - "speaker": 36, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 348, - "fields": { - "ballot_submission": 44, - "debate_team": 87, - "speaker": 34, - "score": 38.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 349, - "fields": { - "ballot_submission": 44, - "debate_team": 88, - "speaker": 25, - "score": 72.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 350, - "fields": { - "ballot_submission": 44, - "debate_team": 88, - "speaker": 27, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 351, - "fields": { - "ballot_submission": 44, - "debate_team": 88, - "speaker": 26, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 352, - "fields": { - "ballot_submission": 44, - "debate_team": 88, - "speaker": 25, - "score": 36.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 353, - "fields": { - "ballot_submission": 45, - "debate_team": 89, - "speaker": 48, - "score": 75.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 354, - "fields": { - "ballot_submission": 45, - "debate_team": 89, - "speaker": 46, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 355, - "fields": { - "ballot_submission": 45, - "debate_team": 89, - "speaker": 47, - "score": 75.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 356, - "fields": { - "ballot_submission": 45, - "debate_team": 89, - "speaker": 48, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 357, - "fields": { - "ballot_submission": 45, - "debate_team": 90, - "speaker": 1, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 358, - "fields": { - "ballot_submission": 45, - "debate_team": 90, - "speaker": 3, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 359, - "fields": { - "ballot_submission": 45, - "debate_team": 90, - "speaker": 2, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 360, - "fields": { - "ballot_submission": 45, - "debate_team": 90, - "speaker": 1, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 361, - "fields": { - "ballot_submission": 46, - "debate_team": 91, - "speaker": 10, - "score": 78.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 362, - "fields": { - "ballot_submission": 46, - "debate_team": 91, - "speaker": 11, - "score": 75.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 363, - "fields": { - "ballot_submission": 46, - "debate_team": 91, - "speaker": 12, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 364, - "fields": { - "ballot_submission": 46, - "debate_team": 91, - "speaker": 10, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 365, - "fields": { - "ballot_submission": 46, - "debate_team": 92, - "speaker": 54, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 366, - "fields": { - "ballot_submission": 46, - "debate_team": 92, - "speaker": 53, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 367, - "fields": { - "ballot_submission": 46, - "debate_team": 92, - "speaker": 52, - "score": 77.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 368, - "fields": { - "ballot_submission": 46, - "debate_team": 92, - "speaker": 54, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 369, - "fields": { - "ballot_submission": 47, - "debate_team": 93, - "speaker": 17, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 370, - "fields": { - "ballot_submission": 47, - "debate_team": 93, - "speaker": 16, - "score": 73.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 371, - "fields": { - "ballot_submission": 47, - "debate_team": 93, - "speaker": 18, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 372, - "fields": { - "ballot_submission": 47, - "debate_team": 93, - "speaker": 17, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 373, - "fields": { - "ballot_submission": 47, - "debate_team": 94, - "speaker": 59, - "score": 76.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 374, - "fields": { - "ballot_submission": 47, - "debate_team": 94, - "speaker": 58, - "score": 76.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 375, - "fields": { - "ballot_submission": 47, - "debate_team": 94, - "speaker": 60, - "score": 76.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 376, - "fields": { - "ballot_submission": 47, - "debate_team": 94, - "speaker": 59, - "score": 38.0, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 377, - "fields": { - "ballot_submission": 48, - "debate_team": 95, - "speaker": 49, - "score": 77.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 378, - "fields": { - "ballot_submission": 48, - "debate_team": 95, - "speaker": 50, - "score": 78.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 379, - "fields": { - "ballot_submission": 48, - "debate_team": 95, - "speaker": 51, - "score": 74.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 380, - "fields": { - "ballot_submission": 48, - "debate_team": 95, - "speaker": 49, - "score": 37.5, - "position": 4 - } - }, - { - "model": "results.speakerscore", - "pk": 381, - "fields": { - "ballot_submission": 48, - "debate_team": 96, - "speaker": 29, - "score": 74.0, - "position": 1 - } - }, - { - "model": "results.speakerscore", - "pk": 382, - "fields": { - "ballot_submission": 48, - "debate_team": 96, - "speaker": 28, - "score": 74.0, - "position": 2 - } - }, - { - "model": "results.speakerscore", - "pk": 383, - "fields": { - "ballot_submission": 48, - "debate_team": 96, - "speaker": 30, - "score": 72.0, - "position": 3 - } - }, - { - "model": "results.speakerscore", - "pk": 384, - "fields": { - "ballot_submission": 48, - "debate_team": 96, - "speaker": 29, - "score": 38.5, - "position": 4 - } - }, - { - "model": "tournaments.tournament", - "pk": 1, - "fields": { - "name": "demo", - "short_name": "demo", - "emoji": null, - "seq": null, - "slug": "demo", - "current_round": 4, - "welcome_msg": "", - "release_all": false, - "active": true - } - }, - { - "model": "tournaments.round", - "pk": 1, - "fields": { - "tournament": 1, - "seq": 1, - "name": "Round 1", - "abbreviation": "R1", - "draw_type": "R", - "stage": "P", - "break_category": null, - "draw_status": "R", - "feedback_weight": 0.7, - "silent": false, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 2, - "fields": { - "tournament": 1, - "seq": 2, - "name": "Round 2", - "abbreviation": "R2", - "draw_type": "P", - "stage": "P", - "break_category": null, - "draw_status": "R", - "feedback_weight": 0.7, - "silent": false, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 3, - "fields": { - "tournament": 1, - "seq": 3, - "name": "Round 3", - "abbreviation": "R3", - "draw_type": "P", - "stage": "P", - "break_category": null, - "draw_status": "C", - "feedback_weight": 0.7, - "silent": false, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 4, - "fields": { - "tournament": 1, - "seq": 4, - "name": "Round 4", - "abbreviation": "R4", - "draw_type": "P", - "stage": "P", - "break_category": null, - "draw_status": "C", - "feedback_weight": 0.7, - "silent": false, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 5, - "fields": { - "tournament": 1, - "seq": 5, - "name": "Open Quarterfinal", - "abbreviation": "OQF", - "draw_type": "F", - "stage": "E", - "break_category": 1, - "draw_status": "N", - "feedback_weight": 0.7, - "silent": true, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 6, - "fields": { - "tournament": 1, - "seq": 6, - "name": "ESL Semifinal", - "abbreviation": "SSF", - "draw_type": "F", - "stage": "E", - "break_category": 2, - "draw_status": "N", - "feedback_weight": 0.7, - "silent": true, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 7, - "fields": { - "tournament": 1, - "seq": 7, - "name": "Open Semifinal", - "abbreviation": "OSF", - "draw_type": "B", - "stage": "E", - "break_category": 1, - "draw_status": "C", - "feedback_weight": 0.7, - "silent": true, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 8, - "fields": { - "tournament": 1, - "seq": 8, - "name": "ESL Grand Final", - "abbreviation": "SGF", - "draw_type": "B", - "stage": "E", - "break_category": 2, - "draw_status": "N", - "feedback_weight": 0.7, - "silent": true, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 9, - "fields": { - "tournament": 1, - "seq": 9, - "name": "EFL Grand Final", - "abbreviation": "FGF", - "draw_type": "F", - "stage": "E", - "break_category": 3, - "draw_status": "N", - "feedback_weight": 0.7, - "silent": true, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "tournaments.round", - "pk": 10, - "fields": { - "tournament": 1, - "seq": 10, - "name": "Open Grand Final", - "abbreviation": "OGF", - "draw_type": "B", - "stage": "E", - "break_category": 1, - "draw_status": "N", - "feedback_weight": 0.7, - "silent": true, - "motions_released": false, - "starts_at": null - } - }, - { - "model": "venues.venuegroup", - "pk": 1, - "fields": { - "name": "1", - "short_name": "1", - "team_capacity": null - } - }, - { - "model": "venues.venuegroup", - "pk": 2, - "fields": { - "name": "2", - "short_name": "2", - "team_capacity": null - } - }, - { - "model": "venues.venuegroup", - "pk": 3, - "fields": { - "name": "3", - "short_name": "3", - "team_capacity": null - } - }, - { - "model": "venues.venuegroup", - "pk": 4, - "fields": { - "name": "4", - "short_name": "4", - "team_capacity": null - } - }, - { - "model": "venues.venuegroup", - "pk": 5, - "fields": { - "name": "5", - "short_name": "5", - "team_capacity": null - } - }, - { - "model": "venues.venuegroup", - "pk": 6, - "fields": { - "name": "6", - "short_name": "6", - "team_capacity": null - } - }, - { - "model": "venues.venuegroup", - "pk": 7, - "fields": { - "name": "7", - "short_name": "7", - "team_capacity": null - } - }, - { - "model": "venues.venue", - "pk": 1, - "fields": { - "name": "M04", - "group": null, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 2, - "fields": { - "name": "M05", - "group": 1, - "priority": 10, - "tournament": null - } - }, - { - "model": "venues.venue", - "pk": 3, - "fields": { - "name": "M10", - "group": 1, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 4, - "fields": { - "name": "M11", - "group": 1, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 5, - "fields": { - "name": "G01", - "group": 2, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 6, - "fields": { - "name": "G02", - "group": 2, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 7, - "fields": { - "name": "G03", - "group": 2, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 8, - "fields": { - "name": "G04", - "group": 3, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 9, - "fields": { - "name": "G05", - "group": 3, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 10, - "fields": { - "name": "G06", - "group": 3, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 11, - "fields": { - "name": "G07", - "group": null, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 12, - "fields": { - "name": "G08", - "group": 3, - "priority": 10, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 13, - "fields": { - "name": "K03", - "group": 4, - "priority": 20, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 14, - "fields": { - "name": "K04", - "group": 4, - "priority": 20, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 15, - "fields": { - "name": "K05", - "group": 4, - "priority": 20, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 16, - "fields": { - "name": "K06", - "group": null, - "priority": 20, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 17, - "fields": { - "name": "K08", - "group": 4, - "priority": 20, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 18, - "fields": { - "name": "P01", - "group": 5, - "priority": 30, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 19, - "fields": { - "name": "P03", - "group": 5, - "priority": 30, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 20, - "fields": { - "name": "P05", - "group": 6, - "priority": 30, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 21, - "fields": { - "name": "P07", - "group": 6, - "priority": 30, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 22, - "fields": { - "name": "Z09", - "group": 7, - "priority": 40, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 23, - "fields": { - "name": "Z10", - "group": null, - "priority": 40, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 24, - "fields": { - "name": "Shared 140", - "group": null, - "priority": 200, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 25, - "fields": { - "name": "Shared 2.9.0", - "group": null, - "priority": 100, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 26, - "fields": { - "name": "Black 11G", - "group": null, - "priority": 50, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 27, - "fields": { - "name": "Test", - "group": null, - "priority": 55, - "tournament": 1 - } - }, - { - "model": "venues.venue", - "pk": 28, - "fields": { - "name": "Test2SSS", - "group": null, - "priority": 155, - "tournament": null - } - }, - { - "model": "venues.venue", - "pk": 29, - "fields": { - "name": "Test3SSS", - "group": null, - "priority": 200, - "tournament": null - } - }, - { - "model": "auth.permission", - "pk": 1, - "fields": { - "name": "Can add bookmark", - "content_type": 1, - "codename": "add_bookmark" - } - }, - { - "model": "auth.permission", - "pk": 2, - "fields": { - "name": "Can change bookmark", - "content_type": 1, - "codename": "change_bookmark" - } - }, - { - "model": "auth.permission", - "pk": 3, - "fields": { - "name": "Can delete bookmark", - "content_type": 1, - "codename": "delete_bookmark" - } - }, - { - "model": "auth.permission", - "pk": 4, - "fields": { - "name": "Can add pinned application", - "content_type": 2, - "codename": "add_pinnedapplication" - } - }, - { - "model": "auth.permission", - "pk": 5, - "fields": { - "name": "Can change pinned application", - "content_type": 2, - "codename": "change_pinnedapplication" - } - }, - { - "model": "auth.permission", - "pk": 6, - "fields": { - "name": "Can delete pinned application", - "content_type": 2, - "codename": "delete_pinnedapplication" - } - }, - { - "model": "auth.permission", - "pk": 7, - "fields": { - "name": "Can add log entry", - "content_type": 3, - "codename": "add_logentry" - } - }, - { - "model": "auth.permission", - "pk": 8, - "fields": { - "name": "Can change log entry", - "content_type": 3, - "codename": "change_logentry" - } - }, - { - "model": "auth.permission", - "pk": 9, - "fields": { - "name": "Can delete log entry", - "content_type": 3, - "codename": "delete_logentry" - } - }, - { - "model": "auth.permission", - "pk": 10, - "fields": { - "name": "Can add permission", - "content_type": 4, - "codename": "add_permission" - } - }, - { - "model": "auth.permission", - "pk": 11, - "fields": { - "name": "Can change permission", - "content_type": 4, - "codename": "change_permission" - } - }, - { - "model": "auth.permission", - "pk": 12, - "fields": { - "name": "Can delete permission", - "content_type": 4, - "codename": "delete_permission" - } - }, - { - "model": "auth.permission", - "pk": 13, - "fields": { - "name": "Can add group", - "content_type": 5, - "codename": "add_group" - } - }, - { - "model": "auth.permission", - "pk": 14, - "fields": { - "name": "Can change group", - "content_type": 5, - "codename": "change_group" - } - }, - { - "model": "auth.permission", - "pk": 15, - "fields": { - "name": "Can delete group", - "content_type": 5, - "codename": "delete_group" - } - }, - { - "model": "auth.permission", - "pk": 16, - "fields": { - "name": "Can add user", - "content_type": 6, - "codename": "add_user" - } - }, - { - "model": "auth.permission", - "pk": 17, - "fields": { - "name": "Can change user", - "content_type": 6, - "codename": "change_user" - } - }, - { - "model": "auth.permission", - "pk": 18, - "fields": { - "name": "Can delete user", - "content_type": 6, - "codename": "delete_user" - } - }, - { - "model": "auth.permission", - "pk": 19, - "fields": { - "name": "Can add content type", - "content_type": 7, - "codename": "add_contenttype" - } - }, - { - "model": "auth.permission", - "pk": 20, - "fields": { - "name": "Can change content type", - "content_type": 7, - "codename": "change_contenttype" - } - }, - { - "model": "auth.permission", - "pk": 21, - "fields": { - "name": "Can delete content type", - "content_type": 7, - "codename": "delete_contenttype" - } - }, - { - "model": "auth.permission", - "pk": 22, - "fields": { - "name": "Can add session", - "content_type": 8, - "codename": "add_session" - } - }, - { - "model": "auth.permission", - "pk": 23, - "fields": { - "name": "Can change session", - "content_type": 8, - "codename": "change_session" - } - }, - { - "model": "auth.permission", - "pk": 24, - "fields": { - "name": "Can delete session", - "content_type": 8, - "codename": "delete_session" - } - }, - { - "model": "auth.permission", - "pk": 25, - "fields": { - "name": "Can add action log entry", - "content_type": 9, - "codename": "add_actionlogentry" - } - }, - { - "model": "auth.permission", - "pk": 26, - "fields": { - "name": "Can change action log entry", - "content_type": 9, - "codename": "change_actionlogentry" - } - }, - { - "model": "auth.permission", - "pk": 27, - "fields": { - "name": "Can delete action log entry", - "content_type": 9, - "codename": "delete_actionlogentry" - } - }, - { - "model": "auth.permission", - "pk": 28, - "fields": { - "name": "Can add debate adjudicator", - "content_type": 10, - "codename": "add_debateadjudicator" - } - }, - { - "model": "auth.permission", - "pk": 29, - "fields": { - "name": "Can change debate adjudicator", - "content_type": 10, - "codename": "change_debateadjudicator" - } - }, - { - "model": "auth.permission", - "pk": 30, - "fields": { - "name": "Can delete debate adjudicator", - "content_type": 10, - "codename": "delete_debateadjudicator" - } - }, - { - "model": "auth.permission", - "pk": 31, - "fields": { - "name": "Can add adjudicator-team conflict", - "content_type": 11, - "codename": "add_adjudicatorconflict" - } - }, - { - "model": "auth.permission", - "pk": 32, - "fields": { - "name": "Can change adjudicator-team conflict", - "content_type": 11, - "codename": "change_adjudicatorconflict" - } - }, - { - "model": "auth.permission", - "pk": 33, - "fields": { - "name": "Can delete adjudicator-team conflict", - "content_type": 11, - "codename": "delete_adjudicatorconflict" - } - }, - { - "model": "auth.permission", - "pk": 34, - "fields": { - "name": "Can add adjudicator-adjudicator conflict", - "content_type": 12, - "codename": "add_adjudicatoradjudicatorconflict" - } - }, - { - "model": "auth.permission", - "pk": 35, - "fields": { - "name": "Can change adjudicator-adjudicator conflict", - "content_type": 12, - "codename": "change_adjudicatoradjudicatorconflict" - } - }, - { - "model": "auth.permission", - "pk": 36, - "fields": { - "name": "Can delete adjudicator-adjudicator conflict", - "content_type": 12, - "codename": "delete_adjudicatoradjudicatorconflict" - } - }, - { - "model": "auth.permission", - "pk": 37, - "fields": { - "name": "Can add adjudicator-institution conflict", - "content_type": 13, - "codename": "add_adjudicatorinstitutionconflict" - } - }, - { - "model": "auth.permission", - "pk": 38, - "fields": { - "name": "Can change adjudicator-institution conflict", - "content_type": 13, - "codename": "change_adjudicatorinstitutionconflict" - } - }, - { - "model": "auth.permission", - "pk": 39, - "fields": { - "name": "Can delete adjudicator-institution conflict", - "content_type": 13, - "codename": "delete_adjudicatorinstitutionconflict" - } - }, - { - "model": "auth.permission", - "pk": 40, - "fields": { - "name": "Can add adjudicator test score history", - "content_type": 14, - "codename": "add_adjudicatortestscorehistory" - } - }, - { - "model": "auth.permission", - "pk": 41, - "fields": { - "name": "Can change adjudicator test score history", - "content_type": 14, - "codename": "change_adjudicatortestscorehistory" - } - }, - { - "model": "auth.permission", - "pk": 42, - "fields": { - "name": "Can delete adjudicator test score history", - "content_type": 14, - "codename": "delete_adjudicatortestscorehistory" - } - }, - { - "model": "auth.permission", - "pk": 43, - "fields": { - "name": "Can add adjudicator feedback boolean answer", - "content_type": 15, - "codename": "add_adjudicatorfeedbackbooleananswer" - } - }, - { - "model": "auth.permission", - "pk": 44, - "fields": { - "name": "Can change adjudicator feedback boolean answer", - "content_type": 15, - "codename": "change_adjudicatorfeedbackbooleananswer" - } - }, - { - "model": "auth.permission", - "pk": 45, - "fields": { - "name": "Can delete adjudicator feedback boolean answer", - "content_type": 15, - "codename": "delete_adjudicatorfeedbackbooleananswer" - } - }, - { - "model": "auth.permission", - "pk": 46, - "fields": { - "name": "Can add adjudicator feedback integer answer", - "content_type": 16, - "codename": "add_adjudicatorfeedbackintegeranswer" - } - }, - { - "model": "auth.permission", - "pk": 47, - "fields": { - "name": "Can change adjudicator feedback integer answer", - "content_type": 16, - "codename": "change_adjudicatorfeedbackintegeranswer" - } - }, - { - "model": "auth.permission", - "pk": 48, - "fields": { - "name": "Can delete adjudicator feedback integer answer", - "content_type": 16, - "codename": "delete_adjudicatorfeedbackintegeranswer" - } - }, - { - "model": "auth.permission", - "pk": 49, - "fields": { - "name": "Can add adjudicator feedback float answer", - "content_type": 17, - "codename": "add_adjudicatorfeedbackfloatanswer" - } - }, - { - "model": "auth.permission", - "pk": 50, - "fields": { - "name": "Can change adjudicator feedback float answer", - "content_type": 17, - "codename": "change_adjudicatorfeedbackfloatanswer" - } - }, - { - "model": "auth.permission", - "pk": 51, - "fields": { - "name": "Can delete adjudicator feedback float answer", - "content_type": 17, - "codename": "delete_adjudicatorfeedbackfloatanswer" - } - }, - { - "model": "auth.permission", - "pk": 52, - "fields": { - "name": "Can add adjudicator feedback string answer", - "content_type": 18, - "codename": "add_adjudicatorfeedbackstringanswer" - } - }, - { - "model": "auth.permission", - "pk": 53, - "fields": { - "name": "Can change adjudicator feedback string answer", - "content_type": 18, - "codename": "change_adjudicatorfeedbackstringanswer" - } - }, - { - "model": "auth.permission", - "pk": 54, - "fields": { - "name": "Can delete adjudicator feedback string answer", - "content_type": 18, - "codename": "delete_adjudicatorfeedbackstringanswer" - } - }, - { - "model": "auth.permission", - "pk": 55, - "fields": { - "name": "Can add adjudicator feedback question", - "content_type": 19, - "codename": "add_adjudicatorfeedbackquestion" - } - }, - { - "model": "auth.permission", - "pk": 56, - "fields": { - "name": "Can change adjudicator feedback question", - "content_type": 19, - "codename": "change_adjudicatorfeedbackquestion" - } - }, - { - "model": "auth.permission", - "pk": 57, - "fields": { - "name": "Can delete adjudicator feedback question", - "content_type": 19, - "codename": "delete_adjudicatorfeedbackquestion" - } - }, - { - "model": "auth.permission", - "pk": 58, - "fields": { - "name": "Can add adjudicator feedback", - "content_type": 20, - "codename": "add_adjudicatorfeedback" - } - }, - { - "model": "auth.permission", - "pk": 59, - "fields": { - "name": "Can change adjudicator feedback", - "content_type": 20, - "codename": "change_adjudicatorfeedback" - } - }, - { - "model": "auth.permission", - "pk": 60, - "fields": { - "name": "Can delete adjudicator feedback", - "content_type": 20, - "codename": "delete_adjudicatorfeedback" - } - }, - { - "model": "auth.permission", - "pk": 61, - "fields": { - "name": "Can add checkin", - "content_type": 21, - "codename": "add_checkin" - } - }, - { - "model": "auth.permission", - "pk": 62, - "fields": { - "name": "Can change checkin", - "content_type": 21, - "codename": "change_checkin" - } - }, - { - "model": "auth.permission", - "pk": 63, - "fields": { - "name": "Can delete checkin", - "content_type": 21, - "codename": "delete_checkin" - } - }, - { - "model": "auth.permission", - "pk": 64, - "fields": { - "name": "Can add active venue", - "content_type": 22, - "codename": "add_activevenue" - } - }, - { - "model": "auth.permission", - "pk": 65, - "fields": { - "name": "Can change active venue", - "content_type": 22, - "codename": "change_activevenue" - } - }, - { - "model": "auth.permission", - "pk": 66, - "fields": { - "name": "Can delete active venue", - "content_type": 22, - "codename": "delete_activevenue" - } - }, - { - "model": "auth.permission", - "pk": 67, - "fields": { - "name": "Can add active team", - "content_type": 23, - "codename": "add_activeteam" - } - }, - { - "model": "auth.permission", - "pk": 68, - "fields": { - "name": "Can change active team", - "content_type": 23, - "codename": "change_activeteam" - } - }, - { - "model": "auth.permission", - "pk": 69, - "fields": { - "name": "Can delete active team", - "content_type": 23, - "codename": "delete_activeteam" - } - }, - { - "model": "auth.permission", - "pk": 70, - "fields": { - "name": "Can add active adjudicator", - "content_type": 24, - "codename": "add_activeadjudicator" - } - }, - { - "model": "auth.permission", - "pk": 71, - "fields": { - "name": "Can change active adjudicator", - "content_type": 24, - "codename": "change_activeadjudicator" - } - }, - { - "model": "auth.permission", - "pk": 72, - "fields": { - "name": "Can delete active adjudicator", - "content_type": 24, - "codename": "delete_activeadjudicator" - } - }, - { - "model": "auth.permission", - "pk": 73, - "fields": { - "name": "Can add break category", - "content_type": 25, - "codename": "add_breakcategory" - } - }, - { - "model": "auth.permission", - "pk": 74, - "fields": { - "name": "Can change break category", - "content_type": 25, - "codename": "change_breakcategory" - } - }, - { - "model": "auth.permission", - "pk": 75, - "fields": { - "name": "Can delete break category", - "content_type": 25, - "codename": "delete_breakcategory" - } - }, - { - "model": "auth.permission", - "pk": 76, - "fields": { - "name": "Can add breaking team", - "content_type": 26, - "codename": "add_breakingteam" - } - }, - { - "model": "auth.permission", - "pk": 77, - "fields": { - "name": "Can change breaking team", - "content_type": 26, - "codename": "change_breakingteam" - } - }, - { - "model": "auth.permission", - "pk": 78, - "fields": { - "name": "Can delete breaking team", - "content_type": 26, - "codename": "delete_breakingteam" - } - }, - { - "model": "auth.permission", - "pk": 79, - "fields": { - "name": "Can add debate", - "content_type": 27, - "codename": "add_debate" - } - }, - { - "model": "auth.permission", - "pk": 80, - "fields": { - "name": "Can change debate", - "content_type": 27, - "codename": "change_debate" - } - }, - { - "model": "auth.permission", - "pk": 81, - "fields": { - "name": "Can delete debate", - "content_type": 27, - "codename": "delete_debate" - } - }, - { - "model": "auth.permission", - "pk": 82, - "fields": { - "name": "Can add debate team", - "content_type": 28, - "codename": "add_debateteam" - } - }, - { - "model": "auth.permission", - "pk": 83, - "fields": { - "name": "Can change debate team", - "content_type": 28, - "codename": "change_debateteam" - } - }, - { - "model": "auth.permission", - "pk": 84, - "fields": { - "name": "Can delete debate team", - "content_type": 28, - "codename": "delete_debateteam" - } - }, - { - "model": "auth.permission", - "pk": 85, - "fields": { - "name": "Can add team position allocation", - "content_type": 29, - "codename": "add_teampositionallocation" - } - }, - { - "model": "auth.permission", - "pk": 86, - "fields": { - "name": "Can change team position allocation", - "content_type": 29, - "codename": "change_teampositionallocation" - } - }, - { - "model": "auth.permission", - "pk": 87, - "fields": { - "name": "Can delete team position allocation", - "content_type": 29, - "codename": "delete_teampositionallocation" - } - }, - { - "model": "auth.permission", - "pk": 88, - "fields": { - "name": "Can add team venue preference", - "content_type": 30, - "codename": "add_teamvenuepreference" - } - }, - { - "model": "auth.permission", - "pk": 89, - "fields": { - "name": "Can change team venue preference", - "content_type": 30, - "codename": "change_teamvenuepreference" - } - }, - { - "model": "auth.permission", - "pk": 90, - "fields": { - "name": "Can delete team venue preference", - "content_type": 30, - "codename": "delete_teamvenuepreference" - } - }, - { - "model": "auth.permission", - "pk": 91, - "fields": { - "name": "Can add institution venue preference", - "content_type": 31, - "codename": "add_institutionvenuepreference" - } - }, - { - "model": "auth.permission", - "pk": 92, - "fields": { - "name": "Can change institution venue preference", - "content_type": 31, - "codename": "change_institutionvenuepreference" - } - }, - { - "model": "auth.permission", - "pk": 93, - "fields": { - "name": "Can delete institution venue preference", - "content_type": 31, - "codename": "delete_institutionvenuepreference" - } - }, - { - "model": "auth.permission", - "pk": 94, - "fields": { - "name": "Can add motion", - "content_type": 32, - "codename": "add_motion" - } - }, - { - "model": "auth.permission", - "pk": 95, - "fields": { - "name": "Can change motion", - "content_type": 32, - "codename": "change_motion" - } - }, - { - "model": "auth.permission", - "pk": 96, - "fields": { - "name": "Can delete motion", - "content_type": 32, - "codename": "delete_motion" - } - }, - { - "model": "auth.permission", - "pk": 97, - "fields": { - "name": "Can add debate team motion preference", - "content_type": 33, - "codename": "add_debateteammotionpreference" - } - }, - { - "model": "auth.permission", - "pk": 98, - "fields": { - "name": "Can change debate team motion preference", - "content_type": 33, - "codename": "change_debateteammotionpreference" - } - }, - { - "model": "auth.permission", - "pk": 99, - "fields": { - "name": "Can delete debate team motion preference", - "content_type": 33, - "codename": "delete_debateteammotionpreference" - } - }, - { - "model": "auth.permission", - "pk": 100, - "fields": { - "name": "Can add tournament preference", - "content_type": 34, - "codename": "add_tournamentpreferencemodel" - } - }, - { - "model": "auth.permission", - "pk": 101, - "fields": { - "name": "Can change tournament preference", - "content_type": 34, - "codename": "change_tournamentpreferencemodel" - } - }, - { - "model": "auth.permission", - "pk": 102, - "fields": { - "name": "Can delete tournament preference", - "content_type": 34, - "codename": "delete_tournamentpreferencemodel" - } - }, - { - "model": "auth.permission", - "pk": 103, - "fields": { - "name": "Can add region", - "content_type": 35, - "codename": "add_region" - } - }, - { - "model": "auth.permission", - "pk": 104, - "fields": { - "name": "Can change region", - "content_type": 35, - "codename": "change_region" - } - }, - { - "model": "auth.permission", - "pk": 105, - "fields": { - "name": "Can delete region", - "content_type": 35, - "codename": "delete_region" - } - }, - { - "model": "auth.permission", - "pk": 106, - "fields": { - "name": "Can add institution", - "content_type": 36, - "codename": "add_institution" - } - }, - { - "model": "auth.permission", - "pk": 107, - "fields": { - "name": "Can change institution", - "content_type": 36, - "codename": "change_institution" - } - }, - { - "model": "auth.permission", - "pk": 108, - "fields": { - "name": "Can delete institution", - "content_type": 36, - "codename": "delete_institution" - } - }, - { - "model": "auth.permission", - "pk": 109, - "fields": { - "name": "Can add person", - "content_type": 37, - "codename": "add_person" - } - }, - { - "model": "auth.permission", - "pk": 110, - "fields": { - "name": "Can change person", - "content_type": 37, - "codename": "change_person" - } - }, - { - "model": "auth.permission", - "pk": 111, - "fields": { - "name": "Can delete person", - "content_type": 37, - "codename": "delete_person" - } - }, - { - "model": "auth.permission", - "pk": 112, - "fields": { - "name": "Can add team", - "content_type": 38, - "codename": "add_team" - } - }, - { - "model": "auth.permission", - "pk": 113, - "fields": { - "name": "Can change team", - "content_type": 38, - "codename": "change_team" - } - }, - { - "model": "auth.permission", - "pk": 114, - "fields": { - "name": "Can delete team", - "content_type": 38, - "codename": "delete_team" - } - }, - { - "model": "auth.permission", - "pk": 115, - "fields": { - "name": "Can add speaker", - "content_type": 39, - "codename": "add_speaker" - } - }, - { - "model": "auth.permission", - "pk": 116, - "fields": { - "name": "Can change speaker", - "content_type": 39, - "codename": "change_speaker" - } - }, - { - "model": "auth.permission", - "pk": 117, - "fields": { - "name": "Can delete speaker", - "content_type": 39, - "codename": "delete_speaker" - } - }, - { - "model": "auth.permission", - "pk": 118, - "fields": { - "name": "Can add adjudicator", - "content_type": 40, - "codename": "add_adjudicator" - } - }, - { - "model": "auth.permission", - "pk": 119, - "fields": { - "name": "Can change adjudicator", - "content_type": 40, - "codename": "change_adjudicator" - } - }, - { - "model": "auth.permission", - "pk": 120, - "fields": { - "name": "Can delete adjudicator", - "content_type": 40, - "codename": "delete_adjudicator" - } - }, - { - "model": "auth.permission", - "pk": 121, - "fields": { - "name": "Can add ballot submission", - "content_type": 41, - "codename": "add_ballotsubmission" - } - }, - { - "model": "auth.permission", - "pk": 122, - "fields": { - "name": "Can change ballot submission", - "content_type": 41, - "codename": "change_ballotsubmission" - } - }, - { - "model": "auth.permission", - "pk": 123, - "fields": { - "name": "Can delete ballot submission", - "content_type": 41, - "codename": "delete_ballotsubmission" - } - }, - { - "model": "auth.permission", - "pk": 124, - "fields": { - "name": "Can add speaker score by adj", - "content_type": 42, - "codename": "add_speakerscorebyadj" - } - }, - { - "model": "auth.permission", - "pk": 125, - "fields": { - "name": "Can change speaker score by adj", - "content_type": 42, - "codename": "change_speakerscorebyadj" - } - }, - { - "model": "auth.permission", - "pk": 126, - "fields": { - "name": "Can delete speaker score by adj", - "content_type": 42, - "codename": "delete_speakerscorebyadj" - } - }, - { - "model": "auth.permission", - "pk": 127, - "fields": { - "name": "Can add team score", - "content_type": 43, - "codename": "add_teamscore" - } - }, - { - "model": "auth.permission", - "pk": 128, - "fields": { - "name": "Can change team score", - "content_type": 43, - "codename": "change_teamscore" - } - }, - { - "model": "auth.permission", - "pk": 129, - "fields": { - "name": "Can delete team score", - "content_type": 43, - "codename": "delete_teamscore" - } - }, - { - "model": "auth.permission", - "pk": 130, - "fields": { - "name": "Can add speaker score", - "content_type": 44, - "codename": "add_speakerscore" - } - }, - { - "model": "auth.permission", - "pk": 131, - "fields": { - "name": "Can change speaker score", - "content_type": 44, - "codename": "change_speakerscore" - } - }, - { - "model": "auth.permission", - "pk": 132, - "fields": { - "name": "Can delete speaker score", - "content_type": 44, - "codename": "delete_speakerscore" - } - }, - { - "model": "auth.permission", - "pk": 133, - "fields": { - "name": "Can add tournament", - "content_type": 45, - "codename": "add_tournament" - } - }, - { - "model": "auth.permission", - "pk": 134, - "fields": { - "name": "Can change tournament", - "content_type": 45, - "codename": "change_tournament" - } - }, - { - "model": "auth.permission", - "pk": 135, - "fields": { - "name": "Can delete tournament", - "content_type": 45, - "codename": "delete_tournament" - } - }, - { - "model": "auth.permission", - "pk": 136, - "fields": { - "name": "Can add division", - "content_type": 46, - "codename": "add_division" - } - }, - { - "model": "auth.permission", - "pk": 137, - "fields": { - "name": "Can change division", - "content_type": 46, - "codename": "change_division" - } - }, - { - "model": "auth.permission", - "pk": 138, - "fields": { - "name": "Can delete division", - "content_type": 46, - "codename": "delete_division" - } - }, - { - "model": "auth.permission", - "pk": 139, - "fields": { - "name": "Can add round", - "content_type": 47, - "codename": "add_round" - } - }, - { - "model": "auth.permission", - "pk": 140, - "fields": { - "name": "Can change round", - "content_type": 47, - "codename": "change_round" - } - }, - { - "model": "auth.permission", - "pk": 141, - "fields": { - "name": "Can delete round", - "content_type": 47, - "codename": "delete_round" - } - }, - { - "model": "auth.permission", - "pk": 142, - "fields": { - "name": "Can add venue group", - "content_type": 48, - "codename": "add_venuegroup" - } - }, - { - "model": "auth.permission", - "pk": 143, - "fields": { - "name": "Can change venue group", - "content_type": 48, - "codename": "change_venuegroup" - } - }, - { - "model": "auth.permission", - "pk": 144, - "fields": { - "name": "Can delete venue group", - "content_type": 48, - "codename": "delete_venuegroup" - } - }, - { - "model": "auth.permission", - "pk": 145, - "fields": { - "name": "Can add venue", - "content_type": 49, - "codename": "add_venue" - } - }, - { - "model": "auth.permission", - "pk": 146, - "fields": { - "name": "Can change venue", - "content_type": 49, - "codename": "change_venue" - } - }, - { - "model": "auth.permission", - "pk": 147, - "fields": { - "name": "Can delete venue", - "content_type": 49, - "codename": "delete_venue" - } - }, - { - "model": "auth.permission", - "pk": 148, - "fields": { - "name": "Can add global preference", - "content_type": 50, - "codename": "add_globalpreferencemodel" - } - }, - { - "model": "auth.permission", - "pk": 149, - "fields": { - "name": "Can change global preference", - "content_type": 50, - "codename": "change_globalpreferencemodel" - } - }, - { - "model": "auth.permission", - "pk": 150, - "fields": { - "name": "Can delete global preference", - "content_type": 50, - "codename": "delete_globalpreferencemodel" - } - }, - { - "model": "auth.permission", - "pk": 151, - "fields": { - "name": "Can add user preference", - "content_type": 51, - "codename": "add_userpreferencemodel" - } - }, - { - "model": "auth.permission", - "pk": 152, - "fields": { - "name": "Can change user preference", - "content_type": 51, - "codename": "change_userpreferencemodel" - } - }, - { - "model": "auth.permission", - "pk": 153, - "fields": { - "name": "Can delete user preference", - "content_type": 51, - "codename": "delete_userpreferencemodel" - } - }, - { - "model": "auth.user", - "pk": 1, - "fields": { - "password": "pbkdf2_sha256$24000$ZU59rBpnLzvD$g1h4H9wZ6a9Hgn0F3WwQNFC9RfZUH7omgeCvxqCdD7E=", - "last_login": "2016-05-16T13:49:56.575", - "is_superuser": true, - "username": "admin", - "first_name": "", - "last_name": "", - "email": "", - "is_staff": true, - "is_active": true, - "date_joined": "2016-04-14T13:17:48.740", - "groups": [], - "user_permissions": [] - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 1, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T13:21:06.434", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 1, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 2, - "fields": { - "type": "dr.conf", - "timestamp": "2016-04-14T13:21:10.527", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 1, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 3, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T13:21:51.229", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 2, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 4, - "fields": { - "type": "dr.conf", - "timestamp": "2016-04-14T13:21:55.770", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 2, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 5, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T13:22:30.913", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 3, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 6, - "fields": { - "type": "dr.conf", - "timestamp": "2016-04-14T13:22:39.537", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 3, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 7, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T13:24:55.099", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 4, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 8, - "fields": { - "type": "dr.conf", - "timestamp": "2016-04-14T13:25:00.527", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 4, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 9, - "fields": { - "type": "br.gene", - "timestamp": "2016-04-14T13:27:00.966", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 10, - "fields": { - "type": "br.el.edit", - "timestamp": "2016-04-14T13:38:03.231", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 11, - "fields": { - "type": "br.el.edit", - "timestamp": "2016-04-14T13:39:08.781", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 12, - "fields": { - "type": "br.el.edit", - "timestamp": "2016-04-14T13:39:18.554", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 13, - "fields": { - "type": "br.gene", - "timestamp": "2016-04-14T13:53:07.351", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 14, - "fields": { - "type": "av.aj.save", - "timestamp": "2016-04-14T13:56:01.510", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 15, - "fields": { - "type": "av.aj.save", - "timestamp": "2016-04-14T16:29:11.100", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 16, - "fields": { - "type": "av.aj.save", - "timestamp": "2016-04-14T16:38:46.302", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 17, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T17:22:18.358", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 18, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T17:43:52.159", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 19, - "fields": { - "type": "dr.conf", - "timestamp": "2016-04-14T18:01:43.200", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 20, - "fields": { - "type": "av.tm.save", - "timestamp": "2016-04-14T18:03:34.016", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 6, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 21, - "fields": { - "type": "br.rm.edit", - "timestamp": "2016-04-14T18:04:43.998", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 22, - "fields": { - "type": "br.rm.edit", - "timestamp": "2016-04-14T18:04:48.977", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 23, - "fields": { - "type": "av.ve.save", - "timestamp": "2016-04-14T18:05:18.958", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 6, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 24, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T18:06:05.427", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 6, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 25, - "fields": { - "type": "dr.conf", - "timestamp": "2016-04-14T18:06:12.381", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 6, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 26, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T21:47:56.684", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 6, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 27, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T22:05:25.305", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 6, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 28, - "fields": { - "type": "br.rm.edit", - "timestamp": "2016-04-14T22:15:58.623", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 29, - "fields": { - "type": "br.rm.edit", - "timestamp": "2016-04-14T22:16:11.181", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 30, - "fields": { - "type": "br.gene", - "timestamp": "2016-04-14T22:16:36.674", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 31, - "fields": { - "type": "av.tm.save", - "timestamp": "2016-04-14T22:18:41.742", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 32, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T22:25:35.394", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 33, - "fields": { - "type": "dr.conf", - "timestamp": "2016-04-14T22:25:38.639", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 34, - "fields": { - "type": "av.ve.save", - "timestamp": "2016-04-14T22:28:56.668", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 7, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 35, - "fields": { - "type": "dr.crea", - "timestamp": "2016-04-14T22:33:29.382", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 7, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 36, - "fields": { - "type": "dr.conf", - "timestamp": "2016-04-14T22:35:46.395", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 7, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 37, - "fields": { - "type": "op.edit", - "timestamp": "2016-04-24T15:34:35.349", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 38, - "fields": { - "type": "av.tm.save", - "timestamp": "2016-04-24T15:35:11.314", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 2, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 39, - "fields": { - "type": "op.edit", - "timestamp": "2016-04-24T15:38:02.715", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 40, - "fields": { - "type": "av.ve.save", - "timestamp": "2016-04-24T15:44:15.086", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 1, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 41, - "fields": { - "type": "av.aj.save", - "timestamp": "2016-04-24T15:44:24.404", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 1, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 45, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-01T21:53:16.267", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 46, - "fields": { - "type": "dr.rele", - "timestamp": "2016-05-01T21:53:31.708", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 1, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 47, - "fields": { - "type": "dr.rele", - "timestamp": "2016-05-01T21:53:32.588", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 2, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 48, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-01T22:27:46.395", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 49, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-01T22:36:55.463", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 50, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-01T22:43:09.912", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 69, - "fields": { - "type": "aa.save", - "timestamp": "2016-05-14T16:40:34.594", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 70, - "fields": { - "type": "aa.save", - "timestamp": "2016-05-14T16:40:48.792", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 71, - "fields": { - "type": "aa.save", - "timestamp": "2016-05-14T16:43:39.686", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 72, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-15T09:51:34.957", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 73, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-15T18:59:58.290", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 74, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-15T19:00:05.596", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 75, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-15T21:11:10.270", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 76, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-15T21:11:25.319", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 77, - "fields": { - "type": "dr.rege", - "timestamp": "2016-05-16T13:50:16.881", - "user": 1, - "ip_address": null, - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": 5, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 78, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-16T14:04:19.008", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "actionlog.actionlogentry", - "pk": 79, - "fields": { - "type": "op.edit", - "timestamp": "2016-05-16T18:24:00.929", - "user": 1, - "ip_address": "0.0.0.0", - "tournament": 1, - "debate": null, - "adjudicator": null, - "ballot_submission": null, - "adjudicator_test_score_history": null, - "adjudicator_feedback": null, - "round": null, - "motion": null, - "break_category": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 1, - "fields": { - "timestamp": "2016-04-14T13:21:34.759", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 12, - "motion": 3, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 2, - "fields": { - "timestamp": "2016-04-14T13:21:34.841", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 11, - "motion": 2, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 3, - "fields": { - "timestamp": "2016-04-14T13:21:34.914", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 10, - "motion": 2, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 4, - "fields": { - "timestamp": "2016-04-14T13:21:34.987", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 9, - "motion": 1, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 5, - "fields": { - "timestamp": "2016-04-14T13:21:35.057", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 8, - "motion": 3, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 6, - "fields": { - "timestamp": "2016-04-14T13:21:35.127", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 7, - "motion": 2, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 7, - "fields": { - "timestamp": "2016-04-14T13:21:35.198", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 6, - "motion": 2, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 8, - "fields": { - "timestamp": "2016-04-14T13:21:35.268", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 5, - "motion": 3, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 9, - "fields": { - "timestamp": "2016-04-14T13:21:35.398", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 4, - "motion": 1, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 10, - "fields": { - "timestamp": "2016-04-14T13:21:35.503", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 3, - "motion": 3, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 11, - "fields": { - "timestamp": "2016-04-14T13:21:35.654", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 2, - "motion": 1, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 12, - "fields": { - "timestamp": "2016-04-14T13:21:35.757", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 1, - "motion": 2, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 13, - "fields": { - "timestamp": "2016-04-14T13:22:17.975", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 24, - "motion": 4, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 14, - "fields": { - "timestamp": "2016-04-14T13:22:18.113", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 23, - "motion": 6, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 15, - "fields": { - "timestamp": "2016-04-14T13:22:18.193", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 22, - "motion": 5, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 16, - "fields": { - "timestamp": "2016-04-14T13:22:18.319", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 21, - "motion": 4, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 17, - "fields": { - "timestamp": "2016-04-14T13:22:18.475", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 20, - "motion": 4, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 18, - "fields": { - "timestamp": "2016-04-14T13:22:18.592", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 19, - "motion": 6, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 19, - "fields": { - "timestamp": "2016-04-14T13:22:18.666", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 18, - "motion": 6, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 20, - "fields": { - "timestamp": "2016-04-14T13:22:18.789", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 17, - "motion": 4, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 21, - "fields": { - "timestamp": "2016-04-14T13:22:18.909", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 16, - "motion": 4, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 22, - "fields": { - "timestamp": "2016-04-14T13:22:18.986", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 15, - "motion": 4, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 23, - "fields": { - "timestamp": "2016-04-14T13:22:19.061", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 14, - "motion": 5, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 24, - "fields": { - "timestamp": "2016-04-14T13:22:19.183", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 13, - "motion": 4, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 25, - "fields": { - "timestamp": "2016-04-14T13:23:01.130", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 25, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 26, - "fields": { - "timestamp": "2016-04-14T13:23:01.211", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 26, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 27, - "fields": { - "timestamp": "2016-04-14T13:23:01.279", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 27, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 28, - "fields": { - "timestamp": "2016-04-14T13:23:01.382", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 28, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 29, - "fields": { - "timestamp": "2016-04-14T13:23:01.490", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 29, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 30, - "fields": { - "timestamp": "2016-04-14T13:23:01.595", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 30, - "motion": 8, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 31, - "fields": { - "timestamp": "2016-04-14T13:23:01.664", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 31, - "motion": 7, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 32, - "fields": { - "timestamp": "2016-04-14T13:23:01.732", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 32, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 33, - "fields": { - "timestamp": "2016-04-14T13:23:01.800", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 33, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 34, - "fields": { - "timestamp": "2016-04-14T13:23:01.870", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 34, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 35, - "fields": { - "timestamp": "2016-04-14T13:23:02.052", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 35, - "motion": 9, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 36, - "fields": { - "timestamp": "2016-04-14T13:23:02.157", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 36, - "motion": 7, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 37, - "fields": { - "timestamp": "2016-04-14T13:25:54.869", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 37, - "motion": 12, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 38, - "fields": { - "timestamp": "2016-04-14T13:25:54.956", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 38, - "motion": 12, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 39, - "fields": { - "timestamp": "2016-04-14T13:25:55.027", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 39, - "motion": 12, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 40, - "fields": { - "timestamp": "2016-04-14T13:25:55.136", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 40, - "motion": 10, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 41, - "fields": { - "timestamp": "2016-04-14T13:25:55.246", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 41, - "motion": 12, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 42, - "fields": { - "timestamp": "2016-04-14T13:25:55.351", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 42, - "motion": 12, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 43, - "fields": { - "timestamp": "2016-04-14T13:25:55.486", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 43, - "motion": 12, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 44, - "fields": { - "timestamp": "2016-04-14T13:25:55.594", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 44, - "motion": 11, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 45, - "fields": { - "timestamp": "2016-04-14T13:25:55.665", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 45, - "motion": 12, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 46, - "fields": { - "timestamp": "2016-04-14T13:25:55.778", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 46, - "motion": 11, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 47, - "fields": { - "timestamp": "2016-04-14T13:25:55.854", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 47, - "motion": 11, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "results.ballotsubmission", - "pk": 48, - "fields": { - "timestamp": "2016-04-14T13:25:55.933", - "version": 1, - "submitter_type": "T", - "submitter": 1, - "confirmer": null, - "confirm_timestamp": null, - "ip_address": null, - "confirmed": true, - "debate": 48, - "motion": 12, - "copied_from": null, - "discarded": false, - "forfeit": null - } - }, - { - "model": "admin.logentry", - "pk": 1, - "fields": { - "action_time": "2016-04-14T13:26:29.906", - "user": 1, - "content_type": 45, - "object_id": "1", - "object_repr": "demo", - "action_flag": 2, - "change_message": "Changed current_round." - } - }, - { - "model": "admin.logentry", - "pk": 2, - "fields": { - "action_time": "2016-04-14T13:28:12.766", - "user": 1, - "content_type": 26, - "object_id": "24", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 3, - "fields": { - "action_time": "2016-04-14T13:28:12.772", - "user": 1, - "content_type": 26, - "object_id": "23", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 4, - "fields": { - "action_time": "2016-04-14T13:28:12.776", - "user": 1, - "content_type": 26, - "object_id": "22", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 5, - "fields": { - "action_time": "2016-04-14T13:28:12.781", - "user": 1, - "content_type": 26, - "object_id": "21", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 6, - "fields": { - "action_time": "2016-04-14T13:28:12.786", - "user": 1, - "content_type": 26, - "object_id": "20", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 7, - "fields": { - "action_time": "2016-04-14T13:28:12.790", - "user": 1, - "content_type": 26, - "object_id": "19", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 8, - "fields": { - "action_time": "2016-04-14T13:28:12.795", - "user": 1, - "content_type": 26, - "object_id": "18", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 9, - "fields": { - "action_time": "2016-04-14T13:28:12.800", - "user": 1, - "content_type": 26, - "object_id": "17", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 10, - "fields": { - "action_time": "2016-04-14T13:28:12.804", - "user": 1, - "content_type": 26, - "object_id": "16", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 11, - "fields": { - "action_time": "2016-04-14T13:28:12.809", - "user": 1, - "content_type": 26, - "object_id": "15", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 12, - "fields": { - "action_time": "2016-04-14T13:28:12.813", - "user": 1, - "content_type": 26, - "object_id": "14", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 13, - "fields": { - "action_time": "2016-04-14T13:28:12.818", - "user": 1, - "content_type": 26, - "object_id": "13", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 14, - "fields": { - "action_time": "2016-04-14T13:28:12.822", - "user": 1, - "content_type": 26, - "object_id": "12", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 15, - "fields": { - "action_time": "2016-04-14T13:28:12.827", - "user": 1, - "content_type": 26, - "object_id": "11", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 16, - "fields": { - "action_time": "2016-04-14T13:28:12.831", - "user": 1, - "content_type": 26, - "object_id": "10", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 17, - "fields": { - "action_time": "2016-04-14T13:28:12.836", - "user": 1, - "content_type": 26, - "object_id": "9", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 18, - "fields": { - "action_time": "2016-04-14T13:28:12.841", - "user": 1, - "content_type": 26, - "object_id": "8", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 19, - "fields": { - "action_time": "2016-04-14T13:28:12.846", - "user": 1, - "content_type": 26, - "object_id": "7", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 20, - "fields": { - "action_time": "2016-04-14T13:28:12.920", - "user": 1, - "content_type": 26, - "object_id": "6", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 21, - "fields": { - "action_time": "2016-04-14T13:28:12.924", - "user": 1, - "content_type": 26, - "object_id": "5", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 22, - "fields": { - "action_time": "2016-04-14T13:28:12.929", - "user": 1, - "content_type": 26, - "object_id": "4", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 23, - "fields": { - "action_time": "2016-04-14T13:28:12.934", - "user": 1, - "content_type": 26, - "object_id": "3", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 24, - "fields": { - "action_time": "2016-04-14T13:28:12.938", - "user": 1, - "content_type": 26, - "object_id": "2", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 25, - "fields": { - "action_time": "2016-04-14T13:28:12.942", - "user": 1, - "content_type": 26, - "object_id": "1", - "object_repr": "BreakingTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 26, - "fields": { - "action_time": "2016-04-14T13:55:15.082", - "user": 1, - "content_type": 23, - "object_id": "120", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 27, - "fields": { - "action_time": "2016-04-14T13:55:15.087", - "user": 1, - "content_type": 23, - "object_id": "119", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 28, - "fields": { - "action_time": "2016-04-14T13:55:15.092", - "user": 1, - "content_type": 23, - "object_id": "118", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 29, - "fields": { - "action_time": "2016-04-14T13:55:15.096", - "user": 1, - "content_type": 23, - "object_id": "117", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 30, - "fields": { - "action_time": "2016-04-14T13:55:15.101", - "user": 1, - "content_type": 23, - "object_id": "116", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 31, - "fields": { - "action_time": "2016-04-14T13:55:15.105", - "user": 1, - "content_type": 23, - "object_id": "115", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 32, - "fields": { - "action_time": "2016-04-14T13:55:15.109", - "user": 1, - "content_type": 23, - "object_id": "114", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 33, - "fields": { - "action_time": "2016-04-14T13:55:15.114", - "user": 1, - "content_type": 23, - "object_id": "113", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 34, - "fields": { - "action_time": "2016-04-14T13:55:15.118", - "user": 1, - "content_type": 23, - "object_id": "112", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 35, - "fields": { - "action_time": "2016-04-14T13:55:15.122", - "user": 1, - "content_type": 23, - "object_id": "111", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 36, - "fields": { - "action_time": "2016-04-14T13:55:15.126", - "user": 1, - "content_type": 23, - "object_id": "110", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 37, - "fields": { - "action_time": "2016-04-14T13:55:15.131", - "user": 1, - "content_type": 23, - "object_id": "109", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 38, - "fields": { - "action_time": "2016-04-14T13:55:15.135", - "user": 1, - "content_type": 23, - "object_id": "108", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 39, - "fields": { - "action_time": "2016-04-14T13:55:15.140", - "user": 1, - "content_type": 23, - "object_id": "107", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 40, - "fields": { - "action_time": "2016-04-14T13:55:15.144", - "user": 1, - "content_type": 23, - "object_id": "106", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 41, - "fields": { - "action_time": "2016-04-14T13:55:15.149", - "user": 1, - "content_type": 23, - "object_id": "105", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 42, - "fields": { - "action_time": "2016-04-14T13:55:15.153", - "user": 1, - "content_type": 23, - "object_id": "104", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 43, - "fields": { - "action_time": "2016-04-14T13:55:15.158", - "user": 1, - "content_type": 23, - "object_id": "103", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 44, - "fields": { - "action_time": "2016-04-14T13:55:15.162", - "user": 1, - "content_type": 23, - "object_id": "102", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 45, - "fields": { - "action_time": "2016-04-14T13:55:15.166", - "user": 1, - "content_type": 23, - "object_id": "101", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 46, - "fields": { - "action_time": "2016-04-14T13:55:15.171", - "user": 1, - "content_type": 23, - "object_id": "100", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 47, - "fields": { - "action_time": "2016-04-14T13:55:15.176", - "user": 1, - "content_type": 23, - "object_id": "99", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 48, - "fields": { - "action_time": "2016-04-14T13:55:15.180", - "user": 1, - "content_type": 23, - "object_id": "98", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 49, - "fields": { - "action_time": "2016-04-14T13:55:15.184", - "user": 1, - "content_type": 23, - "object_id": "97", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 50, - "fields": { - "action_time": "2016-04-14T13:55:15.195", - "user": 1, - "content_type": 23, - "object_id": "96", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 51, - "fields": { - "action_time": "2016-04-14T13:55:15.205", - "user": 1, - "content_type": 23, - "object_id": "95", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 52, - "fields": { - "action_time": "2016-04-14T13:55:15.215", - "user": 1, - "content_type": 23, - "object_id": "94", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 53, - "fields": { - "action_time": "2016-04-14T13:55:15.224", - "user": 1, - "content_type": 23, - "object_id": "93", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 54, - "fields": { - "action_time": "2016-04-14T13:55:15.229", - "user": 1, - "content_type": 23, - "object_id": "92", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 55, - "fields": { - "action_time": "2016-04-14T13:55:15.233", - "user": 1, - "content_type": 23, - "object_id": "91", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 56, - "fields": { - "action_time": "2016-04-14T13:55:15.242", - "user": 1, - "content_type": 23, - "object_id": "90", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 57, - "fields": { - "action_time": "2016-04-14T13:55:15.253", - "user": 1, - "content_type": 23, - "object_id": "89", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 58, - "fields": { - "action_time": "2016-04-14T13:55:15.263", - "user": 1, - "content_type": 23, - "object_id": "88", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 59, - "fields": { - "action_time": "2016-04-14T13:55:15.268", - "user": 1, - "content_type": 23, - "object_id": "87", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 60, - "fields": { - "action_time": "2016-04-14T13:55:15.272", - "user": 1, - "content_type": 23, - "object_id": "86", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 61, - "fields": { - "action_time": "2016-04-14T13:55:15.277", - "user": 1, - "content_type": 23, - "object_id": "85", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 62, - "fields": { - "action_time": "2016-04-14T13:55:15.282", - "user": 1, - "content_type": 23, - "object_id": "84", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 63, - "fields": { - "action_time": "2016-04-14T13:55:15.286", - "user": 1, - "content_type": 23, - "object_id": "83", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 64, - "fields": { - "action_time": "2016-04-14T13:55:15.291", - "user": 1, - "content_type": 23, - "object_id": "82", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 65, - "fields": { - "action_time": "2016-04-14T13:55:15.296", - "user": 1, - "content_type": 23, - "object_id": "81", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 66, - "fields": { - "action_time": "2016-04-14T13:55:15.300", - "user": 1, - "content_type": 23, - "object_id": "80", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 67, - "fields": { - "action_time": "2016-04-14T13:55:15.305", - "user": 1, - "content_type": 23, - "object_id": "79", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 68, - "fields": { - "action_time": "2016-04-14T13:55:15.309", - "user": 1, - "content_type": 23, - "object_id": "78", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 69, - "fields": { - "action_time": "2016-04-14T13:55:15.313", - "user": 1, - "content_type": 23, - "object_id": "77", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 70, - "fields": { - "action_time": "2016-04-14T13:55:15.318", - "user": 1, - "content_type": 23, - "object_id": "76", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 71, - "fields": { - "action_time": "2016-04-14T13:55:15.322", - "user": 1, - "content_type": 23, - "object_id": "75", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 72, - "fields": { - "action_time": "2016-04-14T13:55:15.326", - "user": 1, - "content_type": 23, - "object_id": "74", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 73, - "fields": { - "action_time": "2016-04-14T13:55:15.331", - "user": 1, - "content_type": 23, - "object_id": "73", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 74, - "fields": { - "action_time": "2016-04-14T13:55:15.336", - "user": 1, - "content_type": 23, - "object_id": "72", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 75, - "fields": { - "action_time": "2016-04-14T13:55:15.340", - "user": 1, - "content_type": 23, - "object_id": "71", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 76, - "fields": { - "action_time": "2016-04-14T13:55:15.344", - "user": 1, - "content_type": 23, - "object_id": "70", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 77, - "fields": { - "action_time": "2016-04-14T13:55:15.349", - "user": 1, - "content_type": 23, - "object_id": "69", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 78, - "fields": { - "action_time": "2016-04-14T13:55:15.354", - "user": 1, - "content_type": 23, - "object_id": "68", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 79, - "fields": { - "action_time": "2016-04-14T13:55:15.358", - "user": 1, - "content_type": 23, - "object_id": "67", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 80, - "fields": { - "action_time": "2016-04-14T13:55:15.363", - "user": 1, - "content_type": 23, - "object_id": "66", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 81, - "fields": { - "action_time": "2016-04-14T13:55:15.368", - "user": 1, - "content_type": 23, - "object_id": "65", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 82, - "fields": { - "action_time": "2016-04-14T13:55:15.372", - "user": 1, - "content_type": 23, - "object_id": "64", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 83, - "fields": { - "action_time": "2016-04-14T13:55:15.376", - "user": 1, - "content_type": 23, - "object_id": "63", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 84, - "fields": { - "action_time": "2016-04-14T13:55:15.381", - "user": 1, - "content_type": 23, - "object_id": "62", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 85, - "fields": { - "action_time": "2016-04-14T13:55:15.386", - "user": 1, - "content_type": 23, - "object_id": "61", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 86, - "fields": { - "action_time": "2016-04-14T13:55:15.391", - "user": 1, - "content_type": 23, - "object_id": "60", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 87, - "fields": { - "action_time": "2016-04-14T13:55:15.395", - "user": 1, - "content_type": 23, - "object_id": "59", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 88, - "fields": { - "action_time": "2016-04-14T13:55:15.400", - "user": 1, - "content_type": 23, - "object_id": "58", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 89, - "fields": { - "action_time": "2016-04-14T13:55:15.404", - "user": 1, - "content_type": 23, - "object_id": "57", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 90, - "fields": { - "action_time": "2016-04-14T13:55:15.409", - "user": 1, - "content_type": 23, - "object_id": "56", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 91, - "fields": { - "action_time": "2016-04-14T13:55:15.413", - "user": 1, - "content_type": 23, - "object_id": "55", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 92, - "fields": { - "action_time": "2016-04-14T13:55:15.417", - "user": 1, - "content_type": 23, - "object_id": "54", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 93, - "fields": { - "action_time": "2016-04-14T13:55:15.421", - "user": 1, - "content_type": 23, - "object_id": "53", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 94, - "fields": { - "action_time": "2016-04-14T13:55:15.425", - "user": 1, - "content_type": 23, - "object_id": "52", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 95, - "fields": { - "action_time": "2016-04-14T13:55:15.430", - "user": 1, - "content_type": 23, - "object_id": "51", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 96, - "fields": { - "action_time": "2016-04-14T13:55:15.434", - "user": 1, - "content_type": 23, - "object_id": "50", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 97, - "fields": { - "action_time": "2016-04-14T13:55:15.438", - "user": 1, - "content_type": 23, - "object_id": "49", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 98, - "fields": { - "action_time": "2016-04-14T13:55:15.443", - "user": 1, - "content_type": 23, - "object_id": "48", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 99, - "fields": { - "action_time": "2016-04-14T13:55:15.448", - "user": 1, - "content_type": 23, - "object_id": "47", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 100, - "fields": { - "action_time": "2016-04-14T13:55:15.453", - "user": 1, - "content_type": 23, - "object_id": "46", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 101, - "fields": { - "action_time": "2016-04-14T13:55:15.457", - "user": 1, - "content_type": 23, - "object_id": "45", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 102, - "fields": { - "action_time": "2016-04-14T13:55:15.462", - "user": 1, - "content_type": 23, - "object_id": "44", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 103, - "fields": { - "action_time": "2016-04-14T13:55:15.466", - "user": 1, - "content_type": 23, - "object_id": "43", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 104, - "fields": { - "action_time": "2016-04-14T13:55:15.471", - "user": 1, - "content_type": 23, - "object_id": "42", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 105, - "fields": { - "action_time": "2016-04-14T13:55:15.476", - "user": 1, - "content_type": 23, - "object_id": "41", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 106, - "fields": { - "action_time": "2016-04-14T13:55:15.480", - "user": 1, - "content_type": 23, - "object_id": "40", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 107, - "fields": { - "action_time": "2016-04-14T13:55:15.484", - "user": 1, - "content_type": 23, - "object_id": "39", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 108, - "fields": { - "action_time": "2016-04-14T13:55:15.489", - "user": 1, - "content_type": 23, - "object_id": "38", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 109, - "fields": { - "action_time": "2016-04-14T13:55:15.493", - "user": 1, - "content_type": 23, - "object_id": "37", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 110, - "fields": { - "action_time": "2016-04-14T13:55:15.498", - "user": 1, - "content_type": 23, - "object_id": "36", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 111, - "fields": { - "action_time": "2016-04-14T13:55:15.502", - "user": 1, - "content_type": 23, - "object_id": "35", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 112, - "fields": { - "action_time": "2016-04-14T13:55:15.506", - "user": 1, - "content_type": 23, - "object_id": "34", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 113, - "fields": { - "action_time": "2016-04-14T13:55:15.511", - "user": 1, - "content_type": 23, - "object_id": "33", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 114, - "fields": { - "action_time": "2016-04-14T13:55:15.515", - "user": 1, - "content_type": 23, - "object_id": "32", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 115, - "fields": { - "action_time": "2016-04-14T13:55:15.520", - "user": 1, - "content_type": 23, - "object_id": "31", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 116, - "fields": { - "action_time": "2016-04-14T13:55:15.524", - "user": 1, - "content_type": 23, - "object_id": "30", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 117, - "fields": { - "action_time": "2016-04-14T13:55:15.529", - "user": 1, - "content_type": 23, - "object_id": "29", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 118, - "fields": { - "action_time": "2016-04-14T13:55:15.534", - "user": 1, - "content_type": 23, - "object_id": "28", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 119, - "fields": { - "action_time": "2016-04-14T13:55:15.538", - "user": 1, - "content_type": 23, - "object_id": "27", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 120, - "fields": { - "action_time": "2016-04-14T13:55:15.542", - "user": 1, - "content_type": 23, - "object_id": "26", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 121, - "fields": { - "action_time": "2016-04-14T13:55:15.547", - "user": 1, - "content_type": 23, - "object_id": "25", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 122, - "fields": { - "action_time": "2016-04-14T13:55:15.552", - "user": 1, - "content_type": 23, - "object_id": "24", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 123, - "fields": { - "action_time": "2016-04-14T13:55:15.557", - "user": 1, - "content_type": 23, - "object_id": "23", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 124, - "fields": { - "action_time": "2016-04-14T13:55:15.561", - "user": 1, - "content_type": 23, - "object_id": "22", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 125, - "fields": { - "action_time": "2016-04-14T13:55:15.566", - "user": 1, - "content_type": 23, - "object_id": "21", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 126, - "fields": { - "action_time": "2016-04-14T17:43:48.050", - "user": 1, - "content_type": 47, - "object_id": "5", - "object_repr": "demo - Open Quarterfinal", - "action_flag": 2, - "change_message": "Changed draw_status." - } - }, - { - "model": "admin.logentry", - "pk": 127, - "fields": { - "action_time": "2016-04-14T21:47:44.613", - "user": 1, - "content_type": 47, - "object_id": "6", - "object_repr": "demo - ESL Semifinal", - "action_flag": 2, - "change_message": "Changed draw_status." - } - }, - { - "model": "admin.logentry", - "pk": 128, - "fields": { - "action_time": "2016-04-14T21:47:47.557", - "user": 1, - "content_type": 23, - "object_id": "139", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 129, - "fields": { - "action_time": "2016-04-14T21:47:47.563", - "user": 1, - "content_type": 23, - "object_id": "138", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 130, - "fields": { - "action_time": "2016-04-14T21:47:47.567", - "user": 1, - "content_type": 23, - "object_id": "137", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 131, - "fields": { - "action_time": "2016-04-14T21:47:47.571", - "user": 1, - "content_type": 23, - "object_id": "136", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 132, - "fields": { - "action_time": "2016-04-14T21:59:23.337", - "user": 1, - "content_type": 47, - "object_id": "6", - "object_repr": "demo - ESL Semifinal", - "action_flag": 2, - "change_message": "Changed draw_status." - } - }, - { - "model": "admin.logentry", - "pk": 133, - "fields": { - "action_time": "2016-04-14T22:05:36.581", - "user": 1, - "content_type": 47, - "object_id": "6", - "object_repr": "demo - ESL Semifinal", - "action_flag": 2, - "change_message": "Changed draw_status." - } - }, - { - "model": "admin.logentry", - "pk": 134, - "fields": { - "action_time": "2016-04-14T22:07:37.399", - "user": 1, - "content_type": 47, - "object_id": "5", - "object_repr": "demo - Open Quarterfinal", - "action_flag": 2, - "change_message": "Changed draw_status." - } - }, - { - "model": "admin.logentry", - "pk": 135, - "fields": { - "action_time": "2016-04-14T22:07:46.463", - "user": 1, - "content_type": 23, - "object_id": "128", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 136, - "fields": { - "action_time": "2016-04-14T22:07:46.469", - "user": 1, - "content_type": 23, - "object_id": "127", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 137, - "fields": { - "action_time": "2016-04-14T22:07:46.474", - "user": 1, - "content_type": 23, - "object_id": "126", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 138, - "fields": { - "action_time": "2016-04-14T22:07:46.478", - "user": 1, - "content_type": 23, - "object_id": "125", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 139, - "fields": { - "action_time": "2016-04-14T22:07:46.482", - "user": 1, - "content_type": 23, - "object_id": "124", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 140, - "fields": { - "action_time": "2016-04-14T22:07:46.486", - "user": 1, - "content_type": 23, - "object_id": "123", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 141, - "fields": { - "action_time": "2016-04-14T22:07:46.491", - "user": 1, - "content_type": 23, - "object_id": "122", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 142, - "fields": { - "action_time": "2016-04-14T22:07:46.495", - "user": 1, - "content_type": 23, - "object_id": "121", - "object_repr": "ActiveTeam object", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 143, - "fields": { - "action_time": "2016-04-24T11:54:17.877", - "user": 1, - "content_type": 45, - "object_id": "2", - "object_repr": "Test", - "action_flag": 1, - "change_message": "Added." - } - }, - { - "model": "admin.logentry", - "pk": 144, - "fields": { - "action_time": "2016-04-24T11:54:48.689", - "user": 1, - "content_type": 47, - "object_id": "11", - "object_repr": "Test - 1", - "action_flag": 1, - "change_message": "Added." - } - }, - { - "model": "admin.logentry", - "pk": 145, - "fields": { - "action_time": "2016-04-24T15:39:59.911", - "user": 1, - "content_type": 49, - "object_id": "2", - "object_repr": "1 - M05", - "action_flag": 2, - "change_message": "Changed tournament." - } - }, - { - "model": "admin.logentry", - "pk": 146, - "fields": { - "action_time": "2016-05-01T22:28:49.579", - "user": 1, - "content_type": 40, - "object_id": "106", - "object_repr": "An Adjudicator (Caltech)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 147, - "fields": { - "action_time": "2016-05-01T22:28:49.658", - "user": 1, - "content_type": 40, - "object_id": "100", - "object_repr": "An Adjudicator (Caltech)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 148, - "fields": { - "action_time": "2016-05-01T22:28:49.668", - "user": 1, - "content_type": 40, - "object_id": "101", - "object_repr": "An Adjudicator (Caltech)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 149, - "fields": { - "action_time": "2016-05-01T22:28:49.673", - "user": 1, - "content_type": 40, - "object_id": "102", - "object_repr": "An Adjudicator (Caltech)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 150, - "fields": { - "action_time": "2016-05-01T22:28:49.677", - "user": 1, - "content_type": 40, - "object_id": "103", - "object_repr": "An Adjudicator (Caltech)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 151, - "fields": { - "action_time": "2016-05-01T22:28:49.682", - "user": 1, - "content_type": 40, - "object_id": "107", - "object_repr": "An Adjudicator (Caltech)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 152, - "fields": { - "action_time": "2016-05-01T22:28:49.687", - "user": 1, - "content_type": 40, - "object_id": "105", - "object_repr": "An Adjudicator (Columbia)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 153, - "fields": { - "action_time": "2016-05-01T22:28:49.691", - "user": 1, - "content_type": 40, - "object_id": "104", - "object_repr": "An Adjudicator (Columbia)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 154, - "fields": { - "action_time": "2016-05-01T22:28:49.696", - "user": 1, - "content_type": 40, - "object_id": "108", - "object_repr": "An Adjudicator (Columbia)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 155, - "fields": { - "action_time": "2016-05-01T22:28:49.701", - "user": 1, - "content_type": 40, - "object_id": "111", - "object_repr": "An Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 156, - "fields": { - "action_time": "2016-05-01T22:28:49.706", - "user": 1, - "content_type": 40, - "object_id": "147", - "object_repr": "An Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 157, - "fields": { - "action_time": "2016-05-01T22:28:49.710", - "user": 1, - "content_type": 40, - "object_id": "146", - "object_repr": "An Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 158, - "fields": { - "action_time": "2016-05-01T22:28:49.714", - "user": 1, - "content_type": 40, - "object_id": "109", - "object_repr": "An Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 159, - "fields": { - "action_time": "2016-05-01T22:28:49.719", - "user": 1, - "content_type": 40, - "object_id": "110", - "object_repr": "An Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 160, - "fields": { - "action_time": "2016-05-01T22:28:49.723", - "user": 1, - "content_type": 40, - "object_id": "148", - "object_repr": "An Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 161, - "fields": { - "action_time": "2016-05-01T22:28:49.727", - "user": 1, - "content_type": 40, - "object_id": "112", - "object_repr": "An Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 162, - "fields": { - "action_time": "2016-05-01T22:28:49.731", - "user": 1, - "content_type": 40, - "object_id": "113", - "object_repr": "An Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 163, - "fields": { - "action_time": "2016-05-01T22:28:49.737", - "user": 1, - "content_type": 40, - "object_id": "128", - "object_repr": "An Adjudicator1 (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 164, - "fields": { - "action_time": "2016-05-01T22:28:49.741", - "user": 1, - "content_type": 40, - "object_id": "119", - "object_repr": "An Adjudicator1 (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 165, - "fields": { - "action_time": "2016-05-01T22:28:49.745", - "user": 1, - "content_type": 40, - "object_id": "137", - "object_repr": "An Adjudicator1 (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 166, - "fields": { - "action_time": "2016-05-01T22:28:49.749", - "user": 1, - "content_type": 40, - "object_id": "129", - "object_repr": "An Adjudicator2 (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 167, - "fields": { - "action_time": "2016-05-01T22:28:49.754", - "user": 1, - "content_type": 40, - "object_id": "120", - "object_repr": "An Adjudicator2 (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 168, - "fields": { - "action_time": "2016-05-01T22:28:49.759", - "user": 1, - "content_type": 40, - "object_id": "138", - "object_repr": "An Adjudicator2 (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 169, - "fields": { - "action_time": "2016-05-01T22:28:49.764", - "user": 1, - "content_type": 40, - "object_id": "121", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 170, - "fields": { - "action_time": "2016-05-01T22:28:49.770", - "user": 1, - "content_type": 40, - "object_id": "114", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 171, - "fields": { - "action_time": "2016-05-01T22:28:49.774", - "user": 1, - "content_type": 40, - "object_id": "115", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 172, - "fields": { - "action_time": "2016-05-01T22:28:49.778", - "user": 1, - "content_type": 40, - "object_id": "116", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 173, - "fields": { - "action_time": "2016-05-01T22:28:49.782", - "user": 1, - "content_type": 40, - "object_id": "117", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 174, - "fields": { - "action_time": "2016-05-01T22:28:49.788", - "user": 1, - "content_type": 40, - "object_id": "118", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 175, - "fields": { - "action_time": "2016-05-01T22:28:49.793", - "user": 1, - "content_type": 40, - "object_id": "122", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 176, - "fields": { - "action_time": "2016-05-01T22:28:49.796", - "user": 1, - "content_type": 40, - "object_id": "130", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 177, - "fields": { - "action_time": "2016-05-01T22:28:49.802", - "user": 1, - "content_type": 40, - "object_id": "131", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 178, - "fields": { - "action_time": "2016-05-01T22:28:49.808", - "user": 1, - "content_type": 40, - "object_id": "139", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 179, - "fields": { - "action_time": "2016-05-01T22:28:49.812", - "user": 1, - "content_type": 40, - "object_id": "140", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 180, - "fields": { - "action_time": "2016-05-01T22:28:49.817", - "user": 1, - "content_type": 40, - "object_id": "149", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 181, - "fields": { - "action_time": "2016-05-01T22:28:49.822", - "user": 1, - "content_type": 40, - "object_id": "150", - "object_repr": "An Adjudicator (Harvard)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 182, - "fields": { - "action_time": "2016-05-01T22:28:49.826", - "user": 1, - "content_type": 40, - "object_id": "132", - "object_repr": "An Adjudicator (Johns Hopkins)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 183, - "fields": { - "action_time": "2016-05-01T22:28:49.829", - "user": 1, - "content_type": 40, - "object_id": "141", - "object_repr": "An Adjudicator (Johns Hopkins)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 184, - "fields": { - "action_time": "2016-05-01T22:28:49.834", - "user": 1, - "content_type": 40, - "object_id": "123", - "object_repr": "An Adjudicator (Johns Hopkins)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 185, - "fields": { - "action_time": "2016-05-01T22:28:49.839", - "user": 1, - "content_type": 40, - "object_id": "151", - "object_repr": "An Adjudicator (Johns Hopkins)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 186, - "fields": { - "action_time": "2016-05-01T22:28:49.843", - "user": 1, - "content_type": 40, - "object_id": "155", - "object_repr": "An Adjudicator (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 187, - "fields": { - "action_time": "2016-05-01T22:28:49.847", - "user": 1, - "content_type": 40, - "object_id": "152", - "object_repr": "An Adjudicator (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 188, - "fields": { - "action_time": "2016-05-01T22:28:49.851", - "user": 1, - "content_type": 40, - "object_id": "153", - "object_repr": "An Adjudicator (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 189, - "fields": { - "action_time": "2016-05-01T22:28:49.856", - "user": 1, - "content_type": 40, - "object_id": "154", - "object_repr": "An Adjudicator (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 190, - "fields": { - "action_time": "2016-05-01T22:28:49.860", - "user": 1, - "content_type": 40, - "object_id": "133", - "object_repr": "An Adjudicator1 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 191, - "fields": { - "action_time": "2016-05-01T22:28:49.873", - "user": 1, - "content_type": 40, - "object_id": "124", - "object_repr": "An Adjudicator1 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 192, - "fields": { - "action_time": "2016-05-01T22:28:49.877", - "user": 1, - "content_type": 40, - "object_id": "142", - "object_repr": "An Adjudicator1 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 193, - "fields": { - "action_time": "2016-05-01T22:28:49.882", - "user": 1, - "content_type": 40, - "object_id": "134", - "object_repr": "An Adjudicator2 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 194, - "fields": { - "action_time": "2016-05-01T22:28:49.886", - "user": 1, - "content_type": 40, - "object_id": "125", - "object_repr": "An Adjudicator2 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 195, - "fields": { - "action_time": "2016-05-01T22:28:49.891", - "user": 1, - "content_type": 40, - "object_id": "143", - "object_repr": "An Adjudicator2 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 196, - "fields": { - "action_time": "2016-05-01T22:28:49.895", - "user": 1, - "content_type": 40, - "object_id": "135", - "object_repr": "An Adjudicator3 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 197, - "fields": { - "action_time": "2016-05-01T22:28:49.900", - "user": 1, - "content_type": 40, - "object_id": "126", - "object_repr": "An Adjudicator3 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 198, - "fields": { - "action_time": "2016-05-01T22:28:49.905", - "user": 1, - "content_type": 40, - "object_id": "144", - "object_repr": "An Adjudicator3 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 199, - "fields": { - "action_time": "2016-05-01T22:28:49.910", - "user": 1, - "content_type": 40, - "object_id": "145", - "object_repr": "An Adjudicator4 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 200, - "fields": { - "action_time": "2016-05-01T22:28:49.915", - "user": 1, - "content_type": 40, - "object_id": "127", - "object_repr": "An Adjudicator4 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 201, - "fields": { - "action_time": "2016-05-01T22:28:49.919", - "user": 1, - "content_type": 40, - "object_id": "136", - "object_repr": "An Adjudicator4 (Princeton)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 202, - "fields": { - "action_time": "2016-05-01T22:29:23.853", - "user": 1, - "content_type": 40, - "object_id": "156", - "object_repr": "New Adjudicator Shared (Caltech)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 203, - "fields": { - "action_time": "2016-05-01T22:29:23.858", - "user": 1, - "content_type": 40, - "object_id": "157", - "object_repr": "New Adjudicator Shared (Columbia)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 204, - "fields": { - "action_time": "2016-05-01T22:29:47.358", - "user": 1, - "content_type": 40, - "object_id": "158", - "object_repr": "New Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 205, - "fields": { - "action_time": "2016-05-01T22:29:47.363", - "user": 1, - "content_type": 40, - "object_id": "161", - "object_repr": "New Adjudicator (Cornell)", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 206, - "fields": { - "action_time": "2016-05-12T00:13:12.641", - "user": 1, - "content_type": 45, - "object_id": "3", - "object_repr": "New DM", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 207, - "fields": { - "action_time": "2016-05-12T00:13:12.740", - "user": 1, - "content_type": 45, - "object_id": "2", - "object_repr": "Test", - "action_flag": 3, - "change_message": "" - } - }, - { - "model": "admin.logentry", - "pk": 208, - "fields": { - "action_time": "2016-05-14T16:44:04.284", - "user": 1, - "content_type": 40, - "object_id": "89", - "object_repr": "Jo Allen (Princeton)", - "action_flag": 2, - "change_message": "Added adjudicator-team conflict \"AdjudicatorConflict object\"." - } - }, - { - "model": "admin.logentry", - "pk": 209, - "fields": { - "action_time": "2016-05-16T13:57:32.785", - "user": 1, - "content_type": 45, - "object_id": "1", - "object_repr": "demo", - "action_flag": 2, - "change_message": "Changed current_round." - } - } -] \ No newline at end of file +[{"model": "contenttypes.contenttype", "pk": 1, "fields": {"app_label": "jet", "model": "bookmark"}}, {"model": "contenttypes.contenttype", "pk": 2, "fields": {"app_label": "jet", "model": "pinnedapplication"}}, {"model": "contenttypes.contenttype", "pk": 3, "fields": {"app_label": "admin", "model": "logentry"}}, {"model": "contenttypes.contenttype", "pk": 4, "fields": {"app_label": "auth", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 5, "fields": {"app_label": "auth", "model": "group"}}, {"model": "contenttypes.contenttype", "pk": 6, "fields": {"app_label": "auth", "model": "user"}}, {"model": "contenttypes.contenttype", "pk": 7, "fields": {"app_label": "contenttypes", "model": "contenttype"}}, {"model": "contenttypes.contenttype", "pk": 8, "fields": {"app_label": "sessions", "model": "session"}}, {"model": "contenttypes.contenttype", "pk": 9, "fields": {"app_label": "actionlog", "model": "actionlogentry"}}, {"model": "contenttypes.contenttype", "pk": 10, "fields": {"app_label": "adjallocation", "model": "debateadjudicator"}}, {"model": "contenttypes.contenttype", "pk": 11, "fields": {"app_label": "adjallocation", "model": "adjudicatorconflict"}}, {"model": "contenttypes.contenttype", "pk": 12, "fields": {"app_label": "adjallocation", "model": "adjudicatoradjudicatorconflict"}}, {"model": "contenttypes.contenttype", "pk": 13, "fields": {"app_label": "adjallocation", "model": "adjudicatorinstitutionconflict"}}, {"model": "contenttypes.contenttype", "pk": 14, "fields": {"app_label": "adjfeedback", "model": "adjudicatortestscorehistory"}}, {"model": "contenttypes.contenttype", "pk": 15, "fields": {"app_label": "adjfeedback", "model": "adjudicatorfeedbackbooleananswer"}}, {"model": "contenttypes.contenttype", "pk": 16, "fields": {"app_label": "adjfeedback", "model": "adjudicatorfeedbackintegeranswer"}}, {"model": "contenttypes.contenttype", "pk": 17, "fields": {"app_label": "adjfeedback", "model": "adjudicatorfeedbackfloatanswer"}}, {"model": "contenttypes.contenttype", "pk": 18, "fields": {"app_label": "adjfeedback", "model": "adjudicatorfeedbackstringanswer"}}, {"model": "contenttypes.contenttype", "pk": 19, "fields": {"app_label": "adjfeedback", "model": "adjudicatorfeedbackquestion"}}, {"model": "contenttypes.contenttype", "pk": 20, "fields": {"app_label": "adjfeedback", "model": "adjudicatorfeedback"}}, {"model": "contenttypes.contenttype", "pk": 21, "fields": {"app_label": "availability", "model": "checkin"}}, {"model": "contenttypes.contenttype", "pk": 22, "fields": {"app_label": "availability", "model": "activevenue"}}, {"model": "contenttypes.contenttype", "pk": 23, "fields": {"app_label": "availability", "model": "activeteam"}}, {"model": "contenttypes.contenttype", "pk": 24, "fields": {"app_label": "availability", "model": "activeadjudicator"}}, {"model": "contenttypes.contenttype", "pk": 25, "fields": {"app_label": "breakqual", "model": "breakcategory"}}, {"model": "contenttypes.contenttype", "pk": 26, "fields": {"app_label": "breakqual", "model": "breakingteam"}}, {"model": "contenttypes.contenttype", "pk": 27, "fields": {"app_label": "divisions", "model": "division"}}, {"model": "contenttypes.contenttype", "pk": 28, "fields": {"app_label": "draw", "model": "debate"}}, {"model": "contenttypes.contenttype", "pk": 29, "fields": {"app_label": "draw", "model": "debateteam"}}, {"model": "contenttypes.contenttype", "pk": 30, "fields": {"app_label": "draw", "model": "teampositionallocation"}}, {"model": "contenttypes.contenttype", "pk": 31, "fields": {"app_label": "motions", "model": "motion"}}, {"model": "contenttypes.contenttype", "pk": 32, "fields": {"app_label": "motions", "model": "debateteammotionpreference"}}, {"model": "contenttypes.contenttype", "pk": 33, "fields": {"app_label": "options", "model": "tournamentpreferencemodel"}}, {"model": "contenttypes.contenttype", "pk": 34, "fields": {"app_label": "participants", "model": "region"}}, {"model": "contenttypes.contenttype", "pk": 35, "fields": {"app_label": "participants", "model": "institution"}}, {"model": "contenttypes.contenttype", "pk": 36, "fields": {"app_label": "participants", "model": "person"}}, {"model": "contenttypes.contenttype", "pk": 37, "fields": {"app_label": "participants", "model": "team"}}, {"model": "contenttypes.contenttype", "pk": 38, "fields": {"app_label": "participants", "model": "speaker"}}, {"model": "contenttypes.contenttype", "pk": 39, "fields": {"app_label": "participants", "model": "adjudicator"}}, {"model": "contenttypes.contenttype", "pk": 40, "fields": {"app_label": "results", "model": "ballotsubmission"}}, {"model": "contenttypes.contenttype", "pk": 41, "fields": {"app_label": "results", "model": "speakerscorebyadj"}}, {"model": "contenttypes.contenttype", "pk": 42, "fields": {"app_label": "results", "model": "teamscore"}}, {"model": "contenttypes.contenttype", "pk": 43, "fields": {"app_label": "results", "model": "speakerscore"}}, {"model": "contenttypes.contenttype", "pk": 44, "fields": {"app_label": "tournaments", "model": "tournament"}}, {"model": "contenttypes.contenttype", "pk": 45, "fields": {"app_label": "tournaments", "model": "round"}}, {"model": "contenttypes.contenttype", "pk": 46, "fields": {"app_label": "venues", "model": "venuegroup"}}, {"model": "contenttypes.contenttype", "pk": 47, "fields": {"app_label": "venues", "model": "venue"}}, {"model": "contenttypes.contenttype", "pk": 48, "fields": {"app_label": "venues", "model": "teamvenueconstraint"}}, {"model": "contenttypes.contenttype", "pk": 49, "fields": {"app_label": "venues", "model": "adjudicatorvenueconstraint"}}, {"model": "contenttypes.contenttype", "pk": 50, "fields": {"app_label": "venues", "model": "institutionvenueconstraint"}}, {"model": "contenttypes.contenttype", "pk": 51, "fields": {"app_label": "venues", "model": "divisionvenueconstraint"}}, {"model": "contenttypes.contenttype", "pk": 52, "fields": {"app_label": "dynamic_preferences", "model": "globalpreferencemodel"}}, {"model": "contenttypes.contenttype", "pk": 53, "fields": {"app_label": "dynamic_preferences", "model": "userpreferencemodel"}}, {"model": "adjallocation.debateadjudicator", "pk": 1, "fields": {"debate": 12, "adjudicator": 77, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 2, "fields": {"debate": 11, "adjudicator": 79, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 3, "fields": {"debate": 10, "adjudicator": 75, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 4, "fields": {"debate": 9, "adjudicator": 82, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 5, "fields": {"debate": 8, "adjudicator": 88, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 6, "fields": {"debate": 7, "adjudicator": 74, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 7, "fields": {"debate": 6, "adjudicator": 99, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 8, "fields": {"debate": 5, "adjudicator": 93, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 9, "fields": {"debate": 5, "adjudicator": 83, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 10, "fields": {"debate": 5, "adjudicator": 96, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 11, "fields": {"debate": 4, "adjudicator": 95, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 12, "fields": {"debate": 4, "adjudicator": 87, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 13, "fields": {"debate": 4, "adjudicator": 94, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 14, "fields": {"debate": 3, "adjudicator": 73, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 15, "fields": {"debate": 3, "adjudicator": 80, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 16, "fields": {"debate": 3, "adjudicator": 78, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 17, "fields": {"debate": 2, "adjudicator": 81, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 18, "fields": {"debate": 2, "adjudicator": 97, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 19, "fields": {"debate": 2, "adjudicator": 90, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 20, "fields": {"debate": 1, "adjudicator": 98, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 21, "fields": {"debate": 1, "adjudicator": 89, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 22, "fields": {"debate": 1, "adjudicator": 92, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 23, "fields": {"debate": 19, "adjudicator": 74, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 24, "fields": {"debate": 23, "adjudicator": 75, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 25, "fields": {"debate": 13, "adjudicator": 99, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 26, "fields": {"debate": 17, "adjudicator": 79, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 27, "fields": {"debate": 18, "adjudicator": 88, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 28, "fields": {"debate": 15, "adjudicator": 73, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 29, "fields": {"debate": 16, "adjudicator": 77, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 30, "fields": {"debate": 20, "adjudicator": 81, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 31, "fields": {"debate": 20, "adjudicator": 82, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 32, "fields": {"debate": 20, "adjudicator": 78, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 33, "fields": {"debate": 24, "adjudicator": 97, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 34, "fields": {"debate": 24, "adjudicator": 90, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 35, "fields": {"debate": 24, "adjudicator": 92, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 36, "fields": {"debate": 22, "adjudicator": 93, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 37, "fields": {"debate": 22, "adjudicator": 95, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 38, "fields": {"debate": 22, "adjudicator": 89, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 39, "fields": {"debate": 21, "adjudicator": 80, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 40, "fields": {"debate": 21, "adjudicator": 83, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 41, "fields": {"debate": 21, "adjudicator": 96, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 42, "fields": {"debate": 14, "adjudicator": 98, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 43, "fields": {"debate": 14, "adjudicator": 94, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 44, "fields": {"debate": 14, "adjudicator": 87, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 45, "fields": {"debate": 31, "adjudicator": 77, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 46, "fields": {"debate": 33, "adjudicator": 81, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 47, "fields": {"debate": 26, "adjudicator": 74, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 48, "fields": {"debate": 25, "adjudicator": 99, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 49, "fields": {"debate": 32, "adjudicator": 73, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 50, "fields": {"debate": 30, "adjudicator": 82, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 51, "fields": {"debate": 36, "adjudicator": 88, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 52, "fields": {"debate": 27, "adjudicator": 97, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 53, "fields": {"debate": 27, "adjudicator": 98, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 54, "fields": {"debate": 27, "adjudicator": 87, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 55, "fields": {"debate": 28, "adjudicator": 83, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 56, "fields": {"debate": 28, "adjudicator": 93, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 57, "fields": {"debate": 28, "adjudicator": 92, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 58, "fields": {"debate": 35, "adjudicator": 75, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 59, "fields": {"debate": 35, "adjudicator": 95, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 60, "fields": {"debate": 35, "adjudicator": 90, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 61, "fields": {"debate": 34, "adjudicator": 79, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 62, "fields": {"debate": 34, "adjudicator": 78, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 63, "fields": {"debate": 34, "adjudicator": 94, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 64, "fields": {"debate": 29, "adjudicator": 80, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 65, "fields": {"debate": 29, "adjudicator": 96, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 66, "fields": {"debate": 29, "adjudicator": 89, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 67, "fields": {"debate": 38, "adjudicator": 88, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 68, "fields": {"debate": 46, "adjudicator": 81, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 69, "fields": {"debate": 48, "adjudicator": 79, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 70, "fields": {"debate": 47, "adjudicator": 99, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 71, "fields": {"debate": 44, "adjudicator": 82, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 72, "fields": {"debate": 45, "adjudicator": 73, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 73, "fields": {"debate": 37, "adjudicator": 74, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 74, "fields": {"debate": 40, "adjudicator": 95, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 75, "fields": {"debate": 40, "adjudicator": 87, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 76, "fields": {"debate": 40, "adjudicator": 90, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 77, "fields": {"debate": 39, "adjudicator": 98, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 78, "fields": {"debate": 39, "adjudicator": 96, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 79, "fields": {"debate": 39, "adjudicator": 78, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 80, "fields": {"debate": 41, "adjudicator": 77, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 81, "fields": {"debate": 41, "adjudicator": 80, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 82, "fields": {"debate": 41, "adjudicator": 94, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 83, "fields": {"debate": 43, "adjudicator": 75, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 84, "fields": {"debate": 43, "adjudicator": 93, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 85, "fields": {"debate": 43, "adjudicator": 92, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 86, "fields": {"debate": 42, "adjudicator": 83, "type": "C", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 87, "fields": {"debate": 42, "adjudicator": 97, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.debateadjudicator", "pk": 88, "fields": {"debate": 42, "adjudicator": 89, "type": "P", "timing_confirmed": null}}, {"model": "adjallocation.adjudicatorconflict", "pk": 1, "fields": {"adjudicator": 77, "team": 1}}, {"model": "adjallocation.adjudicatorconflict", "pk": 2, "fields": {"adjudicator": 81, "team": 2}}, {"model": "adjallocation.adjudicatorconflict", "pk": 3, "fields": {"adjudicator": 84, "team": 10}}, {"model": "adjallocation.adjudicatorconflict", "pk": 4, "fields": {"adjudicator": 87, "team": 13}}, {"model": "adjallocation.adjudicatorconflict", "pk": 5, "fields": {"adjudicator": 89, "team": 10}}, {"model": "adjallocation.adjudicatorconflict", "pk": 6, "fields": {"adjudicator": 91, "team": 17}}, {"model": "adjallocation.adjudicatorconflict", "pk": 7, "fields": {"adjudicator": 93, "team": 23}}, {"model": "adjallocation.adjudicatorconflict", "pk": 8, "fields": {"adjudicator": 89, "team": 7}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 1, "fields": {"adjudicator": 73, "institution": 13}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 2, "fields": {"adjudicator": 74, "institution": 8}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 3, "fields": {"adjudicator": 75, "institution": 12}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 4, "fields": {"adjudicator": 76, "institution": 1}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 5, "fields": {"adjudicator": 77, "institution": 1}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 6, "fields": {"adjudicator": 78, "institution": 2}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 7, "fields": {"adjudicator": 79, "institution": 3}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 8, "fields": {"adjudicator": 80, "institution": 4}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 9, "fields": {"adjudicator": 81, "institution": 4}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 10, "fields": {"adjudicator": 82, "institution": 12}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 11, "fields": {"adjudicator": 83, "institution": 12}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 12, "fields": {"adjudicator": 84, "institution": 8}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 13, "fields": {"adjudicator": 85, "institution": 5}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 14, "fields": {"adjudicator": 86, "institution": 5}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 15, "fields": {"adjudicator": 87, "institution": 6}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 16, "fields": {"adjudicator": 88, "institution": 6}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 17, "fields": {"adjudicator": 89, "institution": 7}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 18, "fields": {"adjudicator": 90, "institution": 7}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 19, "fields": {"adjudicator": 91, "institution": 8}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 20, "fields": {"adjudicator": 92, "institution": 8}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 21, "fields": {"adjudicator": 93, "institution": 9}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 22, "fields": {"adjudicator": 94, "institution": 10}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 23, "fields": {"adjudicator": 95, "institution": 10}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 24, "fields": {"adjudicator": 96, "institution": 11}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 25, "fields": {"adjudicator": 97, "institution": 13}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 26, "fields": {"adjudicator": 98, "institution": 13}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 27, "fields": {"adjudicator": 99, "institution": 5}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 28, "fields": {"adjudicator": 76, "institution": 7}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 29, "fields": {"adjudicator": 81, "institution": 12}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 30, "fields": {"adjudicator": 82, "institution": 4}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 31, "fields": {"adjudicator": 87, "institution": 3}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 32, "fields": {"adjudicator": 87, "institution": 11}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 33, "fields": {"adjudicator": 87, "institution": 13}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 34, "fields": {"adjudicator": 88, "institution": 9}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 35, "fields": {"adjudicator": 94, "institution": 5}}, {"model": "adjallocation.adjudicatorinstitutionconflict", "pk": 36, "fields": {"adjudicator": 96, "institution": 8}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 1, "fields": {"adjudicator": 73, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.407"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 2, "fields": {"adjudicator": 74, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.409"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 3, "fields": {"adjudicator": 75, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.410"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 4, "fields": {"adjudicator": 76, "round": null, "score": 1.0, "timestamp": "2016-04-14T13:19:04.411"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 5, "fields": {"adjudicator": 77, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.412"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 6, "fields": {"adjudicator": 78, "round": null, "score": 2.0, "timestamp": "2016-04-14T13:19:04.413"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 7, "fields": {"adjudicator": 79, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.414"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 8, "fields": {"adjudicator": 80, "round": null, "score": 4.0, "timestamp": "2016-04-14T13:19:04.415"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 9, "fields": {"adjudicator": 81, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.416"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 10, "fields": {"adjudicator": 82, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.417"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 11, "fields": {"adjudicator": 83, "round": null, "score": 4.0, "timestamp": "2016-04-14T13:19:04.417"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 12, "fields": {"adjudicator": 84, "round": null, "score": 4.0, "timestamp": "2016-04-14T13:19:04.418"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 13, "fields": {"adjudicator": 85, "round": null, "score": 4.0, "timestamp": "2016-04-14T13:19:04.419"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 14, "fields": {"adjudicator": 86, "round": null, "score": 2.0, "timestamp": "2016-04-14T13:19:04.420"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 15, "fields": {"adjudicator": 87, "round": null, "score": 2.0, "timestamp": "2016-04-14T13:19:04.421"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 16, "fields": {"adjudicator": 88, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.422"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 17, "fields": {"adjudicator": 89, "round": null, "score": 2.0, "timestamp": "2016-04-14T13:19:04.423"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 18, "fields": {"adjudicator": 90, "round": null, "score": 2.0, "timestamp": "2016-04-14T13:19:04.424"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 19, "fields": {"adjudicator": 91, "round": null, "score": 1.0, "timestamp": "2016-04-14T13:19:04.425"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 20, "fields": {"adjudicator": 92, "round": null, "score": 2.0, "timestamp": "2016-04-14T13:19:04.425"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 21, "fields": {"adjudicator": 93, "round": null, "score": 4.0, "timestamp": "2016-04-14T13:19:04.426"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 22, "fields": {"adjudicator": 94, "round": null, "score": 2.0, "timestamp": "2016-04-14T13:19:04.427"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 23, "fields": {"adjudicator": 95, "round": null, "score": 3.0, "timestamp": "2016-04-14T13:19:04.428"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 24, "fields": {"adjudicator": 96, "round": null, "score": 2.0, "timestamp": "2016-04-14T13:19:04.429"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 25, "fields": {"adjudicator": 97, "round": null, "score": 4.0, "timestamp": "2016-04-14T13:19:04.430"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 26, "fields": {"adjudicator": 98, "round": null, "score": 3.0, "timestamp": "2016-04-14T13:19:04.430"}}, {"model": "adjfeedback.adjudicatortestscorehistory", "pk": 27, "fields": {"adjudicator": 99, "round": null, "score": 5.0, "timestamp": "2016-04-14T13:19:04.431"}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 1, "fields": {"tournament": 1, "seq": 10, "text": "Did you agree with the decision?", "name": "Agree", "reference": "agree", "from_adj": false, "from_team": true, "answer_type": "bs", "required": true, "min_value": null, "max_value": null, "choices": null}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 2, "fields": {"tournament": 1, "seq": 11, "text": "Did this judge's decision concur with yours?", "name": "Concur", "reference": "concur", "from_adj": true, "from_team": false, "answer_type": "bs", "required": true, "min_value": null, "max_value": null, "choices": null}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 3, "fields": {"tournament": 1, "seq": 20, "text": "What adjustment should be applied to this judge's speaker scores?", "name": "Adjustment", "reference": "adjustment", "from_adj": true, "from_team": false, "answer_type": "f", "required": true, "min_value": -20.0, "max_value": 20.0, "choices": null}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 4, "fields": {"tournament": 1, "seq": 30, "text": "Choose one word to describe this adjudicator.", "name": "One word", "reference": "word", "from_adj": true, "from_team": true, "answer_type": "t", "required": true, "min_value": null, "max_value": null, "choices": null}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 5, "fields": {"tournament": 1, "seq": 40, "text": "Do you think this adjudicator should be promoted?", "name": "Promote", "reference": "promote", "from_adj": true, "from_team": true, "answer_type": "bc", "required": false, "min_value": null, "max_value": null, "choices": null}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 6, "fields": {"tournament": 1, "seq": 50, "text": "Do you think this adjudicator should be demoted?", "name": "Demote", "reference": "demote", "from_adj": true, "from_team": true, "answer_type": "bc", "required": false, "min_value": null, "max_value": null, "choices": null}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 7, "fields": {"tournament": 1, "seq": 60, "text": "How well was this adjudicator's reasoning explained?", "name": "Explanation", "reference": "explanation", "from_adj": true, "from_team": true, "answer_type": "is", "required": true, "min_value": 0.0, "max_value": 10.0, "choices": null}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 8, "fields": {"tournament": 1, "seq": 70, "text": "How impartial did you think this adjudicator was?", "name": "Impartial", "reference": "impartial", "from_adj": true, "from_team": true, "answer_type": "is", "required": true, "min_value": 0.0, "max_value": 10.0, "choices": null}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 9, "fields": {"tournament": 1, "seq": 80, "text": "Would you like to see this adjudicator again?", "name": "Again", "reference": "again", "from_adj": false, "from_team": true, "answer_type": "ss", "required": false, "min_value": null, "max_value": null, "choices": "Absolutely!//Sure, why not//If I have to//Please don't"}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 10, "fields": {"tournament": 1, "seq": 90, "text": "How would you describe this adjudicator?", "name": "Adjectives", "reference": "adjectives", "from_adj": false, "from_team": true, "answer_type": "ms", "required": false, "min_value": null, "max_value": null, "choices": "biased//clear//concise//rambly//attentive//inattentive"}}, {"model": "adjfeedback.adjudicatorfeedbackquestion", "pk": 11, "fields": {"tournament": 1, "seq": 1000, "text": "Other comments:", "name": "Comments", "reference": "comments", "from_adj": true, "from_team": true, "answer_type": "tl", "required": false, "min_value": null, "max_value": null, "choices": null}}, {"model": "availability.activevenue", "pk": 1, "fields": {"venue": 1, "round": 4}}, {"model": "availability.activevenue", "pk": 2, "fields": {"venue": 2, "round": 4}}, {"model": "availability.activevenue", "pk": 3, "fields": {"venue": 3, "round": 4}}, {"model": "availability.activevenue", "pk": 4, "fields": {"venue": 4, "round": 4}}, {"model": "availability.activevenue", "pk": 5, "fields": {"venue": 5, "round": 4}}, {"model": "availability.activevenue", "pk": 6, "fields": {"venue": 6, "round": 4}}, {"model": "availability.activevenue", "pk": 7, "fields": {"venue": 7, "round": 4}}, {"model": "availability.activevenue", "pk": 8, "fields": {"venue": 8, "round": 4}}, {"model": "availability.activevenue", "pk": 9, "fields": {"venue": 9, "round": 4}}, {"model": "availability.activevenue", "pk": 10, "fields": {"venue": 10, "round": 4}}, {"model": "availability.activevenue", "pk": 11, "fields": {"venue": 11, "round": 4}}, {"model": "availability.activevenue", "pk": 12, "fields": {"venue": 12, "round": 4}}, {"model": "availability.activevenue", "pk": 13, "fields": {"venue": 13, "round": 4}}, {"model": "availability.activevenue", "pk": 14, "fields": {"venue": 14, "round": 4}}, {"model": "availability.activevenue", "pk": 15, "fields": {"venue": 15, "round": 4}}, {"model": "availability.activevenue", "pk": 16, "fields": {"venue": 16, "round": 4}}, {"model": "availability.activevenue", "pk": 17, "fields": {"venue": 17, "round": 4}}, {"model": "availability.activevenue", "pk": 18, "fields": {"venue": 18, "round": 4}}, {"model": "availability.activevenue", "pk": 19, "fields": {"venue": 19, "round": 4}}, {"model": "availability.activevenue", "pk": 20, "fields": {"venue": 20, "round": 4}}, {"model": "availability.activevenue", "pk": 21, "fields": {"venue": 21, "round": 4}}, {"model": "availability.activevenue", "pk": 22, "fields": {"venue": 22, "round": 4}}, {"model": "availability.activevenue", "pk": 23, "fields": {"venue": 23, "round": 4}}, {"model": "availability.activevenue", "pk": 24, "fields": {"venue": 1, "round": 3}}, {"model": "availability.activevenue", "pk": 25, "fields": {"venue": 2, "round": 3}}, {"model": "availability.activevenue", "pk": 26, "fields": {"venue": 3, "round": 3}}, {"model": "availability.activevenue", "pk": 27, "fields": {"venue": 4, "round": 3}}, {"model": "availability.activevenue", "pk": 28, "fields": {"venue": 5, "round": 3}}, {"model": "availability.activevenue", "pk": 29, "fields": {"venue": 6, "round": 3}}, {"model": "availability.activevenue", "pk": 30, "fields": {"venue": 7, "round": 3}}, {"model": "availability.activevenue", "pk": 31, "fields": {"venue": 8, "round": 3}}, {"model": "availability.activevenue", "pk": 32, "fields": {"venue": 9, "round": 3}}, {"model": "availability.activevenue", "pk": 33, "fields": {"venue": 10, "round": 3}}, {"model": "availability.activevenue", "pk": 34, "fields": {"venue": 11, "round": 3}}, {"model": "availability.activevenue", "pk": 35, "fields": {"venue": 12, "round": 3}}, {"model": "availability.activevenue", "pk": 36, "fields": {"venue": 13, "round": 3}}, {"model": "availability.activevenue", "pk": 37, "fields": {"venue": 14, "round": 3}}, {"model": "availability.activevenue", "pk": 38, "fields": {"venue": 15, "round": 3}}, {"model": "availability.activevenue", "pk": 39, "fields": {"venue": 16, "round": 3}}, {"model": "availability.activevenue", "pk": 40, "fields": {"venue": 17, "round": 3}}, {"model": "availability.activevenue", "pk": 41, "fields": {"venue": 18, "round": 3}}, {"model": "availability.activevenue", "pk": 42, "fields": {"venue": 19, "round": 3}}, {"model": "availability.activevenue", "pk": 43, "fields": {"venue": 20, "round": 3}}, {"model": "availability.activevenue", "pk": 44, "fields": {"venue": 21, "round": 3}}, {"model": "availability.activevenue", "pk": 45, "fields": {"venue": 22, "round": 3}}, {"model": "availability.activevenue", "pk": 46, "fields": {"venue": 23, "round": 3}}, {"model": "availability.activevenue", "pk": 47, "fields": {"venue": 1, "round": 2}}, {"model": "availability.activevenue", "pk": 48, "fields": {"venue": 2, "round": 2}}, {"model": "availability.activevenue", "pk": 49, "fields": {"venue": 3, "round": 2}}, {"model": "availability.activevenue", "pk": 50, "fields": {"venue": 4, "round": 2}}, {"model": "availability.activevenue", "pk": 51, "fields": {"venue": 5, "round": 2}}, {"model": "availability.activevenue", "pk": 52, "fields": {"venue": 6, "round": 2}}, {"model": "availability.activevenue", "pk": 53, "fields": {"venue": 7, "round": 2}}, {"model": "availability.activevenue", "pk": 54, "fields": {"venue": 8, "round": 2}}, {"model": "availability.activevenue", "pk": 55, "fields": {"venue": 9, "round": 2}}, {"model": "availability.activevenue", "pk": 56, "fields": {"venue": 10, "round": 2}}, {"model": "availability.activevenue", "pk": 57, "fields": {"venue": 11, "round": 2}}, {"model": "availability.activevenue", "pk": 58, "fields": {"venue": 12, "round": 2}}, {"model": "availability.activevenue", "pk": 59, "fields": {"venue": 13, "round": 2}}, {"model": "availability.activevenue", "pk": 60, "fields": {"venue": 14, "round": 2}}, {"model": "availability.activevenue", "pk": 61, "fields": {"venue": 15, "round": 2}}, {"model": "availability.activevenue", "pk": 62, "fields": {"venue": 16, "round": 2}}, {"model": "availability.activevenue", "pk": 63, "fields": {"venue": 17, "round": 2}}, {"model": "availability.activevenue", "pk": 64, "fields": {"venue": 18, "round": 2}}, {"model": "availability.activevenue", "pk": 65, "fields": {"venue": 19, "round": 2}}, {"model": "availability.activevenue", "pk": 66, "fields": {"venue": 20, "round": 2}}, {"model": "availability.activevenue", "pk": 67, "fields": {"venue": 21, "round": 2}}, {"model": "availability.activevenue", "pk": 68, "fields": {"venue": 22, "round": 2}}, {"model": "availability.activevenue", "pk": 69, "fields": {"venue": 23, "round": 2}}, {"model": "availability.activevenue", "pk": 93, "fields": {"venue": 1, "round": 5}}, {"model": "availability.activevenue", "pk": 94, "fields": {"venue": 2, "round": 5}}, {"model": "availability.activevenue", "pk": 95, "fields": {"venue": 3, "round": 5}}, {"model": "availability.activevenue", "pk": 96, "fields": {"venue": 4, "round": 5}}, {"model": "availability.activevenue", "pk": 97, "fields": {"venue": 5, "round": 5}}, {"model": "availability.activevenue", "pk": 98, "fields": {"venue": 6, "round": 5}}, {"model": "availability.activevenue", "pk": 99, "fields": {"venue": 7, "round": 5}}, {"model": "availability.activevenue", "pk": 100, "fields": {"venue": 8, "round": 5}}, {"model": "availability.activevenue", "pk": 101, "fields": {"venue": 9, "round": 5}}, {"model": "availability.activevenue", "pk": 102, "fields": {"venue": 10, "round": 5}}, {"model": "availability.activevenue", "pk": 103, "fields": {"venue": 11, "round": 5}}, {"model": "availability.activevenue", "pk": 104, "fields": {"venue": 12, "round": 5}}, {"model": "availability.activevenue", "pk": 105, "fields": {"venue": 13, "round": 5}}, {"model": "availability.activevenue", "pk": 106, "fields": {"venue": 14, "round": 5}}, {"model": "availability.activevenue", "pk": 107, "fields": {"venue": 15, "round": 5}}, {"model": "availability.activevenue", "pk": 108, "fields": {"venue": 16, "round": 5}}, {"model": "availability.activevenue", "pk": 109, "fields": {"venue": 17, "round": 5}}, {"model": "availability.activevenue", "pk": 110, "fields": {"venue": 18, "round": 5}}, {"model": "availability.activevenue", "pk": 111, "fields": {"venue": 19, "round": 5}}, {"model": "availability.activevenue", "pk": 112, "fields": {"venue": 20, "round": 5}}, {"model": "availability.activevenue", "pk": 113, "fields": {"venue": 21, "round": 5}}, {"model": "availability.activevenue", "pk": 114, "fields": {"venue": 22, "round": 5}}, {"model": "availability.activevenue", "pk": 115, "fields": {"venue": 23, "round": 5}}, {"model": "availability.activevenue", "pk": 116, "fields": {"venue": 1, "round": 6}}, {"model": "availability.activevenue", "pk": 117, "fields": {"venue": 2, "round": 6}}, {"model": "availability.activevenue", "pk": 118, "fields": {"venue": 3, "round": 6}}, {"model": "availability.activevenue", "pk": 119, "fields": {"venue": 4, "round": 6}}, {"model": "availability.activevenue", "pk": 120, "fields": {"venue": 5, "round": 6}}, {"model": "availability.activevenue", "pk": 121, "fields": {"venue": 6, "round": 6}}, {"model": "availability.activevenue", "pk": 122, "fields": {"venue": 7, "round": 6}}, {"model": "availability.activevenue", "pk": 123, "fields": {"venue": 8, "round": 6}}, {"model": "availability.activevenue", "pk": 124, "fields": {"venue": 9, "round": 6}}, {"model": "availability.activevenue", "pk": 125, "fields": {"venue": 10, "round": 6}}, {"model": "availability.activevenue", "pk": 126, "fields": {"venue": 11, "round": 6}}, {"model": "availability.activevenue", "pk": 127, "fields": {"venue": 12, "round": 6}}, {"model": "availability.activevenue", "pk": 128, "fields": {"venue": 13, "round": 6}}, {"model": "availability.activevenue", "pk": 129, "fields": {"venue": 14, "round": 6}}, {"model": "availability.activevenue", "pk": 130, "fields": {"venue": 15, "round": 6}}, {"model": "availability.activevenue", "pk": 131, "fields": {"venue": 16, "round": 6}}, {"model": "availability.activevenue", "pk": 132, "fields": {"venue": 17, "round": 6}}, {"model": "availability.activevenue", "pk": 133, "fields": {"venue": 18, "round": 6}}, {"model": "availability.activevenue", "pk": 134, "fields": {"venue": 19, "round": 6}}, {"model": "availability.activevenue", "pk": 135, "fields": {"venue": 20, "round": 6}}, {"model": "availability.activevenue", "pk": 136, "fields": {"venue": 21, "round": 6}}, {"model": "availability.activevenue", "pk": 137, "fields": {"venue": 22, "round": 6}}, {"model": "availability.activevenue", "pk": 138, "fields": {"venue": 23, "round": 6}}, {"model": "availability.activevenue", "pk": 139, "fields": {"venue": 16, "round": 7}}, {"model": "availability.activevenue", "pk": 140, "fields": {"venue": 9, "round": 7}}, {"model": "availability.activevenue", "pk": 141, "fields": {"venue": 12, "round": 7}}, {"model": "availability.activevenue", "pk": 142, "fields": {"venue": 6, "round": 7}}, {"model": "availability.activevenue", "pk": 152, "fields": {"venue": 1, "round": 1}}, {"model": "availability.activevenue", "pk": 153, "fields": {"venue": 3, "round": 1}}, {"model": "availability.activevenue", "pk": 154, "fields": {"venue": 4, "round": 1}}, {"model": "availability.activevenue", "pk": 155, "fields": {"venue": 5, "round": 1}}, {"model": "availability.activevenue", "pk": 156, "fields": {"venue": 6, "round": 1}}, {"model": "availability.activevenue", "pk": 157, "fields": {"venue": 7, "round": 1}}, {"model": "availability.activevenue", "pk": 158, "fields": {"venue": 8, "round": 1}}, {"model": "availability.activevenue", "pk": 159, "fields": {"venue": 9, "round": 1}}, {"model": "availability.activevenue", "pk": 160, "fields": {"venue": 10, "round": 1}}, {"model": "availability.activevenue", "pk": 161, "fields": {"venue": 11, "round": 1}}, {"model": "availability.activevenue", "pk": 162, "fields": {"venue": 12, "round": 1}}, {"model": "availability.activevenue", "pk": 163, "fields": {"venue": 13, "round": 1}}, {"model": "availability.activevenue", "pk": 164, "fields": {"venue": 14, "round": 1}}, {"model": "availability.activevenue", "pk": 165, "fields": {"venue": 15, "round": 1}}, {"model": "availability.activevenue", "pk": 166, "fields": {"venue": 16, "round": 1}}, {"model": "availability.activevenue", "pk": 167, "fields": {"venue": 17, "round": 1}}, {"model": "availability.activevenue", "pk": 168, "fields": {"venue": 18, "round": 1}}, {"model": "availability.activevenue", "pk": 169, "fields": {"venue": 19, "round": 1}}, {"model": "availability.activevenue", "pk": 170, "fields": {"venue": 20, "round": 1}}, {"model": "availability.activevenue", "pk": 171, "fields": {"venue": 21, "round": 1}}, {"model": "availability.activevenue", "pk": 172, "fields": {"venue": 22, "round": 1}}, {"model": "availability.activevenue", "pk": 173, "fields": {"venue": 23, "round": 1}}, {"model": "availability.activevenue", "pk": 174, "fields": {"venue": 24, "round": 1}}, {"model": "availability.activevenue", "pk": 175, "fields": {"venue": 25, "round": 1}}, {"model": "availability.activevenue", "pk": 176, "fields": {"venue": 26, "round": 1}}, {"model": "availability.activevenue", "pk": 177, "fields": {"venue": 27, "round": 1}}, {"model": "availability.activeteam", "pk": 1, "fields": {"team": 1, "round": 4}}, {"model": "availability.activeteam", "pk": 2, "fields": {"team": 2, "round": 4}}, {"model": "availability.activeteam", "pk": 3, "fields": {"team": 3, "round": 4}}, {"model": "availability.activeteam", "pk": 4, "fields": {"team": 4, "round": 4}}, {"model": "availability.activeteam", "pk": 5, "fields": {"team": 5, "round": 4}}, {"model": "availability.activeteam", "pk": 6, "fields": {"team": 6, "round": 4}}, {"model": "availability.activeteam", "pk": 7, "fields": {"team": 7, "round": 4}}, {"model": "availability.activeteam", "pk": 8, "fields": {"team": 8, "round": 4}}, {"model": "availability.activeteam", "pk": 9, "fields": {"team": 9, "round": 4}}, {"model": "availability.activeteam", "pk": 10, "fields": {"team": 10, "round": 4}}, {"model": "availability.activeteam", "pk": 11, "fields": {"team": 11, "round": 4}}, {"model": "availability.activeteam", "pk": 12, "fields": {"team": 12, "round": 4}}, {"model": "availability.activeteam", "pk": 13, "fields": {"team": 13, "round": 4}}, {"model": "availability.activeteam", "pk": 14, "fields": {"team": 14, "round": 4}}, {"model": "availability.activeteam", "pk": 15, "fields": {"team": 15, "round": 4}}, {"model": "availability.activeteam", "pk": 16, "fields": {"team": 16, "round": 4}}, {"model": "availability.activeteam", "pk": 17, "fields": {"team": 17, "round": 4}}, {"model": "availability.activeteam", "pk": 18, "fields": {"team": 18, "round": 4}}, {"model": "availability.activeteam", "pk": 19, "fields": {"team": 19, "round": 4}}, {"model": "availability.activeteam", "pk": 20, "fields": {"team": 20, "round": 4}}, {"model": "availability.activeteam", "pk": 160, "fields": {"team": 9, "round": 6}}, {"model": "availability.activeteam", "pk": 161, "fields": {"team": 10, "round": 6}}, {"model": "availability.activeteam", "pk": 162, "fields": {"team": 5, "round": 6}}, {"model": "availability.activeteam", "pk": 163, "fields": {"team": 6, "round": 6}}, {"model": "availability.activeteam", "pk": 164, "fields": {"team": 19, "round": 9}}, {"model": "availability.activeteam", "pk": 165, "fields": {"team": 1, "round": 5}}, {"model": "availability.activeteam", "pk": 173, "fields": {"team": 4, "round": 5}}, {"model": "availability.activeteam", "pk": 174, "fields": {"team": 7, "round": 5}}, {"model": "availability.activeteam", "pk": 175, "fields": {"team": 11, "round": 5}}, {"model": "availability.activeteam", "pk": 176, "fields": {"team": 12, "round": 5}}, {"model": "availability.activeteam", "pk": 177, "fields": {"team": 17, "round": 5}}, {"model": "availability.activeteam", "pk": 178, "fields": {"team": 18, "round": 5}}, {"model": "availability.activeteam", "pk": 179, "fields": {"team": 20, "round": 5}}, {"model": "availability.activeteam", "pk": 180, "fields": {"team": 18, "round": 7}}, {"model": "availability.activeteam", "pk": 181, "fields": {"team": 12, "round": 7}}, {"model": "availability.activeteam", "pk": 182, "fields": {"team": 4, "round": 7}}, {"model": "availability.activeteam", "pk": 183, "fields": {"team": 20, "round": 7}}, {"model": "availability.activeteam", "pk": 184, "fields": {"team": 1, "round": 2}}, {"model": "availability.activeteam", "pk": 185, "fields": {"team": 2, "round": 2}}, {"model": "availability.activeteam", "pk": 186, "fields": {"team": 3, "round": 2}}, {"model": "availability.activeteam", "pk": 187, "fields": {"team": 4, "round": 2}}, {"model": "availability.activeteam", "pk": 188, "fields": {"team": 5, "round": 2}}, {"model": "availability.activeteam", "pk": 189, "fields": {"team": 6, "round": 2}}, {"model": "availability.activeteam", "pk": 190, "fields": {"team": 7, "round": 2}}, {"model": "availability.activeteam", "pk": 191, "fields": {"team": 8, "round": 2}}, {"model": "availability.activeteam", "pk": 192, "fields": {"team": 9, "round": 2}}, {"model": "availability.activeteam", "pk": 193, "fields": {"team": 10, "round": 2}}, {"model": "availability.activeteam", "pk": 194, "fields": {"team": 11, "round": 2}}, {"model": "availability.activeteam", "pk": 195, "fields": {"team": 12, "round": 2}}, {"model": "availability.activeteam", "pk": 196, "fields": {"team": 13, "round": 2}}, {"model": "availability.activeteam", "pk": 197, "fields": {"team": 14, "round": 2}}, {"model": "availability.activeteam", "pk": 198, "fields": {"team": 15, "round": 2}}, {"model": "availability.activeteam", "pk": 199, "fields": {"team": 16, "round": 2}}, {"model": "availability.activeteam", "pk": 200, "fields": {"team": 17, "round": 2}}, {"model": "availability.activeteam", "pk": 201, "fields": {"team": 18, "round": 2}}, {"model": "availability.activeteam", "pk": 202, "fields": {"team": 19, "round": 2}}, {"model": "availability.activeteam", "pk": 203, "fields": {"team": 20, "round": 2}}, {"model": "availability.activeteam", "pk": 204, "fields": {"team": 21, "round": 2}}, {"model": "availability.activeteam", "pk": 205, "fields": {"team": 22, "round": 2}}, {"model": "availability.activeteam", "pk": 206, "fields": {"team": 23, "round": 2}}, {"model": "availability.activeteam", "pk": 207, "fields": {"team": 24, "round": 2}}, {"model": "availability.activeteam", "pk": 213, "fields": {"team": 1, "round": 1}}, {"model": "availability.activeteam", "pk": 214, "fields": {"team": 2, "round": 1}}, {"model": "availability.activeteam", "pk": 215, "fields": {"team": 3, "round": 1}}, {"model": "availability.activeteam", "pk": 216, "fields": {"team": 4, "round": 1}}, {"model": "availability.activeteam", "pk": 217, "fields": {"team": 5, "round": 1}}, {"model": "availability.activeteam", "pk": 218, "fields": {"team": 6, "round": 1}}, {"model": "availability.activeteam", "pk": 219, "fields": {"team": 7, "round": 1}}, {"model": "availability.activeteam", "pk": 220, "fields": {"team": 8, "round": 1}}, {"model": "availability.activeteam", "pk": 221, "fields": {"team": 9, "round": 1}}, {"model": "availability.activeteam", "pk": 222, "fields": {"team": 10, "round": 1}}, {"model": "availability.activeteam", "pk": 223, "fields": {"team": 11, "round": 1}}, {"model": "availability.activeteam", "pk": 224, "fields": {"team": 12, "round": 1}}, {"model": "availability.activeteam", "pk": 225, "fields": {"team": 13, "round": 1}}, {"model": "availability.activeteam", "pk": 226, "fields": {"team": 14, "round": 1}}, {"model": "availability.activeteam", "pk": 227, "fields": {"team": 15, "round": 1}}, {"model": "availability.activeteam", "pk": 228, "fields": {"team": 16, "round": 1}}, {"model": "availability.activeteam", "pk": 229, "fields": {"team": 17, "round": 1}}, {"model": "availability.activeteam", "pk": 230, "fields": {"team": 18, "round": 1}}, {"model": "availability.activeteam", "pk": 231, "fields": {"team": 19, "round": 1}}, {"model": "availability.activeteam", "pk": 232, "fields": {"team": 20, "round": 1}}, {"model": "availability.activeteam", "pk": 233, "fields": {"team": 21, "round": 1}}, {"model": "availability.activeteam", "pk": 234, "fields": {"team": 22, "round": 1}}, {"model": "availability.activeteam", "pk": 235, "fields": {"team": 23, "round": 1}}, {"model": "availability.activeteam", "pk": 236, "fields": {"team": 24, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 1, "fields": {"adjudicator": 73, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 2, "fields": {"adjudicator": 74, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 3, "fields": {"adjudicator": 75, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 4, "fields": {"adjudicator": 76, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 5, "fields": {"adjudicator": 77, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 6, "fields": {"adjudicator": 78, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 7, "fields": {"adjudicator": 79, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 8, "fields": {"adjudicator": 80, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 9, "fields": {"adjudicator": 81, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 10, "fields": {"adjudicator": 82, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 11, "fields": {"adjudicator": 83, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 12, "fields": {"adjudicator": 84, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 13, "fields": {"adjudicator": 85, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 14, "fields": {"adjudicator": 86, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 15, "fields": {"adjudicator": 87, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 16, "fields": {"adjudicator": 88, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 17, "fields": {"adjudicator": 89, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 18, "fields": {"adjudicator": 90, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 19, "fields": {"adjudicator": 91, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 20, "fields": {"adjudicator": 92, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 21, "fields": {"adjudicator": 93, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 22, "fields": {"adjudicator": 94, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 23, "fields": {"adjudicator": 95, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 24, "fields": {"adjudicator": 96, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 25, "fields": {"adjudicator": 97, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 26, "fields": {"adjudicator": 98, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 27, "fields": {"adjudicator": 99, "round": 4}}, {"model": "availability.activeadjudicator", "pk": 28, "fields": {"adjudicator": 73, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 29, "fields": {"adjudicator": 74, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 30, "fields": {"adjudicator": 75, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 31, "fields": {"adjudicator": 76, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 32, "fields": {"adjudicator": 77, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 33, "fields": {"adjudicator": 78, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 34, "fields": {"adjudicator": 79, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 35, "fields": {"adjudicator": 80, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 36, "fields": {"adjudicator": 81, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 37, "fields": {"adjudicator": 82, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 38, "fields": {"adjudicator": 83, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 39, "fields": {"adjudicator": 84, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 40, "fields": {"adjudicator": 85, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 41, "fields": {"adjudicator": 86, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 42, "fields": {"adjudicator": 87, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 43, "fields": {"adjudicator": 88, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 44, "fields": {"adjudicator": 89, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 45, "fields": {"adjudicator": 90, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 46, "fields": {"adjudicator": 91, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 47, "fields": {"adjudicator": 92, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 48, "fields": {"adjudicator": 93, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 49, "fields": {"adjudicator": 94, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 50, "fields": {"adjudicator": 95, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 51, "fields": {"adjudicator": 96, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 52, "fields": {"adjudicator": 97, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 53, "fields": {"adjudicator": 98, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 54, "fields": {"adjudicator": 99, "round": 3}}, {"model": "availability.activeadjudicator", "pk": 55, "fields": {"adjudicator": 73, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 56, "fields": {"adjudicator": 74, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 57, "fields": {"adjudicator": 75, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 58, "fields": {"adjudicator": 76, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 59, "fields": {"adjudicator": 77, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 60, "fields": {"adjudicator": 78, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 61, "fields": {"adjudicator": 79, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 62, "fields": {"adjudicator": 80, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 63, "fields": {"adjudicator": 81, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 64, "fields": {"adjudicator": 82, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 65, "fields": {"adjudicator": 83, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 66, "fields": {"adjudicator": 84, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 67, "fields": {"adjudicator": 85, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 68, "fields": {"adjudicator": 86, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 69, "fields": {"adjudicator": 87, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 70, "fields": {"adjudicator": 88, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 71, "fields": {"adjudicator": 89, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 72, "fields": {"adjudicator": 90, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 73, "fields": {"adjudicator": 91, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 74, "fields": {"adjudicator": 92, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 75, "fields": {"adjudicator": 93, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 76, "fields": {"adjudicator": 94, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 77, "fields": {"adjudicator": 95, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 78, "fields": {"adjudicator": 96, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 79, "fields": {"adjudicator": 97, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 80, "fields": {"adjudicator": 98, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 81, "fields": {"adjudicator": 99, "round": 2}}, {"model": "availability.activeadjudicator", "pk": 136, "fields": {"adjudicator": 98, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 137, "fields": {"adjudicator": 74, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 138, "fields": {"adjudicator": 78, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 139, "fields": {"adjudicator": 87, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 140, "fields": {"adjudicator": 88, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 141, "fields": {"adjudicator": 89, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 142, "fields": {"adjudicator": 90, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 145, "fields": {"adjudicator": 95, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 146, "fields": {"adjudicator": 92, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 147, "fields": {"adjudicator": 94, "round": 5}}, {"model": "availability.activeadjudicator", "pk": 148, "fields": {"adjudicator": 98, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 149, "fields": {"adjudicator": 74, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 150, "fields": {"adjudicator": 78, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 151, "fields": {"adjudicator": 87, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 152, "fields": {"adjudicator": 88, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 153, "fields": {"adjudicator": 89, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 154, "fields": {"adjudicator": 90, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 155, "fields": {"adjudicator": 92, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 156, "fields": {"adjudicator": 94, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 157, "fields": {"adjudicator": 95, "round": 6}}, {"model": "availability.activeadjudicator", "pk": 158, "fields": {"adjudicator": 98, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 159, "fields": {"adjudicator": 74, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 160, "fields": {"adjudicator": 78, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 161, "fields": {"adjudicator": 87, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 162, "fields": {"adjudicator": 88, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 163, "fields": {"adjudicator": 89, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 164, "fields": {"adjudicator": 90, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 165, "fields": {"adjudicator": 92, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 166, "fields": {"adjudicator": 94, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 167, "fields": {"adjudicator": 95, "round": 7}}, {"model": "availability.activeadjudicator", "pk": 174, "fields": {"adjudicator": 73, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 175, "fields": {"adjudicator": 74, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 176, "fields": {"adjudicator": 75, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 177, "fields": {"adjudicator": 76, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 178, "fields": {"adjudicator": 77, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 179, "fields": {"adjudicator": 78, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 180, "fields": {"adjudicator": 79, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 181, "fields": {"adjudicator": 80, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 182, "fields": {"adjudicator": 81, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 183, "fields": {"adjudicator": 82, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 184, "fields": {"adjudicator": 83, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 185, "fields": {"adjudicator": 84, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 186, "fields": {"adjudicator": 85, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 187, "fields": {"adjudicator": 86, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 188, "fields": {"adjudicator": 87, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 189, "fields": {"adjudicator": 88, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 190, "fields": {"adjudicator": 89, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 191, "fields": {"adjudicator": 90, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 192, "fields": {"adjudicator": 91, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 193, "fields": {"adjudicator": 92, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 194, "fields": {"adjudicator": 93, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 195, "fields": {"adjudicator": 94, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 196, "fields": {"adjudicator": 95, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 197, "fields": {"adjudicator": 96, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 198, "fields": {"adjudicator": 97, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 199, "fields": {"adjudicator": 98, "round": 1}}, {"model": "availability.activeadjudicator", "pk": 200, "fields": {"adjudicator": 99, "round": 1}}, {"model": "breakqual.breakcategory", "pk": 1, "fields": {"tournament": 1, "name": "Open", "slug": "open", "seq": 10, "break_size": 8, "is_general": true, "priority": 10}}, {"model": "breakqual.breakcategory", "pk": 2, "fields": {"tournament": 1, "name": "ESL", "slug": "esl", "seq": 20, "break_size": 4, "is_general": false, "priority": 20}}, {"model": "breakqual.breakcategory", "pk": 3, "fields": {"tournament": 1, "name": "EFL", "slug": "efl", "seq": 30, "break_size": 2, "is_general": false, "priority": 30}}, {"model": "breakqual.breakingteam", "pk": 44, "fields": {"break_category": 1, "team": 7, "rank": 1, "break_rank": 1, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 45, "fields": {"break_category": 1, "team": 18, "rank": 2, "break_rank": 2, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 46, "fields": {"break_category": 1, "team": 17, "rank": 3, "break_rank": 3, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 47, "fields": {"break_category": 1, "team": 1, "rank": 4, "break_rank": 4, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 48, "fields": {"break_category": 1, "team": 12, "rank": 5, "break_rank": 5, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 49, "fields": {"break_category": 1, "team": 20, "rank": 6, "break_rank": 6, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 50, "fields": {"break_category": 1, "team": 11, "rank": 7, "break_rank": 7, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 51, "fields": {"break_category": 1, "team": 4, "rank": 8, "break_rank": 8, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 52, "fields": {"break_category": 2, "team": 18, "rank": 1, "break_rank": null, "remark": "D"}}, {"model": "breakqual.breakingteam", "pk": 53, "fields": {"break_category": 2, "team": 17, "rank": 2, "break_rank": null, "remark": "D"}}, {"model": "breakqual.breakingteam", "pk": 54, "fields": {"break_category": 2, "team": 4, "rank": 3, "break_rank": null, "remark": "D"}}, {"model": "breakqual.breakingteam", "pk": 55, "fields": {"break_category": 2, "team": 10, "rank": 4, "break_rank": 1, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 56, "fields": {"break_category": 2, "team": 6, "rank": 5, "break_rank": 2, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 57, "fields": {"break_category": 2, "team": 5, "rank": 6, "break_rank": 3, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 58, "fields": {"break_category": 2, "team": 9, "rank": 7, "break_rank": 4, "remark": null}}, {"model": "breakqual.breakingteam", "pk": 59, "fields": {"break_category": 3, "team": 4, "rank": 1, "break_rank": null, "remark": "D"}}, {"model": "breakqual.breakingteam", "pk": 60, "fields": {"break_category": 3, "team": 6, "rank": 2, "break_rank": null, "remark": "D"}}, {"model": "breakqual.breakingteam", "pk": 61, "fields": {"break_category": 3, "team": 5, "rank": 3, "break_rank": null, "remark": "D"}}, {"model": "breakqual.breakingteam", "pk": 62, "fields": {"break_category": 3, "team": 19, "rank": 4, "break_rank": 1, "remark": null}}, {"model": "draw.debate", "pk": 1, "fields": {"round": 1, "venue": 21, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 2, "fields": {"round": 1, "venue": 23, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 3, "fields": {"round": 1, "venue": 14, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 4, "fields": {"round": 1, "venue": 18, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 5, "fields": {"round": 1, "venue": 1, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 6, "fields": {"round": 1, "venue": 19, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 7, "fields": {"round": 1, "venue": 22, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 8, "fields": {"round": 1, "venue": 17, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 9, "fields": {"round": 1, "venue": 16, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 10, "fields": {"round": 1, "venue": 20, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 11, "fields": {"round": 1, "venue": 13, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 12, "fields": {"round": 1, "venue": 15, "division": null, "bracket": 0.0, "room_rank": 0, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 13, "fields": {"round": 2, "venue": 17, "division": null, "bracket": 1.0, "room_rank": 3, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 14, "fields": {"round": 2, "venue": 20, "division": null, "bracket": 0.0, "room_rank": 12, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 15, "fields": {"round": 2, "venue": 1, "division": null, "bracket": 1.0, "room_rank": 6, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 16, "fields": {"round": 2, "venue": 22, "division": null, "bracket": 0.0, "room_rank": 7, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 17, "fields": {"round": 2, "venue": 23, "division": null, "bracket": 1.0, "room_rank": 4, "time": null, "flags": "1u1d_inst", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 18, "fields": {"round": 2, "venue": 15, "division": null, "bracket": 1.0, "room_rank": 5, "time": null, "flags": "1u1d_other", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 19, "fields": {"round": 2, "venue": 14, "division": null, "bracket": 1.0, "room_rank": 1, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 20, "fields": {"round": 2, "venue": 19, "division": null, "bracket": 0.0, "room_rank": 8, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 21, "fields": {"round": 2, "venue": 13, "division": null, "bracket": 0.0, "room_rank": 11, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 22, "fields": {"round": 2, "venue": 18, "division": null, "bracket": 0.0, "room_rank": 10, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 23, "fields": {"round": 2, "venue": 16, "division": null, "bracket": 1.0, "room_rank": 2, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 24, "fields": {"round": 2, "venue": 21, "division": null, "bracket": 0.0, "room_rank": 9, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 25, "fields": {"round": 3, "venue": 20, "division": null, "bracket": 1.0, "room_rank": 4, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 26, "fields": {"round": 3, "venue": 14, "division": null, "bracket": 2.0, "room_rank": 3, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 27, "fields": {"round": 3, "venue": 16, "division": null, "bracket": 1.0, "room_rank": 8, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 28, "fields": {"round": 3, "venue": 18, "division": null, "bracket": 1.0, "room_rank": 9, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 29, "fields": {"round": 3, "venue": 21, "division": null, "bracket": 0.0, "room_rank": 12, "time": null, "flags": "1u1d_other", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 30, "fields": {"round": 3, "venue": 17, "division": null, "bracket": 1.0, "room_rank": 6, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 31, "fields": {"round": 3, "venue": 23, "division": null, "bracket": 2.0, "room_rank": 1, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 32, "fields": {"round": 3, "venue": 1, "division": null, "bracket": 1.0, "room_rank": 5, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 33, "fields": {"round": 3, "venue": 19, "division": null, "bracket": 2.0, "room_rank": 2, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 34, "fields": {"round": 3, "venue": 22, "division": null, "bracket": 0.0, "room_rank": 11, "time": null, "flags": "1u1d_inst", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 35, "fields": {"round": 3, "venue": 13, "division": null, "bracket": 0.0, "room_rank": 10, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 36, "fields": {"round": 3, "venue": 15, "division": null, "bracket": 1.0, "room_rank": 7, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 37, "fields": {"round": 4, "venue": 23, "division": null, "bracket": 1.0, "room_rank": 7, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 38, "fields": {"round": 4, "venue": 16, "division": null, "bracket": 3.0, "room_rank": 1, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 39, "fields": {"round": 4, "venue": 18, "division": null, "bracket": 1.0, "room_rank": 9, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 40, "fields": {"round": 4, "venue": 15, "division": null, "bracket": 1.0, "room_rank": 8, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 41, "fields": {"round": 4, "venue": 21, "division": null, "bracket": 1.0, "room_rank": 10, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 42, "fields": {"round": 4, "venue": 13, "division": null, "bracket": 0.0, "room_rank": 12, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 43, "fields": {"round": 4, "venue": 17, "division": null, "bracket": 0.5, "room_rank": 11, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 44, "fields": {"round": 4, "venue": 1, "division": null, "bracket": 2.0, "room_rank": 5, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 45, "fields": {"round": 4, "venue": 19, "division": null, "bracket": 2.0, "room_rank": 6, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 46, "fields": {"round": 4, "venue": 22, "division": null, "bracket": 2.5, "room_rank": 2, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 47, "fields": {"round": 4, "venue": 14, "division": null, "bracket": 2.0, "room_rank": 4, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 48, "fields": {"round": 4, "venue": 20, "division": null, "bracket": 2.0, "room_rank": 3, "time": null, "flags": "", "importance": 2, "result_status": "C", "ballot_in": false}}, {"model": "draw.debate", "pk": 61, "fields": {"round": 6, "venue": 23, "division": null, "bracket": 0.0, "room_rank": 1, "time": null, "flags": "", "importance": 2, "result_status": "N", "ballot_in": false}}, {"model": "draw.debate", "pk": 62, "fields": {"round": 6, "venue": 22, "division": null, "bracket": 0.0, "room_rank": 2, "time": null, "flags": "", "importance": 2, "result_status": "N", "ballot_in": false}}, {"model": "draw.debate", "pk": 67, "fields": {"round": 7, "venue": 9, "division": null, "bracket": 0.0, "room_rank": 2, "time": null, "flags": "", "importance": 2, "result_status": "N", "ballot_in": false}}, {"model": "draw.debate", "pk": 68, "fields": {"round": 7, "venue": 16, "division": null, "bracket": 0.0, "room_rank": 1, "time": null, "flags": "", "importance": 2, "result_status": "N", "ballot_in": false}}, {"model": "draw.debateteam", "pk": 1, "fields": {"debate": 1, "team": 3, "position": "A"}}, {"model": "draw.debateteam", "pk": 2, "fields": {"debate": 1, "team": 21, "position": "N"}}, {"model": "draw.debateteam", "pk": 3, "fields": {"debate": 2, "team": 20, "position": "A"}}, {"model": "draw.debateteam", "pk": 4, "fields": {"debate": 2, "team": 9, "position": "N"}}, {"model": "draw.debateteam", "pk": 5, "fields": {"debate": 3, "team": 2, "position": "A"}}, {"model": "draw.debateteam", "pk": 6, "fields": {"debate": 3, "team": 13, "position": "N"}}, {"model": "draw.debateteam", "pk": 7, "fields": {"debate": 4, "team": 7, "position": "A"}}, {"model": "draw.debateteam", "pk": 8, "fields": {"debate": 4, "team": 24, "position": "N"}}, {"model": "draw.debateteam", "pk": 9, "fields": {"debate": 5, "team": 6, "position": "A"}}, {"model": "draw.debateteam", "pk": 10, "fields": {"debate": 5, "team": 22, "position": "N"}}, {"model": "draw.debateteam", "pk": 11, "fields": {"debate": 6, "team": 5, "position": "A"}}, {"model": "draw.debateteam", "pk": 12, "fields": {"debate": 6, "team": 10, "position": "N"}}, {"model": "draw.debateteam", "pk": 13, "fields": {"debate": 7, "team": 12, "position": "A"}}, {"model": "draw.debateteam", "pk": 14, "fields": {"debate": 7, "team": 16, "position": "N"}}, {"model": "draw.debateteam", "pk": 15, "fields": {"debate": 8, "team": 19, "position": "A"}}, {"model": "draw.debateteam", "pk": 16, "fields": {"debate": 8, "team": 15, "position": "N"}}, {"model": "draw.debateteam", "pk": 17, "fields": {"debate": 9, "team": 17, "position": "A"}}, {"model": "draw.debateteam", "pk": 18, "fields": {"debate": 9, "team": 1, "position": "N"}}, {"model": "draw.debateteam", "pk": 19, "fields": {"debate": 10, "team": 23, "position": "A"}}, {"model": "draw.debateteam", "pk": 20, "fields": {"debate": 10, "team": 11, "position": "N"}}, {"model": "draw.debateteam", "pk": 21, "fields": {"debate": 11, "team": 4, "position": "A"}}, {"model": "draw.debateteam", "pk": 22, "fields": {"debate": 11, "team": 8, "position": "N"}}, {"model": "draw.debateteam", "pk": 23, "fields": {"debate": 12, "team": 14, "position": "A"}}, {"model": "draw.debateteam", "pk": 24, "fields": {"debate": 12, "team": 18, "position": "N"}}, {"model": "draw.debateteam", "pk": 25, "fields": {"debate": 13, "team": 16, "position": "A"}}, {"model": "draw.debateteam", "pk": 26, "fields": {"debate": 13, "team": 2, "position": "N"}}, {"model": "draw.debateteam", "pk": 27, "fields": {"debate": 14, "team": 13, "position": "A"}}, {"model": "draw.debateteam", "pk": 28, "fields": {"debate": 14, "team": 12, "position": "N"}}, {"model": "draw.debateteam", "pk": 29, "fields": {"debate": 15, "team": 15, "position": "A"}}, {"model": "draw.debateteam", "pk": 30, "fields": {"debate": 15, "team": 7, "position": "N"}}, {"model": "draw.debateteam", "pk": 31, "fields": {"debate": 16, "team": 22, "position": "A"}}, {"model": "draw.debateteam", "pk": 32, "fields": {"debate": 16, "team": 4, "position": "N"}}, {"model": "draw.debateteam", "pk": 33, "fields": {"debate": 17, "team": 18, "position": "A"}}, {"model": "draw.debateteam", "pk": 34, "fields": {"debate": 17, "team": 3, "position": "N"}}, {"model": "draw.debateteam", "pk": 35, "fields": {"debate": 18, "team": 1, "position": "A"}}, {"model": "draw.debateteam", "pk": 36, "fields": {"debate": 18, "team": 6, "position": "N"}}, {"model": "draw.debateteam", "pk": 37, "fields": {"debate": 19, "team": 11, "position": "A"}}, {"model": "draw.debateteam", "pk": 38, "fields": {"debate": 19, "team": 5, "position": "N"}}, {"model": "draw.debateteam", "pk": 39, "fields": {"debate": 20, "team": 24, "position": "A"}}, {"model": "draw.debateteam", "pk": 40, "fields": {"debate": 20, "team": 21, "position": "N"}}, {"model": "draw.debateteam", "pk": 41, "fields": {"debate": 21, "team": 17, "position": "A"}}, {"model": "draw.debateteam", "pk": 42, "fields": {"debate": 21, "team": 23, "position": "N"}}, {"model": "draw.debateteam", "pk": 43, "fields": {"debate": 22, "team": 14, "position": "A"}}, {"model": "draw.debateteam", "pk": 44, "fields": {"debate": 22, "team": 20, "position": "N"}}, {"model": "draw.debateteam", "pk": 45, "fields": {"debate": 23, "team": 9, "position": "A"}}, {"model": "draw.debateteam", "pk": 46, "fields": {"debate": 23, "team": 8, "position": "N"}}, {"model": "draw.debateteam", "pk": 47, "fields": {"debate": 24, "team": 10, "position": "A"}}, {"model": "draw.debateteam", "pk": 48, "fields": {"debate": 24, "team": 19, "position": "N"}}, {"model": "draw.debateteam", "pk": 49, "fields": {"debate": 25, "team": 3, "position": "A"}}, {"model": "draw.debateteam", "pk": 50, "fields": {"debate": 25, "team": 4, "position": "N"}}, {"model": "draw.debateteam", "pk": 51, "fields": {"debate": 26, "team": 1, "position": "A"}}, {"model": "draw.debateteam", "pk": 52, "fields": {"debate": 26, "team": 18, "position": "N"}}, {"model": "draw.debateteam", "pk": 53, "fields": {"debate": 27, "team": 15, "position": "A"}}, {"model": "draw.debateteam", "pk": 54, "fields": {"debate": 27, "team": 6, "position": "N"}}, {"model": "draw.debateteam", "pk": 55, "fields": {"debate": 28, "team": 21, "position": "A"}}, {"model": "draw.debateteam", "pk": 56, "fields": {"debate": 28, "team": 12, "position": "N"}}, {"model": "draw.debateteam", "pk": 57, "fields": {"debate": 29, "team": 24, "position": "A"}}, {"model": "draw.debateteam", "pk": 58, "fields": {"debate": 29, "team": 19, "position": "N"}}, {"model": "draw.debateteam", "pk": 59, "fields": {"debate": 30, "team": 10, "position": "A"}}, {"model": "draw.debateteam", "pk": 60, "fields": {"debate": 30, "team": 2, "position": "N"}}, {"model": "draw.debateteam", "pk": 61, "fields": {"debate": 31, "team": 9, "position": "A"}}, {"model": "draw.debateteam", "pk": 62, "fields": {"debate": 31, "team": 7, "position": "N"}}, {"model": "draw.debateteam", "pk": 63, "fields": {"debate": 32, "team": 20, "position": "A"}}, {"model": "draw.debateteam", "pk": 64, "fields": {"debate": 32, "team": 5, "position": "N"}}, {"model": "draw.debateteam", "pk": 65, "fields": {"debate": 33, "team": 16, "position": "A"}}, {"model": "draw.debateteam", "pk": 66, "fields": {"debate": 33, "team": 11, "position": "N"}}, {"model": "draw.debateteam", "pk": 67, "fields": {"debate": 34, "team": 23, "position": "A"}}, {"model": "draw.debateteam", "pk": 68, "fields": {"debate": 34, "team": 14, "position": "N"}}, {"model": "draw.debateteam", "pk": 69, "fields": {"debate": 35, "team": 22, "position": "A"}}, {"model": "draw.debateteam", "pk": 70, "fields": {"debate": 35, "team": 13, "position": "N"}}, {"model": "draw.debateteam", "pk": 71, "fields": {"debate": 36, "team": 8, "position": "A"}}, {"model": "draw.debateteam", "pk": 72, "fields": {"debate": 36, "team": 17, "position": "N"}}, {"model": "draw.debateteam", "pk": 73, "fields": {"debate": 37, "team": 19, "position": "A"}}, {"model": "draw.debateteam", "pk": 74, "fields": {"debate": 37, "team": 22, "position": "N"}}, {"model": "draw.debateteam", "pk": 75, "fields": {"debate": 38, "team": 11, "position": "A"}}, {"model": "draw.debateteam", "pk": 76, "fields": {"debate": 38, "team": 7, "position": "N"}}, {"model": "draw.debateteam", "pk": 77, "fields": {"debate": 39, "team": 8, "position": "A"}}, {"model": "draw.debateteam", "pk": 78, "fields": {"debate": 39, "team": 5, "position": "N"}}, {"model": "draw.debateteam", "pk": 79, "fields": {"debate": 40, "team": 3, "position": "A"}}, {"model": "draw.debateteam", "pk": 80, "fields": {"debate": 40, "team": 23, "position": "N"}}, {"model": "draw.debateteam", "pk": 81, "fields": {"debate": 41, "team": 21, "position": "A"}}, {"model": "draw.debateteam", "pk": 82, "fields": {"debate": 41, "team": 15, "position": "N"}}, {"model": "draw.debateteam", "pk": 83, "fields": {"debate": 42, "team": 13, "position": "A"}}, {"model": "draw.debateteam", "pk": 84, "fields": {"debate": 42, "team": 14, "position": "N"}}, {"model": "draw.debateteam", "pk": 85, "fields": {"debate": 43, "team": 2, "position": "A"}}, {"model": "draw.debateteam", "pk": 86, "fields": {"debate": 43, "team": 24, "position": "N"}}, {"model": "draw.debateteam", "pk": 87, "fields": {"debate": 44, "team": 12, "position": "A"}}, {"model": "draw.debateteam", "pk": 88, "fields": {"debate": 44, "team": 9, "position": "N"}}, {"model": "draw.debateteam", "pk": 89, "fields": {"debate": 45, "team": 16, "position": "A"}}, {"model": "draw.debateteam", "pk": 90, "fields": {"debate": 45, "team": 1, "position": "N"}}, {"model": "draw.debateteam", "pk": 91, "fields": {"debate": 46, "team": 4, "position": "A"}}, {"model": "draw.debateteam", "pk": 92, "fields": {"debate": 46, "team": 18, "position": "N"}}, {"model": "draw.debateteam", "pk": 93, "fields": {"debate": 47, "team": 6, "position": "A"}}, {"model": "draw.debateteam", "pk": 94, "fields": {"debate": 47, "team": 20, "position": "N"}}, {"model": "draw.debateteam", "pk": 95, "fields": {"debate": 48, "team": 17, "position": "A"}}, {"model": "draw.debateteam", "pk": 96, "fields": {"debate": 48, "team": 10, "position": "N"}}, {"model": "draw.debateteam", "pk": 121, "fields": {"debate": 61, "team": 10, "position": "A"}}, {"model": "draw.debateteam", "pk": 122, "fields": {"debate": 61, "team": 9, "position": "N"}}, {"model": "draw.debateteam", "pk": 123, "fields": {"debate": 62, "team": 6, "position": "A"}}, {"model": "draw.debateteam", "pk": 124, "fields": {"debate": 62, "team": 5, "position": "N"}}, {"model": "draw.debateteam", "pk": 133, "fields": {"debate": 67, "team": 12, "position": "A"}}, {"model": "draw.debateteam", "pk": 134, "fields": {"debate": 67, "team": 20, "position": "N"}}, {"model": "draw.debateteam", "pk": 135, "fields": {"debate": 68, "team": 18, "position": "A"}}, {"model": "draw.debateteam", "pk": 136, "fields": {"debate": 68, "team": 4, "position": "N"}}, {"model": "motions.motion", "pk": 1, "fields": {"seq": 1, "text": "This House would abolish national days", "reference": "National days", "flagged": false, "round": 1, "divisions": []}}, {"model": "motions.motion", "pk": 2, "fields": {"seq": 2, "text": "This House regrets the existence of Valentine's Day", "reference": "Valentine\u2019s Day", "flagged": false, "round": 1, "divisions": []}}, {"model": "motions.motion", "pk": 3, "fields": {"seq": 3, "text": "This House would rename Christmas with a name that is religiously neutral", "reference": "Christmas", "flagged": false, "round": 1, "divisions": []}}, {"model": "motions.motion", "pk": 4, "fields": {"seq": 1, "text": "This House would not buy Apple", "reference": "Apple", "flagged": false, "round": 2, "divisions": []}}, {"model": "motions.motion", "pk": 5, "fields": {"seq": 2, "text": "This House would end all research and development tax credits for highly profitable technology companies", "reference": "R&D tax credit", "flagged": false, "round": 2, "divisions": []}}, {"model": "motions.motion", "pk": 6, "fields": {"seq": 3, "text": "This House regrets the rise of computer science at the expense of the humanities", "reference": "Computer science", "flagged": false, "round": 2, "divisions": []}}, {"model": "motions.motion", "pk": 7, "fields": {"seq": 1, "text": "This House would favour creativity over intelligence", "reference": "Creativity and intelligence", "flagged": false, "round": 3, "divisions": []}}, {"model": "motions.motion", "pk": 8, "fields": {"seq": 2, "text": "This House believes that field hockey is better than ice hockey", "reference": "Hockey", "flagged": false, "round": 3, "divisions": []}}, {"model": "motions.motion", "pk": 9, "fields": {"seq": 3, "text": "This House would rather play with Lego than Barbie", "reference": "Lego and Barbie", "flagged": false, "round": 3, "divisions": []}}, {"model": "motions.motion", "pk": 10, "fields": {"seq": 1, "text": "This House would stop importing bananas from Latin America", "reference": "Bananas", "flagged": false, "round": 4, "divisions": []}}, {"model": "motions.motion", "pk": 11, "fields": {"seq": 2, "text": "This House believes that tomatoes are a fruit", "reference": "Tomatoes", "flagged": false, "round": 4, "divisions": []}}, {"model": "motions.motion", "pk": 12, "fields": {"seq": 3, "text": "This House would require all fruit to carry labels noting what pesticides are used on them", "reference": "Pesticide labelling", "flagged": false, "round": 4, "divisions": []}}, {"model": "motions.motion", "pk": 13, "fields": {"seq": 1, "text": "This House would make an exception to laws forbidding indecent exposure for days with hot temperatures", "reference": "Indecent exposure", "flagged": false, "round": 7, "divisions": []}}, {"model": "motions.motion", "pk": 14, "fields": {"seq": 2, "text": "This House regrets the development of different fashion lines for men and women", "reference": "Gender and fashion", "flagged": false, "round": 7, "divisions": []}}, {"model": "motions.motion", "pk": 15, "fields": {"seq": 3, "text": "This House believes that it is unprofessional to wear flip-flops (jandals, thongs) to work", "reference": "Flip-flops", "flagged": false, "round": 7, "divisions": []}}, {"model": "motions.motion", "pk": 16, "fields": {"seq": 1, "text": "This House would stop using cash", "reference": "Cash", "flagged": false, "round": 10, "divisions": []}}, {"model": "motions.motion", "pk": 17, "fields": {"seq": 2, "text": "This House supports Bitcoin", "reference": "Bitcoin", "flagged": false, "round": 10, "divisions": []}}, {"model": "motions.motion", "pk": 18, "fields": {"seq": 3, "text": "This House would allow private organisations to compete in providing currency", "reference": "Private currency", "flagged": false, "round": 10, "divisions": []}}, {"model": "participants.region", "pk": 1, "fields": {"name": "NY", "tournament": 1}}, {"model": "participants.region", "pk": 2, "fields": {"name": "MA", "tournament": 1}}, {"model": "participants.region", "pk": 3, "fields": {"name": "MD", "tournament": 1}}, {"model": "participants.region", "pk": 4, "fields": {"name": "CT", "tournament": 1}}, {"model": "participants.region", "pk": 5, "fields": {"name": "PA", "tournament": 1}}, {"model": "participants.region", "pk": 6, "fields": {"name": "CA", "tournament": 1}}, {"model": "participants.region", "pk": 7, "fields": {"name": "Other", "tournament": 1}}, {"model": "participants.institution", "pk": 1, "fields": {"name": "California Institute of Technology", "code": "Caltech", "abbreviation": "Calt", "region": 6}}, {"model": "participants.institution", "pk": 2, "fields": {"name": "Columbia University", "code": "Columbia", "abbreviation": "Colum", "region": 1}}, {"model": "participants.institution", "pk": 3, "fields": {"name": "Cornell University", "code": "Cornell", "abbreviation": "Corn", "region": 1}}, {"model": "participants.institution", "pk": 4, "fields": {"name": "Harvard University", "code": "Harvard", "abbreviation": "Harv", "region": 2}}, {"model": "participants.institution", "pk": 5, "fields": {"name": "Johns Hopkins University", "code": "Johns Hopkins", "abbreviation": "JHU", "region": 3}}, {"model": "participants.institution", "pk": 6, "fields": {"name": "Massachusetts Institute of Technology", "code": "MIT", "abbreviation": "MIT", "region": 2}}, {"model": "participants.institution", "pk": 7, "fields": {"name": "Princeton University", "code": "Princeton", "abbreviation": "Prin", "region": null}}, {"model": "participants.institution", "pk": 8, "fields": {"name": "Stanford University", "code": "Stanford", "abbreviation": "Stan", "region": 6}}, {"model": "participants.institution", "pk": 9, "fields": {"name": "University of California, Berkeley", "code": "Berkeley", "abbreviation": "Cal", "region": 6}}, {"model": "participants.institution", "pk": 10, "fields": {"name": "University of Chicago", "code": "Chicago", "abbreviation": "Chic", "region": null}}, {"model": "participants.institution", "pk": 11, "fields": {"name": "University of Pennsylvania", "code": "Pennsylvania", "abbreviation": "Penn", "region": 5}}, {"model": "participants.institution", "pk": 12, "fields": {"name": "University of Toronto", "code": "Toronto", "abbreviation": "Toron", "region": null}}, {"model": "participants.institution", "pk": 13, "fields": {"name": "Yale University", "code": "Yale", "abbreviation": "Yale", "region": 4}}, {"model": "participants.person", "pk": 1, "fields": {"name": "Georgia Crawford", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 2, "fields": {"name": "Wanda Griffin", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 3, "fields": {"name": "Helen Keller", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 4, "fields": {"name": "Russell Warren", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 5, "fields": {"name": "Angel Rhodes", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": null, "pronoun": "they"}}, {"model": "participants.person", "pk": 6, "fields": {"name": "Terry Henderson", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 7, "fields": {"name": "Kyle Ruiz", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 8, "fields": {"name": "Randolph Lambert", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": null}}, {"model": "participants.person", "pk": 9, "fields": {"name": "Sergio Pittman", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 10, "fields": {"name": "Earnest Becker", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 11, "fields": {"name": "Ellis Rowe", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 12, "fields": {"name": "Robin Roberson", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 13, "fields": {"name": "Gwen Newman", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 14, "fields": {"name": "Robyn Caldwell", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": null}}, {"model": "participants.person", "pk": 15, "fields": {"name": "Angie Holt", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 16, "fields": {"name": "Melvin Jordan", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 17, "fields": {"name": "Gladys Burke", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": null}}, {"model": "participants.person", "pk": 18, "fields": {"name": "Patty Saunders", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 19, "fields": {"name": "Thomas Pierce", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 20, "fields": {"name": "Stella Lindsey", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 21, "fields": {"name": "Adrian May", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 22, "fields": {"name": "Taylor Brown", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": null}}, {"model": "participants.person", "pk": 23, "fields": {"name": "Bethany Chambers", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 24, "fields": {"name": "Pamela Bryan", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 25, "fields": {"name": "Janet Nunez", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 26, "fields": {"name": "Owen Chandler", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": null}}, {"model": "participants.person", "pk": 27, "fields": {"name": "Lillie Rodriquez", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 28, "fields": {"name": "Rufus Dennis", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 29, "fields": {"name": "Marty Love", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 30, "fields": {"name": "Shelia Wright", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 31, "fields": {"name": "Clark Mills", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 32, "fields": {"name": "Randy Carroll", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 33, "fields": {"name": "Casey Sparks", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 34, "fields": {"name": "Candace Bowen", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 35, "fields": {"name": "Jaime Long", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 36, "fields": {"name": "Leon Hall", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 37, "fields": {"name": "Morris Nichols", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 38, "fields": {"name": "Benjamin Padilla", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 39, "fields": {"name": "Phil Lyons", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 40, "fields": {"name": "Clay Holland", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 41, "fields": {"name": "Elena Cobb", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 42, "fields": {"name": "Shawn Torres", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 43, "fields": {"name": "Willis Carson", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 44, "fields": {"name": "Wendell Nelson", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 45, "fields": {"name": "Felicia Welch", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 46, "fields": {"name": "Cory Meyer", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 47, "fields": {"name": "Stacy Frazier", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 48, "fields": {"name": "Claire Dunn", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 49, "fields": {"name": "Eloise Munoz", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 50, "fields": {"name": "Patricia Palmer", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 51, "fields": {"name": "Stewart Day", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 52, "fields": {"name": "Timmy Craig", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 53, "fields": {"name": "Patrick Kelly", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 54, "fields": {"name": "Kristopher Hayes", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 55, "fields": {"name": "Andy Lane", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 56, "fields": {"name": "Scott Mcdonald", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 57, "fields": {"name": "Charlene Cortez", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 58, "fields": {"name": "Leigh Holmes", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": null}}, {"model": "participants.person", "pk": 59, "fields": {"name": "Alma Spencer", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 60, "fields": {"name": "Winston Castro", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 61, "fields": {"name": "Emilio Simmons", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 62, "fields": {"name": "Ron Delgado", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": null, "pronoun": "he"}}, {"model": "participants.person", "pk": 63, "fields": {"name": "Nadine Barber", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 64, "fields": {"name": "Gail Adkins", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": null, "pronoun": "he"}}, {"model": "participants.person", "pk": 65, "fields": {"name": "Willard Walton", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": null}}, {"model": "participants.person", "pk": 66, "fields": {"name": "Jackie Peterson", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 67, "fields": {"name": "Terry Thornton", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": null, "pronoun": "they"}}, {"model": "participants.person", "pk": 68, "fields": {"name": "Norman Rodgers", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 69, "fields": {"name": "Mattie Lee", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": null, "pronoun": "they"}}, {"model": "participants.person", "pk": 70, "fields": {"name": "Woodrow Harvey", "barcode_id": null, "email": null, "phone": null, "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 71, "fields": {"name": "Javier Chavez", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": null, "pronoun": null}}, {"model": "participants.person", "pk": 72, "fields": {"name": "Janie Daniels", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 73, "fields": {"name": "Levi Flores", "barcode_id": null, "email": "leviflores@gmail.com", "phone": "(400) 258-4262", "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 74, "fields": {"name": "Boyd Pierce", "barcode_id": null, "email": "boydpierce@yahoo.com", "phone": "(645) 106-7743", "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 75, "fields": {"name": "Eunice Mcbride", "barcode_id": null, "email": "eunicemcbride@outlook.com", "phone": "(549) 309-9187", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 76, "fields": {"name": "Ramona Cobb", "barcode_id": null, "email": "ramonacobb@yahoo.com", "phone": "(440) 487-5776", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 77, "fields": {"name": "Justin Ford", "barcode_id": null, "email": "justinford@outlook.com", "phone": "(618) 921-9188", "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 78, "fields": {"name": "Luis Bennett", "barcode_id": null, "email": "luisbennett@gmail.com", "phone": "(730) 097-8797", "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 79, "fields": {"name": "Mandy Estrada", "barcode_id": null, "email": "mandyestrada@gmail.com", "phone": "(559) 299-0471", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 80, "fields": {"name": "Leigh Mcgee", "barcode_id": null, "email": "leighmcgee@gmail.com", "phone": "(844) 760-9302", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 81, "fields": {"name": "Jacqueline Freeman", "barcode_id": null, "email": "jacquelinefreeman@yahoo.com", "phone": "(297) 916-1716", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 82, "fields": {"name": "Holly Howard", "barcode_id": null, "email": "hollyhoward@gmail.com", "phone": "(958) 783-2610", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 83, "fields": {"name": "Pedro Burgess", "barcode_id": null, "email": "pedroburgess@yahoo.com", "phone": "(854) 441-0104", "novice": false, "checkin_message": "", "notes": null, "gender": null, "pronoun": null}}, {"model": "participants.person", "pk": 84, "fields": {"name": "Kristy Carr", "barcode_id": null, "email": "kristycarr@yahoo.com", "phone": "(644) 607-3297", "novice": true, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 85, "fields": {"name": "Wilma Vaughn", "barcode_id": null, "email": "wilmavaughn@outlook.com", "phone": "(398) 759-9537", "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 86, "fields": {"name": "Virginia Mccarthy", "barcode_id": null, "email": "virginiamccarthy@gmail.com", "phone": "(455) 177-0459", "novice": true, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 87, "fields": {"name": "Tasha Jenkins", "barcode_id": null, "email": "tashajenkins@outlook.com", "phone": "(875) 519-9891", "novice": false, "checkin_message": "", "notes": null, "gender": null, "pronoun": null}}, {"model": "participants.person", "pk": 88, "fields": {"name": "Toby Wong", "barcode_id": null, "email": "tobywong@gmail.com", "phone": "(404) 641-5999", "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 89, "fields": {"name": "Jo Allen", "barcode_id": null, "email": "joallen@yahoo.com", "phone": "(761) 993-2983", "novice": false, "checkin_message": "", "notes": "", "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 90, "fields": {"name": "Billy Griffin", "barcode_id": null, "email": "billygriffin@outlook.com", "phone": "(430) 532-2939", "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 91, "fields": {"name": "Angela Reed", "barcode_id": null, "email": "angelareed@yahoo.com", "phone": "(936) 500-1228", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 92, "fields": {"name": "Hugo Lewis", "barcode_id": null, "email": "hugolewis@outlook.com", "phone": "(422) 585-9609", "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "they"}}, {"model": "participants.person", "pk": 93, "fields": {"name": "Cassandra Wilson", "barcode_id": null, "email": "cassandrawilson@gmail.com", "phone": "(604) 306-2084", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 94, "fields": {"name": "George Willis", "barcode_id": null, "email": "georgewillis@yahoo.com", "phone": "(222) 204-5944", "novice": false, "checkin_message": "", "notes": null, "gender": "M", "pronoun": "he"}}, {"model": "participants.person", "pk": 95, "fields": {"name": "Jamie Hodges", "barcode_id": null, "email": "jamiehodges@outlook.com", "phone": "(737) 122-6102", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 96, "fields": {"name": "Bennie Rodriguez", "barcode_id": null, "email": "bennierodriguez@gmail.com", "phone": "(537) 641-2175", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 97, "fields": {"name": "Allison Martin", "barcode_id": null, "email": "allisonmartin@outlook.com", "phone": "(525) 384-2715", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 98, "fields": {"name": "Kristi Elliott", "barcode_id": null, "email": "kristielliott@gmail.com", "phone": "(790) 289-5430", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 99, "fields": {"name": "Pearl Graves", "barcode_id": null, "email": "pearlgraves@outlook.com", "phone": "(317) 721-2439", "novice": false, "checkin_message": "", "notes": null, "gender": "F", "pronoun": "she"}}, {"model": "participants.person", "pk": 159, "fields": {"name": "New Adjudicator Shared", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": null, "pronoun": null}}, {"model": "participants.person", "pk": 160, "fields": {"name": "New Adjudicator Shared", "barcode_id": null, "email": null, "phone": null, "novice": false, "checkin_message": "", "notes": null, "gender": null, "pronoun": null}}, {"model": "participants.team", "pk": 1, "fields": {"reference": "1", "short_reference": "1", "short_name": "Caltech 1", "long_name": "California Institute of Technology 1", "emoji": "\ud83c\udf29", "institution": 1, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 2, "fields": {"reference": "2", "short_reference": "2", "short_name": "Caltech 2", "long_name": "California Institute of Technology 2", "emoji": "\ud83c\udf83", "institution": 1, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 3, "fields": {"reference": "3", "short_reference": "3", "short_name": "Caltech 3", "long_name": "California Institute of Technology 3", "emoji": "\ud83c\udd92", "institution": 1, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 4, "fields": {"reference": "1", "short_reference": "1", "short_name": "Columbia 1", "long_name": "Columbia University 1", "emoji": "\ud83c\udf4c", "institution": 2, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1, 2, 3]}}, {"model": "participants.team", "pk": 5, "fields": {"reference": "1", "short_reference": "1", "short_name": "Cornell 1", "long_name": "Cornell University 1", "emoji": "\ud83c\udd98", "institution": 3, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1, 2, 3]}}, {"model": "participants.team", "pk": 6, "fields": {"reference": "1", "short_reference": "1", "short_name": "Harvard 1", "long_name": "Harvard University 1", "emoji": "\ud83d\udc8e", "institution": 4, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1, 2, 3]}}, {"model": "participants.team", "pk": 7, "fields": {"reference": "2", "short_reference": "2", "short_name": "Harvard 2", "long_name": "Harvard University 2", "emoji": "\ud83d\udd6f", "institution": 4, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 8, "fields": {"reference": "1", "short_reference": "1", "short_name": "Johns Hopkins 1", "long_name": "Johns Hopkins University 1", "emoji": "\ud83c\udf96", "institution": 5, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 9, "fields": {"reference": "1", "short_reference": "1", "short_name": "MIT 1", "long_name": "Massachusetts Institute of Technology 1", "emoji": "\ud83d\udda8", "institution": 6, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1, 2]}}, {"model": "participants.team", "pk": 10, "fields": {"reference": "2", "short_reference": "2", "short_name": "MIT 2", "long_name": "Massachusetts Institute of Technology 2", "emoji": "\ud83d\ude34", "institution": 6, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1, 2]}}, {"model": "participants.team", "pk": 11, "fields": {"reference": "1", "short_reference": "1", "short_name": "Princeton 1", "long_name": "Princeton University 1", "emoji": "\ud83c\udf36", "institution": 7, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 12, "fields": {"reference": "2", "short_reference": "2", "short_name": "Princeton 2", "long_name": "Princeton University 2", "emoji": "\ud83d\ude4c", "institution": 7, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 13, "fields": {"reference": "1", "short_reference": "1", "short_name": "Stanford 1", "long_name": "Stanford University 1", "emoji": "\ud83d\udd96", "institution": 8, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 14, "fields": {"reference": "2", "short_reference": "2", "short_name": "Stanford 2", "long_name": "Stanford University 2", "emoji": "\ud83d\udd95", "institution": 8, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 15, "fields": {"reference": "3", "short_reference": "3", "short_name": "Stanford 3", "long_name": "Stanford University 3", "emoji": "\u26cf", "institution": 8, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 16, "fields": {"reference": "1", "short_reference": "1", "short_name": "Berkeley 1", "long_name": "University of California, Berkeley 1", "emoji": "\ud83d\udc26", "institution": 9, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 17, "fields": {"reference": "1", "short_reference": "1", "short_name": "Chicago 1", "long_name": "University of Chicago 1", "emoji": "\ud83d\ude2e", "institution": 10, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1, 2]}}, {"model": "participants.team", "pk": 18, "fields": {"reference": "2", "short_reference": "2", "short_name": "Chicago 2", "long_name": "University of Chicago 2", "emoji": "\ud83c\udf37", "institution": 10, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1, 2]}}, {"model": "participants.team", "pk": 19, "fields": {"reference": "3", "short_reference": "3", "short_name": "Chicago 3", "long_name": "University of Chicago 3", "emoji": "\ud83d\udd75", "institution": 10, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1, 2, 3]}}, {"model": "participants.team", "pk": 20, "fields": {"reference": "1", "short_reference": "1", "short_name": "Pennsylvania 1", "long_name": "University of Pennsylvania 1", "emoji": "\ud83d\udeac", "institution": 11, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 21, "fields": {"reference": "2", "short_reference": "2", "short_name": "Pennsylvania 2", "long_name": "University of Pennsylvania 2", "emoji": "\ud83d\udc60", "institution": 11, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 22, "fields": {"reference": "1", "short_reference": "1", "short_name": "Yale 1", "long_name": "Yale University 1", "emoji": "\ud83d\udc53", "institution": 13, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 23, "fields": {"reference": "2", "short_reference": "2", "short_name": "Yale 2", "long_name": "Yale University 2", "emoji": "\ud83d\udc4a", "institution": 13, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.team", "pk": 24, "fields": {"reference": "3", "short_reference": "3", "short_name": "Yale 3", "long_name": "Yale University 3", "emoji": "\ud83c\udf53", "institution": 13, "tournament": 1, "division": null, "use_institution_prefix": true, "url_key": null, "type": "N", "break_categories": [1]}}, {"model": "participants.speaker", "pk": 21, "fields": {"team": 7}}, {"model": "participants.speaker", "pk": 59, "fields": {"team": 20}}, {"model": "participants.speaker", "pk": 55, "fields": {"team": 19}}, {"model": "participants.speaker", "pk": 5, "fields": {"team": 2}}, {"model": "participants.speaker", "pk": 15, "fields": {"team": 5}}, {"model": "participants.speaker", "pk": 38, "fields": {"team": 13}}, {"model": "participants.speaker", "pk": 23, "fields": {"team": 8}}, {"model": "participants.speaker", "pk": 34, "fields": {"team": 12}}, {"model": "participants.speaker", "pk": 33, "fields": {"team": 11}}, {"model": "participants.speaker", "pk": 57, "fields": {"team": 19}}, {"model": "participants.speaker", "pk": 48, "fields": {"team": 16}}, {"model": "participants.speaker", "pk": 31, "fields": {"team": 11}}, {"model": "participants.speaker", "pk": 40, "fields": {"team": 14}}, {"model": "participants.speaker", "pk": 46, "fields": {"team": 16}}, {"model": "participants.speaker", "pk": 10, "fields": {"team": 4}}, {"model": "participants.speaker", "pk": 41, "fields": {"team": 14}}, {"model": "participants.speaker", "pk": 11, "fields": {"team": 4}}, {"model": "participants.speaker", "pk": 49, "fields": {"team": 17}}, {"model": "participants.speaker", "pk": 61, "fields": {"team": 21}}, {"model": "participants.speaker", "pk": 45, "fields": {"team": 15}}, {"model": "participants.speaker", "pk": 64, "fields": {"team": 22}}, {"model": "participants.speaker", "pk": 1, "fields": {"team": 1}}, {"model": "participants.speaker", "pk": 17, "fields": {"team": 6}}, {"model": "participants.speaker", "pk": 13, "fields": {"team": 5}}, {"model": "participants.speaker", "pk": 3, "fields": {"team": 1}}, {"model": "participants.speaker", "pk": 66, "fields": {"team": 22}}, {"model": "participants.speaker", "pk": 35, "fields": {"team": 12}}, {"model": "participants.speaker", "pk": 25, "fields": {"team": 9}}, {"model": "participants.speaker", "pk": 72, "fields": {"team": 24}}, {"model": "participants.speaker", "pk": 71, "fields": {"team": 24}}, {"model": "participants.speaker", "pk": 54, "fields": {"team": 18}}, {"model": "participants.speaker", "pk": 7, "fields": {"team": 3}}, {"model": "participants.speaker", "pk": 58, "fields": {"team": 20}}, {"model": "participants.speaker", "pk": 36, "fields": {"team": 12}}, {"model": "participants.speaker", "pk": 27, "fields": {"team": 9}}, {"model": "participants.speaker", "pk": 29, "fields": {"team": 10}}, {"model": "participants.speaker", "pk": 69, "fields": {"team": 23}}, {"model": "participants.speaker", "pk": 16, "fields": {"team": 6}}, {"model": "participants.speaker", "pk": 37, "fields": {"team": 13}}, {"model": "participants.speaker", "pk": 63, "fields": {"team": 21}}, {"model": "participants.speaker", "pk": 68, "fields": {"team": 23}}, {"model": "participants.speaker", "pk": 26, "fields": {"team": 9}}, {"model": "participants.speaker", "pk": 24, "fields": {"team": 8}}, {"model": "participants.speaker", "pk": 50, "fields": {"team": 17}}, {"model": "participants.speaker", "pk": 53, "fields": {"team": 18}}, {"model": "participants.speaker", "pk": 18, "fields": {"team": 6}}, {"model": "participants.speaker", "pk": 39, "fields": {"team": 13}}, {"model": "participants.speaker", "pk": 8, "fields": {"team": 3}}, {"model": "participants.speaker", "pk": 32, "fields": {"team": 11}}, {"model": "participants.speaker", "pk": 12, "fields": {"team": 4}}, {"model": "participants.speaker", "pk": 14, "fields": {"team": 5}}, {"model": "participants.speaker", "pk": 62, "fields": {"team": 21}}, {"model": "participants.speaker", "pk": 28, "fields": {"team": 10}}, {"model": "participants.speaker", "pk": 4, "fields": {"team": 2}}, {"model": "participants.speaker", "pk": 56, "fields": {"team": 19}}, {"model": "participants.speaker", "pk": 9, "fields": {"team": 3}}, {"model": "participants.speaker", "pk": 42, "fields": {"team": 14}}, {"model": "participants.speaker", "pk": 30, "fields": {"team": 10}}, {"model": "participants.speaker", "pk": 47, "fields": {"team": 16}}, {"model": "participants.speaker", "pk": 20, "fields": {"team": 7}}, {"model": "participants.speaker", "pk": 51, "fields": {"team": 17}}, {"model": "participants.speaker", "pk": 22, "fields": {"team": 8}}, {"model": "participants.speaker", "pk": 6, "fields": {"team": 2}}, {"model": "participants.speaker", "pk": 67, "fields": {"team": 23}}, {"model": "participants.speaker", "pk": 19, "fields": {"team": 7}}, {"model": "participants.speaker", "pk": 52, "fields": {"team": 18}}, {"model": "participants.speaker", "pk": 2, "fields": {"team": 1}}, {"model": "participants.speaker", "pk": 44, "fields": {"team": 15}}, {"model": "participants.speaker", "pk": 65, "fields": {"team": 22}}, {"model": "participants.speaker", "pk": 43, "fields": {"team": 15}}, {"model": "participants.speaker", "pk": 60, "fields": {"team": 20}}, {"model": "participants.speaker", "pk": 70, "fields": {"team": 24}}, {"model": "participants.adjudicator", "pk": 97, "fields": {"institution": 13, "tournament": 1, "test_score": 4.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 91, "fields": {"institution": 8, "tournament": 1, "test_score": 1.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 96, "fields": {"institution": 11, "tournament": 1, "test_score": 2.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 90, "fields": {"institution": 7, "tournament": 1, "test_score": 2.0, "url_key": null, "breaking": true, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 74, "fields": {"institution": 8, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": true, "independent": true, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 93, "fields": {"institution": 9, "tournament": 1, "test_score": 4.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 75, "fields": {"institution": 12, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 94, "fields": {"institution": 10, "tournament": 1, "test_score": 2.0, "url_key": null, "breaking": true, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 82, "fields": {"institution": 12, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": false, "independent": true, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 92, "fields": {"institution": 8, "tournament": 1, "test_score": 2.0, "url_key": null, "breaking": true, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 81, "fields": {"institution": 4, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": false, "independent": true, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 95, "fields": {"institution": 10, "tournament": 1, "test_score": 3.0, "url_key": null, "breaking": true, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 89, "fields": {"institution": 7, "tournament": 1, "test_score": 2.0, "url_key": null, "breaking": true, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 77, "fields": {"institution": 1, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 98, "fields": {"institution": 13, "tournament": 1, "test_score": 3.0, "url_key": null, "breaking": true, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 84, "fields": {"institution": 8, "tournament": 1, "test_score": 4.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 80, "fields": {"institution": 4, "tournament": 1, "test_score": 4.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 73, "fields": {"institution": 13, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 78, "fields": {"institution": 2, "tournament": 1, "test_score": 2.0, "url_key": null, "breaking": true, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 79, "fields": {"institution": 3, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": false, "independent": true, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 159, "fields": {"institution": 1, "tournament": null, "test_score": 2.5, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 160, "fields": {"institution": 2, "tournament": null, "test_score": 2.5, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 99, "fields": {"institution": 5, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 83, "fields": {"institution": 12, "tournament": 1, "test_score": 4.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 76, "fields": {"institution": 1, "tournament": 1, "test_score": 1.0, "url_key": null, "breaking": false, "independent": true, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 87, "fields": {"institution": 6, "tournament": 1, "test_score": 2.0, "url_key": null, "breaking": true, "independent": true, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 88, "fields": {"institution": 6, "tournament": 1, "test_score": 5.0, "url_key": null, "breaking": true, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 86, "fields": {"institution": 5, "tournament": 1, "test_score": 2.0, "url_key": null, "breaking": false, "independent": false, "adj_core": false}}, {"model": "participants.adjudicator", "pk": 85, "fields": {"institution": 5, "tournament": 1, "test_score": 4.0, "url_key": null, "breaking": false, "independent": true, "adj_core": false}}, {"model": "results.speakerscorebyadj", "pk": 1, "fields": {"ballot_submission": 1, "debate_adjudicator": 1, "debate_team": 23, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 2, "fields": {"ballot_submission": 1, "debate_adjudicator": 1, "debate_team": 23, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 3, "fields": {"ballot_submission": 1, "debate_adjudicator": 1, "debate_team": 23, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 4, "fields": {"ballot_submission": 1, "debate_adjudicator": 1, "debate_team": 23, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 5, "fields": {"ballot_submission": 1, "debate_adjudicator": 1, "debate_team": 24, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 6, "fields": {"ballot_submission": 1, "debate_adjudicator": 1, "debate_team": 24, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 7, "fields": {"ballot_submission": 1, "debate_adjudicator": 1, "debate_team": 24, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 8, "fields": {"ballot_submission": 1, "debate_adjudicator": 1, "debate_team": 24, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 9, "fields": {"ballot_submission": 2, "debate_adjudicator": 2, "debate_team": 21, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 10, "fields": {"ballot_submission": 2, "debate_adjudicator": 2, "debate_team": 21, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 11, "fields": {"ballot_submission": 2, "debate_adjudicator": 2, "debate_team": 21, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 12, "fields": {"ballot_submission": 2, "debate_adjudicator": 2, "debate_team": 21, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 13, "fields": {"ballot_submission": 2, "debate_adjudicator": 2, "debate_team": 22, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 14, "fields": {"ballot_submission": 2, "debate_adjudicator": 2, "debate_team": 22, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 15, "fields": {"ballot_submission": 2, "debate_adjudicator": 2, "debate_team": 22, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 16, "fields": {"ballot_submission": 2, "debate_adjudicator": 2, "debate_team": 22, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 17, "fields": {"ballot_submission": 3, "debate_adjudicator": 3, "debate_team": 19, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 18, "fields": {"ballot_submission": 3, "debate_adjudicator": 3, "debate_team": 19, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 19, "fields": {"ballot_submission": 3, "debate_adjudicator": 3, "debate_team": 19, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 20, "fields": {"ballot_submission": 3, "debate_adjudicator": 3, "debate_team": 19, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 21, "fields": {"ballot_submission": 3, "debate_adjudicator": 3, "debate_team": 20, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 22, "fields": {"ballot_submission": 3, "debate_adjudicator": 3, "debate_team": 20, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 23, "fields": {"ballot_submission": 3, "debate_adjudicator": 3, "debate_team": 20, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 24, "fields": {"ballot_submission": 3, "debate_adjudicator": 3, "debate_team": 20, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 25, "fields": {"ballot_submission": 4, "debate_adjudicator": 4, "debate_team": 17, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 26, "fields": {"ballot_submission": 4, "debate_adjudicator": 4, "debate_team": 17, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 27, "fields": {"ballot_submission": 4, "debate_adjudicator": 4, "debate_team": 17, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 28, "fields": {"ballot_submission": 4, "debate_adjudicator": 4, "debate_team": 17, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 29, "fields": {"ballot_submission": 4, "debate_adjudicator": 4, "debate_team": 18, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 30, "fields": {"ballot_submission": 4, "debate_adjudicator": 4, "debate_team": 18, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 31, "fields": {"ballot_submission": 4, "debate_adjudicator": 4, "debate_team": 18, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 32, "fields": {"ballot_submission": 4, "debate_adjudicator": 4, "debate_team": 18, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 33, "fields": {"ballot_submission": 5, "debate_adjudicator": 5, "debate_team": 15, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 34, "fields": {"ballot_submission": 5, "debate_adjudicator": 5, "debate_team": 15, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 35, "fields": {"ballot_submission": 5, "debate_adjudicator": 5, "debate_team": 15, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 36, "fields": {"ballot_submission": 5, "debate_adjudicator": 5, "debate_team": 15, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 37, "fields": {"ballot_submission": 5, "debate_adjudicator": 5, "debate_team": 16, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 38, "fields": {"ballot_submission": 5, "debate_adjudicator": 5, "debate_team": 16, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 39, "fields": {"ballot_submission": 5, "debate_adjudicator": 5, "debate_team": 16, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 40, "fields": {"ballot_submission": 5, "debate_adjudicator": 5, "debate_team": 16, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 41, "fields": {"ballot_submission": 6, "debate_adjudicator": 6, "debate_team": 13, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 42, "fields": {"ballot_submission": 6, "debate_adjudicator": 6, "debate_team": 13, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 43, "fields": {"ballot_submission": 6, "debate_adjudicator": 6, "debate_team": 13, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 44, "fields": {"ballot_submission": 6, "debate_adjudicator": 6, "debate_team": 13, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 45, "fields": {"ballot_submission": 6, "debate_adjudicator": 6, "debate_team": 14, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 46, "fields": {"ballot_submission": 6, "debate_adjudicator": 6, "debate_team": 14, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 47, "fields": {"ballot_submission": 6, "debate_adjudicator": 6, "debate_team": 14, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 48, "fields": {"ballot_submission": 6, "debate_adjudicator": 6, "debate_team": 14, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 49, "fields": {"ballot_submission": 7, "debate_adjudicator": 7, "debate_team": 11, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 50, "fields": {"ballot_submission": 7, "debate_adjudicator": 7, "debate_team": 11, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 51, "fields": {"ballot_submission": 7, "debate_adjudicator": 7, "debate_team": 11, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 52, "fields": {"ballot_submission": 7, "debate_adjudicator": 7, "debate_team": 11, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 53, "fields": {"ballot_submission": 7, "debate_adjudicator": 7, "debate_team": 12, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 54, "fields": {"ballot_submission": 7, "debate_adjudicator": 7, "debate_team": 12, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 55, "fields": {"ballot_submission": 7, "debate_adjudicator": 7, "debate_team": 12, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 56, "fields": {"ballot_submission": 7, "debate_adjudicator": 7, "debate_team": 12, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 57, "fields": {"ballot_submission": 8, "debate_adjudicator": 10, "debate_team": 9, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 58, "fields": {"ballot_submission": 8, "debate_adjudicator": 10, "debate_team": 9, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 59, "fields": {"ballot_submission": 8, "debate_adjudicator": 10, "debate_team": 9, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 60, "fields": {"ballot_submission": 8, "debate_adjudicator": 10, "debate_team": 9, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 61, "fields": {"ballot_submission": 8, "debate_adjudicator": 10, "debate_team": 10, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 62, "fields": {"ballot_submission": 8, "debate_adjudicator": 10, "debate_team": 10, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 63, "fields": {"ballot_submission": 8, "debate_adjudicator": 10, "debate_team": 10, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 64, "fields": {"ballot_submission": 8, "debate_adjudicator": 10, "debate_team": 10, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 65, "fields": {"ballot_submission": 8, "debate_adjudicator": 9, "debate_team": 9, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 66, "fields": {"ballot_submission": 8, "debate_adjudicator": 9, "debate_team": 9, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 67, "fields": {"ballot_submission": 8, "debate_adjudicator": 9, "debate_team": 9, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 68, "fields": {"ballot_submission": 8, "debate_adjudicator": 9, "debate_team": 9, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 69, "fields": {"ballot_submission": 8, "debate_adjudicator": 9, "debate_team": 10, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 70, "fields": {"ballot_submission": 8, "debate_adjudicator": 9, "debate_team": 10, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 71, "fields": {"ballot_submission": 8, "debate_adjudicator": 9, "debate_team": 10, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 72, "fields": {"ballot_submission": 8, "debate_adjudicator": 9, "debate_team": 10, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 73, "fields": {"ballot_submission": 8, "debate_adjudicator": 8, "debate_team": 9, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 74, "fields": {"ballot_submission": 8, "debate_adjudicator": 8, "debate_team": 9, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 75, "fields": {"ballot_submission": 8, "debate_adjudicator": 8, "debate_team": 9, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 76, "fields": {"ballot_submission": 8, "debate_adjudicator": 8, "debate_team": 9, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 77, "fields": {"ballot_submission": 8, "debate_adjudicator": 8, "debate_team": 10, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 78, "fields": {"ballot_submission": 8, "debate_adjudicator": 8, "debate_team": 10, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 79, "fields": {"ballot_submission": 8, "debate_adjudicator": 8, "debate_team": 10, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 80, "fields": {"ballot_submission": 8, "debate_adjudicator": 8, "debate_team": 10, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 81, "fields": {"ballot_submission": 9, "debate_adjudicator": 12, "debate_team": 7, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 82, "fields": {"ballot_submission": 9, "debate_adjudicator": 12, "debate_team": 7, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 83, "fields": {"ballot_submission": 9, "debate_adjudicator": 12, "debate_team": 7, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 84, "fields": {"ballot_submission": 9, "debate_adjudicator": 12, "debate_team": 7, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 85, "fields": {"ballot_submission": 9, "debate_adjudicator": 12, "debate_team": 8, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 86, "fields": {"ballot_submission": 9, "debate_adjudicator": 12, "debate_team": 8, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 87, "fields": {"ballot_submission": 9, "debate_adjudicator": 12, "debate_team": 8, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 88, "fields": {"ballot_submission": 9, "debate_adjudicator": 12, "debate_team": 8, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 89, "fields": {"ballot_submission": 9, "debate_adjudicator": 13, "debate_team": 7, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 90, "fields": {"ballot_submission": 9, "debate_adjudicator": 13, "debate_team": 7, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 91, "fields": {"ballot_submission": 9, "debate_adjudicator": 13, "debate_team": 7, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 92, "fields": {"ballot_submission": 9, "debate_adjudicator": 13, "debate_team": 7, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 93, "fields": {"ballot_submission": 9, "debate_adjudicator": 13, "debate_team": 8, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 94, "fields": {"ballot_submission": 9, "debate_adjudicator": 13, "debate_team": 8, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 95, "fields": {"ballot_submission": 9, "debate_adjudicator": 13, "debate_team": 8, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 96, "fields": {"ballot_submission": 9, "debate_adjudicator": 13, "debate_team": 8, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 97, "fields": {"ballot_submission": 9, "debate_adjudicator": 11, "debate_team": 7, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 98, "fields": {"ballot_submission": 9, "debate_adjudicator": 11, "debate_team": 7, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 99, "fields": {"ballot_submission": 9, "debate_adjudicator": 11, "debate_team": 7, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 100, "fields": {"ballot_submission": 9, "debate_adjudicator": 11, "debate_team": 7, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 101, "fields": {"ballot_submission": 9, "debate_adjudicator": 11, "debate_team": 8, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 102, "fields": {"ballot_submission": 9, "debate_adjudicator": 11, "debate_team": 8, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 103, "fields": {"ballot_submission": 9, "debate_adjudicator": 11, "debate_team": 8, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 104, "fields": {"ballot_submission": 9, "debate_adjudicator": 11, "debate_team": 8, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 105, "fields": {"ballot_submission": 10, "debate_adjudicator": 15, "debate_team": 5, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 106, "fields": {"ballot_submission": 10, "debate_adjudicator": 15, "debate_team": 5, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 107, "fields": {"ballot_submission": 10, "debate_adjudicator": 15, "debate_team": 5, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 108, "fields": {"ballot_submission": 10, "debate_adjudicator": 15, "debate_team": 5, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 109, "fields": {"ballot_submission": 10, "debate_adjudicator": 15, "debate_team": 6, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 110, "fields": {"ballot_submission": 10, "debate_adjudicator": 15, "debate_team": 6, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 111, "fields": {"ballot_submission": 10, "debate_adjudicator": 15, "debate_team": 6, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 112, "fields": {"ballot_submission": 10, "debate_adjudicator": 15, "debate_team": 6, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 113, "fields": {"ballot_submission": 10, "debate_adjudicator": 14, "debate_team": 5, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 114, "fields": {"ballot_submission": 10, "debate_adjudicator": 14, "debate_team": 5, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 115, "fields": {"ballot_submission": 10, "debate_adjudicator": 14, "debate_team": 5, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 116, "fields": {"ballot_submission": 10, "debate_adjudicator": 14, "debate_team": 5, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 117, "fields": {"ballot_submission": 10, "debate_adjudicator": 14, "debate_team": 6, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 118, "fields": {"ballot_submission": 10, "debate_adjudicator": 14, "debate_team": 6, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 119, "fields": {"ballot_submission": 10, "debate_adjudicator": 14, "debate_team": 6, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 120, "fields": {"ballot_submission": 10, "debate_adjudicator": 14, "debate_team": 6, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 121, "fields": {"ballot_submission": 10, "debate_adjudicator": 16, "debate_team": 5, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 122, "fields": {"ballot_submission": 10, "debate_adjudicator": 16, "debate_team": 5, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 123, "fields": {"ballot_submission": 10, "debate_adjudicator": 16, "debate_team": 5, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 124, "fields": {"ballot_submission": 10, "debate_adjudicator": 16, "debate_team": 5, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 125, "fields": {"ballot_submission": 10, "debate_adjudicator": 16, "debate_team": 6, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 126, "fields": {"ballot_submission": 10, "debate_adjudicator": 16, "debate_team": 6, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 127, "fields": {"ballot_submission": 10, "debate_adjudicator": 16, "debate_team": 6, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 128, "fields": {"ballot_submission": 10, "debate_adjudicator": 16, "debate_team": 6, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 129, "fields": {"ballot_submission": 11, "debate_adjudicator": 17, "debate_team": 3, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 130, "fields": {"ballot_submission": 11, "debate_adjudicator": 17, "debate_team": 3, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 131, "fields": {"ballot_submission": 11, "debate_adjudicator": 17, "debate_team": 3, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 132, "fields": {"ballot_submission": 11, "debate_adjudicator": 17, "debate_team": 3, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 133, "fields": {"ballot_submission": 11, "debate_adjudicator": 17, "debate_team": 4, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 134, "fields": {"ballot_submission": 11, "debate_adjudicator": 17, "debate_team": 4, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 135, "fields": {"ballot_submission": 11, "debate_adjudicator": 17, "debate_team": 4, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 136, "fields": {"ballot_submission": 11, "debate_adjudicator": 17, "debate_team": 4, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 137, "fields": {"ballot_submission": 11, "debate_adjudicator": 19, "debate_team": 3, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 138, "fields": {"ballot_submission": 11, "debate_adjudicator": 19, "debate_team": 3, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 139, "fields": {"ballot_submission": 11, "debate_adjudicator": 19, "debate_team": 3, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 140, "fields": {"ballot_submission": 11, "debate_adjudicator": 19, "debate_team": 3, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 141, "fields": {"ballot_submission": 11, "debate_adjudicator": 19, "debate_team": 4, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 142, "fields": {"ballot_submission": 11, "debate_adjudicator": 19, "debate_team": 4, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 143, "fields": {"ballot_submission": 11, "debate_adjudicator": 19, "debate_team": 4, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 144, "fields": {"ballot_submission": 11, "debate_adjudicator": 19, "debate_team": 4, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 145, "fields": {"ballot_submission": 11, "debate_adjudicator": 18, "debate_team": 3, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 146, "fields": {"ballot_submission": 11, "debate_adjudicator": 18, "debate_team": 3, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 147, "fields": {"ballot_submission": 11, "debate_adjudicator": 18, "debate_team": 3, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 148, "fields": {"ballot_submission": 11, "debate_adjudicator": 18, "debate_team": 3, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 149, "fields": {"ballot_submission": 11, "debate_adjudicator": 18, "debate_team": 4, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 150, "fields": {"ballot_submission": 11, "debate_adjudicator": 18, "debate_team": 4, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 151, "fields": {"ballot_submission": 11, "debate_adjudicator": 18, "debate_team": 4, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 152, "fields": {"ballot_submission": 11, "debate_adjudicator": 18, "debate_team": 4, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 153, "fields": {"ballot_submission": 12, "debate_adjudicator": 21, "debate_team": 1, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 154, "fields": {"ballot_submission": 12, "debate_adjudicator": 21, "debate_team": 1, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 155, "fields": {"ballot_submission": 12, "debate_adjudicator": 21, "debate_team": 1, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 156, "fields": {"ballot_submission": 12, "debate_adjudicator": 21, "debate_team": 1, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 157, "fields": {"ballot_submission": 12, "debate_adjudicator": 21, "debate_team": 2, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 158, "fields": {"ballot_submission": 12, "debate_adjudicator": 21, "debate_team": 2, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 159, "fields": {"ballot_submission": 12, "debate_adjudicator": 21, "debate_team": 2, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 160, "fields": {"ballot_submission": 12, "debate_adjudicator": 21, "debate_team": 2, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 161, "fields": {"ballot_submission": 12, "debate_adjudicator": 20, "debate_team": 1, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 162, "fields": {"ballot_submission": 12, "debate_adjudicator": 20, "debate_team": 1, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 163, "fields": {"ballot_submission": 12, "debate_adjudicator": 20, "debate_team": 1, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 164, "fields": {"ballot_submission": 12, "debate_adjudicator": 20, "debate_team": 1, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 165, "fields": {"ballot_submission": 12, "debate_adjudicator": 20, "debate_team": 2, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 166, "fields": {"ballot_submission": 12, "debate_adjudicator": 20, "debate_team": 2, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 167, "fields": {"ballot_submission": 12, "debate_adjudicator": 20, "debate_team": 2, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 168, "fields": {"ballot_submission": 12, "debate_adjudicator": 20, "debate_team": 2, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 169, "fields": {"ballot_submission": 12, "debate_adjudicator": 22, "debate_team": 1, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 170, "fields": {"ballot_submission": 12, "debate_adjudicator": 22, "debate_team": 1, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 171, "fields": {"ballot_submission": 12, "debate_adjudicator": 22, "debate_team": 1, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 172, "fields": {"ballot_submission": 12, "debate_adjudicator": 22, "debate_team": 1, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 173, "fields": {"ballot_submission": 12, "debate_adjudicator": 22, "debate_team": 2, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 174, "fields": {"ballot_submission": 12, "debate_adjudicator": 22, "debate_team": 2, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 175, "fields": {"ballot_submission": 12, "debate_adjudicator": 22, "debate_team": 2, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 176, "fields": {"ballot_submission": 12, "debate_adjudicator": 22, "debate_team": 2, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 177, "fields": {"ballot_submission": 13, "debate_adjudicator": 33, "debate_team": 47, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 178, "fields": {"ballot_submission": 13, "debate_adjudicator": 33, "debate_team": 47, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 179, "fields": {"ballot_submission": 13, "debate_adjudicator": 33, "debate_team": 47, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 180, "fields": {"ballot_submission": 13, "debate_adjudicator": 33, "debate_team": 47, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 181, "fields": {"ballot_submission": 13, "debate_adjudicator": 33, "debate_team": 48, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 182, "fields": {"ballot_submission": 13, "debate_adjudicator": 33, "debate_team": 48, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 183, "fields": {"ballot_submission": 13, "debate_adjudicator": 33, "debate_team": 48, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 184, "fields": {"ballot_submission": 13, "debate_adjudicator": 33, "debate_team": 48, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 185, "fields": {"ballot_submission": 13, "debate_adjudicator": 34, "debate_team": 47, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 186, "fields": {"ballot_submission": 13, "debate_adjudicator": 34, "debate_team": 47, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 187, "fields": {"ballot_submission": 13, "debate_adjudicator": 34, "debate_team": 47, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 188, "fields": {"ballot_submission": 13, "debate_adjudicator": 34, "debate_team": 47, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 189, "fields": {"ballot_submission": 13, "debate_adjudicator": 34, "debate_team": 48, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 190, "fields": {"ballot_submission": 13, "debate_adjudicator": 34, "debate_team": 48, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 191, "fields": {"ballot_submission": 13, "debate_adjudicator": 34, "debate_team": 48, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 192, "fields": {"ballot_submission": 13, "debate_adjudicator": 34, "debate_team": 48, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 193, "fields": {"ballot_submission": 13, "debate_adjudicator": 35, "debate_team": 47, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 194, "fields": {"ballot_submission": 13, "debate_adjudicator": 35, "debate_team": 47, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 195, "fields": {"ballot_submission": 13, "debate_adjudicator": 35, "debate_team": 47, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 196, "fields": {"ballot_submission": 13, "debate_adjudicator": 35, "debate_team": 47, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 197, "fields": {"ballot_submission": 13, "debate_adjudicator": 35, "debate_team": 48, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 198, "fields": {"ballot_submission": 13, "debate_adjudicator": 35, "debate_team": 48, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 199, "fields": {"ballot_submission": 13, "debate_adjudicator": 35, "debate_team": 48, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 200, "fields": {"ballot_submission": 13, "debate_adjudicator": 35, "debate_team": 48, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 201, "fields": {"ballot_submission": 14, "debate_adjudicator": 24, "debate_team": 45, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 202, "fields": {"ballot_submission": 14, "debate_adjudicator": 24, "debate_team": 45, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 203, "fields": {"ballot_submission": 14, "debate_adjudicator": 24, "debate_team": 45, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 204, "fields": {"ballot_submission": 14, "debate_adjudicator": 24, "debate_team": 45, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 205, "fields": {"ballot_submission": 14, "debate_adjudicator": 24, "debate_team": 46, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 206, "fields": {"ballot_submission": 14, "debate_adjudicator": 24, "debate_team": 46, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 207, "fields": {"ballot_submission": 14, "debate_adjudicator": 24, "debate_team": 46, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 208, "fields": {"ballot_submission": 14, "debate_adjudicator": 24, "debate_team": 46, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 209, "fields": {"ballot_submission": 15, "debate_adjudicator": 38, "debate_team": 43, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 210, "fields": {"ballot_submission": 15, "debate_adjudicator": 38, "debate_team": 43, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 211, "fields": {"ballot_submission": 15, "debate_adjudicator": 38, "debate_team": 43, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 212, "fields": {"ballot_submission": 15, "debate_adjudicator": 38, "debate_team": 43, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 213, "fields": {"ballot_submission": 15, "debate_adjudicator": 38, "debate_team": 44, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 214, "fields": {"ballot_submission": 15, "debate_adjudicator": 38, "debate_team": 44, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 215, "fields": {"ballot_submission": 15, "debate_adjudicator": 38, "debate_team": 44, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 216, "fields": {"ballot_submission": 15, "debate_adjudicator": 38, "debate_team": 44, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 217, "fields": {"ballot_submission": 15, "debate_adjudicator": 36, "debate_team": 43, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 218, "fields": {"ballot_submission": 15, "debate_adjudicator": 36, "debate_team": 43, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 219, "fields": {"ballot_submission": 15, "debate_adjudicator": 36, "debate_team": 43, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 220, "fields": {"ballot_submission": 15, "debate_adjudicator": 36, "debate_team": 43, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 221, "fields": {"ballot_submission": 15, "debate_adjudicator": 36, "debate_team": 44, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 222, "fields": {"ballot_submission": 15, "debate_adjudicator": 36, "debate_team": 44, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 223, "fields": {"ballot_submission": 15, "debate_adjudicator": 36, "debate_team": 44, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 224, "fields": {"ballot_submission": 15, "debate_adjudicator": 36, "debate_team": 44, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 225, "fields": {"ballot_submission": 15, "debate_adjudicator": 37, "debate_team": 43, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 226, "fields": {"ballot_submission": 15, "debate_adjudicator": 37, "debate_team": 43, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 227, "fields": {"ballot_submission": 15, "debate_adjudicator": 37, "debate_team": 43, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 228, "fields": {"ballot_submission": 15, "debate_adjudicator": 37, "debate_team": 43, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 229, "fields": {"ballot_submission": 15, "debate_adjudicator": 37, "debate_team": 44, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 230, "fields": {"ballot_submission": 15, "debate_adjudicator": 37, "debate_team": 44, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 231, "fields": {"ballot_submission": 15, "debate_adjudicator": 37, "debate_team": 44, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 232, "fields": {"ballot_submission": 15, "debate_adjudicator": 37, "debate_team": 44, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 233, "fields": {"ballot_submission": 16, "debate_adjudicator": 39, "debate_team": 41, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 234, "fields": {"ballot_submission": 16, "debate_adjudicator": 39, "debate_team": 41, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 235, "fields": {"ballot_submission": 16, "debate_adjudicator": 39, "debate_team": 41, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 236, "fields": {"ballot_submission": 16, "debate_adjudicator": 39, "debate_team": 41, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 237, "fields": {"ballot_submission": 16, "debate_adjudicator": 39, "debate_team": 42, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 238, "fields": {"ballot_submission": 16, "debate_adjudicator": 39, "debate_team": 42, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 239, "fields": {"ballot_submission": 16, "debate_adjudicator": 39, "debate_team": 42, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 240, "fields": {"ballot_submission": 16, "debate_adjudicator": 39, "debate_team": 42, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 241, "fields": {"ballot_submission": 16, "debate_adjudicator": 41, "debate_team": 41, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 242, "fields": {"ballot_submission": 16, "debate_adjudicator": 41, "debate_team": 41, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 243, "fields": {"ballot_submission": 16, "debate_adjudicator": 41, "debate_team": 41, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 244, "fields": {"ballot_submission": 16, "debate_adjudicator": 41, "debate_team": 41, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 245, "fields": {"ballot_submission": 16, "debate_adjudicator": 41, "debate_team": 42, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 246, "fields": {"ballot_submission": 16, "debate_adjudicator": 41, "debate_team": 42, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 247, "fields": {"ballot_submission": 16, "debate_adjudicator": 41, "debate_team": 42, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 248, "fields": {"ballot_submission": 16, "debate_adjudicator": 41, "debate_team": 42, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 249, "fields": {"ballot_submission": 16, "debate_adjudicator": 40, "debate_team": 41, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 250, "fields": {"ballot_submission": 16, "debate_adjudicator": 40, "debate_team": 41, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 251, "fields": {"ballot_submission": 16, "debate_adjudicator": 40, "debate_team": 41, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 252, "fields": {"ballot_submission": 16, "debate_adjudicator": 40, "debate_team": 41, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 253, "fields": {"ballot_submission": 16, "debate_adjudicator": 40, "debate_team": 42, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 254, "fields": {"ballot_submission": 16, "debate_adjudicator": 40, "debate_team": 42, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 255, "fields": {"ballot_submission": 16, "debate_adjudicator": 40, "debate_team": 42, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 256, "fields": {"ballot_submission": 16, "debate_adjudicator": 40, "debate_team": 42, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 257, "fields": {"ballot_submission": 17, "debate_adjudicator": 30, "debate_team": 39, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 258, "fields": {"ballot_submission": 17, "debate_adjudicator": 30, "debate_team": 39, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 259, "fields": {"ballot_submission": 17, "debate_adjudicator": 30, "debate_team": 39, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 260, "fields": {"ballot_submission": 17, "debate_adjudicator": 30, "debate_team": 39, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 261, "fields": {"ballot_submission": 17, "debate_adjudicator": 30, "debate_team": 40, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 262, "fields": {"ballot_submission": 17, "debate_adjudicator": 30, "debate_team": 40, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 263, "fields": {"ballot_submission": 17, "debate_adjudicator": 30, "debate_team": 40, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 264, "fields": {"ballot_submission": 17, "debate_adjudicator": 30, "debate_team": 40, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 265, "fields": {"ballot_submission": 17, "debate_adjudicator": 31, "debate_team": 39, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 266, "fields": {"ballot_submission": 17, "debate_adjudicator": 31, "debate_team": 39, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 267, "fields": {"ballot_submission": 17, "debate_adjudicator": 31, "debate_team": 39, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 268, "fields": {"ballot_submission": 17, "debate_adjudicator": 31, "debate_team": 39, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 269, "fields": {"ballot_submission": 17, "debate_adjudicator": 31, "debate_team": 40, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 270, "fields": {"ballot_submission": 17, "debate_adjudicator": 31, "debate_team": 40, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 271, "fields": {"ballot_submission": 17, "debate_adjudicator": 31, "debate_team": 40, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 272, "fields": {"ballot_submission": 17, "debate_adjudicator": 31, "debate_team": 40, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 273, "fields": {"ballot_submission": 17, "debate_adjudicator": 32, "debate_team": 39, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 274, "fields": {"ballot_submission": 17, "debate_adjudicator": 32, "debate_team": 39, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 275, "fields": {"ballot_submission": 17, "debate_adjudicator": 32, "debate_team": 39, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 276, "fields": {"ballot_submission": 17, "debate_adjudicator": 32, "debate_team": 39, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 277, "fields": {"ballot_submission": 17, "debate_adjudicator": 32, "debate_team": 40, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 278, "fields": {"ballot_submission": 17, "debate_adjudicator": 32, "debate_team": 40, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 279, "fields": {"ballot_submission": 17, "debate_adjudicator": 32, "debate_team": 40, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 280, "fields": {"ballot_submission": 17, "debate_adjudicator": 32, "debate_team": 40, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 281, "fields": {"ballot_submission": 18, "debate_adjudicator": 23, "debate_team": 37, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 282, "fields": {"ballot_submission": 18, "debate_adjudicator": 23, "debate_team": 37, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 283, "fields": {"ballot_submission": 18, "debate_adjudicator": 23, "debate_team": 37, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 284, "fields": {"ballot_submission": 18, "debate_adjudicator": 23, "debate_team": 37, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 285, "fields": {"ballot_submission": 18, "debate_adjudicator": 23, "debate_team": 38, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 286, "fields": {"ballot_submission": 18, "debate_adjudicator": 23, "debate_team": 38, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 287, "fields": {"ballot_submission": 18, "debate_adjudicator": 23, "debate_team": 38, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 288, "fields": {"ballot_submission": 18, "debate_adjudicator": 23, "debate_team": 38, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 289, "fields": {"ballot_submission": 19, "debate_adjudicator": 27, "debate_team": 35, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 290, "fields": {"ballot_submission": 19, "debate_adjudicator": 27, "debate_team": 35, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 291, "fields": {"ballot_submission": 19, "debate_adjudicator": 27, "debate_team": 35, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 292, "fields": {"ballot_submission": 19, "debate_adjudicator": 27, "debate_team": 35, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 293, "fields": {"ballot_submission": 19, "debate_adjudicator": 27, "debate_team": 36, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 294, "fields": {"ballot_submission": 19, "debate_adjudicator": 27, "debate_team": 36, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 295, "fields": {"ballot_submission": 19, "debate_adjudicator": 27, "debate_team": 36, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 296, "fields": {"ballot_submission": 19, "debate_adjudicator": 27, "debate_team": 36, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 297, "fields": {"ballot_submission": 20, "debate_adjudicator": 26, "debate_team": 33, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 298, "fields": {"ballot_submission": 20, "debate_adjudicator": 26, "debate_team": 33, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 299, "fields": {"ballot_submission": 20, "debate_adjudicator": 26, "debate_team": 33, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 300, "fields": {"ballot_submission": 20, "debate_adjudicator": 26, "debate_team": 33, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 301, "fields": {"ballot_submission": 20, "debate_adjudicator": 26, "debate_team": 34, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 302, "fields": {"ballot_submission": 20, "debate_adjudicator": 26, "debate_team": 34, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 303, "fields": {"ballot_submission": 20, "debate_adjudicator": 26, "debate_team": 34, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 304, "fields": {"ballot_submission": 20, "debate_adjudicator": 26, "debate_team": 34, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 305, "fields": {"ballot_submission": 21, "debate_adjudicator": 29, "debate_team": 31, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 306, "fields": {"ballot_submission": 21, "debate_adjudicator": 29, "debate_team": 31, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 307, "fields": {"ballot_submission": 21, "debate_adjudicator": 29, "debate_team": 31, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 308, "fields": {"ballot_submission": 21, "debate_adjudicator": 29, "debate_team": 31, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 309, "fields": {"ballot_submission": 21, "debate_adjudicator": 29, "debate_team": 32, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 310, "fields": {"ballot_submission": 21, "debate_adjudicator": 29, "debate_team": 32, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 311, "fields": {"ballot_submission": 21, "debate_adjudicator": 29, "debate_team": 32, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 312, "fields": {"ballot_submission": 21, "debate_adjudicator": 29, "debate_team": 32, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 313, "fields": {"ballot_submission": 22, "debate_adjudicator": 28, "debate_team": 29, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 314, "fields": {"ballot_submission": 22, "debate_adjudicator": 28, "debate_team": 29, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 315, "fields": {"ballot_submission": 22, "debate_adjudicator": 28, "debate_team": 29, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 316, "fields": {"ballot_submission": 22, "debate_adjudicator": 28, "debate_team": 29, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 317, "fields": {"ballot_submission": 22, "debate_adjudicator": 28, "debate_team": 30, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 318, "fields": {"ballot_submission": 22, "debate_adjudicator": 28, "debate_team": 30, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 319, "fields": {"ballot_submission": 22, "debate_adjudicator": 28, "debate_team": 30, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 320, "fields": {"ballot_submission": 22, "debate_adjudicator": 28, "debate_team": 30, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 321, "fields": {"ballot_submission": 23, "debate_adjudicator": 42, "debate_team": 27, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 322, "fields": {"ballot_submission": 23, "debate_adjudicator": 42, "debate_team": 27, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 323, "fields": {"ballot_submission": 23, "debate_adjudicator": 42, "debate_team": 27, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 324, "fields": {"ballot_submission": 23, "debate_adjudicator": 42, "debate_team": 27, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 325, "fields": {"ballot_submission": 23, "debate_adjudicator": 42, "debate_team": 28, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 326, "fields": {"ballot_submission": 23, "debate_adjudicator": 42, "debate_team": 28, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 327, "fields": {"ballot_submission": 23, "debate_adjudicator": 42, "debate_team": 28, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 328, "fields": {"ballot_submission": 23, "debate_adjudicator": 42, "debate_team": 28, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 329, "fields": {"ballot_submission": 23, "debate_adjudicator": 43, "debate_team": 27, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 330, "fields": {"ballot_submission": 23, "debate_adjudicator": 43, "debate_team": 27, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 331, "fields": {"ballot_submission": 23, "debate_adjudicator": 43, "debate_team": 27, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 332, "fields": {"ballot_submission": 23, "debate_adjudicator": 43, "debate_team": 27, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 333, "fields": {"ballot_submission": 23, "debate_adjudicator": 43, "debate_team": 28, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 334, "fields": {"ballot_submission": 23, "debate_adjudicator": 43, "debate_team": 28, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 335, "fields": {"ballot_submission": 23, "debate_adjudicator": 43, "debate_team": 28, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 336, "fields": {"ballot_submission": 23, "debate_adjudicator": 43, "debate_team": 28, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 337, "fields": {"ballot_submission": 23, "debate_adjudicator": 44, "debate_team": 27, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 338, "fields": {"ballot_submission": 23, "debate_adjudicator": 44, "debate_team": 27, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 339, "fields": {"ballot_submission": 23, "debate_adjudicator": 44, "debate_team": 27, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 340, "fields": {"ballot_submission": 23, "debate_adjudicator": 44, "debate_team": 27, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 341, "fields": {"ballot_submission": 23, "debate_adjudicator": 44, "debate_team": 28, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 342, "fields": {"ballot_submission": 23, "debate_adjudicator": 44, "debate_team": 28, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 343, "fields": {"ballot_submission": 23, "debate_adjudicator": 44, "debate_team": 28, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 344, "fields": {"ballot_submission": 23, "debate_adjudicator": 44, "debate_team": 28, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 345, "fields": {"ballot_submission": 24, "debate_adjudicator": 25, "debate_team": 25, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 346, "fields": {"ballot_submission": 24, "debate_adjudicator": 25, "debate_team": 25, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 347, "fields": {"ballot_submission": 24, "debate_adjudicator": 25, "debate_team": 25, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 348, "fields": {"ballot_submission": 24, "debate_adjudicator": 25, "debate_team": 25, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 349, "fields": {"ballot_submission": 24, "debate_adjudicator": 25, "debate_team": 26, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 350, "fields": {"ballot_submission": 24, "debate_adjudicator": 25, "debate_team": 26, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 351, "fields": {"ballot_submission": 24, "debate_adjudicator": 25, "debate_team": 26, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 352, "fields": {"ballot_submission": 24, "debate_adjudicator": 25, "debate_team": 26, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 353, "fields": {"ballot_submission": 25, "debate_adjudicator": 48, "debate_team": 49, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 354, "fields": {"ballot_submission": 25, "debate_adjudicator": 48, "debate_team": 49, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 355, "fields": {"ballot_submission": 25, "debate_adjudicator": 48, "debate_team": 49, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 356, "fields": {"ballot_submission": 25, "debate_adjudicator": 48, "debate_team": 49, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 357, "fields": {"ballot_submission": 25, "debate_adjudicator": 48, "debate_team": 50, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 358, "fields": {"ballot_submission": 25, "debate_adjudicator": 48, "debate_team": 50, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 359, "fields": {"ballot_submission": 25, "debate_adjudicator": 48, "debate_team": 50, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 360, "fields": {"ballot_submission": 25, "debate_adjudicator": 48, "debate_team": 50, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 361, "fields": {"ballot_submission": 26, "debate_adjudicator": 47, "debate_team": 51, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 362, "fields": {"ballot_submission": 26, "debate_adjudicator": 47, "debate_team": 51, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 363, "fields": {"ballot_submission": 26, "debate_adjudicator": 47, "debate_team": 51, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 364, "fields": {"ballot_submission": 26, "debate_adjudicator": 47, "debate_team": 51, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 365, "fields": {"ballot_submission": 26, "debate_adjudicator": 47, "debate_team": 52, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 366, "fields": {"ballot_submission": 26, "debate_adjudicator": 47, "debate_team": 52, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 367, "fields": {"ballot_submission": 26, "debate_adjudicator": 47, "debate_team": 52, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 368, "fields": {"ballot_submission": 26, "debate_adjudicator": 47, "debate_team": 52, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 369, "fields": {"ballot_submission": 27, "debate_adjudicator": 52, "debate_team": 53, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 370, "fields": {"ballot_submission": 27, "debate_adjudicator": 52, "debate_team": 53, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 371, "fields": {"ballot_submission": 27, "debate_adjudicator": 52, "debate_team": 53, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 372, "fields": {"ballot_submission": 27, "debate_adjudicator": 52, "debate_team": 53, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 373, "fields": {"ballot_submission": 27, "debate_adjudicator": 52, "debate_team": 54, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 374, "fields": {"ballot_submission": 27, "debate_adjudicator": 52, "debate_team": 54, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 375, "fields": {"ballot_submission": 27, "debate_adjudicator": 52, "debate_team": 54, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 376, "fields": {"ballot_submission": 27, "debate_adjudicator": 52, "debate_team": 54, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 377, "fields": {"ballot_submission": 27, "debate_adjudicator": 53, "debate_team": 53, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 378, "fields": {"ballot_submission": 27, "debate_adjudicator": 53, "debate_team": 53, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 379, "fields": {"ballot_submission": 27, "debate_adjudicator": 53, "debate_team": 53, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 380, "fields": {"ballot_submission": 27, "debate_adjudicator": 53, "debate_team": 53, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 381, "fields": {"ballot_submission": 27, "debate_adjudicator": 53, "debate_team": 54, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 382, "fields": {"ballot_submission": 27, "debate_adjudicator": 53, "debate_team": 54, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 383, "fields": {"ballot_submission": 27, "debate_adjudicator": 53, "debate_team": 54, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 384, "fields": {"ballot_submission": 27, "debate_adjudicator": 53, "debate_team": 54, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 385, "fields": {"ballot_submission": 27, "debate_adjudicator": 54, "debate_team": 53, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 386, "fields": {"ballot_submission": 27, "debate_adjudicator": 54, "debate_team": 53, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 387, "fields": {"ballot_submission": 27, "debate_adjudicator": 54, "debate_team": 53, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 388, "fields": {"ballot_submission": 27, "debate_adjudicator": 54, "debate_team": 53, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 389, "fields": {"ballot_submission": 27, "debate_adjudicator": 54, "debate_team": 54, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 390, "fields": {"ballot_submission": 27, "debate_adjudicator": 54, "debate_team": 54, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 391, "fields": {"ballot_submission": 27, "debate_adjudicator": 54, "debate_team": 54, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 392, "fields": {"ballot_submission": 27, "debate_adjudicator": 54, "debate_team": 54, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 393, "fields": {"ballot_submission": 28, "debate_adjudicator": 55, "debate_team": 55, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 394, "fields": {"ballot_submission": 28, "debate_adjudicator": 55, "debate_team": 55, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 395, "fields": {"ballot_submission": 28, "debate_adjudicator": 55, "debate_team": 55, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 396, "fields": {"ballot_submission": 28, "debate_adjudicator": 55, "debate_team": 55, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 397, "fields": {"ballot_submission": 28, "debate_adjudicator": 55, "debate_team": 56, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 398, "fields": {"ballot_submission": 28, "debate_adjudicator": 55, "debate_team": 56, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 399, "fields": {"ballot_submission": 28, "debate_adjudicator": 55, "debate_team": 56, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 400, "fields": {"ballot_submission": 28, "debate_adjudicator": 55, "debate_team": 56, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 401, "fields": {"ballot_submission": 28, "debate_adjudicator": 57, "debate_team": 55, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 402, "fields": {"ballot_submission": 28, "debate_adjudicator": 57, "debate_team": 55, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 403, "fields": {"ballot_submission": 28, "debate_adjudicator": 57, "debate_team": 55, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 404, "fields": {"ballot_submission": 28, "debate_adjudicator": 57, "debate_team": 55, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 405, "fields": {"ballot_submission": 28, "debate_adjudicator": 57, "debate_team": 56, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 406, "fields": {"ballot_submission": 28, "debate_adjudicator": 57, "debate_team": 56, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 407, "fields": {"ballot_submission": 28, "debate_adjudicator": 57, "debate_team": 56, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 408, "fields": {"ballot_submission": 28, "debate_adjudicator": 57, "debate_team": 56, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 409, "fields": {"ballot_submission": 28, "debate_adjudicator": 56, "debate_team": 55, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 410, "fields": {"ballot_submission": 28, "debate_adjudicator": 56, "debate_team": 55, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 411, "fields": {"ballot_submission": 28, "debate_adjudicator": 56, "debate_team": 55, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 412, "fields": {"ballot_submission": 28, "debate_adjudicator": 56, "debate_team": 55, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 413, "fields": {"ballot_submission": 28, "debate_adjudicator": 56, "debate_team": 56, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 414, "fields": {"ballot_submission": 28, "debate_adjudicator": 56, "debate_team": 56, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 415, "fields": {"ballot_submission": 28, "debate_adjudicator": 56, "debate_team": 56, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 416, "fields": {"ballot_submission": 28, "debate_adjudicator": 56, "debate_team": 56, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 417, "fields": {"ballot_submission": 29, "debate_adjudicator": 64, "debate_team": 57, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 418, "fields": {"ballot_submission": 29, "debate_adjudicator": 64, "debate_team": 57, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 419, "fields": {"ballot_submission": 29, "debate_adjudicator": 64, "debate_team": 57, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 420, "fields": {"ballot_submission": 29, "debate_adjudicator": 64, "debate_team": 57, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 421, "fields": {"ballot_submission": 29, "debate_adjudicator": 64, "debate_team": 58, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 422, "fields": {"ballot_submission": 29, "debate_adjudicator": 64, "debate_team": 58, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 423, "fields": {"ballot_submission": 29, "debate_adjudicator": 64, "debate_team": 58, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 424, "fields": {"ballot_submission": 29, "debate_adjudicator": 64, "debate_team": 58, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 425, "fields": {"ballot_submission": 29, "debate_adjudicator": 66, "debate_team": 57, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 426, "fields": {"ballot_submission": 29, "debate_adjudicator": 66, "debate_team": 57, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 427, "fields": {"ballot_submission": 29, "debate_adjudicator": 66, "debate_team": 57, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 428, "fields": {"ballot_submission": 29, "debate_adjudicator": 66, "debate_team": 57, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 429, "fields": {"ballot_submission": 29, "debate_adjudicator": 66, "debate_team": 58, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 430, "fields": {"ballot_submission": 29, "debate_adjudicator": 66, "debate_team": 58, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 431, "fields": {"ballot_submission": 29, "debate_adjudicator": 66, "debate_team": 58, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 432, "fields": {"ballot_submission": 29, "debate_adjudicator": 66, "debate_team": 58, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 433, "fields": {"ballot_submission": 29, "debate_adjudicator": 65, "debate_team": 57, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 434, "fields": {"ballot_submission": 29, "debate_adjudicator": 65, "debate_team": 57, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 435, "fields": {"ballot_submission": 29, "debate_adjudicator": 65, "debate_team": 57, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 436, "fields": {"ballot_submission": 29, "debate_adjudicator": 65, "debate_team": 57, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 437, "fields": {"ballot_submission": 29, "debate_adjudicator": 65, "debate_team": 58, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 438, "fields": {"ballot_submission": 29, "debate_adjudicator": 65, "debate_team": 58, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 439, "fields": {"ballot_submission": 29, "debate_adjudicator": 65, "debate_team": 58, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 440, "fields": {"ballot_submission": 29, "debate_adjudicator": 65, "debate_team": 58, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 441, "fields": {"ballot_submission": 30, "debate_adjudicator": 50, "debate_team": 59, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 442, "fields": {"ballot_submission": 30, "debate_adjudicator": 50, "debate_team": 59, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 443, "fields": {"ballot_submission": 30, "debate_adjudicator": 50, "debate_team": 59, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 444, "fields": {"ballot_submission": 30, "debate_adjudicator": 50, "debate_team": 59, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 445, "fields": {"ballot_submission": 30, "debate_adjudicator": 50, "debate_team": 60, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 446, "fields": {"ballot_submission": 30, "debate_adjudicator": 50, "debate_team": 60, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 447, "fields": {"ballot_submission": 30, "debate_adjudicator": 50, "debate_team": 60, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 448, "fields": {"ballot_submission": 30, "debate_adjudicator": 50, "debate_team": 60, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 449, "fields": {"ballot_submission": 31, "debate_adjudicator": 45, "debate_team": 61, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 450, "fields": {"ballot_submission": 31, "debate_adjudicator": 45, "debate_team": 61, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 451, "fields": {"ballot_submission": 31, "debate_adjudicator": 45, "debate_team": 61, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 452, "fields": {"ballot_submission": 31, "debate_adjudicator": 45, "debate_team": 61, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 453, "fields": {"ballot_submission": 31, "debate_adjudicator": 45, "debate_team": 62, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 454, "fields": {"ballot_submission": 31, "debate_adjudicator": 45, "debate_team": 62, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 455, "fields": {"ballot_submission": 31, "debate_adjudicator": 45, "debate_team": 62, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 456, "fields": {"ballot_submission": 31, "debate_adjudicator": 45, "debate_team": 62, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 457, "fields": {"ballot_submission": 32, "debate_adjudicator": 49, "debate_team": 63, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 458, "fields": {"ballot_submission": 32, "debate_adjudicator": 49, "debate_team": 63, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 459, "fields": {"ballot_submission": 32, "debate_adjudicator": 49, "debate_team": 63, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 460, "fields": {"ballot_submission": 32, "debate_adjudicator": 49, "debate_team": 63, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 461, "fields": {"ballot_submission": 32, "debate_adjudicator": 49, "debate_team": 64, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 462, "fields": {"ballot_submission": 32, "debate_adjudicator": 49, "debate_team": 64, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 463, "fields": {"ballot_submission": 32, "debate_adjudicator": 49, "debate_team": 64, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 464, "fields": {"ballot_submission": 32, "debate_adjudicator": 49, "debate_team": 64, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 465, "fields": {"ballot_submission": 33, "debate_adjudicator": 46, "debate_team": 65, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 466, "fields": {"ballot_submission": 33, "debate_adjudicator": 46, "debate_team": 65, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 467, "fields": {"ballot_submission": 33, "debate_adjudicator": 46, "debate_team": 65, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 468, "fields": {"ballot_submission": 33, "debate_adjudicator": 46, "debate_team": 65, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 469, "fields": {"ballot_submission": 33, "debate_adjudicator": 46, "debate_team": 66, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 470, "fields": {"ballot_submission": 33, "debate_adjudicator": 46, "debate_team": 66, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 471, "fields": {"ballot_submission": 33, "debate_adjudicator": 46, "debate_team": 66, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 472, "fields": {"ballot_submission": 33, "debate_adjudicator": 46, "debate_team": 66, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 473, "fields": {"ballot_submission": 34, "debate_adjudicator": 63, "debate_team": 67, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 474, "fields": {"ballot_submission": 34, "debate_adjudicator": 63, "debate_team": 67, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 475, "fields": {"ballot_submission": 34, "debate_adjudicator": 63, "debate_team": 67, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 476, "fields": {"ballot_submission": 34, "debate_adjudicator": 63, "debate_team": 67, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 477, "fields": {"ballot_submission": 34, "debate_adjudicator": 63, "debate_team": 68, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 478, "fields": {"ballot_submission": 34, "debate_adjudicator": 63, "debate_team": 68, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 479, "fields": {"ballot_submission": 34, "debate_adjudicator": 63, "debate_team": 68, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 480, "fields": {"ballot_submission": 34, "debate_adjudicator": 63, "debate_team": 68, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 481, "fields": {"ballot_submission": 34, "debate_adjudicator": 62, "debate_team": 67, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 482, "fields": {"ballot_submission": 34, "debate_adjudicator": 62, "debate_team": 67, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 483, "fields": {"ballot_submission": 34, "debate_adjudicator": 62, "debate_team": 67, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 484, "fields": {"ballot_submission": 34, "debate_adjudicator": 62, "debate_team": 67, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 485, "fields": {"ballot_submission": 34, "debate_adjudicator": 62, "debate_team": 68, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 486, "fields": {"ballot_submission": 34, "debate_adjudicator": 62, "debate_team": 68, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 487, "fields": {"ballot_submission": 34, "debate_adjudicator": 62, "debate_team": 68, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 488, "fields": {"ballot_submission": 34, "debate_adjudicator": 62, "debate_team": 68, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 489, "fields": {"ballot_submission": 34, "debate_adjudicator": 61, "debate_team": 67, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 490, "fields": {"ballot_submission": 34, "debate_adjudicator": 61, "debate_team": 67, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 491, "fields": {"ballot_submission": 34, "debate_adjudicator": 61, "debate_team": 67, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 492, "fields": {"ballot_submission": 34, "debate_adjudicator": 61, "debate_team": 67, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 493, "fields": {"ballot_submission": 34, "debate_adjudicator": 61, "debate_team": 68, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 494, "fields": {"ballot_submission": 34, "debate_adjudicator": 61, "debate_team": 68, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 495, "fields": {"ballot_submission": 34, "debate_adjudicator": 61, "debate_team": 68, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 496, "fields": {"ballot_submission": 34, "debate_adjudicator": 61, "debate_team": 68, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 497, "fields": {"ballot_submission": 35, "debate_adjudicator": 60, "debate_team": 69, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 498, "fields": {"ballot_submission": 35, "debate_adjudicator": 60, "debate_team": 69, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 499, "fields": {"ballot_submission": 35, "debate_adjudicator": 60, "debate_team": 69, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 500, "fields": {"ballot_submission": 35, "debate_adjudicator": 60, "debate_team": 69, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 501, "fields": {"ballot_submission": 35, "debate_adjudicator": 60, "debate_team": 70, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 502, "fields": {"ballot_submission": 35, "debate_adjudicator": 60, "debate_team": 70, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 503, "fields": {"ballot_submission": 35, "debate_adjudicator": 60, "debate_team": 70, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 504, "fields": {"ballot_submission": 35, "debate_adjudicator": 60, "debate_team": 70, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 505, "fields": {"ballot_submission": 35, "debate_adjudicator": 58, "debate_team": 69, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 506, "fields": {"ballot_submission": 35, "debate_adjudicator": 58, "debate_team": 69, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 507, "fields": {"ballot_submission": 35, "debate_adjudicator": 58, "debate_team": 69, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 508, "fields": {"ballot_submission": 35, "debate_adjudicator": 58, "debate_team": 69, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 509, "fields": {"ballot_submission": 35, "debate_adjudicator": 58, "debate_team": 70, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 510, "fields": {"ballot_submission": 35, "debate_adjudicator": 58, "debate_team": 70, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 511, "fields": {"ballot_submission": 35, "debate_adjudicator": 58, "debate_team": 70, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 512, "fields": {"ballot_submission": 35, "debate_adjudicator": 58, "debate_team": 70, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 513, "fields": {"ballot_submission": 35, "debate_adjudicator": 59, "debate_team": 69, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 514, "fields": {"ballot_submission": 35, "debate_adjudicator": 59, "debate_team": 69, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 515, "fields": {"ballot_submission": 35, "debate_adjudicator": 59, "debate_team": 69, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 516, "fields": {"ballot_submission": 35, "debate_adjudicator": 59, "debate_team": 69, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 517, "fields": {"ballot_submission": 35, "debate_adjudicator": 59, "debate_team": 70, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 518, "fields": {"ballot_submission": 35, "debate_adjudicator": 59, "debate_team": 70, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 519, "fields": {"ballot_submission": 35, "debate_adjudicator": 59, "debate_team": 70, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 520, "fields": {"ballot_submission": 35, "debate_adjudicator": 59, "debate_team": 70, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 521, "fields": {"ballot_submission": 36, "debate_adjudicator": 51, "debate_team": 71, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 522, "fields": {"ballot_submission": 36, "debate_adjudicator": 51, "debate_team": 71, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 523, "fields": {"ballot_submission": 36, "debate_adjudicator": 51, "debate_team": 71, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 524, "fields": {"ballot_submission": 36, "debate_adjudicator": 51, "debate_team": 71, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 525, "fields": {"ballot_submission": 36, "debate_adjudicator": 51, "debate_team": 72, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 526, "fields": {"ballot_submission": 36, "debate_adjudicator": 51, "debate_team": 72, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 527, "fields": {"ballot_submission": 36, "debate_adjudicator": 51, "debate_team": 72, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 528, "fields": {"ballot_submission": 36, "debate_adjudicator": 51, "debate_team": 72, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 529, "fields": {"ballot_submission": 37, "debate_adjudicator": 73, "debate_team": 73, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 530, "fields": {"ballot_submission": 37, "debate_adjudicator": 73, "debate_team": 73, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 531, "fields": {"ballot_submission": 37, "debate_adjudicator": 73, "debate_team": 73, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 532, "fields": {"ballot_submission": 37, "debate_adjudicator": 73, "debate_team": 73, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 533, "fields": {"ballot_submission": 37, "debate_adjudicator": 73, "debate_team": 74, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 534, "fields": {"ballot_submission": 37, "debate_adjudicator": 73, "debate_team": 74, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 535, "fields": {"ballot_submission": 37, "debate_adjudicator": 73, "debate_team": 74, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 536, "fields": {"ballot_submission": 37, "debate_adjudicator": 73, "debate_team": 74, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 537, "fields": {"ballot_submission": 38, "debate_adjudicator": 67, "debate_team": 75, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 538, "fields": {"ballot_submission": 38, "debate_adjudicator": 67, "debate_team": 75, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 539, "fields": {"ballot_submission": 38, "debate_adjudicator": 67, "debate_team": 75, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 540, "fields": {"ballot_submission": 38, "debate_adjudicator": 67, "debate_team": 75, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 541, "fields": {"ballot_submission": 38, "debate_adjudicator": 67, "debate_team": 76, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 542, "fields": {"ballot_submission": 38, "debate_adjudicator": 67, "debate_team": 76, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 543, "fields": {"ballot_submission": 38, "debate_adjudicator": 67, "debate_team": 76, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 544, "fields": {"ballot_submission": 38, "debate_adjudicator": 67, "debate_team": 76, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 545, "fields": {"ballot_submission": 39, "debate_adjudicator": 78, "debate_team": 77, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 546, "fields": {"ballot_submission": 39, "debate_adjudicator": 78, "debate_team": 77, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 547, "fields": {"ballot_submission": 39, "debate_adjudicator": 78, "debate_team": 77, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 548, "fields": {"ballot_submission": 39, "debate_adjudicator": 78, "debate_team": 77, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 549, "fields": {"ballot_submission": 39, "debate_adjudicator": 78, "debate_team": 78, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 550, "fields": {"ballot_submission": 39, "debate_adjudicator": 78, "debate_team": 78, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 551, "fields": {"ballot_submission": 39, "debate_adjudicator": 78, "debate_team": 78, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 552, "fields": {"ballot_submission": 39, "debate_adjudicator": 78, "debate_team": 78, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 553, "fields": {"ballot_submission": 39, "debate_adjudicator": 77, "debate_team": 77, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 554, "fields": {"ballot_submission": 39, "debate_adjudicator": 77, "debate_team": 77, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 555, "fields": {"ballot_submission": 39, "debate_adjudicator": 77, "debate_team": 77, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 556, "fields": {"ballot_submission": 39, "debate_adjudicator": 77, "debate_team": 77, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 557, "fields": {"ballot_submission": 39, "debate_adjudicator": 77, "debate_team": 78, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 558, "fields": {"ballot_submission": 39, "debate_adjudicator": 77, "debate_team": 78, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 559, "fields": {"ballot_submission": 39, "debate_adjudicator": 77, "debate_team": 78, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 560, "fields": {"ballot_submission": 39, "debate_adjudicator": 77, "debate_team": 78, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 561, "fields": {"ballot_submission": 39, "debate_adjudicator": 79, "debate_team": 77, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 562, "fields": {"ballot_submission": 39, "debate_adjudicator": 79, "debate_team": 77, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 563, "fields": {"ballot_submission": 39, "debate_adjudicator": 79, "debate_team": 77, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 564, "fields": {"ballot_submission": 39, "debate_adjudicator": 79, "debate_team": 77, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 565, "fields": {"ballot_submission": 39, "debate_adjudicator": 79, "debate_team": 78, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 566, "fields": {"ballot_submission": 39, "debate_adjudicator": 79, "debate_team": 78, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 567, "fields": {"ballot_submission": 39, "debate_adjudicator": 79, "debate_team": 78, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 568, "fields": {"ballot_submission": 39, "debate_adjudicator": 79, "debate_team": 78, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 569, "fields": {"ballot_submission": 40, "debate_adjudicator": 76, "debate_team": 79, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 570, "fields": {"ballot_submission": 40, "debate_adjudicator": 76, "debate_team": 79, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 571, "fields": {"ballot_submission": 40, "debate_adjudicator": 76, "debate_team": 79, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 572, "fields": {"ballot_submission": 40, "debate_adjudicator": 76, "debate_team": 79, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 573, "fields": {"ballot_submission": 40, "debate_adjudicator": 76, "debate_team": 80, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 574, "fields": {"ballot_submission": 40, "debate_adjudicator": 76, "debate_team": 80, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 575, "fields": {"ballot_submission": 40, "debate_adjudicator": 76, "debate_team": 80, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 576, "fields": {"ballot_submission": 40, "debate_adjudicator": 76, "debate_team": 80, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 577, "fields": {"ballot_submission": 40, "debate_adjudicator": 75, "debate_team": 79, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 578, "fields": {"ballot_submission": 40, "debate_adjudicator": 75, "debate_team": 79, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 579, "fields": {"ballot_submission": 40, "debate_adjudicator": 75, "debate_team": 79, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 580, "fields": {"ballot_submission": 40, "debate_adjudicator": 75, "debate_team": 79, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 581, "fields": {"ballot_submission": 40, "debate_adjudicator": 75, "debate_team": 80, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 582, "fields": {"ballot_submission": 40, "debate_adjudicator": 75, "debate_team": 80, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 583, "fields": {"ballot_submission": 40, "debate_adjudicator": 75, "debate_team": 80, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 584, "fields": {"ballot_submission": 40, "debate_adjudicator": 75, "debate_team": 80, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 585, "fields": {"ballot_submission": 40, "debate_adjudicator": 74, "debate_team": 79, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 586, "fields": {"ballot_submission": 40, "debate_adjudicator": 74, "debate_team": 79, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 587, "fields": {"ballot_submission": 40, "debate_adjudicator": 74, "debate_team": 79, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 588, "fields": {"ballot_submission": 40, "debate_adjudicator": 74, "debate_team": 79, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 589, "fields": {"ballot_submission": 40, "debate_adjudicator": 74, "debate_team": 80, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 590, "fields": {"ballot_submission": 40, "debate_adjudicator": 74, "debate_team": 80, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 591, "fields": {"ballot_submission": 40, "debate_adjudicator": 74, "debate_team": 80, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 592, "fields": {"ballot_submission": 40, "debate_adjudicator": 74, "debate_team": 80, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 593, "fields": {"ballot_submission": 41, "debate_adjudicator": 81, "debate_team": 81, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 594, "fields": {"ballot_submission": 41, "debate_adjudicator": 81, "debate_team": 81, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 595, "fields": {"ballot_submission": 41, "debate_adjudicator": 81, "debate_team": 81, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 596, "fields": {"ballot_submission": 41, "debate_adjudicator": 81, "debate_team": 81, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 597, "fields": {"ballot_submission": 41, "debate_adjudicator": 81, "debate_team": 82, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 598, "fields": {"ballot_submission": 41, "debate_adjudicator": 81, "debate_team": 82, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 599, "fields": {"ballot_submission": 41, "debate_adjudicator": 81, "debate_team": 82, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 600, "fields": {"ballot_submission": 41, "debate_adjudicator": 81, "debate_team": 82, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 601, "fields": {"ballot_submission": 41, "debate_adjudicator": 80, "debate_team": 81, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 602, "fields": {"ballot_submission": 41, "debate_adjudicator": 80, "debate_team": 81, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 603, "fields": {"ballot_submission": 41, "debate_adjudicator": 80, "debate_team": 81, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 604, "fields": {"ballot_submission": 41, "debate_adjudicator": 80, "debate_team": 81, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 605, "fields": {"ballot_submission": 41, "debate_adjudicator": 80, "debate_team": 82, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 606, "fields": {"ballot_submission": 41, "debate_adjudicator": 80, "debate_team": 82, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 607, "fields": {"ballot_submission": 41, "debate_adjudicator": 80, "debate_team": 82, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 608, "fields": {"ballot_submission": 41, "debate_adjudicator": 80, "debate_team": 82, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 609, "fields": {"ballot_submission": 41, "debate_adjudicator": 82, "debate_team": 81, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 610, "fields": {"ballot_submission": 41, "debate_adjudicator": 82, "debate_team": 81, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 611, "fields": {"ballot_submission": 41, "debate_adjudicator": 82, "debate_team": 81, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 612, "fields": {"ballot_submission": 41, "debate_adjudicator": 82, "debate_team": 81, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 613, "fields": {"ballot_submission": 41, "debate_adjudicator": 82, "debate_team": 82, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 614, "fields": {"ballot_submission": 41, "debate_adjudicator": 82, "debate_team": 82, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 615, "fields": {"ballot_submission": 41, "debate_adjudicator": 82, "debate_team": 82, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 616, "fields": {"ballot_submission": 41, "debate_adjudicator": 82, "debate_team": 82, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 617, "fields": {"ballot_submission": 42, "debate_adjudicator": 88, "debate_team": 83, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 618, "fields": {"ballot_submission": 42, "debate_adjudicator": 88, "debate_team": 83, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 619, "fields": {"ballot_submission": 42, "debate_adjudicator": 88, "debate_team": 83, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 620, "fields": {"ballot_submission": 42, "debate_adjudicator": 88, "debate_team": 83, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 621, "fields": {"ballot_submission": 42, "debate_adjudicator": 88, "debate_team": 84, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 622, "fields": {"ballot_submission": 42, "debate_adjudicator": 88, "debate_team": 84, "score": 72.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 623, "fields": {"ballot_submission": 42, "debate_adjudicator": 88, "debate_team": 84, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 624, "fields": {"ballot_submission": 42, "debate_adjudicator": 88, "debate_team": 84, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 625, "fields": {"ballot_submission": 42, "debate_adjudicator": 86, "debate_team": 83, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 626, "fields": {"ballot_submission": 42, "debate_adjudicator": 86, "debate_team": 83, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 627, "fields": {"ballot_submission": 42, "debate_adjudicator": 86, "debate_team": 83, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 628, "fields": {"ballot_submission": 42, "debate_adjudicator": 86, "debate_team": 83, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 629, "fields": {"ballot_submission": 42, "debate_adjudicator": 86, "debate_team": 84, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 630, "fields": {"ballot_submission": 42, "debate_adjudicator": 86, "debate_team": 84, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 631, "fields": {"ballot_submission": 42, "debate_adjudicator": 86, "debate_team": 84, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 632, "fields": {"ballot_submission": 42, "debate_adjudicator": 86, "debate_team": 84, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 633, "fields": {"ballot_submission": 42, "debate_adjudicator": 87, "debate_team": 83, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 634, "fields": {"ballot_submission": 42, "debate_adjudicator": 87, "debate_team": 83, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 635, "fields": {"ballot_submission": 42, "debate_adjudicator": 87, "debate_team": 83, "score": 78.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 636, "fields": {"ballot_submission": 42, "debate_adjudicator": 87, "debate_team": 83, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 637, "fields": {"ballot_submission": 42, "debate_adjudicator": 87, "debate_team": 84, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 638, "fields": {"ballot_submission": 42, "debate_adjudicator": 87, "debate_team": 84, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 639, "fields": {"ballot_submission": 42, "debate_adjudicator": 87, "debate_team": 84, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 640, "fields": {"ballot_submission": 42, "debate_adjudicator": 87, "debate_team": 84, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 641, "fields": {"ballot_submission": 43, "debate_adjudicator": 83, "debate_team": 85, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 642, "fields": {"ballot_submission": 43, "debate_adjudicator": 83, "debate_team": 85, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 643, "fields": {"ballot_submission": 43, "debate_adjudicator": 83, "debate_team": 85, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 644, "fields": {"ballot_submission": 43, "debate_adjudicator": 83, "debate_team": 85, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 645, "fields": {"ballot_submission": 43, "debate_adjudicator": 83, "debate_team": 86, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 646, "fields": {"ballot_submission": 43, "debate_adjudicator": 83, "debate_team": 86, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 647, "fields": {"ballot_submission": 43, "debate_adjudicator": 83, "debate_team": 86, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 648, "fields": {"ballot_submission": 43, "debate_adjudicator": 83, "debate_team": 86, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 649, "fields": {"ballot_submission": 43, "debate_adjudicator": 85, "debate_team": 85, "score": 73.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 650, "fields": {"ballot_submission": 43, "debate_adjudicator": 85, "debate_team": 85, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 651, "fields": {"ballot_submission": 43, "debate_adjudicator": 85, "debate_team": 85, "score": 73.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 652, "fields": {"ballot_submission": 43, "debate_adjudicator": 85, "debate_team": 85, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 653, "fields": {"ballot_submission": 43, "debate_adjudicator": 85, "debate_team": 86, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 654, "fields": {"ballot_submission": 43, "debate_adjudicator": 85, "debate_team": 86, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 655, "fields": {"ballot_submission": 43, "debate_adjudicator": 85, "debate_team": 86, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 656, "fields": {"ballot_submission": 43, "debate_adjudicator": 85, "debate_team": 86, "score": 39.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 657, "fields": {"ballot_submission": 43, "debate_adjudicator": 84, "debate_team": 85, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 658, "fields": {"ballot_submission": 43, "debate_adjudicator": 84, "debate_team": 85, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 659, "fields": {"ballot_submission": 43, "debate_adjudicator": 84, "debate_team": 85, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 660, "fields": {"ballot_submission": 43, "debate_adjudicator": 84, "debate_team": 85, "score": 36.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 661, "fields": {"ballot_submission": 43, "debate_adjudicator": 84, "debate_team": 86, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 662, "fields": {"ballot_submission": 43, "debate_adjudicator": 84, "debate_team": 86, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 663, "fields": {"ballot_submission": 43, "debate_adjudicator": 84, "debate_team": 86, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 664, "fields": {"ballot_submission": 43, "debate_adjudicator": 84, "debate_team": 86, "score": 37.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 665, "fields": {"ballot_submission": 44, "debate_adjudicator": 71, "debate_team": 87, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 666, "fields": {"ballot_submission": 44, "debate_adjudicator": 71, "debate_team": 87, "score": 77.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 667, "fields": {"ballot_submission": 44, "debate_adjudicator": 71, "debate_team": 87, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 668, "fields": {"ballot_submission": 44, "debate_adjudicator": 71, "debate_team": 87, "score": 38.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 669, "fields": {"ballot_submission": 44, "debate_adjudicator": 71, "debate_team": 88, "score": 72.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 670, "fields": {"ballot_submission": 44, "debate_adjudicator": 71, "debate_team": 88, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 671, "fields": {"ballot_submission": 44, "debate_adjudicator": 71, "debate_team": 88, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 672, "fields": {"ballot_submission": 44, "debate_adjudicator": 71, "debate_team": 88, "score": 36.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 673, "fields": {"ballot_submission": 45, "debate_adjudicator": 72, "debate_team": 89, "score": 75.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 674, "fields": {"ballot_submission": 45, "debate_adjudicator": 72, "debate_team": 89, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 675, "fields": {"ballot_submission": 45, "debate_adjudicator": 72, "debate_team": 89, "score": 75.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 676, "fields": {"ballot_submission": 45, "debate_adjudicator": 72, "debate_team": 89, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 677, "fields": {"ballot_submission": 45, "debate_adjudicator": 72, "debate_team": 90, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 678, "fields": {"ballot_submission": 45, "debate_adjudicator": 72, "debate_team": 90, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 679, "fields": {"ballot_submission": 45, "debate_adjudicator": 72, "debate_team": 90, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 680, "fields": {"ballot_submission": 45, "debate_adjudicator": 72, "debate_team": 90, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 681, "fields": {"ballot_submission": 46, "debate_adjudicator": 68, "debate_team": 91, "score": 78.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 682, "fields": {"ballot_submission": 46, "debate_adjudicator": 68, "debate_team": 91, "score": 75.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 683, "fields": {"ballot_submission": 46, "debate_adjudicator": 68, "debate_team": 91, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 684, "fields": {"ballot_submission": 46, "debate_adjudicator": 68, "debate_team": 91, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 685, "fields": {"ballot_submission": 46, "debate_adjudicator": 68, "debate_team": 92, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 686, "fields": {"ballot_submission": 46, "debate_adjudicator": 68, "debate_team": 92, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 687, "fields": {"ballot_submission": 46, "debate_adjudicator": 68, "debate_team": 92, "score": 77.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 688, "fields": {"ballot_submission": 46, "debate_adjudicator": 68, "debate_team": 92, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 689, "fields": {"ballot_submission": 47, "debate_adjudicator": 70, "debate_team": 93, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 690, "fields": {"ballot_submission": 47, "debate_adjudicator": 70, "debate_team": 93, "score": 73.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 691, "fields": {"ballot_submission": 47, "debate_adjudicator": 70, "debate_team": 93, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 692, "fields": {"ballot_submission": 47, "debate_adjudicator": 70, "debate_team": 93, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 693, "fields": {"ballot_submission": 47, "debate_adjudicator": 70, "debate_team": 94, "score": 76.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 694, "fields": {"ballot_submission": 47, "debate_adjudicator": 70, "debate_team": 94, "score": 76.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 695, "fields": {"ballot_submission": 47, "debate_adjudicator": 70, "debate_team": 94, "score": 76.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 696, "fields": {"ballot_submission": 47, "debate_adjudicator": 70, "debate_team": 94, "score": 38.0, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 697, "fields": {"ballot_submission": 48, "debate_adjudicator": 69, "debate_team": 95, "score": 77.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 698, "fields": {"ballot_submission": 48, "debate_adjudicator": 69, "debate_team": 95, "score": 78.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 699, "fields": {"ballot_submission": 48, "debate_adjudicator": 69, "debate_team": 95, "score": 74.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 700, "fields": {"ballot_submission": 48, "debate_adjudicator": 69, "debate_team": 95, "score": 37.5, "position": 4}}, {"model": "results.speakerscorebyadj", "pk": 701, "fields": {"ballot_submission": 48, "debate_adjudicator": 69, "debate_team": 96, "score": 74.0, "position": 1}}, {"model": "results.speakerscorebyadj", "pk": 702, "fields": {"ballot_submission": 48, "debate_adjudicator": 69, "debate_team": 96, "score": 74.0, "position": 2}}, {"model": "results.speakerscorebyadj", "pk": 703, "fields": {"ballot_submission": 48, "debate_adjudicator": 69, "debate_team": 96, "score": 72.0, "position": 3}}, {"model": "results.speakerscorebyadj", "pk": 704, "fields": {"ballot_submission": 48, "debate_adjudicator": 69, "debate_team": 96, "score": 38.5, "position": 4}}, {"model": "results.teamscore", "pk": 1, "fields": {"ballot_submission": 1, "debate_team": 23, "points": 0, "margin": -2.5, "win": false, "score": 259.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 2, "fields": {"ballot_submission": 1, "debate_team": 24, "points": 1, "margin": 2.5, "win": true, "score": 261.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 3, "fields": {"ballot_submission": 2, "debate_team": 21, "points": 0, "margin": -0.5, "win": false, "score": 266.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 4, "fields": {"ballot_submission": 2, "debate_team": 22, "points": 1, "margin": 0.5, "win": true, "score": 267.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 5, "fields": {"ballot_submission": 3, "debate_team": 19, "points": 0, "margin": -3.5, "win": false, "score": 261.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 6, "fields": {"ballot_submission": 3, "debate_team": 20, "points": 1, "margin": 3.5, "win": true, "score": 265.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 7, "fields": {"ballot_submission": 4, "debate_team": 17, "points": 0, "margin": -4.5, "win": false, "score": 257.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 8, "fields": {"ballot_submission": 4, "debate_team": 18, "points": 1, "margin": 4.5, "win": true, "score": 262.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 9, "fields": {"ballot_submission": 5, "debate_team": 15, "points": 0, "margin": -0.5, "win": false, "score": 260.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 10, "fields": {"ballot_submission": 5, "debate_team": 16, "points": 1, "margin": 0.5, "win": true, "score": 261.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 11, "fields": {"ballot_submission": 6, "debate_team": 13, "points": 0, "margin": -7.5, "win": false, "score": 255.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 12, "fields": {"ballot_submission": 6, "debate_team": 14, "points": 1, "margin": 7.5, "win": true, "score": 263.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 13, "fields": {"ballot_submission": 7, "debate_team": 11, "points": 1, "margin": 2.5, "win": true, "score": 267.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 14, "fields": {"ballot_submission": 7, "debate_team": 12, "points": 0, "margin": -2.5, "win": false, "score": 264.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 15, "fields": {"ballot_submission": 8, "debate_team": 9, "points": 1, "margin": 4.66666666666669, "win": true, "score": 266.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 16, "fields": {"ballot_submission": 8, "debate_team": 10, "points": 0, "margin": -4.66666666666669, "win": false, "score": 261.333333333333, "forfeit": false}}, {"model": "results.teamscore", "pk": 17, "fields": {"ballot_submission": 9, "debate_team": 7, "points": 1, "margin": 5.0, "win": true, "score": 266.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 18, "fields": {"ballot_submission": 9, "debate_team": 8, "points": 0, "margin": -5.0, "win": false, "score": 261.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 19, "fields": {"ballot_submission": 10, "debate_team": 5, "points": 1, "margin": 5.33333333333331, "win": true, "score": 266.833333333333, "forfeit": false}}, {"model": "results.teamscore", "pk": 20, "fields": {"ballot_submission": 10, "debate_team": 6, "points": 0, "margin": -5.33333333333331, "win": false, "score": 261.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 21, "fields": {"ballot_submission": 11, "debate_team": 3, "points": 0, "margin": -2.75, "win": false, "score": 261.75, "forfeit": false}}, {"model": "results.teamscore", "pk": 22, "fields": {"ballot_submission": 11, "debate_team": 4, "points": 1, "margin": 2.75, "win": true, "score": 264.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 23, "fields": {"ballot_submission": 12, "debate_team": 1, "points": 1, "margin": 1.25, "win": true, "score": 266.25, "forfeit": false}}, {"model": "results.teamscore", "pk": 24, "fields": {"ballot_submission": 12, "debate_team": 2, "points": 0, "margin": -1.25, "win": false, "score": 265.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 25, "fields": {"ballot_submission": 13, "debate_team": 47, "points": 1, "margin": 1.83333333333331, "win": true, "score": 264.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 26, "fields": {"ballot_submission": 13, "debate_team": 48, "points": 0, "margin": -1.83333333333331, "win": false, "score": 262.166666666667, "forfeit": false}}, {"model": "results.teamscore", "pk": 27, "fields": {"ballot_submission": 14, "debate_team": 45, "points": 1, "margin": 0.5, "win": true, "score": 261.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 28, "fields": {"ballot_submission": 14, "debate_team": 46, "points": 0, "margin": -0.5, "win": false, "score": 261.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 29, "fields": {"ballot_submission": 15, "debate_team": 43, "points": 0, "margin": -1.75, "win": false, "score": 261.25, "forfeit": false}}, {"model": "results.teamscore", "pk": 30, "fields": {"ballot_submission": 15, "debate_team": 44, "points": 1, "margin": 1.75, "win": true, "score": 263.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 31, "fields": {"ballot_submission": 16, "debate_team": 41, "points": 1, "margin": 2.0, "win": true, "score": 263.666666666667, "forfeit": false}}, {"model": "results.teamscore", "pk": 32, "fields": {"ballot_submission": 16, "debate_team": 42, "points": 0, "margin": -2.0, "win": false, "score": 261.666666666667, "forfeit": false}}, {"model": "results.teamscore", "pk": 33, "fields": {"ballot_submission": 17, "debate_team": 39, "points": 0, "margin": -2.0, "win": false, "score": 260.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 34, "fields": {"ballot_submission": 17, "debate_team": 40, "points": 1, "margin": 2.0, "win": true, "score": 262.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 35, "fields": {"ballot_submission": 18, "debate_team": 37, "points": 1, "margin": 0.5, "win": true, "score": 263.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 36, "fields": {"ballot_submission": 18, "debate_team": 38, "points": 0, "margin": -0.5, "win": false, "score": 262.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 37, "fields": {"ballot_submission": 19, "debate_team": 35, "points": 1, "margin": 3.0, "win": true, "score": 265.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 38, "fields": {"ballot_submission": 19, "debate_team": 36, "points": 0, "margin": -3.0, "win": false, "score": 262.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 39, "fields": {"ballot_submission": 20, "debate_team": 33, "points": 1, "margin": 2.0, "win": true, "score": 261.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 40, "fields": {"ballot_submission": 20, "debate_team": 34, "points": 0, "margin": -2.0, "win": false, "score": 259.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 41, "fields": {"ballot_submission": 21, "debate_team": 31, "points": 0, "margin": -0.5, "win": false, "score": 264.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 42, "fields": {"ballot_submission": 21, "debate_team": 32, "points": 1, "margin": 0.5, "win": true, "score": 265.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 43, "fields": {"ballot_submission": 22, "debate_team": 29, "points": 0, "margin": -6.0, "win": false, "score": 260.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 44, "fields": {"ballot_submission": 22, "debate_team": 30, "points": 1, "margin": 6.0, "win": true, "score": 266.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 45, "fields": {"ballot_submission": 23, "debate_team": 27, "points": 0, "margin": -1.5, "win": false, "score": 261.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 46, "fields": {"ballot_submission": 23, "debate_team": 28, "points": 1, "margin": 1.5, "win": true, "score": 262.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 47, "fields": {"ballot_submission": 24, "debate_team": 25, "points": 1, "margin": 7.5, "win": true, "score": 262.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 48, "fields": {"ballot_submission": 24, "debate_team": 26, "points": 0, "margin": -7.5, "win": false, "score": 254.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 49, "fields": {"ballot_submission": 25, "debate_team": 49, "points": 0, "margin": -2.5, "win": false, "score": 261.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 50, "fields": {"ballot_submission": 25, "debate_team": 50, "points": 1, "margin": 2.5, "win": true, "score": 264.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 51, "fields": {"ballot_submission": 26, "debate_team": 51, "points": 0, "margin": -2.5, "win": false, "score": 259.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 52, "fields": {"ballot_submission": 26, "debate_team": 52, "points": 1, "margin": 2.5, "win": true, "score": 262.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 53, "fields": {"ballot_submission": 27, "debate_team": 53, "points": 0, "margin": -4.0, "win": false, "score": 259.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 54, "fields": {"ballot_submission": 27, "debate_team": 54, "points": 1, "margin": 4.0, "win": true, "score": 263.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 55, "fields": {"ballot_submission": 28, "debate_team": 55, "points": 0, "margin": -3.25, "win": false, "score": 260.75, "forfeit": false}}, {"model": "results.teamscore", "pk": 56, "fields": {"ballot_submission": 28, "debate_team": 56, "points": 1, "margin": 3.25, "win": true, "score": 264.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 57, "fields": {"ballot_submission": 29, "debate_team": 57, "points": 0, "margin": -5.25, "win": false, "score": 262.25, "forfeit": false}}, {"model": "results.teamscore", "pk": 58, "fields": {"ballot_submission": 29, "debate_team": 58, "points": 1, "margin": 5.25, "win": true, "score": 267.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 59, "fields": {"ballot_submission": 30, "debate_team": 59, "points": 1, "margin": 7.0, "win": true, "score": 266.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 60, "fields": {"ballot_submission": 30, "debate_team": 60, "points": 0, "margin": -7.0, "win": false, "score": 259.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 61, "fields": {"ballot_submission": 31, "debate_team": 61, "points": 0, "margin": -5.5, "win": false, "score": 260.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 62, "fields": {"ballot_submission": 31, "debate_team": 62, "points": 1, "margin": 5.5, "win": true, "score": 266.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 63, "fields": {"ballot_submission": 32, "debate_team": 63, "points": 1, "margin": 5.5, "win": true, "score": 258.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 64, "fields": {"ballot_submission": 32, "debate_team": 64, "points": 0, "margin": -5.5, "win": false, "score": 253.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 65, "fields": {"ballot_submission": 33, "debate_team": 65, "points": 0, "margin": -6.5, "win": false, "score": 255.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 66, "fields": {"ballot_submission": 33, "debate_team": 66, "points": 1, "margin": 6.5, "win": true, "score": 262.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 67, "fields": {"ballot_submission": 34, "debate_team": 67, "points": 1, "margin": 7.75, "win": true, "score": 266.75, "forfeit": false}}, {"model": "results.teamscore", "pk": 68, "fields": {"ballot_submission": 34, "debate_team": 68, "points": 0, "margin": -7.75, "win": false, "score": 259.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 69, "fields": {"ballot_submission": 35, "debate_team": 69, "points": 1, "margin": 4.25, "win": true, "score": 261.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 70, "fields": {"ballot_submission": 35, "debate_team": 70, "points": 0, "margin": -4.25, "win": false, "score": 257.25, "forfeit": false}}, {"model": "results.teamscore", "pk": 71, "fields": {"ballot_submission": 36, "debate_team": 71, "points": 0, "margin": -1.5, "win": false, "score": 261.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 72, "fields": {"ballot_submission": 36, "debate_team": 72, "points": 1, "margin": 1.5, "win": true, "score": 262.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 73, "fields": {"ballot_submission": 37, "debate_team": 73, "points": 0, "margin": -5.5, "win": false, "score": 259.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 74, "fields": {"ballot_submission": 37, "debate_team": 74, "points": 1, "margin": 5.5, "win": true, "score": 264.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 75, "fields": {"ballot_submission": 38, "debate_team": 75, "points": 0, "margin": -4.0, "win": false, "score": 258.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 76, "fields": {"ballot_submission": 38, "debate_team": 76, "points": 1, "margin": 4.0, "win": true, "score": 262.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 77, "fields": {"ballot_submission": 39, "debate_team": 77, "points": 0, "margin": -6.0, "win": false, "score": 256.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 78, "fields": {"ballot_submission": 39, "debate_team": 78, "points": 1, "margin": 6.0, "win": true, "score": 262.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 79, "fields": {"ballot_submission": 40, "debate_team": 79, "points": 0, "margin": -2.33333333333337, "win": false, "score": 261.833333333333, "forfeit": false}}, {"model": "results.teamscore", "pk": 80, "fields": {"ballot_submission": 40, "debate_team": 80, "points": 1, "margin": 2.33333333333337, "win": true, "score": 264.166666666667, "forfeit": false}}, {"model": "results.teamscore", "pk": 81, "fields": {"ballot_submission": 41, "debate_team": 81, "points": 0, "margin": -4.25, "win": false, "score": 262.25, "forfeit": false}}, {"model": "results.teamscore", "pk": 82, "fields": {"ballot_submission": 41, "debate_team": 82, "points": 1, "margin": 4.25, "win": true, "score": 266.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 83, "fields": {"ballot_submission": 42, "debate_team": 83, "points": 1, "margin": 3.16666666666669, "win": true, "score": 264.666666666667, "forfeit": false}}, {"model": "results.teamscore", "pk": 84, "fields": {"ballot_submission": 42, "debate_team": 84, "points": 0, "margin": -3.16666666666669, "win": false, "score": 261.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 85, "fields": {"ballot_submission": 43, "debate_team": 85, "points": 0, "margin": -5.83333333333331, "win": false, "score": 260.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 86, "fields": {"ballot_submission": 43, "debate_team": 86, "points": 1, "margin": 5.83333333333331, "win": true, "score": 266.333333333333, "forfeit": false}}, {"model": "results.teamscore", "pk": 87, "fields": {"ballot_submission": 44, "debate_team": 87, "points": 1, "margin": 10.0, "win": true, "score": 267.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 88, "fields": {"ballot_submission": 44, "debate_team": 88, "points": 0, "margin": -10.0, "win": false, "score": 257.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 89, "fields": {"ballot_submission": 45, "debate_team": 89, "points": 0, "margin": -1.0, "win": false, "score": 262.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 90, "fields": {"ballot_submission": 45, "debate_team": 90, "points": 1, "margin": 1.0, "win": true, "score": 263.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 91, "fields": {"ballot_submission": 46, "debate_team": 91, "points": 0, "margin": -1.0, "win": false, "score": 268.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 92, "fields": {"ballot_submission": 46, "debate_team": 92, "points": 1, "margin": 1.0, "win": true, "score": 269.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 93, "fields": {"ballot_submission": 47, "debate_team": 93, "points": 0, "margin": -7.5, "win": false, "score": 258.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 94, "fields": {"ballot_submission": 47, "debate_team": 94, "points": 1, "margin": 7.5, "win": true, "score": 266.0, "forfeit": false}}, {"model": "results.teamscore", "pk": 95, "fields": {"ballot_submission": 48, "debate_team": 95, "points": 1, "margin": 8.0, "win": true, "score": 266.5, "forfeit": false}}, {"model": "results.teamscore", "pk": 96, "fields": {"ballot_submission": 48, "debate_team": 96, "points": 0, "margin": -8.0, "win": false, "score": 258.5, "forfeit": false}}, {"model": "results.speakerscore", "pk": 1, "fields": {"ballot_submission": 1, "debate_team": 23, "speaker": 40, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 2, "fields": {"ballot_submission": 1, "debate_team": 23, "speaker": 41, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 3, "fields": {"ballot_submission": 1, "debate_team": 23, "speaker": 42, "score": 73.0, "position": 3}}, {"model": "results.speakerscore", "pk": 4, "fields": {"ballot_submission": 1, "debate_team": 23, "speaker": 40, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 5, "fields": {"ballot_submission": 1, "debate_team": 24, "speaker": 54, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 6, "fields": {"ballot_submission": 1, "debate_team": 24, "speaker": 53, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 7, "fields": {"ballot_submission": 1, "debate_team": 24, "speaker": 52, "score": 78.0, "position": 3}}, {"model": "results.speakerscore", "pk": 8, "fields": {"ballot_submission": 1, "debate_team": 24, "speaker": 54, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 9, "fields": {"ballot_submission": 2, "debate_team": 21, "speaker": 10, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 10, "fields": {"ballot_submission": 2, "debate_team": 21, "speaker": 11, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 11, "fields": {"ballot_submission": 2, "debate_team": 21, "speaker": 12, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 12, "fields": {"ballot_submission": 2, "debate_team": 21, "speaker": 10, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 13, "fields": {"ballot_submission": 2, "debate_team": 22, "speaker": 23, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 14, "fields": {"ballot_submission": 2, "debate_team": 22, "speaker": 24, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 15, "fields": {"ballot_submission": 2, "debate_team": 22, "speaker": 22, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 16, "fields": {"ballot_submission": 2, "debate_team": 22, "speaker": 23, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 17, "fields": {"ballot_submission": 3, "debate_team": 19, "speaker": 69, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 18, "fields": {"ballot_submission": 3, "debate_team": 19, "speaker": 68, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 19, "fields": {"ballot_submission": 3, "debate_team": 19, "speaker": 67, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 20, "fields": {"ballot_submission": 3, "debate_team": 19, "speaker": 69, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 21, "fields": {"ballot_submission": 3, "debate_team": 20, "speaker": 33, "score": 78.0, "position": 1}}, {"model": "results.speakerscore", "pk": 22, "fields": {"ballot_submission": 3, "debate_team": 20, "speaker": 31, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 23, "fields": {"ballot_submission": 3, "debate_team": 20, "speaker": 32, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 24, "fields": {"ballot_submission": 3, "debate_team": 20, "speaker": 33, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 25, "fields": {"ballot_submission": 4, "debate_team": 17, "speaker": 49, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 26, "fields": {"ballot_submission": 4, "debate_team": 17, "speaker": 50, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 27, "fields": {"ballot_submission": 4, "debate_team": 17, "speaker": 51, "score": 73.0, "position": 3}}, {"model": "results.speakerscore", "pk": 28, "fields": {"ballot_submission": 4, "debate_team": 17, "speaker": 49, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 29, "fields": {"ballot_submission": 4, "debate_team": 18, "speaker": 1, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 30, "fields": {"ballot_submission": 4, "debate_team": 18, "speaker": 3, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 31, "fields": {"ballot_submission": 4, "debate_team": 18, "speaker": 2, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 32, "fields": {"ballot_submission": 4, "debate_team": 18, "speaker": 1, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 33, "fields": {"ballot_submission": 5, "debate_team": 15, "speaker": 55, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 34, "fields": {"ballot_submission": 5, "debate_team": 15, "speaker": 57, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 35, "fields": {"ballot_submission": 5, "debate_team": 15, "speaker": 56, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 36, "fields": {"ballot_submission": 5, "debate_team": 15, "speaker": 55, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 37, "fields": {"ballot_submission": 5, "debate_team": 16, "speaker": 45, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 38, "fields": {"ballot_submission": 5, "debate_team": 16, "speaker": 44, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 39, "fields": {"ballot_submission": 5, "debate_team": 16, "speaker": 43, "score": 72.0, "position": 3}}, {"model": "results.speakerscore", "pk": 40, "fields": {"ballot_submission": 5, "debate_team": 16, "speaker": 45, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 41, "fields": {"ballot_submission": 6, "debate_team": 13, "speaker": 34, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 42, "fields": {"ballot_submission": 6, "debate_team": 13, "speaker": 35, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 43, "fields": {"ballot_submission": 6, "debate_team": 13, "speaker": 36, "score": 72.0, "position": 3}}, {"model": "results.speakerscore", "pk": 44, "fields": {"ballot_submission": 6, "debate_team": 13, "speaker": 34, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 45, "fields": {"ballot_submission": 6, "debate_team": 14, "speaker": 48, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 46, "fields": {"ballot_submission": 6, "debate_team": 14, "speaker": 46, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 47, "fields": {"ballot_submission": 6, "debate_team": 14, "speaker": 47, "score": 78.0, "position": 3}}, {"model": "results.speakerscore", "pk": 48, "fields": {"ballot_submission": 6, "debate_team": 14, "speaker": 48, "score": 36.0, "position": 4}}, {"model": "results.speakerscore", "pk": 49, "fields": {"ballot_submission": 7, "debate_team": 11, "speaker": 15, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 50, "fields": {"ballot_submission": 7, "debate_team": 11, "speaker": 13, "score": 78.0, "position": 2}}, {"model": "results.speakerscore", "pk": 51, "fields": {"ballot_submission": 7, "debate_team": 11, "speaker": 14, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 52, "fields": {"ballot_submission": 7, "debate_team": 11, "speaker": 15, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 53, "fields": {"ballot_submission": 7, "debate_team": 12, "speaker": 29, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 54, "fields": {"ballot_submission": 7, "debate_team": 12, "speaker": 28, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 55, "fields": {"ballot_submission": 7, "debate_team": 12, "speaker": 30, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 56, "fields": {"ballot_submission": 7, "debate_team": 12, "speaker": 29, "score": 38.5, "position": 4}}, {"model": "results.speakerscore", "pk": 57, "fields": {"ballot_submission": 8, "debate_team": 9, "speaker": 17, "score": 76.6666666666667, "position": 1}}, {"model": "results.speakerscore", "pk": 58, "fields": {"ballot_submission": 8, "debate_team": 9, "speaker": 16, "score": 75.6666666666667, "position": 2}}, {"model": "results.speakerscore", "pk": 59, "fields": {"ballot_submission": 8, "debate_team": 9, "speaker": 18, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 60, "fields": {"ballot_submission": 8, "debate_team": 9, "speaker": 17, "score": 37.6666666666667, "position": 4}}, {"model": "results.speakerscore", "pk": 61, "fields": {"ballot_submission": 8, "debate_team": 10, "speaker": 64, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 62, "fields": {"ballot_submission": 8, "debate_team": 10, "speaker": 66, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 63, "fields": {"ballot_submission": 8, "debate_team": 10, "speaker": 65, "score": 74.3333333333333, "position": 3}}, {"model": "results.speakerscore", "pk": 64, "fields": {"ballot_submission": 8, "debate_team": 10, "speaker": 64, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 65, "fields": {"ballot_submission": 9, "debate_team": 7, "speaker": 21, "score": 77.5, "position": 1}}, {"model": "results.speakerscore", "pk": 66, "fields": {"ballot_submission": 9, "debate_team": 7, "speaker": 20, "score": 74.5, "position": 2}}, {"model": "results.speakerscore", "pk": 67, "fields": {"ballot_submission": 9, "debate_team": 7, "speaker": 19, "score": 76.5, "position": 3}}, {"model": "results.speakerscore", "pk": 68, "fields": {"ballot_submission": 9, "debate_team": 7, "speaker": 21, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 69, "fields": {"ballot_submission": 9, "debate_team": 8, "speaker": 72, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 70, "fields": {"ballot_submission": 9, "debate_team": 8, "speaker": 71, "score": 73.5, "position": 2}}, {"model": "results.speakerscore", "pk": 71, "fields": {"ballot_submission": 9, "debate_team": 8, "speaker": 70, "score": 74.5, "position": 3}}, {"model": "results.speakerscore", "pk": 72, "fields": {"ballot_submission": 9, "debate_team": 8, "speaker": 72, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 73, "fields": {"ballot_submission": 10, "debate_team": 5, "speaker": 5, "score": 75.6666666666667, "position": 1}}, {"model": "results.speakerscore", "pk": 74, "fields": {"ballot_submission": 10, "debate_team": 5, "speaker": 4, "score": 77.6666666666667, "position": 2}}, {"model": "results.speakerscore", "pk": 75, "fields": {"ballot_submission": 10, "debate_team": 5, "speaker": 6, "score": 75.6666666666667, "position": 3}}, {"model": "results.speakerscore", "pk": 76, "fields": {"ballot_submission": 10, "debate_team": 5, "speaker": 5, "score": 37.8333333333333, "position": 4}}, {"model": "results.speakerscore", "pk": 77, "fields": {"ballot_submission": 10, "debate_team": 6, "speaker": 38, "score": 75.3333333333333, "position": 1}}, {"model": "results.speakerscore", "pk": 78, "fields": {"ballot_submission": 10, "debate_team": 6, "speaker": 37, "score": 74.3333333333333, "position": 2}}, {"model": "results.speakerscore", "pk": 79, "fields": {"ballot_submission": 10, "debate_team": 6, "speaker": 39, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 80, "fields": {"ballot_submission": 10, "debate_team": 6, "speaker": 38, "score": 36.8333333333333, "position": 4}}, {"model": "results.speakerscore", "pk": 81, "fields": {"ballot_submission": 11, "debate_team": 3, "speaker": 59, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 82, "fields": {"ballot_submission": 11, "debate_team": 3, "speaker": 58, "score": 74.5, "position": 2}}, {"model": "results.speakerscore", "pk": 83, "fields": {"ballot_submission": 11, "debate_team": 3, "speaker": 60, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 84, "fields": {"ballot_submission": 11, "debate_team": 3, "speaker": 59, "score": 36.25, "position": 4}}, {"model": "results.speakerscore", "pk": 85, "fields": {"ballot_submission": 11, "debate_team": 4, "speaker": 25, "score": 76.5, "position": 1}}, {"model": "results.speakerscore", "pk": 86, "fields": {"ballot_submission": 11, "debate_team": 4, "speaker": 27, "score": 74.5, "position": 2}}, {"model": "results.speakerscore", "pk": 87, "fields": {"ballot_submission": 11, "debate_team": 4, "speaker": 26, "score": 75.5, "position": 3}}, {"model": "results.speakerscore", "pk": 88, "fields": {"ballot_submission": 11, "debate_team": 4, "speaker": 25, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 89, "fields": {"ballot_submission": 12, "debate_team": 1, "speaker": 7, "score": 77.5, "position": 1}}, {"model": "results.speakerscore", "pk": 90, "fields": {"ballot_submission": 12, "debate_team": 1, "speaker": 8, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 91, "fields": {"ballot_submission": 12, "debate_team": 1, "speaker": 9, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 92, "fields": {"ballot_submission": 12, "debate_team": 1, "speaker": 7, "score": 37.75, "position": 4}}, {"model": "results.speakerscore", "pk": 93, "fields": {"ballot_submission": 12, "debate_team": 2, "speaker": 61, "score": 77.5, "position": 1}}, {"model": "results.speakerscore", "pk": 94, "fields": {"ballot_submission": 12, "debate_team": 2, "speaker": 63, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 95, "fields": {"ballot_submission": 12, "debate_team": 2, "speaker": 62, "score": 75.5, "position": 3}}, {"model": "results.speakerscore", "pk": 96, "fields": {"ballot_submission": 12, "debate_team": 2, "speaker": 61, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 97, "fields": {"ballot_submission": 13, "debate_team": 47, "speaker": 29, "score": 74.6666666666667, "position": 1}}, {"model": "results.speakerscore", "pk": 98, "fields": {"ballot_submission": 13, "debate_team": 47, "speaker": 28, "score": 76.3333333333333, "position": 2}}, {"model": "results.speakerscore", "pk": 99, "fields": {"ballot_submission": 13, "debate_team": 47, "speaker": 30, "score": 76.3333333333333, "position": 3}}, {"model": "results.speakerscore", "pk": 100, "fields": {"ballot_submission": 13, "debate_team": 47, "speaker": 29, "score": 36.6666666666667, "position": 4}}, {"model": "results.speakerscore", "pk": 101, "fields": {"ballot_submission": 13, "debate_team": 48, "speaker": 55, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 102, "fields": {"ballot_submission": 13, "debate_team": 48, "speaker": 57, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 103, "fields": {"ballot_submission": 13, "debate_team": 48, "speaker": 56, "score": 76.3333333333333, "position": 3}}, {"model": "results.speakerscore", "pk": 104, "fields": {"ballot_submission": 13, "debate_team": 48, "speaker": 55, "score": 37.8333333333333, "position": 4}}, {"model": "results.speakerscore", "pk": 105, "fields": {"ballot_submission": 14, "debate_team": 45, "speaker": 25, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 106, "fields": {"ballot_submission": 14, "debate_team": 45, "speaker": 27, "score": 78.0, "position": 2}}, {"model": "results.speakerscore", "pk": 107, "fields": {"ballot_submission": 14, "debate_team": 45, "speaker": 26, "score": 73.0, "position": 3}}, {"model": "results.speakerscore", "pk": 108, "fields": {"ballot_submission": 14, "debate_team": 45, "speaker": 25, "score": 38.5, "position": 4}}, {"model": "results.speakerscore", "pk": 109, "fields": {"ballot_submission": 14, "debate_team": 46, "speaker": 23, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 110, "fields": {"ballot_submission": 14, "debate_team": 46, "speaker": 24, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 111, "fields": {"ballot_submission": 14, "debate_team": 46, "speaker": 22, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 112, "fields": {"ballot_submission": 14, "debate_team": 46, "speaker": 23, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 113, "fields": {"ballot_submission": 15, "debate_team": 43, "speaker": 40, "score": 73.5, "position": 1}}, {"model": "results.speakerscore", "pk": 114, "fields": {"ballot_submission": 15, "debate_team": 43, "speaker": 41, "score": 72.5, "position": 2}}, {"model": "results.speakerscore", "pk": 115, "fields": {"ballot_submission": 15, "debate_team": 43, "speaker": 42, "score": 77.5, "position": 3}}, {"model": "results.speakerscore", "pk": 116, "fields": {"ballot_submission": 15, "debate_team": 43, "speaker": 40, "score": 37.75, "position": 4}}, {"model": "results.speakerscore", "pk": 117, "fields": {"ballot_submission": 15, "debate_team": 44, "speaker": 59, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 118, "fields": {"ballot_submission": 15, "debate_team": 44, "speaker": 58, "score": 74.5, "position": 2}}, {"model": "results.speakerscore", "pk": 119, "fields": {"ballot_submission": 15, "debate_team": 44, "speaker": 60, "score": 75.5, "position": 3}}, {"model": "results.speakerscore", "pk": 120, "fields": {"ballot_submission": 15, "debate_team": 44, "speaker": 59, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 121, "fields": {"ballot_submission": 16, "debate_team": 41, "speaker": 49, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 122, "fields": {"ballot_submission": 16, "debate_team": 41, "speaker": 50, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 123, "fields": {"ballot_submission": 16, "debate_team": 41, "speaker": 51, "score": 75.6666666666667, "position": 3}}, {"model": "results.speakerscore", "pk": 124, "fields": {"ballot_submission": 16, "debate_team": 41, "speaker": 49, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 125, "fields": {"ballot_submission": 16, "debate_team": 42, "speaker": 69, "score": 75.3333333333333, "position": 1}}, {"model": "results.speakerscore", "pk": 126, "fields": {"ballot_submission": 16, "debate_team": 42, "speaker": 68, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 127, "fields": {"ballot_submission": 16, "debate_team": 42, "speaker": 67, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 128, "fields": {"ballot_submission": 16, "debate_team": 42, "speaker": 69, "score": 37.3333333333333, "position": 4}}, {"model": "results.speakerscore", "pk": 129, "fields": {"ballot_submission": 17, "debate_team": 39, "speaker": 72, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 130, "fields": {"ballot_submission": 17, "debate_team": 39, "speaker": 71, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 131, "fields": {"ballot_submission": 17, "debate_team": 39, "speaker": 70, "score": 74.5, "position": 3}}, {"model": "results.speakerscore", "pk": 132, "fields": {"ballot_submission": 17, "debate_team": 39, "speaker": 72, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 133, "fields": {"ballot_submission": 17, "debate_team": 40, "speaker": 61, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 134, "fields": {"ballot_submission": 17, "debate_team": 40, "speaker": 63, "score": 75.5, "position": 2}}, {"model": "results.speakerscore", "pk": 135, "fields": {"ballot_submission": 17, "debate_team": 40, "speaker": 62, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 136, "fields": {"ballot_submission": 17, "debate_team": 40, "speaker": 61, "score": 36.5, "position": 4}}, {"model": "results.speakerscore", "pk": 137, "fields": {"ballot_submission": 18, "debate_team": 37, "speaker": 33, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 138, "fields": {"ballot_submission": 18, "debate_team": 37, "speaker": 31, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 139, "fields": {"ballot_submission": 18, "debate_team": 37, "speaker": 32, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 140, "fields": {"ballot_submission": 18, "debate_team": 37, "speaker": 33, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 141, "fields": {"ballot_submission": 18, "debate_team": 38, "speaker": 15, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 142, "fields": {"ballot_submission": 18, "debate_team": 38, "speaker": 13, "score": 72.0, "position": 2}}, {"model": "results.speakerscore", "pk": 143, "fields": {"ballot_submission": 18, "debate_team": 38, "speaker": 14, "score": 78.0, "position": 3}}, {"model": "results.speakerscore", "pk": 144, "fields": {"ballot_submission": 18, "debate_team": 38, "speaker": 15, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 145, "fields": {"ballot_submission": 19, "debate_team": 35, "speaker": 1, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 146, "fields": {"ballot_submission": 19, "debate_team": 35, "speaker": 3, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 147, "fields": {"ballot_submission": 19, "debate_team": 35, "speaker": 2, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 148, "fields": {"ballot_submission": 19, "debate_team": 35, "speaker": 1, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 149, "fields": {"ballot_submission": 19, "debate_team": 36, "speaker": 17, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 150, "fields": {"ballot_submission": 19, "debate_team": 36, "speaker": 16, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 151, "fields": {"ballot_submission": 19, "debate_team": 36, "speaker": 18, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 152, "fields": {"ballot_submission": 19, "debate_team": 36, "speaker": 17, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 153, "fields": {"ballot_submission": 20, "debate_team": 33, "speaker": 54, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 154, "fields": {"ballot_submission": 20, "debate_team": 33, "speaker": 53, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 155, "fields": {"ballot_submission": 20, "debate_team": 33, "speaker": 52, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 156, "fields": {"ballot_submission": 20, "debate_team": 33, "speaker": 54, "score": 36.0, "position": 4}}, {"model": "results.speakerscore", "pk": 157, "fields": {"ballot_submission": 20, "debate_team": 34, "speaker": 7, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 158, "fields": {"ballot_submission": 20, "debate_team": 34, "speaker": 8, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 159, "fields": {"ballot_submission": 20, "debate_team": 34, "speaker": 9, "score": 72.0, "position": 3}}, {"model": "results.speakerscore", "pk": 160, "fields": {"ballot_submission": 20, "debate_team": 34, "speaker": 7, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 161, "fields": {"ballot_submission": 21, "debate_team": 31, "speaker": 64, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 162, "fields": {"ballot_submission": 21, "debate_team": 31, "speaker": 66, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 163, "fields": {"ballot_submission": 21, "debate_team": 31, "speaker": 65, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 164, "fields": {"ballot_submission": 21, "debate_team": 31, "speaker": 64, "score": 36.5, "position": 4}}, {"model": "results.speakerscore", "pk": 165, "fields": {"ballot_submission": 21, "debate_team": 32, "speaker": 10, "score": 78.0, "position": 1}}, {"model": "results.speakerscore", "pk": 166, "fields": {"ballot_submission": 21, "debate_team": 32, "speaker": 11, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 167, "fields": {"ballot_submission": 21, "debate_team": 32, "speaker": 12, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 168, "fields": {"ballot_submission": 21, "debate_team": 32, "speaker": 10, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 169, "fields": {"ballot_submission": 22, "debate_team": 29, "speaker": 45, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 170, "fields": {"ballot_submission": 22, "debate_team": 29, "speaker": 44, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 171, "fields": {"ballot_submission": 22, "debate_team": 29, "speaker": 43, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 172, "fields": {"ballot_submission": 22, "debate_team": 29, "speaker": 45, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 173, "fields": {"ballot_submission": 22, "debate_team": 30, "speaker": 21, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 174, "fields": {"ballot_submission": 22, "debate_team": 30, "speaker": 20, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 175, "fields": {"ballot_submission": 22, "debate_team": 30, "speaker": 19, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 176, "fields": {"ballot_submission": 22, "debate_team": 30, "speaker": 21, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 177, "fields": {"ballot_submission": 23, "debate_team": 27, "speaker": 38, "score": 74.5, "position": 1}}, {"model": "results.speakerscore", "pk": 178, "fields": {"ballot_submission": 23, "debate_team": 27, "speaker": 37, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 179, "fields": {"ballot_submission": 23, "debate_team": 27, "speaker": 39, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 180, "fields": {"ballot_submission": 23, "debate_team": 27, "speaker": 38, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 181, "fields": {"ballot_submission": 23, "debate_team": 28, "speaker": 34, "score": 76.5, "position": 1}}, {"model": "results.speakerscore", "pk": 182, "fields": {"ballot_submission": 23, "debate_team": 28, "speaker": 35, "score": 74.5, "position": 2}}, {"model": "results.speakerscore", "pk": 183, "fields": {"ballot_submission": 23, "debate_team": 28, "speaker": 36, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 184, "fields": {"ballot_submission": 23, "debate_team": 28, "speaker": 34, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 185, "fields": {"ballot_submission": 24, "debate_team": 25, "speaker": 48, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 186, "fields": {"ballot_submission": 24, "debate_team": 25, "speaker": 46, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 187, "fields": {"ballot_submission": 24, "debate_team": 25, "speaker": 47, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 188, "fields": {"ballot_submission": 24, "debate_team": 25, "speaker": 48, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 189, "fields": {"ballot_submission": 24, "debate_team": 26, "speaker": 5, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 190, "fields": {"ballot_submission": 24, "debate_team": 26, "speaker": 4, "score": 72.0, "position": 2}}, {"model": "results.speakerscore", "pk": 191, "fields": {"ballot_submission": 24, "debate_team": 26, "speaker": 6, "score": 72.0, "position": 3}}, {"model": "results.speakerscore", "pk": 192, "fields": {"ballot_submission": 24, "debate_team": 26, "speaker": 5, "score": 36.5, "position": 4}}, {"model": "results.speakerscore", "pk": 193, "fields": {"ballot_submission": 25, "debate_team": 49, "speaker": 7, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 194, "fields": {"ballot_submission": 25, "debate_team": 49, "speaker": 8, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 195, "fields": {"ballot_submission": 25, "debate_team": 49, "speaker": 9, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 196, "fields": {"ballot_submission": 25, "debate_team": 49, "speaker": 7, "score": 38.5, "position": 4}}, {"model": "results.speakerscore", "pk": 197, "fields": {"ballot_submission": 25, "debate_team": 50, "speaker": 10, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 198, "fields": {"ballot_submission": 25, "debate_team": 50, "speaker": 11, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 199, "fields": {"ballot_submission": 25, "debate_team": 50, "speaker": 12, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 200, "fields": {"ballot_submission": 25, "debate_team": 50, "speaker": 10, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 201, "fields": {"ballot_submission": 26, "debate_team": 51, "speaker": 1, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 202, "fields": {"ballot_submission": 26, "debate_team": 51, "speaker": 3, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 203, "fields": {"ballot_submission": 26, "debate_team": 51, "speaker": 2, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 204, "fields": {"ballot_submission": 26, "debate_team": 51, "speaker": 1, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 205, "fields": {"ballot_submission": 26, "debate_team": 52, "speaker": 54, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 206, "fields": {"ballot_submission": 26, "debate_team": 52, "speaker": 53, "score": 72.0, "position": 2}}, {"model": "results.speakerscore", "pk": 207, "fields": {"ballot_submission": 26, "debate_team": 52, "speaker": 52, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 208, "fields": {"ballot_submission": 26, "debate_team": 52, "speaker": 54, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 209, "fields": {"ballot_submission": 27, "debate_team": 53, "speaker": 45, "score": 74.5, "position": 1}}, {"model": "results.speakerscore", "pk": 210, "fields": {"ballot_submission": 27, "debate_team": 53, "speaker": 44, "score": 73.5, "position": 2}}, {"model": "results.speakerscore", "pk": 211, "fields": {"ballot_submission": 27, "debate_team": 53, "speaker": 43, "score": 72.5, "position": 3}}, {"model": "results.speakerscore", "pk": 212, "fields": {"ballot_submission": 27, "debate_team": 53, "speaker": 45, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 213, "fields": {"ballot_submission": 27, "debate_team": 54, "speaker": 17, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 214, "fields": {"ballot_submission": 27, "debate_team": 54, "speaker": 16, "score": 77.5, "position": 2}}, {"model": "results.speakerscore", "pk": 215, "fields": {"ballot_submission": 27, "debate_team": 54, "speaker": 18, "score": 73.5, "position": 3}}, {"model": "results.speakerscore", "pk": 216, "fields": {"ballot_submission": 27, "debate_team": 54, "speaker": 17, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 217, "fields": {"ballot_submission": 28, "debate_team": 55, "speaker": 61, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 218, "fields": {"ballot_submission": 28, "debate_team": 55, "speaker": 63, "score": 73.5, "position": 2}}, {"model": "results.speakerscore", "pk": 219, "fields": {"ballot_submission": 28, "debate_team": 55, "speaker": 62, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 220, "fields": {"ballot_submission": 28, "debate_team": 55, "speaker": 61, "score": 36.25, "position": 4}}, {"model": "results.speakerscore", "pk": 221, "fields": {"ballot_submission": 28, "debate_team": 56, "speaker": 34, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 222, "fields": {"ballot_submission": 28, "debate_team": 56, "speaker": 35, "score": 75.5, "position": 2}}, {"model": "results.speakerscore", "pk": 223, "fields": {"ballot_submission": 28, "debate_team": 56, "speaker": 36, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 224, "fields": {"ballot_submission": 28, "debate_team": 56, "speaker": 34, "score": 36.5, "position": 4}}, {"model": "results.speakerscore", "pk": 225, "fields": {"ballot_submission": 29, "debate_team": 57, "speaker": 72, "score": 75.5, "position": 1}}, {"model": "results.speakerscore", "pk": 226, "fields": {"ballot_submission": 29, "debate_team": 57, "speaker": 71, "score": 72.5, "position": 2}}, {"model": "results.speakerscore", "pk": 227, "fields": {"ballot_submission": 29, "debate_team": 57, "speaker": 70, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 228, "fields": {"ballot_submission": 29, "debate_team": 57, "speaker": 72, "score": 38.25, "position": 4}}, {"model": "results.speakerscore", "pk": 229, "fields": {"ballot_submission": 29, "debate_team": 58, "speaker": 55, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 230, "fields": {"ballot_submission": 29, "debate_team": 58, "speaker": 57, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 231, "fields": {"ballot_submission": 29, "debate_team": 58, "speaker": 56, "score": 75.5, "position": 3}}, {"model": "results.speakerscore", "pk": 232, "fields": {"ballot_submission": 29, "debate_team": 58, "speaker": 55, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 233, "fields": {"ballot_submission": 30, "debate_team": 59, "speaker": 29, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 234, "fields": {"ballot_submission": 30, "debate_team": 59, "speaker": 28, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 235, "fields": {"ballot_submission": 30, "debate_team": 59, "speaker": 30, "score": 78.0, "position": 3}}, {"model": "results.speakerscore", "pk": 236, "fields": {"ballot_submission": 30, "debate_team": 59, "speaker": 29, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 237, "fields": {"ballot_submission": 30, "debate_team": 60, "speaker": 5, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 238, "fields": {"ballot_submission": 30, "debate_team": 60, "speaker": 4, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 239, "fields": {"ballot_submission": 30, "debate_team": 60, "speaker": 6, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 240, "fields": {"ballot_submission": 30, "debate_team": 60, "speaker": 5, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 241, "fields": {"ballot_submission": 31, "debate_team": 61, "speaker": 25, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 242, "fields": {"ballot_submission": 31, "debate_team": 61, "speaker": 27, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 243, "fields": {"ballot_submission": 31, "debate_team": 61, "speaker": 26, "score": 73.0, "position": 3}}, {"model": "results.speakerscore", "pk": 244, "fields": {"ballot_submission": 31, "debate_team": 61, "speaker": 25, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 245, "fields": {"ballot_submission": 31, "debate_team": 62, "speaker": 21, "score": 78.0, "position": 1}}, {"model": "results.speakerscore", "pk": 246, "fields": {"ballot_submission": 31, "debate_team": 62, "speaker": 20, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 247, "fields": {"ballot_submission": 31, "debate_team": 62, "speaker": 19, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 248, "fields": {"ballot_submission": 31, "debate_team": 62, "speaker": 21, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 249, "fields": {"ballot_submission": 32, "debate_team": 63, "speaker": 59, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 250, "fields": {"ballot_submission": 32, "debate_team": 63, "speaker": 58, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 251, "fields": {"ballot_submission": 32, "debate_team": 63, "speaker": 60, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 252, "fields": {"ballot_submission": 32, "debate_team": 63, "speaker": 59, "score": 36.5, "position": 4}}, {"model": "results.speakerscore", "pk": 253, "fields": {"ballot_submission": 32, "debate_team": 64, "speaker": 15, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 254, "fields": {"ballot_submission": 32, "debate_team": 64, "speaker": 13, "score": 72.0, "position": 2}}, {"model": "results.speakerscore", "pk": 255, "fields": {"ballot_submission": 32, "debate_team": 64, "speaker": 14, "score": 72.0, "position": 3}}, {"model": "results.speakerscore", "pk": 256, "fields": {"ballot_submission": 32, "debate_team": 64, "speaker": 15, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 257, "fields": {"ballot_submission": 33, "debate_team": 65, "speaker": 48, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 258, "fields": {"ballot_submission": 33, "debate_team": 65, "speaker": 46, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 259, "fields": {"ballot_submission": 33, "debate_team": 65, "speaker": 47, "score": 72.0, "position": 3}}, {"model": "results.speakerscore", "pk": 260, "fields": {"ballot_submission": 33, "debate_team": 65, "speaker": 48, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 261, "fields": {"ballot_submission": 33, "debate_team": 66, "speaker": 33, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 262, "fields": {"ballot_submission": 33, "debate_team": 66, "speaker": 31, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 263, "fields": {"ballot_submission": 33, "debate_team": 66, "speaker": 32, "score": 78.0, "position": 3}}, {"model": "results.speakerscore", "pk": 264, "fields": {"ballot_submission": 33, "debate_team": 66, "speaker": 33, "score": 37.0, "position": 4}}, {"model": "results.speakerscore", "pk": 265, "fields": {"ballot_submission": 34, "debate_team": 67, "speaker": 69, "score": 75.5, "position": 1}}, {"model": "results.speakerscore", "pk": 266, "fields": {"ballot_submission": 34, "debate_team": 67, "speaker": 68, "score": 76.5, "position": 2}}, {"model": "results.speakerscore", "pk": 267, "fields": {"ballot_submission": 34, "debate_team": 67, "speaker": 67, "score": 76.5, "position": 3}}, {"model": "results.speakerscore", "pk": 268, "fields": {"ballot_submission": 34, "debate_team": 67, "speaker": 69, "score": 38.25, "position": 4}}, {"model": "results.speakerscore", "pk": 269, "fields": {"ballot_submission": 34, "debate_team": 68, "speaker": 40, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 270, "fields": {"ballot_submission": 34, "debate_team": 68, "speaker": 41, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 271, "fields": {"ballot_submission": 34, "debate_team": 68, "speaker": 42, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 272, "fields": {"ballot_submission": 34, "debate_team": 68, "speaker": 40, "score": 36.0, "position": 4}}, {"model": "results.speakerscore", "pk": 273, "fields": {"ballot_submission": 35, "debate_team": 69, "speaker": 64, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 274, "fields": {"ballot_submission": 35, "debate_team": 69, "speaker": 66, "score": 76.5, "position": 2}}, {"model": "results.speakerscore", "pk": 275, "fields": {"ballot_submission": 35, "debate_team": 69, "speaker": 65, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 276, "fields": {"ballot_submission": 35, "debate_team": 69, "speaker": 64, "score": 36.0, "position": 4}}, {"model": "results.speakerscore", "pk": 277, "fields": {"ballot_submission": 35, "debate_team": 70, "speaker": 38, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 278, "fields": {"ballot_submission": 35, "debate_team": 70, "speaker": 37, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 279, "fields": {"ballot_submission": 35, "debate_team": 70, "speaker": 39, "score": 72.5, "position": 3}}, {"model": "results.speakerscore", "pk": 280, "fields": {"ballot_submission": 35, "debate_team": 70, "speaker": 38, "score": 36.75, "position": 4}}, {"model": "results.speakerscore", "pk": 281, "fields": {"ballot_submission": 36, "debate_team": 71, "speaker": 23, "score": 73.0, "position": 1}}, {"model": "results.speakerscore", "pk": 282, "fields": {"ballot_submission": 36, "debate_team": 71, "speaker": 24, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 283, "fields": {"ballot_submission": 36, "debate_team": 71, "speaker": 22, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 284, "fields": {"ballot_submission": 36, "debate_team": 71, "speaker": 23, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 285, "fields": {"ballot_submission": 36, "debate_team": 72, "speaker": 49, "score": 78.0, "position": 1}}, {"model": "results.speakerscore", "pk": 286, "fields": {"ballot_submission": 36, "debate_team": 72, "speaker": 50, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 287, "fields": {"ballot_submission": 36, "debate_team": 72, "speaker": 51, "score": 73.0, "position": 3}}, {"model": "results.speakerscore", "pk": 288, "fields": {"ballot_submission": 36, "debate_team": 72, "speaker": 49, "score": 36.5, "position": 4}}, {"model": "results.speakerscore", "pk": 289, "fields": {"ballot_submission": 37, "debate_team": 73, "speaker": 55, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 290, "fields": {"ballot_submission": 37, "debate_team": 73, "speaker": 57, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 291, "fields": {"ballot_submission": 37, "debate_team": 73, "speaker": 56, "score": 78.0, "position": 3}}, {"model": "results.speakerscore", "pk": 292, "fields": {"ballot_submission": 37, "debate_team": 73, "speaker": 55, "score": 36.0, "position": 4}}, {"model": "results.speakerscore", "pk": 293, "fields": {"ballot_submission": 37, "debate_team": 74, "speaker": 64, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 294, "fields": {"ballot_submission": 37, "debate_team": 74, "speaker": 66, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 295, "fields": {"ballot_submission": 37, "debate_team": 74, "speaker": 65, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 296, "fields": {"ballot_submission": 37, "debate_team": 74, "speaker": 64, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 297, "fields": {"ballot_submission": 38, "debate_team": 75, "speaker": 33, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 298, "fields": {"ballot_submission": 38, "debate_team": 75, "speaker": 31, "score": 72.0, "position": 2}}, {"model": "results.speakerscore", "pk": 299, "fields": {"ballot_submission": 38, "debate_team": 75, "speaker": 32, "score": 73.0, "position": 3}}, {"model": "results.speakerscore", "pk": 300, "fields": {"ballot_submission": 38, "debate_team": 75, "speaker": 33, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 301, "fields": {"ballot_submission": 38, "debate_team": 76, "speaker": 21, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 302, "fields": {"ballot_submission": 38, "debate_team": 76, "speaker": 20, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 303, "fields": {"ballot_submission": 38, "debate_team": 76, "speaker": 19, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 304, "fields": {"ballot_submission": 38, "debate_team": 76, "speaker": 21, "score": 39.0, "position": 4}}, {"model": "results.speakerscore", "pk": 305, "fields": {"ballot_submission": 39, "debate_team": 77, "speaker": 23, "score": 73.6666666666667, "position": 1}}, {"model": "results.speakerscore", "pk": 306, "fields": {"ballot_submission": 39, "debate_team": 77, "speaker": 24, "score": 73.3333333333333, "position": 2}}, {"model": "results.speakerscore", "pk": 307, "fields": {"ballot_submission": 39, "debate_team": 77, "speaker": 22, "score": 73.3333333333333, "position": 3}}, {"model": "results.speakerscore", "pk": 308, "fields": {"ballot_submission": 39, "debate_team": 77, "speaker": 23, "score": 36.1666666666667, "position": 4}}, {"model": "results.speakerscore", "pk": 309, "fields": {"ballot_submission": 39, "debate_team": 78, "speaker": 15, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 310, "fields": {"ballot_submission": 39, "debate_team": 78, "speaker": 13, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 311, "fields": {"ballot_submission": 39, "debate_team": 78, "speaker": 14, "score": 73.0, "position": 3}}, {"model": "results.speakerscore", "pk": 312, "fields": {"ballot_submission": 39, "debate_team": 78, "speaker": 15, "score": 36.5, "position": 4}}, {"model": "results.speakerscore", "pk": 313, "fields": {"ballot_submission": 40, "debate_team": 79, "speaker": 7, "score": 75.6666666666667, "position": 1}}, {"model": "results.speakerscore", "pk": 314, "fields": {"ballot_submission": 40, "debate_team": 79, "speaker": 8, "score": 73.3333333333333, "position": 2}}, {"model": "results.speakerscore", "pk": 315, "fields": {"ballot_submission": 40, "debate_team": 79, "speaker": 9, "score": 75.3333333333333, "position": 3}}, {"model": "results.speakerscore", "pk": 316, "fields": {"ballot_submission": 40, "debate_team": 79, "speaker": 7, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 317, "fields": {"ballot_submission": 40, "debate_team": 80, "speaker": 69, "score": 76.6666666666667, "position": 1}}, {"model": "results.speakerscore", "pk": 318, "fields": {"ballot_submission": 40, "debate_team": 80, "speaker": 68, "score": 74.3333333333333, "position": 2}}, {"model": "results.speakerscore", "pk": 319, "fields": {"ballot_submission": 40, "debate_team": 80, "speaker": 67, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 320, "fields": {"ballot_submission": 40, "debate_team": 80, "speaker": 69, "score": 38.1666666666667, "position": 4}}, {"model": "results.speakerscore", "pk": 321, "fields": {"ballot_submission": 41, "debate_team": 81, "speaker": 61, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 322, "fields": {"ballot_submission": 41, "debate_team": 81, "speaker": 63, "score": 73.5, "position": 2}}, {"model": "results.speakerscore", "pk": 323, "fields": {"ballot_submission": 41, "debate_team": 81, "speaker": 62, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 324, "fields": {"ballot_submission": 41, "debate_team": 81, "speaker": 61, "score": 37.75, "position": 4}}, {"model": "results.speakerscore", "pk": 325, "fields": {"ballot_submission": 41, "debate_team": 82, "speaker": 45, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 326, "fields": {"ballot_submission": 41, "debate_team": 82, "speaker": 44, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 327, "fields": {"ballot_submission": 41, "debate_team": 82, "speaker": 43, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 328, "fields": {"ballot_submission": 41, "debate_team": 82, "speaker": 45, "score": 38.5, "position": 4}}, {"model": "results.speakerscore", "pk": 329, "fields": {"ballot_submission": 42, "debate_team": 83, "speaker": 38, "score": 74.6666666666667, "position": 1}}, {"model": "results.speakerscore", "pk": 330, "fields": {"ballot_submission": 42, "debate_team": 83, "speaker": 37, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 331, "fields": {"ballot_submission": 42, "debate_team": 83, "speaker": 39, "score": 75.3333333333333, "position": 3}}, {"model": "results.speakerscore", "pk": 332, "fields": {"ballot_submission": 42, "debate_team": 83, "speaker": 38, "score": 37.6666666666667, "position": 4}}, {"model": "results.speakerscore", "pk": 333, "fields": {"ballot_submission": 42, "debate_team": 84, "speaker": 40, "score": 76.3333333333333, "position": 1}}, {"model": "results.speakerscore", "pk": 334, "fields": {"ballot_submission": 42, "debate_team": 84, "speaker": 41, "score": 74.3333333333333, "position": 2}}, {"model": "results.speakerscore", "pk": 335, "fields": {"ballot_submission": 42, "debate_team": 84, "speaker": 42, "score": 73.6666666666667, "position": 3}}, {"model": "results.speakerscore", "pk": 336, "fields": {"ballot_submission": 42, "debate_team": 84, "speaker": 40, "score": 37.1666666666667, "position": 4}}, {"model": "results.speakerscore", "pk": 337, "fields": {"ballot_submission": 43, "debate_team": 85, "speaker": 5, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 338, "fields": {"ballot_submission": 43, "debate_team": 85, "speaker": 4, "score": 76.3333333333333, "position": 2}}, {"model": "results.speakerscore", "pk": 339, "fields": {"ballot_submission": 43, "debate_team": 85, "speaker": 6, "score": 72.3333333333333, "position": 3}}, {"model": "results.speakerscore", "pk": 340, "fields": {"ballot_submission": 43, "debate_team": 85, "speaker": 5, "score": 36.8333333333333, "position": 4}}, {"model": "results.speakerscore", "pk": 341, "fields": {"ballot_submission": 43, "debate_team": 86, "speaker": 72, "score": 76.6666666666667, "position": 1}}, {"model": "results.speakerscore", "pk": 342, "fields": {"ballot_submission": 43, "debate_team": 86, "speaker": 71, "score": 75.6666666666667, "position": 2}}, {"model": "results.speakerscore", "pk": 343, "fields": {"ballot_submission": 43, "debate_team": 86, "speaker": 70, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 344, "fields": {"ballot_submission": 43, "debate_team": 86, "speaker": 72, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 345, "fields": {"ballot_submission": 44, "debate_team": 87, "speaker": 34, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 346, "fields": {"ballot_submission": 44, "debate_team": 87, "speaker": 35, "score": 77.0, "position": 2}}, {"model": "results.speakerscore", "pk": 347, "fields": {"ballot_submission": 44, "debate_team": 87, "speaker": 36, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 348, "fields": {"ballot_submission": 44, "debate_team": 87, "speaker": 34, "score": 38.5, "position": 4}}, {"model": "results.speakerscore", "pk": 349, "fields": {"ballot_submission": 44, "debate_team": 88, "speaker": 25, "score": 72.0, "position": 1}}, {"model": "results.speakerscore", "pk": 350, "fields": {"ballot_submission": 44, "debate_team": 88, "speaker": 27, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 351, "fields": {"ballot_submission": 44, "debate_team": 88, "speaker": 26, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 352, "fields": {"ballot_submission": 44, "debate_team": 88, "speaker": 25, "score": 36.5, "position": 4}}, {"model": "results.speakerscore", "pk": 353, "fields": {"ballot_submission": 45, "debate_team": 89, "speaker": 48, "score": 75.0, "position": 1}}, {"model": "results.speakerscore", "pk": 354, "fields": {"ballot_submission": 45, "debate_team": 89, "speaker": 46, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 355, "fields": {"ballot_submission": 45, "debate_team": 89, "speaker": 47, "score": 75.0, "position": 3}}, {"model": "results.speakerscore", "pk": 356, "fields": {"ballot_submission": 45, "debate_team": 89, "speaker": 48, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 357, "fields": {"ballot_submission": 45, "debate_team": 90, "speaker": 1, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 358, "fields": {"ballot_submission": 45, "debate_team": 90, "speaker": 3, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 359, "fields": {"ballot_submission": 45, "debate_team": 90, "speaker": 2, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 360, "fields": {"ballot_submission": 45, "debate_team": 90, "speaker": 1, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 361, "fields": {"ballot_submission": 46, "debate_team": 91, "speaker": 10, "score": 78.0, "position": 1}}, {"model": "results.speakerscore", "pk": 362, "fields": {"ballot_submission": 46, "debate_team": 91, "speaker": 11, "score": 75.0, "position": 2}}, {"model": "results.speakerscore", "pk": 363, "fields": {"ballot_submission": 46, "debate_team": 91, "speaker": 12, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 364, "fields": {"ballot_submission": 46, "debate_team": 91, "speaker": 10, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 365, "fields": {"ballot_submission": 46, "debate_team": 92, "speaker": 54, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 366, "fields": {"ballot_submission": 46, "debate_team": 92, "speaker": 53, "score": 78.0, "position": 2}}, {"model": "results.speakerscore", "pk": 367, "fields": {"ballot_submission": 46, "debate_team": 92, "speaker": 52, "score": 77.0, "position": 3}}, {"model": "results.speakerscore", "pk": 368, "fields": {"ballot_submission": 46, "debate_team": 92, "speaker": 54, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 369, "fields": {"ballot_submission": 47, "debate_team": 93, "speaker": 17, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 370, "fields": {"ballot_submission": 47, "debate_team": 93, "speaker": 16, "score": 73.0, "position": 2}}, {"model": "results.speakerscore", "pk": 371, "fields": {"ballot_submission": 47, "debate_team": 93, "speaker": 18, "score": 72.0, "position": 3}}, {"model": "results.speakerscore", "pk": 372, "fields": {"ballot_submission": 47, "debate_team": 93, "speaker": 17, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 373, "fields": {"ballot_submission": 47, "debate_team": 94, "speaker": 59, "score": 76.0, "position": 1}}, {"model": "results.speakerscore", "pk": 374, "fields": {"ballot_submission": 47, "debate_team": 94, "speaker": 58, "score": 76.0, "position": 2}}, {"model": "results.speakerscore", "pk": 375, "fields": {"ballot_submission": 47, "debate_team": 94, "speaker": 60, "score": 76.0, "position": 3}}, {"model": "results.speakerscore", "pk": 376, "fields": {"ballot_submission": 47, "debate_team": 94, "speaker": 59, "score": 38.0, "position": 4}}, {"model": "results.speakerscore", "pk": 377, "fields": {"ballot_submission": 48, "debate_team": 95, "speaker": 49, "score": 77.0, "position": 1}}, {"model": "results.speakerscore", "pk": 378, "fields": {"ballot_submission": 48, "debate_team": 95, "speaker": 50, "score": 78.0, "position": 2}}, {"model": "results.speakerscore", "pk": 379, "fields": {"ballot_submission": 48, "debate_team": 95, "speaker": 51, "score": 74.0, "position": 3}}, {"model": "results.speakerscore", "pk": 380, "fields": {"ballot_submission": 48, "debate_team": 95, "speaker": 49, "score": 37.5, "position": 4}}, {"model": "results.speakerscore", "pk": 381, "fields": {"ballot_submission": 48, "debate_team": 96, "speaker": 29, "score": 74.0, "position": 1}}, {"model": "results.speakerscore", "pk": 382, "fields": {"ballot_submission": 48, "debate_team": 96, "speaker": 28, "score": 74.0, "position": 2}}, {"model": "results.speakerscore", "pk": 383, "fields": {"ballot_submission": 48, "debate_team": 96, "speaker": 30, "score": 72.0, "position": 3}}, {"model": "results.speakerscore", "pk": 384, "fields": {"ballot_submission": 48, "debate_team": 96, "speaker": 29, "score": 38.5, "position": 4}}, {"model": "tournaments.tournament", "pk": 1, "fields": {"name": "demo", "short_name": "demo", "emoji": null, "seq": null, "slug": "demo", "current_round": 4, "welcome_msg": "", "active": true}}, {"model": "tournaments.round", "pk": 1, "fields": {"tournament": 1, "seq": 1, "name": "Round 1", "abbreviation": "R1", "draw_type": "R", "stage": "P", "break_category": null, "draw_status": "R", "feedback_weight": 0.7, "silent": false, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 2, "fields": {"tournament": 1, "seq": 2, "name": "Round 2", "abbreviation": "R2", "draw_type": "P", "stage": "P", "break_category": null, "draw_status": "R", "feedback_weight": 0.7, "silent": false, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 3, "fields": {"tournament": 1, "seq": 3, "name": "Round 3", "abbreviation": "R3", "draw_type": "P", "stage": "P", "break_category": null, "draw_status": "C", "feedback_weight": 0.7, "silent": false, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 4, "fields": {"tournament": 1, "seq": 4, "name": "Round 4", "abbreviation": "R4", "draw_type": "P", "stage": "P", "break_category": null, "draw_status": "C", "feedback_weight": 0.7, "silent": false, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 5, "fields": {"tournament": 1, "seq": 5, "name": "Open Quarterfinal", "abbreviation": "OQF", "draw_type": "F", "stage": "E", "break_category": 1, "draw_status": "N", "feedback_weight": 0.7, "silent": true, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 6, "fields": {"tournament": 1, "seq": 6, "name": "ESL Semifinal", "abbreviation": "SSF", "draw_type": "F", "stage": "E", "break_category": 2, "draw_status": "N", "feedback_weight": 0.7, "silent": true, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 7, "fields": {"tournament": 1, "seq": 7, "name": "Open Semifinal", "abbreviation": "OSF", "draw_type": "B", "stage": "E", "break_category": 1, "draw_status": "C", "feedback_weight": 0.7, "silent": true, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 8, "fields": {"tournament": 1, "seq": 8, "name": "ESL Grand Final", "abbreviation": "SGF", "draw_type": "B", "stage": "E", "break_category": 2, "draw_status": "N", "feedback_weight": 0.7, "silent": true, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 9, "fields": {"tournament": 1, "seq": 9, "name": "EFL Grand Final", "abbreviation": "FGF", "draw_type": "F", "stage": "E", "break_category": 3, "draw_status": "N", "feedback_weight": 0.7, "silent": true, "motions_released": false, "starts_at": null}}, {"model": "tournaments.round", "pk": 10, "fields": {"tournament": 1, "seq": 10, "name": "Open Grand Final", "abbreviation": "OGF", "draw_type": "B", "stage": "E", "break_category": 1, "draw_status": "N", "feedback_weight": 0.7, "silent": true, "motions_released": false, "starts_at": null}}, {"model": "venues.venuegroup", "pk": 1, "fields": {"name": "1", "short_name": "1", "team_capacity": null}}, {"model": "venues.venuegroup", "pk": 2, "fields": {"name": "2", "short_name": "2", "team_capacity": null}}, {"model": "venues.venuegroup", "pk": 3, "fields": {"name": "3", "short_name": "3", "team_capacity": null}}, {"model": "venues.venuegroup", "pk": 4, "fields": {"name": "4", "short_name": "4", "team_capacity": null}}, {"model": "venues.venuegroup", "pk": 5, "fields": {"name": "5", "short_name": "5", "team_capacity": null}}, {"model": "venues.venuegroup", "pk": 6, "fields": {"name": "6", "short_name": "6", "team_capacity": null}}, {"model": "venues.venuegroup", "pk": 7, "fields": {"name": "7", "short_name": "7", "team_capacity": null}}, {"model": "venues.venue", "pk": 1, "fields": {"name": "M04", "group": null, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 2, "fields": {"name": "M05", "group": 1, "priority": 10, "tournament": null}}, {"model": "venues.venue", "pk": 3, "fields": {"name": "M10", "group": 1, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 4, "fields": {"name": "M11", "group": 1, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 5, "fields": {"name": "G01", "group": 2, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 6, "fields": {"name": "G02", "group": 2, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 7, "fields": {"name": "G03", "group": 2, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 8, "fields": {"name": "G04", "group": 3, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 9, "fields": {"name": "G05", "group": 3, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 10, "fields": {"name": "G06", "group": 3, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 11, "fields": {"name": "G07", "group": null, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 12, "fields": {"name": "G08", "group": 3, "priority": 10, "tournament": 1}}, {"model": "venues.venue", "pk": 13, "fields": {"name": "K03", "group": 4, "priority": 20, "tournament": 1}}, {"model": "venues.venue", "pk": 14, "fields": {"name": "K04", "group": 4, "priority": 20, "tournament": 1}}, {"model": "venues.venue", "pk": 15, "fields": {"name": "K05", "group": 4, "priority": 20, "tournament": 1}}, {"model": "venues.venue", "pk": 16, "fields": {"name": "K06", "group": null, "priority": 20, "tournament": 1}}, {"model": "venues.venue", "pk": 17, "fields": {"name": "K08", "group": 4, "priority": 20, "tournament": 1}}, {"model": "venues.venue", "pk": 18, "fields": {"name": "P01", "group": 5, "priority": 30, "tournament": 1}}, {"model": "venues.venue", "pk": 19, "fields": {"name": "P03", "group": 5, "priority": 30, "tournament": 1}}, {"model": "venues.venue", "pk": 20, "fields": {"name": "P05", "group": 6, "priority": 30, "tournament": 1}}, {"model": "venues.venue", "pk": 21, "fields": {"name": "P07", "group": 6, "priority": 30, "tournament": 1}}, {"model": "venues.venue", "pk": 22, "fields": {"name": "Z09", "group": 7, "priority": 40, "tournament": 1}}, {"model": "venues.venue", "pk": 23, "fields": {"name": "Z10", "group": null, "priority": 40, "tournament": 1}}, {"model": "venues.venue", "pk": 24, "fields": {"name": "Shared 140", "group": null, "priority": 200, "tournament": 1}}, {"model": "venues.venue", "pk": 25, "fields": {"name": "Shared 2.9.0", "group": null, "priority": 100, "tournament": 1}}, {"model": "venues.venue", "pk": 26, "fields": {"name": "Black 11G", "group": null, "priority": 50, "tournament": 1}}, {"model": "venues.venue", "pk": 27, "fields": {"name": "Test", "group": null, "priority": 55, "tournament": 1}}, {"model": "venues.venue", "pk": 28, "fields": {"name": "Test2SSS", "group": null, "priority": 155, "tournament": null}}, {"model": "venues.venue", "pk": 29, "fields": {"name": "Test3SSS", "group": null, "priority": 200, "tournament": null}}, {"model": "auth.permission", "pk": 1, "fields": {"name": "Can add bookmark", "content_type": 1, "codename": "add_bookmark"}}, {"model": "auth.permission", "pk": 2, "fields": {"name": "Can change bookmark", "content_type": 1, "codename": "change_bookmark"}}, {"model": "auth.permission", "pk": 3, "fields": {"name": "Can delete bookmark", "content_type": 1, "codename": "delete_bookmark"}}, {"model": "auth.permission", "pk": 4, "fields": {"name": "Can add pinned application", "content_type": 2, "codename": "add_pinnedapplication"}}, {"model": "auth.permission", "pk": 5, "fields": {"name": "Can change pinned application", "content_type": 2, "codename": "change_pinnedapplication"}}, {"model": "auth.permission", "pk": 6, "fields": {"name": "Can delete pinned application", "content_type": 2, "codename": "delete_pinnedapplication"}}, {"model": "auth.permission", "pk": 7, "fields": {"name": "Can add log entry", "content_type": 3, "codename": "add_logentry"}}, {"model": "auth.permission", "pk": 8, "fields": {"name": "Can change log entry", "content_type": 3, "codename": "change_logentry"}}, {"model": "auth.permission", "pk": 9, "fields": {"name": "Can delete log entry", "content_type": 3, "codename": "delete_logentry"}}, {"model": "auth.permission", "pk": 10, "fields": {"name": "Can add permission", "content_type": 4, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 11, "fields": {"name": "Can change permission", "content_type": 4, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 12, "fields": {"name": "Can delete permission", "content_type": 4, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 13, "fields": {"name": "Can add group", "content_type": 5, "codename": "add_group"}}, {"model": "auth.permission", "pk": 14, "fields": {"name": "Can change group", "content_type": 5, "codename": "change_group"}}, {"model": "auth.permission", "pk": 15, "fields": {"name": "Can delete group", "content_type": 5, "codename": "delete_group"}}, {"model": "auth.permission", "pk": 16, "fields": {"name": "Can add user", "content_type": 6, "codename": "add_user"}}, {"model": "auth.permission", "pk": 17, "fields": {"name": "Can change user", "content_type": 6, "codename": "change_user"}}, {"model": "auth.permission", "pk": 18, "fields": {"name": "Can delete user", "content_type": 6, "codename": "delete_user"}}, {"model": "auth.permission", "pk": 19, "fields": {"name": "Can add content type", "content_type": 7, "codename": "add_contenttype"}}, {"model": "auth.permission", "pk": 20, "fields": {"name": "Can change content type", "content_type": 7, "codename": "change_contenttype"}}, {"model": "auth.permission", "pk": 21, "fields": {"name": "Can delete content type", "content_type": 7, "codename": "delete_contenttype"}}, {"model": "auth.permission", "pk": 22, "fields": {"name": "Can add session", "content_type": 8, "codename": "add_session"}}, {"model": "auth.permission", "pk": 23, "fields": {"name": "Can change session", "content_type": 8, "codename": "change_session"}}, {"model": "auth.permission", "pk": 24, "fields": {"name": "Can delete session", "content_type": 8, "codename": "delete_session"}}, {"model": "auth.permission", "pk": 25, "fields": {"name": "Can add action log entry", "content_type": 9, "codename": "add_actionlogentry"}}, {"model": "auth.permission", "pk": 26, "fields": {"name": "Can change action log entry", "content_type": 9, "codename": "change_actionlogentry"}}, {"model": "auth.permission", "pk": 27, "fields": {"name": "Can delete action log entry", "content_type": 9, "codename": "delete_actionlogentry"}}, {"model": "auth.permission", "pk": 28, "fields": {"name": "Can add debate adjudicator", "content_type": 10, "codename": "add_debateadjudicator"}}, {"model": "auth.permission", "pk": 29, "fields": {"name": "Can change debate adjudicator", "content_type": 10, "codename": "change_debateadjudicator"}}, {"model": "auth.permission", "pk": 30, "fields": {"name": "Can delete debate adjudicator", "content_type": 10, "codename": "delete_debateadjudicator"}}, {"model": "auth.permission", "pk": 31, "fields": {"name": "Can add adjudicator-team conflict", "content_type": 11, "codename": "add_adjudicatorconflict"}}, {"model": "auth.permission", "pk": 32, "fields": {"name": "Can change adjudicator-team conflict", "content_type": 11, "codename": "change_adjudicatorconflict"}}, {"model": "auth.permission", "pk": 33, "fields": {"name": "Can delete adjudicator-team conflict", "content_type": 11, "codename": "delete_adjudicatorconflict"}}, {"model": "auth.permission", "pk": 34, "fields": {"name": "Can add adjudicator-adjudicator conflict", "content_type": 12, "codename": "add_adjudicatoradjudicatorconflict"}}, {"model": "auth.permission", "pk": 35, "fields": {"name": "Can change adjudicator-adjudicator conflict", "content_type": 12, "codename": "change_adjudicatoradjudicatorconflict"}}, {"model": "auth.permission", "pk": 36, "fields": {"name": "Can delete adjudicator-adjudicator conflict", "content_type": 12, "codename": "delete_adjudicatoradjudicatorconflict"}}, {"model": "auth.permission", "pk": 37, "fields": {"name": "Can add adjudicator-institution conflict", "content_type": 13, "codename": "add_adjudicatorinstitutionconflict"}}, {"model": "auth.permission", "pk": 38, "fields": {"name": "Can change adjudicator-institution conflict", "content_type": 13, "codename": "change_adjudicatorinstitutionconflict"}}, {"model": "auth.permission", "pk": 39, "fields": {"name": "Can delete adjudicator-institution conflict", "content_type": 13, "codename": "delete_adjudicatorinstitutionconflict"}}, {"model": "auth.permission", "pk": 40, "fields": {"name": "Can add adjudicator test score history", "content_type": 14, "codename": "add_adjudicatortestscorehistory"}}, {"model": "auth.permission", "pk": 41, "fields": {"name": "Can change adjudicator test score history", "content_type": 14, "codename": "change_adjudicatortestscorehistory"}}, {"model": "auth.permission", "pk": 42, "fields": {"name": "Can delete adjudicator test score history", "content_type": 14, "codename": "delete_adjudicatortestscorehistory"}}, {"model": "auth.permission", "pk": 43, "fields": {"name": "Can add adjudicator feedback boolean answer", "content_type": 15, "codename": "add_adjudicatorfeedbackbooleananswer"}}, {"model": "auth.permission", "pk": 44, "fields": {"name": "Can change adjudicator feedback boolean answer", "content_type": 15, "codename": "change_adjudicatorfeedbackbooleananswer"}}, {"model": "auth.permission", "pk": 45, "fields": {"name": "Can delete adjudicator feedback boolean answer", "content_type": 15, "codename": "delete_adjudicatorfeedbackbooleananswer"}}, {"model": "auth.permission", "pk": 46, "fields": {"name": "Can add adjudicator feedback integer answer", "content_type": 16, "codename": "add_adjudicatorfeedbackintegeranswer"}}, {"model": "auth.permission", "pk": 47, "fields": {"name": "Can change adjudicator feedback integer answer", "content_type": 16, "codename": "change_adjudicatorfeedbackintegeranswer"}}, {"model": "auth.permission", "pk": 48, "fields": {"name": "Can delete adjudicator feedback integer answer", "content_type": 16, "codename": "delete_adjudicatorfeedbackintegeranswer"}}, {"model": "auth.permission", "pk": 49, "fields": {"name": "Can add adjudicator feedback float answer", "content_type": 17, "codename": "add_adjudicatorfeedbackfloatanswer"}}, {"model": "auth.permission", "pk": 50, "fields": {"name": "Can change adjudicator feedback float answer", "content_type": 17, "codename": "change_adjudicatorfeedbackfloatanswer"}}, {"model": "auth.permission", "pk": 51, "fields": {"name": "Can delete adjudicator feedback float answer", "content_type": 17, "codename": "delete_adjudicatorfeedbackfloatanswer"}}, {"model": "auth.permission", "pk": 52, "fields": {"name": "Can add adjudicator feedback string answer", "content_type": 18, "codename": "add_adjudicatorfeedbackstringanswer"}}, {"model": "auth.permission", "pk": 53, "fields": {"name": "Can change adjudicator feedback string answer", "content_type": 18, "codename": "change_adjudicatorfeedbackstringanswer"}}, {"model": "auth.permission", "pk": 54, "fields": {"name": "Can delete adjudicator feedback string answer", "content_type": 18, "codename": "delete_adjudicatorfeedbackstringanswer"}}, {"model": "auth.permission", "pk": 55, "fields": {"name": "Can add adjudicator feedback question", "content_type": 19, "codename": "add_adjudicatorfeedbackquestion"}}, {"model": "auth.permission", "pk": 56, "fields": {"name": "Can change adjudicator feedback question", "content_type": 19, "codename": "change_adjudicatorfeedbackquestion"}}, {"model": "auth.permission", "pk": 57, "fields": {"name": "Can delete adjudicator feedback question", "content_type": 19, "codename": "delete_adjudicatorfeedbackquestion"}}, {"model": "auth.permission", "pk": 58, "fields": {"name": "Can add adjudicator feedback", "content_type": 20, "codename": "add_adjudicatorfeedback"}}, {"model": "auth.permission", "pk": 59, "fields": {"name": "Can change adjudicator feedback", "content_type": 20, "codename": "change_adjudicatorfeedback"}}, {"model": "auth.permission", "pk": 60, "fields": {"name": "Can delete adjudicator feedback", "content_type": 20, "codename": "delete_adjudicatorfeedback"}}, {"model": "auth.permission", "pk": 61, "fields": {"name": "Can add checkin", "content_type": 21, "codename": "add_checkin"}}, {"model": "auth.permission", "pk": 62, "fields": {"name": "Can change checkin", "content_type": 21, "codename": "change_checkin"}}, {"model": "auth.permission", "pk": 63, "fields": {"name": "Can delete checkin", "content_type": 21, "codename": "delete_checkin"}}, {"model": "auth.permission", "pk": 64, "fields": {"name": "Can add active venue", "content_type": 22, "codename": "add_activevenue"}}, {"model": "auth.permission", "pk": 65, "fields": {"name": "Can change active venue", "content_type": 22, "codename": "change_activevenue"}}, {"model": "auth.permission", "pk": 66, "fields": {"name": "Can delete active venue", "content_type": 22, "codename": "delete_activevenue"}}, {"model": "auth.permission", "pk": 67, "fields": {"name": "Can add active team", "content_type": 23, "codename": "add_activeteam"}}, {"model": "auth.permission", "pk": 68, "fields": {"name": "Can change active team", "content_type": 23, "codename": "change_activeteam"}}, {"model": "auth.permission", "pk": 69, "fields": {"name": "Can delete active team", "content_type": 23, "codename": "delete_activeteam"}}, {"model": "auth.permission", "pk": 70, "fields": {"name": "Can add active adjudicator", "content_type": 24, "codename": "add_activeadjudicator"}}, {"model": "auth.permission", "pk": 71, "fields": {"name": "Can change active adjudicator", "content_type": 24, "codename": "change_activeadjudicator"}}, {"model": "auth.permission", "pk": 72, "fields": {"name": "Can delete active adjudicator", "content_type": 24, "codename": "delete_activeadjudicator"}}, {"model": "auth.permission", "pk": 73, "fields": {"name": "Can add break category", "content_type": 25, "codename": "add_breakcategory"}}, {"model": "auth.permission", "pk": 74, "fields": {"name": "Can change break category", "content_type": 25, "codename": "change_breakcategory"}}, {"model": "auth.permission", "pk": 75, "fields": {"name": "Can delete break category", "content_type": 25, "codename": "delete_breakcategory"}}, {"model": "auth.permission", "pk": 76, "fields": {"name": "Can add breaking team", "content_type": 26, "codename": "add_breakingteam"}}, {"model": "auth.permission", "pk": 77, "fields": {"name": "Can change breaking team", "content_type": 26, "codename": "change_breakingteam"}}, {"model": "auth.permission", "pk": 78, "fields": {"name": "Can delete breaking team", "content_type": 26, "codename": "delete_breakingteam"}}, {"model": "auth.permission", "pk": 79, "fields": {"name": "Can add division", "content_type": 27, "codename": "add_division"}}, {"model": "auth.permission", "pk": 80, "fields": {"name": "Can change division", "content_type": 27, "codename": "change_division"}}, {"model": "auth.permission", "pk": 81, "fields": {"name": "Can delete division", "content_type": 27, "codename": "delete_division"}}, {"model": "auth.permission", "pk": 82, "fields": {"name": "Can add debate", "content_type": 28, "codename": "add_debate"}}, {"model": "auth.permission", "pk": 83, "fields": {"name": "Can change debate", "content_type": 28, "codename": "change_debate"}}, {"model": "auth.permission", "pk": 84, "fields": {"name": "Can delete debate", "content_type": 28, "codename": "delete_debate"}}, {"model": "auth.permission", "pk": 85, "fields": {"name": "Can add debate team", "content_type": 29, "codename": "add_debateteam"}}, {"model": "auth.permission", "pk": 86, "fields": {"name": "Can change debate team", "content_type": 29, "codename": "change_debateteam"}}, {"model": "auth.permission", "pk": 87, "fields": {"name": "Can delete debate team", "content_type": 29, "codename": "delete_debateteam"}}, {"model": "auth.permission", "pk": 88, "fields": {"name": "Can add team position allocation", "content_type": 30, "codename": "add_teampositionallocation"}}, {"model": "auth.permission", "pk": 89, "fields": {"name": "Can change team position allocation", "content_type": 30, "codename": "change_teampositionallocation"}}, {"model": "auth.permission", "pk": 90, "fields": {"name": "Can delete team position allocation", "content_type": 30, "codename": "delete_teampositionallocation"}}, {"model": "auth.permission", "pk": 91, "fields": {"name": "Can add motion", "content_type": 31, "codename": "add_motion"}}, {"model": "auth.permission", "pk": 92, "fields": {"name": "Can change motion", "content_type": 31, "codename": "change_motion"}}, {"model": "auth.permission", "pk": 93, "fields": {"name": "Can delete motion", "content_type": 31, "codename": "delete_motion"}}, {"model": "auth.permission", "pk": 94, "fields": {"name": "Can add debate team motion preference", "content_type": 32, "codename": "add_debateteammotionpreference"}}, {"model": "auth.permission", "pk": 95, "fields": {"name": "Can change debate team motion preference", "content_type": 32, "codename": "change_debateteammotionpreference"}}, {"model": "auth.permission", "pk": 96, "fields": {"name": "Can delete debate team motion preference", "content_type": 32, "codename": "delete_debateteammotionpreference"}}, {"model": "auth.permission", "pk": 97, "fields": {"name": "Can add tournament preference", "content_type": 33, "codename": "add_tournamentpreferencemodel"}}, {"model": "auth.permission", "pk": 98, "fields": {"name": "Can change tournament preference", "content_type": 33, "codename": "change_tournamentpreferencemodel"}}, {"model": "auth.permission", "pk": 99, "fields": {"name": "Can delete tournament preference", "content_type": 33, "codename": "delete_tournamentpreferencemodel"}}, {"model": "auth.permission", "pk": 100, "fields": {"name": "Can add region", "content_type": 34, "codename": "add_region"}}, {"model": "auth.permission", "pk": 101, "fields": {"name": "Can change region", "content_type": 34, "codename": "change_region"}}, {"model": "auth.permission", "pk": 102, "fields": {"name": "Can delete region", "content_type": 34, "codename": "delete_region"}}, {"model": "auth.permission", "pk": 103, "fields": {"name": "Can add institution", "content_type": 35, "codename": "add_institution"}}, {"model": "auth.permission", "pk": 104, "fields": {"name": "Can change institution", "content_type": 35, "codename": "change_institution"}}, {"model": "auth.permission", "pk": 105, "fields": {"name": "Can delete institution", "content_type": 35, "codename": "delete_institution"}}, {"model": "auth.permission", "pk": 106, "fields": {"name": "Can add person", "content_type": 36, "codename": "add_person"}}, {"model": "auth.permission", "pk": 107, "fields": {"name": "Can change person", "content_type": 36, "codename": "change_person"}}, {"model": "auth.permission", "pk": 108, "fields": {"name": "Can delete person", "content_type": 36, "codename": "delete_person"}}, {"model": "auth.permission", "pk": 109, "fields": {"name": "Can add team", "content_type": 37, "codename": "add_team"}}, {"model": "auth.permission", "pk": 110, "fields": {"name": "Can change team", "content_type": 37, "codename": "change_team"}}, {"model": "auth.permission", "pk": 111, "fields": {"name": "Can delete team", "content_type": 37, "codename": "delete_team"}}, {"model": "auth.permission", "pk": 112, "fields": {"name": "Can add speaker", "content_type": 38, "codename": "add_speaker"}}, {"model": "auth.permission", "pk": 113, "fields": {"name": "Can change speaker", "content_type": 38, "codename": "change_speaker"}}, {"model": "auth.permission", "pk": 114, "fields": {"name": "Can delete speaker", "content_type": 38, "codename": "delete_speaker"}}, {"model": "auth.permission", "pk": 115, "fields": {"name": "Can add adjudicator", "content_type": 39, "codename": "add_adjudicator"}}, {"model": "auth.permission", "pk": 116, "fields": {"name": "Can change adjudicator", "content_type": 39, "codename": "change_adjudicator"}}, {"model": "auth.permission", "pk": 117, "fields": {"name": "Can delete adjudicator", "content_type": 39, "codename": "delete_adjudicator"}}, {"model": "auth.permission", "pk": 118, "fields": {"name": "Can add ballot submission", "content_type": 40, "codename": "add_ballotsubmission"}}, {"model": "auth.permission", "pk": 119, "fields": {"name": "Can change ballot submission", "content_type": 40, "codename": "change_ballotsubmission"}}, {"model": "auth.permission", "pk": 120, "fields": {"name": "Can delete ballot submission", "content_type": 40, "codename": "delete_ballotsubmission"}}, {"model": "auth.permission", "pk": 121, "fields": {"name": "Can add speaker score by adj", "content_type": 41, "codename": "add_speakerscorebyadj"}}, {"model": "auth.permission", "pk": 122, "fields": {"name": "Can change speaker score by adj", "content_type": 41, "codename": "change_speakerscorebyadj"}}, {"model": "auth.permission", "pk": 123, "fields": {"name": "Can delete speaker score by adj", "content_type": 41, "codename": "delete_speakerscorebyadj"}}, {"model": "auth.permission", "pk": 124, "fields": {"name": "Can add team score", "content_type": 42, "codename": "add_teamscore"}}, {"model": "auth.permission", "pk": 125, "fields": {"name": "Can change team score", "content_type": 42, "codename": "change_teamscore"}}, {"model": "auth.permission", "pk": 126, "fields": {"name": "Can delete team score", "content_type": 42, "codename": "delete_teamscore"}}, {"model": "auth.permission", "pk": 127, "fields": {"name": "Can add speaker score", "content_type": 43, "codename": "add_speakerscore"}}, {"model": "auth.permission", "pk": 128, "fields": {"name": "Can change speaker score", "content_type": 43, "codename": "change_speakerscore"}}, {"model": "auth.permission", "pk": 129, "fields": {"name": "Can delete speaker score", "content_type": 43, "codename": "delete_speakerscore"}}, {"model": "auth.permission", "pk": 130, "fields": {"name": "Can add tournament", "content_type": 44, "codename": "add_tournament"}}, {"model": "auth.permission", "pk": 131, "fields": {"name": "Can change tournament", "content_type": 44, "codename": "change_tournament"}}, {"model": "auth.permission", "pk": 132, "fields": {"name": "Can delete tournament", "content_type": 44, "codename": "delete_tournament"}}, {"model": "auth.permission", "pk": 133, "fields": {"name": "Can add round", "content_type": 45, "codename": "add_round"}}, {"model": "auth.permission", "pk": 134, "fields": {"name": "Can change round", "content_type": 45, "codename": "change_round"}}, {"model": "auth.permission", "pk": 135, "fields": {"name": "Can delete round", "content_type": 45, "codename": "delete_round"}}, {"model": "auth.permission", "pk": 136, "fields": {"name": "Can add venue group", "content_type": 46, "codename": "add_venuegroup"}}, {"model": "auth.permission", "pk": 137, "fields": {"name": "Can change venue group", "content_type": 46, "codename": "change_venuegroup"}}, {"model": "auth.permission", "pk": 138, "fields": {"name": "Can delete venue group", "content_type": 46, "codename": "delete_venuegroup"}}, {"model": "auth.permission", "pk": 139, "fields": {"name": "Can add venue", "content_type": 47, "codename": "add_venue"}}, {"model": "auth.permission", "pk": 140, "fields": {"name": "Can change venue", "content_type": 47, "codename": "change_venue"}}, {"model": "auth.permission", "pk": 141, "fields": {"name": "Can delete venue", "content_type": 47, "codename": "delete_venue"}}, {"model": "auth.permission", "pk": 142, "fields": {"name": "Can add team venue constraint", "content_type": 48, "codename": "add_teamvenueconstraint"}}, {"model": "auth.permission", "pk": 143, "fields": {"name": "Can change team venue constraint", "content_type": 48, "codename": "change_teamvenueconstraint"}}, {"model": "auth.permission", "pk": 144, "fields": {"name": "Can delete team venue constraint", "content_type": 48, "codename": "delete_teamvenueconstraint"}}, {"model": "auth.permission", "pk": 145, "fields": {"name": "Can add adjudicator venue constraint", "content_type": 49, "codename": "add_adjudicatorvenueconstraint"}}, {"model": "auth.permission", "pk": 146, "fields": {"name": "Can change adjudicator venue constraint", "content_type": 49, "codename": "change_adjudicatorvenueconstraint"}}, {"model": "auth.permission", "pk": 147, "fields": {"name": "Can delete adjudicator venue constraint", "content_type": 49, "codename": "delete_adjudicatorvenueconstraint"}}, {"model": "auth.permission", "pk": 148, "fields": {"name": "Can add institution venue constraint", "content_type": 50, "codename": "add_institutionvenueconstraint"}}, {"model": "auth.permission", "pk": 149, "fields": {"name": "Can change institution venue constraint", "content_type": 50, "codename": "change_institutionvenueconstraint"}}, {"model": "auth.permission", "pk": 150, "fields": {"name": "Can delete institution venue constraint", "content_type": 50, "codename": "delete_institutionvenueconstraint"}}, {"model": "auth.permission", "pk": 151, "fields": {"name": "Can add division venue constraint", "content_type": 51, "codename": "add_divisionvenueconstraint"}}, {"model": "auth.permission", "pk": 152, "fields": {"name": "Can change division venue constraint", "content_type": 51, "codename": "change_divisionvenueconstraint"}}, {"model": "auth.permission", "pk": 153, "fields": {"name": "Can delete division venue constraint", "content_type": 51, "codename": "delete_divisionvenueconstraint"}}, {"model": "auth.permission", "pk": 154, "fields": {"name": "Can add global preference", "content_type": 52, "codename": "add_globalpreferencemodel"}}, {"model": "auth.permission", "pk": 155, "fields": {"name": "Can change global preference", "content_type": 52, "codename": "change_globalpreferencemodel"}}, {"model": "auth.permission", "pk": 156, "fields": {"name": "Can delete global preference", "content_type": 52, "codename": "delete_globalpreferencemodel"}}, {"model": "auth.permission", "pk": 157, "fields": {"name": "Can add user preference", "content_type": 53, "codename": "add_userpreferencemodel"}}, {"model": "auth.permission", "pk": 158, "fields": {"name": "Can change user preference", "content_type": 53, "codename": "change_userpreferencemodel"}}, {"model": "auth.permission", "pk": 159, "fields": {"name": "Can delete user preference", "content_type": 53, "codename": "delete_userpreferencemodel"}}, {"model": "auth.permission", "pk": 160, "fields": {"name": "Can add global preference", "content_type": 50, "codename": "add_globalpreferencemodel"}}, {"model": "auth.permission", "pk": 161, "fields": {"name": "Can change global preference", "content_type": 50, "codename": "change_globalpreferencemodel"}}, {"model": "auth.permission", "pk": 162, "fields": {"name": "Can delete global preference", "content_type": 50, "codename": "delete_globalpreferencemodel"}}, {"model": "auth.permission", "pk": 163, "fields": {"name": "Can add user preference", "content_type": 51, "codename": "add_userpreferencemodel"}}, {"model": "auth.permission", "pk": 164, "fields": {"name": "Can change user preference", "content_type": 51, "codename": "change_userpreferencemodel"}}, {"model": "auth.permission", "pk": 165, "fields": {"name": "Can delete user preference", "content_type": 51, "codename": "delete_userpreferencemodel"}}, {"model": "auth.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$24000$ZU59rBpnLzvD$g1h4H9wZ6a9Hgn0F3WwQNFC9RfZUH7omgeCvxqCdD7E=", "last_login": "2016-05-16T13:49:56.575", "is_superuser": true, "username": "admin", "first_name": "", "last_name": "", "email": "", "is_staff": true, "is_active": true, "date_joined": "2016-04-14T13:17:48.740", "groups": [], "user_permissions": []}}, {"model": "actionlog.actionlogentry", "pk": 1, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T13:21:06.434", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 1, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 2, "fields": {"type": "dr.conf", "timestamp": "2016-04-14T13:21:10.527", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 1, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 3, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T13:21:51.229", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 2, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 4, "fields": {"type": "dr.conf", "timestamp": "2016-04-14T13:21:55.770", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 2, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 5, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T13:22:30.913", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 3, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 6, "fields": {"type": "dr.conf", "timestamp": "2016-04-14T13:22:39.537", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 3, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 7, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T13:24:55.099", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 4, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 8, "fields": {"type": "dr.conf", "timestamp": "2016-04-14T13:25:00.527", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 4, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 9, "fields": {"type": "br.gene", "timestamp": "2016-04-14T13:27:00.966", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 10, "fields": {"type": "br.el.edit", "timestamp": "2016-04-14T13:38:03.231", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 11, "fields": {"type": "br.el.edit", "timestamp": "2016-04-14T13:39:08.781", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 12, "fields": {"type": "br.el.edit", "timestamp": "2016-04-14T13:39:18.554", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 13, "fields": {"type": "br.gene", "timestamp": "2016-04-14T13:53:07.351", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 14, "fields": {"type": "av.aj.save", "timestamp": "2016-04-14T13:56:01.510", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 15, "fields": {"type": "av.aj.save", "timestamp": "2016-04-14T16:29:11.100", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 16, "fields": {"type": "av.aj.save", "timestamp": "2016-04-14T16:38:46.302", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 17, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T17:22:18.358", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 18, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T17:43:52.159", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 19, "fields": {"type": "dr.conf", "timestamp": "2016-04-14T18:01:43.200", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 20, "fields": {"type": "av.tm.save", "timestamp": "2016-04-14T18:03:34.016", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 6, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 21, "fields": {"type": "br.rm.edit", "timestamp": "2016-04-14T18:04:43.998", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 22, "fields": {"type": "br.rm.edit", "timestamp": "2016-04-14T18:04:48.977", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 23, "fields": {"type": "av.ve.save", "timestamp": "2016-04-14T18:05:18.958", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 6, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 24, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T18:06:05.427", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 6, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 25, "fields": {"type": "dr.conf", "timestamp": "2016-04-14T18:06:12.381", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 6, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 26, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T21:47:56.684", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 6, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 27, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T22:05:25.305", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 6, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 28, "fields": {"type": "br.rm.edit", "timestamp": "2016-04-14T22:15:58.623", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 29, "fields": {"type": "br.rm.edit", "timestamp": "2016-04-14T22:16:11.181", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 30, "fields": {"type": "br.gene", "timestamp": "2016-04-14T22:16:36.674", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 31, "fields": {"type": "av.tm.save", "timestamp": "2016-04-14T22:18:41.742", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 32, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T22:25:35.394", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 33, "fields": {"type": "dr.conf", "timestamp": "2016-04-14T22:25:38.639", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 34, "fields": {"type": "av.ve.save", "timestamp": "2016-04-14T22:28:56.668", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 7, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 35, "fields": {"type": "dr.crea", "timestamp": "2016-04-14T22:33:29.382", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 7, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 36, "fields": {"type": "dr.conf", "timestamp": "2016-04-14T22:35:46.395", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 7, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 37, "fields": {"type": "op.edit", "timestamp": "2016-04-24T15:34:35.349", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 38, "fields": {"type": "av.tm.save", "timestamp": "2016-04-24T15:35:11.314", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 2, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 39, "fields": {"type": "op.edit", "timestamp": "2016-04-24T15:38:02.715", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 40, "fields": {"type": "av.ve.save", "timestamp": "2016-04-24T15:44:15.086", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 1, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 41, "fields": {"type": "av.aj.save", "timestamp": "2016-04-24T15:44:24.404", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 1, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 45, "fields": {"type": "op.edit", "timestamp": "2016-05-01T21:53:16.267", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 46, "fields": {"type": "dr.rele", "timestamp": "2016-05-01T21:53:31.708", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 1, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 47, "fields": {"type": "dr.rele", "timestamp": "2016-05-01T21:53:32.588", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 2, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 48, "fields": {"type": "op.edit", "timestamp": "2016-05-01T22:27:46.395", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 49, "fields": {"type": "op.edit", "timestamp": "2016-05-01T22:36:55.463", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 50, "fields": {"type": "op.edit", "timestamp": "2016-05-01T22:43:09.912", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 69, "fields": {"type": "aa.save", "timestamp": "2016-05-14T16:40:34.594", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 70, "fields": {"type": "aa.save", "timestamp": "2016-05-14T16:40:48.792", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 71, "fields": {"type": "aa.save", "timestamp": "2016-05-14T16:43:39.686", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 72, "fields": {"type": "op.edit", "timestamp": "2016-05-15T09:51:34.957", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 73, "fields": {"type": "op.edit", "timestamp": "2016-05-15T18:59:58.290", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 74, "fields": {"type": "op.edit", "timestamp": "2016-05-15T19:00:05.596", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 75, "fields": {"type": "op.edit", "timestamp": "2016-05-15T21:11:10.270", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 76, "fields": {"type": "op.edit", "timestamp": "2016-05-15T21:11:25.319", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 77, "fields": {"type": "dr.rege", "timestamp": "2016-05-16T13:50:16.881", "user": 1, "ip_address": null, "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": 5, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 78, "fields": {"type": "op.edit", "timestamp": "2016-05-16T14:04:19.008", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "actionlog.actionlogentry", "pk": 79, "fields": {"type": "op.edit", "timestamp": "2016-05-16T18:24:00.929", "user": 1, "ip_address": "0.0.0.0", "tournament": 1, "debate": null, "adjudicator": null, "ballot_submission": null, "adjudicator_test_score_history": null, "adjudicator_feedback": null, "round": null, "motion": null, "break_category": null}}, {"model": "results.ballotsubmission", "pk": 1, "fields": {"timestamp": "2016-04-14T13:21:34.759", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 12, "motion": 3, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 2, "fields": {"timestamp": "2016-04-14T13:21:34.841", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 11, "motion": 2, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 3, "fields": {"timestamp": "2016-04-14T13:21:34.914", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 10, "motion": 2, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 4, "fields": {"timestamp": "2016-04-14T13:21:34.987", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 9, "motion": 1, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 5, "fields": {"timestamp": "2016-04-14T13:21:35.057", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 8, "motion": 3, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 6, "fields": {"timestamp": "2016-04-14T13:21:35.127", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 7, "motion": 2, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 7, "fields": {"timestamp": "2016-04-14T13:21:35.198", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 6, "motion": 2, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 8, "fields": {"timestamp": "2016-04-14T13:21:35.268", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 5, "motion": 3, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 9, "fields": {"timestamp": "2016-04-14T13:21:35.398", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 4, "motion": 1, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 10, "fields": {"timestamp": "2016-04-14T13:21:35.503", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 3, "motion": 3, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 11, "fields": {"timestamp": "2016-04-14T13:21:35.654", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 2, "motion": 1, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 12, "fields": {"timestamp": "2016-04-14T13:21:35.757", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 1, "motion": 2, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 13, "fields": {"timestamp": "2016-04-14T13:22:17.975", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 24, "motion": 4, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 14, "fields": {"timestamp": "2016-04-14T13:22:18.113", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 23, "motion": 6, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 15, "fields": {"timestamp": "2016-04-14T13:22:18.193", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 22, "motion": 5, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 16, "fields": {"timestamp": "2016-04-14T13:22:18.319", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 21, "motion": 4, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 17, "fields": {"timestamp": "2016-04-14T13:22:18.475", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 20, "motion": 4, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 18, "fields": {"timestamp": "2016-04-14T13:22:18.592", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 19, "motion": 6, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 19, "fields": {"timestamp": "2016-04-14T13:22:18.666", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 18, "motion": 6, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 20, "fields": {"timestamp": "2016-04-14T13:22:18.789", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 17, "motion": 4, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 21, "fields": {"timestamp": "2016-04-14T13:22:18.909", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 16, "motion": 4, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 22, "fields": {"timestamp": "2016-04-14T13:22:18.986", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 15, "motion": 4, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 23, "fields": {"timestamp": "2016-04-14T13:22:19.061", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 14, "motion": 5, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 24, "fields": {"timestamp": "2016-04-14T13:22:19.183", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 13, "motion": 4, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 25, "fields": {"timestamp": "2016-04-14T13:23:01.130", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 25, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 26, "fields": {"timestamp": "2016-04-14T13:23:01.211", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 26, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 27, "fields": {"timestamp": "2016-04-14T13:23:01.279", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 27, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 28, "fields": {"timestamp": "2016-04-14T13:23:01.382", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 28, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 29, "fields": {"timestamp": "2016-04-14T13:23:01.490", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 29, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 30, "fields": {"timestamp": "2016-04-14T13:23:01.595", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 30, "motion": 8, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 31, "fields": {"timestamp": "2016-04-14T13:23:01.664", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 31, "motion": 7, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 32, "fields": {"timestamp": "2016-04-14T13:23:01.732", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 32, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 33, "fields": {"timestamp": "2016-04-14T13:23:01.800", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 33, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 34, "fields": {"timestamp": "2016-04-14T13:23:01.870", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 34, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 35, "fields": {"timestamp": "2016-04-14T13:23:02.052", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 35, "motion": 9, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 36, "fields": {"timestamp": "2016-04-14T13:23:02.157", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 36, "motion": 7, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 37, "fields": {"timestamp": "2016-04-14T13:25:54.869", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 37, "motion": 12, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 38, "fields": {"timestamp": "2016-04-14T13:25:54.956", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 38, "motion": 12, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 39, "fields": {"timestamp": "2016-04-14T13:25:55.027", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 39, "motion": 12, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 40, "fields": {"timestamp": "2016-04-14T13:25:55.136", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 40, "motion": 10, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 41, "fields": {"timestamp": "2016-04-14T13:25:55.246", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 41, "motion": 12, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 42, "fields": {"timestamp": "2016-04-14T13:25:55.351", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 42, "motion": 12, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 43, "fields": {"timestamp": "2016-04-14T13:25:55.486", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 43, "motion": 12, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 44, "fields": {"timestamp": "2016-04-14T13:25:55.594", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 44, "motion": 11, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 45, "fields": {"timestamp": "2016-04-14T13:25:55.665", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 45, "motion": 12, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 46, "fields": {"timestamp": "2016-04-14T13:25:55.778", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 46, "motion": 11, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 47, "fields": {"timestamp": "2016-04-14T13:25:55.854", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 47, "motion": 11, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "results.ballotsubmission", "pk": 48, "fields": {"timestamp": "2016-04-14T13:25:55.933", "version": 1, "submitter_type": "T", "submitter": 1, "confirmer": null, "confirm_timestamp": null, "ip_address": null, "confirmed": true, "debate": 48, "motion": 12, "copied_from": null, "discarded": false, "forfeit": null}}, {"model": "admin.logentry", "pk": 1, "fields": {"action_time": "2016-04-14T13:26:29.906", "user": 1, "content_type": 44, "object_id": "1", "object_repr": "demo", "action_flag": 2, "change_message": "Changed current_round."}}, {"model": "admin.logentry", "pk": 2, "fields": {"action_time": "2016-04-14T13:28:12.766", "user": 1, "content_type": 26, "object_id": "24", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 3, "fields": {"action_time": "2016-04-14T13:28:12.772", "user": 1, "content_type": 26, "object_id": "23", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 4, "fields": {"action_time": "2016-04-14T13:28:12.776", "user": 1, "content_type": 26, "object_id": "22", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 5, "fields": {"action_time": "2016-04-14T13:28:12.781", "user": 1, "content_type": 26, "object_id": "21", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 6, "fields": {"action_time": "2016-04-14T13:28:12.786", "user": 1, "content_type": 26, "object_id": "20", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 7, "fields": {"action_time": "2016-04-14T13:28:12.790", "user": 1, "content_type": 26, "object_id": "19", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 8, "fields": {"action_time": "2016-04-14T13:28:12.795", "user": 1, "content_type": 26, "object_id": "18", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 9, "fields": {"action_time": "2016-04-14T13:28:12.800", "user": 1, "content_type": 26, "object_id": "17", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 10, "fields": {"action_time": "2016-04-14T13:28:12.804", "user": 1, "content_type": 26, "object_id": "16", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 11, "fields": {"action_time": "2016-04-14T13:28:12.809", "user": 1, "content_type": 26, "object_id": "15", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 12, "fields": {"action_time": "2016-04-14T13:28:12.813", "user": 1, "content_type": 26, "object_id": "14", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 13, "fields": {"action_time": "2016-04-14T13:28:12.818", "user": 1, "content_type": 26, "object_id": "13", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 14, "fields": {"action_time": "2016-04-14T13:28:12.822", "user": 1, "content_type": 26, "object_id": "12", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 15, "fields": {"action_time": "2016-04-14T13:28:12.827", "user": 1, "content_type": 26, "object_id": "11", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 16, "fields": {"action_time": "2016-04-14T13:28:12.831", "user": 1, "content_type": 26, "object_id": "10", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 17, "fields": {"action_time": "2016-04-14T13:28:12.836", "user": 1, "content_type": 26, "object_id": "9", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 18, "fields": {"action_time": "2016-04-14T13:28:12.841", "user": 1, "content_type": 26, "object_id": "8", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 19, "fields": {"action_time": "2016-04-14T13:28:12.846", "user": 1, "content_type": 26, "object_id": "7", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 20, "fields": {"action_time": "2016-04-14T13:28:12.920", "user": 1, "content_type": 26, "object_id": "6", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 21, "fields": {"action_time": "2016-04-14T13:28:12.924", "user": 1, "content_type": 26, "object_id": "5", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 22, "fields": {"action_time": "2016-04-14T13:28:12.929", "user": 1, "content_type": 26, "object_id": "4", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 23, "fields": {"action_time": "2016-04-14T13:28:12.934", "user": 1, "content_type": 26, "object_id": "3", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 24, "fields": {"action_time": "2016-04-14T13:28:12.938", "user": 1, "content_type": 26, "object_id": "2", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 25, "fields": {"action_time": "2016-04-14T13:28:12.942", "user": 1, "content_type": 26, "object_id": "1", "object_repr": "BreakingTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 26, "fields": {"action_time": "2016-04-14T13:55:15.082", "user": 1, "content_type": 23, "object_id": "120", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 27, "fields": {"action_time": "2016-04-14T13:55:15.087", "user": 1, "content_type": 23, "object_id": "119", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 28, "fields": {"action_time": "2016-04-14T13:55:15.092", "user": 1, "content_type": 23, "object_id": "118", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 29, "fields": {"action_time": "2016-04-14T13:55:15.096", "user": 1, "content_type": 23, "object_id": "117", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 30, "fields": {"action_time": "2016-04-14T13:55:15.101", "user": 1, "content_type": 23, "object_id": "116", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 31, "fields": {"action_time": "2016-04-14T13:55:15.105", "user": 1, "content_type": 23, "object_id": "115", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 32, "fields": {"action_time": "2016-04-14T13:55:15.109", "user": 1, "content_type": 23, "object_id": "114", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 33, "fields": {"action_time": "2016-04-14T13:55:15.114", "user": 1, "content_type": 23, "object_id": "113", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 34, "fields": {"action_time": "2016-04-14T13:55:15.118", "user": 1, "content_type": 23, "object_id": "112", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 35, "fields": {"action_time": "2016-04-14T13:55:15.122", "user": 1, "content_type": 23, "object_id": "111", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 36, "fields": {"action_time": "2016-04-14T13:55:15.126", "user": 1, "content_type": 23, "object_id": "110", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 37, "fields": {"action_time": "2016-04-14T13:55:15.131", "user": 1, "content_type": 23, "object_id": "109", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 38, "fields": {"action_time": "2016-04-14T13:55:15.135", "user": 1, "content_type": 23, "object_id": "108", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 39, "fields": {"action_time": "2016-04-14T13:55:15.140", "user": 1, "content_type": 23, "object_id": "107", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 40, "fields": {"action_time": "2016-04-14T13:55:15.144", "user": 1, "content_type": 23, "object_id": "106", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 41, "fields": {"action_time": "2016-04-14T13:55:15.149", "user": 1, "content_type": 23, "object_id": "105", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 42, "fields": {"action_time": "2016-04-14T13:55:15.153", "user": 1, "content_type": 23, "object_id": "104", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 43, "fields": {"action_time": "2016-04-14T13:55:15.158", "user": 1, "content_type": 23, "object_id": "103", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 44, "fields": {"action_time": "2016-04-14T13:55:15.162", "user": 1, "content_type": 23, "object_id": "102", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 45, "fields": {"action_time": "2016-04-14T13:55:15.166", "user": 1, "content_type": 23, "object_id": "101", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 46, "fields": {"action_time": "2016-04-14T13:55:15.171", "user": 1, "content_type": 23, "object_id": "100", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 47, "fields": {"action_time": "2016-04-14T13:55:15.176", "user": 1, "content_type": 23, "object_id": "99", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 48, "fields": {"action_time": "2016-04-14T13:55:15.180", "user": 1, "content_type": 23, "object_id": "98", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 49, "fields": {"action_time": "2016-04-14T13:55:15.184", "user": 1, "content_type": 23, "object_id": "97", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 50, "fields": {"action_time": "2016-04-14T13:55:15.195", "user": 1, "content_type": 23, "object_id": "96", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 51, "fields": {"action_time": "2016-04-14T13:55:15.205", "user": 1, "content_type": 23, "object_id": "95", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 52, "fields": {"action_time": "2016-04-14T13:55:15.215", "user": 1, "content_type": 23, "object_id": "94", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 53, "fields": {"action_time": "2016-04-14T13:55:15.224", "user": 1, "content_type": 23, "object_id": "93", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 54, "fields": {"action_time": "2016-04-14T13:55:15.229", "user": 1, "content_type": 23, "object_id": "92", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 55, "fields": {"action_time": "2016-04-14T13:55:15.233", "user": 1, "content_type": 23, "object_id": "91", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 56, "fields": {"action_time": "2016-04-14T13:55:15.242", "user": 1, "content_type": 23, "object_id": "90", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 57, "fields": {"action_time": "2016-04-14T13:55:15.253", "user": 1, "content_type": 23, "object_id": "89", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 58, "fields": {"action_time": "2016-04-14T13:55:15.263", "user": 1, "content_type": 23, "object_id": "88", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 59, "fields": {"action_time": "2016-04-14T13:55:15.268", "user": 1, "content_type": 23, "object_id": "87", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 60, "fields": {"action_time": "2016-04-14T13:55:15.272", "user": 1, "content_type": 23, "object_id": "86", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 61, "fields": {"action_time": "2016-04-14T13:55:15.277", "user": 1, "content_type": 23, "object_id": "85", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 62, "fields": {"action_time": "2016-04-14T13:55:15.282", "user": 1, "content_type": 23, "object_id": "84", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 63, "fields": {"action_time": "2016-04-14T13:55:15.286", "user": 1, "content_type": 23, "object_id": "83", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 64, "fields": {"action_time": "2016-04-14T13:55:15.291", "user": 1, "content_type": 23, "object_id": "82", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 65, "fields": {"action_time": "2016-04-14T13:55:15.296", "user": 1, "content_type": 23, "object_id": "81", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 66, "fields": {"action_time": "2016-04-14T13:55:15.300", "user": 1, "content_type": 23, "object_id": "80", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 67, "fields": {"action_time": "2016-04-14T13:55:15.305", "user": 1, "content_type": 23, "object_id": "79", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 68, "fields": {"action_time": "2016-04-14T13:55:15.309", "user": 1, "content_type": 23, "object_id": "78", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 69, "fields": {"action_time": "2016-04-14T13:55:15.313", "user": 1, "content_type": 23, "object_id": "77", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 70, "fields": {"action_time": "2016-04-14T13:55:15.318", "user": 1, "content_type": 23, "object_id": "76", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 71, "fields": {"action_time": "2016-04-14T13:55:15.322", "user": 1, "content_type": 23, "object_id": "75", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 72, "fields": {"action_time": "2016-04-14T13:55:15.326", "user": 1, "content_type": 23, "object_id": "74", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 73, "fields": {"action_time": "2016-04-14T13:55:15.331", "user": 1, "content_type": 23, "object_id": "73", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 74, "fields": {"action_time": "2016-04-14T13:55:15.336", "user": 1, "content_type": 23, "object_id": "72", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 75, "fields": {"action_time": "2016-04-14T13:55:15.340", "user": 1, "content_type": 23, "object_id": "71", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 76, "fields": {"action_time": "2016-04-14T13:55:15.344", "user": 1, "content_type": 23, "object_id": "70", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 77, "fields": {"action_time": "2016-04-14T13:55:15.349", "user": 1, "content_type": 23, "object_id": "69", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 78, "fields": {"action_time": "2016-04-14T13:55:15.354", "user": 1, "content_type": 23, "object_id": "68", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 79, "fields": {"action_time": "2016-04-14T13:55:15.358", "user": 1, "content_type": 23, "object_id": "67", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 80, "fields": {"action_time": "2016-04-14T13:55:15.363", "user": 1, "content_type": 23, "object_id": "66", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 81, "fields": {"action_time": "2016-04-14T13:55:15.368", "user": 1, "content_type": 23, "object_id": "65", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 82, "fields": {"action_time": "2016-04-14T13:55:15.372", "user": 1, "content_type": 23, "object_id": "64", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 83, "fields": {"action_time": "2016-04-14T13:55:15.376", "user": 1, "content_type": 23, "object_id": "63", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 84, "fields": {"action_time": "2016-04-14T13:55:15.381", "user": 1, "content_type": 23, "object_id": "62", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 85, "fields": {"action_time": "2016-04-14T13:55:15.386", "user": 1, "content_type": 23, "object_id": "61", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 86, "fields": {"action_time": "2016-04-14T13:55:15.391", "user": 1, "content_type": 23, "object_id": "60", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 87, "fields": {"action_time": "2016-04-14T13:55:15.395", "user": 1, "content_type": 23, "object_id": "59", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 88, "fields": {"action_time": "2016-04-14T13:55:15.400", "user": 1, "content_type": 23, "object_id": "58", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 89, "fields": {"action_time": "2016-04-14T13:55:15.404", "user": 1, "content_type": 23, "object_id": "57", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 90, "fields": {"action_time": "2016-04-14T13:55:15.409", "user": 1, "content_type": 23, "object_id": "56", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 91, "fields": {"action_time": "2016-04-14T13:55:15.413", "user": 1, "content_type": 23, "object_id": "55", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 92, "fields": {"action_time": "2016-04-14T13:55:15.417", "user": 1, "content_type": 23, "object_id": "54", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 93, "fields": {"action_time": "2016-04-14T13:55:15.421", "user": 1, "content_type": 23, "object_id": "53", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 94, "fields": {"action_time": "2016-04-14T13:55:15.425", "user": 1, "content_type": 23, "object_id": "52", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 95, "fields": {"action_time": "2016-04-14T13:55:15.430", "user": 1, "content_type": 23, "object_id": "51", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 96, "fields": {"action_time": "2016-04-14T13:55:15.434", "user": 1, "content_type": 23, "object_id": "50", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 97, "fields": {"action_time": "2016-04-14T13:55:15.438", "user": 1, "content_type": 23, "object_id": "49", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 98, "fields": {"action_time": "2016-04-14T13:55:15.443", "user": 1, "content_type": 23, "object_id": "48", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 99, "fields": {"action_time": "2016-04-14T13:55:15.448", "user": 1, "content_type": 23, "object_id": "47", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 100, "fields": {"action_time": "2016-04-14T13:55:15.453", "user": 1, "content_type": 23, "object_id": "46", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 101, "fields": {"action_time": "2016-04-14T13:55:15.457", "user": 1, "content_type": 23, "object_id": "45", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 102, "fields": {"action_time": "2016-04-14T13:55:15.462", "user": 1, "content_type": 23, "object_id": "44", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 103, "fields": {"action_time": "2016-04-14T13:55:15.466", "user": 1, "content_type": 23, "object_id": "43", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 104, "fields": {"action_time": "2016-04-14T13:55:15.471", "user": 1, "content_type": 23, "object_id": "42", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 105, "fields": {"action_time": "2016-04-14T13:55:15.476", "user": 1, "content_type": 23, "object_id": "41", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 106, "fields": {"action_time": "2016-04-14T13:55:15.480", "user": 1, "content_type": 23, "object_id": "40", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 107, "fields": {"action_time": "2016-04-14T13:55:15.484", "user": 1, "content_type": 23, "object_id": "39", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 108, "fields": {"action_time": "2016-04-14T13:55:15.489", "user": 1, "content_type": 23, "object_id": "38", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 109, "fields": {"action_time": "2016-04-14T13:55:15.493", "user": 1, "content_type": 23, "object_id": "37", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 110, "fields": {"action_time": "2016-04-14T13:55:15.498", "user": 1, "content_type": 23, "object_id": "36", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 111, "fields": {"action_time": "2016-04-14T13:55:15.502", "user": 1, "content_type": 23, "object_id": "35", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 112, "fields": {"action_time": "2016-04-14T13:55:15.506", "user": 1, "content_type": 23, "object_id": "34", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 113, "fields": {"action_time": "2016-04-14T13:55:15.511", "user": 1, "content_type": 23, "object_id": "33", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 114, "fields": {"action_time": "2016-04-14T13:55:15.515", "user": 1, "content_type": 23, "object_id": "32", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 115, "fields": {"action_time": "2016-04-14T13:55:15.520", "user": 1, "content_type": 23, "object_id": "31", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 116, "fields": {"action_time": "2016-04-14T13:55:15.524", "user": 1, "content_type": 23, "object_id": "30", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 117, "fields": {"action_time": "2016-04-14T13:55:15.529", "user": 1, "content_type": 23, "object_id": "29", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 118, "fields": {"action_time": "2016-04-14T13:55:15.534", "user": 1, "content_type": 23, "object_id": "28", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 119, "fields": {"action_time": "2016-04-14T13:55:15.538", "user": 1, "content_type": 23, "object_id": "27", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 120, "fields": {"action_time": "2016-04-14T13:55:15.542", "user": 1, "content_type": 23, "object_id": "26", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 121, "fields": {"action_time": "2016-04-14T13:55:15.547", "user": 1, "content_type": 23, "object_id": "25", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 122, "fields": {"action_time": "2016-04-14T13:55:15.552", "user": 1, "content_type": 23, "object_id": "24", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 123, "fields": {"action_time": "2016-04-14T13:55:15.557", "user": 1, "content_type": 23, "object_id": "23", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 124, "fields": {"action_time": "2016-04-14T13:55:15.561", "user": 1, "content_type": 23, "object_id": "22", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 125, "fields": {"action_time": "2016-04-14T13:55:15.566", "user": 1, "content_type": 23, "object_id": "21", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 126, "fields": {"action_time": "2016-04-14T17:43:48.050", "user": 1, "content_type": 45, "object_id": "5", "object_repr": "demo - Open Quarterfinal", "action_flag": 2, "change_message": "Changed draw_status."}}, {"model": "admin.logentry", "pk": 127, "fields": {"action_time": "2016-04-14T21:47:44.613", "user": 1, "content_type": 45, "object_id": "6", "object_repr": "demo - ESL Semifinal", "action_flag": 2, "change_message": "Changed draw_status."}}, {"model": "admin.logentry", "pk": 128, "fields": {"action_time": "2016-04-14T21:47:47.557", "user": 1, "content_type": 23, "object_id": "139", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 129, "fields": {"action_time": "2016-04-14T21:47:47.563", "user": 1, "content_type": 23, "object_id": "138", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 130, "fields": {"action_time": "2016-04-14T21:47:47.567", "user": 1, "content_type": 23, "object_id": "137", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 131, "fields": {"action_time": "2016-04-14T21:47:47.571", "user": 1, "content_type": 23, "object_id": "136", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 132, "fields": {"action_time": "2016-04-14T21:59:23.337", "user": 1, "content_type": 45, "object_id": "6", "object_repr": "demo - ESL Semifinal", "action_flag": 2, "change_message": "Changed draw_status."}}, {"model": "admin.logentry", "pk": 133, "fields": {"action_time": "2016-04-14T22:05:36.581", "user": 1, "content_type": 45, "object_id": "6", "object_repr": "demo - ESL Semifinal", "action_flag": 2, "change_message": "Changed draw_status."}}, {"model": "admin.logentry", "pk": 134, "fields": {"action_time": "2016-04-14T22:07:37.399", "user": 1, "content_type": 45, "object_id": "5", "object_repr": "demo - Open Quarterfinal", "action_flag": 2, "change_message": "Changed draw_status."}}, {"model": "admin.logentry", "pk": 135, "fields": {"action_time": "2016-04-14T22:07:46.463", "user": 1, "content_type": 23, "object_id": "128", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 136, "fields": {"action_time": "2016-04-14T22:07:46.469", "user": 1, "content_type": 23, "object_id": "127", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 137, "fields": {"action_time": "2016-04-14T22:07:46.474", "user": 1, "content_type": 23, "object_id": "126", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 138, "fields": {"action_time": "2016-04-14T22:07:46.478", "user": 1, "content_type": 23, "object_id": "125", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 139, "fields": {"action_time": "2016-04-14T22:07:46.482", "user": 1, "content_type": 23, "object_id": "124", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 140, "fields": {"action_time": "2016-04-14T22:07:46.486", "user": 1, "content_type": 23, "object_id": "123", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 141, "fields": {"action_time": "2016-04-14T22:07:46.491", "user": 1, "content_type": 23, "object_id": "122", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 142, "fields": {"action_time": "2016-04-14T22:07:46.495", "user": 1, "content_type": 23, "object_id": "121", "object_repr": "ActiveTeam object", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 143, "fields": {"action_time": "2016-04-24T11:54:17.877", "user": 1, "content_type": 44, "object_id": "2", "object_repr": "Test", "action_flag": 1, "change_message": "Added."}}, {"model": "admin.logentry", "pk": 144, "fields": {"action_time": "2016-04-24T11:54:48.689", "user": 1, "content_type": 45, "object_id": "11", "object_repr": "Test - 1", "action_flag": 1, "change_message": "Added."}}, {"model": "admin.logentry", "pk": 145, "fields": {"action_time": "2016-04-24T15:39:59.911", "user": 1, "content_type": 47, "object_id": "2", "object_repr": "1 - M05", "action_flag": 2, "change_message": "Changed tournament."}}, {"model": "admin.logentry", "pk": 146, "fields": {"action_time": "2016-05-01T22:28:49.579", "user": 1, "content_type": 39, "object_id": "106", "object_repr": "An Adjudicator (Caltech)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 147, "fields": {"action_time": "2016-05-01T22:28:49.658", "user": 1, "content_type": 39, "object_id": "100", "object_repr": "An Adjudicator (Caltech)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 148, "fields": {"action_time": "2016-05-01T22:28:49.668", "user": 1, "content_type": 39, "object_id": "101", "object_repr": "An Adjudicator (Caltech)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 149, "fields": {"action_time": "2016-05-01T22:28:49.673", "user": 1, "content_type": 39, "object_id": "102", "object_repr": "An Adjudicator (Caltech)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 150, "fields": {"action_time": "2016-05-01T22:28:49.677", "user": 1, "content_type": 39, "object_id": "103", "object_repr": "An Adjudicator (Caltech)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 151, "fields": {"action_time": "2016-05-01T22:28:49.682", "user": 1, "content_type": 39, "object_id": "107", "object_repr": "An Adjudicator (Caltech)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 152, "fields": {"action_time": "2016-05-01T22:28:49.687", "user": 1, "content_type": 39, "object_id": "105", "object_repr": "An Adjudicator (Columbia)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 153, "fields": {"action_time": "2016-05-01T22:28:49.691", "user": 1, "content_type": 39, "object_id": "104", "object_repr": "An Adjudicator (Columbia)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 154, "fields": {"action_time": "2016-05-01T22:28:49.696", "user": 1, "content_type": 39, "object_id": "108", "object_repr": "An Adjudicator (Columbia)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 155, "fields": {"action_time": "2016-05-01T22:28:49.701", "user": 1, "content_type": 39, "object_id": "111", "object_repr": "An Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 156, "fields": {"action_time": "2016-05-01T22:28:49.706", "user": 1, "content_type": 39, "object_id": "147", "object_repr": "An Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 157, "fields": {"action_time": "2016-05-01T22:28:49.710", "user": 1, "content_type": 39, "object_id": "146", "object_repr": "An Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 158, "fields": {"action_time": "2016-05-01T22:28:49.714", "user": 1, "content_type": 39, "object_id": "109", "object_repr": "An Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 159, "fields": {"action_time": "2016-05-01T22:28:49.719", "user": 1, "content_type": 39, "object_id": "110", "object_repr": "An Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 160, "fields": {"action_time": "2016-05-01T22:28:49.723", "user": 1, "content_type": 39, "object_id": "148", "object_repr": "An Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 161, "fields": {"action_time": "2016-05-01T22:28:49.727", "user": 1, "content_type": 39, "object_id": "112", "object_repr": "An Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 162, "fields": {"action_time": "2016-05-01T22:28:49.731", "user": 1, "content_type": 39, "object_id": "113", "object_repr": "An Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 163, "fields": {"action_time": "2016-05-01T22:28:49.737", "user": 1, "content_type": 39, "object_id": "128", "object_repr": "An Adjudicator1 (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 164, "fields": {"action_time": "2016-05-01T22:28:49.741", "user": 1, "content_type": 39, "object_id": "119", "object_repr": "An Adjudicator1 (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 165, "fields": {"action_time": "2016-05-01T22:28:49.745", "user": 1, "content_type": 39, "object_id": "137", "object_repr": "An Adjudicator1 (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 166, "fields": {"action_time": "2016-05-01T22:28:49.749", "user": 1, "content_type": 39, "object_id": "129", "object_repr": "An Adjudicator2 (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 167, "fields": {"action_time": "2016-05-01T22:28:49.754", "user": 1, "content_type": 39, "object_id": "120", "object_repr": "An Adjudicator2 (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 168, "fields": {"action_time": "2016-05-01T22:28:49.759", "user": 1, "content_type": 39, "object_id": "138", "object_repr": "An Adjudicator2 (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 169, "fields": {"action_time": "2016-05-01T22:28:49.764", "user": 1, "content_type": 39, "object_id": "121", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 170, "fields": {"action_time": "2016-05-01T22:28:49.770", "user": 1, "content_type": 39, "object_id": "114", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 171, "fields": {"action_time": "2016-05-01T22:28:49.774", "user": 1, "content_type": 39, "object_id": "115", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 172, "fields": {"action_time": "2016-05-01T22:28:49.778", "user": 1, "content_type": 39, "object_id": "116", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 173, "fields": {"action_time": "2016-05-01T22:28:49.782", "user": 1, "content_type": 39, "object_id": "117", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 174, "fields": {"action_time": "2016-05-01T22:28:49.788", "user": 1, "content_type": 39, "object_id": "118", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 175, "fields": {"action_time": "2016-05-01T22:28:49.793", "user": 1, "content_type": 39, "object_id": "122", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 176, "fields": {"action_time": "2016-05-01T22:28:49.796", "user": 1, "content_type": 39, "object_id": "130", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 177, "fields": {"action_time": "2016-05-01T22:28:49.802", "user": 1, "content_type": 39, "object_id": "131", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 178, "fields": {"action_time": "2016-05-01T22:28:49.808", "user": 1, "content_type": 39, "object_id": "139", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 179, "fields": {"action_time": "2016-05-01T22:28:49.812", "user": 1, "content_type": 39, "object_id": "140", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 180, "fields": {"action_time": "2016-05-01T22:28:49.817", "user": 1, "content_type": 39, "object_id": "149", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 181, "fields": {"action_time": "2016-05-01T22:28:49.822", "user": 1, "content_type": 39, "object_id": "150", "object_repr": "An Adjudicator (Harvard)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 182, "fields": {"action_time": "2016-05-01T22:28:49.826", "user": 1, "content_type": 39, "object_id": "132", "object_repr": "An Adjudicator (Johns Hopkins)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 183, "fields": {"action_time": "2016-05-01T22:28:49.829", "user": 1, "content_type": 39, "object_id": "141", "object_repr": "An Adjudicator (Johns Hopkins)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 184, "fields": {"action_time": "2016-05-01T22:28:49.834", "user": 1, "content_type": 39, "object_id": "123", "object_repr": "An Adjudicator (Johns Hopkins)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 185, "fields": {"action_time": "2016-05-01T22:28:49.839", "user": 1, "content_type": 39, "object_id": "151", "object_repr": "An Adjudicator (Johns Hopkins)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 186, "fields": {"action_time": "2016-05-01T22:28:49.843", "user": 1, "content_type": 39, "object_id": "155", "object_repr": "An Adjudicator (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 187, "fields": {"action_time": "2016-05-01T22:28:49.847", "user": 1, "content_type": 39, "object_id": "152", "object_repr": "An Adjudicator (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 188, "fields": {"action_time": "2016-05-01T22:28:49.851", "user": 1, "content_type": 39, "object_id": "153", "object_repr": "An Adjudicator (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 189, "fields": {"action_time": "2016-05-01T22:28:49.856", "user": 1, "content_type": 39, "object_id": "154", "object_repr": "An Adjudicator (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 190, "fields": {"action_time": "2016-05-01T22:28:49.860", "user": 1, "content_type": 39, "object_id": "133", "object_repr": "An Adjudicator1 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 191, "fields": {"action_time": "2016-05-01T22:28:49.873", "user": 1, "content_type": 39, "object_id": "124", "object_repr": "An Adjudicator1 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 192, "fields": {"action_time": "2016-05-01T22:28:49.877", "user": 1, "content_type": 39, "object_id": "142", "object_repr": "An Adjudicator1 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 193, "fields": {"action_time": "2016-05-01T22:28:49.882", "user": 1, "content_type": 39, "object_id": "134", "object_repr": "An Adjudicator2 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 194, "fields": {"action_time": "2016-05-01T22:28:49.886", "user": 1, "content_type": 39, "object_id": "125", "object_repr": "An Adjudicator2 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 195, "fields": {"action_time": "2016-05-01T22:28:49.891", "user": 1, "content_type": 39, "object_id": "143", "object_repr": "An Adjudicator2 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 196, "fields": {"action_time": "2016-05-01T22:28:49.895", "user": 1, "content_type": 39, "object_id": "135", "object_repr": "An Adjudicator3 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 197, "fields": {"action_time": "2016-05-01T22:28:49.900", "user": 1, "content_type": 39, "object_id": "126", "object_repr": "An Adjudicator3 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 198, "fields": {"action_time": "2016-05-01T22:28:49.905", "user": 1, "content_type": 39, "object_id": "144", "object_repr": "An Adjudicator3 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 199, "fields": {"action_time": "2016-05-01T22:28:49.910", "user": 1, "content_type": 39, "object_id": "145", "object_repr": "An Adjudicator4 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 200, "fields": {"action_time": "2016-05-01T22:28:49.915", "user": 1, "content_type": 39, "object_id": "127", "object_repr": "An Adjudicator4 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 201, "fields": {"action_time": "2016-05-01T22:28:49.919", "user": 1, "content_type": 39, "object_id": "136", "object_repr": "An Adjudicator4 (Princeton)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 202, "fields": {"action_time": "2016-05-01T22:29:23.853", "user": 1, "content_type": 39, "object_id": "156", "object_repr": "New Adjudicator Shared (Caltech)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 203, "fields": {"action_time": "2016-05-01T22:29:23.858", "user": 1, "content_type": 39, "object_id": "157", "object_repr": "New Adjudicator Shared (Columbia)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 204, "fields": {"action_time": "2016-05-01T22:29:47.358", "user": 1, "content_type": 39, "object_id": "158", "object_repr": "New Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 205, "fields": {"action_time": "2016-05-01T22:29:47.363", "user": 1, "content_type": 39, "object_id": "161", "object_repr": "New Adjudicator (Cornell)", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 206, "fields": {"action_time": "2016-05-12T00:13:12.641", "user": 1, "content_type": 44, "object_id": "3", "object_repr": "New DM", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 207, "fields": {"action_time": "2016-05-12T00:13:12.740", "user": 1, "content_type": 44, "object_id": "2", "object_repr": "Test", "action_flag": 3, "change_message": ""}}, {"model": "admin.logentry", "pk": 208, "fields": {"action_time": "2016-05-14T16:44:04.284", "user": 1, "content_type": 39, "object_id": "89", "object_repr": "Jo Allen (Princeton)", "action_flag": 2, "change_message": "Added adjudicator-team conflict \"AdjudicatorConflict object\"."}}, {"model": "admin.logentry", "pk": 209, "fields": {"action_time": "2016-05-16T13:57:32.785", "user": 1, "content_type": 44, "object_id": "1", "object_repr": "demo", "action_flag": 2, "change_message": "Changed current_round."}}] \ No newline at end of file diff --git a/data/sandbox/motions.py b/data/sandbox/motions.py index 3da47f5472d..93dfc7bfe16 100644 --- a/data/sandbox/motions.py +++ b/data/sandbox/motions.py @@ -1,13 +1,11 @@ """Sandbox for figuring out how to do motion aggregations.""" -import header +import argparse + import tournaments.models as tm import draw.models as dm import motions.models as mm -from django.db import models - -import argparse parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("round", type=int, help="Round to look at") args = parser.parse_args() @@ -26,9 +24,8 @@ AND "draws_debateteam"."position" = '{pos:s}' """ - - -motions = motions.extra({"chosen_in": """ +motions = motions.extra({ + "chosen_in": """ SELECT COUNT (*) FROM "results_ballotsubmission" WHERE "results_ballotsubmission"."confirmed" = True @@ -39,4 +36,5 @@ }) for motion in motions: - print "{0:30} {1:5} {2:5} {3:5}".format(motion.reference, motion.chosen_in, motion.aff_score, motion.neg_score) + print("{0:30} {1:5} {2:5} {3:5}".format( + motion.reference, motion.chosen_in, motion.aff_score, motion.neg_score)) diff --git a/data/sandbox/standings.py b/data/sandbox/standings.py index 9a06459fd3a..069dcfff23c 100644 --- a/data/sandbox/standings.py +++ b/data/sandbox/standings.py @@ -19,51 +19,53 @@ teams = tm.Team.objects teams = teams.filter( - institution__tournament = round.tournament, - debateteam__debate__round__seq__lte = round.seq, + institution__tournament=round.tournament, + debateteam__debate__round__seq__lte=round.seq, ) - #teams = teams.filter( - #debateteam__teamscore__ballot_submission__confirmed = True - #).annotate( - #points = models.Count('debateteam__teamscore__points'), - #speaker_score = models.Count('debateteam__teamscore__score'), - #).order_by('-points', '-speaker_score') - - #teams = teams.annotate( - #points = models.Count('debateteam__teamscore__points'), - #speaker_score = models.Count('debateteam__teamscore__score'), - #) - - #teams = teams.order_by('-points', '-speaker_score') - - # Sum the team scores for each team for which - #teams = teams.extra({"points": """ - #SELECT DISTINCT SUM("points") - #FROM "results_teamscore" - #JOIN "results_ballotsubmission" ON "results_teamscore"."ballot_submission_id" = "results_ballotsubmission"."id" - #JOIN "draws_debateteam" ON "results_teamscore"."debate_team_id" = "draws_debateteam"."id" - #JOIN "draws_debate" ON "draws_debateteam"."debate_id" = "draws_debate"."id" - #JOIN "tournaments_round" ON "draws_debate"."round_id" = "tournaments_round"."id" - #JOIN "debate_institution" ON "debate_team"."instition_id" = "debate_institution"."id" - #WHERE "results_ballotsubmission"."confirmed" = True - #AND "draws_debateteam"."team_id" = "debate_team"."id" - #AND "debate_institution"."tournament_id" = {tournament:d} - #AND "tournaments_round"."seq" <= {round:d} - #""".format(tournament=round.tournament.id, round=round.seq), - #"speaker_score": """ - #SELECT SUM("score") - #FROM "results_teamscore" - #JOIN "results_ballotsubmission" ON "results_teamscore"."ballot_submission_id" = "results_ballotsubmission"."id" - #JOIN "draws_debateteam" ON "results_teamscore"."debate_team_id" = "draws_debateteam"."id" - #JOIN "draws_debate" ON "draws_debateteam"."debate_id" = "draws_debate"."id" - #JOIN "tournaments_round" ON "draws_debate"."round_id" = "tournaments_round"."id" - #JOIN "debate_institution" ON "debate_team"."institution_id" = "debate_institution"."id" - #WHERE "results_ballotsubmission"."confirmed" = True - #AND "draws_debateteam"."team_id" = "debate_team"."id" - #AND "debate_institution"."tournament_id" = {tournament:d} - #AND "tournaments_round"."seq" <= {round:d} - #""".format(tournament=round.tournament.id, round=round.seq)}).distinct() + ''' + teams = teams.filter( + debateteam__teamscore__ballot_submission__confirmed = True + ).annotate( + points = models.Count('debateteam__teamscore__points'), + speaker_score = models.Count('debateteam__teamscore__score'), + ).order_by('-points', '-speaker_score') + + teams = teams.annotate( + points = models.Count('debateteam__teamscore__points'), + speaker_score = models.Count('debateteam__teamscore__score'), + ) + + teams = teams.order_by('-points', '-speaker_score') + + Sum the team scores for each team for which + teams = teams.extra({"points": """ + SELECT DISTINCT SUM("points") + FROM "results_teamscore" + JOIN "results_ballotsubmission" ON "results_teamscore"."ballot_submission_id" = "results_ballotsubmission"."id" + JOIN "draws_debateteam" ON "results_teamscore"."debate_team_id" = "draws_debateteam"."id" + JOIN "draws_debate" ON "draws_debateteam"."debate_id" = "draws_debate"."id" + JOIN "tournaments_round" ON "draws_debate"."round_id" = "tournaments_round"."id" + JOIN "debate_institution" ON "debate_team"."instition_id" = "debate_institution"."id" + WHERE "results_ballotsubmission"."confirmed" = True + AND "draws_debateteam"."team_id" = "debate_team"."id" + AND "debate_institution"."tournament_id" = {tournament:d} + AND "tournaments_round"."seq" <= {round:d} + """.format(tournament=round.tournament.id, round=round.seq), + "speaker_score": """ + SELECT SUM("score") + FROM "results_teamscore" + JOIN "results_ballotsubmission" ON "results_teamscore"."ballot_submission_id" = "results_ballotsubmission"."id" + JOIN "draws_debateteam" ON "results_teamscore"."debate_team_id" = "draws_debateteam"."id" + JOIN "draws_debate" ON "draws_debateteam"."debate_id" = "draws_debate"."id" + JOIN "tournaments_round" ON "draws_debate"."round_id" = "tournaments_round"."id" + JOIN "debate_institution" ON "debate_team"."institution_id" = "debate_institution"."id" + WHERE "results_ballotsubmission"."confirmed" = True + AND "draws_debateteam"."team_id" = "debate_team"."id" + AND "debate_institution"."tournament_id" = {tournament:d} + AND "tournaments_round"."seq" <= {round:d} + """.format(tournament=round.tournament.id, round=round.seq)}).distinct() + ''' EXTRA_QUERY = """ SELECT DISTINCT SUM({field:s}) @@ -81,7 +83,7 @@ "speaker_score": EXTRA_QUERY.format(field="score", round=round.seq, affects_averages=True)} ).distinct().order_by("-points", "-speaker_score") - print teams.query + print teams.query # flake8: noqa print teams.count() for team in teams: @@ -91,13 +93,15 @@ speakers = Speaker.objects.filter( team__institution__tournament=round.tournament, speakerscore__position__lte=round.tournament.LAST_SUBSTANTIVE_POSITION, - speakerscore__debate_team__debate__round__seq__lte = round.seq, + speakerscore__debate_team__debate__round__seq__lte=round.seq, ) # TODO fix this, should only aggregate over confirmed ballots - #speakers = speakers.annotate( - #total = models.Sum('speakerscore__score'), - #).order_by('-total', 'name') + ''' + speakers = speakers.annotate( + total = models.Sum('speakerscore__score'), + ).order_by('-total', 'name') + ''' EXTRA_QUERY = """ SELECT DISTINCT SUM("score") @@ -111,18 +115,21 @@ AND "debate_speakerscore"."position" <= {position:d} AND "tournaments_round"."seq" <= {round:d} """.format( - round = round.seq, - position = round.tournament.LAST_SUBSTANTIVE_POSITION + round=round.seq, + position=round.tournament.LAST_SUBSTANTIVE_POSITION ) speakers = speakers.extra({"total": EXTRA_QUERY}).distinct().order_by("-total") print speakers.query print speakers.count() - #print SpeakerScore.objects.filter( - #ballot_submission__confirmed=True, - #debate_team__debate__round__seq__lte = round.seq, - #position__lte = round.tournament.LAST_SUBSTANTIVE_POSITION - #).distinct().count() + + ''' + print SpeakerScore.objects.filter( + ballot_submission__confirmed=True, + debate_team__debate__round__seq__lte = round.seq, + position__lte = round.tournament.LAST_SUBSTANTIVE_POSITION + ).distinct().count() + ''' for speaker in speakers: print "{0:<30} {1:>10.2f}".format(speaker.name, speaker.total) @@ -131,8 +138,7 @@ speakers = Speaker.objects.filter( team__institution__tournament=round.tournament, speakerscore__position=round.tournament.REPLY_POSITION, - speakerscore__debate_team__debate__round__seq__lte = - round.seq, + speakerscore__debate_team__debate__round__seq__lte=round.seq, ) EXTRA_QUERY = """ @@ -148,13 +154,13 @@ AND "tournaments_round"."seq" <= {round:d} """ speakers = speakers.extra({"average": EXTRA_QUERY.format( - aggregator = "AVG", - round = round.seq, - position = round.tournament.REPLY_POSITION + aggregator="AVG", + round=round.seq, + position=round.tournament.REPLY_POSITION ), "replies": EXTRA_QUERY.format( - aggregator = "COUNT", - round = round.seq, - position = round.tournament.REPLY_POSITION + aggregator="COUNT", + round=round.seq, + position=round.tournament.REPLY_POSITION )}).distinct().order_by('-average', '-replies', 'name') print speakers.query diff --git a/data/sandbox/standings2.py b/data/sandbox/standings2.py index 94b0c13a09b..249781a3365 100644 --- a/data/sandbox/standings2.py +++ b/data/sandbox/standings2.py @@ -18,8 +18,8 @@ teams = Team.objects teams = teams.filter( - institution__tournament = round.tournament, - debateteam__debate__round__seq__lte = round.seq, + institution__tournament=round.tournament, + debateteam__debate__round__seq__lte=round.seq, ) EXTRA_QUERY = """ @@ -38,7 +38,7 @@ "speaker_score": EXTRA_QUERY.format(field="score", round=round.seq)} ).distinct() -print teams.query +print teams.query # flake8: noqa print teams.count() # Add draw strength annotation. @@ -55,6 +55,7 @@ print "=" * 50 + def who_beat_whom(team1, team2): """Returns a positive value if team1 won more debates, a negative value if team2 won more, 0 if the teams won the same number against each other @@ -72,6 +73,7 @@ def get_wins(team, other): print "who beat whom, {0} vs {1}: {2} wins against {3}".format(team1, team2, wins1, wins2) return cmp(wins1, wins2) + def cmp_teams(team1, team2): """Returns 1 if team1 ranks ahead of team2, -1 if team2 ranks ahead of team1, and 0 if they rank the same. Requires access to teams, so that it knows whether @@ -83,7 +85,7 @@ def two_teams_left(key): if two_teams_left(lambda x: x.points) or two_teams_left(lambda x: (x.points, x.speaker_score)) \ or two_teams_left(lambda x: (x.points, x.speaker_score, x.draw_strength)): winner = who_beat_whom(team1, team2) - if winner != 0: # if this doesn't help, keep going + if winner != 0: # If this doesn't help, keep going return winner key = lambda x: (x.points, x.speaker_score, x.draw_strength) return cmp(key(team1), key(team2)) @@ -102,7 +104,7 @@ def two_teams_left(key): print "=" * 50 sorted_teams = list(teams) -random.shuffle(sorted_teams) # shuffle first, so that if teams are truly equal, they'll be in random order +random.shuffle(sorted_teams) # Shuffle first, so that if teams are truly equal, they'll be in random order sorted_teams.sort(cmp=cmp_teams, reverse=True) for team in sorted_teams: diff --git a/data/test/choices/judges.csv b/data/test/choices/judges.csv index d3eb5e5ca16..b8153342019 100644 --- a/data/test/choices/judges.csv +++ b/data/test/choices/judges.csv @@ -1,28 +1,28 @@ name,institution,test_score,institution_conflicts,team_conflicts,gender,pronoun,independent,novice,phone,email,notes Levi Flores,Yale University,5,,,male,they,0,0,(400) 258-4262,leviflores@gmail.com, -Boyd Pierce,Stanford University,5,,,M,he,1,0,(645) 106-7743,boydpierce@yahoo.com, -Eunice Mcbride,University of Toronto,5,,,female,she,0,0,(549) 309-9187,eunicemcbride@outlook.com, -Ramona Cobb,California Institute of Technology,1,Princeton,,F,she,1,0,(440) 487-5776,ramonacobb@yahoo.com, -Justin Ford,California Institute of Technology,5,,Caltech 1,M,he,0,0,(618) 921-9188,justinford@outlook.com, -Luis Bennett,Columbia University,2,,,M,he,0,0,(730) 097-8797,luisbennett@gmail.com, +Boyd Pierce, Stanford University ,5,,,M,he,1,0,(645) 106-7743,boydpierce@yahoo.com, +Eunice Mcbride,University of Toronto,5,,,female,she,0, 0,(549) 309-9187,eunicemcbride@outlook.com, +Ramona Cobb,California Institute of Technology,1, Princeton,,F,she,1, 0,(440) 487-5776,ramonacobb@yahoo.com, +Justin Ford,California Institute of Technology,5,,Custom Team Name,M,he,0,0,(618) 921-9188,justinford@outlook.com, +Luis Bennett,Columbia University,2,,,,he,0,0,(730) 097-8797,luisbennett@gmail.com, Mandy Estrada,Cornell University,5,,,female,,1,0,(559) 299-0471,mandyestrada@gmail.com, Leigh Mcgee,Harvard University,4,,,F,,0,0,(844) 760-9302,leighmcgee@gmail.com, -Jacqueline Freeman,Harvard University,5,Toronto,Caltech 2,m,,1,0,(297) 916-1716,jacquelinefreeman@yahoo.com, -Holly Howard,University of Toronto,5,Harvard,,FEMALE,,1,0,(958) 783-2610,hollyhoward@gmail.com, +Jacqueline Freeman,Harvard University,5,Toronto ,Caltech 2,m,,1 ,0,(297) 916-1716,jacquelinefreeman@yahoo.com, +Holly Howard,University of Toronto,5,Harvard,, FEMALE ,,1,0,(958) 783-2610,hollyhoward@gmail.com, Pedro Burgess,Toronto,4,,,,,0,0,(854) 441-0104,pedroburgess@yahoo.com, Kristy Carr,Stan,4,,MIT 2,M,,0,1,(644) 607-3297,kristycarr@yahoo.com, Wilma Vaughn,Johns Hopkins,4,,,MALE,,1,1,(398) 759-9537,wilmavaughn@outlook.com, Virginia Mccarthy,Johns Hopkins University,2,,,fEmAlE,,0,1,(455) 177-0459,virginiamccarthy@gmail.com, -Tasha Jenkins,Massachusetts Institute of Technology,2,"Cornell,Penn,Yale",Stan 1,,,0,1,(875) 519-9891,tashajenkins@outlook.com, -Toby Wong,Massachusetts Institute of Technology,5,Berkeley,,MALE,,0,0,(404) 641-5999,tobywong@gmail.com, +Tasha Jenkins,Massachusetts Institute of Technology,2,"Cornell,Penn,Yale",Stanford University 1,,,0,1,(875) 519-9891,tashajenkins@outlook.com, +Toby Wong,Massachusetts Institute of Technology,5,Berkeley,,MALE ,,0, 0 ,(404) 641-5999,tobywong@gmail.com, Jo Allen,Princeton University,2,,MIT 2,M,,0,0,(761) 993-2983,joallen@yahoo.com, Billy Griffin,Princeton University,2,,,M,,0,0,(430) 532-2939,billygriffin@outlook.com, Angela Reed,Stanford University,1,,Chicago 1,F,,0,0,(936) 500-1228,angelareed@yahoo.com, Hugo Lewis,Stanford University,2,,,M,,0,0,(422) 585-9609,hugolewis@outlook.com, -Cassandra Wilson,Berkeley,4,,Yale 2,F,,,0,(604) 306-2084,cassandrawilson@gmail.com, -George Willis,University of Chicago,2,Johns Hopkins University,,M,,0,0,(222) 204-5944,georgewillis@yahoo.com, -Jamie Hodges,University of Chicago,3,,,Female,,0,,(737) 122-6102,jamiehodges@outlook.com, -Bennie Rodriguez,University of Pennsylvania,2,Stan,,F,,0,,(537) 641-2175,bennierodriguez@gmail.com, -Allison Martin,Yale University,4,,,F,,,0,(525) 384-2715,allisonmartin@outlook.com, -Kristi Elliott,Yale University,3,,,F,,0,0,(790) 289-5430,kristielliott@gmail.com, +Cassandra Wilson,Berkeley,4,,Yale 2, ,,,0,(604) 306-2084,cassandrawilson@gmail.com, +George Willis,University of Chicago,2, Johns Hopkins University,,M,,0,0 ,(222) 204-5944,georgewillis@yahoo.com, +Jamie Hodges,University of Chicago,3,,,Female ,,0,,(737) 122-6102,jamiehodges@outlook.com, +Bennie Rodriguez,University of Pennsylvania,2,Stan,, F,,0,,(537) 641-2175,bennierodriguez@gmail.com, +Allison Martin,Yale University,4,,, ,,,0,(525) 384-2715,allisonmartin@outlook.com, +Kristi Elliott,Yale University, 3,,,F,,0,0,(790) 289-5430,kristielliott@gmail.com, Pearl Graves,Johns Hopkins University,5,,,F,,,0,(317) 721-2439,pearlgraves@outlook.com, diff --git a/deploy_heroku.py b/deploy_heroku.py index dea4cfacab9..ffecd47feff 100644 --- a/deploy_heroku.py +++ b/deploy_heroku.py @@ -3,46 +3,69 @@ This script is compatible with both Python 2.7 and Python 3.4 (and later).""" import argparse -import subprocess +import platform import re +import subprocess import sys -import platform # Arguments parser = argparse.ArgumentParser(description="Deploy Tabbycat to a new Heroku app.") -parser.add_argument("urlname", type=str, + +parser.add_argument( + "urlname", type=str, help="Name of the Heroku app. The app will be at urlname.herokuapp.com. Use '-' to use a Heroku-generated default.") -parser.add_argument("--no-open", action="store_false", default=True, dest="open", + +parser.add_argument( + "--no-open", action="store_false", default=True, dest="open", help="Don't open the Heroku website in your browser at the end") -parser.add_argument("--no-init-db", action="store_false", default=True, dest="init_db", + +parser.add_argument( + "--no-init-db", action="store_false", default=True, dest="init_db", help="Don't run initial migrations on the database") -parser.add_argument("--git-remote", type=str, default=None, + +parser.add_argument( + "--git-remote", type=str, default=None, help="Name of Git remote to use. Use '-' to use the urlname. If omitted, reverts to default Heroku behaviour.") -parser.add_argument("--git-branch", type=str, default=None, + +parser.add_argument( + "--git-branch", type=str, default=None, help="Git branch to push (defaults to current branch)") -parser.add_argument("--pg-plan", "--postgresql-plan", type=str, default="hobby-dev", + +parser.add_argument( + "--pg-plan", "--postgresql-plan", type=str, default="hobby-dev", help="Heroku Postgres plan (default hobby-dev)") -parser.add_argument("--import-tournament", type=str, metavar="IMPORT_DIR", + +parser.add_argument( + "--import-tournament", type=str, metavar="IMPORT_DIR", help="Also run the importtournament command, importing from IMPORT_DIR") -parser.add_argument("--dry-run", action="store_true", default=False, + +parser.add_argument( + "--dry-run", action="store_true", default=False, help="Print commands, don't run them.") config_group = parser.add_argument_group("heroku configuration settings") config_group.add_argument("--public-cache-timeout", type=int, default=None, metavar="TIMEOUT", - help="Set the public page cache timeout to TIMEOUT") + help="Set the public page cache timeout to TIMEOUT") config_group.add_argument("--tab-cache-timeout", type=int, default=None, metavar="TIMEOUT", - help="Set the tab page cache timeout to TIMEOUT") + help="Set the tab page cache timeout to TIMEOUT") config_group.add_argument("--enable-debug", action="store_true", default=False, - help="Enable Django debug pages") + help="Enable Django debug pages") # Import tournament arguments are copied from importtournament.py, and should be # updated when these options in importtournament.py change. -import_tournament_group = parser.add_argument_group("import tournament options", "Passed to the importtournament command. Ignored unless --import-tournament is used. Provided for convenience; to use other importtournament options, run the importtournament command separately instead.") -import_tournament_group.add_argument('-s', '--slug', type=str, action='store', default=None, dest="tournament_slug", +import_tournament_group = parser.add_argument_group( + "import tournament options", + "Passed to the importtournament command. Ignored unless " + + "--import-tournament is used. Provided for convenience; to use other " + + "importtournament options, run the importtournament command separately instead.") +import_tournament_group.add_argument( + '-s', '--slug', type=str, action='store', default=None, dest="tournament_slug", help='Override tournament slug. (Default: use name of directory.)'), -import_tournament_group.add_argument('--name', type=str, action='store', default=None, dest="tournament_name", +import_tournament_group.add_argument( + '--name', type=str, action='store', default=None, dest="tournament_name", help='Override tournament name. (Default: use name of directory.)'), -import_tournament_group.add_argument('--short-name', type=str, action='store', default=None, dest="tournament_short_name", +import_tournament_group.add_argument( + '--short-name', type=str, action='store', default=None, dest="tournament_short_name", help='Override tournament short name. (Default: use name of directory.)'), args = parser.parse_args() @@ -56,24 +79,29 @@ # Helper functions + def print_command(command): message = "$ " + " ".join(command) if use_color: message = "\033[1;36m" + message + "\033[0m" print(message) + def run_command(command): print_command(command) if not args.dry_run: subprocess.check_call(command, **subprocess_kwargs) + def make_heroku_command(command): return ["heroku"] + command + ["--app", urlname] + def run_heroku_command(command): command = make_heroku_command(command) run_command(command) + def get_output_from_command(command): print_command(command) output = subprocess.check_output(command, **subprocess_kwargs) @@ -82,11 +110,13 @@ def get_output_from_command(command): sys.stdout.flush() return output + def print_yellow(message): if use_color: message = "\033[1;33m" + message + "\033[0m" print(message) + def get_git_push_spec(): if args.git_branch: return "master" if args.git_branch == "master" else args.git_branch + ":master" @@ -142,18 +172,19 @@ def get_git_push_spec(): if args.init_db: print_yellow("Now creating a superuser for the Heroku site.") print_yellow("You'll need to respond to the prompts:") - run_heroku_command(["run", "python", "manage.py", "createsuperuser"]) + run_heroku_command(["run", "python", "tabbycat/manage.py", "createsuperuser"]) - command = make_heroku_command(["run", "python", "manage.py", "generate_secret_key"]) + command = make_heroku_command(["run", "python", "tabbycat/manage.py", "generate_secret_key"]) secret_key = get_output_from_command(command) - secret_key = secret_key.strip().split()[0].strip() # turn command output into string of just the key + # Turn command output into string of just the key + secret_key = secret_key.strip().split()[0].strip() print_yellow("Made secret key: \"%s\"" % secret_key) command = ["config:add", "DJANGO_SECRET_KEY=%s" % secret_key] run_heroku_command(command) # Import tournament, if provided if args.import_tournament: - command = ["run", "python", "manage.py", "importtournament", args.import_tournament] + command = ["run", "python", "tabbycat/manage.py", "importtournament", args.import_tournament] if args.tournament_slug: command += ["--slug", args.tournament_slug] if args.tournament_name: diff --git a/docs/about/tournament-history.rst b/docs/about/tournament-history.rst index 0294afbfa4b..d8f13f3b2b5 100644 --- a/docs/about/tournament-history.rst +++ b/docs/about/tournament-history.rst @@ -10,8 +10,10 @@ A list of tournaments (that we know of) which have used Tabbycat. - ACT Debating Union Grades - `Australian Easters `_ - IIT KGP PD +- `Malaysia Debate Open 2016 `_ - `Mad Mini `_ - `New Zealand Easters `_ +- `Perth Australs `_ - Pre SSIDC - Thailand United Asian Debating Championships ``_ - The National Law School Debate diff --git a/docs/conf.py b/docs/conf.py index 4ab3e583529..de6b674e69f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,6 +31,7 @@ # ones. extensions = [ 'sphinx.ext.todo', + 'sphinx.ext.imgmath', ] # Add any paths that contain templates here, relative to this directory. @@ -57,9 +58,9 @@ # built documents. # # The short X.Y version. -version = '0.9' +version = '1.0' # The full version, including alpha/beta/rc tags. -release = '0.9.0' +release = '1.0.0' rst_epilog = """ .. |vrelease| replace:: v{release} diff --git a/docs/features/adjudicator-feedback.rst b/docs/features/adjudicator-feedback.rst index 0711c92d9a7..74174a89fb7 100644 --- a/docs/features/adjudicator-feedback.rst +++ b/docs/features/adjudicator-feedback.rst @@ -6,9 +6,15 @@ 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. -The only current method of setting questions is through the :ref:`edit data interface `. Go to the **Edit Data**, then click **Change** next to *Adjudicator feedback questions*. You can add questions here. +Currently, there are two methods of setting questions: -Most of what you need to know is explained in help text on that page. Some more details are here. +- through the :ref:`edit database area `. Go to **Setup** > + **Edit Database**, then click **Change** next to *Adjudicator feedback + questions*. You can add questions here. +- using the :ref:`importtournament command `. + +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 ======================== @@ -46,29 +52,96 @@ Options: Want another answer type? ========================= -If the above answer types don't cover your needs, please contact us using the contact details in the :ref:`authors` section. If it's easy enough to add your requested type and if you give us enough notice, we'll gladly add it for you. We should warn you though: we don't intend to develop Tabbycat feedback into a fully-fledged `SurveyMonkey `_ or `Google Forms `_-style system. If your request amounts to this, we suggest using a third-party system. +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 :ref:`feedback-questionnaires` below). If you think there is such a case, +please contact us using the contact details in the :ref:`authors` section. -As a guide, a type is "easy enough to add" if you can imagine easily how to implement it using standard web page elements, and it requires only basic structure encompassing only a single question. +.. _feedback-questionnaires: Different questionnaires ======================== -Tabbycat allows you to specify two questionnaires: team-on-orallist, and adjudicator-on-adjudicator. You must specify in each question whether to include the question in each questionnaire. - -- **team on orallist**, if checked, includes the question on all team-on-orallist forms. -- **chair on panellist**, if checked, includes the question on *all* adjudicator-on-adjudicator forms. - -.. note:: The **panellist on panellist** and **panellist on chair** don't currently do anything, and **chair on panellist** is a misnomer, it actually means **adjudicator on adjudicator**. These are all there for future support. +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. + +.. admonition:: Advanced users + :class: tip + + 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 as equal to: +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: -``Test Score x (1 - Current Round's Feedback Weight) + (Current Round's Feedback Weight * Average Feedback Score)`` +.. math:: -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. + \textrm{score} = (1-w)\times\textrm{test score} + w\times\textrm{average feedback score} -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. +where :math:`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. \ No newline at end of file diff --git a/docs/features/breaks.rst b/docs/features/breaks.rst index 2134a63376c..4dc692e15d9 100644 --- a/docs/features/breaks.rst +++ b/docs/features/breaks.rst @@ -1,33 +1,179 @@ +.. _breaks: + ========================= Breaks and Break Rounds ========================= -Creating Break Categories -========================= +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". -Each tournament may have a single or multiple break categories that group a particular series of out-rounds such as an "Open" or "ESL" break. +About break categories +====================== -At the moment new break rounds must be added through the **edit data** interface (available in the **Setup** section once in a tournament). Once there go to **Break Qualification** > **break categories** and click **Add break category**. The fields required for each category should be relatively self-explanatory. +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. -Setting Break Eligibility -========================= +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. + +.. _breakqual-rules: + +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 | Description | +| use in ``importtournament`` | | +| CSV files) | | ++=============================+=========================================================+ +| **Standard** | The top *n* teams break. This is the default, and | +| (``standard``) | most tournaments use this rule. | ++-----------------------------+---------------------------------------------------------+ +| **AIDA Pre-2015** | The top *n* teams that are also in the top three teams | +| (``aida-pre2015``) | from their institution break. | ++-----------------------------+---------------------------------------------------------+ +| **AIDA 2016 (Australs)** | The top *n* teams that fulfil either of these criteria | +| (``aida-2016-australs``) | 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 *n*\ th-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)** | As for AIDA 2016 (Australs), except that if fewer than | +| (``aida-2016-easters``) | *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 | The division winners are taken first, then the best | +| first** | teams who did not win their division are added to make | +| (``wadl-div-first``) | *n* teams. | ++-----------------------------+---------------------------------------------------------+ +| **WADL division winners | The division winners are guaranteed to break, and the | +| guaranteed** | best teams who did not win their division are added | +| (``wadl-div-guaranteed``) | 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. -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**. +If you create your tournament using the `importtournament` command or in **Edit +Database**, you'll need to do all three steps above yourself. -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. +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 :ref:`breakqual-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. -Determining a Break -=================== +Generating the break +==================== -Unlike team or speaker standings, each category's break ranks are not determined automatically and updated continuously. Instead each can be calculated (and re-calculated) as desired. +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. +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). +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). -Creating Draws for Break Rounds +.. 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 =============================== -TODO \ No newline at end of file +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. diff --git a/docs/features/data-entry.rst b/docs/features/data-entry.rst index b1f3ac33d11..24d52cecb0e 100644 --- a/docs/features/data-entry.rst +++ b/docs/features/data-entry.rst @@ -40,7 +40,7 @@ As a general principle, Tabbycat requires all ballots to be looked at by two peo 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 Data** 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. +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. diff --git a/docs/features/draw-generation.rst b/docs/features/draw-generation.rst index 9f6514c26fd..cffbcbbb51b 100644 --- a/docs/features/draw-generation.rst +++ b/docs/features/draw-generation.rst @@ -89,8 +89,8 @@ 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 ``import_tournament`` command, it reads sides from the file sides.csv. -* You can do this from the Django admin interface (under Setup > Edit Data) by going to the relevant team and adding a **team position allocation** entry. That is: +* If you're using the :ref:`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: #. Click **Admin** on the bottom right of any page after logging into an account with :ref:`superuser access `. #. Next to **Teams**, click **Change**. diff --git a/docs/features/user-accounts.rst b/docs/features/user-accounts.rst index 9a646a23d0d..88add36abb2 100644 --- a/docs/features/user-accounts.rst +++ b/docs/features/user-accounts.rst @@ -15,7 +15,7 @@ For obvious reasons, user logins are required to data entry and administrative f +-----------+--------------------+------------------------------------------------+-----------------------------------------------------------------------------------------------------+ | 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 data interfaces. | Editing the database directly. | +| Staff | Tab director | The Tabbycat and edit database interfaces. | Editing the database directly. | +-----------+--------------------+------------------------------------------------+-----------------------------------------------------------------------------------------------------+ Account roles @@ -25,7 +25,7 @@ If the adjudication core and tab directors will be helping with data entry, you 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](data-entry.md) procedure, for example, to unconfirm a ballot or edit a score. -The **Edit Data** 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. +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 =============== diff --git a/docs/features/venue-constraints.rst b/docs/features/venue-constraints.rst index f6a976b689d..a5593623fea 100644 --- a/docs/features/venue-constraints.rst +++ b/docs/features/venue-constraints.rst @@ -27,7 +27,7 @@ save human effort (and time) in specially allocating rooms. Adding venue constraints ======================== -To add a venue constraint, go to the **Edit Data** section (under Setup), scroll +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 diff --git a/docs/index.rst b/docs/index.rst index cf5547b6c2d..e1024c64b09 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -39,9 +39,9 @@ tournaments. features/breaks features/data-entry features/draw-generation - features/data-importers features/printing features/team-standings-rules + features/data-importers features/user-accounts features/venue-constraints diff --git a/docs/install/heroku.rst b/docs/install/heroku.rst index a2371fe2ad6..825b8511dbd 100644 --- a/docs/install/heroku.rst +++ b/docs/install/heroku.rst @@ -52,7 +52,7 @@ If you want to :ref:`import tournament data ` from CSV f git commit -am "Add data for " git push heroku master - heroku run dj importtournament --slug --name --short-name + heroku run tabbycat/manage.py importtournament --slug --name --short-name 1. Install dependencies ----------------------- @@ -82,7 +82,7 @@ Open a command shell. Navigate to an appropriate directory on your computer usin 1. Navigate to your Tabbycat directory:: - cd path/to/my/tabbycat + cd path/to/my/tabbycat/directory 2. Run the script to deploy the app to Heroku. Replace ```` with your preferred URL. Your website will be at ``.herokuapp.com``. @@ -123,7 +123,7 @@ In order to use the ``importtournament`` command directly on the server, your da 3. Run this command, replacing ```` with your own names:: - heroku run dj importtournament --slug --name --short-name + heroku run tabbycat/manage.py importtournament --slug --name --short-name Addons ====== diff --git a/docs/install/linux.rst b/docs/install/linux.rst index e71b639b3c6..9f8d2a56b76 100644 --- a/docs/install/linux.rst +++ b/docs/install/linux.rst @@ -41,6 +41,7 @@ Then create local_settings.py as described :ref:`below `, pip install --upgrade pip pip install -r requirements_common.txt npm install + cd tabbycat dj migrate dj collectstatic dj createsuperuser @@ -141,11 +142,27 @@ Almost there! 1. Navigate to your Tabbycat directory:: - $ cd path/to/my/tabbycat + $ cd path/to/my/tabbycat/directory .. _local-settings-linux: -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: +2. Start a new virtual environment. We suggest the name ``venv``, though it can be any name you like: + + .. code:: bash + + $ python3 -m venv venv + +3. Run the ``activate`` script. This puts you "into" the virtual environment:: + + $ source venv/bin/activate + +4. Install Tabbycat's requirements into your virtual environment:: + + $ pip install --upgrade pip + $ pip install -r requirements_common.txt + $ npm install + +5. 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: .. code:: python @@ -160,24 +177,9 @@ Almost there! } } -3. Start a new virtual environment. We suggest the name ``venv``, though it can be any name you like: - - .. code:: bash - - $ python3 -m venv venv - -4. Run the ``activate`` script. This puts you "into" the virtual environment:: - - $ source venv/bin/activate - -5. Install Tabbycat's requirements into your virtual environment:: - - $ pip install --upgrade pip - $ pip install -r requirements_common.txt - $ npm install - -6. Initialize the database, compile the assets, and create a user account for yourself:: +6. 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 @@ -203,6 +205,7 @@ Starting up an existing Tabbycat instance ========================================= To start your Tabbycat instance up again next time you use your computer:: - $ cd path/to/my/tabbycat + $ cd path/to/my/tabbycat/directory $ source venv/bin/activate + $ cd tabbycat $ waitress-serve wsgi:application diff --git a/docs/install/osx.rst b/docs/install/osx.rst index 6915808e18e..f0a4d12d601 100644 --- a/docs/install/osx.rst +++ b/docs/install/osx.rst @@ -91,7 +91,7 @@ Almost there! 1. Navigate to your Tabbycat directory:: - $ cd path/to/my/tabbycat + $ 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: @@ -121,10 +121,10 @@ Almost there! $ pip install --upgrade pip $ pip install -r requirements_common.txt $ npm install - $ bower install -6. Initialize the database, compile the assets, and create a user account for yourself:: +6. 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 @@ -150,6 +150,7 @@ Starting up an existing Tabbycat instance ================================================================================ To start your Tabbycat instance up again next time you use your computer:: - $ cd path/to/my/tabbycat + $ cd path/to/my/tabbycat/directory $ source venv/bin/activate + $ cd tabbycat $ waitress-serve wsgi:application diff --git a/docs/install/windows.rst b/docs/install/windows.rst index bd10d9483f7..8f09e177e57 100644 --- a/docs/install/windows.rst +++ b/docs/install/windows.rst @@ -114,7 +114,7 @@ Download and run the `node.js Windows Installer (.msi) (If you really don't know what to pick, use "tabbycat".) + - 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.) @@ -194,6 +194,7 @@ Almost there! 6. Initialize the database and create a user account for yourself:: + > cd tabbycat > dj migrate > dj collectstatic > dj createsuperuser @@ -223,4 +224,5 @@ To start your Tabbycat instance up again next time you use your computer, open a > Set-Location C:\Users\myusername\Documents\GitHub\tabbycat # or wherever your installation is > .\venv\Scripts\activate + > cd tabbycat > waitress-serve wsgi:application diff --git a/docs/requirements.txt b/docs/requirements.txt index efc1019505b..a47d5c441e9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,3 @@ -sphinx +sphinx>=1.4 sphinx-autobuild livereload==2.4.1 \ No newline at end of file diff --git a/docs/use/finishing-a-tournament.rst b/docs/use/finishing-a-tournament.rst index 9f65343155d..207e1f56c11 100644 --- a/docs/use/finishing-a-tournament.rst +++ b/docs/use/finishing-a-tournament.rst @@ -13,4 +13,4 @@ Tabs can be released using the *Tab released* option under **Setup** > **Configu 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 Data** area, find the tournament and hit "release all" so that the results for the final round can be released. +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. diff --git a/docs/use/importing-data.rst b/docs/use/importing-data.rst index 5a83a6aa8e4..2436e159ec3 100644 --- a/docs/use/importing-data.rst +++ b/docs/use/importing-data.rst @@ -13,7 +13,7 @@ Once you've got Tabbycat installed, the next step is to import data for the tour Manual setup ============ -For sufficiently small tournaments, you might just choose to edit the database via the Django administrative interface (under Setup > Edit Data). +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. @@ -34,10 +34,12 @@ For medium sized tournaments there are a number of tools that allow you to impor .. 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 ``import_tournament`` command +.. _importtournament-command: + +The ``importtournament`` command ================================= -We've written a management command called ``import_tournament`` 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. +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. @@ -45,18 +47,18 @@ We've written a management command called ``import_tournament`` to help automate :: - $ ./manage.py import_tournament YOUR_DATA_DIR [--slug SLUG] [--short-name SHORT_NAME] [--name FULL_NAME] + $ ./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 import_tournament --help + $ ./manage.py importtournament --help 4. Assuming the command completes successfully without errors, you should double check the data in the Django interface, as described above in :ref:`import-manual-setup`. In particular you should check that the *Rounds* have the correct draw types and that silent rounds have been marked correctly. -``import_tournament`` on Heroku installs +``importtournament`` on Heroku installs ======================================== -The ``import_tournament`` script can be run on Heroku directly; you just need to commit and push your new data directory to your server first. See :ref:`install-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. +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 :ref:`install-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. diff --git a/docs/use/starting-a-tournament.rst b/docs/use/starting-a-tournament.rst index 4073fe38f00..1e5375b1f25 100644 --- a/docs/use/starting-a-tournament.rst +++ b/docs/use/starting-a-tournament.rst @@ -19,7 +19,7 @@ Here you can adjust the debate rules and interface options to your liking then h 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 Data** area (link is in the menu under **Setup**). +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 :ref:`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. @@ -43,8 +43,8 @@ Participants > Adjudicators 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 uncessary. - - If you do have composite teams, and wish to have them be conflicted by ajudicators from each respective instutution, you'll need to add a new team conflict to each adjudicator from each institution. + - 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 diff --git a/draw/templates/draw_confirmed.html b/draw/templates/draw_confirmed.html deleted file mode 100644 index 723cd57361c..00000000000 --- a/draw/templates/draw_confirmed.html +++ /dev/null @@ -1,305 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} - -{% block page-title %}Draw for {{ round.name }}{% endblock %} -{% block head-title %} - 👀Draw for {{ round.name }} -{% endblock %} -{% block sub-title %} - {% if round.draw_status = round.STATUS_CONFIRMED %} - draw is confirmed but not released; - {% elif round.draw_status = round.STATUS_RELEASED %} - draw is confirmed and released; - {% else %} - DRAW STATUS ERROR, - {% endif %} - motions {{ round.motions_released|yesno:",are not" }} released -{% endblock %} - -{% block page-subnav-sections %} - - Edit Adjudicators - - - Edit Motions - - - Edit Venues - - - Edit Matchups - - {% if pref.allocation_confirmations %} - - Shift Confirms - - {% endif %} - {% if pref.enable_division_motions %} - - Assign Motions to Divisions - - {% endif %} - - - View Draw Details - - - Regenerate Draw - - -{% endblock %} - -{% block page-subnav-actions %} - - Enter Results - -{% endblock %} - -{% block page-alerts %} - {% if round.motion_set.all.count == 0 %} -
- There are currently no motions entered, which means results cannot be entered. Edit the motions. -
- {% endif %} - {% if not round.venue_allocation_valid %} -
- One or more debates does not have a venue Edit the venues. -
- {% endif %} - {% if active_adjs.count < draw.count %} -
- There are currently fewer checked-in adjudicators than there are rooms. Check in some more adjudicators. -
- {% else %} - {% if round.adjudicators_allocation_validity > 0 %} -
- {% if round.adjudicators_allocation_validity == 1 %} - One or more debates don't have a chair. - {% elif round.adjudicators_allocation_validity == 2 %} - One or more debates have panels with an even number of adjudicators. - {% endif %} - Edit adjudicators. -
- {% endif %} - {% endif %} - - {% if round.draw_status = round.STATUS_RELEASED and not pref.public_draw %} -
- You have released the draw, but it will not show to the public unless - 'public view of draw' setting is enabled in - this tournament's - configuration. -
- {% endif %} - - {% if round.motions_released and not pref.public_motions %} -
- You have released the motions, but they will not show to the public unless the - 'public view of motions' setting is enabled in - this tournament's - configuration. -
- {% endif %} - -{% endblock %} - -{% block content %} - -
-
- - - - - - {% if round.motions_released %} -
- {% csrf_token %} - -
- {% else %} -
- {% csrf_token %} - -
- {% endif %} - {% if round.draw_status = round.STATUS_CONFIRMED %} -
- {% csrf_token %} - -
- {% elif round.draw_status = round.STATUS_RELEASED %} -
- {% csrf_token %} - -
- {% endif %} - - - -
- -
- - - - {% if pref.enable_divisions %} - - {% else %} - - {% endif %} - {% if pref.enable_venue_groups %} - - {% endif %} - - {% if pref.enable_debate_scheduling %} - - {% endif %} - {% if pref.enable_debate_scheduling %} - - {% endif %} - - - - - - - - {% for debate in draw %} - - {% if pref.enable_divisions %} - - {% else %} - - {% endif %} - {% if pref.enable_venue_groups %} - {% if debate.division %} - - {% else %} - - {% endif %} - {% endif %} - - {% if pref.enable_debate_scheduling %} - - - {% endif %} - - - {% include "tables/debate_adjudicators_compact.html" %} - - - {% endfor %} - -
{{ debate.division.name }}Venue{% if pref.side_allocations_unknown == 'manual-ballot' %}Team 1{% else %}Affirmative{% endif %}{% if pref.side_allocations_unknown == 'manual-ballot' %}Team 2{% else %}Negative{% endif %}AdjsConflict
{{ debate.division.name }}{{ debate.bracket }}{{ debate.division.venue_group.short_name }}{{ debate.venue.group.short_name }}{{ debate.venue.name }} - {% if debate.time %} - - {{ debate.time|date:"D jS F" }} - {% endif %} - - {{ debate.time|time:'h:i A' }} - - {% include "tables/team.html" with team=debate.aff_team %} - {% if round.is_break_round %} - {% break_rank debate.aff_team round %} - {% endif %} - - {% include "tables/team.html" with team=debate.neg_team %} - {% if round.is_break_round %} - {% break_rank debate.neg_team round %} - {% endif %} - {{ debate.all_conflicts|join:",
" }}
-
-
- - - -{% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/draw/templates/draw_display_by.html b/draw/templates/draw_display_by.html deleted file mode 100644 index 3529e4d1d4a..00000000000 --- a/draw/templates/draw_display_by.html +++ /dev/null @@ -1,59 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} -{% load static %} - -{% block head-title %} - 👏Draw for {{ round.name }} - {% if round.starts_at %} - debates start at {{ round.starts_at }} - {% endif %} -{% endblock %} -{% block page-title %}Draw for {{ round.name }}{% endblock %} -{% block sub-title %}ESC stops scroll{% endblock %} - - -{% block nav %} - {# For admins the draw opens without menu (for displaying publicly)#} - {% if 'admin/' in request.path and user.is_superuser %} -
- {% else %} - {{ block.super }} - {% endif %} -{% endblock %} - -{% block footer %}{% endblock %} - -{% block page-subnav-sections %} - Scroll - - Text -
- XS - S - M - L - XL -
- {% include "tables/table_search.html" %} -{% endblock %} - -{% block extra-js %} - - -{% endblock extra-js %} diff --git a/draw/templates/draw_display_by_team.html b/draw/templates/draw_display_by_team.html deleted file mode 100644 index 50ecff88fe8..00000000000 --- a/draw/templates/draw_display_by_team.html +++ /dev/null @@ -1,98 +0,0 @@ -{% extends "draw_display_by.html" %} -{% load debate_tags %} -{% load static %} - -{% block content %} - -
-
- - - - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.enable_debate_scheduling %} - - - {% endif %} - - - - - - - {% for debate in draw %} - - - {% if pref.show_emoji %} - - {% endif %} - {% if pref.enable_venue_groups %} - {% if debate.division %} - - {% else %} - - {% endif %} - {% else %} - - {% endif %} - {% if pref.enable_debate_scheduling %} - - {% if pref.enable_debate_scheduling %} - {% include "tables/debate_status.html" %} - {% endif %} - {% endif %} - - - {% include "tables/debate_adjudicators.html" %} - {% endfor %} - {% for debate in draw %} - - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.enable_debate_scheduling %} - - - {% endif %} - - - {% include "tables/debate_adjudicators.html" %} - {% endfor %} - -
Team{% if pref.side_allocations_unknown == 'manual-ballot' %}Team 1{% else %}Aff{% endif %}{% if pref.side_allocations_unknown == 'manual-ballot' %}Team 2{% else %}Neg{% endif %}Adjs
- {% include "tables/team.html" with team=debate.aff_team %} - - {{ debate.aff_team.emoji }} - {{ debate.division.venue_group.short_name }}{{ debate.venue.group.short_name }} {{ debate.venue.name }}{{ debate.venue.name }} - {% if debate.time %} - - {{ debate.time|date:"D jS F" }} - {% endif %} - - {% include "tables/team.html" with team=debate.aff_team %} - - {% include "tables/team.html" with team=debate.neg_team %} -
- {% include "tables/team.html" with team=debate.neg_team %} - {{ debate.neg_team.emoji }} - {% if debate.division.venue_group %}{{ debate.division.venue_group.short_name }}{% else %}{{ debate.venue.name }} {% endif %} - - - {{ debate.time|date:"D jS F" }} - - {{ debate.time|time:'h:i A' }} - - {% include "tables/team.html" with team=debate.aff_team %} - - {% include "tables/team.html" with team=debate.neg_team %} -
-
-
- -{% endblock content %} \ No newline at end of file diff --git a/draw/templates/draw_display_by_venue.html b/draw/templates/draw_display_by_venue.html deleted file mode 100644 index 54cf3f2152f..00000000000 --- a/draw/templates/draw_display_by_venue.html +++ /dev/null @@ -1,92 +0,0 @@ -{% extends "draw_display_by.html" %} -{% load debate_tags %} -{% load static %} - -{% block content %} - -
-
- - - - {% if pref.enable_divisions %} - - {% endif %} - - {% if pref.enable_debate_scheduling %} - - - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.enable_division_motions %} - - {% endif %} - {% if not pref.enable_divisions %} - - {% endif %} - - - - {% for debate in draw %} - - {% if pref.enable_divisions %} - - {% endif %} - {% if pref.enable_venue_groups %} - {% if debate.division %} - - {% else %} - - {% endif %} - {% else %} - - {% endif %} - {% if pref.enable_debate_scheduling %} - {% include "tables/debate_status.html" %} - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.enable_division_motions %} - - {% endif %} - {% if not pref.enable_divisions %} - {% include "tables/debate_adjudicators.html" %} - {% endif %} - - {% endfor %} - -
{% if pref.side_allocations_unknown == 'manual-ballot' %}Team 1{% else %}Aff{% endif %}{% if pref.side_allocations_unknown == 'manual-ballot' %}Team 2{% else %}Neg{% endif %}MotionAdjs
{{ debate.division.name }}{{ debate.division.venue_group.short_name }}{{ debate.venue.group.short_name }} {{ debate.venue.name }}{{ debate.venue.name }} - {{ debate.aff_team.emoji }} - - {% if debate.aff_team.type != 'B' %} - {% include "tables/team.html" with team=debate.aff_team %} - {% endif %} - - {{ debate.neg_team.emoji }} - - {% if debate.neg_team.type != 'B' %} - {% include "tables/team.html" with team=debate.neg_team %} - {% endif %} - - {% for motion in debate.division_motion %} - {{ motion.reference }} - (view) - {% endfor %} -
-
-
- -{% endblock content %} diff --git a/draw/templates/draw_draft.html b/draw/templates/draw_draft.html deleted file mode 100644 index 01f4cd9d4aa..00000000000 --- a/draw/templates/draw_draft.html +++ /dev/null @@ -1,44 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} - -{% block page-title %}Draw for {{ round.name }} (DRAFT){% endblock %} -{% block head-title %} 👀Draw for {{ round.name }}{% endblock %} -{% block sub-title %}(DRAFT DRAW){% endblock %} - -{% block page-subnav-actions %} - -
- {% csrf_token %} -
-{% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} - -{% block content %} - {% include "draw_with_standings_content.html" %} -{% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/draw/templates/draw_index.html b/draw/templates/draw_index.html deleted file mode 100644 index f6bf5cd9c82..00000000000 --- a/draw/templates/draw_index.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "base.html" %} - -{% block head-title %}Draw{% endblock %} -{% block page-title %}Draw{% endblock %} - -{% block content %} - Content here -{% endblock %} diff --git a/draw/templates/draw_matchups_edit.html b/draw/templates/draw_matchups_edit.html deleted file mode 100644 index 7f00b0fabbf..00000000000 --- a/draw/templates/draw_matchups_edit.html +++ /dev/null @@ -1,206 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} - -{% block nav %}
{% endblock %} - -{% block head-title %}Edit Matchups for {{ round.abbreviation }}{% endblock %} -{% block page-title %}Edit Matchups for {{ round.abbreviation }}{% endblock %} -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} - Save Matchups - Quit -{% endblock %} - - -{% block content %} -
- -
- - - - - - - - -
Unused Teams
- {% for team in round.unused_teams %} -
- {{ team.short_name }} {% if team.division %}(Div{{ team.division.name }}){% endif %} -
- {% endfor %} -
- -
-
-
-
- - - - - - - - - - - - {% for debate in draw %} - - - - - {% include "tables/debate_adjudicators_compact.html" %} - - {% endfor %} - {% for debate in possible_debates %} - - - - - - - {% endfor %} - -
AffNegAdjudicators
- {{ debate.venue }} - - {% if debate.aff_team %} -
- {{ debate.aff_team.short_name }} {% if debate.aff_team.division %}(Div{{ debate.aff_team.division.name }}){% endif %} -
- {% endif %} -
- {% if debate.neg_team %} -
- {{ debate.neg_team.short_name }} {% if debate.neg_team.division %}(Div{{ debate.neg_team.division.name }}){% endif %} -
- {% endif %} -
- -
- -
-
- -
-
-{% endblock content %} - -{% block footer %}{% endblock footer %} - -{% block extra-js %} - - -{% endblock extra-js %} diff --git a/draw/templates/draw_none.html b/draw/templates/draw_none.html deleted file mode 100644 index be9f27aba99..00000000000 --- a/draw/templates/draw_none.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} - -{% block page-title %} - {{ round.name }}'s draw has not been generated -{% endblock %} -{% block head-title %} - 👀No draw for {{ round.name }} -{% endblock %} - - -{% block page-alerts %} - -
- No draw exists yet — go to the - check-ins section to generate a draw. -
- -{% endblock %} diff --git a/draw/templates/draw_with_standings.html b/draw/templates/draw_with_standings.html deleted file mode 100644 index 00df4b37671..00000000000 --- a/draw/templates/draw_with_standings.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "base.html" %} - -{% load debate_tags %} - -{% block head-title %}Draw for {{ round.name }} with Details {% endblock %} -{% block page-title %}Draw for {{ round.name }} with Details{% endblock %} - -{% block page-subnav-sections %} - -{% endblock %} - -{% block content %} - - {% include "draw_with_standings_content.html" %} - -{% endblock content %} diff --git a/draw/templates/draw_with_standings_content.html b/draw/templates/draw_with_standings_content.html deleted file mode 100644 index fc45f7e292d..00000000000 --- a/draw/templates/draw_with_standings_content.html +++ /dev/null @@ -1,80 +0,0 @@ -{% load debate_tags %} -{% load metricformat %} -
-
- - - - {% if pref.enable_divisions %} - - {% else %} - - {% endif %} - - - {% if round.is_break_round %} - - - {% else %} - - - {% endif %} - {% for info in standings.metrics_info %} - - - {% endfor %} - - - - - - - {% for debate in draw %} - - - - - {% if round.is_break_round %} - - - {% else %} - - - {% endif %} - {% for metric in debate.metrics %} - - - {% endfor %} - - - - - {% endfor %} - -
AffNegAff Break RankNeg Break RankASRNSR - {% if info.glyphicon %} - A - {% else %} - A{{ info.abbr }} - {% endif %} - - {% if info.glyphicon %} - N - {% else %} - N{{ info.abbr }} - {% endif %} - AAffsNAffsConflicts/Flags
- {{ debate.bracket }} - - {% include "tables/team.html" with team=debate.aff_team %} - - {% include "tables/team.html" with team=debate.neg_team %} - {{ debate.aff_breakrank }}{{ debate.neg_breakrank }}{{ debate.aff_subrank.0 }}{% if debate.aff_subrank.1 %}={% endif %}{{ debate.neg_subrank.0 }}{% if debate.neg_subrank.1 %}={% endif %}{{ metric.0|metricformat }}{{ metric.1|metricformat }} - {% aff_count debate.aff_team debate.round.prev %} - - {% aff_count debate.neg_team debate.round.prev %} - - {{ debate.draw_conflicts|add:debate.flags_all|join:", " }} -
-
-
diff --git a/draw/templates/public_draw_released.html b/draw/templates/public_draw_released.html deleted file mode 100644 index 862f3ac0bb8..00000000000 --- a/draw/templates/public_draw_released.html +++ /dev/null @@ -1,3 +0,0 @@ -{% extends "draw_display_by_venue.html" %} -{% load debate_tags %} -{% load static %} diff --git a/draw/templates/public_draw_unreleased.html b/draw/templates/public_draw_unreleased.html deleted file mode 100644 index d17c3b96d3b..00000000000 --- a/draw/templates/public_draw_unreleased.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} - -{% block head-title %}{{ round.name }} Draw{% endblock %} -{% block page-title %}{{ round.name }} Draw{% endblock %} - -{% block content %} -
-
-

The draw for {{ round.name }} has yet to be released 😴

-
-
-{% endblock %} diff --git a/draw/templates/side_allocations.html b/draw/templates/side_allocations.html deleted file mode 100644 index f95e6675e7f..00000000000 --- a/draw/templates/side_allocations.html +++ /dev/null @@ -1,49 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} - -{% block head-title %}Side Allocations{% endblock %} -{% block page-title %}Side Allocations{% endblock %} - -{% block content %} -
-
- - - - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for round in rounds %} - - {% endfor %} - - - - {% for team in teams %} - - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for side in team.side_allocations %} - - {% endfor %} - - {% endfor %} - -
TeamInst{{ round.abbreviation }}
{{ team.emoji }} - {% include "tables/team.html" with team=team %}{{ team.break_categories_str }} - {{ team.institution.code }}{{ side }}
- -
-
-{% endblock content %} \ No newline at end of file diff --git a/draw/urls_admin.py b/draw/urls_admin.py deleted file mode 100644 index 871839a381e..00000000000 --- a/draw/urls_admin.py +++ /dev/null @@ -1,82 +0,0 @@ -from django.conf.urls import url - -from . import views - -urlpatterns = [ - - # Display - url(r'^round/(?P\d+)/$', - views.draw, - name='draw'), - url(r'^round/(?P\d+)/details/$', - views.draw_with_standings, - name='draw_with_standings'), - url(r'^round/(?P\d+)/display_by_venue/$', - views.draw_display_by_venue, - name='draw_display_by_venue'), - url(r'^round/(?P\d+)/display_by_team/$', - views.draw_display_by_team, - name='draw_display_by_team'), - - # Print - url(r'^round/(?P\d+)/print/scoresheets/$', - views.PrintScoreSheetsView.as_view(), - name='draw_print_scoresheets'), - url(r'^round/(?P\d+)/print/feedback/$', - views.PrintFeedbackFormsView.as_view(), - name='draw_print_feedback'), - url(r'^round/(?P\d+)/master_sheets/list/$', - views.master_sheets_list, - name='master_sheets_list'), - url(r'^round/(?P\d+)/master_sheets/venue_group/(?P\d+)/$', - views.master_sheets_view, - name='master_sheets_view'), - url(r'^round/(?P\d+)/room_sheets_view/venue_group/(?P\d+)/$', - views.room_sheets_view, - name='room_sheets_view'), - - # Creation/Release - url(r'^round/(?P\d+)/create/$', - views.CreateDrawView.as_view(), - name='create_draw'), - url(r'^round/(?P\d+)/confirm/$', - views.confirm_draw, - name='confirm_draw'), - url(r'^round/(?P\d+)/confirm_regenerate/$', - views.draw_confirm_regenerate, - name='draw_confirm_regenerate'), - url(r'^round/(?P\d+)/regenerate/$', - views.draw_regenerate, - name='draw_regenerate'), - url(r'^round/(?P\d+)/release/$', - views.release_draw, - name='release_draw'), - url(r'^round/(?P\d+)/unrelease/$', - views.unrelease_draw, - name='unrelease_draw'), - - # Side Editing - url(r'^side_allocations/$', - views.side_allocations, - name='side_allocations'), - url(r'^round/(?P\d+)/matchups/edit/$', - views.draw_matchups_edit, - name='draw_matchups_edit'), - url(r'^round/(?P\d+)/matchups/save/$', - views.save_matchups, - name='save_matchups'), - - # Scheduling - url(r'^round/(?P\d+)/schedule_debates/$', - views.schedule_debates, - name='schedule_debates'), - url(r'^round/(?P\d+)/schedule_debates/save/$', - views.apply_schedule, - name='apply_schedule'), - url(r'^round/(?P\d+)/start_time/set/$', - views.SetRoundStartTimeView.as_view(), - name='set_round_start_time'), - url(r'^round/(?P\d+)/confirms/$', - views.confirmations_view, - name='confirmations_view'), -] diff --git a/draw/urls_public.py b/draw/urls_public.py deleted file mode 100644 index 772235313b7..00000000000 --- a/draw/urls_public.py +++ /dev/null @@ -1,18 +0,0 @@ -from django.conf.urls import url - -from . import views - -urlpatterns = [ - url(r'^$', - views.public_draw, - name='public_draw'), - url(r'^round/(?P\d+)/$', - views.public_draw_by_round, - name='public_draw_by_round'), - url(r'^all/$', - views.public_all_draws, - name='public_all_draws'), - url(r'^side_allocations/$', - views.public_side_allocations, - name='public_side_allocations'), -] diff --git a/draw/views.py b/draw/views.py deleted file mode 100644 index b4dfba3ea47..00000000000 --- a/draw/views.py +++ /dev/null @@ -1,667 +0,0 @@ -import datetime -import json -import logging -logger = logging.getLogger(__name__) - -from django.views.generic.base import TemplateView - -from actionlog.mixins import LogActionMixin -from actionlog.models import ActionLogEntry -from adjfeedback.models import AdjudicatorFeedbackQuestion -from breakqual.models import BreakingTeam -from motions.models import Motion -from participants.models import Team -from standings.teams import TeamStandingsGenerator -from tournaments.mixins import RoundMixin -from tournaments.models import Tournament, Round, Division -from utils.mixins import SuperuserRequiredMixin, PostOnlyRedirectView -from utils.misc import reverse_round, redirect_round -from utils.views import * -from venues.models import Venue, VenueGroup -from venues.allocator import allocate_venues - -from .manager import DrawManager -from .models import TeamPositionAllocation, Debate, DebateTeam -# Viewing Draw - -@admin_required -@round_view -def draw_display_by_venue(request, round): - draw = round.get_draw() - return render(request, - "draw_display_by_venue.html", - dict(round=round, - draw=draw)) - - -@admin_required -@round_view -def draw_display_by_team(request, round): - draw = round.get_draw() - return render(request, "draw_display_by_team.html", dict(draw=draw)) - -# Creating Draw -@login_required -@round_view -def draw(request, round): - - if request.user.is_superuser: - if round.draw_status == round.STATUS_NONE: - return draw_none(request, round) - - if round.draw_status == round.STATUS_DRAFT: - return draw_draft(request, round) - - if round.draw_status == round.STATUS_CONFIRMED: - return draw_confirmed(request, round) - - if round.draw_status == round.STATUS_RELEASED: - return draw_confirmed(request, round) - else: - if round.draw_status == round.STATUS_RELEASED: - draw = round.get_draw() - return render(request, - "public_draw_released.html", - dict(draw=draw, - round=round)) - else: - return render(request, - 'public_draw_unreleased.html', - dict(draw=None, - round=round)) - - raise - - -def assistant_draw(request, round): - if round.draw_status == round.STATUS_RELEASED: - return draw_confirmed(request, round) - -def get_draw_with_standings(round): - draw = round.get_draw() - - if round.prev is None: - return None, draw - - teams = round.tournament.team_set.select_related('institution') - metrics = round.tournament.pref('team_standings_precedence') - generator = TeamStandingsGenerator(metrics, ('rank', 'subrank')) - standings = generator.generate(teams, round=round.prev) - - for debate in draw: - aff_standing = standings.get_standing(debate.aff_team) - neg_standing = standings.get_standing(debate.neg_team) - debate.metrics = [(a, n) for a, n in zip(aff_standing.itermetrics(), neg_standing.itermetrics())] - if round.is_break_round: - debate.aff_breakrank = BreakingTeam.objects.get( - break_category=round.break_category, - team=debate.aff_team.id).break_rank - debate.neg_breakrank = BreakingTeam.objects.get( - break_category=round.break_category, - team=debate.neg_team.id).break_rank - else: - if "points" in standings.metric_keys: - debate.aff_is_pullup = abs(aff_standing.metrics["points"] - debate.bracket) >= 1 - debate.neg_is_pullup = abs(neg_standing.metrics["points"] - debate.bracket) >= 1 - debate.aff_subrank = aff_standing.rankings["subrank"] - debate.neg_subrank = neg_standing.rankings["subrank"] - - return standings, draw - -def draw_none(request, round): - all_teams_count = Team.objects.filter(tournament=round.tournament).count() - active_teams = round.active_teams.all() - active_venues_count = round.active_venues.count() - active_adjs = round.active_adjudicators.count() - rooms = float(active_teams.count()) // 2 - if round.prev: - previous_unconfirmed = round.prev.get_draw().filter( - result_status__in=[Debate.STATUS_NONE, Debate.STATUS_DRAFT]).count() - else: - previous_unconfirmed = 0 - - return render(request, - "draw_none.html", - dict(active_teams=active_teams, - active_venues_count=active_venues_count, - active_adjs=active_adjs, - rooms=rooms, - round=round, - previous_unconfirmed=previous_unconfirmed, - all_teams_count=all_teams_count)) - - -def draw_draft(request, round): - standings, draw = get_draw_with_standings(round) - return render(request, "draw_draft.html", dict(draw=draw, standings=standings)) - - -def draw_confirmed(request, round): - draw = round.cached_draw - rooms = float(round.active_teams.count()) // 2 - active_adjs = round.active_adjudicators.all() - - return render(request, - "draw_confirmed.html", - dict(draw=draw, - active_adjs=active_adjs, - rooms=rooms)) - - -@admin_required -@round_view -def draw_with_standings(request, round): - standings, draw = get_draw_with_standings(round) - return render(request, "draw_with_standings.html", dict(draw=draw, standings=standings)) - - -class CreateDrawView(LogActionMixin, SuperuserRequiredMixin, RoundMixin, PostOnlyRedirectView): - - action_log_type = ActionLogEntry.ACTION_TYPE_DRAW_CREATE - - def get_redirect_url(self): - return reverse_round('draw', self.get_round()) - - def post(self, request, *args, **kwargs): - round = self.get_round() - - if round.draw_status != round.STATUS_NONE: - messages.error(request, "Could not create draw for {}, there was already a draw!".format(round.name)) - return super().post(request, *args, **kwargs) - - manager = DrawManager(round) - manager.create() - - allocate_venues(round) - - self.log_action() - return super().post(request, *args, **kwargs) - - -@admin_required -@expect_post -@round_view -def confirm_draw(request, round): - if round.draw_status != round.STATUS_DRAFT: - return HttpResponseBadRequest("Draw status is not DRAFT") - - round.draw_status = round.STATUS_CONFIRMED - round.save() - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_DRAW_CONFIRM, - user=request.user, - round=round, - tournament=round.tournament) - - return redirect_round('draw', round) - -@round_view -def draw_confirm_regenerate(request, round): - return render(request, "draw_confirm_regeneration.html", dict()) - - -@admin_required -@expect_post -@round_view -def draw_regenerate(request, round): - from .dbutils import delete_round_draw - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_DRAW_REGENERATE, - user=request.user, - round=round, - tournament=round.tournament) - delete_round_draw(round) - return redirect_round('draw', round) - - -@admin_required -@expect_post -@round_view -def release_draw(request, round): - if round.draw_status != round.STATUS_CONFIRMED: - return HttpResponseBadRequest("Draw status is not CONFIRMED") - - round.draw_status = round.STATUS_RELEASED - round.save() - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_DRAW_RELEASE, - user=request.user, - round=round, - tournament=round.tournament) - - return redirect_round('draw', round) - - -@admin_required -@expect_post -@round_view -def unrelease_draw(request, round): - if round.draw_status != round.STATUS_RELEASED: - return HttpResponseBadRequest("Draw status is not RELEASED") - - round.draw_status = round.STATUS_CONFIRMED - round.save() - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_DRAW_UNRELEASE, - user=request.user, - round=round, - tournament=round.tournament) - - return redirect_round('draw', round) - - -@admin_required -@tournament_view -def side_allocations(request, t): - # TODO: move to draws app - teams = Team.objects.filter(tournament=t) - rounds = Round.objects.filter(tournament=t).order_by("seq") - tpas = dict() - TPA_MAP = { - TeamPositionAllocation.POSITION_AFFIRMATIVE: "Aff", - TeamPositionAllocation.POSITION_NEGATIVE: "Neg", - None: "-" - } - for tpa in TeamPositionAllocation.objects.all(): - tpas[(tpa.team.id, tpa.round.seq)] = TPA_MAP[tpa.position] - for team in teams: - team.side_allocations = [tpas.get( - (team.id, round.id), "-") for round in rounds] - return render(request, - "side_allocations.html", - dict(teams=teams, - rounds=rounds)) - - -class SetRoundStartTimeView(SuperuserRequiredMixin, LogActionMixin, RoundMixin, PostOnlyRedirectView): - - action_log_type = ActionLogEntry.ACTION_TYPE_ROUND_START_TIME_SET - - def get_redirect_url(self): - return reverse_round('draw', self.get_round()) - - def post(self, request, *args, **kwargs): - time_text = request.POST["start_time"] - try: - time = datetime.datetime.strptime(time_text, "%H:%M").time() - except ValueError as e: - messages.error(request, "Sorry, \"{}\" isn't a valid time. It must be in 24-hour format, with a colon, for example: \"13:57\".".format(time_text)) - return super().post(request, *args, **kwargs) - - round = self.get_round() - round.starts_at = time - round.save() - - self.log_action() # need to call explicitly, since this isn't a form view - - return super().post(request, *args, **kwargs) - - -@admin_required -@round_view -def schedule_debates(request, round): - venue_groups = VenueGroup.objects.all() - divisions = Division.objects.filter(tournament=round.tournament).order_by('id') - return render(request, - "draw_set_debate_times.html", - dict(venue_groups=venue_groups, divisions=divisions)) - - -@admin_required -@expect_post -@round_view -def apply_schedule(request, round): - import datetime - debates = Debate.objects.filter(round=round) - for debate in debates: - division = debate.teams[0].division - if division and division.time_slot: - date = request.POST[str(division.venue_group.id)] - if date: - time = "%s %s" % (date, division.time_slot) - try: - debate.time = datetime.datetime.strptime(time, - "%Y-%m-%d %H:%M:%S") # Chrome - except ValueError: - debate.time = datetime.datetime.strptime(time, - "%d/%m/%Y %H:%M:%S") # Others - - debate.save() - - messages.success(request, "Applied schedules to debates") - return redirect_round('draw', round) - - -@admin_required -@round_view -def draw_matchups_edit(request, round): - standings, draw = get_draw_with_standings(round) - debates = len(draw) - unused_teams = round.unused_teams() - possible_debates = len(unused_teams) // 2 + 1 # The blank rows to add - possible_debates = [None] * possible_debates - return render(request, - "draw_matchups_edit.html", - dict(draw=draw, standings=standings, - possible_debates=possible_debates, - unused_teams=unused_teams)) - - -@admin_required -@expect_post -@round_view -def save_matchups(request, round): - # TODO: move to draws app - #print request.POST.keys() - - existing_debate_ids = [int(a.replace('debate_', '')) - for a in list(request.POST.keys()) - if a.startswith('debate_')] - for debate_id in existing_debate_ids: - debate = Debate.objects.get(id=debate_id) - new_aff_id = request.POST.get('aff_%s' % debate_id).replace('team_', - '') - new_neg_id = request.POST.get('neg_%s' % debate_id).replace('team_', - '') - - if new_aff_id and new_neg_id: - DebateTeam.objects.filter(debate=debate).delete() - debate.save() - - new_aff_team = Team.objects.get(id=int(new_aff_id)) - new_aff_dt = DebateTeam(debate=debate, - team=new_aff_team, - position=DebateTeam.POSITION_AFFIRMATIVE) - new_aff_dt.save() - - new_aff_team = Team.objects.get(id=int(new_neg_id)) - new_neg_dt = DebateTeam(debate=debate, - team=new_aff_team, - position=DebateTeam.POSITION_NEGATIVE) - new_neg_dt.save() - else: - # If there's blank debates we need to delete those - debate.delete() - - new_debate_ids = [int(a.replace('new_debate_', '')) - for a in list(request.POST.keys()) - if a.startswith('new_debate_')] - for debate_id in new_debate_ids: - new_aff_id = request.POST.get('aff_%s' % debate_id).replace('team_', - '') - new_neg_id = request.POST.get('neg_%s' % debate_id).replace('team_', - '') - - if new_aff_id and new_neg_id: - debate = Debate(round=round, venue=None) - debate.save() - - aff_team = Team.objects.get(id=int(new_aff_id)) - neg_team = Team.objects.get(id=int(new_neg_id)) - new_aff_dt = DebateTeam(debate=debate, - team=aff_team, - position=DebateTeam.POSITION_AFFIRMATIVE) - new_neg_dt = DebateTeam(debate=debate, - team=neg_team, - position=DebateTeam.POSITION_NEGATIVE) - new_aff_dt.save() - new_neg_dt.save() - - return HttpResponse("ok") - - - -# Public - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('public_draw') -def public_draw(request, t): - r = t.current_round - if r.draw_status == r.STATUS_RELEASED: - draw = r.get_draw() - return render(request, - "public_draw_released.html", - dict(draw=draw, - round=r)) - else: - return render(request, - 'public_draw_unreleased.html', - dict(draw=None, - round=r)) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_round_view('show_all_draws') -def public_draw_by_round(request, round): - if round.draw_status == round.STATUS_RELEASED: - draw = round.get_draw() - return render(request, - "public_draw_released.html", - dict(draw=draw, - round=round)) - else: - return render(request, - 'public_draw_unreleased.html', - dict(draw=None, - round=round)) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@tournament_view -def public_all_draws(request, t): - all_rounds = list(Round.objects.filter( - tournament=t, draw_status=Round.STATUS_RELEASED)) - for r in all_rounds: - r.draw = r.get_draw() - - return render(request, - 'public_draw_display_all.html', - dict(all_rounds=all_rounds)) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('public_side_allocations') -def public_side_allocations(request, t): - # TODO: move to draws app - teams = Team.objects.filter(tournament=t) - rounds = Round.objects.filter(tournament=t).order_by("seq") - tpas = dict() - TPA_MAP = { - TeamPositionAllocation.POSITION_AFFIRMATIVE: "Aff", - TeamPositionAllocation.POSITION_NEGATIVE: "Neg", - } - for tpa in TeamPositionAllocation.objects.all(): - tpas[(tpa.team.id, tpa.round.seq)] = TPA_MAP[tpa.position] - for team in teams: - team.side_allocations = [tpas.get( - (team.id, round.id), "-") for round in rounds] - return render(request, - "side_allocations.html", - dict(teams=teams, - rounds=rounds)) - -@login_required -@round_view -def confirmations_view(request, round): - from participants.models import Adjudicator - from adjallocation.models import DebateAdjudicator - adjs = Adjudicator.objects.all().order_by('name') - for adj in adjs: - shifts = DebateAdjudicator.objects.filter(adjudicator=adj, debate__round__tournament__active=True) - if len(shifts) > 0: - adj.shifts = shifts - - return render(request, 'confirmations_view.html', dict(adjs=adjs)) - -# Mastersheets -@login_required -@round_view -def master_sheets_list(request, round): - venue_groups = VenueGroup.objects.all() - return render(request, - 'division_sheets_list.html', - dict(venue_groups=venue_groups)) - - -@login_required -@round_view -def master_sheets_view(request, round, venue_group_id): - # Temporary - pre unified venue groups - base_venue_group = VenueGroup.objects.get(id=venue_group_id) - active_tournaments = Tournament.objects.filter(active=True) - - for tournament in list(active_tournaments): - tournament.debates = Debate.objects.select_related( - 'division', 'division__venue_group__short_name', 'round', - 'round__tournament').filter( - # All Debates, with a matching round, at the same venue group name - round__seq=round.seq, - round__tournament=tournament, - division__venue_group__short_name= - base_venue_group.short_name # hack - remove when venue groups are unified - ).order_by('round', 'division__venue_group__short_name', - 'division') - - return render(request, - 'printing/master_sheets_view.html', - dict(base_venue_group=base_venue_group, - active_tournaments=active_tournaments)) - - -@login_required -@round_view -def room_sheets_view(request, round, venue_group_id): - # Temporary - pre unified venue groups - base_venue_group = VenueGroup.objects.get(id=venue_group_id) - venues = Venue.objects.filter(group=base_venue_group) - - for venue in venues: - venue.debates = Debate.objects.filter( - # All Debates, with a matching round, at the same venue group name - round__seq=round.seq, - venue=venue - ).select_related('round__tournament__short_name').order_by('round__tournament__seq') - - return render(request, - 'printing/room_sheets_view.html', - dict(base_venue_group=base_venue_group, - venues=venues)) - - -class PrintFeedbackFormsView(RoundMixin, SuperuserRequiredMixin, TemplateView): - - template_name = 'printing/feedback_list.html' - - def team_on_orallist(self): - return AdjudicatorFeedbackQuestion.objects.filter(tournament=self.get_round().tournament, chair_on_panellist=True).exists() - - def chair_on_panellist(self): - return AdjudicatorFeedbackQuestion.objects.filter(tournament=self.get_round().tournament, panellist_on_chair=True).exists() - - def panellist_on_panellist(self): - return AdjudicatorFeedbackQuestion.objects.filter(tournament=self.get_round().tournament, panellist_on_panellist=True).exists() - - def panellist_on_chair(self): - return AdjudicatorFeedbackQuestion.objects.filter(tournament=self.get_round().tournament, team_on_orallist=True).exists() - - def questions_json_dict(self): - questions = [] - for q in self.get_round().tournament.adj_feedback_questions: - q_set = { - 'text': q.text, 'seq': q.seq, 'type': q.answer_type, - 'required': json.dumps(q.answer_type), - 'chair_on_panellist': json.dumps(q.chair_on_panellist), - 'panellist_on_chair': json.dumps(q.panellist_on_chair), - 'panellist_on_panellist': json.dumps(q.panellist_on_panellist), - 'team_on_orallist': json.dumps(q.team_on_orallist), - } - if q.choices: - q_set['choice_options'] = q.choices.split("//") - elif q.min_value is not None and q.max_value is not None: - q_set['choice_options'] = q.choices_for_number_scale - - questions.append(q_set) - return questions - - def construct_info(self, venue, source, source_p, target, target_p): - source_n = source.name if hasattr(source, 'name') else source.short_name - return { - 'room': venue.name, - 'authorInstitution': source.institution.code, - 'author': source_n, 'authorPosition': source_p, - 'target': target.name, 'targetPosition': target_p - } - - def get_context_data(self, **kwargs): - kwargs['questions'] = self.questions_json_dict() - kwargs['ballots'] = [] - - for debate in self.get_round().get_draw_by_room(): - chair = debate.adjudicators.chair - - if self.team_on_orallist(): - for team in debate.teams: - kwargs['ballots'].append(self.construct_info( - debate.venue, team, "Team", chair, "C")) - - if self.chair_on_panellist(): - for adj in debate.adjudicators.panel: - kwargs['ballots'].append(self.construct_info( - debate.venue, chair, "C", adj, "P")) - for adj in debate.adjudicators.trainees: - kwargs['ballots'].append(self.construct_info( - debate.venue, chair, "C", adj, "T")) - - if self.panellist_on_chair(): - for adj in debate.adjudicators.panel: - kwargs['ballots'].append(self.construct_info( - debate.venue, adj, "P", chair, "C")) - for adj in debate.adjudicators.trainees: - kwargs['ballots'].append(self.construct_info( - debate.venue, adj, "T", chair, "C")) - - return super().get_context_data(**kwargs) - - -class PrintScoreSheetsView(RoundMixin, SuperuserRequiredMixin, TemplateView): - - template_name = 'printing/scoresheet_list.html' - - def get_context_data(self, **kwargs): - kwargs['motions'] = Motion.objects.filter(round=self.get_round()).values('text').order_by('seq') - kwargs['ballots'] = [] - - for debate in self.get_round().get_draw_by_room(): - debateInfo = { - 'room': debate.venue.name if debate.venue else 'TBA', - 'aff': debate.aff_team.short_name, - 'affEmoji': debate.aff_team.emoji, - 'affSpeakers': [s.name for s in debate.aff_team.speakers], - 'neg': debate.neg_team.short_name, - 'negEmoji': debate.neg_team.emoji, - 'negSpeakers': [s.name for s in debate.neg_team.speakers], - 'panel': [] - } - for position, adj in debate.adjudicators: - debateInfo['panel'].append({ - 'name': adj.name, - 'institution': adj.institution.code, - 'position': position - }) - - if len(debateInfo['panel']) is 0: - ballotData = { - 'author': "_______________________________________________", - 'authorInstitution': "", - 'authorPosition': "", - } - ballotData.update(debateInfo) # Extend with debateInfo keys - kwargs['ballots'].append(ballotData) - else: - for adj in (a for a in debateInfo['panel'] if a['position'] != "T"): - ballotData = { - 'author': adj['name'], - 'authorInstitution': adj['institution'], - 'authorPosition': adj['position'], - } - ballotData.update(debateInfo) # Extend with debateInfo keys - kwargs['ballots'].append(ballotData) - - return super().get_context_data(**kwargs) \ No newline at end of file diff --git a/motions/admin.py b/motions/admin.py deleted file mode 100644 index f92de45df49..00000000000 --- a/motions/admin.py +++ /dev/null @@ -1,31 +0,0 @@ -from django.contrib import admin - -from .models import Motion, DebateTeamMotionPreference - -# ============================================================================== -# Motions -# ============================================================================== - -_m_tournament = lambda o: o.round.tournament -class MotionAdmin(admin.ModelAdmin): - list_display = ('reference', 'round', 'seq', _m_tournament) - list_filter = ('round', 'divisions') - - -admin.site.register(Motion, MotionAdmin) - -_dtmp_team_name = lambda o: o.debate_team.team.short_name -_dtmp_team_name.short_description = 'Team' -_dtmp_position = lambda o: o.debate_team.position -_dtmp_position.short_description = 'Position' -_dtmp_motion = lambda o: o.motion.reference -_dtmp_motion.short_description = 'Motion' -_dtmp_confirmed = lambda o: o.ballot_submission.confirmed -_dtmp_confirmed.short_description = 'Confirmed' -class DebateTeamMotionPreferenceAdmin(admin.ModelAdmin): - list_display = ('ballot_submission', _dtmp_confirmed, _dtmp_team_name, - _dtmp_position, 'preference', _dtmp_motion) - - -admin.site.register(DebateTeamMotionPreference, - DebateTeamMotionPreferenceAdmin) diff --git a/motions/templates/list.html b/motions/templates/list.html deleted file mode 100644 index 2c231de7b9e..00000000000 --- a/motions/templates/list.html +++ /dev/null @@ -1,136 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} - -{% block page-title %}Motions for {{ round.name }}{% endblock %} -{% block head-title %} - Motions for {{ round.name }} -{% endblock %} -{% block sub-title %} - {% if round.motions_released %}(released){% else %}(not released){% endif %} -{% endblock %} - -{% block page-subnav-sections %} - - Edit Motions - - {% if pref.enable_division_motions %} - - Assign Motions to Divisions - - {% endif %} -
- {% csrf_token %} -
-
- {% csrf_token %} -
-{% endblock %} - -{% block page-subnav-actions %} - - - Enter Results - - -{% endblock %} - -{% block content %} - -
-
- - - - - - - - - {% if pref.enable_flagged_motions %} - - {% endif %} - {% if pref.enable_division_motions %} - - {% endif %} - - {% if pref.motion_vetoes_enabled %} - - - {% endif %} - - - - - - - - {% for motion in motions %} - - - - - - - {% if pref.enable_flagged_motions %} - - {% endif %} - {% if pref.enable_division_motions %} - - {% endif %} - - {% if pref.motion_vetoes_enabled %} - - - {% endif %} - - - - - - {% endfor %} - -
RSeqRoundOrderReferenceMFlaggedDivisionsChosenAVNVAWNWChi2P-val.
{{ motion.round.seq }}{{ motion.round.abbreviation }}{{ motion.seq }}{{ motion.reference }}{{ motion.text }} - {% if motion.flagged %} - Yes - {% else %} - No - {% endif %} - - {% for division in motion.divisions.all %} - {{ division.name }}, - {% endfor %} - {{ motion.chosen_in }}{{ motion.aff_vetoes }}{{ motion.neg_vetoes }}{{ motion.aff_wins }}{{ motion.neg_wins }} - {{ motion.c1|floatformat:1 }} - - {{ motion.p_value|floatformat:2 }} -
-
-
-{% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/motions/templates/public_motions.html b/motions/templates/public_motions.html deleted file mode 100644 index e48da560b8c..00000000000 --- a/motions/templates/public_motions.html +++ /dev/null @@ -1,113 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} -{% load static %} - -{% block head-title %}Motions{% endblock %} -{% block page-title %}Motions{% endblock %} -{% block page-subnav-sections %} - {% if pref.enable_divisions and pref.enable_division_motions %} - {% include "tables/table_search.html" %} - {% endif %} -{% endblock %} - -{% block page-alerts %} - {% if rounds.all.count == 0 %} - - {% endif %} -{% endblock %} - -{% block content %} - - {% if pref.enable_divisions and pref.enable_division_motions %} - {% if rounds.all.count > 0 %} -
-
- - - - - - - - - - {% if pref.enable_flagged_motions %} - - {% endif %} - - - - {% for round in rounds %} - {% for motion in round.motions %} - - - - - - - - {% if pref.enable_flagged_motions %} - - {% endif %} - - {% endfor %} - {% endfor %} - -
RSeqRoundReferenceVenue(s)DivisionsTextContentious
{{ motion.round.seq }}{{ motion.round.abbreviation }}{{ motion.reference }} - {% regroup motion.divisions.all by venue_group as unique_venues %} - {% for venue_group in unique_venues %} - {{ venue_group.grouper.short_name }}, - {% endfor %} - - {% for division in motion.divisions.all %} - - {{ division.name }}, - - {% endfor %} - {{ motion.text }}{% if motion.flagged %}{% endif %}
-
-
- {% endif %} - {% else %} - {% for round in rounds %} -
-
-

{{ round.name }}

-
-
    - {% if round.motions %} - {% for motion in round.motions %} -
  • {{ motion.text }}
  • - {% endfor %} - {% else %} -
  • No motions have been released yet
  • - {% endif %} -
-
- {% endfor %} - {% endif %} - -
-{% endblock content %} - -{% block extra-js %} -{% if pref.enable_divisions and pref.enable_division_motions %} - -{% endif %} -{% endblock extra-js %} diff --git a/motions/urls_admin.py b/motions/urls_admin.py deleted file mode 100644 index abb6356b4a1..00000000000 --- a/motions/urls_admin.py +++ /dev/null @@ -1,21 +0,0 @@ -from django.conf.urls import url - -from . import views - -urlpatterns = [ - url(r'^$', - views.motions, - name='motions'), - url(r'^edit/$', - views.motions_edit, - name='motions_edit'), - url(r'^assign/$', - views.motions_assign, - name='motions_assign'), - url(r'^release/$', - views.release_motions, - name='release_motions'), - url(r'^unrelease/$', - views.unrelease_motions, - name='unrelease_motions'), -] diff --git a/motions/urls_public.py b/motions/urls_public.py deleted file mode 100644 index 9bdf9e05580..00000000000 --- a/motions/urls_public.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.conf.urls import url - -from . import views - -urlpatterns = [ - url(r'^$', views.public_motions, name='public_motions'), -] diff --git a/motions/views.py b/motions/views.py deleted file mode 100644 index 46bb63c05ed..00000000000 --- a/motions/views.py +++ /dev/null @@ -1,109 +0,0 @@ -from django.shortcuts import render - -from .models import Motion -from actionlog.models import ActionLogEntry -from tournaments.models import Round, Division - -from django.forms import ModelForm -from django.forms.models import modelformset_factory -from django.forms.widgets import CheckboxSelectMultiple -from django.forms.models import ModelMultipleChoiceField - -from utils.views import * - -@admin_required -@round_view -def motions(request, round): - motions = list() - if len(motions) > 0: - motions = [m for m in motions if m.round == round] - - return render(request, "list.html", dict(motions=motions)) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('public_motions') -def public_motions(request, t): - order_by = 'seq' if t.pref('public_motions_order') == 'forward' else '-seq' - rounds = Round.objects.filter(motions_released=True, tournament=t).order_by(order_by) - for round in rounds: - round.motions = round.motion_set.all() - - return render(request, 'public_motions.html', dict(rounds=rounds)) - - -@admin_required -@round_view -def motions_edit(request, round): - MotionFormSet = modelformset_factory(Motion, - can_delete=True, extra=3, exclude=['round']) - - if request.method == 'POST': - formset = MotionFormSet(request.POST, request.FILES) - if formset.is_valid(): - motions = formset.save(commit=False) - for motion in motions: - motion.round = round - motion.save() - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_MOTION_EDIT, - user=request.user, motion=motion, tournament=round.tournament) - for motions in formset.deleted_objects: - motions.delete() - if 'submit' in request.POST: - return redirect_round('draw', round) - else: - formset = MotionFormSet(queryset=Motion.objects.filter(round=round)) - - return render(request, "edit.html", dict(formset=formset)) - - -@admin_required -@round_view -def motions_assign(request, round): - - class MyModelChoiceField(ModelMultipleChoiceField): - def label_from_instance(self, obj): - return "D%s @ %s" % ( - obj.name, - obj.venue_group.short_name, - ) - - class ModelAssignForm(ModelForm): - divisions = MyModelChoiceField(widget=CheckboxSelectMultiple, queryset=Division.objects.filter(tournament=round.tournament).order_by('venue_group')) - class Meta: - model = Motion - fields = ("divisions",) - - MotionFormSet = modelformset_factory(Motion, ModelAssignForm, extra=0, fields=['divisions']) - - if request.method == 'POST': - formset = MotionFormSet(request.POST) - formset.save() # Should be checking for validity but on a deadline and was buggy - if 'submit' in request.POST: - return redirect_round('motions', round) - - formset = MotionFormSet(queryset=Motion.objects.filter(round=round)) - return render(request, "assign.html", dict(formset=formset)) - - -@admin_required -@expect_post -@round_view -def release_motions(request, round): - round.motions_released = True - round.save() - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_MOTIONS_RELEASE, - user=request.user, round=round, tournament=round.tournament) - - return redirect_round('draw', round) - -@admin_required -@expect_post -@round_view -def unrelease_motions(request, round): - round.motions_released = False - round.save() - ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_MOTIONS_UNRELEASE, - user=request.user, round=round, tournament=round.tournament) - - return redirect_round('draw', round) diff --git a/package.json b/package.json index d243bffa6bd..dfe97c16985 100644 --- a/package.json +++ b/package.json @@ -3,19 +3,40 @@ "description": "Debating tabulation software for two-team parliamentary formats", "main": "index.js", "dependencies": { - "bower": "^1.7.9", + "babel-core": "^6.9.1", + "babel-plugin-transform-runtime": "^6.12.0", + "babel-preset-es2015": "^6.9.0", + "babel-runtime": "^6.11.6", + "babelify": "^7.3.0", + "bootstrap": "^3.3.6", + "bootstrap-sass": "^3.3.6", + "browserify": "^13.0.1", + "d3": "^3.5.17", + "datatables.net": "^1.10.12", + "eslint": "^3.2.0", + "event-stream": "^3.3.3", "gulp": "^3.9.1", + "gulp-clean-css": "^2.0.12", "gulp-concat": "^2.6.0", "gulp-gzip": "^1.2.0", "gulp-livereload": "^3.8.1", - "gulp-minify-css": "^1.2.4", "gulp-rename": "^1.2.2", "gulp-sass": "^2.3.1", - "gulp-uglify": "^1.5.3" + "gulp-streamify": "^1.0.2", + "gulp-uglify": "^2.0.0", + "gulp-util": "^3.0.7", + "jquery": "^2.2.3", + "jquery-validation": "^1.15.0", + "lato-font": "^1.1.1", + "live-reload": "^1.1.0", + "vinyl-source-stream": "^1.1.0", + "vue": "^1.0.26", + "vue-hot-reload-api": "^2.0.5", + "vueify": "^8.4.0" }, "scripts": { - "postinstall": "node node_modules/bower/bin/bower install", - "gulp": "gulp" + "gulp": "gulp", + "lint": "eslint --ext .js,.vue tabbycat/templates/js-bundles tabbycat/templates/js-vue" }, "repository": "https://github.com/czlee/tabbycat", "license": "UNLICENSED" diff --git a/participants/emoji.py b/participants/emoji.py deleted file mode 100644 index 3593821968e..00000000000 --- a/participants/emoji.py +++ /dev/null @@ -1,1299 +0,0 @@ -# -*- coding: utf-8 -*- - -# With thanks to emojipedia.org - -EMOJI_LIST = ( - # Unicode Version 1.1 (these all render using primitive icons) - # DOESNT SHOW ("☺️", "☺️"), # White Smiling Face - # DOESNT SHOW ("☹", ""), # White Frowning Face - # DOESNT SHOW ("☝️", "☝️"), # White Up Pointing Index - # DOESNT SHOW ("✌️", "✌️"), # Victory Hand - # DOESNT SHOW ("✍", ""), # Writing Hand - # DOESNT SHOW ("❤️", "❤️"), # Heavy Black Heart - # DOESNT SHOW ("❣", ""), # Heavy Heart Exclamation Mark Ornament - # DOESNT SHOW ("☠", ""), # Skull and Crossbones - # DOESNT SHOW ("♨️", "♨️"), # Hot Springs - # DOESNT SHOW ("✈️", "✈️"), # Airplane - # DOESNT SHOW ("⌛", "⌛"), # Hourglass - # DOESNT SHOW ("⌚", "⌚"), # Watch - # LAME ("♈", ""), # Aries - # LAME ("♉", ""), # Taurus - # LAME ("♊", ""), # Gemini - # LAME ("♋", ""), # Cancer - # LAME ("♌", ""), # Leo - # LAME ("♍", ""), # Virgo - # LAME ("♎", ""), # Libra - # LAME ("♏", ""), # Scorpius - # LAME ("♐", ""), # Sagittarius - # LAME ("♑", ""), # Capricorn - # LAME ("♒", ""), # Aquarius - # LAME ("♓", ""), # Pisces - # DOESNT SHOW ("☀️", "☀️"), # Black Sun With Rays - # DOESNT SHOW ("☁️", "☁️"), # Cloud - # DOESNT SHOW ("☂", ""), # Umbrella - # DOESNT SHOW ("❄️", "❄️"), # Snowflake - # DOESNT SHOW ("☃", "☃"), # Snowman - # Doesn't show (" Comet", ""), # - # DOESNT SHOW ("♠️", "♠️"), # Black Spade Suit - # DOESNT SHOW ("♥️", "♥️"), # Black Heart Suit - # DOESNT SHOW ("♦️", "♦️"), # Black Diamond Suit - # DOESNT SHOW ("♣️", "♣️"), # Black Club Suit - # LAME ("▶️", ""), # Black Right-Pointing Triangle - # LAME ("◀️", ""), # Black Left-Pointing Triangle - # DOESNT SHOW ("☎️", "☎️"), # Black Telephone - # DOESNT SHOW ("⌨", ""), # Keyboard - # DOESNT SHOW ("✉️", "✉️"), # Envelope - # DOESNT SHOW ("✏️", "✏️"), # Pencil - # DOESNT SHOW ("✒️", "✒️"), # Black Nib - # DOESNT SHOW ("✂️", "✂️"), # Black Scissors - # LAME ("↗️", ""), # North East Arrow - # LAME ("➡️", ""), # Black Rightwards Arrow - # LAME ("↘️", ""), # South East Arrow - # LAME ("↙️", ""), # South West Arrow - # LAME ("↖️", ""), # North West Arrow - # LAME ("↕️", ""), # Up Down Arrow - # LAME ("↔️", ""), # Left Right Arrow - # LAME ("↩️", ""), # Leftwards Arrow With Hook - # LAME ("↪️", ""), # Rightwards Arrow With Hook - # OFFENSIVE ("✡", ""), # Star of David - # OFFENSIVE ("☸", ""), # Wheel of Dharma - # OFFENSIVE ("☯", ""), # Yin Yang - # OFFENSIVE ("✝", ""), # Latin Cross - # OFFENSIVE ("☦", ""), # Orthodox Cross - # OFFENSIVE ("☪", ""), # Star and Crescent - # OFFENSIVE ("☮", ""), # Peace Symbol - # OFFENSIVE ("☢", ""), # Radioactive Sign - # OFFENSIVE ("☣", ""), # Biohazard Sign - # DOESNT SHOW ("☑️", "☑️"), # Ballot Box With Check - # LAME ("✔️", ""), # Heavy Check Mark - # LAME ("✖️", ""), # Heavy Multiplication X - # LAME ("✳️", ""), # Eight Spoked Asterisk - # LAME ("✴️", ""), # Eight Pointed Black Star - # LAME ("❇️", ""), # Sparkle - # DOESNT SHOW ("‼️", "‼️"), # Double Exclamation Mark - # LAME ("〰️", ""), # Wavy Dash - # LAME ("©️", ""), # Copyright Sign - # LAME ("®️", ""), # Registered Sign - # LAME ("™️", ""), # Trade Mark Sign - # LAME ("Ⓜ️", ""), # Circled Latin Capital Letter M - # LAME ("㊗️", ""), # Circled Ideograph Congratulation - # LAME ("㊙️", ""), # Circled Ideograph Secret - # LAME ("▪️", ""), # Black Small Square - # LAME ("▫️", ""), # White Small Square - # Unicode Version 3.0 - # ("#⃣️", "#⃣️"), # Keycap Number Sign - # ("*⃣", "*⃣"), # Keycap Asterisk - # ("0⃣️", "0⃣️"), # Keycap Digit Zero - # ("1⃣️", "1⃣️"), # Keycap Digit One - # ("2⃣️", "2⃣️"), # Keycap Digit Two - # LAME ("3⃣️", ""), # Keycap Digit Three - # LAME ("4⃣️", ""), # Keycap Digit Four - # LAME ("5⃣️", ""), # Keycap Digit Five - # LAME ("6⃣️", ""), # Keycap Digit Six - # LAME ("7⃣️", ""), # Keycap Digit Seven - # LAME ("8⃣️", ""), # Keycap Digit Eight - # LAME ("9⃣️", ""), # Keycap Digit Nine - # DOESNT SHOW ("⁉️", "⁉️"), # Exclamation Question Mark - # LAME ("ℹ️", ""), # Information Source - # Unicode Version 3.2 - # LAME ("⤴️", ""), # Arrow Pointing Rightwards Then Curving Upwards - # LAME ("⤵️", ""), # Arrow Pointing Rightwards Then Curving Downwards - # DOESNT SHOW ("♻️", "♻️"), # Black Universal Recycling Symbol - # LAME ("〽️", ""), # Part Alternation Mark - # LAME ("◻️", ""), # White Medium Square - # LAME ("◼️", ""), # Black Medium Square - # LAME ("◽", ""), # White Medium Small Square - # LAME ("◾", ""), # Black Medium Small Square - #Unicode Version 4.0 - ("☕", "☕"), # Hot Beverage - # DOESN’T SHOW("⚠️", "⚠️"), # Warning Sign - # DOESN’T SHOW ("☔", ""), # Umbrella With Rain Drops - # LAME ("⏏", ""), # Eject Symbol - # LAME ("⬆️", ""), # Upwards Black Arrow - # LAME ("⬇️", ""), # Downwards Black Arrow - # LAME ("⬅️", ""), # Leftwards Black Arrow - # DOESN’T SHOW ("⚡", ""), # High Voltage Sign - #Unicode Version 4.1 - # DOESN’T SHOW ("☘", ""), # Shamrock - # DOESN’T SHOW ("⚓", ""), # Anchor - # DOESN’T SHOW ("♿", ""), # Wheelchair Symbol - # DOESN’T SHOW ("⚒", ""), # Hammer and Pick - # DOESN’T SHOW ("⚙", ""), # Gear - # DOESN’T SHOW ("⚗", ""), # Alembic - # DOESN’T SHOW ("⚖", ""), # Scales - # DOESN’T SHOW ("⚔", ""), # Crossed Swords - # DOESN’T SHOW ("⚰", ""), # Coffin - # DOESN’T SHOW ("⚱", ""), # Funeral Urn - # DOESN’T SHOW ("⚜", ""), # Fleur-De-Lis - # DOESN’T SHOW ("⚛", ""), # Atom Symbol - # LAME ("⚪", ""), # Medium White Circle - # LAME ("⚫", ""), # Medium Black Circle - # Unicode Version 5.1 - # LAME ("🀄", ""), # Mahjong Tile Red Dragon - # DOESNT SHOW ("⭐", "⭐"), # White Medium Star - # LAME ("⬛", ""), # Black Large Square - # LAME ("⬜", ""), # White Large Square - # Unicode Version 5.2 - ("⛑", "⛑"), # Helmet With White Cross - ("⛰", "⛰"), # Mountain - ("⛪", "⛪"), # Church - # LAME ("⛲", ""), # Fountain - # LAME ("⛺", ""), # Tent - # LAME ("⛽", ""), # Fuel Pump - ("⛵", "⛵"), # Sailboat - # LAME ("⛴", ""), # Ferry - ("⛔", "⛔"), # No Entry - ("⛅", "⛅"), # Sun Behind Cloud - ("⛈", "⛈"), # Thunder Cloud and Rain - ("⛱", "⛱"), # Umbrella on Ground - ("⛄", "⛄"), # Snowman Without Snow - ("⚽", "⚽"), # Soccer Ball - # DOESN"T SHOW ("⚾", ""), # Baseball - # LAME ("⛳", ""), # Flag in Hole - # LAME ("⛸", ""), # Ice Skate - # LAME ("⛷", ""), # Skier - # LAME ("⛹", ""), # Person With Ball - ("⛏", "⛏"), # Pick - # OFFENSIVE ("⛓", ""), # Chains - # LAME ("⛩", ""), # Shinto Shrine - # LAME ("⭕", ""), # Heavy Large Circle - # LAME ("❗", ""), # Heavy Exclamation Mark Symbol - # LAME ("🅿️", ""), # Negative Squared Latin Capital Letter P - # LAME ("🈯", ""), # Squared CJK Unified Ideograph-6307 - # LAME ("🈚", ""), # Squared CJK Unified Ideograph-7121 - # Unicode Version 6.0 - ("😁", "😁"), # Grinning Face With Smiling Eyes - ("😂", "😂"), # Face With Tears of Joy - # TOO SIMILAR ("😃", ""), # Smiling Face With Open Mouth - ("😄", "😄"), # Smiling Face With Open Mouth and Smiling Eyes - # TOO SIMILAR ("😅", ""), # Smiling Face With Open Mouth and Cold Sweat - ("😆", "😆"), # Smiling Face With Open Mouth and Tightly-Closed Eyes - ("😉", "😉"), # Winking Face - ("😊", "😊"), # Smiling Face With Smiling Eyes - # TOO SIMILAR ("😋", ""), # Face Savouring Delicious Food - ("😎", "😎"), # Smiling Face With Sunglasses - ("😍", "😍"), # Smiling Face With Heart-Shaped Eyes - ("😘", "😘"), # Face Throwing a Kiss - # TOO SIMILAR ("😚", ""), # Kissing Face With Closed Eyes - ("😇", "😇"), # Smiling Face With Halo - ("😐", "😐"), # Neutral Face - # TOO SIMILAR ("😶", ""), # Face Without Mouth - ("😏", "😏"), # Smirking Face - # TOO SIMILAR ("😣", ""), # Persevering Face - ("😥", "😥"), # Disappointed but Relieved Face - # TOO SIMILAR ("😪", ""), # Sleepy Face - # TOO SIMILAR ("😫", ""), # Tired Face - # TOO SIMILAR ("😌", ""), # Relieved Face - ("😜", "😜"), # Face With Stuck-Out Tongue and Winking Eye - # TOO SIMILAR ("😝", ""), # Face With Stuck-Out Tongue and Tightly-Closed Eyes - # TOO SIMILAR ("😒", ""), # Unamused Face - # TOO SIMILAR ("😓", ""), # Face With Cold Sweat - # TOO SIMILAR ("😔", ""), # Pensive Face - ("😖", "😖"), # Confounded Face - ("😷", "😷"), # Face With Medical Mask - ("😲", "😲"), # Astonished Face - ("😞", "😞"), # Disappointed Face - # TOO SIMILAR ("😤", ""), # Face With Look of Triumph - # TOO SIMILAR ("😢", ""), # Crying Face - ("😭", "😭"), # Loudly Crying Face - # TOO SIMILAR ("😨", ""), # Fearful Face - # TOO SIMILAR ("😩", ""), # Weary Face - ("😰", "😰"), # Face With Open Mouth and Cold Sweat - ("😱", "😱"), # Face Screaming in Fear - ("😳", "😳"), # Flushed Face - ("😵", "😵"), # Dizzy Face - ("😡", "😡"), # Pouting Face - # TOO SIMILAR ("😠", ""), # Angry Face - ("👿", "👿"), # Imp - # TOO SIMILAR ("😈", ""), # Smiling Face With Horns - # LAME ("👦", ""), # Boy - # LAME ("👧", ""), # Girl - # LAME ("👨", ""), # Man - ("👩", "👩"), # Woman - ("👴", "👴"), # Older Man - ("👵", "👵"), # Older Woman - ("👶", "👶"), # Baby - # LAME ("👱", ""), # Person With Blond Hair - ("👮", "👮"), # Police Officer - # OFFENSIVE ("👲", ""), # Man With Gua Pi Mao - # OFFENSIVE ("👳", ""), # Man With Turban - ("👷", "👷"), # Construction Worker - ("👸", "👸"), # Princess - ("💂", "💂"), # Guardsman - ("🎅", "🎅"), # Father Christmas - ("👼", "👼"), # Baby Angel - # USED BY UI ("👯", ""), # Woman With Bunny Ears // for bulk adding teams and team tab/standings - # LAME ("💆", ""), # Face Massage - # LAME ("💇", ""), # Haircut - ("👰", "👰"), # Bride With Veil - # LAME ("🙍", ""), # Person Frowning - # LAME ("🙎", ""), # Person With Pouting Face - ("🙅", "🙅"), # Face With No Good Gesture - ("🙆", "🙆"), # Face With OK Gesture - # USED BY UI ("💁", ""), # Information Desk Person // for reply standings - ("🙋", "🙋"), # Happy Person Raising One Hand - ("🙇", "🙇"), # Person Bowing Deeply - ("🙌", "🙌"), # Person Raising Both Hands in Celebration - ("🙏", "🙏"), # Person With Folded Hands - # LAME ("👤", ""), # Bust in Silhouette - # LAME ("👥", ""), # Busts in Silhouette - # LAME ("🚶", ""), # Pedestrian - # LAME ("🏃", ""), # Runner - ("💃", "💃"), # Dancer - # TOO SIMILAR ("💏", ""), # Kiss - ("💑", "💑"), # Couple With Heart - ("👪", "👪"), # Family - ("👫", "👫"), # Man and Woman Holding Hands - ("👬", "👬"), # Two Men Holding Hands - ("👭", "👭"), # Two Women Holding Hands - ("💪", "💪"), # Flexed Biceps - # LAME ("👈", ""), # White Left Pointing Backhand Index - # LAME ("👉", ""), # White Right Pointing Backhand Index - ("👆", "👆"), # White Up Pointing Backhand Index - # LAME ("👇", ""), # White Down Pointing Backhand Index - ("✊", "✊"), # Raised Fist - ("✋", "✋"), # Raised Hand - ("👊", "👊"), # Fisted Hand Sign - ("👌", "👌"), # OK Hand Sign - ("👍", "👍"), # Thumbs Up Sign - ("👎", "👎"), # Thumbs Down Sign - # USED BY UI ("👋", "👋"), # Waving Hand Sign // for the welcome pages - # LAME ("👏", ""), # Clapping Hands Sign - ("👐", "👐"), # Open Hands Sign - ("💅", "💅"), # Nail Polish - # LAME ("👣", ""), # Footprints - # USED BY UI ("👀", ""), # Eyes // for the draw pages - ("👂", "👂"), # Ear - ("👃", "👃"), # Nose - ("👅", "👅"), # Tongue - ("👄", "👄"), # Mouth - # TOO SIMILAR ("💋", ""), # Kiss Mark - ("💘", "💘"), # Heart With Arrow - # TOO SIMILAR ("💓", ""), # Beating Heart - ("💔", "💔"), # Broken Heart - # TOO SIMILAR ("💕", ""), # Two Hearts - ("💖", "💖"), # Sparkling Heart - # TOO SIMILAR ("💗", ""), # Growing Heart - # TOO SIMILAR ("💙", ""), # Blue Heart - # TOO SIMILAR ("💚", ""), # Green Heart - # TOO SIMILAR ("💛", ""), # Yellow Heart - # TOO SIMILAR ("💜", ""), # Purple Heart - # TOO SIMILAR ("💝", ""), # Heart With Ribbon - # TOO SIMILAR ("💞", ""), # Revolving Hearts - # LAME ("💟", ""), # Heart Decoration - ("💌", "💌"), # Love Letter - ("💧", "💧"), # Droplet - # LAME ("💤", ""), # Sleeping Symbol - # LAME ("💢", ""), # Anger Symbol - ("💣", "💣"), # Bomb - ("💥", "💥"), # Collision Symbol - ("💦", "💦"), # Splashing Sweat Symbol - ("💨", "💨"), # Dash Symbol - # LAME ("💫", ""), # Dizzy Symbol - # LAME ("💬", ""), # Speech Balloon - # LAME ("💭", ""), # Thought Balloon - ("👓", "👓"), # Eyeglasses - ("👔", "👔"), # Necktie - # LAME ("👕", ""), # T-Shirt - # LAME ("👖", ""), # Jeans - # LAME ("👗", ""), # Dress - # LAME ("👘", ""), # Kimono - ("👙", "👙"), # Bikini - # LAME ("👚", ""), # Womans Clothes - # LAME ("👛", ""), # Purse - ("👜", "👜"), # Handbag - # LAME ("👝", ""), # Pouch - # LAME ("🎒", ""), # School Satchel - # LAME ("👞", ""), # Mans Shoe - ("👟", "👟"), # Athletic Shoe - ("👠", "👠"), # High-Heeled Shoe - # LAME ("👡", ""), # Womans Sandal - # LAME ("👢", ""), # Womans Boots - # USED BY UI ("👑", ""), # Crown // for the break pages - ("👒", "👒"), # Womans Hat - ("🎩", "🎩"), # Top Hat - ("💄", "💄"), # Lipstick - ("💍", "💍"), # Ring - ("💎", "💎"), # Gem Stone - # LAME ("👹", ""), # Japanese Ogre - # LAME ("👺", ""), # Japanese Goblin - ("👻", "👻"), # Ghost - ("💀", "💀"), # Skull - ("👽", "👽"), # Extraterrestrial Alien - ("👾", "👾"), # Alien Monster - ("💩", "💩"), # Pile of Poo - ("🐵", ""), # Monkey Face - ("🙈", ""), # See-No-Evil Monkey - ("🙉", ""), # Hear-No-Evil Monkey - ("🙊", ""), # Speak-No-Evil Monkey - # OFFENSIVE("🐒", ""), # Monkey - ("🐶", "🐶"), # Dog Face - # TOO SIMILAR ("🐕", ""), # Dog - ("🐩", ""), # Poodle - # TOO SIMILAR ("🐺", ""), # Wolf Face - # ("🐱", ""), # Cat Face // USED BY UI - # ("😸", ""), # Grinning Cat Face With Smiling Eyes // USED BY UI - # ("😹", ""), # Cat Face With Tears of Joy // USED BY UI - # ("😺", ""), # Smiling Cat Face With Open Mouth // USED BY UI - # ("😻", ""), # Smiling Cat Face With Heart-Shaped Eyes // USED BY UI - # ("😼", ""), # Cat Face With Wry Smile // USED BY UI - # ("😽", ""), # Kissing Cat Face With Closed Eyes // USED BY UI - # ("😾", ""), # Pouting Cat Face // USED BY UI - # ("😿", ""), # Crying Cat Face // USED BY UI - # ("🙀", ""), # Weary Cat Face // USED BY UI - # LAME ("🐈", ""), # Cat - ("🐯", "🐯"), # Tiger Face - # LAME ("🐅", ""), # Tiger - # LAME ("🐆", ""), # Leopard - ("🐴", "🐴"), # Horse Face - # LAME ("🐎", ""), # Horse - ("🐮", "🐮"), # Cow Face - # LAME ("🐂", ""), # Ox - # LAME ("🐃", ""), # Water Buffalo - # LAME ("🐄", ""), # Cow - ("🐷", "🐷"), # Pig Face - # LAME ("🐖", ""), # Pig - # LAME ("🐗", ""), # Boar - # LAME ("🐽", ""), # Pig Nose - # LAME ("🐏", ""), # Ram - ("🐑", "🐑"), # Sheep - # LAME ("🐐", ""), # Goat - # LAME ("🐪", ""), # Dromedary Camel - # LAME ("🐫", ""), # Bactrian Camel - # LAME ("🐘", ""), # Elephant - ("🐭", "🐭"), # Mouse Face - # LAME ("🐁", ""), # Mouse - # LAME ("🐀", ""), # Rat - ("🐹", "🐹"), # Hamster Face - ("🐰", "🐰"), # Rabbit Face - # LAME ("🐇", ""), # Rabbit - ("🐻", "🐻"), # Bear Face - ("🐨", "🐨"), # Koala - ("🐼", "🐼"), # Panda Face - # LAME ("🐾", ""), # Paw Prints - ("🐔", "🐔"), # Chicken - # LAME ("🐓", ""), # Rooster - # LAME ("🐣", ""), # Hatching Chick - # LAME ("🐤", ""), # Baby Chick - # LAME ("🐥", ""), # Front-Facing Baby Chick - ("🐦", "🐦"), # Bird - ("🐧", "🐧"), # Penguin - ("🐸", "🐸"), # Frog Face - # LAME ("🐊", ""), # Crocodile - # LAME ("🐢", ""), # Turtle - ("🐍", "🐍"), # Snake - ("🐲", "🐲"), # Dragon Face - # LAME ("🐉", ""), # Dragon - ("🐳", "🐳"), # Spouting Whale - # TOO SIMILAR ("🐋", ""), # Whale - # TOO SIMILAR ("🐬", ""), # Dolphin - ("🐟", "🐟"), # Fish - # LAME ("🐠", ""), # Tropical Fish - # LAME ("🐡", ""), # Blowfish - ("🐙", "🐙"), # Octopus - ("🐚", "🐚"), # Spiral Shell - # LAME ("🐌", ""), # Snail - # LAME ("🐛", ""), # Bug - # LAME ("🐜", ""), # Ant - ("🐝", "🐝"), # Honeybee - # LAME ("🐞", ""), # Lady Beetle - # LAME ("💐", ""), # Bouquet - ("🌸", "🌸"), # Cherry Blossom - # LAME ("💮", ""), # White Flower - ("🌹", "🌹"), # Rose - # LAME ("🌺", ""), # Hibiscus - ("🌻", "🌻"), # Sunflower - # LAME ("🌼", ""), # Blossom - ("🌷", "🌷"), # Tulip - ("🌱", ""), # Seedling - # LAME ("🌲", ""), # Evergreen Tree - # LAME ("🌳", ""), # Deciduous Tree - # LAME ("🌴", ""), # Palm Tree - ("🌵", "🌵"), # Cactus - # LAME ("🌾", ""), # Ear of Rice - # LAME ("🌿", ""), # Herb - ("🍀", ""), # Four Leaf Clover - ("🍁", "🍁"), # Maple Leaf - # LAME ("🍂", ""), # Fallen Leaf - # LAME ("🍃", ""), # Leaf Fluttering in Wind - ("🍇", "🍇"), # Grapes - # LAME ("🍈", ""), # Melon - ("🍉", "🍉"), # Watermelon - ("🍊", "🍊"), # Tangerine - ("🍋", "🍋"), # Lemon - ("🍌", "🍌"), # Banana - ("🍍", "🍍"), # Pineapple - ("🍎", "🍎"), # Red Apple - # TOO SIMILAR ("🍏", ""), # Green Apple - # TOO SIMILAR ("🍐", ""), # Pear - ("🍑", "🍑"), # Peach - ("🍒", "🍒"), # Cherries - ("🍓", "🍓"), # Strawberry - ("🍅", "🍅"), # Tomato - ("🍆", "🍆"), # Aubergine - ("🌽", "🌽"), # Ear of Maize - ("🍄", "🍄"), # Mushroom - # LAME ("🌰", ""), # Chestnut - ("🍞", "🍞"), # Bread - # LAME ("🍖", ""), # Meat on Bone - # LAME ("🍗", ""), # Poultry Leg - ("🍔", "🍔"), # Hamburger - # LAME ("🍟", ""), # French Fries - ("🍕", "🍕"), # Slice of Pizza - # LAME ("🍲", ""), # Pot of Food - # LAME ("🍱", ""), # Bento Box - # LAME ("🍘", ""), # Rice Cracker - ("🍙", ""), # Rice Ball - # LAME ("🍚", ""), # Cooked Rice - # LAME ("🍛", ""), # Curry and Rice - # LAME ("🍜", ""), # Steaming Bowl - # LAME ("🍝", ""), # Spaghetti - # LAME ("🍠", ""), # Roasted Sweet Potato - # LAME ("🍢", ""), # Oden - # LAME ("🍣", ""), # Sushi - # LAME ("🍤", ""), # Fried Shrimp - # LAME ("🍥", ""), # Fish Cake With Swirl Design - # LAME ("🍡", ""), # Dango - # LAME ("🍦", ""), # Soft Ice Cream - # LAME ("🍧", ""), # Shaved Ice - ("🍨", "🍨"), # Ice Cream - ("🍩", "🍩"), # Doughnut - ("🍪", "🍪"), # Cookie - # LAME ("🎂", ""), # Birthday Cake - ("🍰", "🍰"), # Shortcake - # LAME ("🍫", ""), # Chocolate Bar - # LAME ("🍬", ""), # Candy - ("🍭", "🍭"), # Lollipop - # LAME ("🍮", ""), # Custard - # LAME ("🍯", ""), # Honey Pot - ("🍼", "🍼"), # Baby Bottle - # LAME ("🍵", ""), # Teacup Without Handle - # LAME ("🍶", ""), # Sake Bottle and Cup - ("🍷", "🍷"), # Wine Glass - ("🍸", "🍸"), # Cocktail Glass - ("🍹", "🍹"), # Tropical Drink - ("🍺", "🍺"), # Beer Mug - # TOO SIMILAR ("🍻", ""), # Clinking Beer Mugs - ("🍴", "🍴"), # Fork and Knife - # LAME ("🍳", ""), # Cooking - # LAME ("🌍", ""), # Earth Globe Europe-Africa - # LAME ("🌎", ""), # Earth Globe Americas - # LAME ("🌏", ""), # Earth Globe Asia-Australia - # LAME ("🌐", ""), # Globe With Meridians - ("🌋", "🌋"), # Volcano - # LAME ("🗻", ""), # Mount Fuji - ("🏠", "🏠"), # House Building - # LAME ("🏡", ""), # House With Garden - ("🏢", "🏢"), # Office Building - # TOO SIMILAR ("🏣", ""), # Japanese Post Office - # TOO SIMILAR ("🏤", ""), # European Post Office - # TOO SIMILAR ("🏥", ""), # Hospital - # TOO SIMILAR ("🏦", ""), # Bank - # TOO SIMILAR ("🏨", ""), # Hotel - ("🏩", "🏩"), # Love Hotel - # TOO SIMILAR ("🏪", ""), # Convenience Store - # TOO SIMILAR ("🏫", ""), # School - # TOO SIMILAR ("🏬", ""), # Department Store - # TOO SIMILAR ("🏭", ""), # Factory - # TOO SIMILAR ("🏯", ""), # Japanese Castle - # TOO SIMILAR ("🏰", ""), # European Castle - # TOO SIMILAR ("💒", ""), # Wedding - # TOO SIMILAR ("🗼", ""), # Tokyo Tower - # TOO SIMILAR ("🗽", ""), # Statue of Liberty - # TOO SIMILAR ("🗾", ""), # Silhouette of Japan - # TOO SIMILAR ("🌁", ""), # Foggy - # TOO SIMILAR ("🌃", ""), # Night With Stars - # TOO SIMILAR ("🌄", ""), # Sunrise Over Mountains - # TOO SIMILAR ("🌅", ""), # Sunrise - # TOO SIMILAR ("🌆", ""), # Cityscape at Dusk - # TOO SIMILAR ("🌇", ""), # Sunset Over Buildings - # TOO SIMILAR ("🌉", ""), # Bridge at Night - ("🌊", "🌊"), # Water Wave - # LAME ("🗿", ""), # Moyai - # LAME ("🌌", ""), # Milky Way - # LAME ("🎠", ""), # Carousel Horse - # LAME ("🎡", ""), # Ferris Wheel - # LAME ("🎢", ""), # Roller Coaster - # LAME ("💈", ""), # Barber Pole - # USED BY THE UI ("🎪", ""), # Circus Tent // venue checkins/adding - # LAME ("🎭", ""), # Performing Arts - ("🎨", "🎨"), # Artist Palette - # LAME ("🎰", ""), # Slot Machine - # LAME ("🚂", ""), # Steam Locomotive - ("🚃", "🚃"), # Railway Car - ("🚄", "🚄"), # High-Speed Train - # TOO SIMILAR ("🚅", ""), # High-Speed Train With Bullet Nose - # TOO SIMILAR ("🚆", ""), # Train - # TOO SIMILAR ("🚇", ""), # Metro - # TOO SIMILAR ("🚈", ""), # Light Rail - # TOO SIMILAR ("🚉", ""), # Station - # TOO SIMILAR ("🚊", ""), # Tram - ("🚝", "🚝"), # Monorail - # TOO SIMILAR ("🚞", ""), # Mountain Railway - # TOO SIMILAR ("🚋", ""), # Tram Car - # TOO SIMILAR ("🚌", ""), # Bus - ("🚍", "🚍"), # Oncoming Bus - # TOO SIMILAR ("🚎", ""), # Trolleybus - # TOO SIMILAR ("🚏", ""), # Bus Stop - # TOO SIMILAR ("🚐", ""), # Minibus - # TOO SIMILAR ("🚑", ""), # Ambulance - # TOO SIMILAR ("🚒", ""), # Fire Engine - # TOO SIMILAR ("🚓", ""), # Police Car - ("🚔", "🚔"), # Oncoming Police Car - # TOO SIMILAR ("🚕", ""), # Taxi - # TOO SIMILAR ("🚖", ""), # Oncoming Taxi - # TOO SIMILAR ("🚗", ""), # Automobile - ("🚘", "🚘"), # Oncoming Automobile - # TOO SIMILAR ("🚙", ""), # Recreational Vehicle - # TOO SIMILAR ("🚚", ""), # Delivery Truck - # TOO SIMILAR ("🚛", ""), # Articulated Lorry - # TOO SIMILAR ("🚜", ""), # Tractor - ("🚲", "🚲"), # Bicycle - # TOO SIMILAR ("🚳", ""), # No Bicycles - ("🚨", "🚨"), # Police Cars Revolving Light - # TOO SIMILAR ("🔱", ""), # Trident Emblem - ("🚣", "🚣"), # Rowboat - # LAME ("🚤", ""), # Speedboat - # LAME ("🚢", ""), # Ship - # LAME ("💺", ""), # Seat - ("🚁", "🚁"), # Helicopter - # LAME ("🚟", ""), # Suspension Railway - # LAME ("🚠", ""), # Mountain Cableway - # LAME ("🚡", ""), # Aerial Tramway - ("🚀", "🚀"), # Rocket - # LAME ("🏧", ""), # Automated Teller Machine - # LAME ("🚮", ""), # Put Litter in Its Place Symbol - # LAME ("🚥", ""), # Horizontal Traffic Light - ("🚦", "🚦"), # Vertical Traffic Light - ("🚧", "🚧"), # Construction Sign - ("🚫", "🚫"), # No Entry Sign - # LAME ("🚭", ""), # No Smoking Symbol - # LAME ("🚯", ""), # Do Not Litter Symbol - # LAME ("🚰", ""), # Potable Water Symbol - # LAME ("🚱", ""), # Non-Potable Water Symbol - ("🚷", "🚷"), # No Pedestrians - # LAME ("🚸", ""), # Children Crossing - # LAME ("🚹", ""), # Mens Symbol - # LAME ("🚺", ""), # Womens Symbol - ("🚻", "🚻"), # Restroom - # LAME ("🚼", ""), # Baby Symbol - # LAME ("🚾", ""), # Water Closet - # LAME ("🛂", ""), # Passport Control - # LAME ("🛃", ""), # Customs - # LAME ("🛄", ""), # Baggage Claim - # LAME ("🛅", ""), # Left Luggage - # LAME ("🚪", ""), # Door - ("🚽", "🚽"), # Toilet - ("🚿", "🚿"), # Shower - ("🛀", "🛀"), # Bath - # LAME ("🛁", ""), # Bathtub - ("⏳", "⏳"), # Hourglass With Flowing Sand - ("⏰", "⏰"), # Alarm Clock - # LAME ("⏱", ""), # Stopwatch - # LAME ("⏲", ""), # Timer Clock - # LAME ("🕛", ""), # Clock Face Twelve O'Clock - # LAME ("🕧", ""), # Clock Face Twelve-Thirty - # LAME ("🕐", ""), # Clock Face One O'Clock - # LAME ("🕜", ""), # Clock Face One-Thirty - # LAME ("🕑", ""), # Clock Face Two O'Clock - # LAME ("🕝", ""), # Clock Face Two-Thirty - # LAME ("🕒", ""), # Clock Face Three O'Clock - # LAME ("🕞", ""), # Clock Face Three-Thirty - # LAME ("🕓", ""), # Clock Face Four O'Clock - # LAME ("🕟", ""), # Clock Face Four-Thirty - # LAME ("🕔", ""), # Clock Face Five O'Clock - # LAME ("🕠", ""), # Clock Face Five-Thirty - # LAME ("🕕", ""), # Clock Face Six O'Clock - # LAME ("🕡", ""), # Clock Face Six-Thirty - # LAME ("🕖", ""), # Clock Face Seven O'Clock - # LAME ("🕢", ""), # Clock Face Seven-Thirty - # LAME ("🕗", ""), # Clock Face Eight O'Clock - # LAME ("🕣", ""), # Clock Face Eight-Thirty - # LAME ("🕘", ""), # Clock Face Nine O'Clock - # LAME ("🕤", ""), # Clock Face Nine-Thirty - # LAME ("🕙", ""), # Clock Face Ten O'Clock - # LAME ("🕥", ""), # Clock Face Ten-Thirty - # LAME ("🕚", ""), # Clock Face Eleven O'Clock - # LAME ("🕦", ""), # Clock Face Eleven-Thirty - # LAME ("⛎", ""), # Ophiuchus - ("🌑", "🌑"), # New Moon Symbol - # LAME ("🌒", ""), # Waxing Crescent Moon Symbol - # LAME ("🌓", ""), # First Quarter Moon Symbol - # LAME ("🌔", ""), # Waxing Gibbous Moon Symbol - ("🌕", "🌕"), # Full Moon Symbol - # LAME ("🌖", ""), # Waning Gibbous Moon Symbol - ("🌗", "🌗"), # Last Quarter Moon Symbol - # LAME ("🌘", ""), # Waning Crescent Moon Symbol - # LAME ("🌙", ""), # Crescent Moon - # OFFENSIVE("🌚", ""), # New Moon With Face - # LAME ("🌛", ""), # First Quarter Moon With Face - # LAME ("🌜", ""), # Last Quarter Moon With Face - # LAME ("🌝", ""), # Full Moon With Face - ("🌞", "🌞"), # Sun With Face - # LAME ("🌀", ""), # Cyclone - ("🌈", "🌈"), # Rainbow - ("🌂", "🌂"), # Closed Umbrella - ("🌟", "🌟"), # Glowing Star - # LAME ("🌠", ""), # Shooting Star - ("🔥", "🔥"), # Fire - ("🎃", "🎃"), # Jack-O-Lantern - ("🎄", "🎄"), # Christmas Tree - # LAME ("🎆", ""), # Fireworks - # LAME ("🎇", ""), # Firework Sparkler - # LAME ("✨", ""), # Sparkles - ("🎈", "🎈"), # Balloon - ("🎉", "🎉"), # Party Popper - # LAME ("🎊", ""), # Confetti Ball - # LAME ("🎋", ""), # Tanabata Tree - # LAME ("🎌", ""), # Crossed Flags - # LAME ("🎍", ""), # Pine Decoration - # LAME ("🎎", ""), # Japanese Dolls - # LAME ("🎏", ""), # Carp Streamer - # LAME ("🎐", ""), # Wind Chime - # LAME ("🎑", ""), # Moon Viewing Ceremony - ("🎓", "🎓"), # Graduation Cap - ("🎯", "🎯"), # Direct Hit - # LAME ("🎴", ""), # Flower Playing Cards - ("🎀", "🎀"), # Ribbon - # LAME ("🎁", ""), # Wrapped Present - # LAME ("🎫", ""), # Ticket - ("🏀", "🏀"), # Basketball and Hoop - ("🏈", "🏈"), # American Football - # TOO SIMILAR ("🏉", ""), # Rugby Football - ("🎾", "🎾"), # Tennis Racquet and Ball - ("🎱", "🎱"), # Billiards - # TOO SIMILAR ("🎳", ""), # Bowling - # LAME ("🎣", ""), # Fishing Pole and Fish - # LAME ("🎽", ""), # Running Shirt With Sash - # LAME ("🎿", ""), # Ski and Ski Boot - # LAME ("🏂", ""), # Snowboarder - # LAME ("🏄", ""), # Surfer - # LAME ("🏇", ""), # Horse Racing - # LAME ("🏊", ""), # Swimmer - # LAME ("🚴", ""), # Bicyclist - # LAME ("🚵", ""), # Mountain Bicyclist - # USED BY UI ("🏆", ""), # Trophy // for adding new tournament/list of tournaments - ("🎮", "🎮"), # Video Game - ("🎲", "🎲"), # Game Die - # LAME ("🃏", ""), # Playing Card Black Joker - # LAME ("🔇", ""), # Speaker With Cancellation Stroke - # LAME ("🔈", ""), # Speaker - # LAME ("🔉", ""), # Speaker With One Sound Wave - # LAME ("🔊", ""), # Speaker With Three Sound Waves - # USED BY UI ("📢", ""), # Public Address Loudspeaker // for public config settings - ("📣", "📣"), # Cheering Megaphone - ("📯", ""), # Postal Horn - ("🔔", "🔔"), # Bell - # ("🔕", ""), # Bell With Cancellation Stroke - # LAME ("🔀", ""), # Twisted Rightwards Arrows - # LAME ("🔁", ""), # Clockwise Rightwards and Leftwards Open Circle Arrows - # LAME ("🔂", ""), # Clockwise Rightwards and Leftwards Open Circle Arrows With Circled One Overlay - # LAME ("⏩", ""), # Black Right-Pointing Double Triangle - # LAME ("⏭", ""), # Black Right-Pointing Double Triangle With Vertical Bar - # LAME ("⏯", ""), # Black Right-Pointing Triangle With Double Vertical Bar - # LAME ("⏪", ""), # Black Left-Pointing Double Triangle - # LAME ("⏮", ""), # Black Left-Pointing Double Triangle With Vertical Bar - # LAME ("🔼", ""), # Up-Pointing Small Red Triangle - # LAME ("⏫", ""), # Black Up-Pointing Double Triangle - # LAME ("🔽", ""), # Down-Pointing Small Red Triangle - # LAME ("⏬", ""), # Black Down-Pointing Double Triangle - # LAME ("🎼", ""), # Musical Score - # LAME ("🎵", ""), # Musical Note - ("🎶", "🎶"), # Multiple Musical Notes - ("🎤", "🎤"), # Microphone - # LAME ("🎧", ""), # Headphone - # LAME ("🎷", ""), # Saxophone - # LAME ("🎸", ""), # Guitar - ("🎹", "🎹"), # Musical Keyboard - ("🎺", "🎺"), # Trumpet - ("🎻", "🎻"), # Violin - ("📻", "📻"), # Radio - ("📱", "📱"), # Mobile Phone - # LAME ("📳", ""), # Vibration Mode - # LAME ("📴", ""), # Mobile Phone Off - # TOO SIMILAR ("📲", ""), # Mobile Phone With Rightwards Arrow at Left - # LAME ("📵", ""), # No Mobile Phones - ("📞", "📞"), # Telephone Receiver - # LAME ("🔟", ""), # Keycap Ten - # LAME ("📶", ""), # Antenna With Bars - # LAME ("📟", ""), # Pager - # LAME ("📠", ""), # Fax Machine - ("🔋", "🔋"), # Battery - ("🔌", "🔌"), # Electric Plug - # LAME ("💻", ""), # Personal Computer - # LAME ("💽", ""), # Minidisc - ("💾", "💾"), # Floppy Disk - ("💿", "💿"), # Optical Disc - # LAME ("📀", ""), # DVD - # LAME ("🎥", ""), # Movie Camera - # LAME ("🎦", ""), # Cinema - ("🎬", "🎬"), # Clapper Board - # LAME ("📺", ""), # Television - ("📷", "📷"), # Camera - # LAME ("📹", ""), # Video Camera - # LAME ("📼", ""), # Videocassette - # LAME ("🔅", ""), # Low Brightness Symbol - # LAME ("🔆", ""), # High Brightness Symbol - ("🔍", "🔍"), # Left-Pointing Magnifying Glass - # LAME ("🔎", ""), # Right-Pointing Magnifying Glass - # LAME ("🔬", ""), # Microscope - ("🔭", "🔭"), # Telescope - # LAME ("📡", ""), # Satellite Antenna - ("💡", "💡"), # Electric Light Bulb - # LAME ("🔦", ""), # Electric Torch - # LAME ("🏮", ""), # Izakaya Lantern - # TOO SIMILAR ("📔", ""), # Notebook With Decorative Cover - ("📕", "📕"), # Closed Book - # TOO SIMILAR ("📖", ""), # Open Book - # TOO SIMILAR ("📗", ""), # Green Book - # TOO SIMILAR ("📘", ""), # Blue Book - # TOO SIMILAR ("📙", ""), # Orange Book - # TOO SIMILAR ("📚", ""), # Books - # TOO SIMILAR ("📓", ""), # Notebook - # TOO SIMILAR ("📒", ""), # Ledger - # TOO SIMILAR ("📃", ""), # Page With Curl - # TOO SIMILAR ("📜", ""), # Scroll - # TOO SIMILAR ("📄", ""), # Page Facing Up - ("📰", "📰"), # Newspaper - # TOO SIMILAR ("📑", ""), # Bookmark Tabs - # TOO SIMILAR ("🔖", ""), # Bookmark - ("💰", "💰"), # Money Bag - # TOO SIMILAR ("💴", ""), # Banknote With Yen Sign - # TOO SIMILAR ("💵", ""), # Banknote With Dollar Sign - # TOO SIMILAR ("💶", ""), # Banknote With Euro Sign - # TOO SIMILAR ("💷", ""), # Banknote With Pound Sign - ("💸", "💸"), # Money With Wings - # LAME ("💱", ""), # Currency Exchange - # LAME ("💲", ""), # Heavy Dollar Sign - # LAME ("💳", ""), # Credit Card - # LAME ("💹", ""), # Chart With Upwards Trend and Yen Sign - # LAME ("📧", ""), # E-Mail Symbol - # LAME ("📨", ""), # Incoming Envelope - # LAME ("📩", ""), # Envelope With Downwards Arrow Above - # LAME ("📤", ""), # Outbox Tray - # LAME ("📥", ""), # Inbox Tray - ("📦", ""), # Package - ("📫", "📫"), # Closed Mailbox With Raised Flag - # LAME ("📪", ""), # Closed Mailbox With Lowered Flag - # LAME ("📬", ""), # Open Mailbox With Raised Flag - # LAME ("📭", ""), # Open Mailbox With Lowered Flag - # LAME ("📮", ""), # Postbox - # LAME ("📝", ""), # Memo - ("💼", "💼"), # Briefcase - # LAME ("📁", ""), # File Folder - # LAME ("📂", ""), # Open File Folder - ("📅", "📅"), # Calendar - # LAME ("📆", ""), # Tear-Off Calendar - # LAME ("📇", ""), # Card Index - # LAME ("📈", ""), # Chart With Upwards Trend - # LAME ("📉", ""), # Chart With Downwards Trend - # LAME ("📊", ""), # Bar Chart - # LAME ("📋", ""), # Clipboard - # LAME ("📌", ""), # Pushpin - # LAME ("📍", ""), # Round Pushpin - # LAME ("📎", ""), # Paperclip - ("📏", "📏"), # Straight Ruler - ("📐", "📐"), # Triangular Ruler - # LAME ("📛", ""), # Name Badge - # USED BY UI ("🔒", ""), # Lock // Logout page - # USED BY UI ("🔓", ""), # Open Lock // Login page - # ("🔏", ""), # Lock With Ink Pen - # ("🔐", ""), # Closed Lock With Key - ("🔑", "🔑"), # Key - # LAME ("🔨", ""), # Hammer - # USED BY UI ("🔧", ""), # Wrench // for tournament config link - ("🔩", "🔩"), # Nut and Bolt - # LAME ("🔗", ""), # Link Symbol - # OFFENSIVE ("💉", ""), # Syringe - ("💊", ""), # Pill - ("🔪", "🔪"), # Hocho - ("🔫", "🔫"), # Pistol - ("🚬", "🚬"), # Smoking Symbol - ("🏁", ""), # Chequered Flag - # LAME ("🚩", ""), # Triangular Flag on Post - # LAME ("🇦🇫", ""), # Flag for Afghanistan - # LAME ("🇦🇽", ""), # Flag for Åland Islands - # LAME ("🇦🇱", ""), # Flag for Albania - # LAME ("🇩🇿", ""), # Flag for Algeria - # LAME ("🇦🇸", ""), # Flag for American Samoa - # LAME ("🇦🇩", ""), # Flag for Andorra - # LAME ("🇦🇴", ""), # Flag for Angola - # LAME ("🇦🇮", ""), # Flag for Anguilla - # ("🇦🇶", "🇦🇶"), # Flag for Antarctica - # LAME ("🇦🇬", ""), # Flag for Antigua & Barbuda - # LAME ("🇦🇷", ""), # Flag for Argentina - # LAME ("🇦🇲", ""), # Flag for Armenia - # LAME ("🇦🇼", ""), # Flag for Aruba - # LAME ("🇦🇨", ""), # Flag for Ascension Island - # ("🇦🇺", "🇦🇺"), # Flag for Australia - # ("🇦🇹", "🇦🇹"), # Flag for Austria - # LAME ("🇦🇿", ""), # Flag for Azerbaijan - # LAME ("🇧🇸", ""), # Flag for Bahamas - # LAME ("🇧🇭", ""), # Flag for Bahrain - # LAME ("🇧🇩", ""), # Flag for Bangladesh - # LAME ("🇧🇧", ""), # Flag for Barbados - # LAME ("🇧🇾", ""), # Flag for Belarus - # LAME ("🇧🇪", ""), # Flag for Belgium - # LAME ("🇧🇿", ""), # Flag for Belize - # LAME ("🇧🇯", ""), # Flag for Benin - # LAME ("🇧🇲", ""), # Flag for Bermuda - # LAME ("🇧🇹", ""), # Flag for Bhutan - # LAME ("🇧🇴", ""), # Flag for Bolivia - # LAME ("🇧🇦", ""), # Flag for Bosnia & Herzegovina - # LAME ("🇧🇼", ""), # Flag for Botswana - # LAME ("🇧🇻", ""), # Flag for Bouvet Island - # ("🇧🇷", "🇧🇷"), # Flag for Brazil - # LAME ("🇮🇴", ""), # Flag for British Indian Ocean Territory - # LAME ("🇻🇬", ""), # Flag for British Virgin Islands - # LAME ("🇧🇳", ""), # Flag for Brunei - # LAME ("🇧🇬", ""), # Flag for Bulgaria - # LAME ("🇧🇫", ""), # Flag for Burkina Faso - # LAME ("🇧🇮", ""), # Flag for Burundi - # LAME ("🇰🇭", ""), # Flag for Cambodia - # LAME ("🇨🇲", ""), # Flag for Cameroon - # ("🇨🇦", "🇨🇦"), # Flag for Canada - # LAME ("🇮🇨", ""), # Flag for Canary Islands - # LAME ("🇨🇻", ""), # Flag for Cape Verde - # LAME ("🇧🇶", ""), # Flag for Caribbean Netherlands - # LAME ("🇰🇾", ""), # Flag for Cayman Islands - # LAME ("🇨🇫", ""), # Flag for Central African Republic - # LAME ("🇪🇦", ""), # Flag for Ceuta & Melilla - # LAME ("🇹🇩", ""), # Flag for Chad - # ("🇨🇱", "🇨🇱"), # Flag for Chile - # ("🇨🇳", "🇨🇳"), # Flag for China - # LAME ("🇨🇽", ""), # Flag for Christmas Island - # LAME ("🇨🇵", ""), # Flag for Clipperton Island - # LAME ("🇨🇨", ""), # Flag for Cocos Islands - # LAME ("🇨🇴", ""), # Flag for Colombia - # LAME ("🇰🇲", ""), # Flag for Comoros - # LAME ("🇨🇬", ""), # Flag for Congo - Brazzaville - # LAME ("🇨🇩", ""), # Flag for Congo - Kinshasa - # LAME ("🇨🇰", ""), # Flag for Cook Islands - # LAME ("🇨🇷", ""), # Flag for Costa Rica - # LAME ("🇨🇮", ""), # Flag for Côte D’Ivoire - # LAME ("🇭🇷", ""), # Flag for Croatia - # LAME ("🇨🇺", ""), # Flag for Cuba - # LAME ("🇨🇼", ""), # Flag for Curaçao - # LAME ("🇨🇾", ""), # Flag for Cyprus - # ("🇨🇿", "🇨🇿"), # Flag for Czech Republic - # ("🇩🇰", "🇩🇰"), # Flag for Denmark - # LAME ("🇩🇬", ""), # Flag for Diego Garcia - # LAME ("🇩🇯", ""), # Flag for Djibouti - # LAME ("🇩🇲", ""), # Flag for Dominica - # LAME ("🇩🇴", ""), # Flag for Dominican Republic - # LAME ("🇪🇨", ""), # Flag for Ecuador - # ("🇪🇬", "🇪🇬"), # Flag for Egypt - # LAME ("🇸🇻", ""), # Flag for El Salvador - # LAME ("🇬🇶", ""), # Flag for Equatorial Guinea - # LAME ("🇪🇷", ""), # Flag for Eritrea - # LAME ("🇪🇪", ""), # Flag for Estonia - # LAME ("🇪🇹", ""), # Flag for Ethiopia - # ("🇪🇺", "🇪🇺"), # Flag for European Union - # LAME ("🇫🇰", ""), # Flag for Falkland Islands - # LAME ("🇫🇴", ""), # Flag for Faroe Islands - # LAME ("🇫🇯", ""), # Flag for Fiji - # LAME ("🇫🇮", ""), # Flag for Finland - # ("🇫🇷", "🇫🇷"), # Flag for France - # LAME ("🇬🇫", ""), # Flag for French Guiana - # LAME ("🇵🇫", ""), # Flag for French Polynesia - # LAME ("🇹🇫", ""), # Flag for French Southern Territories - # LAME ("🇬🇦", ""), # Flag for Gabon - # LAME ("🇬🇲", ""), # Flag for Gambia - # LAME ("🇬🇪", ""), # Flag for Georgia - # ("🇩🇪", "🇩🇪"), # Flag for Germany - # LAME ("🇬🇭", ""), # Flag for Ghana - # LAME ("🇬🇮", ""), # Flag for Gibraltar - # ("🇬🇷", "🇬🇷"), # Flag for Greece - # LAME ("🇬🇱", ""), # Flag for Greenland - # LAME ("🇬🇩", ""), # Flag for Grenada - # LAME ("🇬🇵", ""), # Flag for Guadeloupe - # LAME ("🇬🇺", ""), # Flag for Guam - # LAME ("🇬🇹", ""), # Flag for Guatemala - # LAME ("🇬🇬", ""), # Flag for Guernsey - # LAME ("🇬🇳", ""), # Flag for Guinea - # LAME ("🇬🇼", ""), # Flag for Guinea-Bissau - # LAME ("🇬🇾", ""), # Flag for Guyana - # LAME ("🇭🇹", ""), # Flag for Haiti - # LAME ("🇭🇲", ""), # Flag for Heard & McDonald Islands - # LAME ("🇭🇳", ""), # Flag for Honduras - # LAME ("🇭🇰", ""), # Flag for Hong Kong - # LAME ("🇭🇺", ""), # Flag for Hungary - # LAME ("🇮🇸", ""), # Flag for Iceland - # ("🇮🇳", "🇮🇳"), # Flag for India - # ("🇮🇩", "🇮🇩"), # Flag for Indonesia - # ("🇮🇷", "🇮🇷"), # Flag for Iran - # ("🇮🇶", "🇮🇶"), # Flag for Iraq - # ("🇮🇪", "🇮🇪"), # Flag for Ireland - # LAME ("🇮🇲", ""), # Flag for Isle of Man - # LAME ("🇮🇱", ""), # Flag for Israel - # ("🇮🇹", "🇮🇹"), # Flag for Italy - # LAME ("🇯🇲", ""), # Flag for Jamaica - # ("🇯🇵", "🇯🇵"), # Flag for Japan - # LAME ("🇯🇪", ""), # Flag for Jersey - # LAME ("🇯🇴", ""), # Flag for Jordan - # LAME ("🇰🇿", ""), # Flag for Kazakhstan - # LAME ("🇰🇪", ""), # Flag for Kenya - # LAME ("🇰🇮", ""), # Flag for Kiribati - # LAME ("🇽🇰", ""), # Flag for Kosovo - # LAME ("🇰🇼", ""), # Flag for Kuwait - # LAME ("🇰🇬", ""), # Flag for Kyrgyzstan - # LAME ("🇱🇦", ""), # Flag for Laos - # LAME ("🇱🇻", ""), # Flag for Latvia - # LAME ("🇱🇧", ""), # Flag for Lebanon - # LAME ("🇱🇸", ""), # Flag for Lesotho - # LAME ("🇱🇷", ""), # Flag for Liberia - # LAME ("🇱🇾", ""), # Flag for Libya - # LAME ("🇱🇮", ""), # Flag for Liechtenstein - # LAME ("🇱🇹", ""), # Flag for Lithuania - # LAME ("🇱🇺", ""), # Flag for Luxembourg - # LAME ("🇲🇴", ""), # Flag for Macau - # LAME ("🇲🇰", ""), # Flag for Macedonia - # LAME ("🇲🇬", ""), # Flag for Madagascar - # LAME ("🇲🇼", ""), # Flag for Malawi - # LAME ("🇲🇾", ""), # Flag for Malaysia - # LAME ("🇲🇻", ""), # Flag for Maldives - # LAME ("🇲🇱", ""), # Flag for Mali - # LAME ("🇲🇹", ""), # Flag for Malta - # LAME ("🇲🇭", ""), # Flag for Marshall Islands - # LAME ("🇲🇶", ""), # Flag for Martinique - # LAME ("🇲🇷", ""), # Flag for Mauritania - # LAME ("🇲🇺", ""), # Flag for Mauritius - # LAME ("🇾🇹", ""), # Flag for Mayotte - # ("🇲🇽", "🇲🇽"), # Flag for Mexico - # LAME ("🇫🇲", ""), # Flag for Micronesia - # LAME ("🇲🇩", ""), # Flag for Moldova - # LAME ("🇲🇨", ""), # Flag for Monaco - # LAME ("🇲🇳", ""), # Flag for Mongolia - # LAME ("🇲🇪", ""), # Flag for Montenegro - # LAME ("🇲🇸", ""), # Flag for Montserrat - # LAME ("🇲🇦", ""), # Flag for Morocco - # LAME ("🇲🇿", ""), # Flag for Mozambique - # LAME ("🇲🇲", ""), # Flag for Myanmar - # LAME ("🇳🇦", ""), # Flag for Namibia - # LAME ("🇳🇷", ""), # Flag for Nauru - # LAME ("🇳🇵", ""), # Flag for Nepal - # LAME ("🇳🇱", ""), # Flag for Netherlands - # LAME ("🇳🇨", ""), # Flag for New Caledonia - # ("🇳🇿", "🇳🇿"), # Flag for New Zealand - # LAME ("🇳🇮", ""), # Flag for Nicaragua - # LAME ("🇳🇪", ""), # Flag for Niger - # LAME ("🇳🇬", ""), # Flag for Nigeria - # LAME ("🇳🇺", ""), # Flag for Niue - # LAME ("🇳🇫", ""), # Flag for Norfolk Island - # LAME ("🇲🇵", ""), # Flag for Northern Mariana Islands - # LAME ("🇰🇵", ""), # Flag for North Korea - # ("🇳🇴", "🇳🇴"), # Flag for Norway - # LAME ("🇴🇲", ""), # Flag for Oman - # LAME ("🇵🇰", ""), # Flag for Pakistan - # LAME ("🇵🇼", ""), # Flag for Palau - # ("🇵🇸", "🇵🇸"), # Flag for Palestinian Territories - # LAME ("🇵🇦", ""), # Flag for Panama - # LAME ("🇵🇬", ""), # Flag for Papua New Guinea - # LAME ("🇵🇾", ""), # Flag for Paraguay - # ("🇵🇪", "🇵🇪"), # Flag for Peru - # LAME ("🇵🇭", ""), # Flag for Philippines - # LAME ("🇵🇳", ""), # Flag for Pitcairn Islands - # LAME ("🇵🇱", ""), # Flag for Poland - # LAME ("🇵🇹", ""), # Flag for Portugal - # LAME ("🇵🇷", ""), # Flag for Puerto Rico - # LAME ("🇶🇦", ""), # Flag for Qatar - # LAME ("🇷🇪", ""), # Flag for Réunion - # LAME ("🇷🇴", ""), # Flag for Romania - # ("🇷🇺", "🇷🇺"), # Flag for Russia - # LAME ("🇷🇼", ""), # Flag for Rwanda - # LAME ("🇼🇸", ""), # Flag for Samoa - # LAME ("🇸🇲", ""), # Flag for San Marino - # LAME ("🇸🇹", ""), # Flag for São Tomé & Príncipe - # LAME ("🇸🇦", ""), # Flag for Saudi Arabia - # LAME ("🇸🇳", ""), # Flag for Senegal - # LAME ("🇷🇸", ""), # Flag for Serbia - # LAME ("🇸🇨", ""), # Flag for Seychelles - # LAME ("🇸🇱", ""), # Flag for Sierra Leone - # LAME ("🇸🇬", ""), # Flag for Singapore - # LAME ("🇸🇽", ""), # Flag for Sint Maarten - # LAME ("🇸🇰", ""), # Flag for Slovakia - # LAME ("🇸🇮", ""), # Flag for Slovenia - # LAME ("🇸🇧", ""), # Flag for Solomon Islands - # LAME ("🇸🇴", ""), # Flag for Somalia - # ("🇿🇦", "🇿🇦"), # Flag for South Africa - # LAME ("🇬🇸", ""), # Flag for South Georgia & South Sandwich Islands - # ("🇰🇷", "🇰🇷"), # Flag for South Korea - # LAME ("🇸🇸", ""), # Flag for South Sudan - # ("🇪🇸", "🇪🇸"), # Flag for Spain - # LAME ("🇱🇰", ""), # Flag for Sri Lanka - # LAME ("🇧🇱", ""), # Flag for St. Barthélemy - # LAME ("🇸🇭", ""), # Flag for St. Helena - # LAME ("🇰🇳", ""), # Flag for St. Kitts & Nevis - # LAME ("🇱🇨", ""), # Flag for St. Lucia - # LAME ("🇲🇫", ""), # Flag for St. Martin - # LAME ("🇵🇲", ""), # Flag for St. Pierre & Miquelon - # LAME ("🇻🇨", ""), # Flag for St. Vincent & Grenadines - # LAME ("🇸🇩", ""), # Flag for Sudan - # LAME ("🇸🇷", ""), # Flag for Suriname - # LAME ("🇸🇯", ""), # Flag for Svalbard & Jan Mayen - # LAME ("🇸🇿", ""), # Flag for Swaziland - # ("🇸🇪", "🇸🇪"), # Flag for Sweden - # ("🇨🇭", "🇨🇭"), # Flag for Switzerland - # LAME ("🇸🇾", ""), # Flag for Syria - # LAME ("🇹🇼", ""), # Flag for Taiwan - # LAME ("🇹🇯", ""), # Flag for Tajikistan - # LAME ("🇹🇿", ""), # Flag for Tanzania - # LAME ("🇹🇭", ""), # Flag for Thailand - # LAME ("🇹🇱", ""), # Flag for Timor-Leste - # LAME ("🇹🇬", ""), # Flag for Togo - # LAME ("🇹🇰", ""), # Flag for Tokelau - # LAME ("🇹🇴", ""), # Flag for Tonga - # LAME ("🇹🇹", ""), # Flag for Trinidad & Tobago - # LAME ("🇹🇦", ""), # Flag for Tristan Da Cunha - # LAME ("🇹🇳", ""), # Flag for Tunisia - # ("🇹🇷", "🇹🇷"), # Flag for Turkey - # LAME ("🇹🇲", ""), # Flag for Turkmenistan - # LAME ("🇹🇨", ""), # Flag for Turks & Caicos Islands - # LAME ("🇹🇻", ""), # Flag for Tuvalu - # LAME ("🇺🇬", ""), # Flag for Uganda - # LAME ("🇺🇦", ""), # Flag for Ukraine - # LAME ("🇦🇪", ""), # Flag for United Arab Emirates - # ("🇬🇧", "🇬🇧"), # Flag for United Kingdom - # ("🇺🇸", "🇺🇸"), # Flag for United States - # LAME ("🇺🇾", ""), # Flag for Uruguay - # LAME ("🇺🇲", ""), # Flag for U.S. Outlying Islands - # LAME ("🇻🇮", ""), # Flag for U.S. Virgin Islands - # LAME ("🇺🇿", ""), # Flag for Uzbekistan - # LAME ("🇻🇺", ""), # Flag for Vanuatu - # ("🇻🇦", "🇻🇦"), # Flag for Vatican City - # LAME ("🇻🇪", ""), # Flag for Venezuela - # ("🇻🇳", "🇻🇳"), # Flag for Vietnam - # LAME ("🇼🇫", ""), # Flag for Wallis & Futuna - # LAME ("🇪🇭", ""), # Flag for Western Sahara - # LAME ("🇾🇪", ""), # Flag for Yemen - # LAME ("🇿🇲", ""), # Flag for Zambia - # LAME ("🇿🇼", ""), # Flag for Zimbabwe - # LAME ("🔃", ""), # Clockwise Downwards and Upwards Open Circle Arrows - # LAME ("🔄", ""), # Anticlockwise Downwards and Upwards Open Circle Arrows - # LAME ("🔙", ""), # Back With Leftwards Arrow Above - # LAME ("🔚", ""), # End With Leftwards Arrow Above - # LAME ("🔛", ""), # On With Exclamation Mark With Left Right Arrow Above - # LAME ("🔜", ""), # Soon With Rightwards Arrow Above - # LAME ("🔝", ""), # Top With Upwards Arrow Above - # LAME ("🔰", ""), # Japanese Symbol for Beginner - ("🔮", "🔮"), # Crystal Ball - # LAME ("🔯", ""), # Six Pointed Star With Middle Dot - # LAME ("✅", ""), # White Heavy Check Mark - ("❌", "❌"), # Cross Mark - # LAME ("❎", ""), # Negative Squared Cross Mark - # LAME ("➕", ""), # Heavy Plus Sign - # LAME ("➖", ""), # Heavy Minus Sign - # LAME ("➗", ""), # Heavy Division Sign - # LAME ("➰", ""), # Curly Loop - # LAME ("➿", ""), # Double Curly Loop - ("❓", "❓"), # Black Question Mark Ornament - # TOO SIMILAR ("❔", ""), # White Question Mark Ornament - # TOO SIMILAR ("❕", ""), # White Exclamation Mark Ornament - # USED BY UI ("💯", ""), # Hundred Points Symbol // Speaker tab - ("🔞", "🔞"), # No One Under Eighteen Symbol - # LAME ("🔠", ""), # Input Symbol for Latin Capital Letters - # LAME ("🔡", ""), # Input Symbol for Latin Small Letters - # LAME ("🔢", ""), # Input Symbol for Numbers - # LAME ("🔣", ""), # Input Symbol for Symbols - # LAME ("🔤", ""), # Input Symbol for Latin Letters - # LAME ("🅰️", ""), # Negative Squared Latin Capital Letter A - # LAME ("🆎", ""), # Negative Squared AB - # LAME ("🅱️", ""), # Negative Squared Latin Capital Letter B - # LAME ("🆑", ""), # Squared CL - ("🆒", "🆒"), # Squared Cool - # LAME ("🆓", ""), # Squared Free - # LAME ("🆔", ""), # Squared ID - # LAME ("🆕", ""), # Squared New - # LAME ("🆖", ""), # Squared NG - # LAME ("🅾️", ""), # Negative Squared Latin Capital Letter O - ("🆗", "🆗"), # Squared OK - ("🆘", "🆘"), # Squared SOS - # LAME ("🆙", ""), # Squared Up With Exclamation Mark - # LAME ("🆚", ""), # Squared Vs - # LAME ("🈁", ""), # Squared Katakana Koko - # LAME ("🈂️", ""), # Squared Katakana Sa - # LAME ("🈷️", ""), # Squared CJK Unified Ideograph-6708 - # LAME ("🈶", ""), # Squared CJK Unified Ideograph-6709 - # LAME ("🉐", ""), # Circled Ideograph Advantage - # LAME ("🈹", ""), # Squared CJK Unified Ideograph-5272 - # LAME ("🈲", ""), # Squared CJK Unified Ideograph-7981 - # LAME ("🉑", ""), # Circled Ideograph Accept - # LAME ("🈸", ""), # Squared CJK Unified Ideograph-7533 - # LAME ("🈴", ""), # Squared CJK Unified Ideograph-5408 - # LAME ("🈳", ""), # Squared CJK Unified Ideograph-7a7a - # LAME ("🈺", ""), # Squared CJK Unified Ideograph-55b6 - # LAME ("🈵", ""), # Squared CJK Unified Ideograph-6e80 - # LAME ("🔶", ""), # Large Orange Diamond - # LAME ("🔷", ""), # Large Blue Diamond - # LAME ("🔸", ""), # Small Orange Diamond - # LAME ("🔹", ""), # Small Blue Diamond - # LAME ("🔺", ""), # Up-Pointing Red Triangle - # LAME ("🔻", ""), # Down-Pointing Red Triangle - # LAME ("💠", ""), # Diamond Shape With a Dot Inside - # LAME ("🔘", ""), # Radio Button - # LAME ("🔲", ""), # Black Square Button - # LAME ("🔳", ""), # White Square Button - # LAME ("🔴", ""), # Large Red Circle - # LAME ("🔵", ""), # Large Blue Circle - # Unicode Version 6.1 - # TOO SIMILAR ("😀", ""), # Grinning Face - # TOO SIMILAR ("😗", ""), # Kissing Face - ("😙", "😙"), # Kissing Face With Smiling Eyes - ("😑", "😑"), # Expressionless Face - ("😮", "😮"), # Face With Open Mouth - # TOO SIMILAR ("😯", ""), # Hushed Face - ("😴", "😴"), # Sleeping Face - ("😛", "😛"), # Face With Stuck-Out Tongue - # TOO SIMILAR ("😕", ""), # Confused Face - # TOO SIMILAR ("😟", ""), # Worried Face - # TOO SIMILAR ("😦", ""), # Frowning Face With Open Mouth - ("😧", "😧"), # Anguished Face - ("😬", "😬"), # Grimacing Face - # Unicode Version 7.0 - # TOO SIMILAR ("🙂", ""), # Slightly Smiling Face - # TOO SIMILAR ("🙁", ""), # Slightly Frowning Face - ("🕵", "🕵"), # Sleuth or Spy - # LAME ("🗣", ""), # Speaking Head in Silhouette - # LAME ("🕴", ""), # Man in Business Suit Levitating - ("🖕", "🖕"), # Reversed Hand With Middle Finger Extended - ("🖖", "🖖"), # Raised Hand With Part Between Middle and Ring Fingers - # TOO SIMILAR ("🖐", ""), # Raised Hand With Fingers Splayed - ("👁", "👁"), # Eye - # LAME ("🕳", ""), # Hole - # LAME ("🗯", ""), # Right Anger Bubble - ("🕶", "🕶"), # Dark Sunglasses - ("🛍", "🛍"), # Shopping Bags - ("🐿", "🐿"), # Chipmunk - ("🕊", "🕊"), # Dove of Peace - ("🕷", "🕷"), # Spider - # LAME ("🕸", ""), # Spider Web - # LAME ("🏵", ""), # Rosette - ("🌶", "🌶"), # Hot Pepper - # LAME ("🍽", ""), # Fork and Knife With Plate - # LAME ("🗺", ""), # World Map - # LAME ("🏔", ""), # Snow Capped Mountain - # LAME ("🏕", ""), # Camping - # LAME ("🏖", ""), # Beach With Umbrella - # LAME ("🏜", ""), # Desert - # LAME ("🏝", ""), # Desert Island - # LAME ("🏞", ""), # National Park - # LAME ("🏟", ""), # Stadium - ("🏛", "🏛"), # Classical Building - # LAME ("🏗", ""), # Building Construction - # LAME ("🏘", ""), # House Buildings - # LAME ("🏙", ""), # Cityscape - # LAME ("🏚", ""), # Derelict House Building - # LAME ("🖼", ""), # Frame With Picture - ("🛢", "🛢"), # Oil Drum - # LAME ("🛣", ""), # Motorway - # LAME ("🛤", ""), # Railway Track - # LAME ("🛳", ""), # Passenger Ship - # LAME ("🛥", ""), # Motor Boat - # LAME ("🛩", ""), # Small Airplane - # LAME ("🛫", ""), # Airplane Departure - # LAME ("🛬", ""), # Airplane Arriving - # LAME ("🛰", ""), # Satellite - ("🛎", "🛎"), # Bellhop Bell - # LAME ("🛌", ""), # Sleeping Accommodation - # LAME ("🛏", ""), # Bed - # LAME ("🛋", ""), # Couch and Lamp - ("🕰", "🕰"), # Mantelpiece Clock - ("🌡", "🌡"), # Thermometer - ("🌤", "🌤"), # White Sun With Small Cloud - # LAME ("🌥", ""), # White Sun Behind Cloud - # LAME ("🌦", ""), # White Sun Behind Cloud With Rain - ("🌧", "🌧"), # Cloud With Rain - # LAME ("🌨", ""), # Cloud With Snow - ("🌩", "🌩"), # Cloud With Lightning - ("🌪", "🌪"), # Cloud With Tornado - ("🌫", "🌫"), # Fog - ("🌬", "🌬"), # Wind Blowing Face - ("🎖", "🎖"), # Military Medal - ("🎗", "🎗"), # Reminder Ribbon - ("🎞", "🎞"), # Film Frames - # LAME ("🎟", ""), # Admission Tickets - ("🏷", "🏷"), # Label - # LAME ("🏌", ""), # Golfer - # LAME ("🏋", ""), # Weight Lifter - # LAME ("🏎", ""), # Racing Car - # LAME ("🏍", ""), # Racing Motorcycle - ("🏅", "🏅"), # Sports Medal - ("🕹", "🕹"), # Joystick - # LAME ("⏸", ""), # Double Vertical Bar - # LAME ("⏹", ""), # Black Square for Stop - # LAME ("⏺", ""), # Black Circle for Record - ("🎙", "🎙"), # Studio Microphone - # LAME ("🎚", ""), # Level Slider - # LAME ("🎛", ""), # Control Knobs - ("🖥", "🖥"), # Desktop Computer - ("🖨", "🖨"), # Printer - # LAME ("🖱", ""), # Three Button Mouse - ("🖲", "🖲"), # Trackball - # LAME ("📽", ""), # Film Projector - # LAME ("📸", ""), # Camera With Flash - ("🕯", "🕯"), # Candle - # LAME ("🗞", ""), # Rolled-Up Newspaper - # LAME ("🗳", ""), # Ballot Box With Ballot - ("🖋", "🖋"), # Lower Left Fountain Pen - # LAME ("🖊", ""), # Lower Left Ballpoint Pen - # LAME ("🖌", ""), # Lower Left Paintbrush - # LAME ("🖍", ""), # Lower Left Crayon - # LAME ("🗂", ""), # Card Index Dividers - # LAME ("🗒", ""), # Spiral Note Pad - # LAME ("🗓", ""), # Spiral Calendar Pad - # LAME ("🖇", ""), # Linked Paperclips - # LAME ("🗃", ""), # Card File Box - # LAME ("🗄", ""), # File Cabinet - ("🗑", "🗑"), # Wastebasket - # LAME ("🗝", ""), # Old Key - # LAME ("🛠", ""), # Hammer and Wrench - # LAME ("🗜", ""), # Compression - ("🗡", "🗡"), # Dagger Knife - ("🛡", "🛡"), # Shield - ("🏳", "🏳"), # Waving White Flag - ("🏴", "🏴"), # Waving Black Flag - # LAME ("🕉", ""), # Om Symbol - # LAME ("🗨", ""), # Left Speech Bubble - # Unicode Version 8.0 - ("🤗", "🤗"), # Hugging Face - ("🤔", "🤔"), # Thinking Face - ("🙄", "🙄"), # Face With Rolling Eyes - ("🤐", "🤐"), # Zipper-Mouth Face - ("🤓", "🤓"), # Nerd Face - ("🙃", "🙃"), # Upside-Down Face - ("🤒", "🤒"), # Face With Thermometer - ("🤕", "🤕"), # Face With Head-Bandage - ("🤑", "🤑"), # Money-Mouth Face - # LAME ("🏻", ""), # Emoji Modifier Fitzpatrick Type-1-2 - # LAME ("🏼", ""), # Emoji Modifier Fitzpatrick Type-3 - # LAME ("🏽", ""), # Emoji Modifier Fitzpatrick Type-4 - # LAME ("🏾", ""), # Emoji Modifier Fitzpatrick Type-5 - # LAME ("🏿", ""), # Emoji Modifier Fitzpatrick Type-6 - ("🤘", "🤘"), # Sign of the Horns - ("📿", "📿"), # Prayer Beads - ("🤖", "🤖"), # Robot Face - ("🦁", "🦁"), # Lion Face - ("🦄", "🦄"), # Unicorn Face - # LAME ("🦃", ""), # Turkey - ("🦀", "🦀"), # Crab - # LAME ("🦂", ""), # Scorpion - ("🧀", "🧀"), # Cheese Wedge - ("🌭", "🌭"), # Hot Dog - ("🌮", "🌮"), # Taco - # LAME ("🌯", ""), # Burrito - ("🍿", "🍿"), # Popcorn - ("🍾", "🍾"), # Bottle With Popping Cork - # LAME ("🏺", ""), # Amphora - # LAME ("🛐", ""), # Place of Worship - # OFFENSIVE ("🕋", ""), # Kaaba - # OFFENSIVE ("🕌", ""), # Mosque - # OFFENSIVE ("🕍", ""), # Synagogue - # OFFENSIVE ("🕎", ""), # Menorah With Nine Branches - ("🏏", "🏏"), # Cricket Bat and Ball - ("🏐", "🏐"), # Volleyball - # TOO SIMILAR ("🏑", ""), # Field Hockey Stick and Ball - # TOO SIMILAR ("🏒", ""), # Ice Hockey Stick and Puck - ("🏓", "🏓"), # Table Tennis Paddle and Ball - # TOO SIMILAR ("🏸", ""), # Badminton Racquet and Shuttlecock - ("🏹", "🏹"), # Bow and Arrow -) diff --git a/participants/templates/confirm_shifts.html b/participants/templates/confirm_shifts.html deleted file mode 100644 index e1782384031..00000000000 --- a/participants/templates/confirm_shifts.html +++ /dev/null @@ -1,45 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} -{% load add_field_css %} - -{% block head-title %}Shift Check-In for {{ adjudicator.name }}{% endblock %} -{% block page-title %}Shift Check-In for {{ adjudicator.name }}{% endblock %} - -{% block content %} - -
- {% csrf_token %} - {{ formset.management_form }} - -
- {% for form in formset %} - -
-
-
-

- {{ form.instance.debate.round.abbreviation }}: - {{ form.instance.debate.division.venue_group }} @ - {{ form.instance.debate.division.time_slot }} -

-
-
-
- {{ form }} -
-
-
-
- - {% endfor %} -
- -
- -
- -
- -{% endblock content %} diff --git a/participants/templates/public_participants.html b/participants/templates/public_participants.html deleted file mode 100644 index a7f389b4fb8..00000000000 --- a/participants/templates/public_participants.html +++ /dev/null @@ -1,119 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} -{% load static %} - -{% block head-title %}Participants{% endblock %} -{% block page-title %}Participants{% endblock %} - -{% block content %} - -
-
-

Speakers

-
- - - - - {% if pref.show_novices %} - - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.public_break_categories %} - - {% endif %} - {% if pref.show_institutions %} - - {% endif %} - - - - {% for person in speakers %} - - - {% if pref.show_novices %} - - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.public_break_categories %} - - {% endif %} - {% if pref.show_institutions %} - - {% endif %} - - {% endfor %} - -
NameNoviceTeamEligible forInstitution
{{ person.name }} - {% if person.novice %}{% else %}{% endif %} - - {{ person.team.emoji }} - - {% include "tables/team.html" with team=person.team %} - {{ person.team.break_categories_nongeneral|join:", " }}{{ person.team.institution.name }}
-
-
-
- -
- -
-

Adjudicators

-
- - - - - - - - - {% for person in adjs %} - - - - - {% endfor %} - -
NameInstitution
{{ person.name }} - {% if person.independent %} - Independent / - {% endif %} - {% if person.adj_core %} - Adj Core / - {% endif %} - {{ person.institution.name }} -
-
-
- -
- -{% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/participants/urls_public.py b/participants/urls_public.py deleted file mode 100644 index bde3b118170..00000000000 --- a/participants/urls_public.py +++ /dev/null @@ -1,22 +0,0 @@ -from django.conf.urls import * - -from . import views - -urlpatterns = [ - url(r'^list/$', - views.public_participants, - name='public_participants'), - url(r'^team_list/(?P\d+)/$', - views.team_speakers, - name='team_speakers'), - url(r'^all_tournaments_all_teams/$', - views.all_tournaments_all_teams, - name='all_tournaments_all_teams'), - url(r'^all_tournaments_all_institutions/$', - views.all_tournaments_all_institutions, - name='all_tournaments_all_institutions'), - - url(r'^shifts/a(?P\w+)/$', - views.public_confirm_shift_key, - name='public_confirm_shift_key'), -] diff --git a/participants/views.py b/participants/views.py deleted file mode 100644 index b6b3968b064..00000000000 --- a/participants/views.py +++ /dev/null @@ -1,60 +0,0 @@ -from django.http import JsonResponse -from django.forms.models import modelformset_factory -from utils.views import * -from .models import Adjudicator, Speaker, Institution, Team -from adjallocation.models import DebateAdjudicator - -@cache_page(settings.TAB_PAGES_CACHE_TIMEOUT) -@tournament_view -def team_speakers(request, t, team_id): - team = Team.objects.get(pk=team_id) - speakers = team.speakers - data = {} - for i, speaker in enumerate(speakers): - data[i] = "
  • " + speaker.name + "
  • " - - return JsonResponse(data, safe=False) - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('public_participants') -def public_participants(request, t): - adjs = Adjudicator.objects.all() - speakers = Speaker.objects.all().select_related('team','team__institution') - return render(request, "public_participants.html", dict(adjs=adjs, speakers=speakers)) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('enable_mass_draws') -def all_tournaments_all_institutions(request, t): - institutions = Institution.objects.all() - return render(request, 'public_all_tournament_institutions.html', dict( - institutions=institutions)) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('enable_mass_draws') -def all_tournaments_all_teams(request, t): - teams = Team.objects.filter(tournament__active=True).select_related('tournament').prefetch_related('division') - return render(request, 'public_all_tournament_teams.html', dict( - teams=teams)) - - -# Scheduling - -@public_optional_tournament_view('allocation_confirmations') -def public_confirm_shift_key(request, t, url_key): - adj = get_object_or_404(Adjudicator, url_key=url_key) - adj_debates = DebateAdjudicator.objects.filter(adjudicator=adj) - - ShiftsFormset = modelformset_factory(DebateAdjudicator, - can_delete=False, extra=0, fields=['timing_confirmed']) - - if request.method == 'POST': - formset = ShiftsFormset(request.POST, request.FILES) - if formset.is_valid(): - formset.save() - messages.success(request, "Your shift check-ins have been saved") - else: - formset = ShiftsFormset(queryset=adj_debates) - - return render(request, 'confirm_shifts.html', dict(formset=formset, adjudicator=adj)) diff --git a/requirements.txt b/requirements.txt index 53ba0c3a7b0..1a38db0e9f5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,4 +15,4 @@ django-pylibmc==0.6.1 newrelic # For emailing -sendgrid>=0.5.0 +sendgrid==3.1.10 diff --git a/requirements_common.txt b/requirements_common.txt index 68bbe8a8407..5d37e9000d8 100644 --- a/requirements_common.txt +++ b/requirements_common.txt @@ -1,16 +1,20 @@ # This file contains the necessary dependencies for local and heroku installs -Django==1.9.6 +Django==1.9.9 dj-cmd==0.5 # Provides the dj command alias django-appconf==1.0.2 # Adds helper class for handling app configs django-dynamic-preferences==0.8.1 -django-debug-toolbar==1.4.0 # Debug Toolbar -django-extensions==1.6.7 # For the generate secret command -django-gulp==2.4.0 # Run gulp tasks with runserver/collectstatic +django-debug-toolbar==1.5.0 # Debug Toolbar +django-extensions==1.7.1 # For the generate secret command +django-gulp==2.4.1 # Run gulp tasks with runserver/collectstatic django-ipware==1.1.5 # IP Address logging -django-jet==0.1.4 # Admin Backend -psycopg2==2.6.1 # For Django to talk to postgres +django-jet==0.9.0 # Admin Backend +psycopg2==2.6.2 # For Django to talk to postgres six==1.10.0 # Six is a Python 2 and 3 compatibility library. -sqlparse==0.1.19 -whitenoise==3.2.0 # Static file serving +sqlparse==0.2.1 +whitenoise==3.2.1 # Static file serving waitress==0.9.0 # For web serving +flake8==3.0.4 # For testing/linting (not strictly required) +pep8-naming==0.4.1 # Flake plugin for naming conventions +flake8-import-order==0.9.2 # Flake plugin for import order +flake8-quotes==0.8.1 # Flake plugin for quotes diff --git a/results/templates/enter_results_ballot_set.html b/results/templates/enter_results_ballot_set.html deleted file mode 100644 index 46326a0c1a9..00000000000 --- a/results/templates/enter_results_ballot_set.html +++ /dev/null @@ -1,165 +0,0 @@ -{% load add_field_css %} -{% load debate_tags %} - -
    - - {% if form.errors %} -
    -

    There are some problems with this scoresheet. Please review and correct them.

    - {% if form.non_field_errors %} -

    General errors:

    -
    {{ form.non_field_errors }}
    - {% endif %} -
    - {% endif %} - - {% if form.choose_sides %} -
    - -
    - {{ form.choose_sides|addcss:"form-control choose-sides required" }} - {{ form.choose_sides.errors }} -
    -
    - - {% endif %} - - - {% if pref.enable_motions or pref.enable_motions %} -
    -
    -
    -
    -

    Motion

    -
    -
    - {% if pref.enable_motions %} -
    - -
    - {{ form.motion|addcss:"form-control motion required" }} - {{ form.motion.errors }} -
    -
    - {% endif %} - {% if pref.motion_vetoes_enabled %} -
    - -
    - {{ form.aff_motion_veto|addcss:"form-control motion" }} - {{ form.aff_motion_veto.errors }} -
    -
    -
    - -
    - {{ form.neg_motion_veto|addcss:"form-control motion" }} - {{ form.neg_motion_veto.errors }} -
    -
    - {% endif %} -
    -
    -
    -
    - {% endif %} - - {% for adj in form.adj_iter %} -
    -
    -
    -
    -

    Ballot from {{ adj.adj }} - {% if pref.side_allocations_unknown == 'manual-ballot' %} -

    Assign sides before entering scores

    - {% endif %} -

    -
    -
    -
    -
    -
    - -
    - {% for position in adj.position_iter %} -
    - -
    - {% if forloop.parentloop.first %} - {{ position.aff_speaker|addcss:"form-control js-speaker required aff-speaker" }} - {{ position.aff_speaker.errors }} - {% else %} -
    - {% endif %} -
    -
    - {{ position.aff_score }} - {{ position.aff_score_errors }} - {{ position.aff_score.errors }} -
    -
    - {% endfor %} -
    - -
    -
    00
    -
    -
    -
    -
    -
    - -
    - {% for position in adj.position_iter %} -
    - -
    - {% if forloop.parentloop.first %} - {{ position.neg_speaker|addcss:"form-control js-speaker required neg-speaker" }} - {{ position.neg_speaker.errors }} - {% else %} -
    - {% endif %} -
    -
    - {{ position.neg_score }} - {{ position.neg_score_errors }} - {{ position.neg_score.errors }} -
    -
    - {% endfor %} -
    - -
    -
    00
    -
    -
    -
    -
    -
    -
    -
    -
    - {% endfor %} - - {% if pref.enable_forfeits %} -
    -
    -
    -
    -

    Forfeits

    -
    -
    - {{ form.forfeits|addcss:"form-control" }} - {{ form.forfeits.errors }} -
    -
    -
    -
    - {% endif %} - -
    diff --git a/results/templates/public_results_for_round.html b/results/templates/public_results_for_round.html deleted file mode 100644 index 349cc8a2ac8..00000000000 --- a/results/templates/public_results_for_round.html +++ /dev/null @@ -1,115 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} - -{% block head-title %}💥Results for {{ round.name }}{% endblock %} -{% block page-title %}💥Results for {{ round.name }}{% endblock %} -{% block page-subnav-sections %}{% include "tables/table_search.html" %}{% endblock %} - -{% block content %} -
    -
    - - - - {% if pref.enable_divisions %} - - {% endif %} - - {% if pref.ballots_released %}{% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_emoji %} - - {% endif %} - - - {% if show_motions_column %} - - {% endif %} - - - - {% for debate in draw %} - - {% if pref.enable_divisions %} - - {% endif %} - - {% if pref.ballots_released %} - - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_emoji %} - - {% endif %} - - - {% if show_motions_column %} - - {% endif %} - - - {% endfor %} -
    BallotsAffNegAdjsM
    {{ debate.division.name }}{% if debate.venue %}{{ debate.venue.name }}{% endif %} - {% if debate.confirmed_ballot %} - View ballots - {% else %} - No result - {% endif %} - {{ debate.aff_team.emoji }} - {% if debate.confirmed_ballot.ballot_set.aff_win == 1 %} - - {% elif debate.confirmed_ballot.ballot_set.neg_win == 1 %} - - {% endif %} - {% include "tables/team.html" with team=debate.aff_team %} - {{ debate.neg_team.emoji }} - {% if debate.confirmed_ballot.ballot_set.neg_win == 1 %} - - {% elif debate.confirmed_ballot.ballot_set.aff_win == 1 %} - - {% endif %} - {% include "tables/team.html" with team=debate.neg_team %} - - {% if debate.confirmed_ballot and pref.show_splitting_adjudicators %} - {% for type, adj, split in debate.confirmed_ballot.ballot_set.adjudicator_results %} - {% if split %} - {{ adj.name }}{% if type == 'C' and debate.adjudicators.is_panel %} (c){% elif type == 'T' %} (t){% endif %} {% if not forloop.last %},{% endif %} - {% else %} - {{ adj.name }}{% if type == 'C' and debate.adjudicators.is_panel %} (c){% elif type == 'T' %} (t){% endif %}{% if not forloop.last %},{% endif %} - {% endif %} - {% endfor %} - {% else %} - {% for type, adj in debate.adjudicators %} - {{ adj.name }}{% if type == 'C' and debate.adjudicators.is_panel %} (c){% elif type == 'T' %} (t){% endif %}{% if not forloop.last %},{% endif %} - {% endfor %} - {% endif %} - - - {{ debate.confirmed_ballot.motion.reference }} - -
    -
    -
    -{% endblock content %} - -{% block extra-js %} - {{ block.super }} - -{% endblock extra-js %} diff --git a/results/templates/results.html b/results/templates/results.html deleted file mode 100644 index 3a0b3a5a6cd..00000000000 --- a/results/templates/results.html +++ /dev/null @@ -1,217 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} - -{% block page-title %}Results for {{ round.name }}{% endblock %} -{% block head-title %}📩Results{% endblock %} -{% block sub-title %}for {{ round.name }}{% endblock %} - -{% block page-subnav-sections %} - Ballot Check-In - {% include "tables/table_search.html" %} -{% endblock %} - -{% block page-subnav-actions %} - {% if round.seq < tournament.round_set.count and current_round == round %} - - Advance to Next Round - - {% endif %} -{% endblock %} - -{% block page-alerts %} - {% if not has_motions %} -
    - Currently there are no motions entered for this round, so debate results - cannot be entered. Add Motions. -
    - {% endif %} -{% endblock %} - -{% block content %} - -
    -
    -
    -
    -
    - - {{ stats.ballot_in }} Checked In - - - {{ stats.none }} Unknown - - - {{ stats.draft }} Unconfirmed - - - {{ stats.confirmed }} Confirmed - - {% if pref.enable_postponements %} - - {{ stats.postponed }} Postponed - - - Bye - - {% endif %} -
    -
    -
    - - - - - - - {% if pref.enable_postponements %} - - {% endif %} - - - - - - - - - - - {% for debate in draw %} - - {% include 'tables/debate_icon.html' %} - - - {% if pref.enable_postponements %} - - {% endif %} - - {% if pref.enable_venue_groups %} - {% if debate.division %} - - {% else %} - - {% endif %} - {% else %} - - {% endif %} - - - - - {% endfor %} -
    BallotsAffNegAdjs
    - {% if debate.result_status == debate.STATUS_POSTPONED %} - Un-postpone - {% elif debate.result_status != debate.STATUS_CONFIRMED and debate.aff_team.type != 'B' and debate.neg_team.type != 'B' %} - Postpone - {% endif %} - {{ debate.bracket }}{{ debate.division.venue_group.short_name }}{{ debate.venue.group.short_name }} {{ debate.venue.name }}{{ debate.venue.name }} - {% if debate.confirmed_ballot.forfeit %} - {% if debate.confirmed_ballot.ballot_set.neg_win == 1 %} - - {% else %} - - {% endif %} - {% elif debate.confirmed_ballot.ballot_set.aff_win == 1 %} - - {% elif debate.confirmed_ballot.ballot_set.neg_win == 1 %} - - {% endif %} - {% include "tables/team.html" with team=debate.aff_team %} - - {% if debate.confirmed_ballot.forfeit %} - {% if debate.confirmed_ballot.ballot_set.aff_win == 1 %} - - {% else %} - - {% endif %} - {% elif debate.confirmed_ballot.ballot_set.neg_win == 1 %} - - {% elif debate.confirmed_ballot.ballot_set.aff_win == 1 %} - - {% endif %} - {% include "tables/team.html" with team=debate.neg_team %} - - {% if debate.confirmed_ballot %} - {% for type, adj, split in debate.confirmed_ballot.ballot_set.adjudicator_results %} - {% if split %} - {{ adj.name }}{% if type == 'C' and debate.adjudicators.is_panel %} Ⓒ{% elif type == 'T' %} Ⓣ{% endif %} {% if not forloop.last %},{% endif %} - {% else %} - {{ adj.name }}{% if type == 'C' and debate.adjudicators.is_panel %} Ⓒ{% elif type == 'T' %} Ⓣ{% endif %}{% if not forloop.last %},{% endif %} - {% endif %} - {% endfor %} - {% else %} - {% for type, adj in debate.adjudicators %} - {{ adj.name }}{% if type == 'C' and debate.adjudicators.is_panel %} Ⓒ{% elif type == 'T' %} Ⓣ{% endif %}{% if not forloop.last %},{% endif %} - {% endfor %} - {% endif %} -
    -
    -
    -
    -
    -{% endblock content %} - -{% block extra-js %} - -{% endblock %} diff --git a/standings/templates/divisions.html b/standings/templates/divisions.html deleted file mode 100644 index 5e36c5d885b..00000000000 --- a/standings/templates/divisions.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "teams.html" %} -{% load static %} -{% load debate_tags %} -{% load metricformat %} - -{% block page-title %}👯Division Standings after {{ round.name }}{% endblock %} -{% block head-title %}👯Division Standings{% endblock %} -{% block sub-title %}after {{ round.name }}{% endblock %} -{% block team_active %}{% endblock %} -{% block division_active %}active{% endblock %} diff --git a/standings/templates/motions.html b/standings/templates/motions.html deleted file mode 100644 index 9d0d6b7ddde..00000000000 --- a/standings/templates/motions.html +++ /dev/null @@ -1,116 +0,0 @@ -{% extends "standings_base.html" %} -{% load debate_tags %} - -{% block page-title %}Motions Balance{% endblock %} -{% block head-title %}Motions Balance{% endblock %} -{% block motion_active %}active{% endblock %} - -{% block content %} -
    -
    -
    -
    - - - - - - - - - {% if pref.enable_flagged_motions %} - - {% endif %} - {% if pref.enable_division_motions %} - - {% endif %} - - {% if pref.motion_vetoes_enabled %} - - - {% endif %} - - - - - - - - {% for motion in motions %} - - - - - - - {% if pref.enable_flagged_motions %} - - {% endif %} - {% if pref.enable_division_motions %} - - {% endif %} - - {% if pref.motion_vetoes_enabled %} - - - {% endif %} - - - - - - {% endfor %} - -
    RSeqRoundOrderReferenceMFlaggedDivisionsChosenAVNVAWNWChi2P-val.
    {{ motion.round.seq }}{{ motion.round.abbreviation }}{{ motion.seq }}{{ motion.reference }} - Show full text - {{ motion.text }} - - {% if motion.flagged %} - Yes - {% else %} - No - {% endif %} - - {% for division in motion.divisions.all %} - {{ division.name }}, - {% endfor %} - {{ motion.chosen_in }}{{ motion.aff_vetoes }}{{ motion.neg_vetoes }}{{ motion.aff_wins }}{{ motion.neg_wins }} - {{ motion.c1|floatformat:1 }} - - {{ motion.p_value|floatformat:2 }} -
    -
    -
    -
    -
    -{% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/standings/templates/novices.html b/standings/templates/novices.html deleted file mode 100644 index 16e4a066420..00000000000 --- a/standings/templates/novices.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "speakers.html" %} -{% load debate_tags %} -{% load static %} - -{% block page-title %}Novice Speaker Standings after {{ round.name }}{% endblock %} -{% block head-title %}Novice Speaker Standings{% endblock %} -{% block sub-title %}after {{ round.name }}{% endblock %} - -{% block novices_active %}active{% endblock %} diff --git a/standings/templates/public_feedback_tab.html b/standings/templates/public_feedback_tab.html deleted file mode 100644 index 058c99ba162..00000000000 --- a/standings/templates/public_feedback_tab.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "feedback_progress.html" %} -{% load debate_tags %} - -{% block page-title %}Feedback Progress{% endblock %} -{% block head-title %}Feedback Progress {% endblock %} -{% block sub-title %}(tracking who has or has not returned their ballots){% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} diff --git a/standings/templates/public_motions_tab.html b/standings/templates/public_motions_tab.html deleted file mode 100644 index dc7a22e5304..00000000000 --- a/standings/templates/public_motions_tab.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "motions.html" %} -{% load debate_tags %} - -{% block head-title %}💭Motions Tab{% endblock %} -{% block page-title %}💭Motions Tab{% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} diff --git a/standings/templates/public_novices_tab.html b/standings/templates/public_novices_tab.html deleted file mode 100644 index 235e7c7f564..00000000000 --- a/standings/templates/public_novices_tab.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "speakers.html" %} -{% load debate_tags %} - -{% block head-title %}Novices Speaker Tab{% endblock %} -{% block page-title %}Novices Speaker Tab{% endblock %} -{% block sub-title %}{% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} diff --git a/standings/templates/public_pros_tab.html b/standings/templates/public_pros_tab.html deleted file mode 100644 index 15fa5692e1b..00000000000 --- a/standings/templates/public_pros_tab.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "speakers.html" %} -{% load debate_tags %} - -{% block head-title %}Pros Speaker Tab{% endblock %} -{% block page-title %}Pros Speaker Tab{% endblock %} -{% block sub-title %}{% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} diff --git a/standings/templates/public_reply_tab.html b/standings/templates/public_reply_tab.html deleted file mode 100644 index a1b9e0fa631..00000000000 --- a/standings/templates/public_reply_tab.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "replies.html" %} -{% load debate_tags %} - -{% block head-title %}Replies Tab{% endblock %} -{% block page-title %}Replies Tab{% endblock %} -{% block sub-title %}{% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} diff --git a/standings/templates/public_speaker_tab.html b/standings/templates/public_speaker_tab.html deleted file mode 100644 index ab7a5681dbb..00000000000 --- a/standings/templates/public_speaker_tab.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends "speakers.html" %} -{% load debate_tags %} - -{% block page-title %}💯 Speaker Tab{% endblock %} -{% block head-title %} - 💯Speaker Tab -{% endblock %} -{% block sub-title %}{% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} diff --git a/standings/templates/public_team_standings.html b/standings/templates/public_team_standings.html deleted file mode 100644 index d3de5e2e668..00000000000 --- a/standings/templates/public_team_standings.html +++ /dev/null @@ -1,110 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} - -{% block page-title %}Team Standings after {{ round.name }}{% endblock %} -{% block head-title %}Team Standings{% endblock %} -{% block sub-title %}after {{ round.name }}{% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} - -{% block content %} -
    -
    - - - - {% if pref.enable_divisions %} - - {% endif %} - - {% if pref.show_emoji %} - - {% endif %} - {% if pref.show_institutions %} - - {% endif %} - {% if pref.enable_divisions %} - - {% endif %} - - {% for round in rounds %} - - {% endfor %} - - - - {% for team in teams %} - - {% if pref.enable_divisions %} - - {% endif %} - - {% if pref.show_emoji %} - - {% endif %} - {% if pref.show_institutions %} - - {% endif %} - {% if pref.enable_divisions %} - - {% endif %} - - {% for round_results in team.round_results %} - {% if round_results.win >= 0 %} - - {% else %} - - {% endif %} - {% endfor %} - - - {% endfor %} -
    TeamInstitutionPtsWins{{ round.abbreviation }}
    {{ team.division.name }} - {% include "tables/team.html" with team=team %} - {{ team.emoji }}{{ team.institution.code }}{{ team.points }}{{ team.wins }} - {% if round_results.score == 0 %} - {% with status=round_results.win|yesno:"Won (via forfeit),Forfeitted" icon=round_results.win|yesno:"glyphicon-share-alt text-success,glyphicon-eye-close text-danger" %} - - - {% endwith %} - {% else %} - {% with status=round_results.win|yesno:"Won,Lost" icon=round_results.win|yesno:"glyphicon-arrow-up text-success,glyphicon-arrow-down text-danger" %} - - - {% endwith %} - {% endif %} - {% if pref.show_emoji %} - vs {{ round_results.opposition.emoji }} - {% endif %} - -
    -
    -
    -{% endblock content %} - -{% block extra-js %} - {{ block.super }} - -{% endblock extra-js %} diff --git a/standings/templates/public_team_tab.html b/standings/templates/public_team_tab.html deleted file mode 100644 index 56186e1abc5..00000000000 --- a/standings/templates/public_team_tab.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "teams.html" %} - -{% block head-title %}👯Team Tab{% endblock %} -{% block page-title %}👯Team Tab{% endblock %} -{% block sub-title %}{% endblock %} - -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} diff --git a/standings/templates/replies.html b/standings/templates/replies.html deleted file mode 100644 index 4aefb5aab7d..00000000000 --- a/standings/templates/replies.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "speakers.html" %} -{% load debate_tags %} -{% load static %} - -{% block page-title %}Reply Speaker Standings after {{ round.name }}{% endblock %} -{% block head-title %}💁Reply Standings{% endblock %} -{% block sub-title %}after {{ round.name }}{% endblock %} - -{% block replies_active %}active{% endblock %} -{% block speaker_active %}{% endblock %} diff --git a/standings/templates/speakers.html b/standings/templates/speakers.html deleted file mode 100644 index a2105a4a308..00000000000 --- a/standings/templates/speakers.html +++ /dev/null @@ -1,115 +0,0 @@ -{% extends "standings_base.html" %} -{% load debate_tags %} -{% load static %} -{% load metricformat %} - -{% block page-title %}Speaker Standings after {{ round.name }}{% endblock %} -{% block head-title %} - 💯Speaker Standings -{% endblock %} -{% block sub-title %}after {{ round.name }}{% endblock %} -{% block speaker_active %}active{% endblock %} - -{% block content %} -
    -
    - - - - - {% for info in standings.rankings_info %} - - {% endfor %} - - {% if pref.show_novices %} - - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for round in rounds %} - - {% endfor %} - {% for info in standings.metrics_info %} - - {% endfor %} - - - - {% for info in standings.standings %} - - - {% for ranking in info.iterrankings %} - - {% endfor %} - - {% if pref.show_novices %} - - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for score in info.scores %} - - {% endfor %} - {% for metric in info.itermetrics %} - {# the metricformat filter is defined in templatetags/metricformat.py #} - - {% endfor %} - - {% endfor %} - -
    - {% if info.glyphicon %} - - {% else %} - - {{ info.abbr }} - {% endif %} - NameTeamInstitution{{ round.abbreviation }} - {% if info.glyphicon %} - - {% else %} - - {{ info.abbr }} - {% endif %} -
    - - {{ ranking.0|default:"n/a" }}{% if ranking.1 %}={% endif %} - - {{ info.speaker.name }}{% if info.speaker.novice %}{% endif %} - {{ info.speaker.team.emoji }} - - {% include "tables/team.html" with team=info.speaker.team %} - {{ info.speaker.team.institution.code }}{{ score|stringformat:".2f" }}{{ metric|metricformat }}
    -
    -
    -{% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/standings/templates/teams.html b/standings/templates/teams.html deleted file mode 100644 index c641fd576ff..00000000000 --- a/standings/templates/teams.html +++ /dev/null @@ -1,150 +0,0 @@ -{% extends "standings_base.html" %} -{% load static %} -{% load debate_tags %} -{% load metricformat %} - -{% block page-title %}👯Team Standings after {{ round.name }}{% endblock %} -{% block head-title %}👯Team Standings{% endblock %} -{% block sub-title %}after {{ round.name }}{% endblock %} - -{% block content %} -
    -
    - - - - - {% for info in standings.rankings_info %} - - {% endfor %} - {% if pref.enable_divisions %} - - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for round in rounds %} - - - {% endfor %} - {% for info in standings.metrics_info %} - - {% endfor %} - - - - {% for info in standings.standings %} - - - {% for ranking in info.iterrankings %} - - {% endfor %} - {% if pref.enable_divisions %} - - {% endif %} - {% if pref.show_emoji %} - - {% endif %} - - {% if pref.show_institutions %} - - {% endif %} - {% for round_results in info.round_results %} - {% if round_results.win >= 0 %} - - {% if show_ballots and round_results.debate_team.debate_id and not round_results.forfeit %} - - {% elif not round_results.forfeit %} - - {% else %} - - {% endif %} - {% else %} - - - {% endif %} - {% endfor %} - {% for metric in info.itermetrics %} - {# the metricformat filter is defined in templatetags/metricformat.py #} - - {% endfor %} - - {% endfor %} - -
    - {% if info.glyphicon %} - - {% else %} - - {{ info.abbr }} - {% endif %} - TeamInst{{ round.abbreviation }}{{ round.abbreviation }} - {% if info.glyphicon %} - - {% else %} - - {{ info.abbr }} - {% endif %} -
    - - {{ ranking.0|default:"n/a" }}{% if ranking.1 %}={% endif %} - - D{{ info.team.division.name }}{{ info.team.emoji }} - {% include "tables/team.html" with team=info.team %} - {{ info.team.break_categories_str }} - - - {{ info.team.institution.code }} - - {% if round_results.score == 0 %} - {% with status=round_results.win|yesno:"Won (via forfeit),Forfeitted" icon=round_results.win|yesno:"glyphicon-share-alt text-success,glyphicon-eye-close text-danger" %} - - - {% endwith %} - {% else %} - {% with status=round_results.win|yesno:"Won,Lost" icon=round_results.win|yesno:"glyphicon-arrow-up text-success,glyphicon-arrow-down text-danger" %} - - - {% endwith %} - {% endif %} - {% if pref.show_emoji %} - vs {{ round_results.opposition.emoji }} - {% endif %} - - - - {{ round_results.score|floatformat:2 }} - - {{ round_results.score|floatformat:2 }}n/a{{ metric|metricformat }}
    -
    -
    -{% endblock content %} - -{% block extra-js %} - {{ block.super }} - -{% endblock extra-js %} diff --git a/standings/urls_admin.py b/standings/urls_admin.py deleted file mode 100644 index ef9a3f9a873..00000000000 --- a/standings/urls_admin.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.conf.urls import url - -from . import views - -urlpatterns = [ - url(r'^$', views.StandingsIndexView.as_view(), name='standings-index'), - url(r'^team/$', views.TeamStandingsView.as_view(), name='standings-team'), - url(r'^division/$', views.DivisionStandingsView.as_view(), name='standings-division'), - - url(r'^speaker/$', views.SpeakerStandingsView.as_view(), name='standings-speaker'), - url(r'^novices/$', views.NoviceStandingsView.as_view(), name='standings-novice'), - url(r'^pros/$', views.ProStandingsView.as_view(), name='standings-pro'), - url(r'^reply/$', views.ReplyStandingsView.as_view(), name='standings-reply'), - url(r'^motions/$', views.MotionStandingsView.as_view(), name='standings-motion'), -] diff --git a/static/admin/img/icon-unknown.gif b/static/admin/img/icon-unknown.gif deleted file mode 100644 index 18a642d9282..00000000000 Binary files a/static/admin/img/icon-unknown.gif and /dev/null differ diff --git a/static/admin/img/icon_deletelink.gif b/static/admin/img/icon_deletelink.gif deleted file mode 100644 index 18a642d9282..00000000000 Binary files a/static/admin/img/icon_deletelink.gif and /dev/null differ diff --git a/__init__.py b/tabbycat/__init__.py similarity index 100% rename from __init__.py rename to tabbycat/__init__.py diff --git a/actionlog/__init__.py b/tabbycat/actionlog/__init__.py similarity index 100% rename from actionlog/__init__.py rename to tabbycat/actionlog/__init__.py diff --git a/actionlog/admin.py b/tabbycat/actionlog/admin.py similarity index 99% rename from actionlog/admin.py rename to tabbycat/actionlog/admin.py index 41a53cc10b8..ad931486791 100644 --- a/actionlog/admin.py +++ b/tabbycat/actionlog/admin.py @@ -6,6 +6,7 @@ # Adjudicator Logs # ============================================================================== + class ActionLogEntryAdmin(admin.ModelAdmin): list_display = ('type', 'user', 'timestamp', 'get_parameters_display', 'tournament') diff --git a/actionlog/apps.py b/tabbycat/actionlog/apps.py similarity index 73% rename from actionlog/apps.py rename to tabbycat/actionlog/apps.py index 3e4b42e59a4..9196a304f31 100644 --- a/actionlog/apps.py +++ b/tabbycat/actionlog/apps.py @@ -1,5 +1,6 @@ from django.apps import AppConfig + class ActionLogConfig(AppConfig): name = 'actionlog' - verbose_name = "Action Log" \ No newline at end of file + verbose_name = "Action Log" diff --git a/actionlog/management/commands/printactionlog.py b/tabbycat/actionlog/management/commands/printactionlog.py similarity index 87% rename from actionlog/management/commands/printactionlog.py rename to tabbycat/actionlog/management/commands/printactionlog.py index e2c794933be..b864975ae3b 100644 --- a/actionlog/management/commands/printactionlog.py +++ b/tabbycat/actionlog/management/commands/printactionlog.py @@ -1,10 +1,12 @@ from django.core.management.base import BaseCommand + from ...models import ActionLogEntry + class Command(BaseCommand): help = "Prints every entry in the action log (for all tournaments)" def handle(self, **options): for al in ActionLogEntry.objects.order_by('-timestamp'): - self.stdout.write(repr(al)) \ No newline at end of file + self.stdout.write(repr(al)) diff --git a/actionlog/migrations/0001_initial.py b/tabbycat/actionlog/migrations/0001_initial.py similarity index 100% rename from actionlog/migrations/0001_initial.py rename to tabbycat/actionlog/migrations/0001_initial.py diff --git a/actionlog/migrations/0002_auto_20160103_1927.py b/tabbycat/actionlog/migrations/0002_auto_20160103_1927.py similarity index 100% rename from actionlog/migrations/0002_auto_20160103_1927.py rename to tabbycat/actionlog/migrations/0002_auto_20160103_1927.py diff --git a/actionlog/migrations/0003_auto_20160103_1927.py b/tabbycat/actionlog/migrations/0003_auto_20160103_1927.py similarity index 100% rename from actionlog/migrations/0003_auto_20160103_1927.py rename to tabbycat/actionlog/migrations/0003_auto_20160103_1927.py diff --git a/actionlog/migrations/0004_auto_20160103_1927.py b/tabbycat/actionlog/migrations/0004_auto_20160103_1927.py similarity index 100% rename from actionlog/migrations/0004_auto_20160103_1927.py rename to tabbycat/actionlog/migrations/0004_auto_20160103_1927.py diff --git a/actionlog/migrations/0005_auto_20160109_1834.py b/tabbycat/actionlog/migrations/0005_auto_20160109_1834.py similarity index 100% rename from actionlog/migrations/0005_auto_20160109_1834.py rename to tabbycat/actionlog/migrations/0005_auto_20160109_1834.py diff --git a/actionlog/migrations/0006_auto_20160228_1838.py b/tabbycat/actionlog/migrations/0006_auto_20160228_1838.py similarity index 100% rename from actionlog/migrations/0006_auto_20160228_1838.py rename to tabbycat/actionlog/migrations/0006_auto_20160228_1838.py diff --git a/actionlog/migrations/0007_auto_20160507_1521.py b/tabbycat/actionlog/migrations/0007_auto_20160507_1521.py similarity index 100% rename from actionlog/migrations/0007_auto_20160507_1521.py rename to tabbycat/actionlog/migrations/0007_auto_20160507_1521.py diff --git a/actionlog/migrations/0008_auto_20160510_1610.py b/tabbycat/actionlog/migrations/0008_auto_20160510_1610.py similarity index 100% rename from actionlog/migrations/0008_auto_20160510_1610.py rename to tabbycat/actionlog/migrations/0008_auto_20160510_1610.py diff --git a/actionlog/migrations/0009_auto_20160611_1747.py b/tabbycat/actionlog/migrations/0009_auto_20160611_1747.py similarity index 100% rename from actionlog/migrations/0009_auto_20160611_1747.py rename to tabbycat/actionlog/migrations/0009_auto_20160611_1747.py diff --git a/tabbycat/actionlog/migrations/0010_auto_20160708_1054.py b/tabbycat/actionlog/migrations/0010_auto_20160708_1054.py new file mode 100644 index 00000000000..12be7179d31 --- /dev/null +++ b/tabbycat/actionlog/migrations/0010_auto_20160708_1054.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-08 10:54 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('actionlog', '0009_auto_20160611_1747'), + ] + + operations = [ + migrations.AlterField( + model_name='actionlogentry', + name='type', + field=models.CharField(choices=[('ba.disc', 'Discarded ballot set'), ('ba.ckin', 'Checked in ballot set'), ('ba.crea', 'Created ballot set'), ('ba.edit', 'Edited ballot set'), ('ba.conf', 'Confirmed ballot set'), ('ba.subm', 'Submitted ballot set from the public form'), ('fb.subm', 'Submitted feedback from the public form'), ('fb.save', 'Saved feedback'), ('ts.edit', 'Edited adjudicator test score'), ('aj.note', 'Set adjudicator note'), ('aa.save', 'Saved adjudicator allocation'), ('aa.auto', 'Auto-allocated adjudicators'), ('ve.save', 'Saved venues'), ('ve.auto', 'Auto-allocated venues'), ('dr.crea', 'Created draw'), ('dr.conf', 'Confirmed draw'), ('dr.rege', 'Regenerated draw'), ('dr.rele', 'Released draw'), ('dr.unre', 'Unreleased draw'), ('dr.unre', 'Saved divisions'), ('mo.edit', 'Added/edited motion'), ('mo.rele', 'Released motions'), ('mo.unre', 'Unreleased motions'), ('db.im.edit', 'Edited debate importance'), ('br.aj.set', 'Changed adjudicator breaking status'), ('br.el.edit', 'Edited break eligibility'), ('br.gene', 'Generated the teams break for all categories'), ('br.upda', 'Updated the teams break for all categories'), ('br.upd1', 'Updated the teams break'), ('br.rm.edit', 'Edited breaking team remarks'), ('rd.st.set', 'Set start time'), ('av.tm.save', 'Edited teams availability'), ('av.aj.save', 'Edited adjudicators availability'), ('av.ve.save', 'Edited venue availability'), ('op.edit', 'Edited tournament options')], max_length=10), + ), + ] diff --git a/tabbycat/actionlog/migrations/0011_auto_20160809_1054.py b/tabbycat/actionlog/migrations/0011_auto_20160809_1054.py new file mode 100644 index 00000000000..2336d7bcf15 --- /dev/null +++ b/tabbycat/actionlog/migrations/0011_auto_20160809_1054.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-09 10:54 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('actionlog', '0010_auto_20160708_1054'), + ] + + operations = [ + migrations.AlterField( + model_name='actionlogentry', + name='type', + field=models.CharField(choices=[('ba.disc', 'Discarded ballot set'), ('ba.ckin', 'Checked in ballot set'), ('ba.crea', 'Created ballot set'), ('ba.edit', 'Edited ballot set'), ('ba.conf', 'Confirmed ballot set'), ('ba.subm', 'Submitted ballot set from the public form'), ('fb.subm', 'Submitted feedback from the public form'), ('fb.save', 'Saved feedback'), ('ts.edit', 'Edited adjudicator test score'), ('aj.note', 'Set adjudicator note'), ('aa.save', 'Saved adjudicator allocation'), ('aa.auto', 'Auto-allocated adjudicators'), ('ve.save', 'Saved venues'), ('ve.auto', 'Auto-allocated venues'), ('dr.crea', 'Created draw'), ('dr.conf', 'Confirmed draw'), ('dr.rege', 'Regenerated draw'), ('dr.rele', 'Released draw'), ('dr.unre', 'Unreleased draw'), ('dr.unre', 'Saved divisions'), ('mo.edit', 'Added/edited motion'), ('mo.rele', 'Released motions'), ('mo.unre', 'Unreleased motions'), ('db.im.edit', 'Edited debate importance'), ('br.aj.set', 'Changed adjudicator breaking status'), ('br.el.edit', 'Edited break eligibility'), ('br.gene', 'Generated the team break for all categories'), ('br.upda', 'Edited breaking team remarks and updated all team breaks'), ('br.upd1', 'Edited breaking team remarks and updated this team break'), ('br.rm.edit', 'Edited breaking team remarks'), ('rd.st.set', 'Set start time'), ('av.tm.save', 'Edited teams availability'), ('av.aj.save', 'Edited adjudicators availability'), ('av.ve.save', 'Edited venue availability'), ('op.edit', 'Edited tournament options')], max_length=10), + ), + ] diff --git a/actionlog/migrations/__init__.py b/tabbycat/actionlog/migrations/__init__.py similarity index 100% rename from actionlog/migrations/__init__.py rename to tabbycat/actionlog/migrations/__init__.py diff --git a/actionlog/mixins.py b/tabbycat/actionlog/mixins.py similarity index 84% rename from actionlog/mixins.py rename to tabbycat/actionlog/mixins.py index fbb209557c3..e06320cf5a2 100644 --- a/actionlog/mixins.py +++ b/tabbycat/actionlog/mixins.py @@ -1,9 +1,12 @@ from django.contrib.auth import get_user_model -from .models import ActionLogEntry + from utils.misc import get_ip_address +from .models import ActionLogEntry + User = get_user_model() + class LogActionMixin: """Mixin for views that log an action in the action log when a form is successfully submitted. @@ -44,16 +47,20 @@ def get_action_log_fields(self, **kwargs): """ if hasattr(self, 'get_tournament'): kwargs.setdefault('tournament', self.get_tournament()) - if hasattr(self, 'get_round'): + required_fields = ActionLogEntry.REQUIRED_FIELDS_BY_ACTION_TYPE[self.get_action_log_type()] + if hasattr(self, 'get_round') and 'round' in required_fields: kwargs.setdefault('round', self.get_round()) if hasattr(self.request, 'user') and isinstance(self.request.user, User): kwargs.setdefault('user', self.request.user) return kwargs - def log_action(self): + def log_action(self, **kwargs): ip_address = get_ip_address(self.request) + action_log_fields = self.get_action_log_fields() + action_log_fields.update(kwargs) ActionLogEntry.objects.log(type=self.get_action_log_type(), - ip_address=ip_address, **self.get_action_log_fields()) + ip_address=ip_address, + **action_log_fields) def form_valid(self, form): self.log_action() diff --git a/actionlog/models.py b/tabbycat/actionlog/models.py similarity index 91% rename from actionlog/models.py rename to tabbycat/actionlog/models.py index 79b825589ab..44fbdf5ca84 100644 --- a/actionlog/models.py +++ b/tabbycat/actionlog/models.py @@ -28,6 +28,7 @@ class ActionLogEntry(models.Model): ACTION_TYPE_DRAW_CONFIRM = 'dr.conf' ACTION_TYPE_DRAW_REGENERATE = 'dr.rege' ACTION_TYPE_ADJUDICATORS_SAVE = 'aa.save' + ACTION_TYPE_ADJUDICATORS_AUTO = 'aa.auto' ACTION_TYPE_VENUES_SAVE = 've.save' ACTION_TYPE_VENUES_AUTOALLOCATE = 've.auto' ACTION_TYPE_DRAW_RELEASE = 'dr.rele' @@ -52,15 +53,16 @@ class ActionLogEntry(models.Model): ACTION_TYPE_CHOICES = ( (ACTION_TYPE_BALLOT_DISCARD , 'Discarded ballot set'), (ACTION_TYPE_BALLOT_CHECKIN , 'Checked in ballot set'), - (ACTION_TYPE_BALLOT_CREATE , 'Created ballot set'), # For tab assistants , not debaters + (ACTION_TYPE_BALLOT_CREATE , 'Created ballot set'), # For tab assistants , not debaters (ACTION_TYPE_BALLOT_EDIT , 'Edited ballot set'), (ACTION_TYPE_BALLOT_CONFIRM , 'Confirmed ballot set'), - (ACTION_TYPE_BALLOT_SUBMIT , 'Submitted ballot set from the public form'), # For debaters , not tab assistants - (ACTION_TYPE_FEEDBACK_SUBMIT , 'Submitted feedback from the public form'), # For debaters , not tab assistants - (ACTION_TYPE_FEEDBACK_SAVE , 'Saved feedback'), # For tab assistants , not debaters + (ACTION_TYPE_BALLOT_SUBMIT , 'Submitted ballot set from the public form'), # For debaters , not tab assistants + (ACTION_TYPE_FEEDBACK_SUBMIT , 'Submitted feedback from the public form'), # For debaters , not tab assistants + (ACTION_TYPE_FEEDBACK_SAVE , 'Saved feedback'), # For tab assistants , not debaters (ACTION_TYPE_TEST_SCORE_EDIT , 'Edited adjudicator test score'), (ACTION_TYPE_ADJUDICATOR_NOTE_SET , 'Set adjudicator note'), (ACTION_TYPE_ADJUDICATORS_SAVE , 'Saved adjudicator allocation'), + (ACTION_TYPE_ADJUDICATORS_AUTO , 'Auto-allocated adjudicators'), (ACTION_TYPE_VENUES_SAVE , 'Saved venues'), (ACTION_TYPE_VENUES_AUTOALLOCATE , 'Auto-allocated venues'), (ACTION_TYPE_DRAW_CREATE , 'Created draw'), @@ -75,9 +77,9 @@ class ActionLogEntry(models.Model): (ACTION_TYPE_DEBATE_IMPORTANCE_EDIT , 'Edited debate importance'), (ACTION_TYPE_ADJUDICATOR_BREAK_SET , 'Changed adjudicator breaking status'), (ACTION_TYPE_BREAK_ELIGIBILITY_EDIT , 'Edited break eligibility'), - (ACTION_TYPE_BREAK_GENERATE_ALL , 'Generated the teams break for all categories'), - (ACTION_TYPE_BREAK_UPDATE_ALL , 'Updated the teams break for all categories'), - (ACTION_TYPE_BREAK_UPDATE_ONE , 'Updated the teams break'), + (ACTION_TYPE_BREAK_GENERATE_ALL , 'Generated the team break for all categories'), + (ACTION_TYPE_BREAK_UPDATE_ALL , 'Edited breaking team remarks and updated all team breaks'), + (ACTION_TYPE_BREAK_UPDATE_ONE , 'Edited breaking team remarks and updated this team break'), (ACTION_TYPE_BREAK_EDIT_REMARKS , 'Edited breaking team remarks'), (ACTION_TYPE_ROUND_START_TIME_SET , 'Set start time'), (ACTION_TYPE_AVAIL_TEAMS_SAVE , 'Edited teams availability'), @@ -98,6 +100,7 @@ class ActionLogEntry(models.Model): ACTION_TYPE_TEST_SCORE_EDIT : ('adjudicator_test_score_history', ), ACTION_TYPE_ADJUDICATOR_NOTE_SET : ('adjudicator', ), ACTION_TYPE_ADJUDICATORS_SAVE : ('round', ), + ACTION_TYPE_ADJUDICATORS_AUTO : ('round', ), ACTION_TYPE_VENUES_SAVE : ('round', ), ACTION_TYPE_VENUES_AUTOALLOCATE : ('round', ), ACTION_TYPE_DRAW_CREATE : ('round', ), @@ -109,9 +112,9 @@ class ActionLogEntry(models.Model): ACTION_TYPE_ADJUDICATOR_BREAK_SET : ('adjudicator', ), ACTION_TYPE_BREAK_ELIGIBILITY_EDIT : (), ACTION_TYPE_BREAK_GENERATE_ALL : (), - ACTION_TYPE_BREAK_UPDATE_ALL : (), + ACTION_TYPE_BREAK_UPDATE_ALL : ('break_category', ), ACTION_TYPE_BREAK_UPDATE_ONE : ('break_category', ), - ACTION_TYPE_BREAK_EDIT_REMARKS : (), + ACTION_TYPE_BREAK_EDIT_REMARKS : ('break_category', ), ACTION_TYPE_ROUND_START_TIME_SET : ('round', ), ACTION_TYPE_MOTION_EDIT : ('motion', ), ACTION_TYPE_MOTIONS_RELEASE : ('round', ), @@ -136,9 +139,9 @@ class ActionLogEntry(models.Model): adjudicator = models.ForeignKey('participants.Adjudicator', blank=True, null=True) ballot_submission = models.ForeignKey('results.BallotSubmission', blank=True, null=True) adjudicator_test_score_history = models.ForeignKey('adjfeedback.AdjudicatorTestScoreHistory', - blank=True, null=True) + blank=True, null=True) adjudicator_feedback = models.ForeignKey('adjfeedback.AdjudicatorFeedback', - blank=True, null=True) + blank=True, null=True) round = models.ForeignKey('tournaments.Round', blank=True, null=True) motion = models.ForeignKey('motions.Motion', blank=True, null=True) break_category = models.ForeignKey('breakqual.BreakCategory', blank=True, null=True) diff --git a/tabbycat/actionlog/urls.py b/tabbycat/actionlog/urls.py new file mode 100644 index 00000000000..759470a3944 --- /dev/null +++ b/tabbycat/actionlog/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^latest_actions/$', + views.GetLatestActions.as_view(), + name='latest_actions'), +] diff --git a/tabbycat/actionlog/views.py b/tabbycat/actionlog/views.py new file mode 100644 index 00000000000..a4215697934 --- /dev/null +++ b/tabbycat/actionlog/views.py @@ -0,0 +1,24 @@ +from django.template import Context, Template + +from utils.mixins import JsonDataResponseView, LoginRequiredMixin, TournamentMixin + +from .models import ActionLogEntry + + +class GetLatestActions(JsonDataResponseView, LoginRequiredMixin, TournamentMixin): + + def get_data(self): + t = self.get_tournament() + action_objects = [] + actions = ActionLogEntry.objects.filter(tournament=t).order_by( + '-timestamp')[:15].select_related('user', 'debate', 'ballot_submission') + + timestamp_template = Template("{% load humanize %}{{ t|naturaltime }}") + for a in actions: + action_objects.append({ + 'user': a.user.username if a.user else a.ip_address or "anonymous", + 'type': a.get_type_display(), + 'param': a.get_parameters_display(), + 'timestamp': timestamp_template.render(Context({'t': a.timestamp})), + }) + return action_objects diff --git a/adjallocation/__init__.py b/tabbycat/adjallocation/__init__.py similarity index 100% rename from adjallocation/__init__.py rename to tabbycat/adjallocation/__init__.py diff --git a/tabbycat/adjallocation/admin.py b/tabbycat/adjallocation/admin.py new file mode 100644 index 00000000000..0ce1ebbe677 --- /dev/null +++ b/tabbycat/adjallocation/admin.py @@ -0,0 +1,52 @@ +from django.contrib import admin + +from .models import AdjudicatorAdjudicatorConflict, AdjudicatorConflict +from .models import AdjudicatorInstitutionConflict +from .models import DebateAdjudicator + + +# ============================================================================== +# Debate Adjudicators +# ============================================================================== + +class DebateAdjudicatorAdmin(admin.ModelAdmin): + list_display = ('debate', 'adjudicator', 'type') + search_fields = ('adjudicator__name', 'type') + raw_id_fields = ('debate',) + +admin.site.register(DebateAdjudicator, DebateAdjudicatorAdmin) + + +# ============================================================================== +# Adjudicator Team Conflicts +# ============================================================================== + +class AdjudicatorConflictAdmin(admin.ModelAdmin): + list_display = ('adjudicator', 'team') + search_fields = ('adjudicator__name', 'team__short_name', 'team__long_name') + +admin.site.register(AdjudicatorConflict, AdjudicatorConflictAdmin) + + +# ============================================================================== +# Adjudicator Adjudicator Conflicts +# ============================================================================== + +class AdjudicatorAdjudicatorConflictAdmin(admin.ModelAdmin): + list_display = ('adjudicator', 'conflict_adjudicator') + search_fields = ('adjudicator__name', 'conflict_adjudicator__name') + +admin.site.register(AdjudicatorAdjudicatorConflict, + AdjudicatorAdjudicatorConflictAdmin) + + +# ============================================================================== +# AdjudicatorConflict +# ============================================================================== + +class AdjudicatorInstitutionConflictAdmin(admin.ModelAdmin): + list_display = ('adjudicator', 'institution') + search_fields = ('adjudicator__name', 'institution__name') + +admin.site.register(AdjudicatorInstitutionConflict, + AdjudicatorInstitutionConflictAdmin) diff --git a/tabbycat/adjallocation/allocation.py b/tabbycat/adjallocation/allocation.py new file mode 100644 index 00000000000..d9aec6c673c --- /dev/null +++ b/tabbycat/adjallocation/allocation.py @@ -0,0 +1,211 @@ +import logging +from warnings import warn + +from .models import DebateAdjudicator + +logger = logging.getLogger(__name__) + + +class AdjudicatorAllocation: + """Class for handling the adjudicators on a panel.""" + + POSITION_CHAIR = 'c' + POSITION_ONLY = 'o' + POSITION_PANELLIST = 'p' + POSITION_TRAINEE = 't' + + def __init__(self, debate, chair=None, panellists=None, trainees=None, from_db=False): + self.debate = debate + + if from_db: + if chair or panellists or trainees: + warn("The chair, panellists and trainees arguments are ignored when from_db is used.") + self.chair = None + self.panellists = [] + self.trainees = [] + + debateadjs = self.debate.debateadjudicator_set.all() + + # The purpose of the line below is to avoid redundant database hits. + # It uses an internal (undocumented) flag of Django's QuerySet model + # to detect if there's already a prefetch on it, and avoids causing + # a clone of the query set (prefetch_related makes a clone), so that + # it will use the adjudicators that are already prefetched. An + # important assumption there is that if there's already a prefetch + # on this debateadjudicator_set, we assume it includes + # 'adjudicator'. If there isn't a prefetch done, we add a prefetch + # here to avoid duplicate adjudicator SQLqueries. + if not debateadjs._prefetch_done: + debateadjs = debateadjs.prefetch_related('adjudicator') + + for a in debateadjs: + if a.type == DebateAdjudicator.TYPE_CHAIR: + self.chair = a.adjudicator + elif a.type == DebateAdjudicator.TYPE_PANEL: + self.panellists.append(a.adjudicator) + elif a.type == DebateAdjudicator.TYPE_TRAINEE: + self.trainees.append(a.adjudicator) + + else: + self.chair = chair + self.panellists = panellists or [] + self.trainees = trainees or [] + + def __len__(self): + return (0 if self.chair is None else 1) + len(self.panellists) + len(self.trainees) + + def __str__(self): + items = [str(getattr(x, "name", x)) for x in self.all()] + return ", ".join(items) + + def __repr__(self): + result = " 0 + + @property + def valid(self): + return self.has_chair and len(self.panellists) % 2 == 0 + + @property + def num_voting(self): + return (0 if self.chair is None else 1) + len(self.panellists) + + def get_position(self, adj): + """Returns an AdjudicatorAllocation.POSITION_* constant corresponding + to the given adjudicator. Returns None if the adjudicator is not on + this panel.""" + if adj == self.chair: + if self.is_panel: + return self.POSITION_CHAIR + else: + return self.POSITION_ONLY + elif adj in self.panellists: + return self.POSITION_PANELLIST + elif adj in self.trainees: + return self.POSITION_TRAINEE + else: + return None + + # ========================================================================== + # Iterators + # ========================================================================== + + def voting(self): + """Iterates through voting members of the panel.""" + if self.chair is not None: + yield self.chair + for a in self.panellists: + yield a + + def all(self): + """Iterates through all members of the panel.""" + for a in self.voting(): + yield a + for a in self.trainees: + yield a + + def voting_with_positions(self): + """Like with_positions(), but only iterates through voting members of + the panel.""" + if self.chair is not None: + yield self.chair, self.POSITION_CHAIR if self.is_panel else self.POSITION_ONLY + for a in self.panellists: + yield a, self.POSITION_PANELLIST + + def with_positions(self): + """Iterates through 2-tuples `(adj, type)`, where `type` is one of the + `AdjudicatorAllocation.POSITION_*` constants (`CHAIR`, `ONLY`, + `PANELLIST` or `TRAINEE`). + + Note that the `AdjudicatorAllocation.POSITION_*` constants are not + necessarily the same as the `DebateAdjudicator.TYPE_*` constants.""" + for a, p in self.voting_with_positions(): + yield a, p + for a in self.trainees: + yield a, self.POSITION_TRAINEE + + def with_debateadj_types(self): + if self.chair is not None: + yield self.chair, DebateAdjudicator.TYPE_CHAIR + for a in self.panellists: + yield a, DebateAdjudicator.TYPE_PANEL + for a in self.trainees: + yield a, DebateAdjudicator.TYPE_TRAINEE + + # ========================================================================== + # Database operations + # ========================================================================== + + def delete(self): + """Delete existing, current allocation""" + self.debate.debateadjudicator_set.all().delete() + self.chair = None + self.panellists = [] + self.trainees = [] + + def save(self): + self.debate.debateadjudicator_set.exclude(adjudicator__in=self.all()).delete() + for adj, t in self.with_debateadj_types(): + if not adj: + continue + _, created = DebateAdjudicator.objects.update_or_create(debate=self.debate, adjudicator=adj, + defaults={'type': t}) + logger.info("updating: %s, %s, %s, created = %s" % (self.debate, adj, t, created)) + + # ========================================================================== + # Deprecated + # ========================================================================== + + @property + def list(self): + warn("AdjudicatorAllocation.list is deprecated, use AdjudicatorAllocation.voting() instead", stacklevel=2) + a = [self.chair] + a.extend(self.panellists) + return a + + def __iter__(self): + warn("AdjudicatorAllocation.__iter__() is deprecated, use .with_positions() or .with_debateadj_types() instead", stacklevel=2) + if self.chair is not None: + yield DebateAdjudicator.TYPE_CHAIR, self.chair + for a in self.panellists: + yield DebateAdjudicator.TYPE_PANEL, a + for a in self.trainees: + yield DebateAdjudicator.TYPE_TRAINEE, a + + @property + def panel(self): + warn("AdjudicatorAllocation.panel is deprecated, use AdjudicatorAllocation.panellists instead", stacklevel=2) + return self.panellists diff --git a/adjallocation/allocator.py b/tabbycat/adjallocation/allocator.py similarity index 100% rename from adjallocation/allocator.py rename to tabbycat/adjallocation/allocator.py diff --git a/adjallocation/anneal.py b/tabbycat/adjallocation/anneal.py similarity index 95% rename from adjallocation/anneal.py rename to tabbycat/adjallocation/anneal.py index 6889df634a4..7119a190084 100644 --- a/adjallocation/anneal.py +++ b/tabbycat/adjallocation/anneal.py @@ -1,7 +1,9 @@ +import math +import random + from .allocator import Allocator from .stab import StabAllocator -import random -import math + class SAAllocator(Allocator): SCORE_ADJ_TEAM_CONFLICT = 10000 @@ -12,7 +14,7 @@ class SAAllocator(Allocator): MAX_TRIES = 3 def allocate(self, initial=None): - from .models import AdjudicatorAllocation + from .allocation import AdjudicatorAllocation if initial is None: initial = StabAllocator(self.debates, self.adjudicators).allocate() @@ -39,8 +41,8 @@ def allocate(self, initial=None): self.anneal(800, 1, 1e4, self.state) - #i = 0 - #while self.best_energy > 0 and i < self.MAX_TRIES: + # i = 0 + # while self.best_energy > 0 and i < self.MAX_TRIES: # self.anneal(100, 1, 1e3, self.best_state) # i += 1 @@ -72,7 +74,7 @@ def anneal(self, steps, min_temp, max_temp, state): for i in range(steps): - temp = max_temp * math.exp( tf * i/steps ) + temp = max_temp * math.exp(tf * i/steps) diff, swap = self.candidate_swap() if diff < 0 or math.exp(-diff / temp) > random.random(): @@ -85,7 +87,8 @@ def anneal(self, steps, min_temp, max_temp, state): if self.energy < self.best_energy: self.save_best() - if self.energy == 0: break + if self.energy == 0: + break print("accepts", accepts, "improves", improves) print("end energy", self.best_energy) @@ -95,7 +98,6 @@ def anneal(self, steps, min_temp, max_temp, state): def calc_energy(self, state): return sum(self.score(debate, panel) for debate, panel in list(state.items())) - def candidate_swap(self): meth = random.choice((self.panel_swap, self.member_swap)) return meth() @@ -151,7 +153,6 @@ def apply_swap(self, swap): for debate, panel in swap: self.state[debate] = panel - def score(self, debate, panel): score = sum(getattr(self, f)(debate, panel) for f in dir(self) if f.startswith('score_')) return score @@ -174,7 +175,6 @@ def score_adj_team_history(self, debate, panel): return score - def score_adj_adj_history(self, debate, panel): score = 0 @@ -184,13 +184,13 @@ def score_adj_adj_history(self, debate, panel): return score - def score_target_panel_strength(self, debate, panel): avg = sum(p.score for p in panel) / len(panel) diff = abs(debate.target_panel - avg) return self.SCORE_TARGET_PANEL * diff * debate.target_panel * avg + def test(): from tournaments.models import Round from adjallocation.stab import StabAllocator @@ -202,7 +202,7 @@ def test(): initial = StabAllocator(debates, adjs).allocate() sa = SAAllocator(debates, adjs).allocate(initial) + print(sa) if __name__ == '__main__': test() - diff --git a/adjallocation/apps.py b/tabbycat/adjallocation/apps.py similarity index 68% rename from adjallocation/apps.py rename to tabbycat/adjallocation/apps.py index df250337fdc..9494d7830e6 100644 --- a/adjallocation/apps.py +++ b/tabbycat/adjallocation/apps.py @@ -1,5 +1,6 @@ from django.apps import AppConfig + class AdjAllocationConfig(AppConfig): name = 'adjallocation' - verbose_name = "Adjudicator Allocation" \ No newline at end of file + verbose_name = "Adjudicator Allocation" diff --git a/adjallocation/dumb.py b/tabbycat/adjallocation/dumb.py similarity index 89% rename from adjallocation/dumb.py rename to tabbycat/adjallocation/dumb.py index 6d8dd56806d..5379f9806eb 100644 --- a/adjallocation/dumb.py +++ b/tabbycat/adjallocation/dumb.py @@ -1,8 +1,9 @@ from .allocator import Allocator + class DumbAllocator(Allocator): def allocate(self): - from adjallocation.models import AdjudicatorAllocation + from adjallocation.allocation import AdjudicatorAllocation debates = self.debates adjs = self.adjudicators diff --git a/adjallocation/hungarian.py b/tabbycat/adjallocation/hungarian.py similarity index 82% rename from adjallocation/hungarian.py rename to tabbycat/adjallocation/hungarian.py index 6e670f95ce5..b04c2fb8b31 100644 --- a/adjallocation/hungarian.py +++ b/tabbycat/adjallocation/hungarian.py @@ -1,23 +1,27 @@ -from .allocator import Allocator -from .stab import StabAllocator -from .munkres import Munkres +import logging from math import exp from random import shuffle -import logging + +from .allocator import Allocator +from .munkres import Munkres + logger = logging.getLogger(__name__) + class HungarianAllocator(Allocator): MAX_SCORE = 5.0 - MIN_SCORE = 1.5 + MIN_SCORE = 0.0 + MIN_VOTING_SCORE = 1.5 DEFAULT_IMPORTANCE = 2 def __init__(self, *args, **kwargs): super(HungarianAllocator, self).__init__(*args, **kwargs) t = self.debates[0].round.tournament + self.MIN_SCORE = t.pref('adj_min_score') self.MAX_SCORE = t.pref('adj_max_score') - self.MIN_SCORE = t.pref('adj_min_voting_score') + self.MIN_VOTING_SCORE = t.pref('adj_min_voting_score') self.CONFLICT_PENALTY = t.pref('adj_conflict_penalty') self.HISTORY_PENALTY = t.pref('adj_history_penalty') @@ -29,13 +33,25 @@ def __init__(self, *args, **kwargs): def calc_cost(self, debate, adj, adjustment=0): cost = 0 + # Normalise importances back to the 0-5 range expected + normalised_importance = debate.importance + 2 + # Similarly normalise adj scores to the 0-5 range expected + adj_score_range = self.MAX_SCORE - self.MIN_SCORE + adj_score_scale = adj_score_range / 5 + normalised_adj_score = adj.score / adj_score_scale + + if normalised_adj_score > 5.0: + logger.warning("%s's score is larger than the range" % adj.name) + elif normalised_adj_score < 0.0: + logger.warning("%s's score is smaller than the range" % adj.name) + cost += self.CONFLICT_PENALTY * adj.conflict_with(debate.aff_team) cost += self.CONFLICT_PENALTY * adj.conflict_with(debate.neg_team) cost += self.HISTORY_PENALTY * adj.seen_team(debate.aff_team, debate.round) cost += self.HISTORY_PENALTY * adj.seen_team(debate.neg_team, debate.round) - impt = (debate.importance or self.DEFAULT_IMPORTANCE) + adjustment - diff = 5+ impt - adj.score + impt = (normalised_importance or self.DEFAULT_IMPORTANCE) + adjustment + diff = 5 + impt - adj.score if diff > 0.25: cost += 100000 * exp(diff - 0.25) @@ -44,15 +60,15 @@ def calc_cost(self, debate, adj, adjustment=0): return cost def allocate(self): - from adjallocation.models import AdjudicatorAllocation + from adjallocation.allocation import AdjudicatorAllocation - # remove trainees - self.adjudicators = [a for a in self.adjudicators if a.score >= self.MIN_SCORE] + # Remove trainees + self.adjudicators = [a for a in self.adjudicators if a.score >= self.MIN_VOTING_SCORE] logger.info("Have %s non-trainee adjudidcators", len(self.adjudicators)) - # sort adjudicators and debates in descending score/importance + # Sort adjudicators and debates in descending score/importance self.adjudicators_sorted = list(self.adjudicators) - shuffle(self.adjudicators_sorted) # randomize equally-ranked judges + shuffle(self.adjudicators_sorted) # Randomize equally-ranked judges self.adjudicators_sorted.sort(key=lambda a: a.score, reverse=True) self.debates_sorted = list(self.debates) self.debates_sorted.sort(key=lambda a: a.importance, reverse=True) @@ -136,7 +152,7 @@ def allocate(self): # for the top half of these debates, the final panellist # can be of lower quality than the other 2 - if i < npan/2 and j==2: + if i < npan/2 and j == 2: adjustment = -1.0 else: adjustment = 0 @@ -167,14 +183,15 @@ def allocate(self): a = AdjudicatorAllocation(d) p[i].sort(key=lambda a: a.score, reverse=True) a.chair = p[i].pop(0) - a.panel = p[i] + a.panellists = p[i] alloc.append(a) for a in alloc[len(chairs):]: - logger.info("%s %s %s", a.debate, a.chair, a.panel) + logger.info("%s %s %s", a.debate, a.chair, a.panellists) return alloc + def test(): from tournaments.models import Round r = Round.objects.get(pk=4) diff --git a/adjallocation/migrations/0001_initial.py b/tabbycat/adjallocation/migrations/0001_initial.py similarity index 100% rename from adjallocation/migrations/0001_initial.py rename to tabbycat/adjallocation/migrations/0001_initial.py diff --git a/adjallocation/migrations/0002_auto_20160103_1927.py b/tabbycat/adjallocation/migrations/0002_auto_20160103_1927.py similarity index 100% rename from adjallocation/migrations/0002_auto_20160103_1927.py rename to tabbycat/adjallocation/migrations/0002_auto_20160103_1927.py diff --git a/adjallocation/migrations/0003_auto_20160109_1834.py b/tabbycat/adjallocation/migrations/0003_auto_20160109_1834.py similarity index 100% rename from adjallocation/migrations/0003_auto_20160109_1834.py rename to tabbycat/adjallocation/migrations/0003_auto_20160109_1834.py diff --git a/adjallocation/migrations/0004_debateadjudicator_timing_confirmed.py b/tabbycat/adjallocation/migrations/0004_debateadjudicator_timing_confirmed.py similarity index 100% rename from adjallocation/migrations/0004_debateadjudicator_timing_confirmed.py rename to tabbycat/adjallocation/migrations/0004_debateadjudicator_timing_confirmed.py diff --git a/adjallocation/migrations/0005_auto_20160209_1941.py b/tabbycat/adjallocation/migrations/0005_auto_20160209_1941.py similarity index 100% rename from adjallocation/migrations/0005_auto_20160209_1941.py rename to tabbycat/adjallocation/migrations/0005_auto_20160209_1941.py diff --git a/adjallocation/migrations/0006_auto_20160228_1838.py b/tabbycat/adjallocation/migrations/0006_auto_20160228_1838.py similarity index 100% rename from adjallocation/migrations/0006_auto_20160228_1838.py rename to tabbycat/adjallocation/migrations/0006_auto_20160228_1838.py diff --git a/adjallocation/migrations/0007_auto_20160521_1747.py b/tabbycat/adjallocation/migrations/0007_auto_20160521_1747.py similarity index 100% rename from adjallocation/migrations/0007_auto_20160521_1747.py rename to tabbycat/adjallocation/migrations/0007_auto_20160521_1747.py diff --git a/adjallocation/migrations/__init__.py b/tabbycat/adjallocation/migrations/__init__.py similarity index 100% rename from adjallocation/migrations/__init__.py rename to tabbycat/adjallocation/migrations/__init__.py diff --git a/tabbycat/adjallocation/models.py b/tabbycat/adjallocation/models.py new file mode 100644 index 00000000000..40aa1aecd8b --- /dev/null +++ b/tabbycat/adjallocation/models.py @@ -0,0 +1,57 @@ +from django.db import models + + +class DebateAdjudicatorManager(models.Manager): + use_for_related_fields = True + + def get_queryset(self): + return super().get_queryset().select_related('debate') + + +class DebateAdjudicator(models.Model): + TYPE_CHAIR = 'C' + TYPE_PANEL = 'P' + TYPE_TRAINEE = 'T' + + TYPE_CHOICES = ( + (TYPE_CHAIR, 'chair'), + (TYPE_PANEL, 'panellist'), + (TYPE_TRAINEE, 'trainee'), + ) + + objects = DebateAdjudicatorManager() + + debate = models.ForeignKey('draw.Debate') + adjudicator = models.ForeignKey('participants.Adjudicator') + type = models.CharField(max_length=2, choices=TYPE_CHOICES) + timing_confirmed = models.NullBooleanField(verbose_name="Available? ") + + def __str__(self): + return '{} in {} ({})'.format(self.adjudicator, self.debate, self.get_type_display()) + + class Meta: + unique_together = ('debate', 'adjudicator') + + +class AdjudicatorConflict(models.Model): + adjudicator = models.ForeignKey('participants.Adjudicator') + team = models.ForeignKey('participants.Team') + + class Meta: + verbose_name = "adjudicator-team conflict" + + +class AdjudicatorAdjudicatorConflict(models.Model): + adjudicator = models.ForeignKey('participants.Adjudicator', related_name="source_adjudicator") + conflict_adjudicator = models.ForeignKey('participants.Adjudicator', related_name="target_adjudicator", verbose_name="Adjudicator") + + class Meta: + verbose_name = "adjudicator-adjudicator conflict" + + +class AdjudicatorInstitutionConflict(models.Model): + adjudicator = models.ForeignKey('participants.Adjudicator') + institution = models.ForeignKey('participants.Institution') + + class Meta: + verbose_name = "adjudicator-institution conflict" diff --git a/adjallocation/munkres.py b/tabbycat/adjallocation/munkres.py similarity index 95% rename from adjallocation/munkres.py rename to tabbycat/adjallocation/munkres.py index 5a9292d573a..b142931635b 100644 --- a/adjallocation/munkres.py +++ b/tabbycat/adjallocation/munkres.py @@ -1,8 +1,3 @@ -#!/usr/bin/env python -# -*- coding: iso-8859-1 -*- - -# Documentation is intended to be processed by Epydoc. - """ Introduction ============ @@ -201,7 +196,7 @@ def permute(a, results): So, the above profit-calculation program can be recast as:: - from munkres import Munkres, print_matrix, make_cost_matrix + Munkres, print_matrix, make_cost_matrix matrix = [[5, 9, 1], [10, 3, 2], @@ -277,7 +272,8 @@ def permute(a, results): # Imports # --------------------------------------------------------------------------- -import sys +import sys # noqa +import copy # noqa # --------------------------------------------------------------------------- # Exports @@ -300,6 +296,7 @@ def permute(a, results): # Classes # --------------------------------------------------------------------------- + class Munkres: """ Calculate the Munkres solution to the classical assignment problem. @@ -399,12 +396,14 @@ def compute(self, cost_matrix): done = False step = 1 - steps = { 1 : self.__step1, - 2 : self.__step2, - 3 : self.__step3, - 4 : self.__step4, - 5 : self.__step5, - 6 : self.__step6 } + steps = { + 1: self.__step1, + 2: self.__step2, + 3: self.__step3, + 4: self.__step4, + 5: self.__step5, + 6: self.__step6 + } while not done: try: @@ -438,7 +437,7 @@ def __step1(self): For each row of the matrix, find the smallest element and subtract it from every element in its row. Go to Step 2. """ - C = self.C + C = self.C # noqa n = self.n for i in range(n): minval = min(self.C[i]) @@ -483,7 +482,7 @@ def __step3(self): count += 1 if count >= n: - step = 7 # done + step = 7 # done else: step = 4 @@ -673,6 +672,7 @@ def __erase_primes(self): # Functions # --------------------------------------------------------------------------- + def make_cost_matrix(profit_matrix, inversion_function): """ Create a cost matrix from a profit matrix by calling @@ -708,6 +708,7 @@ def make_cost_matrix(profit_matrix, inversion_function): cost_matrix.append([inversion_function(value) for value in row]) return cost_matrix + def print_matrix(matrix, msg=None): """ Convenience function: Displays the contents of a matrix of integers. @@ -747,36 +748,28 @@ def print_matrix(matrix, msg=None): if __name__ == '__main__': - matrices = [ - # Square - ([[400, 150, 400], - [400, 450, 600], - [300, 225, 300]], - 850 # expected cost - ), - - # Rectangular variant - ([[400, 150, 400, 1], - [400, 450, 600, 2], - [300, 225, 300, 3]], - 452 # expected cost - ), - - # Square - ([[10, 10, 8], - [ 9, 8, 1], - [ 9, 7, 4]], - 18 - ), - - # Rectangular variant - ([[10, 10, 8, 11], - [ 9, 8, 1, 1], - [ 9, 7, 4, 10]], - 15 - ), - ] + # Square + ([[400, 150, 400], + [400, 450, 600], + [300, 225, 300]], + 850), # expected cost + # Rectangular variant + ([[400, 150, 400, 1], + [400, 450, 600, 2], + [300, 225, 300, 3]], + 452), # expected cost + # Square + ([[10, 10, 8], + [9, 8, 1], + [9, 7, 4]], + 18), + # Rectangular variant + ([[10, 10, 8, 11], + [9, 8, 1, 1], + [9, 7, 4, 10]], + 15), + ] m = Munkres() for cost_matrix, expected_total in matrices: @@ -789,4 +782,3 @@ def print_matrix(matrix, msg=None): print('(%d, %d) -> %d' % (r, c, x)) print('lowest cost=%d' % total_cost) assert expected_total == total_cost - diff --git a/adjallocation/stab.py b/tabbycat/adjallocation/stab.py similarity index 95% rename from adjallocation/stab.py rename to tabbycat/adjallocation/stab.py index e3f57e731fb..06d2efb2ec9 100644 --- a/adjallocation/stab.py +++ b/tabbycat/adjallocation/stab.py @@ -1,5 +1,6 @@ from .allocator import Allocator + class PanelMaker(object): RANK_A = 0 RANK_B = 1 @@ -56,7 +57,7 @@ def build_panels(self, panels_left): assert panels_left <= len(self.available) // 3 num_b = self._count(self.RANK_B) num_c = self._count(self.RANK_C) - num_d = self._count(self.RANK_D) + # num_d = self._count(self.RANK_D) if num_b / 2 < panels_left: self.build(self.RANK_B, self.RANK_B, self.RANK_B, num_b % 2) @@ -65,7 +66,7 @@ def build_panels(self, panels_left): self.build(self.RANK_B, self.RANK_B, self.RANK_C, num_bbc) num_c -= num_bbc else: - raise # not enough C's + raise # not enough C's else: self.build(self.RANK_B, self.RANK_B, self.RANK_B, num_b - panels_left * 2) @@ -90,7 +91,6 @@ def build_panels(self, panels_left): self.build(self.RANK_C, self.RANK_C, self.RANK_D, panels_left * 3 - num_c) - def build(self, r1, r2, r3, n): for i in range(n): self.add_panel(self.pop(r1), self.pop(r2), self.pop(r3)) @@ -108,6 +108,7 @@ def add_panel(self, *adjs): def _count(self, r): return len([(adj, rank) for adj, rank in self.available if rank == r]) + class StabAllocator(Allocator): def allocate(self, avoid_conflicts=True): p = PanelMaker() @@ -116,7 +117,7 @@ def allocate(self, avoid_conflicts=True): assert len(self.debates) <= len(panels) self.debates.sort(key=lambda d: self.get_debate_energy(d), reverse=True) - panels.sort(key=lambda p:p.get_energy(), reverse=True) + panels.sort(key=lambda p: p.get_energy(), reverse=True) self.pairings = list(zip(self.debates, panels)) @@ -127,7 +128,7 @@ def allocate(self, avoid_conflicts=True): if j is None: j = self.search_swap(i, list(range(i+1, len(panels)))) - from adjallocation.models import AdjudicatorAllocation + from adjallocation.allocation import AdjudicatorAllocation allocation = [] for debate, panel in self.pairings: @@ -141,7 +142,6 @@ def allocate(self, avoid_conflicts=True): def get_debate_energy(self, debate, bubble=False): # TODO: does TeamAtRound exist? from tournaments.models import TeamAtRound - from draw.models import DebateTeam aff_team = TeamAtRound(debate.aff_team, debate.round) neg_team = TeamAtRound(debate.neg_team, debate.round) @@ -152,7 +152,6 @@ def get_debate_energy(self, debate, bubble=False): return energy - def search_swap(self, idx, search_range): base_debate, base_panel = self.pairings[idx] @@ -188,12 +187,13 @@ def conflicts(self, debate): return True return False + def test(): - p = PanelMaker() from tournaments.models import Round - r = Round.objects.get(pk=1) + r = Round.objects.get(pk=1) a = StabAllocator(r.debates(), r.active_adjudicators.all()) + return a.allocate() if __name__ == '__main__': diff --git a/adjallocation/templates/draw_adjudicators_edit.html b/tabbycat/adjallocation/templates/draw_adjudicators_edit.html similarity index 83% rename from adjallocation/templates/draw_adjudicators_edit.html rename to tabbycat/adjallocation/templates/draw_adjudicators_edit.html index 11e74b1db30..869d3f127b8 100644 --- a/adjallocation/templates/draw_adjudicators_edit.html +++ b/tabbycat/adjallocation/templates/draw_adjudicators_edit.html @@ -5,16 +5,20 @@ {% block nav %}{% endblock %} {% block header %}{% endblock %} {% block footer %}{% endblock %} +{% block body-id %}old-edit-allocation{% endblock %} +{% block page-subnav-sections %}{% endblock page-subnav-sections %} -{% block page-subnav-sections %} -
    +{% block content %} + +
    +
    +
    Auto Allocate
    Save
    Quit
    -
    Venues @@ -32,7 +36,6 @@ Category
    -
    Key
    Seen
    @@ -43,29 +46,26 @@
    Unaccredited
    {% endif %}
    - - - -
    -{% endblock %} -{% block content %} +
    +
    +
    @@ -102,21 +102,21 @@ @@ -156,7 +156,7 @@
    - +
    @@ -199,39 +199,42 @@ - - + {% endblock content %} -{% block extra-js %} +{% block extra-css %} + + +{% endblock extra-css %} + +{% block js %} + {{ block.super }} + -{% endblock extra-js %} +{% endblock js %} diff --git a/tabbycat/adjallocation/templates/edit_adj_allocation.html b/tabbycat/adjallocation/templates/edit_adj_allocation.html new file mode 100644 index 00000000000..ae694690927 --- /dev/null +++ b/tabbycat/adjallocation/templates/edit_adj_allocation.html @@ -0,0 +1,41 @@ +{% extends "base.html" %} +{% load debate_tags %} + +{% block nav %}{% endblock %} +{% block header %}{% endblock %} +{% block subheader %}{% endblock %} +{% block footer %}{% endblock %} +{% block page-subnav-sections %}{% endblock page-subnav-sections %} + +{% block content %} + + + + +{% endblock content %} + +{% block js %} + + {{ block.super }} +{% endblock js %} diff --git a/adjallocation/urls.py b/tabbycat/adjallocation/urls.py similarity index 53% rename from adjallocation/urls.py rename to tabbycat/adjallocation/urls.py index 538e625684f..11b4f48ab59 100644 --- a/adjallocation/urls.py +++ b/tabbycat/adjallocation/urls.py @@ -1,25 +1,38 @@ from django.conf.urls import url from . import views -from participants.models import Adjudicator urlpatterns = [ - url(r'^create/$', + # Old busted + url(r'^create_old/$', views.create_adj_allocation, name='create_adj_allocation'), - url(r'^edit/$', + url(r'^edit_old/$', views.draw_adjudicators_edit, name='draw_adjudicators_edit'), - url(r'^_get/$', + url(r'^_get_old/$', views.draw_adjudicators_get, name='draw_adjudicators_get'), - url(r'^save/$', - views.SaveAdjudicatorsView.as_view(), - name='save_adjudicators'), url(r'^_update_importance/$', views.update_debate_importance, name='update_debate_importance'), - url(r'^conflicts/$', + url(r'^conflicts_old/$', views.adj_conflicts, name='adj_conflicts'), + url(r'^save/$', + views.SaveAdjudicatorsView.as_view(), + name='save_adjudicators'), + # New Hotness + url(r'^edit/$', + views.EditAdjudicatorAllocationView.as_view(), + name='edit_adj_allocation'), + url(r'^create/$', + views.CreateAutoAllocation.as_view(), + name='create_auto_allocation'), + url(r'^importance/set/$', + views.SaveDebateImportance.as_view(), + name='save_debate_importance'), + url(r'^panel/set/$', + views.SaveDebatePanel.as_view(), + name='save_debate_panel'), ] diff --git a/tabbycat/adjallocation/utils.py b/tabbycat/adjallocation/utils.py new file mode 100644 index 00000000000..87b7e3e4e89 --- /dev/null +++ b/tabbycat/adjallocation/utils.py @@ -0,0 +1,376 @@ +import json +import math +from itertools import permutations + +from .models import AdjudicatorAdjudicatorConflict, AdjudicatorConflict, AdjudicatorInstitutionConflict, DebateAdjudicator + +from availability.models import ActiveAdjudicator +from breakqual.utils import calculate_live_thresholds, determine_liveness +from draw.models import DebateTeam +from participants.models import Adjudicator, Team +from participants.prefetch import populate_feedback_scores, populate_win_counts + + +def adjudicator_conflicts_display(debates): + """Returns a dict mapping elements (debates) in `debates` to a list of + strings of explaining conflicts between adjudicators and teams, and + conflicts between adjudicators and each other.""" + + adjteamconflicts = {} + for conflict in AdjudicatorConflict.objects.filter(adjudicator__debateadjudicator__debate__in=debates).distinct(): + adjteamconflicts.setdefault(conflict.adjudicator_id, []).append(conflict.team_id) + adjinstconflicts = {} + for conflict in AdjudicatorInstitutionConflict.objects.filter(adjudicator__debateadjudicator__debate__in=debates).distinct(): + adjinstconflicts.setdefault(conflict.adjudicator_id, []).append(conflict.institution_id) + adjadjconflicts = {} + for conflict in AdjudicatorAdjudicatorConflict.objects.filter(adjudicator__debateadjudicator__debate__in=debates).distinct(): + adjadjconflicts.setdefault(conflict.adjudicator_id, []).append(conflict.conflict_adjudicator_id) + + conflict_messages = {debate: [] for debate in debates} + for debate in debates: + for adjudicator in debate.adjudicators.all(): + for team in debate.teams: + if team.id in adjteamconflicts.get(adjudicator.id, []): + conflict_messages[debate].append( + "Conflict between {adj} & {team}".format( + adj=adjudicator.name, team=team.short_name) + ) + if team.institution_id in adjinstconflicts.get(adjudicator.id, []): + conflict_messages[debate].append( + "Conflict between {adj} & institution {inst} ({team})".format( + adj=adjudicator.name, team=team.short_name, inst=team.institution.code) + ) + + for adj1, adj2 in permutations(debate.adjudicators.all(), 2): + if adj2.id in adjadjconflicts.get(adj1.id, []): + conflict_messages[debate].append( + "Conflict between {adj} & {other}".format( + adj=adj1.name, other=adj2.name) + ) + + if adj2.institution_id in adjinstconflicts.get(adj1.id, []): + conflict_messages[debate].append( + "Conflict between {adj} & {inst} ({other})".format( + adj=adj1.name, other=adj2.name, inst=adj2.institution.code) + ) + + return conflict_messages + + +def percentile(n, percent, key=lambda x:x): + """ + Find the percentile of a list of values. + + @parameter N - is a list of values. Note N MUST BE already sorted. + @parameter percent - a float value from 0.0 to 1.0. + @parameter key - optional key function to compute value from each element of N. + + @return - the percentile of the values + """ + if not n: + return None + k = (len(n)-1) * percent + f = math.floor(k) + c = math.ceil(k) + if f == c: + return key(n[int(k)]) + d0 = key(n[int(f)]) * (c-k) + d1 = key(n[int(c)]) * (k-f) + return d0+d1 + + +def get_adjs(r): + + active = ActiveAdjudicator.objects.filter( + round=r).values_list( + 'adjudicator') + active = [(a[0], None) for a in active] + + allocated_adjs = DebateAdjudicator.objects.select_related( + 'debate__round', 'adjudicator').filter( + debate__round=r).values_list( + 'adjudicator', 'debate') + allocated_ids = [a[0] for a in allocated_adjs] + + # Remove active adjs that have been assigned to debates + unallocated_adjs = [a for a in active if a[0] not in allocated_ids] + all_ids = list(allocated_adjs) + list(unallocated_adjs) + + # Grab all the actual adjudicator objects + active_adjs = Adjudicator.objects.select_related( + 'institution', 'tournament', 'tournament__current_round').in_bulk( + [a[0] for a in all_ids]) + + # Build a list of adjudicator objects (after setting their debate property) + round_adjs = [] + for round_id, round_adj in zip(all_ids, list(active_adjs.values())): + round_adj.debate = round_id[1] + round_adjs.append(round_adj) + + return round_adjs + + +def populate_conflicts(adjs, teams): + # Grab all conflicts data and assign it + teamconflicts = AdjudicatorConflict.objects.filter( + adjudicator__in=adjs).values_list( + 'adjudicator', 'team') + institutionconflicts = AdjudicatorInstitutionConflict.objects.filter( + adjudicator__in=adjs).values_list( + 'adjudicator', 'institution') + adjconflicts = AdjudicatorAdjudicatorConflict.objects.filter( + adjudicator__in=adjs).values_list( + 'adjudicator', 'conflict_adjudicator') + + for a in adjs: + a.personal_teams = [c[1] for c in teamconflicts if c[0] == a.id] + a.institutional_institutions = [a.institution.id] + a.institutional_institutions.extend( + [c[1] for c in institutionconflicts if c[0] == a.id and c[1] != a.institution.id]) + + # Adj-adj conflicts should be symmetric + a.personal_adjudicators = [c[1] for c in adjconflicts if c[0] == a.id] + a.personal_adjudicators += [c[0] for c in adjconflicts if c[1] == a.id] + + for t in teams: + t.personal_adjudicators = [c[0] for c in teamconflicts if c[1] == t.id] + # For teams conflicted_institutions is a list of adjs due to the asymetric + # nature of adjs having multiple instutitonal conflicts + t.institutional_institutions = [t.institution_id] + + return adjs, teams + + +def populate_histories(adjs, teams, t, r): + + da_histories = DebateAdjudicator.objects.filter( + debate__round__tournament=t, debate__round__seq__lt=r.seq).select_related( + 'debate__round').values_list( + 'adjudicator', 'debate', 'debate__round__seq').order_by('-debate__round__seq') + dt_histories = DebateTeam.objects.filter( + debate__round__tournament=t, debate__round__seq__lt=r.seq).select_related( + 'debate__round').values_list( + 'team', 'debate', 'debate__round__seq').order_by('-debate__round__seq') + + for a in adjs: + hists = [] + # Iterate over all DebateAdjudications from this adj + for dah in [dah for dah in da_histories if dah[0] == a.id]: + # Find the relevant DebateTeams from the matching debates + hists.extend([{ + 'team': dat[0], + 'debate': dah[1], + 'ago': r.seq - dah[2], + } for dat in dt_histories if dat[1] == dah[1]]) + # From these DebateAdjudications find panellists from the same debates + hists.extend([{ + 'adjudicator': dah2[0], + 'debate': dah2[1], + 'ago': r.seq - dah2[2], + } for dah2 in da_histories if dah2[1] == dah[1] and dah2 != dah]) + a.histories = hists + + for t in teams: + hists = [] + # Iterate over the DebateTeams and match to teams + for dat in [dat for dat in dt_histories if dat[0] == t.id]: + # Once matched, find all DebateAdjudicators from that debate and + # add them as conflicts for this team + hists.extend([{ + 'adjudicator': dah[0], + 'debate': dah[1], + 'ago': r.seq - dah[2], + } for dah in da_histories if dah[1] == dat[1]]) + t.histories = hists + + return adjs, teams + + +def debates_to_json(draw, t, r): + + data = [{ + 'id': debate.id, + 'bracket': debate.bracket, + 'importance': debate.importance, + 'aff_team': debate.aff_team.id, + 'neg_team': debate.neg_team.id, + 'panel': [{ + 'id': adj.id, + 'position': position, + } for adj, position in debate.adjudicators.with_debateadj_types()], + + } for debate in draw] + return json.dumps(data) + + +def adjs_to_json(adjs, regions, t): + """Converts to a standard JSON object for Vue components to use""" + + populate_feedback_scores(adjs) + fw = t.current_round.feedback_weight + for adj in adjs: + adj.abs_score = adj.weighted_score(fw) + + absolute_scores = [adj.abs_score for adj in adjs] + absolute_scores.sort() + percentile_cutoffs = [(100 - i, percentile(absolute_scores, i/100)) for i in range(0,100,10)] + percentile_cutoffs.reverse() + + data = {} + for adj in adjs: + data[adj.id] = { + 'type': 'adjudicator', + 'id': adj.id, + 'name': adj.name, + 'gender': adj.gender, + 'gender_show': False, + 'region': [r for r in regions if r['id'] is adj.institution.region_id][0] if adj.institution.region_id is not None else '', + 'region_show': False, + 'institution': { + 'id': adj.institution.id, + 'name': adj.institution.code, + 'code' : adj.institution.code, + 'abbreviation' : adj.institution.abbreviation + }, + 'score': "%.1f" % adj.abs_score, + 'ranking': next(pc[0] for pc in percentile_cutoffs if pc[1] <= adj.abs_score), + 'histories': adj.histories, + 'conflicts': { + 'teams': adj.personal_teams, + 'institutions': adj.institutional_institutions, + 'adjudicators': adj.personal_adjudicators, + }, + 'conflicted': { + 'hover': {'personal': False, 'institutional': False, 'history': False, 'history_ago': 99}, + 'panel': {'personal': False, 'institutional': False, 'history': False, 'history_ago': 99} + } + } + + return json.dumps(data) + + +def teams_to_json(teams, regions, categories, t, r): + thresholds = {bc['id']: calculate_live_thresholds(bc, t, r) for bc in categories} + + # populate team categories + tbcs = Team.break_categories.through.objects.filter(team__in=teams) + break_category_ids_by_team = {team.id: [] for team in teams} + for tbc in tbcs: + break_category_ids_by_team[tbc.team_id].append(tbc.breakcategory_id) + + populate_win_counts(teams) + + data = {} + for team in teams: + team_categories = break_category_ids_by_team[team.id] + break_categories = [{ + 'id': bc['id'], + 'name': bc['name'], + 'seq': bc['seq'], + 'will_break': determine_liveness(thresholds[bc['id']], team.wins_count) + } for bc in categories if bc['id'] in team_categories] + + data[team.id] = { + 'type': 'team', + 'id': team.id, + 'name': team.short_name, + 'long_name': team.long_name, + 'uses_prefix': team.use_institution_prefix, + 'speakers': [{ + 'name': s.name, + 'gender': s.gender + } for s in team.speakers], + 'gender_show': False, + 'wins': team.wins_count, + 'region': [r for r in regions if r['id'] is team.institution.region_id][0] if team.institution.region_id else '', + 'region_show': False, + # TODO: Searching for break cats here incurs extra queries; should be done earlier + 'categories': break_categories, + 'category_show': False, + 'institution': { + 'id': team.institution.id, + 'name': team.institution.code, + 'code' : team.institution.code, + 'abbreviation' : team.institution.abbreviation + }, + 'histories': team.histories, + 'conflicts': { + 'teams': [], # No team-team conflicts + 'institutions': team.institutional_institutions, + 'adjudicators': team.personal_adjudicators + }, + 'conflicted': { + 'hover': {'personal': False, 'institutional': False, 'history': False, 'history_ago': 99}, + 'panel': {'personal': False, 'institutional': False, 'history': False, 'history_ago': 99} + } + } + return json.dumps(data) + +# REDUNDANT; although parts worth translating +# class AllocationTableBuilder(TabbycatTableBuilder): + +# def liveness(self, team, teams_count, prelims, current_round): +# live_info = {'text': team.wins_count, 'tooltip': ''} + +# # The actual calculation should be shifed to be a cached method on +# # the relevant break category +# # print("teams count", teams_count) +# # print("prelims", prelims) +# # print("current_round", current_round) + +# highest_liveness = 3 +# for bc in team.break_categories.all(): +# # print(bc.name, bc.break_size) +# import random +# status = random.choice([1,2,3]) +# highest_liveness = 3 +# if status is 1: +# live_info['tooltip'] += 'Definitely in for the %s break
    test' % bc.name +# if highest_liveness != 2: +# highest_liveness = 1 # Live not ins are the most important highlight +# elif status is 2: +# live_info['tooltip'] += 'Still live for the %s break
    test' % bc.name +# highest_liveness = 2 +# elif status is 3: +# live_info['tooltip'] += 'Cannot break in %s break
    test' % bc.name + +# if highest_liveness is 1: +# live_info['class'] = 'bg-success' +# elif highest_liveness is 2: +# live_info['class'] = 'bg-warning' + +# return live_info + +# def add_team_wins(self, draw, round, key): +# prelims = self.tournament.prelim_rounds(until=round).count() +# teams_count = self.tournament.team_set.count() + +# wins_head = { +# 'key': key, +# 'tooltip': "Number of wins a team is on; " +# } +# wins_data = [] +# for d in draw: +# team = d.aff_team if key is "AW" else d.neg_team +# wins_data.append(self.liveness(team, teams_count, prelims, round.seq)) + +# self.add_column(wins_head, wins_data) + +# def add_debate_importances(self, draw, round): +# importance_head = { +# 'key': 'importance', +# 'icon': 'glyphicon-fire', +# 'tooltip': "Set a debate's importance (higher receives better adjs)" +# } +# importance_data = [{ +# 'component': 'debate-importance', +# 'id': d.id, +# 'sort': d.importance, +# 'importance': d.importance, +# 'url': reverse_tournament( +# 'set_debate_importance', +# self.tournament, +# kwargs={'round_seq': round.seq}) +# } for d in draw] + +# self.add_column(importance_head, importance_data) diff --git a/adjallocation/views.py b/tabbycat/adjallocation/views.py similarity index 59% rename from adjallocation/views.py rename to tabbycat/adjallocation/views.py index 026eca083ba..267915bd904 100644 --- a/adjallocation/views.py +++ b/tabbycat/adjallocation/views.py @@ -1,21 +1,31 @@ import json import logging -from django.views.generic.base import View from django.db.utils import IntegrityError +from django.views.generic.base import TemplateView, View +from django.http import HttpResponse, HttpResponseBadRequest +from django.shortcuts import render +from actionlog.mixins import LogActionMixin from actionlog.models import ActionLogEntry +from breakqual.utils import categories_ordered from draw.models import Debate, DebateTeam from participants.models import Adjudicator, Team +from participants.utils import regions_ordered from tournaments.mixins import RoundMixin -from utils.mixins import SuperuserRequiredMixin -from utils.views import * +from utils.mixins import JsonDataResponseView, SuperuserRequiredMixin +from utils.views import admin_required, expect_post, round_view + from .allocator import allocate_adjudicators +from .allocation import AdjudicatorAllocation from .hungarian import HungarianAllocator -from .models import AdjudicatorAllocation, AdjudicatorConflict, AdjudicatorInstitutionConflict, AdjudicatorAdjudicatorConflict, DebateAdjudicator +from .models import AdjudicatorAdjudicatorConflict, AdjudicatorConflict, AdjudicatorInstitutionConflict, DebateAdjudicator +from .utils import adjs_to_json, debates_to_json, get_adjs, populate_conflicts, populate_histories, teams_to_json + logger = logging.getLogger(__name__) + @admin_required @expect_post @round_view @@ -82,58 +92,18 @@ def calculate_prior_adj_genders(team): regions = round.tournament.region_set.order_by('name') break_categories = round.tournament.breakcategory_set.order_by( 'seq').exclude(is_general=True) + # TODO: colors below are redundant colors = ["#C70062", "#00C79B", "#B1E001", "#476C5E", "#777", "#FF2983", "#6A268C", "#00C0CF", "#0051CF"] - context['regions'] = list(zip(regions, colors + ["black"] - * (len(regions) - len(colors)))) + context['regions'] = list(zip(regions, colors + ["black"] * (len(regions) - + len(colors)))) context['break_categories'] = list(zip( - break_categories, colors + ["black"] * (len(break_categories) - len(colors)))) + break_categories, colors + ["black"] * (len(break_categories) - + len(colors)))) return render(request, "draw_adjudicators_edit.html", context) -def _json_adj_allocation(debates, unused_adj): - - obj = {} - - def _adj(a): - - if a.institution.region: - region_name = "region-%s" % a.institution.region.id - else: - region_name = "" - - return { - 'id': a.id, - 'name': a.name, - 'institution': a.institution.short_code, - 'is_unaccredited': a.is_unaccredited, - 'gender': a.gender, - 'region': region_name - } - - def _debate(d): - r = {} - if d.adjudicators.chair: - r['chair'] = _adj(d.adjudicators.chair) - r['panel'] = [_adj(a) for a in d.adjudicators.panel] - r['trainees'] = [_adj(a) for a in d.adjudicators.trainees] - return r - - obj['debates'] = dict((d.id, _debate(d)) for d in debates) - obj['unused'] = [_adj(a) for a in unused_adj] - - return HttpResponse(json.dumps(obj)) - - -@admin_required -@round_view -def draw_adjudicators_get(request, round): - draw = round.get_draw() - - return _json_adj_allocation(draw, round.unused_adjudicators()) - - class SaveAdjudicatorsView(SuperuserRequiredMixin, RoundMixin, View): def post(self, request, *args, **kwargs): @@ -156,10 +126,11 @@ def _extract_id(s): adjs = [Adjudicator.objects.get(id=int(x)) for x in values] if key.startswith("chair_"): if len(adjs) > 1: - logger.warning("There was more than one chair for debate {}, only saving the first".format(allocation.debate)) + logger.warning("There was more than one chair for debate %s, only saving the first", alloc.debate) + continue alloc.chair = adjs[0] elif key.startswith("panel_"): - alloc.panel.extend(adjs) + alloc.panellists.extend(adjs) elif key.startswith("trainees_"): alloc.trainees.extend(adjs) @@ -169,18 +140,16 @@ def _extract_id(s): revised = allocations[d_id] if existing != revised: changed += 1 - logger.info("Saving adjudicators for debate {}".format(debate)) - logger.info("{} --> {}".format(existing, revised)) - existing.delete() + logger.info("Saving adjudicators for debate %s", debate) + logger.info("%s --> %s", existing, revised) try: revised.save() except IntegrityError: - return HttpResponseBadRequest("""An adjudicator - was allocated to the same debate multiple times. Please - remove them and re-save.""") + return HttpResponseBadRequest("An adjudicator was allocated to the same " + "to the same debate multiple times. Please remove them and re-save.") if not changed: - logger.warning("Didn't save any adjudicator allocations, nothing changed.") + logger.info("Didn't save any adjudicator allocations, nothing changed.") return HttpResponse("There aren't any changes to save.") ActionLogEntry.objects.log(type=ActionLogEntry.ACTION_TYPE_ADJUDICATORS_SAVE, @@ -190,6 +159,48 @@ def _extract_id(s): return HttpResponse("Saved changes for {} debates!".format(changed)) +def _json_adj_allocation(debates, unused_adj): + + obj = {} + + def _adj(a): + + if a.institution.region: + region_name = "region-%s" % a.institution.region.id + else: + region_name = "" + + return { + 'id': a.id, + 'name': a.name, + 'institution': a.institution.short_code, + 'is_unaccredited': a.is_unaccredited, + 'gender': a.gender, + 'region': region_name + } + + def _debate(d): + r = {} + if d.adjudicators.chair: + r['chair'] = _adj(d.adjudicators.chair) + r['panel'] = [_adj(a) for a in d.adjudicators.panel] + r['trainees'] = [_adj(a) for a in d.adjudicators.trainees] + return r + + obj['debates'] = dict((d.id, _debate(d)) for d in debates) + obj['unused'] = [_adj(a) for a in unused_adj] + + return HttpResponse(json.dumps(obj)) + + +@admin_required +@round_view +def draw_adjudicators_get(request, round): + draw = round.get_draw() + + return _json_adj_allocation(draw, round.unused_adjudicators()) + + @admin_required @round_view def adj_conflicts(request, round): @@ -224,10 +235,95 @@ def add(type, adj_id, target_id): try: add('history', da.adjudicator_id, da.debate.aff_team.id) except DebateTeam.DoesNotExist: - pass # For when a Debate/DebateTeam may have been deleted + pass # For when a Debate/DebateTeam may have been deleted try: add('history', da.adjudicator_id, da.debate.neg_team.id) except DebateTeam.DoesNotExist: - pass # For when a Debate/DebateTeam may have been deleted + pass # For when a Debate/DebateTeam may have been deleted return HttpResponse(json.dumps(data), content_type="text/json") + + +# ============================================================================== +# New UI +# ============================================================================== + +class EditAdjudicatorAllocationView(RoundMixin, SuperuserRequiredMixin, TemplateView): + + template_name = 'edit_adj_allocation.html' + + def get_context_data(self, **kwargs): + t = self.get_tournament() + r = self.get_round() + + draw = r.debate_set_with_prefetches(ordering=('room_rank',), select_related=(), speakers=False, divisions=False) + + teams = Team.objects.filter(debateteam__debate__round=r).prefetch_related('speaker_set') + adjs = get_adjs(self.get_round()) + + regions = regions_ordered(t) + categories = categories_ordered(t) + adjs, teams = populate_conflicts(adjs, teams) + adjs, teams = populate_histories(adjs, teams, t, r) + + kwargs['allRegions'] = json.dumps(regions) + kwargs['allCategories'] = json.dumps(categories) + kwargs['allDebates'] = debates_to_json(draw, t, r) + kwargs['allTeams'] = teams_to_json(teams, regions, categories, t, r) + kwargs['allAdjudicators'] = adjs_to_json(adjs, regions, t) + + return super().get_context_data(**kwargs) + + +class CreateAutoAllocation(LogActionMixin, RoundMixin, SuperuserRequiredMixin, JsonDataResponseView): + + action_log_type = ActionLogEntry.ACTION_TYPE_ADJUDICATORS_AUTO + + def get_data(self): + round = self.get_round() + if round.draw_status == round.STATUS_RELEASED: + return HttpResponseBadRequest("Draw is already released, unrelease draw to redo auto-allocations.") + if round.draw_status != round.STATUS_CONFIRMED: + return HttpResponseBadRequest("Draw is not confirmed, confirm draw to run auto-allocations.") + + allocate_adjudicators(round, HungarianAllocator) + return debates_to_json(round.get_draw(), self.get_tournament(), round) + + +class SaveDebateInfo(SuperuserRequiredMixin, RoundMixin, LogActionMixin, View): + pass + + +class SaveDebateImportance(SaveDebateInfo): + action_log_type = ActionLogEntry.ACTION_TYPE_DEBATE_IMPORTANCE_EDIT + + def post(self, request, *args, **kwargs): + debate_id = request.POST.get('debate_id') + debate_importance = request.POST.get('importance') + + debate = Debate.objects.get(pk=debate_id) + debate.importance = debate_importance + debate.save() + + return HttpResponse() + + +class SaveDebatePanel(SaveDebateInfo): + action_log_type = ActionLogEntry.ACTION_TYPE_ADJUDICATORS_SAVE + + def post(self, request, *args, **kwargs): + debate_id = request.POST.get('debate_id') + debate_panel = json.loads(request.POST.get('panel')) + + to_delete = DebateAdjudicator.objects.filter(debate_id=debate_id).exclude( + adjudicator_id__in=[da['id'] for da in debate_panel]) + for debateadj in to_delete: + logger.info("deleted %s" % debateadj) + to_delete.delete() + + for da in debate_panel: + debateadj, created = DebateAdjudicator.objects.update_or_create(debate_id=debate_id, + adjudicator_id=da['id'], defaults={'type': da['position']}) + logger.info("%s %s" % ("created" if created else "updated", debateadj)) + + return HttpResponse() diff --git a/adjfeedback/__init__.py b/tabbycat/adjfeedback/__init__.py similarity index 100% rename from adjfeedback/__init__.py rename to tabbycat/adjfeedback/__init__.py diff --git a/adjfeedback/admin.py b/tabbycat/adjfeedback/admin.py similarity index 57% rename from adjfeedback/admin.py rename to tabbycat/adjfeedback/admin.py index da83a845f3b..2b5f621d740 100644 --- a/adjfeedback/admin.py +++ b/tabbycat/adjfeedback/admin.py @@ -1,31 +1,34 @@ -from django.contrib import admin -import django.contrib.messages as messages +from django.contrib import admin, messages from .models import AdjudicatorFeedback, AdjudicatorFeedbackQuestion + # ============================================================================== # Adjudicator Feedback Questions # ============================================================================== class AdjudicatorFeedbackQuestionAdmin(admin.ModelAdmin): - list_display = ('reference', 'text', 'seq', 'tournament', 'answer_type', 'required', 'chair_on_panellist', 'panellist_on_chair', 'panellist_on_panellist', 'team_on_orallist') - list_filter = ('tournament',) - ordering = ('tournament', 'seq') + list_display = ('reference', 'text', 'seq', 'tournament', 'answer_type', + 'required', 'from_adj', 'from_team') + list_filter = ('tournament',) + ordering = ('tournament', 'seq') admin.site.register(AdjudicatorFeedbackQuestion, AdjudicatorFeedbackQuestionAdmin) + # ============================================================================== # Adjudicator Feedback Answers # ============================================================================== class BaseAdjudicatorFeedbackAnswerInline(admin.TabularInline): - model = None # must be set by subclasses + model = None # Must be set by subclasses fields = ('question', 'answer') extra = 1 def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "question": - kwargs["queryset"] = AdjudicatorFeedbackQuestion.objects.filter(answer_type__in=AdjudicatorFeedbackQuestion.ANSWER_TYPE_CLASSES_REVERSE[self.model]) + kwargs["queryset"] = AdjudicatorFeedbackQuestion.objects.filter( + answer_type__in=AdjudicatorFeedbackQuestion.ANSWER_TYPE_CLASSES_REVERSE[self.model]) return super(BaseAdjudicatorFeedbackAnswerInline, self).formfield_for_foreignkey(db_field, request, **kwargs) @@ -36,32 +39,35 @@ class RoundListFilter(admin.SimpleListFilter): def lookups(self, request, model_admin): from tournaments.models import Round - return [(str(r.id), "[{}] {}".format(r.tournament.name, r.name)) for r in Round.objects.all()] + return [(str(r.id), "[{}] {}".format(r.tournament.short_name, r.name)) for r in Round.objects.all()] def queryset(self, request, queryset): return queryset.filter(source_team__debate__round_id=self.value()) | queryset.filter(source_adjudicator__debate__round_id=self.value()) + # ============================================================================== # Adjudicator Feedbacks # ============================================================================== class AdjudicatorFeedbackAdmin(admin.ModelAdmin): - list_display = ('adjudicator', 'source_adjudicator', 'source_team', 'confirmed', 'score', 'version') - search_fields = ('source_adjudicator__adjudicator__name', 'source_team__team__institution__code', 'source_team__team__reference', 'adjudicator__name', 'adjudicator__institution__code',) + list_display = ('adjudicator', 'confirmed', 'score', 'version', + 'source_adjudicator', 'source_team') + search_fields = ('adjudicator', 'score', 'source_adjudicator', 'source_team') raw_id_fields = ('source_team',) - list_filter = (RoundListFilter, 'adjudicator', 'source_adjudicator', 'source_team') - actions = ('mark_as_confirmed', 'mark_as_unconfirmed') + list_filter = (RoundListFilter, 'adjudicator') + actions = ('mark_as_confirmed', 'mark_as_unconfirmed') - # dynamically generate inline tables for different answer types + # Dynamically generate inline tables for different answer types inlines = [] for _answer_type_class in AdjudicatorFeedbackQuestion.ANSWER_TYPE_CLASSES_REVERSE: - _inline_class = type(_answer_type_class.__name__ + "Inline", (BaseAdjudicatorFeedbackAnswerInline,), - {"model": _answer_type_class, "__module__": __name__}) + _inline_class = type( + _answer_type_class.__name__ + "Inline", (BaseAdjudicatorFeedbackAnswerInline,), + {"model": _answer_type_class, "__module__": __name__}) inlines.append(_inline_class) def _construct_message_for_user(self, request, count, action, **kwargs): - message_bit = "1 feedback submission was" if count == 1 else "{:d} feedback submissions were".format(count) - self.message_user(request, message_bit + " " + action, **kwargs) + message_bit = "1 feedback submission was " if count == 1 else "{:d} feedback submissions were ".format(count) + self.message_user(request, message_bit + action, **kwargs) def mark_as_confirmed(self, request, queryset): original_count = queryset.count() @@ -69,16 +75,19 @@ def mark_as_confirmed(self, request, queryset): fb.confirmed = True fb.save() final_count = queryset.filter(confirmed=True).count() - self._construct_message_for_user(request, final_count, "marked as confirmed. " \ - "Note that this may have caused other feedback to be marked as unconfirmed.") + self._construct_message_for_user( + request, final_count, "marked as confirmed. Note that this may " + + "have caused other feedback to be marked as unconfirmed.") difference = original_count - final_count if difference > 0: - self._construct_message_for_user(request, difference, "did not end up as confirmed, " \ - "probably because other feedback that conflicts with it was also marked as confirmed.", - level=messages.WARNING) + self._construct_message_for_user( + request, difference, "not marked as confirmed, probably " + + "because other feedback that conflicts with it was also " + + "marked as confirmed.", level=messages.WARNING) def mark_as_unconfirmed(self, request, queryset): count = queryset.update(confirmed=False) - self._construct_message_for_user(request, count, "marked as unconfirmed.") + self._construct_message_for_user(request, count, + "marked as unconfirmed.") admin.site.register(AdjudicatorFeedback, AdjudicatorFeedbackAdmin) diff --git a/adjfeedback/apps.py b/tabbycat/adjfeedback/apps.py similarity index 69% rename from adjfeedback/apps.py rename to tabbycat/adjfeedback/apps.py index 5ee4ca9b2ee..75c97389df6 100644 --- a/adjfeedback/apps.py +++ b/tabbycat/adjfeedback/apps.py @@ -1,5 +1,6 @@ from django.apps import AppConfig + class AdjFeedbackConfig(AppConfig): name = 'adjfeedback' - verbose_name = "Adjudicator Feedback" \ No newline at end of file + verbose_name = "Adjudicator Feedback" diff --git a/adjfeedback/dbutils.py b/tabbycat/adjfeedback/dbutils.py similarity index 89% rename from adjfeedback/dbutils.py rename to tabbycat/adjfeedback/dbutils.py index 61a2e4dff47..9e0499594c8 100644 --- a/adjfeedback/dbutils.py +++ b/tabbycat/adjfeedback/dbutils.py @@ -5,10 +5,9 @@ by a front-end interface as well.""" from . import models as fm -from draw.models import Debate, DebateTeam +from draw.models import DebateTeam from participants.models import Team, Adjudicator from django.contrib.auth import get_user_model -from results.result import BallotSet from adjallocation.models import DebateAdjudicator import random @@ -26,28 +25,32 @@ } COMMENTS = { - 5: ["Amazeballs.", "Saw it exactly how we did.", "Couldn't have been better.", "Really insightful feedback."], - 4: ["Great adjudication but parts were unclear.", "Clear but a bit long. Should break.", "Understood debate but missed a couple of nuances.", "Agreed with adjudication but feedback wasn't super helpful."], - 3: ["Identified all main issues, didn't see interactions between them.", "Solid, would trust to get right, but couldn't articulate some points.", "Pretty good for a novice adjudicator.", "Know what (s)he's doing but reasoning a bit convoluted."], - 2: ["Missed some crucial points in the debate.", "Stepped into debate, but not too significantly.", "Didn't give the other team enough credit for decent points.", "Had some awareness of the debate but couldn't identify main points."], - 1: ["It's as if (s)he was listening to a different debate.", "Worst adjudication I've ever seen.", "Give his/her own analysis to rebut our arguments.", "Should not be adjudicating at this tournament."] + 5: ["Amazeballs.", "Saw it exactly how we did.", "Couldn't have been better.", "Really insightful feedback."], # flake8: noqa + 4: ["Great adjudication but parts were unclear.", "Clear but a bit long. Should break.", "Understood debate but missed a couple of nuances.", "Agreed with adjudication but feedback wasn't super helpful."], # flake8: noqa + 3: ["Identified all main issues, didn't see interactions between them.", "Solid, would trust to get right, but couldn't articulate some points.", "Pretty good for a novice adjudicator.", "Know what (s)he's doing but reasoning a bit convoluted."], # flake8: noqa + 2: ["Missed some crucial points in the debate.", "Stepped into debate, but not too significantly.", "Didn't give the other team enough credit for decent points.", "Had some awareness of the debate but couldn't identify main points."], # flake8: noqa + 1: ["It's as if (s)he was listening to a different debate.", "Worst adjudication I've ever seen.", "Give his/her own analysis to rebut our arguments.", "Should not be adjudicating at this tournament."] # flake8: noqa } + def add_feedback_to_round(round, **kwargs): """Calls add_feedback() for every debate in the given round.""" for debate in round.get_draw(): add_feedback(debate, **kwargs) + def delete_all_feedback_for_round(round): """Deletes all feedback for the given round.""" fm.AdjudicatorFeedback.objects.filter(source_adjudicator__debate__round=round).delete() fm.AdjudicatorFeedback.objects.filter(source_team__debate__round=round).delete() + def delete_feedback(debate): """Deletes all feedback for the given debate.""" fm.AdjudicatorFeedback.objects.filter(source_adjudicator__debate=debate).delete() fm.AdjudicatorFeedback.objects.filter(source_team__debate=debate).delete() + def add_feedback(debate, submitter_type, user, probability=1.0, discarded=False, confirmed=False): """Adds feedback to a debate. Specifically, adds feedback from both teams on the chair, and from every @@ -58,9 +61,8 @@ def add_feedback(debate, submitter_type, user, probability=1.0, discarded=False, ``user`` is a User object. ``probability``, a float between 0.0 and 1.0, is the probability with which feedback is generated. - ``discarded`` and ``confirmed`` are whether the feedback should be discarded or - confirmed, respectively.""" - + ``discarded`` and ``confirmed`` are whether the feedback should be + discarded or confirmed, respectively.""" if discarded and confirmed: raise ValueError("Feedback can't be both discarded and confirmed!") @@ -73,14 +75,14 @@ def add_feedback(debate, submitter_type, user, probability=1.0, discarded=False, (debate.neg_team, debate.adjudicators.chair), ] sources_and_subjects.extend(itertools.permutations( - (adj for type, adj in debate.adjudicators), 2)) + (adj for type, adj in debate.adjudicators), 2)) fbs = list() for source, adj in sources_and_subjects: if random.random() > probability: - logger.info(" - Skipping {} on {}".format(source, adj)) + logger.info(" - Skipping %s on %s", source, adj) continue fb = fm.AdjudicatorFeedback(submitter_type=submitter_type) @@ -90,10 +92,10 @@ def add_feedback(debate, submitter_type, user, probability=1.0, discarded=False, fb.adjudicator = adj if isinstance(source, Adjudicator): fb.source_adjudicator = DebateAdjudicator.objects.get( - debate=debate, adjudicator=source) + debate=debate, adjudicator=source) elif isinstance(source, Team): fb.source_team = DebateTeam.objects.get( - debate=debate, team=source) + debate=debate, team=source) else: raise TypeError("source must be an Adjudicator or a Team") @@ -130,8 +132,8 @@ def add_feedback(debate, submitter_type, user, probability=1.0, discarded=False, question.answer_type_class(question=question, feedback=fb, answer=answer).save() name = source.name if isinstance(source, Adjudicator) else source.short_name - logger.info("[{}] {} on {}: {}".format(debate.round.tournament.slug, name, adj, score)) + logger.info("[%s] %s on %s: %s", debate.round.tournament.slug, name, adj, score) fbs.append(fb) - return fbs \ No newline at end of file + return fbs diff --git a/adjfeedback/forms.py b/tabbycat/adjfeedback/forms.py similarity index 60% rename from adjfeedback/forms.py rename to tabbycat/adjfeedback/forms.py index 6cd52fc6b8b..e3bee356e2c 100644 --- a/adjfeedback/forms.py +++ b/tabbycat/adjfeedback/forms.py @@ -5,26 +5,41 @@ from django.utils.translation import ugettext_lazy from django.utils.translation import ugettext as _ -from .models import AdjudicatorFeedback, AdjudicatorFeedbackQuestion -from tournaments.models import Round -from participants.models import Adjudicator, Team +from adjallocation.allocation import AdjudicatorAllocation from adjallocation.models import DebateAdjudicator from draw.models import Debate, DebateTeam -from utils.forms import OptionalChoiceField +from participants.models import Adjudicator, Team from results.forms import TournamentPasswordField +from tournaments.models import Round +from utils.forms import OptionalChoiceField + +from .models import AdjudicatorFeedback, AdjudicatorFeedbackQuestion +from .utils import expected_feedback_targets logger = logging.getLogger(__name__) +ADJUDICATOR_POSITION_NAMES = { + 'c': 'chair', + 'o': 'solo', + 'p': 'panellist', + 't': 'trainee' +} + + +# ============================================================================== # General, but only used here +# ============================================================================== class IntegerRadioFieldRenderer(forms.widgets.RadioFieldRenderer): """Used by IntegerRadioSelect.""" - outer_html = '{content}
    Unused Adjudicators
    ' - inner_html = '{choice_value}{sub_widgets}' + outer_html = '{content}
    ' + inner_html = '
    {choice_value}{sub_widgets}
    ' + class IntegerRadioSelect(forms.RadioSelect): renderer = IntegerRadioFieldRenderer + class IntegerScaleField(forms.IntegerField): """Class to do integer scale fields.""" widget = IntegerRadioSelect @@ -33,6 +48,7 @@ def __init__(self, *args, **kwargs): super(IntegerScaleField, self).__init__(*args, **kwargs) self.widget.choices = tuple((i, str(i)) for i in range(self.min_value, self.max_value+1)) + class BlankUnknownBooleanSelect(forms.NullBooleanSelect): """Uses '--------' instead of 'Unknown' for the None choice.""" @@ -43,16 +59,19 @@ def __init__(self, attrs=None): # skip the NullBooleanSelect constructor super(forms.NullBooleanSelect, self).__init__(attrs, choices) + class BooleanSelectField(forms.NullBooleanField): """Widget to do boolean select fields following our conventions. Specifically, if 'required', checks that an option was chosen.""" widget = BlankUnknownBooleanSelect + def clean(self, value): value = super(BooleanSelectField, self).clean(value) if self.required and value is None: raise forms.ValidationError(_("This field is required.")) return value + class RequiredTypedChoiceField(forms.TypedChoiceField): def clean(self, value): value = super(RequiredTypedChoiceField, self).clean(value) @@ -60,16 +79,21 @@ def clean(self, value): raise forms.ValidationError(_("This field is required.")) return value + +# ============================================================================== # Feedback Fields +# ============================================================================== class AdjudicatorFeedbackCheckboxFieldRenderer(forms.widgets.CheckboxFieldRenderer): """Used by AdjudicatorFeedbackCheckboxSelectMultiple.""" outer_html = '
    ' inner_html = '' + class AdjudicatorFeedbackCheckboxSelectMultiple(forms.CheckboxSelectMultiple): renderer = AdjudicatorFeedbackCheckboxFieldRenderer + class AdjudicatorFeedbackCheckboxSelectMultipleField(forms.MultipleChoiceField): """Class to do multiple choice fields following our conventions. Specifically, converts to a string rather than a list.""" @@ -79,14 +103,17 @@ def clean(self, value): value = super(AdjudicatorFeedbackCheckboxSelectMultipleField, self).clean(value) return AdjudicatorFeedbackQuestion.CHOICE_SEPARATOR.join(value) + +# ============================================================================== # Feedback Forms +# ============================================================================== class BaseFeedbackForm(forms.Form): """Base class for all dynamically-created feedback forms. Contains all question fields.""" # parameters set at "compile time" by subclasses - tournament = None # must be set by subclasses + _tournament = None # must be set by subclasses _use_tournament_password = False _confirm_on_submit = False _enforce_required = True @@ -96,6 +123,13 @@ def __init__(self, *args, **kwargs): super(BaseFeedbackForm, self).__init__(*args, **kwargs) self._create_fields() + @staticmethod + def coerce_target(value): + debate_id, adj_id = value.split('-') + debate = Debate.objects.get(id=int(debate_id)) + adjudicator = Adjudicator.objects.get(id=int(adj_id)) + return debate, adjudicator + def _make_question_field(self, question): if question.answer_type == question.ANSWER_TYPE_BOOLEAN_SELECT: field = BooleanSelectField() @@ -114,8 +148,7 @@ def _make_question_field(self, question): else: field = IntegerScaleField(min_value=min_value, max_value=max_value) elif question.answer_type == question.ANSWER_TYPE_FLOAT: - field = forms.FloatField(min_value=question.min_value, - max_value=question.max_value) + field = forms.FloatField(min_value=question.min_value, max_value=question.max_value) elif question.answer_type == question.ANSWER_TYPE_TEXT: field = forms.CharField() elif question.answer_type == question.ANSWER_TYPE_LONGTEXT: @@ -133,17 +166,17 @@ def _make_question_field(self, question): def _create_fields(self): """Creates dynamic fields in the form.""" # Feedback questions defined for the tournament - adj_min_score = self.tournament.pref('adj_min_score') - adj_max_score = self.tournament.pref('adj_max_score') + adj_min_score = self._tournament.pref('adj_min_score') + adj_max_score = self._tournament.pref('adj_max_score') score_label = mark_safe("Overall score
    (%s=lowest, %s=highest)" % (adj_min_score, adj_max_score)) self.fields['score'] = forms.FloatField(min_value=adj_min_score, max_value=adj_max_score, label=score_label) - for question in self.tournament.adj_feedback_questions.filter(**self.question_filter): + for question in self._tournament.adj_feedback_questions.filter(**self.question_filter): self.fields[question.reference] = self._make_question_field(question) # Tournament password field, if applicable - if self._use_tournament_password and self.tournament.pref('public_use_password'): - self.fields['password'] = TournamentPasswordField(tournament=self.tournament) + if self._use_tournament_password and self._tournament.pref('public_use_password'): + self.fields['password'] = TournamentPasswordField(tournament=self._tournament) def save_adjudicatorfeedback(self, **kwargs): """Saves the question fields and returns the AdjudicatorFeedback. @@ -152,17 +185,17 @@ def save_adjudicatorfeedback(self, **kwargs): if self._confirm_on_submit: self.discard_all_existing(adjudicator=kwargs['adjudicator'], - source_adjudicator=kwargs['source_adjudicator'], - source_team=kwargs['source_team']) + source_adjudicator=kwargs['source_adjudicator'], + source_team=kwargs['source_team']) af.confirmed = True af.score = self.cleaned_data['score'] af.save() - for question in self.tournament.adj_feedback_questions.filter(**self.question_filter): + for question in self._tournament.adj_feedback_questions.filter(**self.question_filter): if self.cleaned_data[question.reference] is not None: - answer = question.answer_type_class(feedback=af, question=question, - answer=self.cleaned_data[question.reference]) + answer = question.answer_type_class( + feedback=af, question=question, answer=self.cleaned_data[question.reference]) answer.save() return af @@ -172,7 +205,8 @@ def discard_all_existing(self, **kwargs): fb.discarded = True fb.save() -def make_feedback_form_class(source, *args, **kwargs): + +def make_feedback_form_class(source, tournament, *args, **kwargs): """Constructs a FeedbackForm class specific to the given source. 'source' is the Adjudicator or Team who is giving feedback. 'submission_fields' is a dict of fields that is passed directly as keyword @@ -180,111 +214,109 @@ def make_feedback_form_class(source, *args, **kwargs): 'confirm_on_submit' is a bool, and indicates that this feedback should be as confirmed and all others discarded.""" if isinstance(source, Adjudicator): - return make_feedback_form_class_for_adj(source, *args, **kwargs) + return make_feedback_form_class_for_adj(source, tournament, *args, **kwargs) elif isinstance(source, Team): - return make_feedback_form_class_for_team(source, *args, **kwargs) + return make_feedback_form_class_for_team(source, tournament, *args, **kwargs) else: raise TypeError('source must be Adjudicator or Team: %r' % source) -def make_feedback_form_class_for_adj(source, submission_fields, confirm_on_submit=False, - enforce_required=True, include_unreleased_draws=False): + +def make_feedback_form_class_for_adj(source, tournament, submission_fields, confirm_on_submit=False, + enforce_required=True, include_unreleased_draws=False): """Constructs a FeedbackForm class specific to the given source adjudicator. Parameters are as for make_feedback_form_class.""" - def adj_choice(da): - return (da.id, '%s (%s, %s)' % (da.adjudicator.name, - da.debate.round.name, da.get_type_display())) - def coerce_da(value): - return DebateAdjudicator.objects.get(id=int(value)) + def adj_choice(adj, debate, pos): + value = '%d-%d' % (debate.id, adj.id) + display = '%s (%s, %s)' % (adj.name, debate.round.name, ADJUDICATOR_POSITION_NAMES[pos]) + return (value, display) + + debateadjs = DebateAdjudicator.objects.filter( + debate__round__tournament=tournament, adjudicator=source, + debate__round__seq__lte=tournament.current_round.seq, + debate__round__stage=Round.STAGE_PRELIMINARY + ).order_by('-debate__round__seq').prefetch_related( + 'debate__debateadjudicator_set__adjudicator' + ) - debate_filter = {'debateadjudicator__adjudicator': source} - if not source.tournament.pref('panellist_feedback_enabled'): - debate_filter['debateadjudicator__type'] = DebateAdjudicator.TYPE_CHAIR # include only debates for which this adj was the chair if include_unreleased_draws: - debate_filter['round__draw_status__in'] = [Round.STATUS_CONFIRMED, Round.STATUS_RELEASED] + debateadjs = debateadjs.filter(debate__round__draw_status__in=[Round.STATUS_CONFIRMED, Round.STATUS_RELEASED]) else: - debate_filter['round__draw_status'] = Round.STATUS_RELEASED - debates = Debate.objects.filter(**debate_filter) + debateadjs = debateadjs.filter(debate__round__draw_status=Round.STATUS_RELEASED) choices = [(None, '-- Adjudicators --')] - # for an adjudicator, find every adjudicator on their panel except them - choices.extend(adj_choice(da) for da in DebateAdjudicator.objects.filter( - debate__in=debates).exclude( - adjudicator=source).select_related( - 'debate').order_by( - '-debate__round__seq')) + for debateadj in debateadjs: + targets = expected_feedback_targets(debateadj, tournament.pref('feedback_paths')) + for target, pos in targets: + choices.append(adj_choice(target, debateadj.debate, pos)) class FeedbackForm(BaseFeedbackForm): - tournament = source.tournament # BaseFeedbackForm setting - _use_tournament_password = True # BaseFeedbackForm setting + _tournament = tournament # BaseFeedbackForm setting + _use_tournament_password = True # BaseFeedbackForm setting _confirm_on_submit = confirm_on_submit _enforce_required = enforce_required - question_filter = dict(chair_on_panellist=True) + question_filter = dict(from_adj=True) - debate_adjudicator = RequiredTypedChoiceField(choices=choices, coerce=coerce_da) + target = RequiredTypedChoiceField(choices=choices, coerce=BaseFeedbackForm.coerce_target, label='Adjudicator this feedback is about') def save(self): """Saves the form and returns the AdjudicatorFeedback object.""" - da = self.cleaned_data['debate_adjudicator'] - sa = DebateAdjudicator.objects.get(adjudicator=source, debate=da.debate) - kwargs = dict(adjudicator=da.adjudicator, source_adjudicator=sa, source_team=None) + debate, target = self.cleaned_data['target'] + sa = DebateAdjudicator.objects.get(adjudicator=source, debate=debate) + kwargs = dict(adjudicator=target, source_adjudicator=sa, source_team=None) kwargs.update(submission_fields) return self.save_adjudicatorfeedback(**kwargs) return FeedbackForm -def make_feedback_form_class_for_team(source, submission_fields, confirm_on_submit=False, - enforce_required=True, include_unreleased_draws=False): + +def make_feedback_form_class_for_team(source, tournament, submission_fields, confirm_on_submit=False, + enforce_required=True, include_unreleased_draws=False): """Constructs a FeedbackForm class specific to the given source team. Parameters are as for make_feedback_form_class.""" + def adj_choice(adj, debate, pos): + value = '%d-%d' % (debate.id, adj.id) + if pos == AdjudicatorAllocation.POSITION_CHAIR: + pos_text = '—chair gave oral' + elif pos == AdjudicatorAllocation.POSITION_PANELLIST: + pos_text = '—chair rolled, this panellist gave oral' + elif pos == AdjudicatorAllocation.POSITION_ONLY: + pos_text = '' + display = '{name} ({r}{pos})'.format(name=adj.name, r=debate.round.name, pos=pos_text) + return (value, display) + # Only include non-silent rounds for teams. - debate_filter = { - 'debateteam__team': source, - 'round__silent': False, - } + debates = Debate.objects.filter( + debateteam__team=source, round__silent=False, + round__seq__lte=tournament.current_round.seq, + round__stage=Round.STAGE_PRELIMINARY + ).order_by('-round__seq').prefetch_related('debateadjudicator_set__adjudicator') if include_unreleased_draws: - debate_filter['round__draw_status__in'] = [Round.STATUS_CONFIRMED, Round.STATUS_RELEASED] + debates = debates.filter(round__draw_status__in=[Round.STATUS_CONFIRMED, Round.STATUS_RELEASED]) else: - debate_filter['round__draw_status'] = Round.STATUS_RELEASED - debates = Debate.objects.filter(**debate_filter).order_by('-round__seq') + debates = debates.filter(round__draw_status=Round.STATUS_RELEASED) choices = [(None, '-- Adjudicators --')] for debate in debates: - try: - chair = DebateAdjudicator.objects.get(debate=debate, type=DebateAdjudicator.TYPE_CHAIR) - except DebateAdjudicator.DoesNotExist: - continue - panel = DebateAdjudicator.objects.filter(debate=debate, type=DebateAdjudicator.TYPE_PANEL) - if panel.exists(): - choices.append((chair.id, '{name} ({r} - chair gave oral)'.format( - name=chair.adjudicator.name, r=debate.round.name))) - for da in panel: - choices.append((da.id, '{name} ({r} - chair rolled, this panellist gave oral)'.format( - name=da.adjudicator.name, r=debate.round.name))) - else: - choices.append((chair.id, '{name} ({r})'.format( - name=chair.adjudicator.name, r=debate.round.name))) - - def coerce_da(value): - return DebateAdjudicator.objects.get(id=int(value)) + for adj, pos in debate.adjudicators.voting_with_positions(): + choices.append(adj_choice(adj, debate, pos)) class FeedbackForm(BaseFeedbackForm): - tournament = source.tournament # BaseFeedbackForm setting - _use_tournament_password = True # BaseFeedbackForm setting + _tournament = tournament # BaseFeedbackForm setting + _use_tournament_password = True # BaseFeedbackForm setting _confirm_on_submit = confirm_on_submit _enforce_required = enforce_required - question_filter = dict(team_on_orallist=True) + question_filter = dict(from_team=True) - debate_adjudicator = RequiredTypedChoiceField(choices=choices, coerce=coerce_da) + target = RequiredTypedChoiceField(choices=choices, coerce=BaseFeedbackForm.coerce_target) def save(self): # Saves the form and returns the m.AdjudicatorFeedback object - da = self.cleaned_data['debate_adjudicator'] - st = DebateTeam.objects.get(team=source, debate=da.debate) - kwargs = dict(adjudicator=da.adjudicator, source_adjudicator=None, source_team=st) + debate, target = self.cleaned_data['target'] + st = DebateTeam.objects.get(team=source, debate=debate) + kwargs = dict(adjudicator=target, source_adjudicator=None, source_team=st) kwargs.update(submission_fields) return self.save_adjudicatorfeedback(**kwargs) return FeedbackForm - diff --git a/adjfeedback/management/commands/generatefeedback.py b/tabbycat/adjfeedback/management/commands/generatefeedback.py similarity index 65% rename from adjfeedback/management/commands/generatefeedback.py rename to tabbycat/adjfeedback/management/commands/generatefeedback.py index b27803595e2..656031364ea 100644 --- a/adjfeedback/management/commands/generatefeedback.py +++ b/tabbycat/adjfeedback/management/commands/generatefeedback.py @@ -1,10 +1,10 @@ -from utils.management.base import RoundCommand, CommandError -from ...dbutils import add_feedback, add_feedback_to_round, delete_all_feedback_for_round, delete_feedback - from django.contrib.auth import get_user_model -from tournaments.models import Round -from draw.models import Debate + from adjfeedback.models import AdjudicatorFeedback +from draw.models import Debate +from utils.management.base import CommandError, RoundCommand + +from ...dbutils import add_feedback, add_feedback_to_round, delete_all_feedback_for_round, delete_feedback OBJECT_TYPE_CHOICES = ["round", "debate"] SUBMITTER_TYPE_MAP = { @@ -13,6 +13,7 @@ } User = get_user_model() + class Command(RoundCommand): help = "Adds randomly-generated feedback to the database" @@ -20,17 +21,32 @@ class Command(RoundCommand): def add_arguments(self, parser): super(Command, self).add_arguments(parser) - parser.add_argument("--debates", type=int, nargs="+", help="IDs of specific debates to add feedback to. Done in addition to rounds, if any.", default=[]) - parser.add_argument("-p", "--probability", type=float, help="Probability with which to add feedback", default=1.0) - parser.add_argument("-T", "--submitter-type", type=str, help="Submitter type, either 'tabroom' or 'public'", choices=list(SUBMITTER_TYPE_MAP.keys()), default="tabroom") - parser.add_argument("-u", "--user", type=str, help="Username of submitter", default="random") + parser.add_argument("--debates", type=int, nargs="+", + help="IDs of specific debates to add feedback to. " + "Done in addition to rounds, if any.", + default=[]) + parser.add_argument("-p", "--probability", type=float, + help="Probability with which to add feedback", + default=1.0) + parser.add_argument("-T", "--submitter-type", type=str, + help="Submitter type, either 'tabroom' or 'public'", + choices=list(SUBMITTER_TYPE_MAP.keys()), + default="tabroom") + parser.add_argument("-u", "--user", type=str, + help="Username of submitter", default="random") status = parser.add_mutually_exclusive_group() - status.add_argument("-D", "--discarded", action="store_true", help="Make feedback discarded") - status.add_argument("-c", "--confirmed", action="store_true", help="Make feedback confirmed") - - parser.add_argument("--clean", help="Remove all associated feedback first", action="store_true") - parser.add_argument("--create-user", help="Create user if it doesn't exist", action="store_true") + status.add_argument("-D", "--discarded", action="store_true", + help="Make feedback discarded") + status.add_argument("-c", "--confirmed", action="store_true", + help="Make feedback confirmed") + + parser.add_argument("--clean", + help="Remove all associated feedback first", + action="store_true") + parser.add_argument("--create-user", + help="Create user if it doesn't exist", + action="store_true") @staticmethod def _get_user(options): @@ -58,14 +74,17 @@ def handle(self, *args, **options): if not self.get_rounds(options) and not options["debates"]: raise CommandError("No rounds or debates were given. (Use --help for more info.)") - super(Command, self).handle(*args, **options) # handles rounds + super(Command, self).handle(*args, **options) # Handles rounds for tournament in self.get_tournaments(options): for debate_id in options["debates"]: try: debate = Debate.objects.get(round__tournament=tournament, id=debate_id) except Debate.DoesNotExist: - self.stdout.write(self.style.WARNING("Warning: There is no debate with id {:d} for tournament {!r}, skipping".format(debate_id, tournament.slug))) + self.stdout.write( + self.style.WARNING("Warning: There is no debate with " + "id {:d} for tournament {!r}, " + "skipping".format(debate_id, tournament.slug))) self.handle_debate(debate, **options) def handle_round(self, round, **options): @@ -89,4 +108,3 @@ def handle_debate(self, debate, **options): add_feedback(debate, **self.feedback_kwargs(options)) except ValueError as e: raise CommandError(e) - diff --git a/adjfeedback/management/commands/printmultiplefeedback.py b/tabbycat/adjfeedback/management/commands/printmultiplefeedback.py similarity index 69% rename from adjfeedback/management/commands/printmultiplefeedback.py rename to tabbycat/adjfeedback/management/commands/printmultiplefeedback.py index ef65c78ff62..1a8d903baec 100644 --- a/adjfeedback/management/commands/printmultiplefeedback.py +++ b/tabbycat/adjfeedback/management/commands/printmultiplefeedback.py @@ -1,12 +1,15 @@ from utils.management.base import TournamentCommand + class Command(TournamentCommand): help = "Checks for feedback with more than one version." def add_arguments(self, parser): super(Command, self).add_arguments(parser) - parser.add_argument("--num", "-n", type=int, help="Show feedback with at least this many versions", default=2) + parser.add_argument( + "--num", "-n", type=int, + help="Show feedback with at least this many versions", default=2) def handle_tournament(self, tournament, **options): @@ -21,8 +24,9 @@ def handle_tournament(self, tournament, **options): source_team=feedback.source_team).order_by('version') num = others.count() if num >= options["num"]: - self.stdout.write(self.style.MIGRATE_HEADING(" *** Adjudicator: {0}, from: {1}, {2:d} versions".format(adj, feedback.source, num))) + self.stdout.write(self.style.MIGRATE_HEADING( + " *** Adjudicator: {0}, from: {1}, {2:d} versions".format(adj, feedback.source, num))) for other in others: self.stdout.write(" {id:>3} {submitter:<12} {round:<4} {c} {version} {score:.1f}".format( - score=other.score, version=other.version, round=other.round.abbreviation, submitter=other.submitter.username, - id=other.id, c="c" if other.confirmed else "-")) + score=other.score, version=other.version, round=other.round.abbreviation, submitter=other.submitter.username, + id=other.id, c="c" if other.confirmed else "-")) diff --git a/adjfeedback/migrations/0001_initial.py b/tabbycat/adjfeedback/migrations/0001_initial.py similarity index 100% rename from adjfeedback/migrations/0001_initial.py rename to tabbycat/adjfeedback/migrations/0001_initial.py diff --git a/adjfeedback/migrations/0002_adjudicatortestscorehistory_adjudicator.py b/tabbycat/adjfeedback/migrations/0002_adjudicatortestscorehistory_adjudicator.py similarity index 100% rename from adjfeedback/migrations/0002_adjudicatortestscorehistory_adjudicator.py rename to tabbycat/adjfeedback/migrations/0002_adjudicatortestscorehistory_adjudicator.py diff --git a/adjfeedback/migrations/0003_auto_20160103_1927.py b/tabbycat/adjfeedback/migrations/0003_auto_20160103_1927.py similarity index 100% rename from adjfeedback/migrations/0003_auto_20160103_1927.py rename to tabbycat/adjfeedback/migrations/0003_auto_20160103_1927.py diff --git a/adjfeedback/migrations/0004_auto_20160109_1834.py b/tabbycat/adjfeedback/migrations/0004_auto_20160109_1834.py similarity index 100% rename from adjfeedback/migrations/0004_auto_20160109_1834.py rename to tabbycat/adjfeedback/migrations/0004_auto_20160109_1834.py diff --git a/adjfeedback/migrations/0005_auto_20160228_1838.py b/tabbycat/adjfeedback/migrations/0005_auto_20160228_1838.py similarity index 100% rename from adjfeedback/migrations/0005_auto_20160228_1838.py rename to tabbycat/adjfeedback/migrations/0005_auto_20160228_1838.py diff --git a/tabbycat/adjfeedback/migrations/0006_auto_20160716_1245.py b/tabbycat/adjfeedback/migrations/0006_auto_20160716_1245.py new file mode 100644 index 00000000000..c4e37d9273c --- /dev/null +++ b/tabbycat/adjfeedback/migrations/0006_auto_20160716_1245.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-16 12:45 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('adjfeedback', '0005_auto_20160228_1838'), + ] + + operations = [ + migrations.AlterField( + model_name='adjudicatorfeedbackquestion', + name='chair_on_panellist', + field=models.BooleanField(help_text='Despite the name, applies to all adjudicator-on-adjudicator feedback'), + ), + migrations.AlterField( + model_name='adjudicatorfeedbackquestion', + name='panellist_on_chair', + field=models.BooleanField(help_text='Not currently used, reserved for future use'), + ), + migrations.AlterField( + model_name='adjudicatorfeedbackquestion', + name='panellist_on_panellist', + field=models.BooleanField(help_text='Not currently used, reserved for future use'), + ), + ] diff --git a/tabbycat/adjfeedback/migrations/0007_from_adj_from_team.py b/tabbycat/adjfeedback/migrations/0007_from_adj_from_team.py new file mode 100644 index 00000000000..2e43c36ec87 --- /dev/null +++ b/tabbycat/adjfeedback/migrations/0007_from_adj_from_team.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-26 20:04 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('adjfeedback', '0006_auto_20160716_1245'), + ] + + operations = [ + migrations.RenameField( + model_name='adjudicatorfeedbackquestion', + old_name='chair_on_panellist', + new_name='from_adj', + ), + migrations.RenameField( + model_name='adjudicatorfeedbackquestion', + old_name='team_on_orallist', + new_name='from_team', + ), + migrations.RemoveField( + model_name='adjudicatorfeedbackquestion', + name='panellist_on_chair', + ), + migrations.RemoveField( + model_name='adjudicatorfeedbackquestion', + name='panellist_on_panellist', + ), + ] diff --git a/tabbycat/adjfeedback/migrations/0008_auto_20160726_2007.py b/tabbycat/adjfeedback/migrations/0008_auto_20160726_2007.py new file mode 100644 index 00000000000..95f4c7313d0 --- /dev/null +++ b/tabbycat/adjfeedback/migrations/0008_auto_20160726_2007.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-26 20:07 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('adjfeedback', '0007_from_adj_from_team'), + ] + + operations = [ + migrations.AlterField( + model_name='adjudicatorfeedbackquestion', + name='from_adj', + field=models.BooleanField(help_text='Adjudicators should be asked this question (about other adjudicators)'), + ), + migrations.AlterField( + model_name='adjudicatorfeedbackquestion', + name='from_team', + field=models.BooleanField(help_text='Teams should be asked this question'), + ), + ] diff --git a/adjfeedback/migrations/__init__.py b/tabbycat/adjfeedback/migrations/__init__.py similarity index 100% rename from adjfeedback/migrations/__init__.py rename to tabbycat/adjfeedback/migrations/__init__.py diff --git a/adjfeedback/models.py b/tabbycat/adjfeedback/models.py similarity index 88% rename from adjfeedback/models.py rename to tabbycat/adjfeedback/models.py index 56f1f9a1af6..d98e1b798c0 100644 --- a/adjfeedback/models.py +++ b/tabbycat/adjfeedback/models.py @@ -2,8 +2,8 @@ from django.db import models from django.utils.functional import cached_property -from results.models import Submission from adjallocation.models import DebateAdjudicator +from results.models import Submission class AdjudicatorTestScoreHistory(models.Model): @@ -97,19 +97,15 @@ class AdjudicatorFeedbackQuestion(models.Model): help_text="The order in which questions are displayed") text = models.CharField( max_length=255, - help_text= - "The question displayed to participants, e.g., \"Did you agree with the decision?\"") + help_text="The question displayed to participants, e.g., \"Did you agree with the decision?\"") name = models.CharField( max_length=30, - help_text= - "A short name for the question, e.g., \"Agree with decision\"") + help_text="A short name for the question, e.g., \"Agree with decision\"") reference = models.SlugField( help_text="Code-compatible reference, e.g., \"agree_with_decision\"") - chair_on_panellist = models.BooleanField() - panellist_on_chair = models.BooleanField() # for future use - panellist_on_panellist = models.BooleanField() # for future use - team_on_orallist = models.BooleanField() + from_adj = models.BooleanField(help_text="Adjudicators should be asked this question (about other adjudicators)") + from_team = models.BooleanField(help_text="Teams should be asked this question") answer_type = models.CharField(max_length=2, choices=ANSWER_TYPE_CHOICES) required = models.BooleanField( @@ -118,19 +114,16 @@ class AdjudicatorFeedbackQuestion(models.Model): min_value = models.FloatField( blank=True, null=True, - help_text= - "Minimum allowed value for numeric fields (ignored for text or boolean fields)") + help_text="Minimum allowed value for numeric fields (ignored for text or boolean fields)") max_value = models.FloatField( blank=True, null=True, - help_text= - "Maximum allowed value for numeric fields (ignored for text or boolean fields)") + help_text="Maximum allowed value for numeric fields (ignored for text or boolean fields)") choices = models.CharField( max_length=500, blank=True, null=True, - help_text= - "Permissible choices for select one/multiple fields, separated by %r (ignored for other fields)" + help_text="Permissible choices for select one/multiple fields, separated by %r (ignored for other fields)" % CHOICE_SEPARATOR) class Meta: @@ -198,7 +191,7 @@ def debate_adjudicator(self): try: return self.adjudicator.debateadjudicator_set.get( debate=self.debate) - except DebateAdjudicator.DoesNotExist as e: + except DebateAdjudicator.DoesNotExist: return None @property @@ -215,6 +208,9 @@ def clean(self): if not (self.source_adjudicator or self.source_team): raise ValidationError( "Either the source adjudicator or source team wasn't specified.") + if self.source_adjudicator and self.source_team: + raise ValidationError( + "There was both a source adjudicator and a source team.") if self.adjudicator not in self.debate.adjudicators: - raise ValidationError("Adjudicator did not see this debate") - super(AdjudicatorFeedback, self).clean() + raise ValidationError("Adjudicator did not see this debate.") + return super(AdjudicatorFeedback, self).clean() diff --git a/tabbycat/adjfeedback/progress.py b/tabbycat/adjfeedback/progress.py new file mode 100644 index 00000000000..4a45599641a --- /dev/null +++ b/tabbycat/adjfeedback/progress.py @@ -0,0 +1,378 @@ +"""Utilities to compute which feedback has been submitted and not submitted +by participants of the tournament. + +There are a few possibilities for how to characterise a feedback submission: +""" + +import logging +from operator import attrgetter + +from adjallocation.models import DebateAdjudicator +from adjfeedback.models import AdjudicatorFeedback +from draw.models import DebateTeam +from results.prefetch import populate_confirmed_ballots +from tournaments.models import Round + +from .utils import expected_feedback_targets + +logger = logging.getLogger(__name__) + + +class BaseFeedbackExpectedSubmissionTracker: + """Represents a single piece of expected feedback.""" + + expected = True + + def __init__(self, source): + self.source = source # either a DebateTeam or a DebateAdjudicator + + @property + def round(self): + return self.source.debate.round + + @property + def count(self): + return len(self.acceptable_submissions()) + + @property + def fulfilled(self): + return self.count == 1 + + def acceptable_submissions(self): + if not hasattr(self, '_acceptable_submissions'): + self._acceptable_submissions = self.get_acceptable_submissions() + return self._acceptable_submissions + + def get_acceptable_submissions(self): + """Subclasses should override this method to provide an iterable of + acceptable submissions. Users of this class might pre-populate + the `_acceptable_submissions` attribute to avoid duplicate database + hits.""" + raise NotImplementedError + + def submission(self): + if self.fulfilled: + return self.acceptable_submissions()[0] + else: + return None + + +class FeedbackExpectedSubmissionFromTeamTracker(BaseFeedbackExpectedSubmissionTracker): + """Represents a single piece of expected feedback from a team.""" + + def __init__(self, source, enforce_orallist=True): + self.enforce_orallist = enforce_orallist + super().__init__(source) + + def acceptable_targets(self): + """For a team, this must be the adjudicator who delivered the oral + adjudication. If the chair was rolled, then it is one of the majority + adjudicators; if the chair was in the majority, then it must be the + chair.""" + + if self.enforce_orallist and self.source.debate.confirmed_ballot: + majority = self.source.debate.confirmed_ballot.ballot_set.majority_adj + chair = self.source.debate.adjudicators.chair + if chair in majority: + return [chair] + else: + return majority + else: + return list(self.source.debate.adjudicators.voting()) + + def get_acceptable_submissions(self): + return self.source.adjudicatorfeedback_set.filter(confirmed=True, + source_team=self.source, + adjudicator__in=self.acceptable_targets()).select_related( + 'source_team', 'adjudicator', 'adjudicator__institution') + + +class FeedbackExpectedSubmissionFromAdjudicatorTracker(BaseFeedbackExpectedSubmissionTracker): + """Represents a single piece of expected feedback from an adjudicator.""" + + def __init__(self, source, target): + self.target = target + return super().__init__(source) + + def get_acceptable_submissions(self): + return self.source.adjudicatorfeedback_set.filter(confirmed=True, + adjudicator=self.target, source_adjudicator=self.source).select_related( + 'source_adjudicator', 'adjudicator', 'adjudicator__institution') + + def acceptable_targets(self): + return [self.target] + + +class FeedbackUnexpectedSubmissionTracker: + """Represents a single piece of unexpected feedback.""" + + expected = False + fulfilled = False + + def __init__(self, feedback): + self.feedback = feedback # an AdjudicatorFeedback instance + + @property + def round(self): + return self.feedback.round + + @property + def count(self): + return 1 + + def submission(self): + return self.feedback + + +class BaseFeedbackProgress: + """Class to compute feedback submitted or owed by a participant. + + Rather than just counting and comparing aggregates, everything is compared + at the individual feedback level using objects called "trackers". This + ensures that feedbacks that were actually submitted match those that were + expected.""" + + def __init__(self, tournament): + self.show_unexpected = tournament.pref('show_unexpected_feedback') + + def get_expected_trackers(self): + raise NotImplementedError + + def get_submitted_feedback(self): + raise NotImplementedError + + def expected_trackers(self): + if not hasattr(self, "_expected_trackers"): + self._expected_trackers = self.get_expected_trackers() + return self._expected_trackers + + def submitted_feedback(self): + if not hasattr(self, "_submitted_feedback"): + self._submitted_feedback = self.get_submitted_feedback() + return self._submitted_feedback + + def expected_feedback(self): + """Returns a list of AdjudicatorFeedback objects that are submitted + as expected (including where more are submitted than expected).""" + return [feedback for tracker in self.expected_trackers() + for feedback in tracker.acceptable_submissions()] + + def unexpected_trackers(self): + """Returns a list of trackers for feedback that was submitted but not + expected to be there.""" + if self.show_unexpected: + return [FeedbackUnexpectedSubmissionTracker(feedback) for feedback in + self.submitted_feedback() if feedback not in self.expected_feedback()] + else: + return [] + + def fulfilled_trackers(self): + """Returns a list of trackers that are fulfilled.""" + return [tracker for tracker in self.expected_trackers() if tracker.fulfilled] + + def trackers(self): + """Returns a list of all trackers, sorted by round.""" + return sorted(self.expected_trackers() + self.unexpected_trackers(), + key=lambda x: x.round.seq) + + def num_submitted(self): + """Returns the number of feedbacks that were submitted, including + duplicate and unexpected submissions.""" + return len(self.submitted_feedback()) + + def num_expected(self): + """Returns the number of feedbacks that are expected from this participant.""" + return len(self.expected_trackers()) + + def num_fulfilled(self): + """Returns the number of feedbacks that are correctly submitted, + excluding those where more than one feedback was submitted but only + one was expected.""" + return len(self.fulfilled_trackers()) + + def num_unsubmitted(self): + return self.num_expected() - self.num_fulfilled() + + def coverage(self): + """Returns the number of fulfilled feedbacks divided by the number + of expected feedbacks.""" + if self.num_expected() == 0: + return 1.0 + return self.num_fulfilled() / self.num_expected() + + def _prefetch_tracker_acceptable_submissions(self, trackers, tracker_identifier, feedback_identifier): + trackers_by_identifier = {} + for tracker in trackers: + tracker._acceptable_submissions = [] + identifier = tracker_identifier(tracker) + trackers_by_identifier[identifier] = tracker + for feedback in self.submitted_feedback(): + identifier = feedback_identifier(feedback) + try: + tracker = trackers_by_identifier[identifier] + except KeyError: + continue + if feedback.adjudicator in tracker.acceptable_targets(): + tracker._acceptable_submissions.append(feedback) + + +class FeedbackProgressForTeam(BaseFeedbackProgress): + """Class to compute feedback submitted or owed by a team.""" + + def __init__(self, team, tournament=None): + self.team = team + if tournament is None: + tournament = team.tournament + self.enforce_orallist = tournament.pref("show_splitting_adjudicators") + super().__init__(tournament) + + @staticmethod + def _submitted_feedback_queryset_operations(queryset): + # this is also used by get_feedback_progress + return queryset.filter(confirmed=True, + source_team__debate__round__stage=Round.STAGE_PRELIMINARY).select_related( + 'adjudicator', 'adjudicator__institution', 'source_team__debate__round') + + def get_submitted_feedback(self): + queryset = AdjudicatorFeedback.objects.filter(source_team__team=self.team) + return self._submitted_feedback_queryset_operations(queryset) + + @staticmethod + def _debateteam_queryset_operations(queryset): + # this is also used by get_feedback_progress + debateteams = queryset.filter( + debate__ballotsubmission__confirmed=True, + debate__round__silent=False, + debate__round__stage=Round.STAGE_PRELIMINARY + ).select_related('debate', 'debate__round').prefetch_related( + 'debate__debateadjudicator_set__adjudicator') + populate_confirmed_ballots([dt.debate for dt in debateteams], ballotsets=True) + return debateteams + + def _get_debateteams(self): + if not hasattr(self, '_debateteams'): + self._debateteams = self._debateteam_queryset_operations(self.team.debateteam_set) + return self._debateteams + + def get_expected_trackers(self): + # There is one tracker for each debate for which there is a confirmed ballot, + # and the round is not silent. + + debateteams = self._get_debateteams() + trackers = [FeedbackExpectedSubmissionFromTeamTracker(dt, self.enforce_orallist) for dt in debateteams] + self._prefetch_tracker_acceptable_submissions(trackers, + attrgetter('source'), attrgetter('source_team')) + return trackers + + +class FeedbackProgressForAdjudicator(BaseFeedbackProgress): + """Class to compute feedback submitted or owed by an adjudicator.""" + + def __init__(self, adjudicator, tournament=None): + self.adjudicator = adjudicator + if tournament is None: + tournament = adjudicator.tournament + if tournament is None: + logger.warning("No tournament specified and adjudicator %s has no tournament", adjudicator) + else: + self.feedback_paths = tournament.pref('feedback_paths') + super().__init__(tournament) + + @staticmethod + def _submitted_feedback_queryset_operations(queryset): + # this is also used by get_feedback_progress + return queryset.filter(confirmed=True, + source_adjudicator__debate__round__stage=Round.STAGE_PRELIMINARY).select_related( + 'adjudicator', 'adjudicator__institution', 'source_adjudicator__debate__round') + + def get_submitted_feedback(self): + queryset = AdjudicatorFeedback.objects.filter(source_adjudicator__adjudicator=self.adjudicator) + return self._submitted_feedback_queryset_operations(queryset) + + @staticmethod + def _debateadjudicator_queryset_operations(queryset): + # this is also used by get_feedback_progress + return queryset.filter( + debate__ballotsubmission__confirmed=True, + debate__round__stage=Round.STAGE_PRELIMINARY + ).select_related('debate', 'debate__round').prefetch_related( + 'debate__debateadjudicator_set__adjudicator') + + def _get_debateadjudicators(self): + if not hasattr(self, '_debateadjudicators'): + self._debateadjudicators = self._debateadjudicator_queryset_operations(self.adjudicator.debateadjudicator_set) + return self._debateadjudicators + + def get_expected_trackers(self): + """Trackers are as follows: + - Chairs owe on everyone in their panel. + - Panellists owe on chairs if the relevant tournament preference is enabled. + """ + debateadjs = self._get_debateadjudicators() + + trackers = [] + for debateadj in debateadjs: + for target, _ in expected_feedback_targets(debateadj, self.feedback_paths): + trackers.append(FeedbackExpectedSubmissionFromAdjudicatorTracker(debateadj, target)) + + self._prefetch_tracker_acceptable_submissions(trackers, + attrgetter('source', 'target'), attrgetter('source_adjudicator', 'adjudicator')) + + return trackers + + +def get_feedback_progress(t): + """Returns a list of FeedbackProgressForTeam objects and a list of + FeedbackProgressForAdjudicator objects. + + This function pre-populates the FeedbackProgress objects to avoid needing + duplicate SQL queries for every team and adjudicator, so it should be used + for performance when the feedback progress of all teams and adjudicators is + needed.""" + + teams_progress = [] + adjs_progress = [] + + teams = t.team_set.prefetch_related('speaker_set').all() + + submitted_feedback_by_team_id = {team.id: [] for team in teams} + submitted_feedback_teams = AdjudicatorFeedback.objects.filter( + source_team__team__in=teams).select_related('source_team') + submitted_feedback_teams = FeedbackProgressForTeam._submitted_feedback_queryset_operations(submitted_feedback_teams) + for feedback in submitted_feedback_teams: + submitted_feedback_by_team_id[feedback.source_team.team_id].append(feedback) + + debateteams_by_team_id = {team.id: [] for team in teams} + debateteams = DebateTeam.objects.filter(team__in=teams) + debateteams = FeedbackProgressForTeam._debateteam_queryset_operations(debateteams) + for debateteam in debateteams: + debateteams_by_team_id[debateteam.team_id].append(debateteam) + + for team in teams: + progress = FeedbackProgressForTeam(team) + progress._submitted_feedback = submitted_feedback_by_team_id[team.id] + progress._debateteams = debateteams_by_team_id[team.id] + teams_progress.append(progress) + + adjudicators = t.adjudicator_set.all() + + submitted_feedback_by_adj_id = {adj.id: [] for adj in adjudicators} + submitted_feedback_adjs = AdjudicatorFeedback.objects.filter( + source_adjudicator__adjudicator__in=adjudicators).select_related('source_adjudicator') + submitted_feedback_adjs = FeedbackProgressForAdjudicator._submitted_feedback_queryset_operations(submitted_feedback_adjs) + for feedback in submitted_feedback_adjs: + submitted_feedback_by_adj_id[feedback.source_adjudicator.adjudicator_id].append(feedback) + + debateadjs_by_adj_id = {adj.id: [] for adj in adjudicators} + debateadjs = DebateAdjudicator.objects.filter(adjudicator__in=adjudicators) + debateadjs = FeedbackProgressForAdjudicator._debateadjudicator_queryset_operations(debateadjs) + for debateadj in debateadjs: + debateadjs_by_adj_id[debateadj.adjudicator_id].append(debateadj) + + for adj in adjudicators: + progress = FeedbackProgressForAdjudicator(adj) + progress._submitted_feedback = submitted_feedback_by_adj_id[adj.id] + progress._debateadjudicators = debateadjs_by_adj_id[adj.id] + adjs_progress.append(progress) + + return teams_progress, adjs_progress diff --git a/tabbycat/adjfeedback/tables.py b/tabbycat/adjfeedback/tables.py new file mode 100644 index 00000000000..290d666d9e7 --- /dev/null +++ b/tabbycat/adjfeedback/tables.py @@ -0,0 +1,157 @@ +import logging + +from utils.misc import reverse_tournament +from utils.tables import TabbycatTableBuilder + +from .progress import FeedbackProgressForAdjudicator, FeedbackProgressForTeam + +logger = logging.getLogger(__name__) + + +class FeedbackTableBuilder(TabbycatTableBuilder): + + def add_breaking_checkbox(self, adjudicators, key="Breaking"): + breaking_header = { + 'key': 'B', + 'icon': 'glyphicon-star', + 'tooltip': 'Whether the adj is marked as breaking (click to mark)', + } + breaking_data = [{ + 'text': '' % (adj.id, 'checked' if adj.breaking else ''), + 'sort': adj.breaking, + 'class': 'checkbox-target' + } for adj in adjudicators] + + self.add_column(breaking_header, breaking_data) + + def add_score_columns(self, adjudicators): + + feedback_weight = self.tournament.current_round.feedback_weight + scores = {adj: adj.weighted_score(feedback_weight) for adj in adjudicators} + + overall_header = { + 'key': 'Overall Score', + 'icon': 'glyphicon-signal', + 'tooltip': 'Current weighted score', + } + overall_data = [{ + 'text': '%0.1f' % scores[adj] if scores[adj] is not None else 'N/A', + 'tooltip': 'Current weighted average of all feedback', + } for adj in adjudicators] + self.add_column(overall_header, overall_data) + + test_header = { + 'key': 'Test Score', + 'icon': 'glyphicon-scale', + 'tooltip': 'Test score result', + } + test_data = [{ + 'text': '%0.1f' % adj.test_score if adj.test_score is not None else 'N/A', + 'modal': adj.id, + 'class': 'edit-test-score', + 'tooltip': 'Click to edit test score', + } for adj in adjudicators] + self.add_column(test_header, test_data) + + def add_feedback_graphs(self, adjudicators): + feedback_head = { + 'key': 'Feedback', + 'text': 'Feedback as  Chair ' + + '  Panellist ' + + '  Trainee ' + } + feedback_data = [{ + 'graphData': adj.feedback_data, + 'component': 'feedback-trend', + 'minScore': self.tournament.pref('adj_min_score'), + 'maxScore': self.tournament.pref('adj_max_score'), + 'roundSeq': len(self.tournament.prelim_rounds()), + } for adj in adjudicators] + self.add_column(feedback_head, feedback_data) + + def add_feedback_link_columns(self, adjudicators): + link_head = { + 'key': 'VF', + 'icon': 'glyphicon-question-sign' + } + link_cell = [{ + 'text': 'View
    Feedback', + 'class': 'view-feedback', + 'link': reverse_tournament('adjfeedback-view-on-adjudicator', self.tournament, kwargs={'pk': adj.pk}) + } for adj in adjudicators] + self.add_column(link_head, link_cell) + + def add_feedback_misc_columns(self, adjudicators): + if self.tournament.pref('enable_adj_notes'): + note_head = { + 'key': 'NO', + 'icon': 'glyphicon-list-alt' + } + note_cell = [{ + 'text': 'Edit
    Note', + 'class': 'edit-note', + 'modal': str(adj.id) + '===' + str(adj.notes) + } for adj in adjudicators] + self.add_column(note_head, note_cell) + + adjudications_head = { + 'key': 'DD', + 'icon': 'glyphicon-eye-open', + 'tooltip': 'Debates adjudicated' + } + adjudications_cell = [{'text': adj.debates} for adj in adjudicators] + self.add_column(adjudications_head, adjudications_cell) + + avgs_head = { + 'key': 'AVGS', + 'icon': 'glyphicon-resize-full', + 'tooltip': 'Average Margin (top) and Average Score (bottom)' + } + avgs_cell = [{ + 'text': "%0.1f
    %0.1f" % (adj.avg_margin if adj.avg_margin else 0, adj.avg_score if adj.avg_margin else 0), + 'tooltip': 'Average Margin (top) and Average Score (bottom)' + } for adj in adjudicators] + self.add_column(avgs_head, avgs_cell) + + def add_feedback_progress_columns(self, progress_list, key="P"): + + def _owed_cell(progress): + owed = progress.num_unsubmitted() + cell = { + 'text': owed, + 'sort': owed, + 'class': 'text-danger strong' if owed > 0 else 'text-success' + } + return cell + + owed_header = { + 'key': 'Owed', + 'icon': 'glyphicon-remove', + 'tooltip': 'Unsubmitted feedback ballots', + } + owed_data = [_owed_cell(progress) for progress in progress_list] + self.add_column(owed_header, owed_data) + + if self._show_record_links: + + def _record_link(progress): + if isinstance(progress, FeedbackProgressForTeam): + url_name = 'participants-team-record' if self.admin else 'participants-public-team-record' + pk = progress.team.pk + elif isinstance(progress, FeedbackProgressForAdjudicator): + url_name = 'participants-adjudicator-record' if self.admin else 'participants-public-adjudicator-record' + pk = progress.adjudicator.pk + else: + logger.error("Unrecognised progress type: %s", progress.__class__.__name__) + return '' + return reverse_tournament(url_name, self.tournament, kwargs={'pk': pk}) + + owed_link_header = { + 'key': 'Submitted', + 'icon': 'glyphicon-question-sign', + } + owed_link_data = [{ + 'text': 'View Missing Feedback', + 'link': _record_link(progress) + } for progress in progress_list] + self.add_column(owed_link_header, owed_link_data) diff --git a/adjfeedback/templates/add_feedback.html b/tabbycat/adjfeedback/templates/add_feedback.html similarity index 65% rename from adjfeedback/templates/add_feedback.html rename to tabbycat/adjfeedback/templates/add_feedback.html index 5b22a678e33..c35011512c7 100644 --- a/adjfeedback/templates/add_feedback.html +++ b/tabbycat/adjfeedback/templates/add_feedback.html @@ -1,24 +1,16 @@ -{% extends "base.html" %} +{% extends "feedback_base.html" %} {% load debate_tags %} +{% load static %} {% block head-title %}Who is the feedback from?{% endblock %} {% block page-title %}Enter Feedback{% endblock %} -{% block page-subnav-sections %} - - {% include "tables/table_search.html" %} -{% endblock %} - {% block content %}
    -

    From a Team

    +

    From a Team

    @@ -53,7 +45,7 @@

    From a Team

    -

    From an Adjudicator

    +

    From an Adjudicator

    @@ -88,23 +80,3 @@

    From an Adjudicator

    {% endblock content %} - -{% block extra-js %} - {{ block.super }} - -{% endblock extra-js %} diff --git a/adjfeedback/templates/assistant_add_feedback.html b/tabbycat/adjfeedback/templates/assistant_add_feedback.html similarity index 62% rename from adjfeedback/templates/assistant_add_feedback.html rename to tabbycat/adjfeedback/templates/assistant_add_feedback.html index 96e76fcb150..462b17b5d02 100644 --- a/adjfeedback/templates/assistant_add_feedback.html +++ b/tabbycat/adjfeedback/templates/assistant_add_feedback.html @@ -3,6 +3,4 @@ {% block head-title %}Who is the feedback from?{% endblock %} {% block page-title %}Enter Feedback{% endblock %} -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} +{% block page-subnav-actions %}{% endblock %} diff --git a/adjfeedback/templates/enter_feedback.html b/tabbycat/adjfeedback/templates/enter_feedback.html similarity index 93% rename from adjfeedback/templates/enter_feedback.html rename to tabbycat/adjfeedback/templates/enter_feedback.html index 660f2702c93..c60a8385c1a 100644 --- a/adjfeedback/templates/enter_feedback.html +++ b/tabbycat/adjfeedback/templates/enter_feedback.html @@ -22,6 +22,9 @@
    + {% if pref.feedback_introduction %} +

    {{ pref.feedback_introduction|safe }}

    + {% endif %}
    {% csrf_token %} {% for field in form %} diff --git a/tabbycat/adjfeedback/templates/feedback_base.html b/tabbycat/adjfeedback/templates/feedback_base.html new file mode 100644 index 00000000000..e47d22cdf46 --- /dev/null +++ b/tabbycat/adjfeedback/templates/feedback_base.html @@ -0,0 +1,31 @@ +{% extends "base_vue_table.html" %} +{% load debate_tags %} + +{% block page-subnav-sections %} + + Overview + + + Latest + + + Find by Source + + + Find by Target + + {% if pref.public_ballots_randomised or pref.public_feedback_randomised or pref.allocation_confirmations %} + + Randomised URLs + + {% endif %} + + Unsubmitted Feedback + +{% endblock %} + +{% block page-subnav-actions %} + + Add Feedback + +{% endblock %} diff --git a/adjfeedback/templates/feedback_by_source.html b/tabbycat/adjfeedback/templates/feedback_by_source.html similarity index 72% rename from adjfeedback/templates/feedback_by_source.html rename to tabbycat/adjfeedback/templates/feedback_by_source.html index ca2863dcfbc..f454cb934df 100644 --- a/adjfeedback/templates/feedback_by_source.html +++ b/tabbycat/adjfeedback/templates/feedback_by_source.html @@ -1,8 +1,8 @@ {% extends "base.html" %} {% load debate_tags %} -{% block head-title %}Feedback from {{ source_name }}{% endblock %} -{% block page-title %}Feedback from {{ source_name }}{% endblock %} +{% block head-title %}Feedback {{ source_type }} {{ source_name }}{% endblock %} +{% block page-title %}Feedback {{ source_type }} {{ source_name }}{% endblock %} {% block page-subnav-sections %}{% endblock %} {% block content %} @@ -11,9 +11,7 @@ {% for feedback in feedbacks %}
    - {% include 'feedback_card.html' %} -
    {% if forloop.counter|divisibleby:3 %} @@ -27,7 +25,3 @@
    {% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/adjfeedback/templates/feedback_card.html b/tabbycat/adjfeedback/templates/feedback_card.html similarity index 97% rename from adjfeedback/templates/feedback_card.html rename to tabbycat/adjfeedback/templates/feedback_card.html index 1313f348d16..70018481e35 100644 --- a/adjfeedback/templates/feedback_card.html +++ b/tabbycat/adjfeedback/templates/feedback_card.html @@ -8,18 +8,18 @@ {% endif %}"> {{ feedback.score }} - {{ feedback.adjudicator.name }} + On {{ feedback.adjudicator.name }} ({{ feedback.adjudicator.institution.code }}{% if feedback.debate_adjudicator %}, {{ feedback.debate_adjudicator.get_type_display }}{% endif %}) {% for item in feedback.items %}
  • {% if item.question.answer_type == 'bc' or item.question.answer_type == 'bs' %} - {{ item.question.reference }} + {% elif item.question.answer_type == 'f' %} - {{ item.answer|floatformat:"2" }} {{ item.question.text }} + {{ item.answer|floatformat:"2" }} {% elif item.question.answer_type == 'tl' %} {{ item.answer }} {% else %} diff --git a/tabbycat/adjfeedback/templates/feedback_latest.html b/tabbycat/adjfeedback/templates/feedback_latest.html new file mode 100644 index 00000000000..d06359534ab --- /dev/null +++ b/tabbycat/adjfeedback/templates/feedback_latest.html @@ -0,0 +1,24 @@ +{% extends "feedback_base.html" %} +{% load debate_tags %} + +{% block head-title %}Latest Feedback{% endblock %} +{% block page-title %}Latest Feedback{% endblock %} + +{% block content %} +
    + {% for feedback in feedbacks %} + +
    + {% include 'feedback_card.html' %} +
    + + {% if forloop.counter|divisibleby:3 %} +
    + {% endif %} + + {% empty %} +
    No feedback has been submitted yet.
    + + {% endfor %} +
    +{% endblock content %} diff --git a/tabbycat/adjfeedback/templates/feedback_overview.html b/tabbycat/adjfeedback/templates/feedback_overview.html new file mode 100644 index 00000000000..63ded4744be --- /dev/null +++ b/tabbycat/adjfeedback/templates/feedback_overview.html @@ -0,0 +1,129 @@ +{% extends "feedback_base.html" %} +{% load debate_tags %} +{% load static %} + +{% block sub-title %}{{ breaking_count }} marked as breaking{% endblock %} +{% block body-id %}feedbackOverview{% endblock %} + +{% block content %} + + + + {% if pref.enable_adj_notes > 0 %} + + {% endif %} + + {{ block.super }} + +{% endblock %} + +{% block js %} + + {{ block.super }} + + + +{% endblock js %} diff --git a/adjfeedback/templates/public_add_feedback.html b/tabbycat/adjfeedback/templates/public_add_feedback.html similarity index 86% rename from adjfeedback/templates/public_add_feedback.html rename to tabbycat/adjfeedback/templates/public_add_feedback.html index 62ce140a0fd..f4b683043ca 100644 --- a/adjfeedback/templates/public_add_feedback.html +++ b/tabbycat/adjfeedback/templates/public_add_feedback.html @@ -4,10 +4,8 @@ {% block head-title %}Who are you?{% endblock %} {% block sub-title %}click your name or your team on this list{% endblock %} -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} -{% endblock %} - +{% block page-subnav-sections %}{% endblock %} +{% block page-subnav-actions %}{% endblock %} {% block page-alerts %}{% endblock %} {% block enter-feedback-adj-link %} diff --git a/availability/__init__.py b/tabbycat/adjfeedback/tests/__init__.py similarity index 100% rename from availability/__init__.py rename to tabbycat/adjfeedback/tests/__init__.py diff --git a/tabbycat/adjfeedback/tests/test_progress.py b/tabbycat/adjfeedback/tests/test_progress.py new file mode 100644 index 00000000000..05b67083d08 --- /dev/null +++ b/tabbycat/adjfeedback/tests/test_progress.py @@ -0,0 +1,403 @@ +import logging + +from django.test import TestCase + +from adjallocation.models import DebateAdjudicator +from adjfeedback.models import AdjudicatorFeedback +from draw.models import Debate, DebateTeam +from participants.models import Adjudicator, Institution, Speaker, Team +from results.models import BallotSubmission +from results.result import BallotSet +from tournaments.models import Round, Tournament +from venues.models import Venue + +from ..progress import FeedbackExpectedSubmissionFromAdjudicatorTracker, FeedbackExpectedSubmissionFromTeamTracker +from ..progress import FeedbackProgressForAdjudicator, FeedbackProgressForTeam + + +class TestFeedbackProgress(TestCase): + + NUM_TEAMS = 6 + NUM_ADJS = 7 + NUM_VENUES = 3 + + def setUp(self): + self.t = Tournament.objects.create() + for i in range(self.NUM_TEAMS): + inst = Institution.objects.create(code=i, name=i) + team = Team.objects.create(tournament=self.t, institution=inst, reference=i) + for j in range(3): + Speaker.objects.create(team=team, name="%d-%d" % (i, j)) + + adjsinst = Institution.objects.create(code="Adjs", name="Adjudicators") + for i in range(self.NUM_ADJS): + Adjudicator.objects.create(tournament=self.t, institution=adjsinst, name=i) + for i in range(self.NUM_VENUES): + Venue.objects.create(name=i, priority=i) + + self.rd = Round.objects.create(tournament=self.t, seq=1, abbreviation="R1") + + def tearDown(self): + self.t.delete() + Institution.objects.all().delete() + Venue.objects.all().delete() + + def _team(self, t): + return Team.objects.get(tournament=self.t, reference=t) + + def _adj(self, a): + return Adjudicator.objects.get(tournament=self.t, name=a) + + def _dt(self, debate, t): + return DebateTeam.objects.get(debate=debate, team=self._team(t)) + + def _da(self, debate, a): + return DebateAdjudicator.objects.get(debate=debate, adjudicator=self._adj(a)) + + def _create_debate(self, teams, adjs, votes, trainees=[], venue=None): + """Enters a debate into the database, using the teams and adjudicators specified. + `votes` should be a string (or iterable of characters) indicating "a" for affirmative or + "n" for negative, e.g. "ann" if the chair was rolled in a decision for the negative. + The method will give the winning team all 76s and the losing team all 74s. + The first adjudicator is the chair; the rest are panellists.""" + + if venue is None: + venue = Venue.objects.first() + debate = Debate.objects.create(round=self.rd, venue=venue) + + aff, neg = teams + aff_team = self._team(aff) + DebateTeam.objects.create(debate=debate, team=aff_team, position=DebateTeam.POSITION_AFFIRMATIVE) + neg_team = self._team(neg) + DebateTeam.objects.create(debate=debate, team=neg_team, position=DebateTeam.POSITION_NEGATIVE) + + chair = self._adj(adjs[0]) + DebateAdjudicator.objects.create(debate=debate, adjudicator=chair, + type=DebateAdjudicator.TYPE_CHAIR) + for p in adjs[1:]: + panellist = self._adj(p) + DebateAdjudicator.objects.create(debate=debate, adjudicator=panellist, + type=DebateAdjudicator.TYPE_PANEL) + for tr in trainees: + trainee = self._adj(tr) + DebateAdjudicator.objects.create(debate=debate, adjudicator=trainee, + type=DebateAdjudicator.TYPE_TRAINEE) + + ballotsub = BallotSubmission(debate=debate, submitter_type=BallotSubmission.SUBMITTER_TABROOM) + ballotset = BallotSet(ballotsub) + + for t in teams: + team = self._team(t) + speakers = team.speaker_set.all() + for pos, speaker in enumerate(speakers, start=1): + ballotset.set_speaker(team, pos, speaker) + ballotset.set_speaker(team, 4, speakers[0]) + + for a, vote in zip(adjs, votes): + adj = self._adj(a) + if vote == 'a': + teams = [aff_team, neg_team] + elif vote == 'n': + teams = [neg_team, aff_team] + else: + raise ValueError + for team, score in zip(teams, (76, 74)): + for pos in range(1, 4): + ballotset.set_score(adj, team, pos, score) + ballotset.set_score(adj, team, 4, score / 2) + + ballotset.confirmed = True + ballotset.save() + + return debate + + def _create_feedback(self, source, target): + if isinstance(source, DebateTeam): + source_kwargs = dict(source_team=source) + else: + source_kwargs = dict(source_adjudicator=source) + target_adj = self._adj(target) + return AdjudicatorFeedback.objects.create(confirmed=True, adjudicator=target_adj, score=3, + **source_kwargs) + + # ========================================================================== + # From team + # ========================================================================== + + def assertExpectedFromTeamTracker(self, debate, t, expected, fulfilled, count, submissions, targets, tracker_kwargs={}): # noqa + tracker = FeedbackExpectedSubmissionFromTeamTracker(self._dt(debate, t), **tracker_kwargs) + self.assertIs(tracker.expected, expected) + self.assertIs(tracker.fulfilled, fulfilled) + self.assertEqual(tracker.count, count) + self.assertCountEqual(tracker.acceptable_submissions(), submissions) + self.assertCountEqual(tracker.acceptable_targets(), [self._adj(a) for a in targets]) + + def test_chair_oral_no_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "aan") + for t in (0, 1): + self.assertExpectedFromTeamTracker(debate, t, True, False, 0, [], [0]) + + def test_chair_oral_good_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "aan") + for t in (0, 1): + feedback = self._create_feedback(self._dt(debate, t), 0) + self.assertExpectedFromTeamTracker(debate, t, True, True, 1, [feedback], [0]) + + def test_chair_oral_bad_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "aan") + for t in (0, 1): + feedback = self._create_feedback(self._dt(debate, t), 1) + self.assertExpectedFromTeamTracker(debate, t, True, False, 0, [], [0]) + self.assertExpectedFromTeamTracker(debate, t, True, True, 1, [feedback], [0, 1, 2], {'enforce_orallist': False}) + + def test_chair_oral_multiple_submissions(self): + debate = self._create_debate((0, 1), (0, 1, 2), "aan") + for t in (0, 1): + feedback1 = self._create_feedback(self._dt(debate, t), 0) + feedback2 = self._create_feedback(self._dt(debate, t), 1) + # The submission on adj 1 is irrelevant, so shouldn't appear at all. + # (It should appear as "unexpected" in the FeedbackProgressForTeam.) + self.assertExpectedFromTeamTracker(debate, t, True, True, 1, [feedback1], [0]) + # If the orallist is not enforced, though, both submissions are relevant. + self.assertExpectedFromTeamTracker(debate, t, True, False, 2, [feedback1, feedback2], [0, 1, 2], {'enforce_orallist': False}) + + def test_chair_rolled_no_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "ann") + for t in (0, 1): + self.assertExpectedFromTeamTracker(debate, t, True, False, 0, [], [1, 2]) + + def test_chair_rolled_good_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "ann") + for t in (0, 1): + feedback = self._create_feedback(self._dt(debate, t), 1) + self.assertExpectedFromTeamTracker(debate, t, True, True, 1, [feedback], [1, 2]) + + def test_chair_rolled_bad_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "ann") + for t in (0, 1): + feedback = self._create_feedback(self._dt(debate, t), 0) + self.assertExpectedFromTeamTracker(debate, t, True, False, 0, [], [1, 2]) + self.assertExpectedFromTeamTracker(debate, t, True, True, 1, [feedback], [0, 1, 2], {'enforce_orallist': False}) + + def test_chair_rolled_multiple_submissions(self): + debate = self._create_debate((0, 1), (0, 1, 2), "ann") + for t in (0, 1): + feedback1 = self._create_feedback(self._dt(debate, t), 1) + feedback2 = self._create_feedback(self._dt(debate, t), 2) + self.assertExpectedFromTeamTracker(debate, t, True, False, 2, [feedback1, feedback2], [1, 2]) + + def test_sole_adjudicator_no_submissions(self): + debate = self._create_debate((0, 1), (0,), "n") + for t in (0, 1): + self.assertExpectedFromTeamTracker(debate, t, True, False, 0, [], [0]) + + def test_sole_adjudicator_good_submission(self): + debate = self._create_debate((0, 1), (0,), "n") + for t in (0, 1): + feedback = self._create_feedback(self._dt(debate, t), 0) + self.assertExpectedFromTeamTracker(debate, t, True, True, 1, [feedback], [0]) + + def test_sole_adjudicator_bad_submission(self): + debate = self._create_debate((0, 1), (0,), "n") + for t in (0, 1): + self._create_feedback(self._dt(debate, t), 3) + self.assertExpectedFromTeamTracker(debate, t, True, False, 0, [], [0]) + + def test_sole_adjudicator_multiple_submissions(self): + debate = self._create_debate((0, 1), (0,), "n") + for t in (0, 1): + feedback1 = self._create_feedback(self._dt(debate, t), 0) + self._create_feedback(self._dt(debate, t), 3) + self._create_feedback(self._dt(debate, t), 4) + # The submissions on adjs 3 and 4 are irrelevant, so shouldn't appear at all. + # (They should appear as "unexpected" in the FeedbackProgressForTeam.) + self.assertExpectedFromTeamTracker(debate, t, True, True, 1, [feedback1], [0]) + self.assertExpectedFromTeamTracker(debate, t, True, True, 1, [feedback1], [0], {'enforce_orallist': False}) + + # ========================================================================== + # From adjudicator + # ========================================================================== + + def assertExpectedFromAdjudicatorTracker(self, debate, source, target, expected, fulfilled, count, submissions): # noqa + tracker = FeedbackExpectedSubmissionFromAdjudicatorTracker(self._da(debate, source), self._adj(target)) + self.assertIs(tracker.expected, expected) + self.assertIs(tracker.fulfilled, fulfilled) + self.assertEqual(tracker.count, count) + self.assertCountEqual(tracker.acceptable_submissions(), submissions) + self.assertCountEqual(tracker.acceptable_targets(), [self._adj(target)]) + + def test_adj_on_adj_no_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "aan") + for a in (1, 2): + self.assertExpectedFromAdjudicatorTracker(debate, 0, a, True, False, 0, []) + + def test_adj_on_adj_good_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "aan") + for a in (1, 2): + feedback = self._create_feedback(self._da(debate, 0), a) + self.assertExpectedFromAdjudicatorTracker(debate, 0, a, True, True, 1, [feedback]) + + def test_adj_on_adj_bad_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "aan") + for a in (1, 2): + self._create_feedback(self._da(debate, 0), a+2) + self.assertExpectedFromAdjudicatorTracker(debate, 0, a, True, False, 0, []) + + def test_adj_on_adj_multiple_submission(self): + debate = self._create_debate((0, 1), (0, 1, 2), "aan") + for a in (1, 2): + logging.disable(logging.WARNING) + self._create_feedback(self._da(debate, 0), a) + feedback2 = self._create_feedback(self._da(debate, 0), a) + logging.disable(logging.NOTSET) + self.assertExpectedFromAdjudicatorTracker(debate, 0, a, True, True, 1, [feedback2]) + + def test_adj_on_adj_trainees_not_submitted(self): + debate = self._create_debate((0, 1), (0,), "n", trainees=[4]) + self.assertExpectedFromAdjudicatorTracker(debate, 0, 4, True, False, 0, []) + + def test_adj_on_adj_trainees_submitted(self): + debate = self._create_debate((0, 1), (0, 1, 2), "nan", trainees=[4]) + feedback = self._create_feedback(self._da(debate, 0), 4) + self.assertExpectedFromAdjudicatorTracker(debate, 0, 4, True, True, 1, [feedback]) + + # ========================================================================== + # Team progress + # ========================================================================== + + def _create_team_progress_dataset(self, adj1, adj2, adj3): + debate1 = self._create_debate((0, 1), (0, 1, 2), "nnn") + debate2 = self._create_debate((0, 2), (3, 4, 5), "ann") + debate3 = self._create_debate((0, 3), (6,), "a") + if adj1 is not None: + self._create_feedback(self._dt(debate1, 0), adj1) + if adj2 is not None: + self._create_feedback(self._dt(debate2, 0), adj2) + if adj3 is not None: + self._create_feedback(self._dt(debate3, 0), adj3) + + def assertTeamProgress(self, show_splits, t, submitted, expected, fulfilled, unsubmitted, coverage): # noqa + self.t.preferences['ui_options__show_splitting_adjudicators'] = show_splits + progress = FeedbackProgressForTeam(self._team(t)) + self.assertEqual(progress.num_submitted(), submitted) + self.assertEqual(progress.num_expected(), expected) + self.assertEqual(progress.num_fulfilled(), fulfilled) + self.assertEqual(progress.num_unsubmitted(), unsubmitted) + self.assertAlmostEqual(progress.coverage(), coverage) + return progress + + def test_team_progress_all_good(self): + self._create_team_progress_dataset(0, 4, 6) + self.assertTeamProgress(True, 0, 3, 3, 3, 0, 1.0) + self.assertTeamProgress(False, 0, 3, 3, 3, 0, 1.0) + + def test_team_progress_no_submissions(self): + self._create_team_progress_dataset(None, None, None) + self.assertTeamProgress(True, 0, 0, 3, 0, 3, 0.0) + self.assertTeamProgress(False, 0, 0, 3, 0, 3, 0.0) + + def test_team_progress_no_debates(self): + FeedbackProgressForTeam(self._team(4)) + self.assertTeamProgress(True, 4, 0, 0, 0, 0, 1.0) + + def test_team_progress_missing_submission(self): + self._create_team_progress_dataset(0, None, 6) + self.assertTeamProgress(True, 0, 2, 3, 2, 1, 2/3) + self.assertTeamProgress(False, 0, 2, 3, 2, 1, 2/3) + + def test_team_progress_wrong_target_on_unanimous(self): + self._create_team_progress_dataset(2, 4, 6) + progress = self.assertTeamProgress(True, 0, 3, 3, 2, 1, 2/3) + self.assertEqual(len(progress.unexpected_trackers()), 1) + progress = self.assertTeamProgress(False, 0, 3, 3, 3, 0, 1.0) + self.assertEqual(len(progress.unexpected_trackers()), 0) + + def test_team_progress_wrong_target_on_rolled_chair(self): + self._create_team_progress_dataset(0, 3, 6) + progress = self.assertTeamProgress(True, 0, 3, 3, 2, 1, 2/3) + self.assertEqual(len(progress.unexpected_trackers()), 1) + progress = self.assertTeamProgress(False, 0, 3, 3, 3, 0, 1.0) + self.assertEqual(len(progress.unexpected_trackers()), 0) + + def test_team_progress_unexpected(self): + self._create_team_progress_dataset(5, 3, None) + progress = self.assertTeamProgress(True, 0, 2, 3, 0, 3, 0.0) + self.assertEqual(len(progress.unexpected_trackers()), 2) + + self.t.preferences['feedback__show_unexpected_feedback'] = False + progress = self.assertTeamProgress(True, 0, 2, 3, 0, 3, 0.0) + self.assertEqual(len(progress.unexpected_trackers()), 0) + + # ========================================================================== + # Adjudicator progress + # ========================================================================== + + def _create_adjudicator_progress_dataset(self, adjs1, adjs2, adjs3): + debate1 = self._create_debate((0, 1), (0, 1, 2), "nnn") + debate2 = self._create_debate((2, 3), (3, 0, 4), "ann") + debate3 = self._create_debate((4, 0), (0,), "a") + for adj in adjs1: + self._create_feedback(self._da(debate1, 0), adj) + for adj in adjs2: + self._create_feedback(self._da(debate2, 0), adj) + for adj in adjs3: + self._create_feedback(self._da(debate3, 0), adj) + + def assertAdjudicatorProgress(self, feedback_paths, a, submitted, expected, fulfilled, unsubmitted, coverage): # noqa + self.t.preferences['feedback__feedback_paths'] = feedback_paths + progress = FeedbackProgressForAdjudicator(self._adj(a)) + self.assertEqual(progress.num_submitted(), submitted) + self.assertEqual(progress.num_expected(), expected) + self.assertEqual(progress.num_fulfilled(), fulfilled) + self.assertEqual(progress.num_unsubmitted(), unsubmitted) + self.assertAlmostEqual(progress.coverage(), coverage) + return progress + + def test_adjudicator_progress_all_good(self): + self._create_adjudicator_progress_dataset([1, 2], [3, 4], []) + self.assertAdjudicatorProgress('minimal', 0, 4, 2, 2, 0, 1.0) + self.assertAdjudicatorProgress('with-p-on-c', 0, 4, 3, 3, 0, 1.0) + self.assertAdjudicatorProgress('all-adjs', 0, 4, 4, 4, 0, 1.0) + + def test_adjudicator_progress_missing_p_on_p(self): + self._create_adjudicator_progress_dataset([1, 2], [3], []) + self.assertAdjudicatorProgress('minimal', 0, 3, 2, 2, 0, 1.0) + self.assertAdjudicatorProgress('with-p-on-c', 0, 3, 3, 3, 0, 1.0) + self.assertAdjudicatorProgress('all-adjs', 0, 3, 4, 3, 1, 3/4) + + def test_adjudicator_progress_no_submissions(self): + self._create_adjudicator_progress_dataset([], [], []) + self.assertAdjudicatorProgress('minimal', 0, 0, 2, 0, 2, 0.0) + self.assertAdjudicatorProgress('with-p-on-c', 0, 0, 3, 0, 3, 0.0) + self.assertAdjudicatorProgress('all-adjs', 0, 0, 4, 0, 4, 0.0) + + def test_adjudicator_progress_no_debates(self): + FeedbackProgressForAdjudicator(self._adj(5)) + self.assertAdjudicatorProgress('minimal', 5, 0, 0, 0, 0, 1.0) + self.assertAdjudicatorProgress('with-p-on-c', 5, 0, 0, 0, 0, 1.0) + self.assertAdjudicatorProgress('all-adjs', 5, 0, 0, 0, 0, 1.0) + + def test_adjudicator_progress_missing_submission(self): + self._create_adjudicator_progress_dataset([1], [3], []) + self.assertAdjudicatorProgress('minimal', 0, 2, 2, 1, 1, 1/2) + self.assertAdjudicatorProgress('with-p-on-c', 0, 2, 3, 2, 1, 2/3) + self.assertAdjudicatorProgress('all-adjs', 0, 2, 4, 2, 2, 1/2) + + def test_adjudicator_progress_wrong_target(self): + self._create_adjudicator_progress_dataset([1, 2], [4], []) + progress = self.assertAdjudicatorProgress('with-p-on-c', 0, 3, 3, 2, 1, 2/3) + self.assertEqual(len(progress.unexpected_trackers()), 1) + + def test_adjudicator_progress_extra_target(self): + self._create_adjudicator_progress_dataset([1, 2], [3, 4], []) + progress = self.assertAdjudicatorProgress('with-p-on-c', 0, 4, 3, 3, 0, 1.0) + self.assertEqual(len(progress.unexpected_trackers()), 1) + + def test_adjudicator_progress_unexpected(self): + self._create_adjudicator_progress_dataset([5], [1], [2]) + progress = self.assertAdjudicatorProgress('with-p-on-c', 0, 3, 3, 0, 3, 0.0) + self.assertEqual(len(progress.unexpected_trackers()), 3) + + self.t.preferences['feedback__show_unexpected_feedback'] = False + progress = self.assertAdjudicatorProgress('with-p-on-c', 0, 3, 3, 0, 3, 0.0) + self.assertEqual(len(progress.unexpected_trackers()), 0) diff --git a/adjfeedback/urls_admin.py b/tabbycat/adjfeedback/urls_admin.py similarity index 66% rename from adjfeedback/urls_admin.py rename to tabbycat/adjfeedback/urls_admin.py index 1cae06a7c67..a4754cb9fd1 100644 --- a/adjfeedback/urls_admin.py +++ b/tabbycat/adjfeedback/urls_admin.py @@ -1,24 +1,19 @@ from django.conf.urls import url +from participants.models import Adjudicator, Team + from . import views -from participants.models import Team, Adjudicator urlpatterns = [ # Overviews url(r'^$', - views.feedback_overview, + views.FeedbackOverview.as_view(), name='adjfeedback-overview'), url(r'^progress/$', - views.feedback_progress, + views.FeedbackProgress.as_view(), name='feedback_progress'), # Getting/setting values - url(r'^scores/all/$', - views.adj_scores, - name='adj_scores'), - url(r'^scores/get/$', - views.get_adj_feedback, - name='get_adj_feedback'), url(r'^test/set/$', views.SetAdjudicatorTestScoreView.as_view(), name='adjfeedback-set-adj-test-score'), @@ -28,6 +23,13 @@ url(r'^notes/test/set/$', views.SetAdjudicatorNoteView.as_view(), name='adjfeedback-set-adj-note'), + # Only used in old allocation screen; TODO: deprecate + url(r'^scores/all/$', + views.GetAdjScores.as_view(), + name='adj_scores'), + url(r'^feedback/get/$', + views.GetAdjFeedback.as_view(), + name='get_adj_feedback'), # Source url(r'^latest/$', @@ -42,6 +44,15 @@ url(r'^source/adjudicator/(?P\d+)/$', views.FeedbackFromAdjudicatorView.as_view(), name='adjfeedback-view-from-adjudicator'), + url(r'^target/list/$', + views.FeedbackByTargetView.as_view(), + name='adjfeedback-view-by-target'), + url(r'^target/adjudicator/(?P\d+)/$', + views.FeedbackOnAdjudicatorView.as_view(), + name='adjfeedback-view-on-adjudicator'), + url(r'^target/adjudicator/json/(?P\d+)/$', + views.GetAdjFeedbackJSON.as_view(), + name='get_adj_feedback_json'), # Adding url(r'^add/$', @@ -61,4 +72,10 @@ url(r'^randomised_urls/generate/$', views.GenerateRandomisedUrlsView.as_view(), name='randomised-urls-generate'), + url(r'^randomised_urls/emails/list/$', + views.EmailRandomisedUrlsView.as_view(), + name='randomised-urls-email'), + url(r'^randomised_urls/emails/confirm/$', + views.ConfirmEmailRandomisedUrlsView.as_view(), + name='confirm-feedback-urls-send'), ] diff --git a/adjfeedback/urls_public.py b/tabbycat/adjfeedback/urls_public.py similarity index 91% rename from adjfeedback/urls_public.py rename to tabbycat/adjfeedback/urls_public.py index e91fd6d3d11..d1eca568b92 100644 --- a/adjfeedback/urls_public.py +++ b/tabbycat/adjfeedback/urls_public.py @@ -1,11 +1,13 @@ from django.conf.urls import url -from participants.models import Team, Adjudicator + +from participants.models import Adjudicator, Team + from . import views urlpatterns = [ # Overviews url(r'^feedback_progress/$', - views.public_feedback_progress, + views.PublicFeedbackProgress.as_view(), name='public_feedback_progress'), # Submission via Public Form diff --git a/tabbycat/adjfeedback/utils.py b/tabbycat/adjfeedback/utils.py new file mode 100644 index 00000000000..eb94a843571 --- /dev/null +++ b/tabbycat/adjfeedback/utils.py @@ -0,0 +1,186 @@ +import logging + +from django.core.exceptions import ObjectDoesNotExist + +from adjallocation.allocation import AdjudicatorAllocation +from adjallocation.models import DebateAdjudicator +from adjfeedback.models import AdjudicatorFeedback +from results.models import SpeakerScoreByAdj + +logger = logging.getLogger(__name__) + + +def expected_feedback_targets(debateadj, feedback_paths=None, debate=None): + """Returns a list of adjudicators and positions (adj, pos), each being + someone that the given DebateAdjudicator object is expected to give feedback + on. If the debate adjudicator's position and the tournament preferences + dictate that the source adjudicator should not submit feedback on anyone for + this debate, then it returns an empty list. + + Each element of the returned list is a 2-tuple `(adj, pos)`, where `adj` is + an Adjudicator instance and `pos` is an AdjudicatorAllocation.POSITION_* + constant. DebateAdjudicator instances are not returned by this function; in + fact, the use of DebateAdjudicator instances for feedback targets is in + general discouraged, since feedback targets are Adjudicator instances, not + DebateAdjudicator instances. + + `feedback_paths` can be used to avoid unnecessary tournament lookups, + and should be one of the available options in + options.dynamic_preferences_registry.FeedbackPaths.choices. + + `debate` can be used to avoid unnecessary database hits populating + AdjudicatorAllocation, and should be equal to debateadj.debate. + """ + + if feedback_paths is None: + feedback_paths = debateadj.debate.round.tournament.pref('feedback_paths') + if debate is None: + debate = debateadj.debate + adjudicators = debate.adjudicators + + if feedback_paths == 'all-adjs' or debateadj.type == DebateAdjudicator.TYPE_CHAIR: + targets = [(adj, pos) for adj, pos in adjudicators.with_positions() if adj.id != debateadj.adjudicator_id] + elif feedback_paths == 'with-p-on-c' and debateadj.type == DebateAdjudicator.TYPE_PANEL: + targets = [(adjudicators.chair, AdjudicatorAllocation.POSITION_CHAIR)] + else: + targets = [] + + if feedback_paths not in ['all-adjs', 'with-p-on-c', 'minimal']: + logger.error("Unrecognised preference: %s", feedback_paths) + + return targets + + +def get_feedback_overview(t, adjudicators): + + all_debate_adjudicators = list(DebateAdjudicator.objects.all().select_related( + 'adjudicator')) + all_adj_feedbacks = list(AdjudicatorFeedback.objects.filter(confirmed=True).select_related( + 'adjudicator', 'source_adjudicator', 'source_team', + 'source_adjudicator__debate__round', 'source_team__debate__round').exclude( + source_adjudicator__type=DebateAdjudicator.TYPE_TRAINEE)) + all_adj_scores = list(SpeakerScoreByAdj.objects.filter( + ballot_submission__confirmed=True).exclude(position=t.REPLY_POSITION).select_related( + 'debate_adjudicator__adjudicator__id', 'ballot_submission')) + rounds = t.prelim_rounds(until=t.current_round) + + for adj in adjudicators: + # Gather feedback scores for graphs + feedbacks = [f for f in all_adj_feedbacks if f.adjudicator == adj] + debate_adjudications = [a for a in all_debate_adjudicators if a.adjudicator.id is adj.id] + scores = [s for s in all_adj_scores if s.debate_adjudicator.adjudicator.id is adj.id] + + # Gather a dict of round-by-round feedback for the graph + adj.feedback_data = feedback_stats(adj, rounds, feedbacks, all_debate_adjudicators) + # Sum up remaining stats + adj = scoring_stats(adj, scores, debate_adjudications) + + return adjudicators + + +def feedback_stats(adj, rounds, feedbacks, all_debate_adjudicators): + + # Start off with their test scores + feedback_data = [{'x': 0, 'y': adj.test_score, 'position': "Test Score"}] + + for r in rounds: + # Filter all the feedback to focus on this particular rouond + adj_round_feedbacks = [f for f in feedbacks if (f.source_adjudicator and f.source_adjudicator.debate.round == r)] + adj_round_feedbacks.extend([f for f in feedbacks if (f.source_team and f.source_team.debate.round == r)]) + + if len(adj_round_feedbacks) > 0: + debates = [fb.source_team.debate for fb in adj_round_feedbacks if fb.source_team] + debates.extend([fb.source_adjudicator.debate for fb in adj_round_feedbacks if fb.source_adjudicator]) + adj_da = next((da for da in all_debate_adjudicators if (da.adjudicator == adj and da.debate == debates[0])), None) + if adj_da: + if adj_da.type == adj_da.TYPE_CHAIR: + adj_type = "Chair" + elif adj_da.type == adj_da.TYPE_PANEL: + adj_type = "Panellist" + elif adj_da.type == adj_da.TYPE_TRAINEE: + adj_type = "Trainee" + + total_score = [f.score for f in adj_round_feedbacks] + average_score = round(sum(total_score) / len(total_score), 2) + + # Creating the object list for the graph + feedback_data.append({ + 'x': r.seq, + 'y': average_score, + 'position': adj_type, + }) + + return feedback_data + + +def scoring_stats(adj, scores, debate_adjudications): + # Processing scores to get average margins + adj.debates = len(debate_adjudications) + adj.avg_score = None + adj.avg_margin = None + + if len(scores) > 0: + adj.avg_score = sum(s.score for s in scores) / len(scores) + + ballot_ids = [score.ballot_submission for score in scores] + ballot_ids = sorted(set([b.id for b in ballot_ids])) # Deduplication of ballot IDS + ballot_margins = [] + + for ballot_id in ballot_ids: + # For each unique ballot id total its scores + single_round = [s for s in scores if s.ballot_submission.id is ballot_id] + adj_scores = [s.score for s in single_round] # TODO this is slow - should be prefetched + team_split = int(len(adj_scores) / 2) + try: + # adj_scores is a list of all scores from the debate + t_a_scores = adj_scores[:team_split] + t_b_scores = adj_scores[team_split:] + t_a_total, t_b_total = sum(t_a_scores), sum(t_b_scores) + largest_difference = max(t_a_total, t_b_total) + smallest_difference = min(t_a_total, t_b_total) + ballot_margins.append( + largest_difference - smallest_difference) + except TypeError: + print(team_split) + + if ballot_margins: + print('has %s margins %s' % (len(ballot_margins), ballot_margins)) + adj.avg_margin = sum(ballot_margins) / len(ballot_margins) + + return adj + + +def parse_feedback(feedback, questions): + + if feedback.source_team: + source_annotation = " (" + feedback.source_team.result + ")" + elif feedback.source_adjudicator: + source_annotation = " (" + feedback.source_adjudicator.get_type_display() + ")" + else: + source_annotation = "" + + data = { + 'round': feedback.round.abbreviation, + 'version': str(feedback.version) + (feedback.confirmed and "*" or ""), + 'bracket': feedback.debate.bracket, + 'matchup': feedback.debate.matchup, + 'source': feedback.source, + 'source_note': source_annotation, + 'score': feedback.score, + 'questions': [] + } + + for question in questions: + q = { + 'reference': question.reference, + 'text': question.text, + 'name': question.name + } + try: + q['answer'] = question.answer_set.get(feedback=feedback).answer + except ObjectDoesNotExist: + q['answer'] = "-" + + data['questions'].append(q) + + return data diff --git a/tabbycat/adjfeedback/views.py b/tabbycat/adjfeedback/views.py new file mode 100644 index 00000000000..8fcdaedc735 --- /dev/null +++ b/tabbycat/adjfeedback/views.py @@ -0,0 +1,649 @@ +import logging + +from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib import messages +from django.core.exceptions import ObjectDoesNotExist +from django.core.mail import send_mail +from django.conf import settings +from django.http import HttpResponse +from django.db.models import Q +from django.shortcuts import get_object_or_404 +from django.views.generic.base import TemplateView +from django.views.generic.edit import FormView + +from actionlog.mixins import LogActionMixin +from actionlog.models import ActionLogEntry +from participants.models import Adjudicator, Speaker, Team +from participants.prefetch import populate_feedback_scores +from results.mixins import PublicSubmissionFieldsMixin, TabroomSubmissionFieldsMixin +from tournaments.mixins import PublicTournamentPageMixin, TournamentMixin + +from utils.misc import reverse_tournament +from utils.mixins import CacheMixin, JsonDataResponseView, SingleObjectByRandomisedUrlMixin, SingleObjectFromTournamentMixin +from utils.mixins import PostOnlyRedirectView, SuperuserOrTabroomAssistantTemplateResponseMixin, SuperuserRequiredMixin, VueTableTemplateView +from utils.tables import TabbycatTableBuilder +from utils.urlkeys import populate_url_keys + +from .models import AdjudicatorFeedback, AdjudicatorTestScoreHistory +from .forms import make_feedback_form_class +from .tables import FeedbackTableBuilder +from .utils import get_feedback_overview, parse_feedback +from .progress import get_feedback_progress + +logger = logging.getLogger(__name__) + + +class GetAdjScores(LoginRequiredMixin, TournamentMixin, JsonDataResponseView): + + def get_data(self): + feedback_weight = self.get_tournament().current_round.feedback_weight + data = {} + for adj in Adjudicator.objects.all(): + data[adj.id] = adj.weighted_score(feedback_weight) + return data + + +class GetAdjFeedbackJSON(LoginRequiredMixin, TournamentMixin, JsonDataResponseView): + + def get_data(self): + adjudicator = get_object_or_404(Adjudicator, pk=self.kwargs['pk']) + feedback = adjudicator.get_feedback().filter(confirmed=True) + questions = self.get_tournament().adj_feedback_questions + data = [parse_feedback(f, questions) for f in feedback] + return data + + +class FeedbackOverview(LoginRequiredMixin, TournamentMixin, VueTableTemplateView): + + template_name = 'feedback_overview.html' + page_title = 'Adjudicator Feedback Summary' + page_emoji = '🙅' + + def get_adjudicators(self): + t = self.get_tournament() + if t.pref('share_adjs'): + return Adjudicator.objects.filter(Q(tournament=t) | Q(tournament__isnull=True)) + else: + return Adjudicator.objects.filter(tournament=t) + + def get_context_data(self, **kwargs): + kwargs['breaking_count'] = self.get_adjudicators().filter( + breaking=True).count() + return super().get_context_data(**kwargs) + + def get_table(self): + t = self.get_tournament() + adjudicators = self.get_adjudicators() + populate_feedback_scores(adjudicators) + adjudicators = get_feedback_overview(t, adjudicators) + table = FeedbackTableBuilder(view=self, sort_key='Overall Score', + sort_order='desc') + table.add_adjudicator_columns(adjudicators, hide_institution=True, subtext='institution') + table.add_breaking_checkbox(adjudicators) + table.add_score_columns(adjudicators) + table.add_feedback_graphs(adjudicators) + table.add_feedback_link_columns(adjudicators) + table.add_feedback_misc_columns(adjudicators) + return table + + +class FeedbackByTargetView(LoginRequiredMixin, TournamentMixin, VueTableTemplateView): + template_name = "feedback_base.html" + page_title = 'Find Feedback on Adjudicator' + page_emoji = '🔍' + + def get_table(self): + tournament = self.get_tournament() + table = TabbycatTableBuilder(view=self, sort_key="Name") + table.add_adjudicator_columns(tournament.adjudicator_set.all()) + feedback_data = [] + for adj in tournament.adjudicator_set.all(): + count = adj.adjudicatorfeedback_set.count() + feedback_data.append({ + 'text': "{:d} Feedbacks".format(count), + 'link': reverse_tournament('adjfeedback-view-on-adjudicator', tournament, kwargs={'pk': adj.id}), + }) + table.add_column("Feedbacks", feedback_data) + return table + + +class FeedbackBySourceView(LoginRequiredMixin, TournamentMixin, VueTableTemplateView): + + template_name = "feedback_base.html" + page_title = 'Find Feedback' + page_emoji = '🔍' + + def get_tables(self): + tournament = self.get_tournament() + + teams = tournament.team_set.all() + team_table = TabbycatTableBuilder( + view=self, title='From Teams', sort_key='Name') + team_table.add_team_columns(teams) + team_feedback_data = [] + for team in teams: + count = AdjudicatorFeedback.objects.filter( + source_team__team=team).select_related( + 'source_team__team').count() + team_feedback_data.append({ + 'text': "{:d} Feedbacks".format(count), + 'link': reverse_tournament('adjfeedback-view-from-team', + tournament, + kwargs={'pk': team.id}), + }) + team_table.add_column("Feedbacks", team_feedback_data) + + adjs = tournament.adjudicator_set.all() + adj_table = TabbycatTableBuilder( + view=self, title='From Adjudicators', sort_key='Feedbacks') + adj_table.add_adjudicator_columns(adjs) + adj_feedback_data = [] + for adj in adjs: + count = AdjudicatorFeedback.objects.filter( + source_adjudicator__adjudicator=adj).select_related( + 'source_adjudicator__adjudicator').count() + adj_feedback_data.append({ + 'text': "{:d} Feedbacks".format(count), + 'link': reverse_tournament('adjfeedback-view-from-adjudicator', + tournament, + kwargs={'pk': adj.id}), + }) + adj_table.add_column("Feedbacks", adj_feedback_data) + + return [team_table, adj_table] + + +class FeedbackCardsView(LoginRequiredMixin, TournamentMixin, TemplateView): + """Base class for views displaying feedback as cards.""" + + def get_score_thresholds(self): + tournament = self.get_tournament() + min_score = tournament.pref('adj_min_score') + max_score = tournament.pref('adj_max_score') + score_range = max_score - min_score + return { + 'low_score' : min_score + score_range / 10, + 'medium_score' : min_score + score_range / 5, + 'high_score' : max_score - score_range / 10, + } + + def get_feedbacks(self): + questions = self.get_tournament().adj_feedback_questions + feedbacks = self.get_feedback_queryset() + for feedback in feedbacks: + feedback.items = [] + for question in questions: + try: + answer = question.answer_set.get(feedback=feedback).answer + except ObjectDoesNotExist: + continue + feedback.items.append({'question': question, 'answer': answer}) + return feedbacks + + def get_feedback_queryset(self): + raise NotImplementedError() + + def get_context_data(self, **kwargs): + kwargs['feedbacks'] = self.get_feedbacks() + kwargs['score_thresholds'] = self.get_score_thresholds() + return super().get_context_data(**kwargs) + + +class LatestFeedbackView(FeedbackCardsView): + """View displaying the latest feedback.""" + + template_name = "feedback_latest.html" + + def get_feedback_queryset(self): + return AdjudicatorFeedback.objects.order_by('-timestamp')[:50].select_related( + 'adjudicator', 'source_adjudicator__adjudicator', 'source_team__team') + + +class FeedbackFromSourceView(SingleObjectFromTournamentMixin, FeedbackCardsView): + """Base class for views displaying feedback from a given team or adjudicator.""" + + template_name = "feedback_by_source.html" + source_name_attr = None + source_type = "from" + adjfeedback_filter_field = None + + def get_context_data(self, **kwargs): + kwargs['source_name'] = getattr(self.object, self.source_name_attr, '') + kwargs['source_type'] = self.source_type + return super().get_context_data(**kwargs) + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + return super().get(request, *args, **kwargs) + + def get_feedback_queryset(self): + kwargs = {self.adjfeedback_filter_field: self.object} + return AdjudicatorFeedback.objects.filter(**kwargs).order_by('-timestamp') + + +class FeedbackOnAdjudicatorView(FeedbackFromSourceView): + """Base class for views displaying feedback from a given team or adjudicator.""" + + model = Adjudicator + source_name_attr = 'name' + source_type = "on" + adjfeedback_filter_field = 'adjudicator' + allow_null_tournament = True + + +class FeedbackFromTeamView(FeedbackFromSourceView): + """View displaying feedback from a given source.""" + model = Team + source_name_attr = 'short_name' + adjfeedback_filter_field = 'source_team__team' + allow_null_tournament = False + + +class FeedbackFromAdjudicatorView(FeedbackFromSourceView): + """View displaying feedback from a given adjudicator.""" + model = Adjudicator + source_name_attr = 'name' + adjfeedback_filter_field = 'source_adjudicator__adjudicator' + allow_null_tournament = True + + +class GetAdjFeedback(LoginRequiredMixin, TournamentMixin, JsonDataResponseView): + + def parse_feedback(self, f, questions): + + if f.source_team: + source_annotation = " (" + f.source_team.result + ")" + elif f.source_adjudicator: + source_annotation = " (" + f.source_adjudicator.get_type_display() + ")" + else: + source_annotation = "" + + data = [ + str(f.round.abbreviation), + str(str(f.version) + (f.confirmed and "*" or "")), + f.debate.bracket, + f.debate.matchup, + str(str(f.source) + source_annotation), + f.score, + ] + for question in questions: + try: + data.append(question.answer_set.get(feedback=f).answer) + except ObjectDoesNotExist: + data.append("-") + data.append(f.confirmed) + return data + + def get_data(self): + t = self.get_tournament() + adj = get_object_or_404(Adjudicator, pk=int(self.request.GET['id'])) + feedback = adj.get_feedback().filter(confirmed=True) + questions = t.adj_feedback_questions + + data = [self.parse_feedback(f, questions) for f in feedback] + data = [parse_feedback(f, questions) for f in feedback] + return {'aaData': data} + + +class BaseAddFeedbackIndexView(TournamentMixin, TemplateView): + + def get_context_data(self, **kwargs): + tournament = self.get_tournament() + kwargs['adjudicators'] = tournament.adjudicator_set.all() if not tournament.pref('share_adjs') \ + else Adjudicator.objects.all() + kwargs['teams'] = tournament.team_set.all() + return super().get_context_data(**kwargs) + + +class TabroomAddFeedbackIndexView(SuperuserOrTabroomAssistantTemplateResponseMixin, BaseAddFeedbackIndexView): + """View for the index page for tabroom officials to add feedback. The index + page lists all possible sources; officials should then choose the author + of the feedback.""" + + superuser_template_name = 'add_feedback.html' + assistant_template_name = 'assistant_add_feedback.html' + + +class PublicAddFeedbackIndexView(CacheMixin, PublicTournamentPageMixin, BaseAddFeedbackIndexView): + """View for the index page for public users to add feedback. The index page + lists all possible sources; public users should then choose themselves.""" + + template_name = 'public_add_feedback.html' + public_page_preference = 'public_feedback' + + +class BaseAddFeedbackView(LogActionMixin, SingleObjectFromTournamentMixin, FormView): + """Base class for views that allow users to add feedback.""" + + template_name = "enter_feedback.html" + pk_url_kwarg = 'source_id' + allow_null_tournament = True + + def get_form_class(self): + return make_feedback_form_class(self.object, self.get_tournament(), + self.get_submitter_fields(), **self.feedback_form_class_kwargs) + + def get_action_log_fields(self, **kwargs): + kwargs['adjudicator_feedback'] = self.adj_feedback + return super().get_action_log_fields(**kwargs) + + def form_valid(self, form): + self.adj_feedback = form.save() + return super().form_valid(form) + + def get_context_data(self, **kwargs): + source = self.object + if isinstance(source, Adjudicator): + kwargs['source_type'] = "adj" + elif isinstance(source, Team): + kwargs['source_type'] = "team" + kwargs['source_name'] = self.source_name + return super().get_context_data(**kwargs) + + def _populate_source(self): + self.object = self.get_object() # For compatibility with SingleObjectMixin + if isinstance(self.object, Adjudicator): + self.source_name = self.object.name + elif isinstance(self.object, Team): + self.source_name = self.object.short_name + else: + self.source_name = "" + + def get(self, request, *args, **kwargs): + self._populate_source() + return super().get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + self._populate_source() + return super().post(request, *args, **kwargs) + + +class TabroomAddFeedbackView(TabroomSubmissionFieldsMixin, LoginRequiredMixin, BaseAddFeedbackView): + """View for tabroom officials to add feedback.""" + + action_log_type = ActionLogEntry.ACTION_TYPE_FEEDBACK_SAVE + feedback_form_class_kwargs = { + 'confirm_on_submit': True, + 'enforce_required': False, + 'include_unreleased_draws': True, + } + + def form_valid(self, form): + result = super().form_valid(form) + messages.success(self.request, "Feedback from {} on {} added.".format( + self.source_name, self.adj_feedback.adjudicator.name)) + return result + + def get_success_url(self): + return reverse_tournament('adjfeedback-add-index', self.get_tournament()) + + +class PublicAddFeedbackView(PublicSubmissionFieldsMixin, PublicTournamentPageMixin, BaseAddFeedbackView): + """Base class for views for public users to add feedback.""" + + action_log_type = ActionLogEntry.ACTION_TYPE_FEEDBACK_SUBMIT + feedback_form_class_kwargs = { + 'confirm_on_submit': True, + 'enforce_required': True, + 'include_unreleased_draws': False, + } + + def form_valid(self, form): + result = super().form_valid(form) + messages.success(self.request, "Thanks, {}! Your feedback on {} has been recorded.".format( + self.source_name, self.adj_feedback.adjudicator.name)) + return result + + def get_success_url(self): + return reverse_tournament('tournament-public-index', self.get_tournament()) + + +class PublicAddFeedbackByRandomisedUrlView(SingleObjectByRandomisedUrlMixin, PublicAddFeedbackView): + """View for public users to add feedback, where the URL is a randomised one.""" + public_page_preference = 'public_feedback_randomised' + + +class PublicAddFeedbackByIdUrlView(PublicAddFeedbackView): + """View for public users to add feedback, where the URL is by object ID.""" + public_page_preference = 'public_feedback' + + +class AdjudicatorActionError(RuntimeError): + pass + + +class BaseAdjudicatorActionView(LogActionMixin, SuperuserRequiredMixin, TournamentMixin, PostOnlyRedirectView): + + tournament_redirect_pattern_name = 'adjfeedback-overview' + + def get_action_log_fields(self, **kwargs): + kwargs['adjudicator'] = self.adjudicator + return super().get_action_log_fields(**kwargs) + + def get_adjudicator(self, request): + try: + adj_id = int(request.POST["adj_id"]) + adjudicator = Adjudicator.objects.get(id=adj_id) + except (ValueError, Adjudicator.DoesNotExist, Adjudicator.MultipleObjectsReturned): + raise AdjudicatorActionError("Whoops! I didn't recognise that adjudicator: {}".format(adj_id)) + return adjudicator + + def post(self, request, *args, **kwargs): + try: + self.adjudicator = self.get_adjudicator(request) + self.modify_adjudicator(request, self.adjudicator) + self.log_action() # Need to call explicitly, since this isn't a form view + except AdjudicatorActionError as e: + messages.error(request, str(e)) + + return super().post(request, *args, **kwargs) + + +class SetAdjudicatorTestScoreView(BaseAdjudicatorActionView): + + action_log_type = ActionLogEntry.ACTION_TYPE_TEST_SCORE_EDIT + + def get_action_log_fields(self, **kwargs): + kwargs['adjudicator_test_score_history'] = self.atsh + # Skip BaseAdjudicatorActionView + return super(BaseAdjudicatorActionView, self).get_action_log_fields(**kwargs) + + def modify_adjudicator(self, request, adjudicator): + try: + score = float(request.POST["test_score"]) + except ValueError: + raise AdjudicatorActionError("Whoops! The value isn't a valid test score.") + + adjudicator.test_score = score + adjudicator.save() + + atsh = AdjudicatorTestScoreHistory( + adjudicator=adjudicator, round=self.get_tournament().current_round, + score=score) + atsh.save() + self.atsh = atsh + + +class SetAdjudicatorBreakingStatusView(BaseAdjudicatorActionView): + + action_log_type = ActionLogEntry.ACTION_TYPE_ADJUDICATOR_BREAK_SET + + def modify_adjudicator(self, request, adjudicator): + adjudicator.breaking = (str(request.POST["adj_breaking_status"]) == "true") + adjudicator.save() + + def post(self, request, *args, **kwargs): + super().post(request, *args, **kwargs) # Discard redirect + return HttpResponse("ok") + + +class SetAdjudicatorNoteView(BaseAdjudicatorActionView): + + action_log_type = ActionLogEntry.ACTION_TYPE_ADJUDICATOR_NOTE_SET + + def modify_adjudicator(self, request, adjudicator): + try: + note = str(request.POST["note"]) + except ValueError as e: + raise AdjudicatorActionError("Whoop! There was an error interpreting that string: " + str(e)) + + adjudicator.notes = note + adjudicator.save() + + +class BaseFeedbackProgressView(TournamentMixin, VueTableTemplateView): + + page_title = 'Feedback Progress' + page_subtitle = '' + page_emoji = '🆘' + + def get_feedback_progress(self): + if not hasattr(self, "_feedback_progress_result"): + self._feedback_progress_result = get_feedback_progress(self.get_tournament()) + return self._feedback_progress_result + + def get_page_subtitle(self): + teams_progress, adjs_progress = self.get_feedback_progress() + total_missing = sum([progress.num_unsubmitted() for progress in teams_progress + adjs_progress]) + return "{:d} missing feedback submissions".format(total_missing) + + def get_tables(self): + teams_progress, adjs_progress = self.get_feedback_progress() + + adjs_table = FeedbackTableBuilder(view=self, title="From Adjudicators", + sort_key="Owed", sort_order="desc") + adjudicators = [progress.adjudicator for progress in adjs_progress] + adjs_table.add_adjudicator_columns(adjudicators, hide_metadata=True) + adjs_table.add_feedback_progress_columns(adjs_progress) + + teams_table = FeedbackTableBuilder(view=self, title="From Teams", + sort_key="Owed", sort_order="desc") + teams = [progress.team for progress in teams_progress] + teams_table.add_team_columns(teams) + teams_table.add_feedback_progress_columns(teams_progress) + + return [adjs_table, teams_table] + + +class FeedbackProgress(SuperuserRequiredMixin, BaseFeedbackProgressView): + template_name = 'feedback_base.html' + + +class PublicFeedbackProgress(PublicTournamentPageMixin, CacheMixin, BaseFeedbackProgressView): + public_page_preference = 'feedback_progress' + + +class RandomisedUrlsView(SuperuserRequiredMixin, TournamentMixin, TemplateView): + + template_name = 'randomised_urls.html' + show_emails = False + + def get_context_data(self, **kwargs): + tournament = self.get_tournament() + kwargs['teams'] = tournament.team_set.all() + if not tournament.pref('share_adjs'): + kwargs['adjs'] = tournament.adjudicator_set.all() + else: + kwargs['adjs'] = Adjudicator.objects.all() + kwargs['exists'] = tournament.adjudicator_set.filter(url_key__isnull=False).exists() or \ + tournament.team_set.filter(url_key__isnull=False).exists() + kwargs['tournament_slug'] = tournament.slug + return super().get_context_data(**kwargs) + + +class GenerateRandomisedUrlsView(SuperuserRequiredMixin, TournamentMixin, PostOnlyRedirectView): + + tournament_redirect_pattern_name = 'randomised-urls-view' + + def post(self, request, *args, **kwargs): + tournament = self.get_tournament() + + # Only works if there are no randomised URLs now + if tournament.adjudicator_set.filter(url_key__isnull=False).exists() or \ + tournament.team_set.filter(url_key__isnull=False).exists(): + messages.error( + self.request, "There are already randomised URLs. " + + "You must use the Django management commands to populate or " + + "delete randomised URLs.") + else: + populate_url_keys(tournament.adjudicator_set.all()) + populate_url_keys(tournament.team_set.all()) + messages.success(self.request, "Randomised URLs were generated for all teams and adjudicators.") + + return super().post(request, *args, **kwargs) + + +class EmailRandomisedUrlsView(RandomisedUrlsView): + + show_emails = True + template_name = 'randomised_urls_email_list.html' + + +class ConfirmEmailRandomisedUrlsView(SuperuserRequiredMixin, TournamentMixin, PostOnlyRedirectView): + + tournament_redirect_pattern_name = 'randomised-urls-view' + + def post(self, request, *args, **kwargs): + messages.success(self.request, "Emails were sent for all teams and adjudicators.") + + tournament = self.get_tournament() + speakers = Speaker.objects.filter(team__tournament=tournament, + team__url_key__isnull=False, email__isnull=False) + adjudicators = tournament.adjudicator_set.filter( + url_key__isnull=False, email__isnull=False) + + for speaker in speakers: + if speaker.email is None: + continue + + team_path = reverse_tournament( + 'adjfeedback-public-add-from-team-randomised', + tournament, kwargs={'url_key': speaker.team.url_key}) + team_link = self.request.build_absolute_uri(team_path) + message = ('' + 'Hi %s, \n' + '\n' + 'At %s we are using an online feedback system. Feedback for \n' + 'your team (%s) can be submitted at the following URL. This URL \n' + 'is unique to your team — do not share it as anyone with this \n' + 'link can submit feedback on your behalf. It will not \n' + 'change so we suggest bookmarking it. The URL is: \n' + '\n' + '%s' % (speaker.name, tournament.short_name, speaker.team.short_name, team_link)) + + try: + send_mail("Your Feedback URL for %s" % tournament.short_name, + message, settings.DEFAULT_FROM_EMAIL, [speaker.email], + fail_silently=False) + logger.info("Sent email with key to %s (%s)" % (speaker.email, speaker.name)) + except: + logger.info("Failed to send email to %s speaker.email") + + for adjudicator in adjudicators: + if adjudicator.email is None: + continue + + adj_path = reverse_tournament( + 'adjfeedback-public-add-from-adjudicator-randomised', + tournament, kwargs={'url_key': adjudicator.url_key}) + adj_link = self.request.build_absolute_uri(adj_path) + message = ('' + 'Hi %s, \n' + '\n' + 'At %s we are using an online feedback system. Your feedback \n' + 'can be submitted at the following URL. This URL \n' + 'is unique to you — do not share it as anyone with this \n' + 'link can submit feedback on your behalf. It will not \n' + 'change so we suggest bookmarking it. The URL is: \n' + '\n' + '%s' % (adjudicator.name, tournament.short_name, adj_link)) + + try: + send_mail("Your Feedback URL for %s" % tournament.short_name, + message, settings.DEFAULT_FROM_EMAIL, [adjudicator.email], + fail_silently=False) + logger.info("Sent email with key to %s (%s)" % (adjudicator.email, adjudicator.name)) + except: + logger.info("Failed to send email %s" % adjudicator.email) + + return super().post(request, *args, **kwargs) diff --git a/availability/migrations/__init__.py b/tabbycat/availability/__init__.py similarity index 100% rename from availability/migrations/__init__.py rename to tabbycat/availability/__init__.py diff --git a/availability/admin.py b/tabbycat/availability/admin.py similarity index 93% rename from availability/admin.py rename to tabbycat/availability/admin.py index 338f6bf9f66..a84ffcff390 100644 --- a/availability/admin.py +++ b/tabbycat/availability/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin -from django import forms -from .models import ActiveVenue, ActiveTeam, ActiveAdjudicator +from .models import ActiveAdjudicator, ActiveTeam, ActiveVenue + # ============================================================================== # ActiveVenue @@ -14,6 +14,7 @@ class ActiveVenueAdmin(admin.ModelAdmin): admin.site.register(ActiveVenue, ActiveVenueAdmin) + # ============================================================================== # ActiveTeam # ============================================================================== @@ -25,6 +26,7 @@ class ActiveTeamAdmin(admin.ModelAdmin): admin.site.register(ActiveTeam, ActiveTeamAdmin) + # ============================================================================== # ActiveAdjudicator # ============================================================================== diff --git a/availability/migrations/0001_initial.py b/tabbycat/availability/migrations/0001_initial.py similarity index 100% rename from availability/migrations/0001_initial.py rename to tabbycat/availability/migrations/0001_initial.py diff --git a/availability/migrations/0002_checkin_person.py b/tabbycat/availability/migrations/0002_checkin_person.py similarity index 100% rename from availability/migrations/0002_checkin_person.py rename to tabbycat/availability/migrations/0002_checkin_person.py diff --git a/availability/migrations/0003_auto_20160103_1927.py b/tabbycat/availability/migrations/0003_auto_20160103_1927.py similarity index 100% rename from availability/migrations/0003_auto_20160103_1927.py rename to tabbycat/availability/migrations/0003_auto_20160103_1927.py diff --git a/breakqual/migrations/__init__.py b/tabbycat/availability/migrations/__init__.py similarity index 100% rename from breakqual/migrations/__init__.py rename to tabbycat/availability/migrations/__init__.py diff --git a/availability/models.py b/tabbycat/availability/models.py similarity index 100% rename from availability/models.py rename to tabbycat/availability/models.py diff --git a/availability/templates/availability_index.html b/tabbycat/availability/templates/availability_index.html similarity index 67% rename from availability/templates/availability_index.html rename to tabbycat/availability/templates/availability_index.html index 738c2f868c9..f866f58cff3 100644 --- a/availability/templates/availability_index.html +++ b/tabbycat/availability/templates/availability_index.html @@ -1,41 +1,39 @@ {% extends "base.html" %} {% load debate_tags %} -{% block page-title %}{{ round.name }} Check-Ins{% endblock %} -{% block head-title %}📍️Check-Ins Overview{% endblock %} -{% block sub-title %}For {{ round.name }}{% endblock %} - {% block page-subnav-sections %} - - - Check In Teams - - {% if round.draw_type == "F" %} - - Check In All Breaking Teams + {% if round.is_break_round %} + + Check In Teams - {% elif round.draw_type == "B" %} - - Check In All Advancing Teams + {% else %} + + Check In Teams {% endif %} - + Check In Venues - - Check In Adjudicators + + Check In Adjs {% if round.is_break_round %} - - Check In All Breaking Adjudicators + + Check In All Breaking Adjs {% else %} - - Check In All + + Check In Everything {% if round.prev %} - - Check In All Active in {{ round.prev.abbreviation }} + + Check In Everything Active in {{ round.prev.abbreviation }} {% endif %} {% endif %} @@ -44,7 +42,7 @@ {% block page-subnav-actions %} - {% if round.draw_status == round.STATUS_CONFIRMED or round.draw_status = round.STATUS_RELEASED %} + {% if round.draw_status == round.STATUS_CONFIRMED or round.draw_status == round.STATUS_RELEASED %} View Draw @@ -106,7 +104,8 @@ {% if previous_unconfirmed > 0 and not round.is_break_round %}
    Note: {{ previous_unconfirmed }} debates from {{ round.prev.name }} - do not have a completed ballot — this may lead to a draw that fails or is incorrect depending on your draw rules. + do not have a completed ballot — this may lead to a draw that + fails or is incorrect depending on your draw rules.
    {% endif %} @@ -118,13 +117,35 @@ {% if min_adjudicators > checkin_types.1.in_now %}
    - There need to be at least {{ min_adjudicators }} checked in adjudicators given the number of debates. + There need to be at least {{ min_adjudicators }} checked in adjudicators + given the number of debates.
    {% endif %} {% if min_venues > checkin_types.2.in_now %}
    - There need to be at least {{ min_venues }} checked in venues given the number of debates. + There need to be at least {{ min_venues }} checked in venues given the + number of debates. +
    + {% endif %} + + {% if round.seq > current_round.seq and not round.is_break_round %} +
    + This is a page for {{ round.name }}, however the current + round is still set to {{ current_round.name }}. Did you + forget to + advance to the next round? +
    + {% endif %} + + {% if not round.prev and round.draw_type = round.DRAW_POWERPAIRED %} +
    + This is the first round, but its draw type is + {{ round.get_draw_type_display }}. Did you intend for it + to be Random instead? You can + + edit this round's draw type in the Edit Database area.
    {% endif %} @@ -134,19 +155,20 @@
    - {% for checkin_type in checkin_types %} + {% for ct in checkin_types %} {% include 'checkin_progress.html' %} {% endfor %}
    -
    + {% csrf_token %} {% endblock content %} -{% block extra-js %} +{% block js %} + {{ block.super }} -{% endblock extra-js %} +{% endblock js %} diff --git a/tabbycat/availability/templates/base_availability.html b/tabbycat/availability/templates/base_availability.html new file mode 100644 index 00000000000..093576d1774 --- /dev/null +++ b/tabbycat/availability/templates/base_availability.html @@ -0,0 +1,95 @@ +{% extends "base_vue_table.html" %} +{% load debate_tags %} +{% load static %} + +{% block page-subnav-sections %} + {% if round.seq > 1 %} + + {% endif %} + + + {% if round.is_break_round and page_title == 'Adjudicator Check-Ins' %} + + Check In All Breaking + + {% endif %} + {{ block.super }} +{% endblock %} + +{% block page-subnav-actions %} + +{% endblock %} + +{% block js %} + + {{ block.super }} + + +{% endblock %} diff --git a/tabbycat/availability/templates/checkin_progress.html b/tabbycat/availability/templates/checkin_progress.html new file mode 100644 index 00000000000..0e5d76a08d4 --- /dev/null +++ b/tabbycat/availability/templates/checkin_progress.html @@ -0,0 +1,51 @@ +{% load debate_tags %} + +
    + +
    +

    {{ ct.type }} Check-Ins

    +
    +
    +
    + +
    + {{ round.abbreviation }} +
    +
    +
    +
    + {{ ct.in_now }}/{{ ct.total }} +
    +
    +
    + + {% if ct.in_before %} +
    + {{ round.prev.abbreviation }} +
    +
    +
    +
    + {{ ct.in_before }}/{{ ct.total }} +
    +
    +
    + {% endif %} + + {% if ct.message %} +
    + {{ ct.message }} +
    + {% endif %} + +
    +
    +
    diff --git a/availability/templates/person_availability.html b/tabbycat/availability/templates/person_availability.html similarity index 88% rename from availability/templates/person_availability.html rename to tabbycat/availability/templates/person_availability.html index 59d5a4174cb..cabe0d1b3a0 100644 --- a/availability/templates/person_availability.html +++ b/tabbycat/availability/templates/person_availability.html @@ -5,8 +5,8 @@ {% block draw-url %}{% round_url availability_index %}{% endblock %} {% block post-success %}location.reload();{% endblock %} -{% block head-title %}Personal Checkins for {{ round.name }}{% endblock %} -{% block page-title %}Personal Checkins{% endblock %} +{% block head-title %}Personal Check-Ins for {{ round.name }}{% endblock %} +{% block page-title %}Personal Check-Ins{% endblock %} {% block sub-title %}for {{ round.name }}{% endblock %} {% block copy_btn %}{% endblock %} diff --git a/availability/templates/person_checkin.html b/tabbycat/availability/templates/person_checkin.html similarity index 94% rename from availability/templates/person_checkin.html rename to tabbycat/availability/templates/person_checkin.html index f96e8c4bd96..b24cca483ed 100644 --- a/availability/templates/person_checkin.html +++ b/tabbycat/availability/templates/person_checkin.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% load debate_tags %} -{% block head-title %}Checkin{% endblock %} +{% block head-title %}Check-In{% endblock %} {% block content %}
    @@ -30,7 +30,8 @@

    {% endblock %} -{% block extra-js %} +{% block js %} + {{ block.super }} + {{ block.super }} +{% endblock js %} diff --git a/tournaments/templates/public_divisions.html b/tabbycat/divisions/templates/public_divisions.html similarity index 94% rename from tournaments/templates/public_divisions.html rename to tabbycat/divisions/templates/public_divisions.html index e7bc781400c..3a3bcc5771a 100644 --- a/tournaments/templates/public_divisions.html +++ b/tabbycat/divisions/templates/public_divisions.html @@ -24,5 +24,3 @@
    Division {{ division.name }}
  • {% endfor %} {% endblock content %} - -{% block extra-js %}{% endblock extra-js %} diff --git a/tabbycat/divisions/urls.py b/tabbycat/divisions/urls.py new file mode 100644 index 00000000000..6070e9cd4fe --- /dev/null +++ b/tabbycat/divisions/urls.py @@ -0,0 +1,37 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + + # Divisions Specific + url(r'^divisions/$', + views.public_divisions, + name='public_divisions'), + url(r'^admin/divisions/allocate/$', + views.division_allocations, + name='division_allocations'), + + # POST METHODS + url(r'^admin/divisions/set_venue_group/$', + views.set_division_venue_group, + name='set_division_venue_group'), + url(r'^admin/divisions/set_team_division/$', + views.set_team_division, + name='set_team_division'), + url(r'^admin/divisions/set_division_time/$', + views.set_division_time, + name='set_division_time'), + + # MANUAL ACTIONS + url(r'^admin/divisions/create/$', + views.create_division, + name='create_division'), + url(r'^admin/divisions/create_division_allocation/$', + views.create_division_allocation, + name='create_division_allocation'), + url(r'^admin/divisions/create_byes/$', + views.create_byes, + name='create_byes') + +] diff --git a/tabbycat/divisions/views.py b/tabbycat/divisions/views.py new file mode 100644 index 00000000000..cfab1db79ed --- /dev/null +++ b/tabbycat/divisions/views.py @@ -0,0 +1,164 @@ +import json +import logging + +from django.conf import settings +from django.contrib.auth import get_user_model +from django.http import HttpResponse, HttpResponseBadRequest +from django.shortcuts import render +from django.views.decorators.cache import cache_page + +from participants.models import Institution, Team +from utils.views import admin_required, expect_post, public_optional_tournament_view, tournament_view +from utils.misc import redirect_tournament +from venues.models import InstitutionVenueConstraint, TeamVenueConstraint, VenueGroup + +from .division_allocator import DivisionAllocator +from .models import Division + +User = get_user_model() +logger = logging.getLogger(__name__) + + +@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) +@public_optional_tournament_view('public_divisions') +def public_divisions(request, t): + divisions = Division.objects.filter(tournament=t).all().select_related('venue_group') + divisions = sorted(divisions, key=lambda x: x.name) + venue_groups = set(d.venue_group for d in divisions) + for uvg in venue_groups: + uvg.divisions = [d for d in divisions if d.venue_group == uvg] + + return render(request, 'public_divisions.html', dict(venue_groups=venue_groups)) + + +@admin_required +@tournament_view +def division_allocations(request, t): + # Should be a JsonDataResponseView + teams = list(Team.objects.filter(tournament=t).all().values( + 'id', 'short_reference', 'division', 'use_institution_prefix', 'institution__code', 'institution__id')) + + for team in teams: + team['institutional_preferences'] = list( + InstitutionVenueConstraint.objects.filter( + institution=team['institution__id']).values( + 'venue_group__short_name', 'priority', 'venue_group__id').order_by('-priority')) + team['team_preferences'] = list( + TeamVenueConstraint.objects.filter( + team=team['id']).values( + 'venue_group__short_name', 'priority', 'venue_group__id').order_by('-priority')) + + # team['institutional_preferences'] = "test" + # team['individual_preferences'] = "test" + + teams = json.dumps(teams) + + venue_groups = json.dumps(list( + VenueGroup.objects.all().values( + 'id', 'short_name', 'team_capacity'))) + + divisions = json.dumps(list(Division.objects.filter(tournament=t).all().values( + 'id', 'name', 'venue_group'))) + + return render(request, "division_allocations.html", dict( + teams=teams, divisions=divisions, venue_groups=venue_groups)) + + +@admin_required +@tournament_view +def create_byes(request, t): + divisions = Division.objects.filter(tournament=t) + Team.objects.filter(tournament=t, type=Team.TYPE_BYE).delete() + for division in divisions: + teams_count = Team.objects.filter(division=division).count() + if teams_count % 2 != 0: + bye_institution, created = Institution.objects.get_or_create( + name="Byes", code="Byes") + Team( + institution=bye_institution, + reference="Bye for Division " + division.name, + short_reference="Bye", + tournament=t, + division=division, + use_institution_prefix=False, + type=Team.TYPE_BYE + ).save() + + return redirect_tournament('division_allocations', t) + + +@admin_required +@tournament_view +def create_division(request, t): + division = Division.objects.create(name="temporary_name", tournament=t) + division.save() + division.name = "%s" % division.id + division.save() + return redirect_tournament('division_allocations', t) + + +@admin_required +@tournament_view +def create_division_allocation(request, t): + + teams = list(Team.objects.filter(tournament=t)) + institutions = Institution.objects.all() + venue_groups = VenueGroup.objects.all() + + # Delete all existing divisions - this shouldn't affect teams (on_delete=models.SET_NULL)) + divisions = Division.objects.filter(tournament=t).delete() + + alloc = DivisionAllocator(teams=teams, divisions=divisions, + venue_groups=venue_groups, tournament=t, + institutions=institutions) + success = alloc.allocate() + + if success: + return redirect_tournament('division_allocations', t) + else: + return HttpResponseBadRequest("Couldn't create divisions") + + +@admin_required +@expect_post +@tournament_view +def set_division_venue_group(request, t): + division = Division.objects.get(pk=int(request.POST['division'])) + if request.POST['venueGroup'] == '': + division.venue_group = None + else: + division.venue_group = VenueGroup.objects.get(pk=int(request.POST['venueGroup'])) + + print("saved venue group for for", division.name) + division.save() + return HttpResponse("ok") + + +@admin_required +@expect_post +@tournament_view +def set_team_division(request, t): + team = Team.objects.get(pk=int(request.POST['team'])) + if request.POST['division'] == '': + team.division = None + print("set division to none for", team.short_name) + else: + team.division = Division.objects.get(pk=int(request.POST['division'])) + print("saved divison for ", team.short_name) + + team.save() + return HttpResponse("ok") + + +@admin_required +@expect_post +@tournament_view +def set_division_time(request, t): + division = Division.objects.get(pk=int(request.POST['division'])) + if request.POST['division'] == '': + division = None + else: + division.time_slot = request.POST['time'] + division.save() + + return HttpResponse("ok") diff --git a/draw/__init__.py b/tabbycat/draw/__init__.py similarity index 100% rename from draw/__init__.py rename to tabbycat/draw/__init__.py diff --git a/draw/admin.py b/tabbycat/draw/admin.py similarity index 82% rename from draw/admin.py rename to tabbycat/draw/admin.py index a7a29d1a1de..db33ca6a3d0 100644 --- a/draw/admin.py +++ b/tabbycat/draw/admin.py @@ -1,21 +1,17 @@ from django.contrib import admin -from django import forms -from .models import Debate, DebateTeam -from participants.models import Speaker, Team from adjallocation.models import DebateAdjudicator +from utils.admin import BaseModelAdmin + +from .models import Debate, DebateTeam + # ============================================================================== # DebateTeam # ============================================================================== -_dt_round = lambda o: o.debate.round.abbreviation -_dt_round.short_description = 'Round' -_dt_tournament = lambda o: o.debate.round.tournament -_dt_tournament.short_description = 'Tournament' - -class DebateTeamAdmin(admin.ModelAdmin): - list_display = ('team', _dt_tournament, _dt_round, 'position') +class DebateTeamAdmin(admin.ModelAdmin, BaseModelAdmin): + list_display = ('team', 'get_tournament', 'get_round', 'position') search_fields = ('team', ) raw_id_fields = ('debate', 'team', ) @@ -32,7 +28,6 @@ def get_queryset(self, request): # Debate # ============================================================================== - class DebateTeamInline(admin.TabularInline): model = DebateTeam extra = 1 @@ -66,10 +61,9 @@ def _set_result_status(modeladmin, request, queryset): modeladmin.message_user( request, message_bit + " status set to " + verbose_name) - _set_result_status.__name__ = "set_result_status_%s" % verbose_name.lower( - ) # so that they look different to DebateAdmin - _set_result_status.short_description = "Set result status to %s" % verbose_name.lower( - ) + # so that they look different to DebateAdmin + _set_result_status.__name__ = "set_result_status_%s" % verbose_name.lower() + _set_result_status.short_description = "Set result status to %s" % verbose_name.lower() return _set_result_status actions.append(_make_set_result_status(value, verbose_name)) diff --git a/draw/dbutils.py b/tabbycat/draw/dbutils.py similarity index 77% rename from draw/dbutils.py rename to tabbycat/draw/dbutils.py index 10c1b10b113..01066dedb21 100644 --- a/draw/dbutils.py +++ b/tabbycat/draw/dbutils.py @@ -1,7 +1,8 @@ -from utils.management.base import RoundCommand, CommandError -from .models import Debate from tournaments.models import Round +from .models import Debate + + def delete_round_draw(round, **options): Debate.objects.filter(round=round).delete() round.draw_status = Round.STATUS_NONE diff --git a/draw/generator.py b/tabbycat/draw/generator.py similarity index 90% rename from draw/generator.py rename to tabbycat/draw/generator.py index d4a66fd3c18..bcb6877196c 100644 --- a/draw/generator.py +++ b/tabbycat/draw/generator.py @@ -1,9 +1,10 @@ -from collections import OrderedDict import random -import math -import copy -from .one_up_one_down import OneUpOneDownSwapper import logging +from collections import OrderedDict + +from .one_up_one_down import OneUpOneDownSwapper +from .utils import partial_break_round_split + logger = logging.getLogger(__name__) # Flag codes must NOT have commas in them, because they go into a comma-delimited list. @@ -45,6 +46,16 @@ def __init__(self, teams, bracket, room_rank, flags=[], winner=None, division=No else: self._winner_index = self.teams.index(winner) + @classmethod + def from_debate(cls, debate): + teams = [debate.aff_team, debate.neg_team] # order matters + bracket = debate.bracket + room_rank = debate.room_rank + flags = debate.flags.split(",") + division = debate.division + winner = debate.confirmed_ballot.ballot_set.winner + return cls(teams, bracket, room_rank, flags, winner, division) + def __repr__(self): return "".format( self.teams[0], self.teams[1], self.bracket, self.room_rank) @@ -187,7 +198,7 @@ class BaseDrawGenerator(object): can_be_first_round = True requires_even_teams = True requires_prev_results = False - draw_type = None # must be set by subclasses + draw_type = None # Must be set by subclasses # All subclasses must define this with any options that may exist. DEFAULT_OPTIONS = {} @@ -205,11 +216,15 @@ def __init__(self, teams, round=None, results=None, **kwargs): raise DrawError("There were no teams for the draw.") if results is None and self.requires_prev_results: - raise TypeError("'results' is required for draw of type {0:s}".format( + raise TypeError( + "'results' is required for draw of type {0:s}".format( self.__class__.__name__)) + if results is not None and not self.requires_prev_results: - logger.warning("'results' not required for draw of type {0:s}, will probably be ignored".format( + logger.warning( + "'results' not required for draw of type {0:s}, will probably be ignored".format( self.__class__.__name__)) + if results is not None: self.results = results @@ -257,7 +272,7 @@ def annotate_team_flags(self, pairings): if team in self.team_flags: pairing.add_flags(self.team_flags[team]) - def balance_sides(self, pairings): + def allocate_sides(self, pairings): if self.options["side_allocations"] == "balance": for pairing in pairings: pairing.balance_sides() @@ -289,17 +304,19 @@ def check_teams_for_attribute(self, name, choices=None, checkfunc=None): if not all(has_attribute): offending_teams = has_attribute.count(False) raise DrawError("{0} out of {1} teams don't have a '{name}' attribute.".format( - offending_teams, len(self.teams), name=name)) + offending_teams, len(self.teams), name=name)) + if choices: attribute_value_valid = [getattr(x, name) in choices for x in self.teams] elif checkfunc: attribute_value_valid = [checkfunc(getattr(x, name)) for x in self.teams] else: return + if not all(attribute_value_valid): offending_teams = attribute_value_valid.count(False) raise DrawError("{0} out of {1} teams has an invalid '{name}' attribute. Valid choices: ".format( - offending_teams, len(self.teams), name=name) + ", ".join(map(repr, choices))) + offending_teams, len(self.teams), name=name) + ", ".join(map(repr, choices))) class RandomDrawGenerator(BaseDrawGenerator): @@ -322,12 +339,12 @@ class RandomDrawGenerator(BaseDrawGenerator): def generate(self): self._draw = self._make_initial_pairings() - self.avoid_conflicts(self._draw) # operates in-place - self.balance_sides(self._draw) # operates in-place + self.avoid_conflicts(self._draw) # Operates in-place + self.allocate_sides(self._draw) # Operates in-place return self._draw def _make_initial_pairings(self): - teams = list(self.teams) # make a copy + teams = list(self.teams) # Make a copy random.shuffle(teams) debates = len(teams) // 2 pairings = [Pairing(teams=t, bracket=0, room_rank=0) for t in zip(teams[:debates], teams[debates:])] @@ -350,7 +367,7 @@ def avoid_conflicts(self, pairings): pairing.teams[1], swap_pairing.teams[1] = swap_pairing.teams[1], pairing.teams[1] badness_new = self._badness(pairing, swap_pairing) if badness_new == 0: - break # yay! + break # yay! elif badness_new >= badness_orig or self._badness(swap_pairing) > 0: # swap back and try again pairing.teams[1], swap_pairing.teams[1] = swap_pairing.teams[1], pairing.teams[1] @@ -392,9 +409,7 @@ def _make_initial_pairings(self): random.shuffle(aff_teams) random.shuffle(neg_teams) - debates = len(aff_teams) - pairings = [Pairing(teams=t, bracket=0, room_rank=0) \ - for t in zip(aff_teams, neg_teams)] + pairings = [Pairing(teams=t, bracket=0, room_rank=0) for t in zip(aff_teams, neg_teams)] return pairings @@ -443,15 +458,15 @@ def __init__(self, *args, **kwargs): def generate(self): self._brackets = self._make_raw_brackets() - self.resolve_odd_brackets(self._brackets) # operates in-place + self.resolve_odd_brackets(self._brackets) # Operates in-place self._pairings = self.generate_pairings(self._brackets) - self.avoid_conflicts(self._pairings) # operates in-place + self.avoid_conflicts(self._pairings) # Operates in-place self._draw = list() for bracket in self._pairings.values(): self._draw.extend(bracket) - self.balance_sides(self._draw) # operates in-place - self.annotate_team_flags(self._draw) # operates in-place + self.allocate_sides(self._draw) # Operates in-place + self.annotate_team_flags(self._draw) # Operates in-place return self._draw def _make_raw_brackets(self): @@ -468,7 +483,7 @@ def _make_raw_brackets(self): brackets[points] = pool return brackets - ## Odd bracket resolutions + # Odd bracket resolutions ODD_BRACKET_FUNCTIONS = { "pullup_top" : "_pullup_top", @@ -532,25 +547,26 @@ def _intermediate_bubbles(cls, brackets): def _intermediate_bubbles_with_up_down(self, brackets): """Operates in-place. Requires Team.institution and Team.seen() to be defined.""" - self._intermediate_bubbles(brackets) # operates in-place + self._intermediate_bubbles(brackets) # Operates in-place # Check each of the intermediate bubbles for conflicts. # If there is one, try swapping the top team with the bottom team # of the bracket above. Failing that, try the same with the bottom # team and the top team of the bracket below. Failing that, give up. # Note: Under no circumstances do we swap both teams. + def _check_conflict(team1, team2): try: if team1.institution == team2.institution: - return 1 # institution + return 1 # Institution if team1.seen(team2): - return 2 # history + return 2 # History except AttributeError: raise DrawError("For conflict avoidance, teams must have attributes 'institution' and 'seen'.") - return 0 # no conflict + return 0 # No conflict for points, teams in brackets.items(): if int(points) == points: - continue # skip non-intermediate brackets + continue # Skip non-intermediate brackets # a couple of checks assert points % 0.5 == 0 assert teams[0].points > teams[1].points @@ -571,7 +587,7 @@ def _check_conflict(team1, team2): # bubble down, if bubble up didn't work if points-0.5 in brackets: - swap_team = brackets[points-0.5][0] # bottom team + swap_team = brackets[points-0.5][0] # Bottom team if not _check_conflict(swap_team, teams[0]): self.add_team_flag(teams[1], (conflict == 1) and "bub_dn_inst" or "bub_dn_hist") self.add_team_flag(swap_team, "bub_dn_accom") @@ -581,9 +597,7 @@ def _check_conflict(team1, team2): # if nothing worked, add a "didn't work" flag self.add_team_flag(teams[0], "no_bub_updn") - - ## Pairings generation - + # Pairings generation PAIRING_FUNCTIONS = { "fold" : "_pairings_fold", "slide" : "_pairings_slide", @@ -674,10 +688,10 @@ def _pairings_adjacent(cls, brackets): def _pairings_fold_top_adjacent_rest(cls, brackets): return cls._pairings_top_special(brackets, cls._subpool_fold, cls._subpool_adjacent) - ## Conflict avoidance + # Conflict avoidance AVOID_CONFLICT_FUNCTIONS = { - "one_up_one_down" : "_one_up_one_down", + "one_up_one_down": "_one_up_one_down", } def avoid_conflicts(self, pairings): @@ -694,10 +708,11 @@ def _one_up_one_down(self, pairings): for bracket in pairings.values(): pairs = [tuple(p.teams) for p in bracket] - pairs_orig = list(pairs) # keep a copy for comparison - OPTIONS = ["avoid_history", "avoid_institution", "history_penalty", - "institution_penalty"] - options = dict((key, self.options[key]) for key in OPTIONS) + pairs_orig = list(pairs) # Keep a copy for comparison + OPTIONS = [ + "avoid_history", "avoid_institution", "history_penalty", + "institution_penalty"] + options = dict((key, self.options[key]) for key in OPTIONS) # flake8: noqa swapper = OneUpOneDownSwapper(**options) pairs_new = swapper.run(pairs) swaps = swapper.swaps @@ -829,7 +844,7 @@ def _pullup(self, brackets, indices): pullups_needed_teams.extend(pullup_teams) # Then, figure out if we need any pullups in *this* bracket. - aff_surplus = len(pool["aff"]) - len(pool["neg"]) # could be negative + aff_surplus = len(pool["aff"]) - len(pool["neg"]) # Could be negative if aff_surplus > 0: new_pullups_needed_for.append((pool["neg"], "neg", aff_surplus)) elif aff_surplus < 0: @@ -910,7 +925,7 @@ def _intermediate_bubbles_2(cls, brackets): new = OrderedDict() unfilled = OrderedDict() - intermediates = OrderedDict() # values are lists of {"aff", "neg"} dicts + intermediates = OrderedDict() # Values are lists of {"aff", "neg"} dicts for points, pool in brackets.items(): to_delete_from_unfilled = [] @@ -998,7 +1013,7 @@ def _pairings(brackets, presort_func): @classmethod def _pairings_slide(cls, brackets): def slide(pool): - pass # do nothing + pass # Do nothing return cls._pairings(brackets, slide) @classmethod @@ -1015,95 +1030,74 @@ def shuffle(pool): return cls._pairings(brackets, shuffle) -class FirstEliminationDrawGenerator(BaseDrawGenerator): - """Class for draw for a round that is a first w round, with - a number of teams breaking that is not a power of two.""" +class BaseEliminationDrawGenerator(BaseDrawGenerator): can_be_first_round = False requires_even_teams = False - requires_prev_results = False draw_type = "elimination" - def generate(self): - # Sort by break rank - for team in self.teams: - team.break_rank = team.break_rank_for_category(self.round.break_category) + DEFAULT_OPTIONS = {"side_allocations": "random"} - self.teams = sorted(self.teams, key=lambda x: x.break_rank) - break_size = self.round.break_size + def generate(self): + pairings = self.make_pairings() + self.allocate_sides(pairings) + return pairings - # Determine who debates - bypassing, debating = self._bypass_debate_split(break_size) - if bypassing + debating != break_size: - raise DrawError("The number of debating (%s) and bypassing (%s) teams in this round is not equal to the break size (%s)" % (debating, bypassing, break_size)) + def make_pairings(self): + raise NotImplementedError - self._bypassing_teams = self.teams[:bypassing] - debating_teams = self.teams[-debating:] + def _make_pairings(self, teams, num_bye_rooms): + """Folds the teams in `teams`, assigning consecutive room ranks starting + from `num_bye_rooms+1`. Subclasses can use this method to generate + pairings from a list of teams.""" - # Pair the debating teams - debates = len(debating_teams) // 2 - top = debating_teams[:debates] - bottom = debating_teams[debates:] + debates = len(teams) // 2 + top = teams[:debates] + bottom = teams[debates:] bottom.reverse() pairings = list() - for i, teams in enumerate(zip(top, bottom), start=bypassing+1): - pairing = Pairing(teams, bracket=0, room_rank=i) + for i, ts in enumerate(zip(top, bottom), start=num_bye_rooms+1): + pairing = Pairing(ts, bracket=0, room_rank=i) pairings.append(pairing) - return pairings - @staticmethod - def _bypass_debate_split(number): - next_pow2 = 1 << (number.bit_length() - 1) - if next_pow2 == number: # no partial elimination - return number, 0 - debates = number - next_pow2 - return next_pow2 - debates, 2*debates - def get_bypassing_teams(self): - if hasattr(self, "_bypassing_teams"): - return self._bypassing_teams - raise RuntimeError("get_bypassing_teams() must not be called before generate().") +class FirstEliminationDrawGenerator(BaseEliminationDrawGenerator): + """Class for draw for a round that is a first elimination round, with + a number of teams breaking that is not a power of two.""" + requires_prev_results = False -class EliminationDrawGenerator(BaseDrawGenerator): + def make_pairings(self): + debates, bypassing = partial_break_round_split(len(self.teams)) + logger.info("There will be %d debates in this round and %d teams bypassing it.", debates, bypassing) + teams = self.teams[bypassing:] + return self._make_pairings(teams, bypassing) + + +class EliminationDrawGenerator(BaseEliminationDrawGenerator): """Class for second or subsequent elimination round. For this draw type, 'teams' should be the teams that automatically advanced to this round (i.e., bypassed the previous break round). 'results' should be a list of Pairings with winners indicated.""" - can_be_first_round = False - requires_even_teams = False # It does but enabling trips it at init rather than the DrawError() below - requires_prev_results = False - draw_type = "elimination" + requires_prev_results = True - def generate(self): - category = self.round.break_category + def make_pairings(self): + self.results.sort(key=lambda x: x.room_rank) + winners = [p.winner for p in self.results] + if winners.count(None) > 0: + raise DrawError("%d debates in the previous round don't have a result." % winners.count(None)) - # Sort by break rank - for team in self.teams: - team.break_rank = team.break_rank_for_category(self.round.break_category) + bypassing = self.results[0].room_rank - 1 # e.g. if lowest room rank was 7, then 6 teams should bypass + teams = self.teams[:bypassing] + winners + logger.info("%d teams bypassed the previous round and %d teams won the last round" % (bypassing, len(winners))) - teams = sorted(self.teams, key=lambda x: x.break_rank) + if len(teams) & (len(teams) - 1) != 0: + raise DrawError("The number of teams (%s) in this round is not a power of two" % len(teams)) - # Check for argument sanity. - num_teams = len(self.teams) + len(self.results) - if num_teams != 1 << (num_teams.bit_length() - 1): - raise DrawError("The number of teams (%s) in this round is not a power of two" % num_teams) + return self._make_pairings(teams, 0) - self.results.sort(key=lambda x: x.room_rank) - teams = list(self.teams) - teams.extend([p.winner for p in self.results]) - - debates = len(teams) // 2 - top = teams[:debates] - bottom = teams[debates:] - bottom.reverse() - pairings = list() - for i, ts in enumerate(zip(top, bottom), start=1): - pairing = Pairing(ts, bracket=0, room_rank=i) - pairings.append(pairing) - return pairings class RoundRobinDrawGenerator(BaseDrawGenerator): """ Class for round-robin stype matchups using divisions """ @@ -1112,13 +1106,11 @@ class RoundRobinDrawGenerator(BaseDrawGenerator): requires_even_teams = False requires_prev_results = False draw_type = "preliminary" - side_allocations = "balance" PAIRING_FUNCTIONS = { "random": "_pairings_random" } - DEFAULT_OPTIONS = {"max_swap_attempts": 20, "avoid_conflicts": "off"} def generate(self): @@ -1130,7 +1122,7 @@ def generate(self): for bracket in self._pairings.values(): self._draw.extend(bracket) - self.balance_sides(self._draw) # operates in-place + self.allocate_sides(self._draw) # Operates in-place return self._draw def _make_raw_brackets_from_divisions(self): @@ -1160,13 +1152,14 @@ def _make_raw_brackets_from_divisions(self): def generate_pairings(self, brackets): pairings = OrderedDict() - first_bracket_teams = next(iter(brackets.values())) + # TODO see if there's a way to remove this dependency on self.round, since it's the only + # place in any DrawGenerator where self.round is used. effective_round = self.round.seq print("-------\nTaking as effective round of %s" % effective_round) for bracket in brackets.items(): - teams_list = bracket[1] # Team Array is second item - points = bracket[0] + teams_list = bracket[1] # Team Array is second item + points = bracket[0] total_debates = len(teams_list) // 2 print("BRACKET %s with %s teams" % (points, len(teams_list))) @@ -1182,11 +1175,11 @@ def generate_pairings(self, brackets): print(["%s - %s" % (teams_list.index(t) + 1, t) for t in folded_list[total_debates:]]) for i in range(1, effective_round): - # left-most bottom goes to position[1] on the top + # Left-most bottom goes to position[1] on the top folded_list.insert(1, (folded_list.pop(total_debates))) - # right-most top goes to right-most bottom + # Right-most top goes to right-most bottom folded_list.append(folded_list.pop(total_debates)) - #print "popping %s iteration %s" % (i, total_debates) + # Print "popping %s iteration %s" % (i, total_debates) print(["%s - %s" % (teams_list.index(t) + 1, t) for t in folded_list[:total_debates]]) print(["%s - %s" % (teams_list.index(t) + 1, t) for t in folded_list[total_debates:]]) @@ -1221,8 +1214,6 @@ def generate_pairings(self, brackets): pairings[points] = assigned_pairings - - return pairings diff --git a/draw/management/commands/deletedraw.py b/tabbycat/draw/management/commands/deletedraw.py similarity index 73% rename from draw/management/commands/deletedraw.py rename to tabbycat/draw/management/commands/deletedraw.py index 6c4321334d4..8137aaa1e98 100644 --- a/draw/management/commands/deletedraw.py +++ b/tabbycat/draw/management/commands/deletedraw.py @@ -1,8 +1,8 @@ -from utils.management.base import RoundCommand, CommandError -from ...models import Debate -from tournaments.models import Round +from utils.management.base import RoundCommand + from ...dbutils import delete_round_draw + class Command(RoundCommand): help = "Deletes all debates in a round (or rounds)." @@ -11,4 +11,3 @@ class Command(RoundCommand): def handle_round(self, round, **options): self.stdout.write("Deleting all debates in round '{}'...".format(round.name)) delete_round_draw(round) - diff --git a/draw/management/commands/generatesideallocations.py b/tabbycat/draw/management/commands/generatesideallocations.py similarity index 96% rename from draw/management/commands/generatesideallocations.py rename to tabbycat/draw/management/commands/generatesideallocations.py index 690ae8a8641..b65aded5def 100644 --- a/draw/management/commands/generatesideallocations.py +++ b/tabbycat/draw/management/commands/generatesideallocations.py @@ -1,8 +1,11 @@ -from utils.management.base import RoundCommand, CommandError -from ...models import TeamPositionAllocation from random import shuffle from operator import attrgetter +from utils.management.base import CommandError, RoundCommand + +from ...models import TeamPositionAllocation + + class Command(RoundCommand): help = "Adds randomly generated side allocations to teams for all preliminary rounds." diff --git a/draw/manager.py b/tabbycat/draw/manager.py similarity index 68% rename from draw/manager.py rename to tabbycat/draw/manager.py index 51267c71aae..1bc37a821ee 100644 --- a/draw/manager.py +++ b/tabbycat/draw/manager.py @@ -1,30 +1,27 @@ -from collections import defaultdict, Counter -from itertools import chain import random -from participants.models import Team from tournaments.models import Round from standings.teams import TeamStandingsGenerator from .models import Debate, DebateTeam, TeamPositionAllocation -from .generator import DrawGenerator +from .generator import DrawGenerator, Pairing OPTIONS_TO_CONFIG_MAPPING = { - "avoid_institution": "draw_rules__avoid_same_institution", - "avoid_history": "draw_rules__avoid_team_history", - "history_penalty": "draw_rules__team_history_penalty", - "institution_penalty": "draw_rules__team_institution_penalty", - "side_allocations": "draw_rules__draw_side_allocations", - "avoid_conflicts": "draw_rules__draw_avoid_conflicts", - "odd_bracket" : "draw_rules__draw_odd_bracket", - "pairing_method" : "draw_rules__draw_pairing_method", + "avoid_institution" : "draw_rules__avoid_same_institution", + "avoid_history" : "draw_rules__avoid_team_history", + "history_penalty" : "draw_rules__team_history_penalty", + "institution_penalty" : "draw_rules__team_institution_penalty", + "side_allocations" : "draw_rules__draw_side_allocations", + "avoid_conflicts" : "draw_rules__draw_avoid_conflicts", + "odd_bracket" : "draw_rules__draw_odd_bracket", + "pairing_method" : "draw_rules__draw_pairing_method", } TPA_MAP = {TeamPositionAllocation.POSITION_AFFIRMATIVE: "aff", TeamPositionAllocation.POSITION_NEGATIVE: "neg"} -def DrawManager(round, active_only=True): +def DrawManager(round, active_only=True): # flake8: noqa klass = DRAW_MANAGER_CLASSES[round.draw_type] return klass(round, active_only) @@ -32,15 +29,21 @@ def DrawManager(round, active_only=True): class BaseDrawManager: """Creates, modifies and retrieves relevant Debate objects relating to a draw.""" - relevant_options = ["avoid_institution", "avoid_history", "history_penalty", "institution_penalty", "side_allocations"] + relevant_options = ["avoid_institution", "avoid_history", "history_penalty", "institution_penalty"] def __init__(self, round, active_only=True): self.round = round - self.debate_set = round.debate_set self.active_only = active_only def get_teams(self): - return self.round.active_teams.all() if self.active_only else self.round.tournament.team_set.all() + if self.active_only: + return self.round.active_teams.all() + else: + return self.round.tournament.team_set.all() + + def get_results(self): + # Only needed for EliminationDrawManager + return None def _populate_aff_counts(self, teams): if self.round.prev: @@ -74,7 +77,7 @@ def _make_debates(self, pairings): DebateTeam(debate=debate, team=pairing.teams[1], position=DebateTeam.POSITION_NEGATIVE).save() def delete(self): - self.debate_set.all().delete() + self.round.debate_set.all().delete() def create(self): """Generates a draw and populates the database with it.""" @@ -85,16 +88,17 @@ def create(self): self.delete() teams = self.get_teams() + results = self.get_results() self._populate_aff_counts(teams) self._populate_team_position_allocations(teams) options = dict() for key in self.relevant_options: options[key] = self.round.tournament.preferences[OPTIONS_TO_CONFIG_MAPPING[key]] - if options["side_allocations"] == "manual-ballot": + if options.get("side_allocations") == "manual-ballot": options["side_allocations"] = "balance" - drawer = DrawGenerator(self.draw_type, teams, self.round, results=None, **options) + drawer = DrawGenerator(self.draw_type, teams, self.round, results=results, **options) pairings = drawer.generate() self._make_debates(pairings) self.round.draw_status = Round.STATUS_DRAFT @@ -103,7 +107,7 @@ def create(self): class RandomDrawManager(BaseDrawManager): draw_type = "random" - relevant_options = BaseDrawManager.relevant_options + ["avoid_conflicts"] + relevant_options = BaseDrawManager.relevant_options + ["avoid_conflicts", "side_allocations"] class ManualDrawManager(BaseDrawManager): @@ -112,7 +116,7 @@ class ManualDrawManager(BaseDrawManager): class PowerPairedDrawManager(BaseDrawManager): draw_type = "power_paired" - relevant_options = BaseDrawManager.relevant_options + ["avoid_conflicts", "odd_bracket", "pairing_method"] + relevant_options = BaseDrawManager.relevant_options + ["avoid_conflicts", "odd_bracket", "pairing_method", "side_allocations"] def get_teams(self): metrics = self.round.tournament.pref('team_standings_precedence') @@ -132,13 +136,26 @@ class RoundRobinDrawManager(BaseDrawManager): draw_type = "round_robin" -class FirstEliminationDrawManager(BaseDrawManager): +class BaseEliminationDrawManager(BaseDrawManager): + def get_teams(self): + breaking_teams = self.round.break_category.breakingteam_set.filter( + break_rank__isnull=False).order_by('break_rank').select_related('team') + return [bt.team for bt in breaking_teams] + + +class FirstEliminationDrawManager(BaseEliminationDrawManager): draw_type = "first_elimination" -class EliminationDrawManager(BaseDrawManager): +class EliminationDrawManager(BaseEliminationDrawManager): draw_type = "elimination" + def get_results(self): + last_round = self.round.break_category.round_set.filter(seq__lt=self.round.seq).order_by('-seq').first() + debates = last_round.debate_set.all() + result = [Pairing.from_debate(debate) for debate in debates] + return result + DRAW_MANAGER_CLASSES = { Round.DRAW_RANDOM: RandomDrawManager, diff --git a/draw/migrations/0001_initial.py b/tabbycat/draw/migrations/0001_initial.py similarity index 100% rename from draw/migrations/0001_initial.py rename to tabbycat/draw/migrations/0001_initial.py diff --git a/draw/migrations/0002_teamvenuepreference_team.py b/tabbycat/draw/migrations/0002_teamvenuepreference_team.py similarity index 100% rename from draw/migrations/0002_teamvenuepreference_team.py rename to tabbycat/draw/migrations/0002_teamvenuepreference_team.py diff --git a/draw/migrations/0003_auto_20160103_1927.py b/tabbycat/draw/migrations/0003_auto_20160103_1927.py similarity index 100% rename from draw/migrations/0003_auto_20160103_1927.py rename to tabbycat/draw/migrations/0003_auto_20160103_1927.py diff --git a/draw/migrations/0004_auto_20160109_1834.py b/tabbycat/draw/migrations/0004_auto_20160109_1834.py similarity index 100% rename from draw/migrations/0004_auto_20160109_1834.py rename to tabbycat/draw/migrations/0004_auto_20160109_1834.py diff --git a/draw/migrations/0005_auto_20160109_1904.py b/tabbycat/draw/migrations/0005_auto_20160109_1904.py similarity index 100% rename from draw/migrations/0005_auto_20160109_1904.py rename to tabbycat/draw/migrations/0005_auto_20160109_1904.py diff --git a/draw/migrations/0006_auto_20160228_1838.py b/tabbycat/draw/migrations/0006_auto_20160228_1838.py similarity index 100% rename from draw/migrations/0006_auto_20160228_1838.py rename to tabbycat/draw/migrations/0006_auto_20160228_1838.py diff --git a/draw/migrations/0007_debate_time.py b/tabbycat/draw/migrations/0007_debate_time.py similarity index 100% rename from draw/migrations/0007_debate_time.py rename to tabbycat/draw/migrations/0007_debate_time.py diff --git a/draw/migrations/0008_delete_teamvenuepreference_institutionvenuepreference.py b/tabbycat/draw/migrations/0008_delete_teamvenuepreference_institutionvenuepreference.py similarity index 100% rename from draw/migrations/0008_delete_teamvenuepreference_institutionvenuepreference.py rename to tabbycat/draw/migrations/0008_delete_teamvenuepreference_institutionvenuepreference.py diff --git a/tabbycat/draw/migrations/0009_auto_20160621_1129.py b/tabbycat/draw/migrations/0009_auto_20160621_1129.py new file mode 100644 index 00000000000..37b683e3b53 --- /dev/null +++ b/tabbycat/draw/migrations/0009_auto_20160621_1129.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-06-21 11:29 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('draw', '0008_delete_teamvenuepreference_institutionvenuepreference'), + ] + + operations = [ + migrations.AlterField( + model_name='debate', + name='division', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='divisions.Division'), + ), + ] diff --git a/tabbycat/draw/migrations/0010_auto_20160630_1016.py b/tabbycat/draw/migrations/0010_auto_20160630_1016.py new file mode 100644 index 00000000000..99d7c59adcd --- /dev/null +++ b/tabbycat/draw/migrations/0010_auto_20160630_1016.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-06-30 10:16 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('draw', '0009_auto_20160621_1129'), + ] + + operations = [ + migrations.AlterField( + model_name='debate', + name='importance', + field=models.IntegerField(default=0), + ), + ] diff --git a/importer/tests/__init__.py b/tabbycat/draw/migrations/__init__.py similarity index 100% rename from importer/tests/__init__.py rename to tabbycat/draw/migrations/__init__.py diff --git a/draw/models.py b/tabbycat/draw/models.py similarity index 53% rename from draw/models.py rename to tabbycat/draw/models.py index 162278512d7..55e6d6504f5 100644 --- a/draw/models.py +++ b/tabbycat/draw/models.py @@ -1,19 +1,22 @@ +import logging +from warnings import warn + from django.db import models from django.utils.functional import cached_property -from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned +from django.core.exceptions import ObjectDoesNotExist -from tournaments.models import SRManager from participants.models import Team -from venues.conflicts import venue_conflicts + from .generator import DRAW_FLAG_DESCRIPTIONS +logger = logging.getLogger(__name__) + class DebateManager(models.Manager): use_for_related_fields = True def get_queryset(self): - return super(DebateManager, - self).get_queryset().select_related('round') + return super().get_queryset().select_related('round') class Debate(models.Model): @@ -30,18 +33,19 @@ class Debate(models.Model): round = models.ForeignKey('tournaments.Round', db_index=True) venue = models.ForeignKey('venues.Venue', blank=True, null=True) - division = models.ForeignKey('tournaments.Division', blank=True, null=True) + division = models.ForeignKey('divisions.Division', blank=True, null=True) bracket = models.FloatField(default=0) room_rank = models.IntegerField(default=0) - time = models.DateTimeField(blank=True, null=True, + time = models.DateTimeField( + blank=True, null=True, help_text="The time/date of a debate if it is specifically scheduled") # comma-separated list of strings flags = models.CharField(max_length=100, blank=True, null=True) - importance = models.IntegerField(default=2) + importance = models.IntegerField(default=0) result_status = models.CharField(max_length=1, choices=STATUS_CHOICES, default=STATUS_NONE) @@ -62,17 +66,46 @@ def __str__(self): @property def teams(self): - return Team.objects.filter(debateteam__debate=self) + try: + return [self._aff_team, self._neg_team] + except AttributeError: + return Team.objects.filter(debateteam__debate=self) - @cached_property + @property def aff_team(self): - aff_dt = self.aff_dt - return aff_dt.team + try: + return self._aff_team # may be populated by Round.debate_set_with_prefetches + except AttributeError: + self._aff_team = Team.objects.select_related('institution').get( + debateteam__debate=self, debateteam__position=DebateTeam.POSITION_AFFIRMATIVE) + return self._aff_team - @cached_property + @property def neg_team(self): - neg_dt = self.neg_dt - return neg_dt.team + try: + return self._neg_team + except AttributeError: + self._neg_team = Team.objects.select_related('institution').get( + debateteam__debate=self, debateteam__position=DebateTeam.POSITION_NEGATIVE) + return self._neg_team + + @property + def aff_dt(self): + try: + return self._aff_dt # may be populated by Round.debate_set_with_prefetches + except AttributeError: + self._aff_dt = self.debateteam_set.select_related('team', 'team__institution').get( + position=DebateTeam.POSITION_AFFIRMATIVE) + return self._aff_dt + + @property + def neg_dt(self): + try: + return self._neg_dt # may be populated by Round.debate_set_with_prefetches + except AttributeError: + self._neg_dt = self.debateteam_set.select_related('team', 'team__institution').get( + position=DebateTeam.POSITION_NEGATIVE) + return self._neg_dt # may be populated by Round.debate_set_with_prefetches def get_team(self, side): return getattr(self, '%s_team' % side) @@ -81,22 +114,6 @@ def get_dt(self, side): """dt = DebateTeam""" return getattr(self, '%s_dt' % side) - @cached_property - def aff_dt(self): - aff_dt = DebateTeam.objects.select_related( - 'team', 'team__institution').get( - debate=self, - position=DebateTeam.POSITION_AFFIRMATIVE) - return aff_dt - - @cached_property - def neg_dt(self): - neg_dt = DebateTeam.objects.select_related( - 'team', 'team__institution').get( - debate=self, - position=DebateTeam.POSITION_NEGATIVE) - return neg_dt - def get_side(self, team): if self.aff_team == team: return 'aff' @@ -104,30 +121,25 @@ def get_side(self, team): return 'neg' return None - @cached_property + @property def confirmed_ballot(self): """Returns the confirmed BallotSubmission for this debate, or None if there is no such ballot submission.""" try: - return self.ballotsubmission_set.get(confirmed=True) - except ObjectDoesNotExist: # BallotSubmission isn't defined yet, so can't use BallotSubmission.DoesNotExist - return None - - @property - def ballotsubmission_set_by_version(self): - return self.ballotsubmission_set.order_by('version') - - @property - def ballotsubmission_set_by_version_except_discarded(self): - return self.ballotsubmission_set.filter( - discarded=False).order_by('version') + return self._confirmed_ballot + except AttributeError: + try: + self._confirmed_ballot = self.ballotsubmission_set.get(confirmed=True) + except ObjectDoesNotExist: + self._confirmed_ballot = None + return self._confirmed_ballot @property def identical_ballotsubs_dict(self): """Returns a dict. Keys are BallotSubmissions, values are lists of version numbers of BallotSubmissions that are identical to the key's BallotSubmission. Excludes discarded ballots (always).""" - ballotsubs = self.ballotsubmission_set_by_version_except_discarded + ballotsubs = self.ballotsubmission_set.exclude(discarded=True).order_by('version') result = {b: list() for b in ballotsubs} for ballotsub1 in ballotsubs: # Save a bit of time by avoiding comparisons already done. @@ -149,65 +161,38 @@ def flags_all(self): return [DRAW_FLAG_DESCRIPTIONS[f] for f in self.flags.split(",")] @property - def all_conflicts(self): - return self.draw_conflicts + self.adjudicator_conflicts + venue_conflicts(self) + def history(self): + try: + return self._history + except AttributeError: + self._history = self.aff_team.seen(self.neg_team, before_round=self.round.seq) + return self._history @cached_property def draw_conflicts(self): d = [] - history = self.aff_team.seen(self.neg_team, before_round=self.round.seq) + history = self.history if history == 1: d.append("Teams have met once") elif history == 2: d.append("Teams have met twice") elif history > 2: d.append("Teams have met %d times" % (history,)) - if self.aff_team.institution == self.neg_team.institution: + if self.aff_team.institution_id == self.neg_team.institution_id: d.append("Teams are from the same institution") return d - @cached_property - def adjudicator_conflicts(self): - class Conflict(object): - def __init__(self, adj, team): - self.adj = adj - self.team = team - - def __str__(self): - return 'Adjudicator %s conflicts with %s' % (self.adj, self.team) - - a = [] - for t, adj in self.adjudicators: - for team in (self.aff_team, self.neg_team): - if adj.conflict_with(team): - a.append(Conflict(adj, team)) - - return a - - @cached_property + @property def adjudicators(self): - from adjallocation.models import DebateAdjudicator, AdjudicatorAllocation """Returns an AdjudicatorAllocation containing the adjudicators for this debate.""" - adjs = DebateAdjudicator.objects.filter( - debate=self).select_related('adjudicator') - alloc = AdjudicatorAllocation(self) - for a in adjs: - if a.type == a.TYPE_CHAIR: - alloc.chair = a.adjudicator - if a.type == a.TYPE_PANEL: - alloc.panel.append(a.adjudicator) - if a.type == a.TYPE_TRAINEE: - alloc.trainees.append(a.adjudicator) - return alloc - - @property - def chair(self): - from adjallocation.models import DebateAdjudicator - da_adj = list(DebateAdjudicator.objects.filter(debate=self, type="C")) - a_adj = da_adj[0].adjudicator - return a_adj + try: + return self._adjudicators + except AttributeError: + from adjallocation.allocation import AdjudicatorAllocation + self._adjudicators = AdjudicatorAllocation(self, from_db=True) + return self._adjudicators @property def matchup(self): @@ -215,9 +200,23 @@ def matchup(self): self.neg_team.short_name) @property - def division_motion(self): + def get_division_motions(self): from motions.models import Motion - return Motion.objects.filter(round=self.round, divisions=self.division) + motions = Motion.objects.filter(round=self.round, divisions=self.division) + if motions.count() > 0: + return motions[0] # Pretty sure this should never be > 1 + else: + # Its easiest to assume a division motion is always present, so + # return a fake one if it is not + from motions.models import Motion + return Motion(text='-', reference='-') + + +class DebateTeamManager(models.Manager): + use_for_related_fields = True + + def get_queryset(self): + return super().get_queryset().select_related('debate') class DebateTeam(models.Model): @@ -228,7 +227,7 @@ class DebateTeam(models.Model): (POSITION_NEGATIVE, 'Negative'), (POSITION_UNALLOCATED, 'Unallocated'), ) - objects = SRManager() + objects = DebateTeamManager() debate = models.ForeignKey(Debate, db_index=True) team = models.ForeignKey('participants.Team') @@ -237,28 +236,52 @@ class DebateTeam(models.Model): def __str__(self): return '{} in {}'.format(self.team.short_name, self.debate) - @cached_property # TODO: this slows down the standings pages reasonably heavily - def opposition(self): + @property + def opponent(self): try: - return DebateTeam.objects.exclude( - position=self.position).select_related( - 'team', 'team__institution').get(debate=self.debate) - except (DebateTeam.DoesNotExist, DebateTeam.MultipleObjectsReturned): - logger.error("Error finding opposition: %s, %s", self.debate, - self.position) - return None + return self._opponent + except AttributeError: + try: + self._opponent = DebateTeam.objects.exclude(position=self.position).select_related( + 'team', 'team__institution').get(debate=self.debate) + except (DebateTeam.DoesNotExist, DebateTeam.MultipleObjectsReturned): + logger.warning("No opponent found for %s", str(self)) + self._opponent = None + return self._opponent - @cached_property + @property + def opposition(self): + # Added 11/7/2016, remove after 11/8/2016 + warn("DebateTeam.opposition is deprecated, use DebateTeam.opponent instead.", stacklevel=2) + return self.opponent + + @property def result(self): - """Returns 'won' if won, 'lost' if lost, 'result unknown' if no result confirmed.""" - if self.debate.confirmed_ballot and self.debate.confirmed_ballot.ballot_set: - ballotset = self.debate.confirmed_ballot.ballot_set - if ballotset.aff_win and self.position == DebateTeam.POSITION_AFFIRMATIVE: - return 'won' - if ballotset.neg_win and self.position == DebateTeam.POSITION_NEGATIVE: - return 'won' + # Added 4/7/2016, remove after 4/8/2016 + warn("DebateTeam.result is deprecated, use DebateTeam.get_result_display() instead.", stacklevel=2) + + if self.win is True: + return 'won' + elif self.win is False: return 'lost' - return 'result unknown' + else: + return 'result unknown' + + @property + def win(self): + """Convenience function. Returns True if this team won, False if this + team lost, or None if there isn't a confirmed result. + + This result is stored for the lifetime of the instance -- it won't + update on the same instance if a result is entered.""" + try: + return self._win + except AttributeError: + try: + self._win = self.teamscore_set.get(ballot_submission__confirmed=True).win + except ObjectDoesNotExist: + self._win = None + return self._win class TeamPositionAllocation(models.Model): diff --git a/draw/one_up_one_down.py b/tabbycat/draw/one_up_one_down.py similarity index 93% rename from draw/one_up_one_down.py rename to tabbycat/draw/one_up_one_down.py index c810afa1cfa..dce4dcfafab 100644 --- a/draw/one_up_one_down.py +++ b/tabbycat/draw/one_up_one_down.py @@ -35,7 +35,7 @@ def dp(data): of indices of the optimal swap combinations. The first item is the maximum possible sum so obtained.""" - N = len(data) + 1 + n = len(data) + 1 # 'state' is the cumulative sum of the relevant elements. # 'action' elements are 1 if this integer should be included, and 0 if @@ -43,15 +43,15 @@ def dp(data): # it is included (i.e. a non-nullified 1). We keep nullified 1s in the # list because they might become non-nullified again if another 1 is # added to the end of a number of consecutive 1s. - state = [0] * (N + 1) - action = [0] * (N + 1) + state = [0] * (n + 1) + action = [0] * (n + 1) # If we "activate" this element, then we must consequentially exclude the # previous element. Given that, we would improve the cumulative sum if, # and only if, adding this element to the cumulative sum as of *two* # elements ago (to form the potential cumulative sum of this element) # would beat the cumulative sum as of last element. - for i in range(2, N+1): + for i in range(2, n+1): if (state[i-2] + data[i-2]) > state[i-1]: action[i] = 1 state[i] = state[i-2] + data[i-2] @@ -59,21 +59,21 @@ def dp(data): action[i] = 0 state[i] = state[i-1] - j = N - L = [] - #while j >= 0: + j = n + l = [] + # while j >= 0: # L.insert(0, j) # j -= (action[j] + 1) - #return state[N], L + # return state[n], L # Now go back through the list starting at the end (since a 1 nullifies # the 1 immediately preceding, assuming the former is not itself # nullified). while j >= 2: if action[j]: - L.insert(0, j-2) # insert index corresponding to start of swap + l.insert(0, j-2) # Insert index corresponding to start of swap j -= (action[j] + 1) - return state[N], L + return state[n], l def score_swap(self, debate1, debate2): """Returns an integer representing the improvement from swapping the @@ -99,7 +99,7 @@ def score_swap(self, debate1, debate2): def badness(i, h): return i.count(True) * self.institution_penalty + sum(h) \ - * self.history_penalty + * self.history_penalty # Discount by 1e-3 so that, if there are two otherwise-equivalent # swap combinations, fewer swaps is preferred to more swaps diff --git a/tabbycat/draw/prefetch.py b/tabbycat/draw/prefetch.py new file mode 100644 index 00000000000..3ca1abe4c94 --- /dev/null +++ b/tabbycat/draw/prefetch.py @@ -0,0 +1,92 @@ +"""Functions that prefetch data for efficiency.""" + +import logging + +from django.db.models.expressions import RawSQL + +from .models import Debate, DebateTeam + +logger = logging.getLogger(__name__) + + +def populate_teams(debates, speakers=True, institutions=False): + """Sets attributes `_aff_dt`, `_aff_team`, `_neg_dt`, `_neg_team` on each + debate in `debates`, each being the appropriate Team or DebateTeam. + This can be used for efficiency, since it retrieves all of the + information in bulk in a single SQL query. Operates in-place. + + If `speakers` is True, it also prefetches Speaker instances. + """ + debates_by_id = {debate.id: debate for debate in debates} + + debateteams = DebateTeam.objects.filter(debate__in=debates).select_related('team', 'team__institution') + if speakers: + debateteams = debateteams.prefetch_related('team__speaker_set') + for debateteam in debateteams: + debate = debates_by_id[debateteam.debate_id] + if debateteam.position == DebateTeam.POSITION_AFFIRMATIVE: + debate._aff_dt = debateteam + debate._aff_team = debateteam.team + elif debateteam.position == DebateTeam.POSITION_NEGATIVE: + debate._neg_dt = debateteam + debate._neg_team = debateteam.team + + +def populate_opponents(debateteams, speakers=True): + """Sets the attribute `_opponent` on each DebateTeam in debateteams, to + the DebateTeam representing their opponents. + + If `speakers` is True, it also prefetches Speaker instances. + """ + + ids = [dt.id for dt in debateteams] + debateteams_annotated = DebateTeam.objects.filter(id__in=ids).annotate( + opponent_id=RawSQL(""" + SELECT opponent.id + FROM draw_debateteam AS opponent + WHERE opponent.debate_id = draw_debateteam.debate_id + AND opponent.id != draw_debateteam.id""", ()) + ) + debateteams_annotated_by_id = {dt.id: dt for dt in debateteams_annotated} + opponent_ids = [dt.opponent_id for dt in debateteams_annotated] + + opponent_dts = DebateTeam.objects.select_related('team') + if speakers: + opponent_dts = opponent_dts.prefetch_related('team__speaker_set') + opponent_dts = opponent_dts.in_bulk(opponent_ids) + + for dt in debateteams: + dt_annotated = debateteams_annotated_by_id[dt.id] + try: + dt._opponent = opponent_dts[dt_annotated.opponent_id] + except KeyError: + logger.warning("No opponent found for %s", str(dt)) + dt._opponent = None + + +def populate_history(debates): + """Sets the attribute _history to the number of times the teams in the + debate have seen each other before the round of the debate.""" + + debates_by_id = {debate.id: debate for debate in debates} + + debates_annotated = Debate.objects.filter(id__in=debates_by_id.keys()).annotate( + past_debates=RawSQL(""" + SELECT DISTINCT COUNT(past_debate.id) + FROM draw_debate AS past_debate + JOIN draw_debateteam AS this_aff_dt ON this_aff_dt.debate_id = draw_debate.id + JOIN draw_debateteam AS this_neg_dt ON this_neg_dt.debate_id = draw_debate.id + JOIN tournaments_round AS this_round ON draw_debate.round_id = this_round.id + JOIN draw_debateteam AS past_aff_dt ON past_aff_dt.debate_id = past_debate.id + JOIN draw_debateteam AS past_neg_dt ON past_neg_dt.debate_id = past_debate.id + JOIN tournaments_round AS past_round ON past_debate.round_id = past_round.id + WHERE this_aff_dt.position = 'A' + AND this_neg_dt.position = 'N' + AND past_aff_dt.team_id = this_aff_dt.team_id + AND past_neg_dt.team_id = this_neg_dt.team_id + AND past_round.seq < this_round.seq""", + ()), + ) + + for debate in debates_annotated: + debates_by_id[debate.id]._history = debate.past_debates diff --git a/draw/templates/confirmations_view.html b/tabbycat/draw/templates/confirmations_view.html similarity index 89% rename from draw/templates/confirmations_view.html rename to tabbycat/draw/templates/confirmations_view.html index 521dc099c1b..70452c14c29 100644 --- a/draw/templates/confirmations_view.html +++ b/tabbycat/draw/templates/confirmations_view.html @@ -7,17 +7,17 @@ {% block content %} {% for adj in adjs %} -
    +
    -

    {{ adj }}

    +

    {{ adj.name }}

      {% for shift in adj.shifts %}
    • {{ shift.debate.round.tournament.short_name }} - {{ shift.debate.round.abbreviation }} — + {{ shift.debate.round.abbreviation }} — {{ shift.debate.division.venue_group }} @ {{ shift.debate.time.time|time:'h:i' }} {% if shift.timing_confirmed == True %} diff --git a/tabbycat/draw/templates/draw_base.html b/tabbycat/draw/templates/draw_base.html new file mode 100644 index 00000000000..4c2280c4629 --- /dev/null +++ b/tabbycat/draw/templates/draw_base.html @@ -0,0 +1,42 @@ +{% extends "base_vue_table.html" %} +{% load debate_tags %} + +{% block page-subnav-sections %} + + Edit Adjs + + + Edit Adjs (Old UI) + + + Edit Motions + + + Edit Venues + + + Edit Matchups + + {% if pref.allocation_confirmations %} + + Shift Confirms + + {% endif %} + {% if pref.enable_division_motions %} + + Assign Motions to Divisions + + {% endif %} + + Draw Details + + + Regenerate Draw + +{% endblock %} + +{% block page-subnav-actions %} + + Enter Results + +{% endblock %} diff --git a/draw/templates/draw_confirm_regeneration.html b/tabbycat/draw/templates/draw_confirm_regeneration.html similarity index 92% rename from draw/templates/draw_confirm_regeneration.html rename to tabbycat/draw/templates/draw_confirm_regeneration.html index 942e88e2f7d..35e183ceb82 100644 --- a/draw/templates/draw_confirm_regeneration.html +++ b/tabbycat/draw/templates/draw_confirm_regeneration.html @@ -8,7 +8,6 @@ Confirm Draw Deletion for {{ round.name }} {% endblock %} - {% block page-alerts %}
      @@ -17,7 +16,7 @@ their ballots and adjudicator allocations — and cannot be undone. You probably don't want to do this if any results have been entered!

      -
      + {% csrf_token %}

    + + + + + + + + + + {% for debate in draw %} + + + + + {% include "tables/debate_adjudicators_compact.html" %} + + {% endfor %} + {% for debate in possible_debates %} + + + + + + + {% endfor %} + +
    AffNegAdjudicators
    + {{ debate.venue }} + + {% if debate.aff_team %} +
    + {{ debate.aff_team.short_name }} {% if debate.aff_team.division %}(Div{{ debate.aff_team.division.name }}){% endif %} +
    + {% endif %} +
    + {% if debate.neg_team %} +
    + {{ debate.neg_team.short_name }} {% if debate.neg_team.division %}(Div{{ debate.neg_team.division.name }}){% endif %} +
    + {% endif %} +
    + +
    +
    +
    +
    + +
    + + + + + + + + +
    Unused Teams
    + {% for team in unused_teams %} +
    + {{ team.short_name }} {% if team.division %}(Div{{ team.division.name }}){% endif %} +
    + {% endfor %} +
    + +
    +
    +{% endblock content %} + +{% block js %} + {{ block.super }} + + +{% endblock js %} diff --git a/draw/templates/draw_set_debate_times.html b/tabbycat/draw/templates/draw_set_debate_times.html similarity index 88% rename from draw/templates/draw_set_debate_times.html rename to tabbycat/draw/templates/draw_set_debate_times.html index 83b4955107c..b39368fc12e 100644 --- a/draw/templates/draw_set_debate_times.html +++ b/tabbycat/draw/templates/draw_set_debate_times.html @@ -12,7 +12,7 @@ {% endblock %} {% block page-subnav-actions %} - + Apply Times to Debates {% endblock %} @@ -23,9 +23,9 @@
    -

    Assign Dates to Venue Groups

    +

    Assign Dates to Venue Groups

    - + {% csrf_token %}
      {% for vg in venue_groups %} @@ -47,7 +47,7 @@
      {{ vg.short_name }}
      -

      Assign Times to Divisions

      +

      Assign Times to Divisions

        {% for d in divisions %} @@ -75,7 +75,8 @@
        {{ d.name }} ({{ d.venue_group.short_name }})
        {% endblock %} -{% block extra-js %} +{% block js %} + {{ block.super }} -{% endblock extra-js %} +{% endblock js %} diff --git a/tabbycat/draw/templates/draw_status_confirmed.html b/tabbycat/draw/templates/draw_status_confirmed.html new file mode 100644 index 00000000000..9f661f847df --- /dev/null +++ b/tabbycat/draw/templates/draw_status_confirmed.html @@ -0,0 +1,213 @@ +{% extends "draw_base.html" %} +{% load humanize %} +{% load static %} +{% load debate_tags %} + +{% block page-title %}Draw for {{ round.name }}{% endblock %} +{% block head-title %} + 👀Draw for {{ round.name }} +{% endblock %} +{% block sub-title %} + {% if round.draw_status = round.STATUS_CONFIRMED %} + draw is confirmed but not released; + {% elif round.draw_status = round.STATUS_RELEASED %} + draw is confirmed and released; + {% else %} + DRAW STATUS ERROR, + {% endif %} + motions {{ round.motions_released|yesno:",are not" }} released +{% endblock %} + +{% block page-alerts %} + {% if round.motion_set.all.count == 0 %} +
        + There are currently no motions entered, which means results cannot be entered. + + Edit the motions. + +
        + {% endif %} + {% with no_venue=round.num_debates_without_venue %} + {% if no_venue > 0 %} +
        + {{ no_venue|apnumber|capfirst }} debate{{ no_venue|pluralize:" does,s do" }} not have a venue. + + Edit the venues. + +
        + {% endif %} + {% endwith %} + {% if active_adjs.count < draw.count %} +
        + There are currently fewer checked-in adjudicators than there are rooms. + + Check in some more adjudicators. + +
        + {% else %} + {% with no_chair=round.num_debates_without_chair even_panel=round.num_debates_with_even_panel %} + {% if no_chair > 0 or even_panel > 0 %} +
        + {% if no_chair > 0 %} + {{ no_chair|apnumber|capfirst }} debate{{ no_chair|pluralize:" does,s do" }} not have a chair. + {% endif %} + {% if even_panel > 0 %} + {{ even_panel|apnumber|capfirst }} debate{{ even_panel|pluralize:" has a panel,s have panels" }} with an even number of adjudicators. + {% endif %} + + Edit adjudicators. + +
        + {% endif %} + {% endwith %} + {% endif %} + + {% if round.draw_status = round.STATUS_RELEASED and not pref.public_draw %} +
        + You have released the draw, but it will not show to the public unless + 'public view of draw' setting is enabled in + + this tournament's configuration. +
        + {% endif %} + + {% if round.motions_released and not pref.public_motions %} +
        + You have released the motions, but they will not show to the public unless + the 'public view of motions' setting is enabled in + + this tournament's configuration. +
        + {% endif %} + +{% endblock %} + +{% block content %} + +
        + + + + + +
        + + {% if round.motions_released %} + + {% csrf_token %} + + + {% else %} +
        + {% csrf_token %} + +
        + {% endif %} + {% if round.draw_status = round.STATUS_CONFIRMED %} +
        + {% csrf_token %} + +
        + {% elif round.draw_status = round.STATUS_RELEASED %} +
        + {% csrf_token %} + +
        + {% endif %} +
        + +
        + + + + {{ block.super }} + +{% endblock content %} + +{% block js %} + + {{ block.super }} + +{% endblock %} diff --git a/tabbycat/draw/templates/draw_status_draft.html b/tabbycat/draw/templates/draw_status_draft.html new file mode 100644 index 00000000000..c16a617a640 --- /dev/null +++ b/tabbycat/draw/templates/draw_status_draft.html @@ -0,0 +1,11 @@ +{% extends "base_vue_table.html" %} +{% load debate_tags %} + +{% block page-subnav-actions %} +
        + {% csrf_token %} + +
        +{% endblock %} diff --git a/draw/templates/public_all_draws_for_institution.html b/tabbycat/draw/templates/public_all_draws_for_institution.html similarity index 77% rename from draw/templates/public_all_draws_for_institution.html rename to tabbycat/draw/templates/public_all_draws_for_institution.html index 58ff825f3fb..391d7a902ef 100644 --- a/draw/templates/public_all_draws_for_institution.html +++ b/tabbycat/draw/templates/public_all_draws_for_institution.html @@ -4,7 +4,6 @@ {% block head-title %}All Debates for Teams from {{ institution.name }}{% endblock %} {% block page-title %}All Debates for Teams from {{ institution.name }}{% endblock %} -{% block page-subnav-sections %}{% include "tables/table_search.html" %}{% endblock %} {% block content %}
        @@ -50,10 +49,8 @@ {% endif %} - {% for motion in debate.division_motion %} - {{ motion.reference }} - (view) - {% endfor %} + {{ debate.get_division_motions.reference }} + (view) {% endfor %} @@ -62,17 +59,3 @@
      {% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/draw/templates/public_all_draws_for_venue.html b/tabbycat/draw/templates/public_all_draws_for_venue.html similarity index 75% rename from draw/templates/public_all_draws_for_venue.html rename to tabbycat/draw/templates/public_all_draws_for_venue.html index 90f1d4857e9..b616ac64b90 100644 --- a/draw/templates/public_all_draws_for_venue.html +++ b/tabbycat/draw/templates/public_all_draws_for_venue.html @@ -4,7 +4,6 @@ {% block head-title %}All Debates at {{ venue_group.name}}{% endblock %} {% block page-title %}All Debates at {{ venue_group.name}}{% endblock %} -{% block page-subnav-sections %}{% include "tables/table_search.html" %}{% endblock %} {% block content %}
      @@ -48,10 +47,8 @@ {{ debate.neg_team.short_name }} - {% for motion in debate.division_motion %} - {{ motion.reference }} - (view) - {% endfor %} + {{ debate.get_division_motions.reference }} + (view) {% endfor %} @@ -60,17 +57,3 @@
      {% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/participants/templates/public_all_tournament_institutions.html b/tabbycat/draw/templates/public_all_tournament_institutions.html similarity index 56% rename from participants/templates/public_all_tournament_institutions.html rename to tabbycat/draw/templates/public_all_tournament_institutions.html index 8ea18764ace..0238e773747 100644 --- a/participants/templates/public_all_tournament_institutions.html +++ b/tabbycat/draw/templates/public_all_tournament_institutions.html @@ -8,14 +8,10 @@ {% block content %} {% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/participants/templates/public_all_tournament_teams.html b/tabbycat/draw/templates/public_all_tournament_teams.html similarity index 52% rename from participants/templates/public_all_tournament_teams.html rename to tabbycat/draw/templates/public_all_tournament_teams.html index 769f113483e..2cbdc4f5d47 100644 --- a/participants/templates/public_all_tournament_teams.html +++ b/tabbycat/draw/templates/public_all_tournament_teams.html @@ -2,14 +2,13 @@ {% load debate_tags %} {% load static %} -{% block head-title %}All Teams{% endblock %} -{% block page-title %}All Teams{% endblock %} -{% block page-subnav-sections %}{% include "tables/table_search.html" %}{% endblock %} +{% block head-title %}Draws for All Teams{% endblock %} +{% block page-title %}Draws for All Teams{% endblock %} {% block content %}
      - +
      @@ -36,20 +35,3 @@ {% endblock content %} - -{% block extra-js %} - -{% endblock extra-js %} diff --git a/tournaments/templates/public_all_tournament_venues.html b/tabbycat/draw/templates/public_all_tournament_venues.html similarity index 62% rename from tournaments/templates/public_all_tournament_venues.html rename to tabbycat/draw/templates/public_all_tournament_venues.html index 42c25c9c75c..7d5c3dfdd31 100644 --- a/tournaments/templates/public_all_tournament_venues.html +++ b/tabbycat/draw/templates/public_all_tournament_venues.html @@ -8,9 +8,9 @@ {% block content %} diff --git a/draw/templates/public_draw_display_all.html b/tabbycat/draw/templates/public_draw_display_all.html similarity index 77% rename from draw/templates/public_draw_display_all.html rename to tabbycat/draw/templates/public_draw_display_all.html index f1fa6658188..d52072ff000 100644 --- a/draw/templates/public_draw_display_all.html +++ b/tabbycat/draw/templates/public_draw_display_all.html @@ -4,7 +4,6 @@ {% block head-title %}All Draws{% endblock %} {% block page-title %}All Draws{% endblock %} -{% block page-subnav-sections %}{% include "tables/table_search.html" %}{% endblock %} {% block content %}
      @@ -58,10 +57,8 @@ {% if pref.enable_division_motions %}
      {% endif %} {% if not pref.enable_divisions %} @@ -78,18 +75,3 @@

      No rounds have released draws yet.

      {% endblock content %} - -{% block extra-js %} - - -{% endblock extra-js %} diff --git a/motions/__init__.py b/tabbycat/draw/tests/__init__.py similarity index 100% rename from motions/__init__.py rename to tabbycat/draw/tests/__init__.py diff --git a/draw/tests/generate_standings.py b/tabbycat/draw/tests/generate_standings.py similarity index 89% rename from draw/tests/generate_standings.py rename to tabbycat/draw/tests/generate_standings.py index 7f80e6cfc37..6a544ce2309 100644 --- a/draw/tests/generate_standings.py +++ b/tabbycat/draw/tests/generate_standings.py @@ -9,26 +9,27 @@ This script must be run from the directory it is in.""" -# Some import gymnastics. -import os.path, sys -draw_dir = os.path.abspath(os.path.join("..", "..")) -if draw_dir not in sys.path: sys.path.append(draw_dir) -print(draw_dir) -del draw_dir +import os.path +import sys +import string +import random +import argparse from draw.tests.utils import TestTeam from draw.generator import DrawGenerator -import string -import random -import itertools +draw_dir = os.path.abspath(os.path.join("..", "..")) +if draw_dir not in sys.path: + sys.path.append(draw_dir) +print(draw_dir) +del draw_dir -import argparse parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("rounds", type=int, help="Number of rounds") parser.add_argument("teams", type=int, help="Number of teams") parser.add_argument("insts", type=int, help="Number of institutions") args = parser.parse_args() + R = args.rounds T = args.teams I = args.insts @@ -36,7 +37,7 @@ assert(T % 2 == 0) teams = list() -for i in range(1,T+1): +for i in range(1, T+1): team = TestTeam(i, random.choice(string.uppercase[:I]), 0, list(), aff_count=0) teams.append(team) @@ -70,9 +71,11 @@ for team in sorted(teams, key=lambda x: x.points, reverse=True): print("({id}, '{inst}', {points}, {hist}, {aff_count}),".format( id=team.id, inst=team.institution, points=team.points, - hist=[t.id for t in team.hist], aff_count=team.aff_count)) + hist=[t.id for t in team.hist], aff_count=team.aff_count)) + print("") + for team in sorted(teams, key=lambda x: x.points, reverse=True): print("{id}, {inst}, {points}, {hist}, {aff_count}".format( id=team.id, inst=team.institution, points=team.points, - hist=", ".join([str(t.id) for t in team.hist]), aff_count=team.aff_count)) + hist=", ".join([str(t.id) for t in team.hist]), aff_count=team.aff_count)) diff --git a/draw/tests/test_draw.py b/tabbycat/draw/tests/test_draw.py similarity index 78% rename from draw/tests/test_draw.py rename to tabbycat/draw/tests/test_draw.py index d75fd359e65..59b8855cb2a 100644 --- a/draw/tests/test_draw.py +++ b/tabbycat/draw/tests/test_draw.py @@ -1,12 +1,15 @@ -import os.path, sys import unittest -from collections import OrderedDict -from .. import DrawGenerator, Pairing, DrawError import copy -from .utils import TestTeam, TestRound + +from collections import OrderedDict + +from .. import DrawError, DrawGenerator, Pairing +from ..utils import partial_break_round_split +from .utils import TestTeam DUMMY_TEAMS = [TestTeam(1, 'A', allocated_side="aff"), TestTeam(2, 'B', allocated_side="neg")] + class TestRandomDrawGenerator(unittest.TestCase): """Basic unit test for random draws. Because it's random, you can't really do much to test it.""" @@ -16,6 +19,7 @@ class TestRandomDrawGenerator(unittest.TestCase): def test_invalid_option(self): teams = [TestTeam(*args, aff_count=0) for args in self.teams] + def go(): self.rd = DrawGenerator("random", teams, None, random=True) self.assertRaises(ValueError, go) @@ -151,9 +155,9 @@ def test_intermediate_brackets_avoid_conflicts_1(self): ]) expected = OrderedDict([ (4, [1, 2, 3, 5]), - (3.5, [4, 6]), # bubble-up (institution) + (3.5, [4, 6]), # Bubble-up (institution) (3, [7, 8]), - (2.5, [9, 11]), # bubble-down (history, history) + (2.5, [9, 11]), # Bubble-down (history, history) (2, [10, 12, 13, 14]), (1, [15, 16]) ]) @@ -168,9 +172,9 @@ def test_intermediate_brackets_avoid_conflicts_2(self): ]) expected = OrderedDict([ (4, [1, 2, 3, 5]), - (3.5, [4, 6]), # bubble-up (institution) + (3.5, [4, 6]), # Bubble-up (institution) (3, [7, 9]), - (2.5, [8, 10]), # bubble-up (history) + (2.5, [8, 10]), # Bubble-up (history) (2, [11, 12, 13, 14]), (1, [15, 16]) ]) @@ -185,9 +189,9 @@ def test_intermediate_brackets_avoid_conflicts_3(self): ]) expected = OrderedDict([ (4, [1, 2, 3, 5]), - (3.5, [4, 6]), # bubble-up (institution) + (3.5, [4, 6]), # bubble-up (institution) (3, [7, 8]), - (2.5, [9, 11]), # bubble-down (history, institution) + (2.5, [9, 11]), # bubble-down (history, institution) (2, [10, 12, 13, 14]), (1, [15, 16]) ]) @@ -219,9 +223,9 @@ def test_intermediate_brackets_avoid_conflicts_exhaust(self): ]) expected = OrderedDict([ (4, [1, 2, 3, 5]), - (3.5, [4, 6]), # bubble-up (institution) + (3.5, [4, 6]), # Bubble-up (institution) (3, [7, 8]), - (2.5, [9, 10]), # no bubble (exhausted) + (2.5, [9, 10]), # No bubble (exhausted) (2, [11, 12, 13, 14]), (1, [15, 16]) ]) @@ -340,95 +344,97 @@ class TestPowerPairedDrawGenerator(unittest.TestCase): # result. standings = dict() standings[1] = [((12, 'B', 4, [26, 11, 15, 14]), {"aff_count": 2, "allocated_side": "aff"}), - (( 2, 'D', 3, [22, 16, 20, 10]), {"aff_count": 2, "allocated_side": "aff"}), - (( 3, 'E', 3, [23, 20, 25, 4]), {"aff_count": 2, "allocated_side": "aff"}), - ((11, 'B', 3, [ 1, 12, 23, 22]), {"aff_count": 2, "allocated_side": "neg"}), - (( 6, 'E', 3, [19, 15, 18, 9]), {"aff_count": 2, "allocated_side": "neg"}), + ((2, 'D', 3, [22, 16, 20, 10]), {"aff_count": 2, "allocated_side": "aff"}), + ((3, 'E', 3, [23, 20, 25, 4]), {"aff_count": 2, "allocated_side": "aff"}), + ((11, 'B', 3, [1, 12, 23, 22]), {"aff_count": 2, "allocated_side": "neg"}), + ((6, 'E', 3, [19, 15, 18, 9]), {"aff_count": 2, "allocated_side": "neg"}), ((17, 'E', 3, [21, 14, 7, 25]), {"aff_count": 2, "allocated_side": "neg"}), - (( 4, 'B', 3, [18, 25, 5, 3]), {"aff_count": 3, "allocated_side": "aff"}), + ((4, 'B', 3, [18, 25, 5, 3]), {"aff_count": 3, "allocated_side": "aff"}), ((14, 'A', 3, [24, 17, 9, 12]), {"aff_count": 2, "allocated_side": "aff"}), - (( 8, 'A', 3, [15, 24, 1, 15]), {"aff_count": 2, "allocated_side": "neg"}), - (( 7, 'D', 2, [16, 9, 17, 16]), {"aff_count": 2, "allocated_side": "aff"}), - (( 9, 'D', 2, [ 5, 7, 14, 6]), {"aff_count": 2, "allocated_side": "aff"}), - ((15, 'B', 2, [ 8, 6, 12, 8]), {"aff_count": 2, "allocated_side": "neg"}), - ((18, 'B', 2, [ 4, 21, 6, 21]), {"aff_count": 2, "allocated_side": "neg"}), - ((22, 'A', 2, [ 2, 10, 16, 11]), {"aff_count": 2, "allocated_side": "neg"}), - ((23, 'A', 2, [ 3, 19, 11, 5]), {"aff_count": 2, "allocated_side": "aff"}), + ((8, 'A', 3, [15, 24, 1, 15]), {"aff_count": 2, "allocated_side": "neg"}), + ((7, 'D', 2, [16, 9, 17, 16]), {"aff_count": 2, "allocated_side": "aff"}), + ((9, 'D', 2, [5, 7, 14, 6]), {"aff_count": 2, "allocated_side": "aff"}), + ((15, 'B', 2, [8, 6, 12, 8]), {"aff_count": 2, "allocated_side": "neg"}), + ((18, 'B', 2, [4, 21, 6, 21]), {"aff_count": 2, "allocated_side": "neg"}), + ((22, 'A', 2, [2, 10, 16, 11]), {"aff_count": 2, "allocated_side": "neg"}), + ((23, 'A', 2, [3, 19, 11, 5]), {"aff_count": 2, "allocated_side": "aff"}), ((24, 'B', 2, [14, 8, 19, 20]), {"aff_count": 3, "allocated_side": "aff"}), ((25, 'A', 2, [10, 4, 3, 17]), {"aff_count": 3, "allocated_side": "aff"}), - (( 1, 'C', 1, [11, 26, 8, 19]), {"aff_count": 2, "allocated_side": "neg"}), - (( 5, 'C', 1, [ 9, 13, 4, 23]), {"aff_count": 1, "allocated_side": "neg"}), + ((1, 'C', 1, [11, 26, 8, 19]), {"aff_count": 2, "allocated_side": "neg"}), + ((5, 'C', 1, [9, 13, 4, 23]), {"aff_count": 1, "allocated_side": "neg"}), ((10, 'B', 1, [25, 22, 13, 2]), {"aff_count": 1, "allocated_side": "aff"}), - ((16, 'D', 1, [ 7, 2, 22, 7]), {"aff_count": 2, "allocated_side": "neg"}), + ((16, 'D', 1, [7, 2, 22, 7]), {"aff_count": 2, "allocated_side": "neg"}), ((20, 'E', 1, [13, 3, 2, 24]), {"aff_count": 2, "allocated_side": "aff"}), ((21, 'A', 1, [17, 18, 26, 18]), {"aff_count": 2, "allocated_side": "aff"}), - ((19, 'B', 1, [ 6, 23, 24, 1]), {"aff_count": 1, "allocated_side": "neg"}), + ((19, 'B', 1, [6, 23, 24, 1]), {"aff_count": 1, "allocated_side": "neg"}), ((26, 'B', 1, [12, 1, 21, 13]), {"aff_count": 2, "allocated_side": "neg"}), ((13, 'C', 0, [20, 5, 10, 26]), {"aff_count": 2, "allocated_side": "neg"})] expected = dict() - expected[1] = [dict(odd_bracket="pullup_top", pairing_method="slide", - avoid_conflicts="one_up_one_down", side_allocations="balance"), [ - (12, 2, ["pullup"], True), - ( 3, 14, ["1u1d_hist"], True), - (11, 4, ["1u1d_other"], False), - ( 6, 7, ["1u1d_other", "pullup"], True), - (17, 8, ["1u1d_hist"], True), - ( 9, 24, ["1u1d_other"], False), - (15, 23, ["1u1d_inst"], True), - (18, 25, [], False), - (22, 1, ["pullup"], True), - ( 5, 19, ["1u1d_other"], True), - (10, 21, ["1u1d_inst"], False), - (16, 13, ["1u1d_other", "pullup"], True), - (20, 26, ["1u1d_hist"], True)]] - expected[2] = [dict(odd_bracket="intermediate_bubble_up_down", - pairing_method="slide", avoid_conflicts="one_up_one_down", - side_allocations="balance"), [ - (12, 2, [], True), - (3, 17, [], True), # institution conflict, but swapping - # would give history conflict - (11, 14, ["1u1d_inst"], True), - (6, 4, ["1u1d_other"], False), - (8, 7, [], True), - (9, 22, [], True), - (15, 23, [], True), - (18, 24, [], False), - (1, 25, [], False), - (5, 20, [], False), - (10, 21, [], False), - (16, 26, ["bub_up_hist"], True), - (19, 13, ["bub_up_accom"], False)]] - expected[3] = [dict(odd_bracket="intermediate1", pairing_method="fold", - avoid_conflicts="off", side_allocations="preallocated"), [ - (12, 11, [], False), - ( 2, 8, [], False), - ( 3, 17, [], False), - ( 4, 6, [], False), - (14, 15, [], False), - ( 7, 22, [], False), - ( 9, 18, [], False), - (23, 16, [], False), - (24, 5, [], False), - (25, 1, [], False), - (10, 26, [], False), - (20, 19, [], False), - (21, 13, [], False)]] - expected[4] = [dict(odd_bracket="intermediate2", pairing_method="fold", - avoid_conflicts="off", side_allocations="preallocated"), [ - (12, 11, [], False), - ( 2, 8, [], False), - ( 3, 17, [], False), - ( 4, 6, [], False), - (14, 15, [], False), - ( 7, 22, [], False), - ( 9, 18, [], False), - (23, 16, [], False), - (24, 5, [], False), - (25, 1, [], False), - (10, 26, [], False), - (20, 19, [], False), - (21, 13, [], False)]] + expected[1] = [dict( + odd_bracket="pullup_top", pairing_method="slide", avoid_conflicts="one_up_one_down", side_allocations="balance"), + [(12, 2, ["pullup"], True), + (3, 14, ["1u1d_hist"], True), + (11, 4, ["1u1d_other"], False), + (6, 7, ["1u1d_other", "pullup"], True), + (17, 8, ["1u1d_hist"], True), + (9, 24, ["1u1d_other"], False), + (15, 23, ["1u1d_inst"], True), + (18, 25, [], False), + (22, 1, ["pullup"], True), + (5, 19, ["1u1d_other"], True), + (10, 21, ["1u1d_inst"], False), + (16, 13, ["1u1d_other", "pullup"], True), + (20, 26, ["1u1d_hist"], True)]] + + expected[2] = [dict( + odd_bracket="intermediate_bubble_up_down", pairing_method="slide", avoid_conflicts="one_up_one_down", side_allocations="balance"), + [(12, 2, [], True), + (3, 17, [], True), # institution conflict, but swapping + # would give history conflict + (11, 14, ["1u1d_inst"], True), + (6, 4, ["1u1d_other"], False), + (8, 7, [], True), + (9, 22, [], True), + (15, 23, [], True), + (18, 24, [], False), + (1, 25, [], False), + (5, 20, [], False), + (10, 21, [], False), + (16, 26, ["bub_up_hist"], True), + (19, 13, ["bub_up_accom"], False)]] + + expected[3] = [dict( + odd_bracket="intermediate1", pairing_method="fold", avoid_conflicts="off", side_allocations="preallocated"), + [(12, 11, [], False), + (2, 8, [], False), + (3, 17, [], False), + (4, 6, [], False), + (14, 15, [], False), + (7, 22, [], False), + (9, 18, [], False), + (23, 16, [], False), + (24, 5, [], False), + (25, 1, [], False), + (10, 26, [], False), + (20, 19, [], False), + (21, 13, [], False)]] + + expected[4] = [dict( + odd_bracket="intermediate2", pairing_method="fold", avoid_conflicts="off", side_allocations="preallocated"), + [(12, 11, [], False), + (2, 8, [], False), + (3, 17, [], False), + (4, 6, [], False), + (14, 15, [], False), + (7, 22, [], False), + (9, 18, [], False), + (23, 16, [], False), + (24, 5, [], False), + (25, 1, [], False), + (10, 26, [], False), + (20, 19, [], False), + (21, 13, [], False)]] combinations = [(1, 1), (1, 2), (1, 3), (1, 4)] @@ -485,11 +491,12 @@ class TestPowerPairedWithAllocatedSidesDrawGeneratorPartOddBrackets(unittest.Tes ]) brackets[4] = OrderedDict([ (3, {"aff": ["Yale 2", "Stanford 2", "Yale 1"], "neg": []}), - (2, {"aff": ["John Hopkins 1", "Stanford 1", "MIT 1", "Stanford 3", "Berkeley 1"], "neg": ["MIT 2", "Columbia 1", "Caltech 1", "Caltech 3"]}), - (1, {"aff": ["Caltech 2", "Cornell 1", "Yale 3", "Princeton 1"], "neg": ["Chicago 2", "Chicago 1", "Pennsylvania 1", "Chicago 3", "Princeton 2"]}), + (2, {"aff": ["John Hopkins 1", "Stanford 1", "MIT 1", "Stanford 3", "Berkeley 1"], "neg": ["MIT 2", "Columbia 1", "Caltech 1", "Caltech 3"]}), # flake8: noqa + (1, {"aff": ["Caltech 2", "Cornell 1", "Yale 3", "Princeton 1"], "neg": ["Chicago 2", "Chicago 1", "Pennsylvania 1", "Chicago 3", "Princeton 2"]}), # flake8: noqa (0, {"aff": [], "neg": ["Pennsylvania 2", "Harvard 1", "Harvard 2"]}), ]) - brackets[99] = OrderedDict([ # Uneven aff/neg, should raise exception + brackets[99] = OrderedDict([ + # Uneven aff/neg, should raise exception (5, {"aff": [1, 2], "neg": []}), (4, {"aff": [3, 4], "neg": [14]}), (3, {"aff": [5, 6, 7, 8, 9], "neg": [15, 16]}), @@ -529,8 +536,8 @@ class TestPowerPairedWithAllocatedSidesDrawGeneratorPartOddBrackets(unittest.Tes ]) expecteds["pullup_top"][4] = OrderedDict([ (3, {"aff": ["Yale 2", "Stanford 2", "Yale 1"], "neg": ["MIT 2", "Columbia 1", "Caltech 1"]}), - (2, {"aff": ["John Hopkins 1", "Stanford 1", "MIT 1", "Stanford 3", "Berkeley 1"], "neg": ["Caltech 3", "Chicago 2", "Chicago 1", "Pennsylvania 1", "Chicago 3"]}), - (1, {"aff": ["Caltech 2", "Cornell 1", "Yale 3", "Princeton 1"], "neg": ["Princeton 2", "Pennsylvania 2", "Harvard 1", "Harvard 2"]}), + (2, {"aff": ["John Hopkins 1", "Stanford 1", "MIT 1", "Stanford 3", "Berkeley 1"], "neg": ["Caltech 3", "Chicago 2", "Chicago 1", "Pennsylvania 1", "Chicago 3"]}), # flake8: noqa + (1, {"aff": ["Caltech 2", "Cornell 1", "Yale 3", "Princeton 1"], "neg": ["Princeton 2", "Pennsylvania 2", "Harvard 1", "Harvard 2"]}), # flake8: noqa (0, {"aff": [], "neg": []}), ]) @@ -561,8 +568,8 @@ class TestPowerPairedWithAllocatedSidesDrawGeneratorPartOddBrackets(unittest.Tes ]) expecteds["pullup_bottom"][4] = OrderedDict([ (3, {"aff": ["Yale 2", "Stanford 2", "Yale 1"], "neg": ["Columbia 1", "Caltech 1", "Caltech 3"]}), - (2, {"aff": ["John Hopkins 1", "Stanford 1", "MIT 1", "Stanford 3", "Berkeley 1"], "neg": ["MIT 2", "Chicago 1", "Pennsylvania 1", "Chicago 3", "Princeton 2"]}), - (1, {"aff": ["Caltech 2", "Cornell 1", "Yale 3", "Princeton 1"], "neg": ["Chicago 2", "Pennsylvania 2", "Harvard 1", "Harvard 2"]}), + (2, {"aff": ["John Hopkins 1", "Stanford 1", "MIT 1", "Stanford 3", "Berkeley 1"], "neg": ["MIT 2", "Chicago 1", "Pennsylvania 1", "Chicago 3", "Princeton 2"]}), # flake8: noqa + (1, {"aff": ["Caltech 2", "Cornell 1", "Yale 3", "Princeton 1"], "neg": ["Chicago 2", "Pennsylvania 2", "Harvard 1", "Harvard 2"]}), # flake8: noqa (0, {"aff": [], "neg": []}), ]) @@ -701,23 +708,45 @@ def test_pullup_random(self): self.assertEqual(b2[0], {"aff": [], "neg": []}) -class TestPartialEliminationDrawGenerator(unittest.TestCase): +class TestPartialBreakRoundSplit(unittest.TestCase): + + def test_split(self): + self.assertRaises(AssertionError, partial_break_round_split, -1) + self.assertRaises(AssertionError, partial_break_round_split, 0) + self.assertRaises(AssertionError, partial_break_round_split, 1) + self.assertEqual(partial_break_round_split(2), (1, 0)) + self.assertEqual(partial_break_round_split(3), (1, 1)) + self.assertEqual(partial_break_round_split(4), (2, 0)) + self.assertEqual(partial_break_round_split(5), (1, 3)) + self.assertEqual(partial_break_round_split(6), (2, 2)) + self.assertEqual(partial_break_round_split(7), (3, 1)) + self.assertEqual(partial_break_round_split(8), (4, 0)) + self.assertEqual(partial_break_round_split(11), (3, 5)) + self.assertEqual(partial_break_round_split(21), (5, 11)) + self.assertEqual(partial_break_round_split(24), (8, 8)) + self.assertEqual(partial_break_round_split(27), (11, 5)) + self.assertEqual(partial_break_round_split(31), (15, 1)) + self.assertEqual(partial_break_round_split(32), (16, 0)) + self.assertEqual(partial_break_round_split(45), (13, 19)) + self.assertEqual(partial_break_round_split(48), (16, 16)) + self.assertEqual(partial_break_round_split(61), (29, 3)) + self.assertEqual(partial_break_round_split(64), (32, 0)) + self.assertEqual(partial_break_round_split(99), (35, 29)) + + +class BaseTestEliminationDrawGenerator(unittest.TestCase): # (Team Name, Team Institution) - teams = [(1, 'A', 1), (2, 'B', 2), (3, 'A', 3), (4, 'B', 4), (5, 'C', 5), (6, 'D', 6), - (7, 'E', 7), (8, 'A', 8), (9, 'D', 9), (10, 'E', 10), (11, 'D', 11), (12, 'A', 12)] + team_data = [(1, 'A'), (2, 'B'), (3, 'A'), (4, 'B'), (5, 'C'), (6, 'D'), + (7, 'E'), (8, 'A'), (9, 'D'), (10, 'E'), (11, 'D'), (12, 'A')] - def test_split(self): - self.fed = DrawGenerator("first_elimination", DUMMY_TEAMS, None) - self.assertEqual(self.fed._bypass_debate_split( 3), ( 1, 2)) - self.assertEqual(self.fed._bypass_debate_split( 5), ( 3, 2)) - self.assertEqual(self.fed._bypass_debate_split( 8), ( 8, 0)) - self.assertEqual(self.fed._bypass_debate_split(11), ( 5, 6)) - self.assertEqual(self.fed._bypass_debate_split(21), (11, 10)) - self.assertEqual(self.fed._bypass_debate_split(24), ( 8, 16)) - self.assertEqual(self.fed._bypass_debate_split(31), ( 1, 30)) - self.assertEqual(self.fed._bypass_debate_split(32), (32, 0)) - del self.fed + def assertPairingsEqual(self, actual, expected): + """Checks pairings without regard to sides.""" + for a, p in zip(actual, expected): + self.assertCountEqual((a.aff_team.id, a.neg_team.id), p) + + +class TestPartialEliminationDrawGenerator(BaseTestEliminationDrawGenerator): def test_even_numbers(self): # Run a draw with break size of 2; expect the each team's ID to be paired up as follows @@ -726,71 +755,68 @@ def test_even_numbers(self): self.run_draw(8, [(1, 8), (2, 7), (3, 6), (4, 5)]) def test_weird_numbers(self): - self.run_draw(3, [(2, 3)], [1]) - self.run_draw(5, [(4, 5)], [1, 2, 3]) - self.run_draw(6, [(3, 6), (4, 5)], [1, 2]) - self.run_draw(12, [(5, 12), (6, 11), (7, 10), (8, 9)], [1, 2, 3, 4]) - - def run_draw(self, break_size, expected, exp_bypassing=None): - # Detemine how many teams should be put in from the base set - teams_to_pass_in = len(expected) * 2 - if exp_bypassing is not None: - teams_to_pass_in += len(exp_bypassing) + self.run_draw(3, [(2, 3)]) + self.run_draw(5, [(4, 5)]) + self.run_draw(6, [(3, 6), (4, 5)]) + self.run_draw(12, [(5, 12), (6, 11), (7, 10), (8, 9)]) + def run_draw(self, break_size, expected): # Make the test team objects and generate their pairings - teams = [TestTeam(*args) for args in self.teams][:teams_to_pass_in] - self.fed = DrawGenerator("first_elimination", teams, TestRound(break_size)) + teams = [TestTeam(*args) for args in self.team_data][:break_size] + self.fed = DrawGenerator("first_elimination", teams) pairings = self.fed.generate() + self.assertPairingsEqual(pairings, expected) - # Assert pairings as expected - self.assertEqual([(p.aff_team.id, p.neg_team.id) for p in pairings], expected) - if exp_bypassing is not None: - bypassing = [t.id for t in self.fed.get_bypassing_teams()] - self.assertEqual(bypassing, exp_bypassing) -class TestEliminationDrawGenerator(unittest.TestCase): - - team_data = [(1, 'A', 1), (2, 'B', 2), (3, 'A', 3), (4, 'B', 4), (5, 'C', 5), (6, 'D', 6), - (7, 'E', 7), (8, 'A', 8), (9, 'D', 9), (10, 'E', 10), (11, 'D', 11), (12, 'A', 12)] +class TestEliminationDrawGenerator(BaseTestEliminationDrawGenerator): def setUp(self): self.teams = [TestTeam(*args) for args in self.team_data] - def _results(self, *args): - _t = lambda id: self.teams[id-1] - _p = lambda ids: list(map(_t, ids)) + def t(self, teams): + return lambda id: teams[id-1] + + def p(self, t): + return lambda ids: list(map(t, ids)) + + def _results(self, start_rank, *args): + + _t = self.t(self.teams) + _p = self.p(_t) + pairings = list() - for i, (teams, winner) in enumerate(args): + for i, (teams, winner) in enumerate(args, start=start_rank): pairing = Pairing(_p(teams), 0, i, winner=_t(winner)) pairings.append(pairing) return pairings def _teams(self, *args): - _t = lambda id: self.teams[id-1] + _t = self.t(self.teams) return list(map(_t, args)) def test_no_bypass(self): - teams = list() - results = self._results(([1, 5], 1), ([6, 7], 7), ([3, 2], 3), ([4, 8], 8)) - self.run_draw(teams, TestRound(4), results, [(1, 8), (7, 3)]) + teams = self._teams(1, 3, 4, 2, 5, 8, 9, 11, 10, 12) # it should take none of these + results = self._results(1, ([1, 5], 1), ([6, 7], 7), ([3, 2], 3), ([4, 8], 8)) + self.run_draw(teams, results, [(1, 8), (7, 3)]) def test_bypass(self): - # Test when a series of teams (9-12) have had a partial elimination round - teams = self._teams(9, 11, 10, 12) - results = self._results(([1, 5], 1), ([6, 7], 7), ([3, 2], 3), ([4, 8], 8)) - self.run_draw(teams, TestRound(8), results, [(9, 8), (11, 3), (10, 7), (12, 1)]) + # teams 9 through 12 qualified 1st through 4th, so bypassed the first round + teams = self._teams(9, 11, 10, 12, 1, 2, 3, 4, 5, 6, 7, 8) + results = self._results(5, ([1, 5], 1), ([6, 7], 7), ([3, 2], 3), ([4, 8], 8)) + self.run_draw(teams, results, [(9, 8), (11, 3), (10, 7), (12, 1)]) def test_error(self): # Test when number of teams is not a power of two teams = self._teams(1, 7, 3, 8, 9, 11) - results = self._results(([1, 5], 1), ([6, 7], 7), ([3, 2], 3), ([4, 8], 8)) - self.ed = DrawGenerator("elimination", teams, TestRound(6), results) + results = self._results(3, ([1, 5], 1), ([6, 7], 7), ([3, 2], 3), ([4, 8], 8)) + self.ed = DrawGenerator("elimination", teams, results=results) self.assertRaises(DrawError, self.ed.generate) - def run_draw(self, teams, test_round, results, expected): - self.ed = DrawGenerator("elimination", teams, test_round, results) + def run_draw(self, teams, results, expected): + self.ed = DrawGenerator("elimination", teams, results=results) pairings = self.ed.generate() - self.assertEqual([(p.aff_team.id, p.neg_team.id) for p in pairings], expected) + self.assertPairingsEqual(pairings, expected) + if __name__ == '__main__': unittest.main() diff --git a/draw/tests/test_one_up_one_down.py b/tabbycat/draw/tests/test_one_up_one_down.py similarity index 89% rename from draw/tests/test_one_up_one_down.py rename to tabbycat/draw/tests/test_one_up_one_down.py index 527c56c3bae..bac49add8c2 100644 --- a/draw/tests/test_one_up_one_down.py +++ b/tabbycat/draw/tests/test_one_up_one_down.py @@ -1,15 +1,16 @@ -import os.path, sys import unittest + from .utils import TestTeam from ..one_up_one_down import OneUpOneDownSwapper + class TestOneUpOneDown(unittest.TestCase): @staticmethod def _1u1d_no_change(data): return [(t1[0], t2[0]) for t1, t2 in data] - def testNoSwap(self): + def test_no_swap(self): data = (((1, 'A'), (5, 'B')), ((2, 'C'), (6, 'A')), ((3, 'B'), (7, 'D')), @@ -18,7 +19,7 @@ def testNoSwap(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testSwapInst(self): + def test_swap_inst(self): data = (((1, 'A'), (5, 'A')), ((2, 'C'), (6, 'B')), ((3, 'B'), (7, 'D')), @@ -27,7 +28,7 @@ def testSwapInst(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testNoSwapInst(self): + def test_no_swap_inst(self): data = (((1, 'A'), (5, 'A')), ((2, 'C'), (6, 'B')), ((3, 'B'), (7, 'D')), @@ -36,7 +37,7 @@ def testNoSwapInst(self): self.assertEqual(result, self.draw(data, avoid_institution=False)) return self.draw(data) - def testSwapHist(self): + def test_swap_hist(self): data = (((1, 'A', None, 5), (5, 'B')), ((2, 'C'), (6, 'A')), ((3, 'B'), (7, 'D')), @@ -45,7 +46,7 @@ def testSwapHist(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testNoSwapHist(self): + def test_no_swap_hist(self): data = (((1, 'A', None, 5), (5, 'B')), ((2, 'C'), (6, 'A')), ((3, 'B'), (7, 'D')), @@ -54,7 +55,7 @@ def testNoSwapHist(self): self.assertEqual(result, self.draw(data, avoid_history=False)) return self.draw(data) - def testLastSwap(self): + def test_last_swap(self): data = (((1, 'A'), (5, 'B')), ((2, 'C'), (6, 'A')), ((3, 'B'), (7, 'D')), @@ -63,7 +64,7 @@ def testLastSwap(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testExhaustInstitution1(self): + def test_exhaust_institution_1(self): data = (((1, 'C'), (5, 'A')), ((2, 'A'), (6, 'A')), ((3, 'C'), (7, 'A')), @@ -72,7 +73,7 @@ def testExhaustInstitution1(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testExhaustInstitution2(self): + def test_exhaust_institution_2(self): data = (((1, 'A'), (5, 'C')), ((2, 'A'), (6, 'A')), ((3, 'A'), (7, 'D')), @@ -81,7 +82,7 @@ def testExhaustInstitution2(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testExhaustInstitution3(self): + def test_exhaust_institution_3(self): data = (((1, 'A'), (5, 'C')), ((2, 'A'), (6, 'A')), ((3, 'B'), (7, 'A')), @@ -90,7 +91,7 @@ def testExhaustInstitution3(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testExhaustHistory1(self): + def test_exhaust_history_1(self): data = (((1, 'C'), (5, 'B')), ((2, 'A', None, (5, 6, 7)), (6, 'C')), ((3, 'C'), (7, 'D')), @@ -99,7 +100,7 @@ def testExhaustHistory1(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testExhaustHistory2(self): + def test_exhaust_history_2(self): data = (((1, 'C'), (5, 'B')), ((2, 'A', None, (5, 6)), (6, 'C')), ((3, 'C', None, 6), (7, 'D')), @@ -108,7 +109,7 @@ def testExhaustHistory2(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testPreferInstitutionToHistory(self): + def test_prefer_institution_to_history(self): data = (((1, 'C'), (5, 'B')), ((2, 'A', None, (5, 7)), (6, 'A')), ((3, 'C'), (7, 'D')), @@ -117,7 +118,7 @@ def testPreferInstitutionToHistory(self): self.assertEqual(result, self.draw(data)) return self.draw(data) - def testPreferFewerSwaps(self): + def test_prefer_fewer_swaps(self): """It should swap the middle two debates, as opposed to the top two and last two.""" data = (((1, 'C'), (5, 'B')), @@ -136,4 +137,4 @@ def draw(self, data, **options): return [(a.id, b.id) for (a, b) in r] if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/tabbycat/draw/tests/test_views.py b/tabbycat/draw/tests/test_views.py new file mode 100644 index 00000000000..b2bc56aef53 --- /dev/null +++ b/tabbycat/draw/tests/test_views.py @@ -0,0 +1,14 @@ +from utils.tests import ConditionalTableViewTest, TestCase + +from tournaments.models import Round + + +class PublicDrawForRoundViewTest(ConditionalTableViewTest, TestCase): + view_name = 'draw-public-for-round' + view_toggle = 'public_features__public_draw' + round_seq = 2 + + def table_data(self): + # Check number of debates is correct + round = Round.objects.get(tournament=self.t, seq=self.round_seq) + return round.debate_set.all().count() diff --git a/draw/tests/utils.py b/tabbycat/draw/tests/utils.py similarity index 59% rename from draw/tests/utils.py rename to tabbycat/draw/tests/utils.py index bb0f28b4b98..e5982a45252 100644 --- a/draw/tests/utils.py +++ b/tabbycat/draw/tests/utils.py @@ -1,5 +1,6 @@ """Utilities for draw tests.""" + class TestTeam(object): """Basic implementation of team interface""" @@ -15,24 +16,7 @@ def __init__(self, id, inst, points=None, hist=list(), **kwargs): setattr(self, key, value) def __repr__(self): - return "".format(self.id, self.institution, - hash(self)) - - def break_rank_for_category(self, category): - return self.points + return "".format(self.id, self.institution, hash(self)) def seen(self, other): return self.hist.count(other.id) - - -class TestRound(object): - """Basic implementation of round interface for break rounds + round robins""" - - def __init__(self, break_size): - self.break_size = break_size - - def break_size(self): - return self.break_size - - def break_category(self): - return "NA" \ No newline at end of file diff --git a/tabbycat/draw/urls_admin.py b/tabbycat/draw/urls_admin.py new file mode 100644 index 00000000000..69f3900dd46 --- /dev/null +++ b/tabbycat/draw/urls_admin.py @@ -0,0 +1,66 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + + # Display + url(r'^round/(?P\d+)/$', + views.AdminDrawView.as_view(), + name='draw'), + url(r'^round/(?P\d+)/details/$', + views.AdminDrawWithDetailsView.as_view(), + name='draw-details'), + url(r'^round/(?P\d+)/display_by_venue/$', + views.AdminDrawDisplayForRoundByVenueView.as_view(), + name='draw-display-by-venue'), + url(r'^round/(?P\d+)/display_by_team/$', + views.AdminDrawDisplayForRoundByTeamView.as_view(), + name='draw-display-by-team'), + + # Creation/Release + url(r'^round/(?P\d+)/create/$', + views.CreateDrawView.as_view(), + name='draw-create'), + url(r'^round/(?P\d+)/confirm/$', + views.ConfirmDrawCreationView.as_view(), + name='draw-confirm'), + url(r'^round/(?P\d+)/confirm_regenerate/$', + views.ConfirmDrawRegenerationView.as_view(), + name='draw-confirm-regenerate'), + url(r'^round/(?P\d+)/regenerate/$', + views.DrawRegenerateView.as_view(), + name='draw-regenerate'), + url(r'^round/(?P\d+)/release/$', + views.DrawReleaseView.as_view(), + name='draw-release'), + url(r'^round/(?P\d+)/unrelease/$', + views.DrawUnreleaseView.as_view(), + name='draw-unrelease'), + + # Side Editing + url(r'^sides/$', + views.SideAllocationsView.as_view(), + name='draw-side-allocations'), + url(r'^round/(?P\d+)/matchups/edit/$', + views.DrawMatchupsEditView.as_view(), + name='draw-matchups-edit'), + url(r'^round/(?P\d+)/matchups/save/$', + views.SaveDrawMatchups.as_view(), + name='draw-matchups-save'), + + # Scheduling + url(r'^round/(?P\d+)/schedule_debates/$', + views.ScheduleDebatesView.as_view(), + name='draw-schedule-debates'), + url(r'^round/(?P\d+)/schedule_debates/save/$', + views.ApplyDebateScheduleView.as_view(), + name='draw-schedule-apply'), + url(r'^round/(?P\d+)/confirms/$', + views.ScheduleConfirmationsView.as_view(), + name='draw-schedule-confirmations'), + + url(r'^round/(?P\d+)/start_time/set/$', + views.SetRoundStartTimeView.as_view(), + name='draw-start-time-set'), +] diff --git a/tabbycat/draw/urls_crosst.py b/tabbycat/draw/urls_crosst.py new file mode 100644 index 00000000000..bf779ef6c0a --- /dev/null +++ b/tabbycat/draw/urls_crosst.py @@ -0,0 +1,28 @@ +from django.conf.urls import url + +from . import views + + +urlpatterns = [ + + url(r'^all_tournaments_all_institutions/$', + views.AllTournamentsAllInstitutionsView.as_view(), + name='all-tournaments-all-institutions'), + + url(r'^all_tournaments_all_venues/$', + views.AllTournamentsAllVenuesView.as_view(), + name='all_tournaments-all-venues'), + + url(r'^all_tournaments_all_teams/$', + views.AllDrawsForAllTeamsView.as_view(), + name='all-tournaments-all-teams'), + + url(r'^all_tournaments_all_institutions/all_draws/(?P\d+)$', + views.AllDrawsForInstitutionView.as_view(), + name='all-draws-for-institution'), + + url(r'^all_tournaments_all_venues/all_draws/(?P\d+)$', + views.AllDrawsForVenueView.as_view(), + name='all-draws-for-venue'), + +] diff --git a/tabbycat/draw/urls_public.py b/tabbycat/draw/urls_public.py new file mode 100644 index 00000000000..b3b743547fb --- /dev/null +++ b/tabbycat/draw/urls_public.py @@ -0,0 +1,18 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^$', + views.PublicDrawForCurrentRoundView.as_view(), + name='draw-public-current-round'), + url(r'^round/(?P\d+)/$', + views.PublicDrawForRoundView.as_view(), + name='draw-public-for-round'), + url(r'^all/$', + views.PublicAllDrawsAllTournamentsView.as_view(), + name='draw-public-all-draws'), + url(r'^sides/$', + views.PublicSideAllocationsView.as_view(), + name='draw-public-side-allocations'), +] diff --git a/tabbycat/draw/utils.py b/tabbycat/draw/utils.py new file mode 100644 index 00000000000..396968aacef --- /dev/null +++ b/tabbycat/draw/utils.py @@ -0,0 +1,23 @@ +"""Miscellaneous utilities for the draw.""" + + +def nextpow2(n): + return 1 << (n-1).bit_length() + + +def partial_break_round_split(break_size): + """Returns a tuple `(debating, bypassing)`, where `debating` is how many + teams will debate in the first break round, and `bypassing` is how many + teams will bypass the first break round, qualifying directly for the + second.""" + + assert break_size > 1, "break rounds only make sense for break_size > 1 (found %d)" % (break_size,) + + teams_in_second_break_round = nextpow2(break_size) // 2 + debates = break_size - teams_in_second_break_round + bypassing = teams_in_second_break_round - debates + + assert 2*debates + bypassing == break_size, "2 * %d teams debating + %d teams bypassing doesn't add to break size %d" % (debates, bypassing, break_size) + assert debates > 0, "%d <= 0 debates in first break round (%d teams bypassing)" % (debates, bypassing) + assert bypassing >= 0, "%d < 0 teams bypassing (%d debates)" % (bypassing, debates) + return debates, bypassing diff --git a/tabbycat/draw/views.py b/tabbycat/draw/views.py new file mode 100644 index 00000000000..83e1083c408 --- /dev/null +++ b/tabbycat/draw/views.py @@ -0,0 +1,569 @@ +import datetime +import logging + +from django.views.generic.base import TemplateView, View +from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib import messages +from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect + +from actionlog.mixins import LogActionMixin +from actionlog.models import ActionLogEntry +from adjallocation.models import DebateAdjudicator +from divisions.models import Division +from participants.models import Adjudicator, Institution, Team +from standings.teams import TeamStandingsGenerator +from tournaments.mixins import CrossTournamentPageMixin, PublicTournamentPageMixin, RoundMixin, TournamentMixin +from tournaments.models import Round +from utils.mixins import CacheMixin, PostOnlyRedirectView, SuperuserRequiredMixin, VueTableTemplateView +from utils.misc import reverse_round +from utils.tables import TabbycatTableBuilder +from venues.allocator import allocate_venues +from venues.models import AdjudicatorVenueConstraint, VenueGroup + +from .dbutils import delete_round_draw +from .generator import DrawError +from .manager import DrawManager +from .models import Debate, DebateTeam, TeamPositionAllocation +from .prefetch import populate_history + +logger = logging.getLogger(__name__) + + +TPA_MAP = { + TeamPositionAllocation.POSITION_AFFIRMATIVE: "Aff", + TeamPositionAllocation.POSITION_NEGATIVE: "Neg", + None: "—" +} + + +# ============================================================================== +# Viewing Draw (Public) +# ============================================================================== + +class BaseDrawTableView(RoundMixin, VueTableTemplateView): + + template_name = 'draw_display_by.html' + sort_key = 'Venue' + popovers = True + + def get_page_title(self): + return 'Draw for %s' % self.get_round().name + + def get_page_emoji(self): + if self.get_round().draw_status == Round.STATUS_RELEASED: + return '👏' + else: + return '😴' + + def get_page_subtitle(self): + round = self.get_round() + if round.starts_at: + return 'debates start at %s' % round.starts_at.strftime('%H:%M') + else: + return '' + + def get_context_data(self, **kwargs): + kwargs['round'] = self.get_round() + return super().get_context_data(**kwargs) + + def populate_table(self, draw, table, round, tournament): + table.add_debate_venue_columns(draw) + table.add_team_columns([d.aff_team for d in draw], hide_institution=True, key="Aff") + table.add_team_columns([d.neg_team for d in draw], hide_institution=True, key="Neg") + if tournament.pref('enable_division_motions'): + table.add_motion_column(d.get_division_motions for d in draw) + + if not tournament.pref('enable_divisions'): + table.add_debate_adjudicators_column(draw, show_splits=False) + + def get_table(self): + tournament = self.get_tournament() + round = self.get_round() + draw = round.debate_set_with_prefetches() + table = TabbycatTableBuilder(view=self, sort_key=self.sort_key, popovers=self.popovers) + self.populate_table(draw, table, round, tournament) + return table + + +class PublicDrawForRoundView(PublicTournamentPageMixin, CacheMixin, BaseDrawTableView): + + public_page_preference = 'public_draw' + + def get_template_names(self): + round = self.get_round() + if round.draw_status != round.STATUS_RELEASED: + messages.info(self.request, 'The draw for ' + round.name + + ' has yet to be released') + return ["base.html"] + else: + return super().get_template_names() + + def get_context_data(self, **kwargs): + round = self.get_round() + if round.draw_status != round.STATUS_RELEASED: + kwargs["round"] = self.get_round() + return super(BaseDrawTableView, self).get_context_data(**kwargs) # skip BaseDrawTableView + else: + return super().get_context_data(**kwargs) + + +class PublicDrawForCurrentRoundView(PublicDrawForRoundView): + + def get_round(self): + return self.get_tournament().current_round + + +class PublicAllDrawsAllTournamentsView(PublicTournamentPageMixin, TemplateView): + template_name = "public_draw_display_all.html" + public_page_preference = 'enable_mass_draws' + + def get_context_data(self, **kwargs): + t = self.get_tournament() + all_rounds = list(Round.objects.filter( + tournament=t, draw_status=Round.STATUS_RELEASED)) + for r in all_rounds: + r.draw = r.debate_set_with_prefetches() + kwargs['all_rounds'] = all_rounds + return super().get_context_data(**kwargs) + + +class AdminDrawDisplayForRoundByVenueView(LoginRequiredMixin, BaseDrawTableView): + popovers = True + + +class AdminDrawDisplayForRoundByTeamView(LoginRequiredMixin, BaseDrawTableView): + sort_key = 'Team' + popovers = True + + def populate_table(self, draw, table, round, tournament): + draw = list(draw) + list(draw) # Double up the draw + draw_slice = len(draw) // 2 # Top half gets affs; bottom negs + table.add_team_columns( + [d.aff_team for d in draw[:draw_slice]] + [d.neg_team for d in draw[draw_slice:]], + hide_institution=True, key="Team") + super().populate_table(draw, table, round, tournament) + + +# ============================================================================== +# Draw Creation (Admin) +# ============================================================================== + +class AdminDrawView(RoundMixin, SuperuserRequiredMixin, VueTableTemplateView): + detailed = False + + def get_page_title(self): + round = self.get_round() + self.page_emoji = '👀' + if self.detailed: + return 'Draw with Details for %s' % round.name + if round.draw_status == round.STATUS_NONE: + return 'No draw for %s' % round.name + elif round.draw_status == round.STATUS_DRAFT: + return 'Draft draw for %s' % round.name + elif round.draw_status == round.STATUS_CONFIRMED: + self.page_emoji = '👏' + return 'Confirmed Draw for %s' % round.name + elif round.draw_status == round.STATUS_RELEASED: + self.page_emoji = '👏' + return 'Released draw for %s' % round.name + else: + raise + + def get_table(self): + r = self.get_round() + table = TabbycatTableBuilder(view=self) + if r.draw_status == r.STATUS_NONE: + return table # Return Blank + + draw = r.debate_set_with_prefetches(ordering=('room_rank',), institutions=True) + populate_history(draw) + if r.is_break_round: + table.add_room_rank_columns(draw) + else: + table.add_debate_bracket_columns(draw) + + table.add_debate_venue_columns(draw) + table.add_team_columns([d.aff_team for d in draw], key="Aff", + hide_institution=True) + table.add_team_columns([d.neg_team for d in draw], key="Neg", + hide_institution=True) + + # For draw details and draw draft pages + if (r.draw_status == r.STATUS_DRAFT or self.detailed) and r.prev: + teams = Team.objects.filter(debateteam__debate__round=r) + metrics = r.tournament.pref('team_standings_precedence') + generator = TeamStandingsGenerator(metrics, ('rank', 'subrank')) + standings = generator.generate(teams, round=r.prev) + if not r.is_break_round: + if "points" in standings.metric_keys: + table.add_team_pullup_columns(draw, standings) + table.add_debate_ranking_columns(draw, standings) + else: + table.add_column( + {'tooltip': "Aff Team's Break Rank", 'text': "ABR"}, + ["%s" % d.aff_team.break_rank_for_category(r.break_category) for d in draw]) + table.add_column( + {'tooltip': "Negative Team's Break Rank", 'text': "NBR"}, + ["%s" % d.neg_team.break_rank_for_category(r.break_category) for d in draw]) + table.add_debate_metric_columns(draw, standings) + table.add_sides_count([d.aff_team for d in draw], r.prev, 'aff') + table.add_sides_count([d.neg_team for d in draw], r.prev, 'neg') + else: + table.add_debate_adjudicators_column(draw, show_splits=False) + + table.add_draw_conflicts_columns(draw) + if not r.is_break_round: + table.highlight_rows_by_column_value(column=0) # highlight first row of a new bracket + + return table + + def get_template_names(self): + round = self.get_round() + if self.detailed: + return ["draw_base.html"] + if round.draw_status == round.STATUS_NONE: + messages.warning(self.request, 'No draw exists yet — go to the ' + + 'check-ins section for this round to generate a draw.') + return ["base.html"] + elif round.draw_status == round.STATUS_DRAFT: + return ["draw_status_draft.html"] + elif round.draw_status == round.STATUS_CONFIRMED: + return ["draw_status_confirmed.html"] + elif round.draw_status == round.STATUS_RELEASED: + return ["draw_status_confirmed.html"] + else: + raise + + +class AdminDrawWithDetailsView(AdminDrawView): + detailed = True + + def get_page_title(self): + rd = self.get_round() + return 'Draw for %s with Details' % rd.name + + +# ============================================================================== +# Draw Status POSTS +# ============================================================================== + +class DrawStatusEdit(LogActionMixin, SuperuserRequiredMixin, RoundMixin, PostOnlyRedirectView): + round_redirect_pattern_name = 'draw' + + +class CreateDrawView(DrawStatusEdit): + + action_log_type = ActionLogEntry.ACTION_TYPE_DRAW_CREATE + + def post(self, request, *args, **kwargs): + round = self.get_round() + + if round.draw_status != round.STATUS_NONE: + messages.error(request, "Could not create draw for {}, there was already a draw!".format(round.name)) + return super().post(request, *args, **kwargs) + + manager = DrawManager(round) + try: + manager.create() + except DrawError as e: + messages.error(request, "There was a problem creating the draw: " + str(e) + " If this issue persists, please contact the developers.") + return HttpResponseRedirect(reverse_round('availability_index', round)) + + # TODO provide a more intelligent check in sites where there are multiple tournaments + if not AdjudicatorVenueConstraint.objects.all().exists(): + allocate_venues(round) + else: + messages.warning(request, "Venues were not auto-allocated because there are one or more adjudicator venue constraints. " + "You should run venue allocations after allocating adjudicators.") + + self.log_action() + return super().post(request, *args, **kwargs) + + +class ConfirmDrawCreationView(DrawStatusEdit): + action_log_type = ActionLogEntry.ACTION_TYPE_DRAW_CONFIRM + + def post(self, request, *args, **kwargs): + round = self.get_round() + if round.draw_status != round.STATUS_DRAFT: + return HttpResponseBadRequest("Draw status is not DRAFT") + + round.draw_status = round.STATUS_CONFIRMED + round.save() + return super().post(request, *args, **kwargs) + + +class DrawRegenerateView(DrawStatusEdit): + action_log_type = ActionLogEntry.ACTION_TYPE_DRAW_REGENERATE + + def post(self, request, *args, **kwargs): + round = self.get_round() + delete_round_draw(round) + return super().post(request, *args, **kwargs) + + +class ConfirmDrawRegenerationView(SuperuserRequiredMixin, TemplateView): + template_name = "draw_confirm_regeneration.html" + + +class DrawReleaseView(DrawStatusEdit): + action_log_type = ActionLogEntry.ACTION_TYPE_DRAW_RELEASE + + def post(self, request, *args, **kwargs): + round = self.get_round() + if round.draw_status != round.STATUS_CONFIRMED: + return HttpResponseBadRequest("Draw status is not CONFIRMED") + + round.draw_status = round.STATUS_RELEASED + round.save() + return super().post(request, *args, **kwargs) + + +class DrawUnreleaseView(DrawStatusEdit): + action_log_type = ActionLogEntry.ACTION_TYPE_DRAW_UNRELEASE + + def post(self, request, *args, **kwargs): + round = self.get_round() + if round.draw_status != round.STATUS_RELEASED: + return HttpResponseBadRequest("Draw status is not RELEASED") + + round.draw_status = round.STATUS_CONFIRMED + round.save() + return super().post(request, *args, **kwargs) + + +class SetRoundStartTimeView(DrawStatusEdit): + action_log_type = ActionLogEntry.ACTION_TYPE_ROUND_START_TIME_SET + + def post(self, request, *args, **kwargs): + time_text = request.POST["start_time"] + try: + time = datetime.datetime.strptime(time_text, "%H:%M").time() + except ValueError: + messages.error(request, "Sorry, \"{}\" isn't a valid time. It must " + "be in 24-hour format, with a colon, for " + "example: \"13:57\".".format(time_text)) + return super().post(request, *args, **kwargs) + + round = self.get_round() + round.starts_at = time + round.save() + # Need to call explicitly, since this isn't a form view + self.log_action() + + return super().post(request, *args, **kwargs) + + +# ============================================================================== +# Adjudicator Scheduling +# ============================================================================== + +class ScheduleDebatesView(SuperuserRequiredMixin, RoundMixin, TemplateView): + template_name = "draw_set_debate_times.html" + + def get_context_data(self, **kwargs): + round = self.get_round() + kwargs['venue_groups'] = VenueGroup.objects.all() + kwargs['divisions'] = Division.objects.filter(tournament=round.tournament).order_by('id') + return super().get_context_data(**kwargs) + + +class ScheduleConfirmationsView(SuperuserRequiredMixin, RoundMixin, TemplateView): + template_name = "confirmations_view.html" + + def get_context_data(self, **kwargs): + adjs = Adjudicator.objects.all().order_by('name') + for adj in adjs: + shifts = DebateAdjudicator.objects.filter(adjudicator=adj, debate__round__tournament__active=True) + if len(shifts) > 0: + adj.shifts = shifts + kwargs['adjs'] = adjs + return super().get_context_data(**kwargs) + + +class ApplyDebateScheduleView(DrawStatusEdit): + + def post(self, request, *args, **kwargs): + round = self.get_round() + debates = Debate.objects.filter(round=round) + for debate in debates: + division = debate.teams[0].division + if division and division.time_slot: + date = request.POST[str(division.venue_group.id)] + if date: + time = "%s %s" % (date, division.time_slot) + try: + debate.time = datetime.datetime.strptime( + time, "%Y-%m-%d %H:%M:%S") # Chrome + except ValueError: + debate.time = datetime.datetime.strptime( + time, "%d/%m/%Y %H:%M:%S") # Others + + debate.save() + + messages.success(self.request, "Applied schedules to debates") + return super().post(request, *args, **kwargs) + + +# ============================================================================== +# Sides Editing and Viewing +# ============================================================================== + +class BaseSideAllocationsView(TournamentMixin, VueTableTemplateView): + + page_title = "Side Pre-Allocations" + + def get_table(self): + tournament = self.get_tournament() + teams = tournament.team_set.all() + rounds = tournament.prelim_rounds() + + tpas = dict() + for tpa in TeamPositionAllocation.objects.filter(round__in=rounds): + tpas[(tpa.team.id, tpa.round.seq)] = TPA_MAP[tpa.position] + + table = TabbycatTableBuilder(view=self) + table.add_team_columns(teams) + + headers = [round.abbreviation for round in rounds] + data = [[tpas.get((team.id, round.id), "—") for round in rounds] for team in teams] + table.add_columns(headers, data) + + return table + + +class SideAllocationsView(SuperuserRequiredMixin, BaseSideAllocationsView): + pass + + +class PublicSideAllocationsView(PublicTournamentPageMixin, BaseSideAllocationsView): + public_page_preference = 'public_side_allocations' + + +class DrawMatchupsEditView(SuperuserRequiredMixin, RoundMixin, TemplateView): + template_name = 'draw_matchups_edit.html' + + def get_context_data(self, **kwargs): + round = self.get_round() + kwargs['unused_teams'] = round.unused_teams() + kwargs['draw'] = round.debate_set_with_prefetches(ordering=('room_rank',)) + possible_debates = len(kwargs['unused_teams']) // 2 + 1 + kwargs['possible_debates'] = [None] * possible_debates + return super().get_context_data(**kwargs) + + +class SaveDrawMatchups(SuperuserRequiredMixin, RoundMixin, View): + + def post(self, request, *args, **kwargs): + existing_debate_ids = [int(a.replace('debate_', '')) + for a in list(request.POST.keys()) + if a.startswith('debate_')] + for debate_id in existing_debate_ids: + debate = Debate.objects.get(id=debate_id) + new_aff_id = request.POST.get('aff_%s' % debate_id).replace('team_', + '') + new_neg_id = request.POST.get('neg_%s' % debate_id).replace('team_', + '') + + if new_aff_id and new_neg_id: + DebateTeam.objects.filter(debate=debate).delete() + debate.save() + + new_aff_team = Team.objects.get(id=int(new_aff_id)) + new_aff_dt = DebateTeam(debate=debate, + team=new_aff_team, + position=DebateTeam.POSITION_AFFIRMATIVE) + new_aff_dt.save() + + new_aff_team = Team.objects.get(id=int(new_neg_id)) + new_neg_dt = DebateTeam(debate=debate, + team=new_aff_team, + position=DebateTeam.POSITION_NEGATIVE) + new_neg_dt.save() + else: + # If there's blank debates we need to delete those + debate.delete() + + new_debate_ids = [int(a.replace('new_debate_', '')) + for a in list(request.POST.keys()) + if a.startswith('new_debate_')] + for debate_id in new_debate_ids: + new_aff_id = request.POST.get('aff_%s' % debate_id).replace('team_', + '') + new_neg_id = request.POST.get('neg_%s' % debate_id).replace('team_', + '') + + if new_aff_id and new_neg_id: + debate = Debate(round=round, venue=None) + debate.save() + + aff_team = Team.objects.get(id=int(new_aff_id)) + neg_team = Team.objects.get(id=int(new_neg_id)) + new_aff_dt = DebateTeam(debate=debate, + team=aff_team, + position=DebateTeam.POSITION_AFFIRMATIVE) + new_neg_dt = DebateTeam(debate=debate, + team=neg_team, + position=DebateTeam.POSITION_NEGATIVE) + new_aff_dt.save() + new_neg_dt.save() + + return HttpResponse("ok") + + +# ============================================================================== +# Cross-Tournament Draw Views +# ============================================================================== + +class AllTournamentsAllInstitutionsView(CrossTournamentPageMixin, CacheMixin, TemplateView): + public_page_preference = 'enable_mass_draws' + template_name = 'public_all_tournament_institutions.html' + + def get_context_data(self, **kwargs): + kwargs['institutions'] = Institution.objects.all() + return super().get_context_data(**kwargs) + + +class AllTournamentsAllVenuesView(CrossTournamentPageMixin, CacheMixin, TemplateView): + public_page_preference = 'enable_mass_draws' + template_name = 'public_all_tournament_venues.html' + + def get_context_data(self, **kwargs): + kwargs['venues'] = VenueGroup.objects.all() + return super().get_context_data(**kwargs) + + +class AllDrawsForAllTeamsView(CrossTournamentPageMixin, CacheMixin, TemplateView): + public_page_preference = 'enable_mass_draws' + template_name = 'public_all_tournament_teams.html' + + def get_context_data(self, **kwargs): + kwargs['teams'] = Team.objects.filter(tournament__active=True).select_related('tournament').prefetch_related('division') + return super().get_context_data(**kwargs) + + +class AllDrawsForInstitutionView(CrossTournamentPageMixin, CacheMixin, TemplateView): + public_page_preference = 'enable_mass_draws' + template_name = 'public_all_draws_for_institution.html' + + def get_context_data(self, **kwargs): + kwargs['institution'] = Institution.objects.get( + pk=self.kwargs['institution_id']) + kwargs['debate_teams'] = DebateTeam.objects.filter( + team__institution=kwargs['institution']).select_related( + 'debate', 'debate__division', 'debate__division__venue_group', + 'debate__round') + kwargs['debates'] = [dt.debate for dt in kwargs['debate_teams']] + return super().get_context_data(**kwargs) + + +class AllDrawsForVenueView(CrossTournamentPageMixin, CacheMixin, TemplateView): + public_page_preference = 'enable_mass_draws' + template_name = 'public_all_draws_for_venue.html' + + def get_context_data(self, **kwargs): + kwargs['venue_group'] = VenueGroup.objects.get(pk=self.kwargs['venue_id']) + kwargs['debates'] = Debate.objects.filter( + division__venue_group=kwargs['venue_group']).select_related( + 'round', 'round__tournament', 'division') + return super().get_context_data(**kwargs) diff --git a/motions/migrations/__init__.py b/tabbycat/importer/__init__.py similarity index 100% rename from motions/migrations/__init__.py rename to tabbycat/importer/__init__.py diff --git a/importer/anorak.py b/tabbycat/importer/anorak.py similarity index 73% rename from importer/anorak.py rename to tabbycat/importer/anorak.py index 3bbc1c7640a..30fa6b190f8 100644 --- a/importer/anorak.py +++ b/tabbycat/importer/anorak.py @@ -1,15 +1,15 @@ -from .base import BaseTournamentDataImporter, TournamentDataImporterError, make_lookup, make_interpreter import adjallocation.models as am +import adjfeedback.models as fm import breakqual.models as bm import draw.models as dm -import adjfeedback.models as fm import motions.models as mm -import options.models as cm import participants.models as pm import tournaments.models as tm import tournaments.utils import venues.models as vm -import csv + +from .base import BaseTournamentDataImporter, make_interpreter, make_lookup + class AnorakTournamentDataImporter(BaseTournamentDataImporter): """Anorak: The original tournament data format.""" @@ -60,7 +60,8 @@ def import_rounds(self, f): tournament=self.tournament, stage=self.lookup_round_stage, draw_type=self.lookup_draw_type, - break_category=lambda x: bm.BreakCategory.objects.get(slug=x, tournament=self.tournament) + break_category=lambda x: bm.BreakCategory.objects.get( + slug=x, tournament=self.tournament) ) counts, errors = self._import(f, tm.Round, round_interpreter) @@ -92,9 +93,10 @@ def region_interpreter(line): return None return { 'name': line['region'], - 'tournament' : self.tournament, + 'tournament': self.tournament, } - counts, errors = self._import(f, pm.Region, region_interpreter, expect_unique=False) + counts, errors = self._import(f, pm.Region, region_interpreter, + expect_unique=False) else: counts = None errors = None @@ -103,7 +105,8 @@ def region_interpreter(line): region=lambda x: pm.Region.objects.get(name=x) ) - counts, errors = self._import(f, pm.Institution, institution_interpreter, counts=counts, errors=errors) + counts, errors = self._import(f, pm.Institution, institution_interpreter, + counts=counts, errors=errors) return counts, errors @@ -130,8 +133,8 @@ def venue_group_interpreter(line): 'name' : line['group'], 'short_name' : line['group'][:25], } - counts, errors = self._import(f, vm.VenueGroup, - venue_group_interpreter, expect_unique=False) + counts, errors = self._import( + f, vm.VenueGroup, venue_group_interpreter, expect_unique=False) else: counts = None errors = None @@ -140,7 +143,8 @@ def venue_group_interpreter(line): tournament=self.tournament, group=lambda x: vm.VenueGroup.objects.get(name=x), ) - counts, errors = self._import(f, vm.Venue, venue_interpreter, counts=counts, errors=errors) + counts, errors = self._import(f, vm.Venue, venue_interpreter, + counts=counts, errors=errors) return counts, errors @@ -165,19 +169,23 @@ def import_teams(self, f, create_dummy_speakers=False): tournament=self.tournament, institution=pm.Institution.objects.lookup ) + def team_interpreter(line): line = team_interpreter_part(line) line['short_reference'] = line['reference'][:34] return line - counts, errors = self._import(f, pm.Team, team_interpreter, generated_fields={'emoji': self.get_emoji}) + counts, errors = self._import(f, pm.Team, team_interpreter, + generated_fields={'emoji': self.get_emoji}) if create_dummy_speakers: def speakers_interpreter(line): - team = pm.Teams.objects.get(name=line['reference'], institution=pm.Institution.objects.lookup(line['institution'])) + team = pm.Teams.objects.get(name=line['reference'], + institution=pm.Institution.objects.lookup(line['institution'])) for name in ["1st Speaker", "2nd Speaker", "3rd Speaker", "Reply Speaker"]: yield dict(name=name, team=team) - counts, errors = self._import(f, pm.Speaker, speakers_interpreter, counts=counts, errors=errors) + counts, errors = self._import(f, pm.Speaker, speakers_interpreter, + counts=counts, errors=errors) def import_speakers(self, f, auto_create_teams=True): """Imports speakers from a file, also creating teams as needed (unless @@ -186,21 +194,25 @@ def import_speakers(self, f, auto_create_teams=True): Each line has: name, institution, team_name, use_team_name_as_prefix, gender, - pronoun, novice_status. + pronoun, email, novice_status. """ if auto_create_teams: self.initialise_emoji_options() + def team_interpreter(line): - return { + interpreted = { 'tournament': self.tournament, 'institution': pm.Institution.objects.lookup(line['institution']), 'reference': line['team_name'], 'short_reference': line['team_name'][:34], - 'use_institution_prefix': line.get('use_institution_prefix') or None, } - counts, errors = self._import(f, pm.Team, team_interpreter, expect_unique=False, - generated_fields={'emoji': self.get_emoji}) + if line.get('use_institution_prefix'): + interpreted['use_institution_prefix'] = line['use_institution_prefix'] + return interpreted + counts, errors = self._import(f, pm.Team, team_interpreter, + expect_unique=False, + generated_fields={'emoji': self.get_emoji}) else: counts = None errors = None @@ -209,13 +221,15 @@ def team_interpreter(line): DELETE=['use_institution_prefix', 'institution', 'team_name'], gender=self.lookup_gender, ) + def speaker_interpreter(line): institution = pm.Institution.objects.lookup(line['institution']) - line['team'] = pm.Team.objects.get(institution=institution, - reference=line['team_name'], tournament=self.tournament) + line['team'] = pm.Team.objects.get( + institution=institution, reference=line['team_name'], tournament=self.tournament) line = speaker_interpreter_part(line) return line - counts, errors = self._import(f, pm.Speaker, speaker_interpreter, counts=counts, errors=errors) + counts, errors = self._import(f, pm.Speaker, speaker_interpreter, + counts=counts, errors=errors) return counts, errors @@ -227,26 +241,29 @@ def import_adjudicators(self, f, auto_conflict=True): Each line has: name, institution, rating, gender, independent, novice, cellphone, - email, notes, institution_conflicts, team_conflicts + adj_core, email, notes, institution_conflicts, team_conflicts, + adj_conflicts """ adjudicator_interpreter = make_interpreter( institution=pm.Institution.objects.lookup, tournament=self.tournament, gender=self.lookup_gender, - DELETE=['team_conflicts', 'institution_conflicts'] + DELETE=['team_conflicts', 'institution_conflicts', 'adj_conflicts'] ) counts, errors = self._import(f, pm.Adjudicator, adjudicator_interpreter) def test_score_interpreter(line): institution = pm.Institution.objects.lookup(line['institution']) - return { - 'adjudicator' : pm.Adjudicator.objects.get(name=line['name'], institution=institution, tournament=self.tournament), - 'score' : float(line['test_score']), - 'round' : None, - } - counts, errors = self._import(f, fm.AdjudicatorTestScoreHistory, test_score_interpreter, - counts=counts, errors=errors) + if line['test_score']: + return { + 'adjudicator' : pm.Adjudicator.objects.get(name=line['name'], institution=institution, tournament=self.tournament), + 'score' : line['test_score'], + 'round' : None, + } + counts, errors = self._import(f, fm.AdjudicatorTestScoreHistory, + test_score_interpreter, counts=counts, + errors=errors) def own_institution_conflict_interpreter(line): institution = pm.Institution.objects.lookup(line['institution']) @@ -254,8 +271,9 @@ def own_institution_conflict_interpreter(line): 'adjudicator' : pm.Adjudicator.objects.get(name=line['name'], institution=institution, tournament=self.tournament), 'institution' : institution, } - counts, errors = self._import(f, am.AdjudicatorInstitutionConflict, own_institution_conflict_interpreter, - counts=counts, errors=errors) + counts, errors = self._import(f, am.AdjudicatorInstitutionConflict, + own_institution_conflict_interpreter, + counts=counts, errors=errors) def institution_conflict_interpreter(line): if not line.get('institution_conflicts'): @@ -269,22 +287,43 @@ def institution_conflict_interpreter(line): 'adjudicator' : adjudicator, 'institution' : institution, } - counts, errors = self._import(f, am.AdjudicatorInstitutionConflict, institution_conflict_interpreter, - counts=counts, errors=errors) + counts, errors = self._import(f, am.AdjudicatorInstitutionConflict, + institution_conflict_interpreter, + counts=counts, errors=errors) def team_conflict_interpreter(line): if not line.get('team_conflicts'): return adj_inst = pm.Institution.objects.lookup(line['institution']) - adjudicator = pm.Adjudicator.objects.get(name=line['name'], institution=adj_inst, tournament=self.tournament) + adjudicator = pm.Adjudicator.objects.get(name=line['name'], + institution=adj_inst, tournament=self.tournament) for team_name in line['team_conflicts'].split(","): + team_name = team_name.strip() team = pm.Team.objects.lookup(team_name) yield { 'adjudicator' : adjudicator, 'team' : team, } - counts, errors = self._import(f, am.AdjudicatorConflict, team_conflict_interpreter, - counts=counts, errors=errors) + counts, errors = self._import(f, am.AdjudicatorConflict, + team_conflict_interpreter, + counts=counts, errors=errors) + + def adj_conflict_interpreter(line): + if not line.get('adj_conflicts'): + return + adj_inst = pm.Institution.objects.lookup(line['institution']) + adjudicator = pm.Adjudicator.objects.get(name=line['name'], + institution=adj_inst, tournament=self.tournament) + for adj_name in line['adj_conflicts'].split(","): + adj_name = adj_name.strip() + conflicted_adj = pm.Adjudicator.objects.get(name=adj_name) + yield { + 'adjudicator' : adjudicator, + 'conflict_adjudicator' : conflicted_adj, + } + counts, errors = self._import(f, am.AdjudicatorAdjudicatorConflict, + adj_conflict_interpreter, + counts=counts, errors=errors) return counts, errors @@ -317,8 +356,8 @@ def side_interpreter(line): def import_adj_feedback_questions(self, f): """Imports adjudicator feedback questions from a file. Each line has: - seq, reference, name, text, answer_type, required, team_on_orallist, - chair_on_panel, panel_on_chair, panel_on_panel, min_value, max_value + seq, reference, name, text, answer_type, required, from_adj, from_team, + min_value, max_value """ question_interpreter = make_interpreter( tournament=self.tournament, @@ -327,6 +366,30 @@ def import_adj_feedback_questions(self, f): return self._import(f, fm.AdjudicatorFeedbackQuestion, question_interpreter) + def import_adj_venue_constraints(self, f): + """Imports venue constraints from a file. + Each line has: + adjudicator, group, priority + """ + adj_venue_constraints_interpreter = make_interpreter( + adjudicator=lambda x: pm.Adjudicator.objects.get(name=x), + venue_group=lambda x: vm.VenueGroup.objects.get(name=x), + ) + + return self._import(f, vm.AdjudicatorVenueConstraint, adj_venue_constraints_interpreter) + + def import_team_venue_constraints(self, f): + """Imports venue constraints from a file. + Each line has: + team, group, priority + """ + team_venue_constraints_interpreter = make_interpreter( + team=pm.Team.objects.lookup, + venue_group=lambda x: vm.VenueGroup.objects.get(name=x), + ) + + return self._import(f, vm.TeamVenueConstraint, team_venue_constraints_interpreter) + def auto_make_rounds(self, num_rounds): """Makes the number of rounds specified. The first one is random and the rest are all power-paired. The last one is silent. This is intended as a diff --git a/importer/base.py b/tabbycat/importer/base.py similarity index 96% rename from importer/base.py rename to tabbycat/importer/base.py index b5d57acba6c..906fc87033f 100644 --- a/importer/base.py +++ b/tabbycat/importer/base.py @@ -13,10 +13,11 @@ from participants.emoji import EMOJI_LIST NON_FIELD_ERRORS = '__all__' -DUPLICATE_INFO = 19 # logging level just below INFO +DUPLICATE_INFO = 19 # Logging level just below INFO logging.addLevelName(DUPLICATE_INFO, 'DUPLICATE_INFO') -def make_interpreter(DELETE=[], **kwargs): + +def make_interpreter(DELETE=[], **kwargs): # flake8: noqa """Convenience function for building an interpreter.""" def interpreter(line): # remove blank and unwanted values @@ -33,6 +34,7 @@ def interpreter(line): return line return interpreter + def make_lookup(name, choices): def lookup(val): for k, v in choices.items(): @@ -45,6 +47,7 @@ def lookup(val): class TournamentDataImporterFatal(Exception): pass + class TournamentDataImporterError(Exception): """Inspired by Django's ValidationError, but adapted for the importer's needs. This keeps track of multiple errors and is initialized blank. @@ -95,7 +98,7 @@ def update_with_validation_error(self, lineno, model, ve): for error in ve.error_list: self.add(lineno, model, "; ".join(error), NON_FIELD_ERRORS) else: - message = "Model validation failed: "+ str(ve) + message = "Model validation failed: " + str(ve) self.add(lineno, model, message, NON_FIELD_ERRORS) def update(self, tdie): @@ -192,6 +195,12 @@ def _import(self, csvfile, model, interpreter=make_interpreter(), skipped_because_existing = 0 for lineno, line in enumerate(reader, start=2): + + # Strip whitespace first + for k in line: + if isinstance(line[k], str): + line[k] = line[k].strip() + try: kwargs_list = interpreter(line) if isinstance(kwargs_list, GeneratorType): @@ -232,7 +241,7 @@ def _import(self, csvfile, model, interpreter=make_interpreter(), inst = model(**kwargs) except MultipleObjectsReturned as e: if expect_unique: - errors.add(lineno, model, e.message) + errors.add(lineno, model, str(e)) continue except FieldError as e: match = re.match("Cannot resolve keyword '(\w+)' into field.", str(e)) @@ -248,7 +257,7 @@ def _import(self, csvfile, model, interpreter=make_interpreter(), else: raise except ValueError as e: - errors.add(lineno, model, e.message) + errors.add(lineno, model, str(e)) continue else: skipped_because_existing += 1 diff --git a/importer/forms.py b/tabbycat/importer/forms.py similarity index 80% rename from importer/forms.py rename to tabbycat/importer/forms.py index edb92fcc712..bdfd2d42a02 100644 --- a/importer/forms.py +++ b/tabbycat/importer/forms.py @@ -1,14 +1,17 @@ from django import forms -from django.utils.translation import ugettext as _ + class AddInstitutionsForm(forms.Form): pass + class AddTeamsForm(forms.Form): pass + class AddVenuesForm(forms.Form): pass + class AddAdjudicatorsForm(forms.Form): pass diff --git a/options/migrations/__init__.py b/tabbycat/importer/management/__init__.py similarity index 100% rename from options/migrations/__init__.py rename to tabbycat/importer/management/__init__.py diff --git a/importer/management/commands/importtournament.py b/tabbycat/importer/management/commands/importtournament.py similarity index 83% rename from importer/management/commands/importtournament.py rename to tabbycat/importer/management/commands/importtournament.py index 01cae48251e..f1542fb1f5f 100644 --- a/importer/management/commands/importtournament.py +++ b/tabbycat/importer/management/commands/importtournament.py @@ -1,7 +1,5 @@ import os -import csv import logging -from optparse import make_option from django.core.management.base import BaseCommand, CommandError from django.conf import settings @@ -13,6 +11,7 @@ from importer.anorak import AnorakTournamentDataImporter from importer.base import DUPLICATE_INFO, TournamentDataImporterFatal + class Command(BaseCommand): help = 'Delete all data for a tournament and import from specified directory.' @@ -21,25 +20,25 @@ def add_arguments(self, parser): parser.add_argument('items', help="Items to import (default: import all)", nargs="*", default=[]) parser.add_argument('-r', '--auto-rounds', type=int, metavar='N', default=None, - help='Create N preliminary rounds automatically. Use either this or a rounds.csv file, but not both.') + help='Create N preliminary rounds automatically. Use either this or a rounds.csv file, but not both.') parser.add_argument('--force', action='store_true', default=False, - help='Do not prompt before deleting tournament that already exists.') + help='Do not prompt before deleting tournament that already exists.') parser.add_argument('--keep-existing', action='store_true', default=False, - help='Keep existing tournament and data, skipping lines if they are duplicates.') + help='Keep existing tournament and data, skipping lines if they are duplicates.') parser.add_argument('--delete-institutions', action='store_true', default=False, - help='Delete all institutions from the database. Overrides --keep-existing.') + help='Delete all institutions from the database. Overrides --keep-existing.') parser.add_argument('--delete-venue-groups', action='store_true', default=False, - help='Delete all venue groups from the database. Overrides --keep-existing.') + help='Delete all venue groups from the database. Overrides --keep-existing.') parser.add_argument('--relaxed', action='store_false', dest='strict', default=True, - help='Don\'t crash if there is an error, just skip and keep going.') + help='Don\'t crash if there is an error, just skip and keep going.') # Tournament options parser.add_argument('-s', '--slug', type=str, action='store', default=None, - help='Override tournament slug. (Default: use name of directory.)'), + help='Override tournament slug. (Default: use name of directory.)'), parser.add_argument('--name', type=str, action='store', default=None, - help='Override tournament name. (Default: use name of directory.)'), + help='Override tournament name. (Default: use name of directory.)'), parser.add_argument('--short-name', type=str, action='store', default=None, - help='Override tournament short name. (Default: use name of directory.)'), + help='Override tournament short name. (Default: use name of directory.)'), def handle(self, *args, **options): self.options = options @@ -53,8 +52,8 @@ def handle(self, *args, **options): self.delete_venue_groups() self.make_tournament() loglevel = [logging.ERROR, logging.WARNING, DUPLICATE_INFO, logging.DEBUG][self.verbosity] - self.importer = AnorakTournamentDataImporter(self.t, loglevel=loglevel, - strict=options['strict'], expect_unique=not options['keep_existing']) + self.importer = AnorakTournamentDataImporter( + self.t, loglevel=loglevel, strict=options['strict'], expect_unique=not options['keep_existing']) self._make('venue_groups') self._make('venues') @@ -68,26 +67,32 @@ def handle(self, *args, **options): self._make('motions') self._make('sides') self._make('questions', self.importer.import_adj_feedback_questions) + self._make('adj_venue_constraints') + self._make('team_venue_constraints') def _print_stage(self, message): if self.verbosity > 0: - if self.color: message = "\033[0;36m" + message + "\033[0m\n" + if self.color: + message = "\033[0;36m" + message + "\033[0m\n" self.stdout.write(message) def _print_result(self, counts, errors): if self.verbosity > 0: if errors: for message in errors.itermessages(): - if self.color: message = "\033[1;32m" + message + "\032[0m\n" + if self.color: + message = "\033[1;32m" + message + "\032[0m\n" self.stdout.write(message) count_strs = ("{1:d} {0}".format(model._meta.verbose_name_plural, count) for model, count in counts.items()) message = "Imported " + ", ".join(count_strs) + ", hit {1:d} errors".format(counts, len(errors)) - if self.color: "\033[0;36m" + message + "\033[0m\n" + if self.color: + "\033[0;36m" + message + "\033[0m\n" self.stdout.write(message) def _warning(self, message): if self.verbosity > 0: - if self.color: message = "\033[0;33mWarning: " + message + "\033[0m\n" + if self.color: + message = "\033[0;33mWarning: " + message + "\033[0m\n" self.stdout.write(message) def _csv_file_path(self, filename): @@ -132,11 +137,11 @@ def _check_return(path): self.stdout.write('Importing from directory: ' + path) return path - if os.path.isabs(arg): # absolute path + if os.path.isabs(arg): # Absolute path return _check_return(arg) # relative path, look in debate/data - base_path = os.path.join(settings.BASE_DIR, 'data') + base_path = os.path.join(settings.BASE_DIR, '..', 'data') data_path = os.path.join(base_path, arg) return _check_return(data_path) diff --git a/importer/templates/add_adjudicators.html b/tabbycat/importer/templates/add_adjudicators.html similarity index 100% rename from importer/templates/add_adjudicators.html rename to tabbycat/importer/templates/add_adjudicators.html diff --git a/importer/templates/add_institutions.html b/tabbycat/importer/templates/add_institutions.html similarity index 100% rename from importer/templates/add_institutions.html rename to tabbycat/importer/templates/add_institutions.html diff --git a/importer/templates/add_teams.html b/tabbycat/importer/templates/add_teams.html similarity index 100% rename from importer/templates/add_teams.html rename to tabbycat/importer/templates/add_teams.html diff --git a/importer/templates/add_venue_preferences.html b/tabbycat/importer/templates/add_venue_preferences.html similarity index 100% rename from importer/templates/add_venue_preferences.html rename to tabbycat/importer/templates/add_venue_preferences.html diff --git a/importer/templates/add_venues.html b/tabbycat/importer/templates/add_venues.html similarity index 100% rename from importer/templates/add_venues.html rename to tabbycat/importer/templates/add_venues.html diff --git a/importer/templates/confirmed_data.html b/tabbycat/importer/templates/confirmed_data.html similarity index 66% rename from importer/templates/confirmed_data.html rename to tabbycat/importer/templates/confirmed_data.html index d9be04c1852..91179df679f 100644 --- a/importer/templates/confirmed_data.html +++ b/tabbycat/importer/templates/confirmed_data.html @@ -8,7 +8,12 @@ {% block content %}
      -

      {{ confirmed.quantity }} {{ confirmed.kind }} created. Add more data.

      +

      + {{ confirmed.quantity }} {{ confirmed.kind }} created. + + Add more data. + +

      {% endblock content %} diff --git a/importer/templates/data_index.html b/tabbycat/importer/templates/data_index.html similarity index 100% rename from importer/templates/data_index.html rename to tabbycat/importer/templates/data_index.html diff --git a/importer/templates/edit_adjudicators.html b/tabbycat/importer/templates/edit_adjudicators.html similarity index 93% rename from importer/templates/edit_adjudicators.html rename to tabbycat/importer/templates/edit_adjudicators.html index fa067275daf..36e37849767 100644 --- a/importer/templates/edit_adjudicators.html +++ b/tabbycat/importer/templates/edit_adjudicators.html @@ -11,7 +11,8 @@

      As per the tournament's configuration, an adjudicator's rating must be between {{ pref.adj_min_score }} and {{ pref.adj_max_score }}. Adjudicators marked as 'shared' will not be associated with any particular tournament but - will be available to any tournament which has the + will be available to any tournament which has the + Share Adjudicators" setting enabled.

      @@ -24,7 +25,7 @@
      -
      {{ key }}'s Adjudicators
      +
      {{ key }}'s Adjudicators
        diff --git a/importer/templates/edit_institutions.html b/tabbycat/importer/templates/edit_institutions.html similarity index 100% rename from importer/templates/edit_institutions.html rename to tabbycat/importer/templates/edit_institutions.html diff --git a/importer/templates/edit_teams.html b/tabbycat/importer/templates/edit_teams.html similarity index 97% rename from importer/templates/edit_teams.html rename to tabbycat/importer/templates/edit_teams.html index 5adeb4325a5..42c466da7cb 100644 --- a/importer/templates/edit_teams.html +++ b/tabbycat/importer/templates/edit_teams.html @@ -22,7 +22,7 @@
        -
        {{ institution.name }}'s Teams
        +
        {{ institution.name }}'s Teams
        diff --git a/importer/templates/edit_venue_preferences.html b/tabbycat/importer/templates/edit_venue_preferences.html similarity index 96% rename from importer/templates/edit_venue_preferences.html rename to tabbycat/importer/templates/edit_venue_preferences.html index 5e7cbbdd1ad..560de67a609 100644 --- a/importer/templates/edit_venue_preferences.html +++ b/tabbycat/importer/templates/edit_venue_preferences.html @@ -28,7 +28,7 @@
        -

        {{ institution.name }}

        +

        {{ institution.name }}

          diff --git a/importer/templates/edit_venues.html b/tabbycat/importer/templates/edit_venues.html similarity index 100% rename from importer/templates/edit_venues.html rename to tabbycat/importer/templates/edit_venues.html diff --git a/participants/__init__.py b/tabbycat/importer/tests/__init__.py similarity index 100% rename from participants/__init__.py rename to tabbycat/importer/tests/__init__.py diff --git a/importer/tests/test_anorak.py b/tabbycat/importer/tests/test_anorak.py similarity index 78% rename from importer/tests/test_anorak.py rename to tabbycat/importer/tests/test_anorak.py index ce83766d943..5ad1c06a14e 100644 --- a/importer/tests/test_anorak.py +++ b/tabbycat/importer/tests/test_anorak.py @@ -1,6 +1,6 @@ """Unit tests for the Anorak importer.""" -from unittest import skip, expectedFailure +from unittest import skip import logging import os.path @@ -17,16 +17,18 @@ from ..anorak import AnorakTournamentDataImporter from ..base import TournamentDataImporterError + class TestImporterAnorak(TestCase): - TESTDIR = "data/test/standard" - TESTDIR_CHOICES = "data/test/choices" - TESTDIR_ERRORS = "data/test/errors" + TESTDIR = "../data/test/standard" + TESTDIR_CHOICES = "../data/test/choices" + TESTDIR_ERRORS = "../data/test/errors" def setUp(self): super(TestImporterAnorak, self).setUp() # create tournament + self.maxDiff = None self.t = tm.Tournament(slug="import-test") self.t.save() self.logger = logging.getLogger(__name__) @@ -37,17 +39,21 @@ def _open_csv_file(self, dir, filename): path = os.path.join(dir, filename + ".csv") return open(path, 'r') + def assertCountsDictEqual(self, counts, expected): # noqa + counts = dict(counts) + self.assertEqual(counts, expected) + def test_break_categories(self): f = self._open_csv_file(self.TESTDIR, "break_categories") counts, errors = self.importer.import_break_categories(f) - self.assertEqual(counts, {bm.BreakCategory: 3}) + self.assertCountsDictEqual(counts, {bm.BreakCategory: 3}) self.assertFalse(errors) def test_rounds(self): self.test_break_categories() f = self._open_csv_file(self.TESTDIR, "rounds") counts, errors = self.importer.import_rounds(f) - self.assertEqual(counts, {tm.Round: 10}) + self.assertCountsDictEqual(counts, {tm.Round: 10}) self.assertFalse(errors) def test_auto_make_rounds(self): @@ -57,38 +63,39 @@ def test_auto_make_rounds(self): def test_venues(self): f = self._open_csv_file(self.TESTDIR, "venues") counts, errors = self.importer.import_venues(f) - self.assertEqual(counts, {vm.VenueGroup: 7, vm.Venue: 23}) + self.assertCountsDictEqual(counts, {vm.VenueGroup: 7, vm.Venue: 23}) self.assertFalse(errors) def test_institutions(self): f = self._open_csv_file(self.TESTDIR, "institutions") counts, errors = self.importer.import_institutions(f) - self.assertEqual(counts, {pm.Institution: 13, pm.Region: 6}) + self.assertCountsDictEqual(counts, {pm.Institution: 13, pm.Region: 6}) self.assertFalse(errors) @skip("test file does not yet exist") def test_teams(self): - f = self._open_csv_file(self.TESTDIR, "teams") + f = self._open_csv_file(self.TESTDIR, "teams") # noqa counts, errors = self.importer.import_teams(self) - self.assertEqual(counts, {pm.Team: 12}) + self.assertCountsDictEqual(counts, {pm.Team: 12}) self.assertFalse(errors) def test_speakers(self): self.test_institutions() f = self._open_csv_file(self.TESTDIR, "speakers") counts, errors = self.importer.import_speakers(f) - self.assertEqual(counts, {pm.Team: 24, pm.Speaker: 72}) + self.assertCountsDictEqual(counts, {pm.Team: 24, pm.Speaker: 72}) self.assertFalse(errors) def test_adjudicators(self): self.test_speakers() f = self._open_csv_file(self.TESTDIR, "judges") counts, errors = self.importer.import_adjudicators(f) - self.assertEqual(counts, { + self.assertCountsDictEqual(counts, { pm.Adjudicator: 27, - fm.AdjudicatorTestScoreHistory: 27, + fm.AdjudicatorTestScoreHistory: 24, am.AdjudicatorInstitutionConflict: 36, - am.AdjudicatorConflict: 7, + am.AdjudicatorAdjudicatorConflict: 5, + am.AdjudicatorConflict: 8, }) self.assertFalse(errors) @@ -96,13 +103,13 @@ def test_motions(self): self.test_rounds() f = self._open_csv_file(self.TESTDIR, "motions") counts, errors = self.importer.import_motions(f) - self.assertEqual(counts, {mm.Motion: 18}) + self.assertCountsDictEqual(counts, {mm.Motion: 18}) self.assertFalse(errors) def test_adj_feedback_questions(self): f = self._open_csv_file(self.TESTDIR, "questions") counts, errors = self.importer.import_adj_feedback_questions(f) - self.assertEqual(counts, {fm.AdjudicatorFeedbackQuestion: 11}) + self.assertCountsDictEqual(counts, {fm.AdjudicatorFeedbackQuestion: 11}) self.assertFalse(errors) def test_invalid_line(self): @@ -118,8 +125,9 @@ def test_weird_choices_judges(self): self.test_speakers() f = self._open_csv_file(self.TESTDIR_CHOICES, "judges") counts, errors = self.importer.import_adjudicators(f) - self.assertEqual(counts, { + self.assertCountsDictEqual(counts, { pm.Adjudicator: 27, + am.AdjudicatorAdjudicatorConflict: 0, fm.AdjudicatorTestScoreHistory: 27, am.AdjudicatorInstitutionConflict: 36, am.AdjudicatorConflict: 7, @@ -139,7 +147,7 @@ def test_blank_entry_not_strict(self): self.importer.strict = False with self.assertLogs(self.logger, logging.WARNING) as logscm: counts, errors = self.importer.import_venues(f) - self.assertEqual(counts, {vm.Venue: 20, vm.VenueGroup: 7}) + self.assertCountsDictEqual(counts, {vm.Venue: 20, vm.VenueGroup: 7}) self.assertEqual(len(errors), 3) self.assertEqual(len(logscm.records), 3) self.importer.strict = True diff --git a/importer/urls.py b/tabbycat/importer/urls.py similarity index 95% rename from importer/urls.py rename to tabbycat/importer/urls.py index 251c2a03869..0ae0a1c21a8 100644 --- a/importer/urls.py +++ b/tabbycat/importer/urls.py @@ -1,5 +1,4 @@ -from django.conf.urls import * -from django.core.urlresolvers import reverse +from django.conf.urls import url from . import views @@ -26,4 +25,4 @@ url(r'^data/venue_preferences/$', views.add_venue_preferences, name='add_venue_preferences'), url(r'^data/venue_preferences/edit/$', views.edit_venue_preferences, name='edit_venue_preferences'), url(r'^data/venue_preferences/confirm/$', views.confirm_venue_preferences, name='confirm_venue_preferences'), -] \ No newline at end of file +] diff --git a/importer/views.py b/tabbycat/importer/views.py similarity index 88% rename from importer/views.py rename to tabbycat/importer/views.py index fbfd9ea9c1b..401da00be02 100644 --- a/importer/views.py +++ b/tabbycat/importer/views.py @@ -1,9 +1,8 @@ -from utils.views import * +from django.shortcuts import render -from . import forms - -from participants.models import Adjudicator, Institution, Team, Speaker -from venues.models import Venue, VenueGroup, InstitutionVenueConstraint +from participants.models import Adjudicator, Institution, Speaker, Team +from utils.views import admin_required, expect_post, tournament_view +from venues.models import InstitutionVenueConstraint, Venue, VenueGroup @admin_required @@ -12,12 +11,13 @@ def data_index(request, t): return render(request, 'data_index.html') -# INSTITUTIONS +# ============================================================================== +# Institutions +# ============================================================================== @admin_required @tournament_view def add_institutions(request, t): - form = forms.AddInstitutionsForm return render(request, 'add_institutions.html') @@ -60,14 +60,17 @@ def confirm_institutions(request, t): confirmed = {"kind": "Institutions", "quantity": len(institution_names)} return render(request, 'confirmed_data.html', dict(confirmed=confirmed)) -# VENUES + +# ============================================================================== +# Venues +# ============================================================================== @admin_required @tournament_view def add_venues(request, t): - form = forms.AddVenuesForm return render(request, 'add_venues.html') + @admin_required @expect_post @tournament_view @@ -110,7 +113,7 @@ def confirm_venues(request, t): venue_group = VenueGroup.objects.get(name=venue_groups[i]) except VenueGroup.DoesNotExist: venue_group = VenueGroup(name=venue_groups[i], - short_name=venue_groups[i][:15]).save() + short_name=venue_groups[i][:15]).save() else: venue_group = None @@ -126,7 +129,10 @@ def confirm_venues(request, t): confirmed = {"kind": "Venues", "quantity": len(venue_names)} return render(request, 'confirmed_data.html', dict(confirmed=confirmed)) -# VENUE PREFERENCES + +# ============================================================================== +# Venue Preferences +# ============================================================================== @admin_required @tournament_view @@ -159,7 +165,6 @@ def edit_venue_preferences(request, t): @tournament_view def confirm_venue_preferences(request, t): - institutions = [] for institution_id in request.POST.getlist('institutionIDs'): institution = Institution.objects.get(pk=institution_id) InstitutionVenueConstraint.objects.filter( @@ -188,14 +193,15 @@ def confirm_venue_preferences(request, t): confirmed = {"kind": "Venue Preferences", "quantity": created_preferences} return render(request, 'confirmed_data.html', dict(confirmed=confirmed)) -# TEAMS +# ============================================================================== +# Teams +# ============================================================================== @admin_required @tournament_view def add_teams(request, t): institutions = Institution.objects.all() - form = forms.AddTeamsForm return render(request, 'add_teams.html', dict(institutions=institutions)) @@ -208,7 +214,8 @@ def edit_teams(request, t): # Set default speaker text to match tournament setup default_speakers = "" for i in range(1, t.pref('substantive_speakers') + 1): - if i > 1: default_speakers += "," + if i > 1: + default_speakers += "," default_speakers += "Speaker %s" % i for name, quantity in request.POST.items(): @@ -276,17 +283,16 @@ def confirm_teams(request, t): confirmed = {"kind": "Teams", "quantity": int((len(sorted_post) - 1) / 4)} return render(request, 'confirmed_data.html', dict(confirmed=confirmed)) -# ADJUDICATORS +# ============================================================================== +# Adjudicators +# ============================================================================== @admin_required @tournament_view def add_adjudicators(request, t): institutions = Institution.objects.all() - form = forms.AddAdjudicatorsForm - return render(request, - 'add_adjudicators.html', - dict(institutions=institutions)) + return render(request, 'add_adjudicators.html', dict(institutions=institutions)) @admin_required diff --git a/local_settings.example b/tabbycat/local_settings.example similarity index 51% rename from local_settings.example rename to tabbycat/local_settings.example index 825da1b18eb..445ca34f86f 100644 --- a/local_settings.example +++ b/tabbycat/local_settings.example @@ -1,7 +1,22 @@ -import os - LOCAL_SETTINGS = True -from settings import * +from settings import * # flake8: noqa + +# ============================================================================== +# Database Settings +# ============================================================================== + +SECRET_KEY = '#2q43u&tp4((4&m3i8v%w-6z6pp7m(v0-6@w@i!j5n)n15epwc' +DATABASES = { + 'default': { + 'ENGINE' : 'django.db.backends.postgresql_psycopg2', + 'NAME' : '', + 'USER' : '', + 'PASSWORD': '', + 'HOST': 'localhost', + 'PORT': '5432', + 'CONN_MAX_AGE': 600, + } +} # ============================================================================== # Overwrites main settings @@ -22,13 +37,18 @@ INTERNAL_IPS = ( '127.0.0.1' ) -MIDDLEWARE_CLASSES += ( - 'debug_toolbar.middleware.DebugToolbarMiddleware', -) +# ============================================================================== +# Static Files & Compilation +# ============================================================================== -INSTALLED_APPS += ( - 'debug_toolbar', -) +# collectstatic always runs GULP_PRODUCTION_COMMAND, even on debug +GULP_PRODUCTION_COMMAND = "npm run gulp build -- --development" +GULP_DEVELOP_COMMAND = "npm run gulp watch -- --development" + +# Dont use whitenoise with debug enabled +# When local dont compress assets (not --production) and use watchify if debug +if DEBUG: + STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage' # ============================================================================== # Caching @@ -49,45 +69,41 @@ TEMPLATES[0]['OPTIONS']['loaders'] = [ 'django.template.loaders.app_directories.Loader', ] -# ============================================================================== -# Debug Toolbar -# ============================================================================== - -DEBUG_TOOLBAR_PATCH_SETTINGS = False - -DEBUG_TOOLBAR_PANELS = ( - 'debug_toolbar.panels.versions.VersionsPanel', - 'debug_toolbar.panels.timer.TimerPanel', - 'debug_toolbar.panels.settings.SettingsPanel', - 'debug_toolbar.panels.headers.HeadersPanel', - 'debug_toolbar.panels.request.RequestPanel', - 'debug_toolbar.panels.sql.SQLPanel', - 'debug_toolbar.panels.staticfiles.StaticFilesPanel', - 'debug_toolbar.panels.templates.TemplatesPanel', - 'debug_toolbar.panels.cache.CachePanel', - 'debug_toolbar.panels.signals.SignalsPanel', - 'debug_toolbar.panels.logging.LoggingPanel', - #'debug_toolbar.panels.redirects.RedirectsPanel', -) - -DEBUG_TOOLBAR_CONFIG = { - 'INTERCEPT_REDIRECTS': False, - 'JQUERY_URL': '/static/js/vendor/jquery.min.js', # Enables offline work -} +# Use the cache with database write through for local sessions +SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # ============================================================================== -# Database Settings +# Debug Toolbar # ============================================================================== -SECRET_KEY = '#2q43u&tp4((4&m3i8v%w-6z6pp7m(v0-6@w@i!j5n)n15epwc' -DATABASES = { - 'default': { - 'ENGINE' : 'django.db.backends.postgresql_psycopg2', - 'NAME' : '', - 'USER' : '', - 'PASSWORD': '', - 'HOST': 'localhost', - 'PORT': '5432', - 'CONN_MAX_AGE': 600, +ENABLE_DEBUG_TOOLBAR = True + +if ENABLE_DEBUG_TOOLBAR: + MIDDLEWARE_CLASSES += ( + 'debug_toolbar.middleware.DebugToolbarMiddleware', + ) + + INSTALLED_APPS += ( + 'debug_toolbar', + ) + + DEBUG_TOOLBAR_PATCH_SETTINGS = False + + DEBUG_TOOLBAR_PANELS = ( + 'debug_toolbar.panels.versions.VersionsPanel', + 'debug_toolbar.panels.timer.TimerPanel', + 'debug_toolbar.panels.settings.SettingsPanel', + 'debug_toolbar.panels.headers.HeadersPanel', + 'debug_toolbar.panels.request.RequestPanel', + 'debug_toolbar.panels.sql.SQLPanel', + 'debug_toolbar.panels.staticfiles.StaticFilesPanel', + 'debug_toolbar.panels.templates.TemplatesPanel', + 'debug_toolbar.panels.cache.CachePanel', + 'debug_toolbar.panels.signals.SignalsPanel', + 'debug_toolbar.panels.logging.LoggingPanel', + #'debug_toolbar.panels.redirects.RedirectsPanel', + ) + + DEBUG_TOOLBAR_CONFIG = { + 'JQUERY_URL': '/static/js/vendor/jquery.js', # Enables offline work } -} diff --git a/manage.py b/tabbycat/manage.py similarity index 100% rename from manage.py rename to tabbycat/manage.py diff --git a/participants/migrations/__init__.py b/tabbycat/motions/__init__.py similarity index 100% rename from participants/migrations/__init__.py rename to tabbycat/motions/__init__.py diff --git a/tabbycat/motions/admin.py b/tabbycat/motions/admin.py new file mode 100644 index 00000000000..20e1413a410 --- /dev/null +++ b/tabbycat/motions/admin.py @@ -0,0 +1,23 @@ +from django.contrib import admin + +from .models import DebateTeamMotionPreference, Motion + +from utils.admin import BaseModelAdmin + + +# ============================================================================== +# Motions +# ============================================================================== + +class MotionAdmin(admin.ModelAdmin, BaseModelAdmin): + list_display = ('reference', 'round', 'seq', 'get_tournament') + list_filter = ('round', 'divisions') + +admin.site.register(Motion, MotionAdmin) + + +class DebateTeamMotionPreferenceAdmin(admin.ModelAdmin, BaseModelAdmin): + list_display = ('ballot_submission', 'get_confirmed', 'get_team', + 'get_team_position', 'preference', 'get_motion_ref') + +admin.site.register(DebateTeamMotionPreference, DebateTeamMotionPreferenceAdmin) diff --git a/motions/migrations/0001_initial.py b/tabbycat/motions/migrations/0001_initial.py similarity index 100% rename from motions/migrations/0001_initial.py rename to tabbycat/motions/migrations/0001_initial.py diff --git a/motions/migrations/0002_auto_20160103_1927.py b/tabbycat/motions/migrations/0002_auto_20160103_1927.py similarity index 100% rename from motions/migrations/0002_auto_20160103_1927.py rename to tabbycat/motions/migrations/0002_auto_20160103_1927.py diff --git a/motions/migrations/0003_auto_20160109_1834.py b/tabbycat/motions/migrations/0003_auto_20160109_1834.py similarity index 100% rename from motions/migrations/0003_auto_20160109_1834.py rename to tabbycat/motions/migrations/0003_auto_20160109_1834.py diff --git a/motions/migrations/0004_auto_20160228_1838.py b/tabbycat/motions/migrations/0004_auto_20160228_1838.py similarity index 100% rename from motions/migrations/0004_auto_20160228_1838.py rename to tabbycat/motions/migrations/0004_auto_20160228_1838.py diff --git a/motions/migrations/0005_auto_20160507_1521.py b/tabbycat/motions/migrations/0005_auto_20160507_1521.py similarity index 100% rename from motions/migrations/0005_auto_20160507_1521.py rename to tabbycat/motions/migrations/0005_auto_20160507_1521.py diff --git a/tabbycat/motions/migrations/0006_auto_20160621_1129.py b/tabbycat/motions/migrations/0006_auto_20160621_1129.py new file mode 100644 index 00000000000..085ce3a79f5 --- /dev/null +++ b/tabbycat/motions/migrations/0006_auto_20160621_1129.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-06-21 11:29 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('motions', '0005_auto_20160507_1521'), + ] + + operations = [ + migrations.AlterField( + model_name='motion', + name='divisions', + field=models.ManyToManyField(blank=True, to='divisions.Division'), + ), + ] diff --git a/tabbycat/motions/migrations/0007_auto_20160723_1720.py b/tabbycat/motions/migrations/0007_auto_20160723_1720.py new file mode 100644 index 00000000000..3e9e175eeea --- /dev/null +++ b/tabbycat/motions/migrations/0007_auto_20160723_1720.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.8 on 2016-07-23 17:20 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('motions', '0006_auto_20160621_1129'), + ] + + operations = [ + migrations.AlterField( + model_name='motion', + name='text', + field=models.TextField(help_text='The full motion e.g., "This House would straighten all bananas"', max_length=500), + ), + ] diff --git a/results/__init__.py b/tabbycat/motions/migrations/__init__.py similarity index 100% rename from results/__init__.py rename to tabbycat/motions/migrations/__init__.py diff --git a/motions/models.py b/tabbycat/motions/models.py similarity index 76% rename from motions/models.py rename to tabbycat/motions/models.py index c46ed32b07a..33c1205f988 100644 --- a/motions/models.py +++ b/tabbycat/motions/models.py @@ -1,23 +1,22 @@ from django.db import models + class Motion(models.Model): """Represents a single motion (not a set of motions).""" seq = models.IntegerField( help_text="The order in which motions are displayed") - text = models.CharField( + text = models.TextField( max_length=500, - help_text= - "The motion itself, e.g., \"This House would straighten all bananas\"") + help_text="The full motion e.g., \"This House would straighten all bananas\"") reference = models.CharField( max_length=100, help_text="Shortcode for the motion, e.g., \"Bananas\"") flagged = models.BooleanField( default=False, - help_text= - "For WADL: Allows for particular motions to be flagged as contentious") + help_text="For WADL: Allows for particular motions to be flagged as contentious") round = models.ForeignKey('tournaments.Round') - divisions = models.ManyToManyField('tournaments.Division', blank=True) + divisions = models.ManyToManyField('divisions.Division', blank=True) class Meta: ordering = ('seq', ) diff --git a/motions/statistics.py b/tabbycat/motions/statistics.py similarity index 60% rename from motions/statistics.py rename to tabbycat/motions/statistics.py index 3a39981abb8..13c34ec67b6 100644 --- a/motions/statistics.py +++ b/tabbycat/motions/statistics.py @@ -1,19 +1,21 @@ -from .models import Motion, DebateTeamMotionPreference from draw.models import DebateTeam from results.models import TeamScore -#from scipy.stats import chisquare +from .models import DebateTeamMotionPreference, Motion +# From scipy.stats import chisquare + def statistics(round): motions = Motion.objects.select_related('round').filter( - round__seq__lte=round.seq, round__tournament=round.tournament) + round__seq__lte=round.seq, round__tournament=round.tournament) - winners = TeamScore.objects.filter(win=True, - ballot_submission__confirmed=True, - ballot_submission__debate__round__tournament=round.tournament, - ballot_submission__debate__round__seq__lte=round.seq).select_related( - 'debate_team__position', 'ballot_submission__motion') + winners = TeamScore.objects.filter( + win=True, + ballot_submission__confirmed=True, + ballot_submission__debate__round__tournament=round.tournament, + ballot_submission__debate__round__seq__lte=round.seq).select_related( + 'debate_team__position', 'ballot_submission__motion') wins = dict() for pos, _ in DebateTeam.POSITION_CHOICES: @@ -27,21 +29,25 @@ def statistics(round): motion.neg_wins = wins[DebateTeam.POSITION_NEGATIVE][motion] motion.chosen_in = motion.aff_wins + motion.neg_wins - # motion.c1, motion.p_value = chisquare([motion.aff_wins, motion.neg_wins], f_exp=[motion.chosen_in / 2, motion.chosen_in / 2]) - # # Culling out the NaN errors - # try: - # test = int(motion.c1) - # except ValueError: - # motion.c1, motion.p_value = None, None - # TODO: temporarily disabled + ''' + motion.c1, motion.p_value = chisquare([motion.aff_wins, motion.neg_wins], f_exp=[motion.chosen_in / 2, motion.chosen_in / 2]) + # Culling out the NaN errors + try: + test = int(motion.c1) + except ValueError: + motion.c1, motion.p_value = None, None + TODO: temporarily disabled + ''' + motion.c1, motion.p_value = None, None if round.tournament.pref('motion_vetoes_enabled'): - veto_objs = DebateTeamMotionPreference.objects.filter(preference=3, - ballot_submission__confirmed=True, - ballot_submission__debate__round__tournament=round.tournament, - ballot_submission__debate__round__seq__lte=round.seq).select_related( - 'debate_team__position', 'ballot_submission__motion') + veto_objs = DebateTeamMotionPreference.objects.filter( + preference=3, + ballot_submission__confirmed=True, + ballot_submission__debate__round__tournament=round.tournament, + ballot_submission__debate__round__seq__lte=round.seq).select_related( + 'debate_team__position', 'ballot_submission__motion') vetoes = dict() for pos, _ in DebateTeam.POSITION_CHOICES: vetoes[pos] = dict.fromkeys(motions, 0) @@ -52,4 +58,4 @@ def statistics(round): motion.aff_vetoes = vetoes[DebateTeam.POSITION_AFFIRMATIVE][motion] motion.neg_vetoes = vetoes[DebateTeam.POSITION_NEGATIVE][motion] - return motions \ No newline at end of file + return motions diff --git a/motions/templates/assign.html b/tabbycat/motions/templates/assign.html similarity index 96% rename from motions/templates/assign.html rename to tabbycat/motions/templates/assign.html index 0c7872eaca2..3d504f40620 100644 --- a/motions/templates/assign.html +++ b/tabbycat/motions/templates/assign.html @@ -42,7 +42,8 @@

          {{ form.instance.reference }}

          {% endblock content %} -{% block extra-js %} +{% block js %} + {{ block.super }} -{% endblock extra-js %} +{% endblock js %} diff --git a/motions/templates/edit.html b/tabbycat/motions/templates/edit.html similarity index 69% rename from motions/templates/edit.html rename to tabbycat/motions/templates/edit.html index 16321aaefe4..a67d3a68d56 100644 --- a/motions/templates/edit.html +++ b/tabbycat/motions/templates/edit.html @@ -10,14 +10,11 @@
          {% csrf_token %}
          -
          -

          Motion Options

          +

          Motion Options

            - {{ formset.management_form }} - {% for form in formset %}
          • @@ -31,25 +28,36 @@

            Motion Options

            -
            - {{form.text|addcss:"form-control help-anchor required"}} +
            + {{form.text|addcss:"form-control help-anchor required text-area-limited"}} +
            +
            + {{form.text.help_text}}
            -
            +
            {{form.reference|addcss:"form-control required"}}
            +
            + {{form.reference.help_text}} +
            -
            +
            {{form.seq|addcss:"form-control required"}}{{ form.id }}
            +
            + {{form.seq.help_text}} +
            +
            +
            @@ -72,21 +80,27 @@

            Motion Options

          • {% endfor %} - +
          • +
            +
            + +
            +
            + +
            +
            + Cancel +
            +
            +
          - -
          - -
          - - - Cancel
          - + {% endblock content %} -{% block extra-js %} +{% block js %} + {{ block.super }} -{% endblock extra-js %} +{% endblock js %} diff --git a/tabbycat/motions/templates/public_division_motions.html b/tabbycat/motions/templates/public_division_motions.html new file mode 100644 index 00000000000..dc19a0afe47 --- /dev/null +++ b/tabbycat/motions/templates/public_division_motions.html @@ -0,0 +1,69 @@ +{% extends "base.html" %} +{% load debate_tags %} +{% load static %} + +{% block head-title %}Motions{% endblock %} +{% block page-title %}Motions{% endblock %} + +{% block page-alerts %} + {% if rounds.all.count == 0 %} + + {% endif %} +{% endblock %} + +{% block content %} + + {% if rounds.all.count > 0 %} +
          +
          +
      Institution - {% for motion in debate.division_motion %} - {{ motion.reference }} - (view) - {% endfor %} + {{ debate.get_division_motions.reference }} + (view)
      + + + + + + + + + {% if pref.enable_flagged_motions %} + + {% endif %} + + + + {% for round in rounds %} + {% for motion in round.motion_set.all %} + + + + + + + + {% if pref.enable_flagged_motions %} + + {% endif %} + + {% endfor %} + {% endfor %} + +
      RSeqRoundReferenceVenue(s)DivisionsTextContentious
      {{ motion.round.seq }}{{ motion.round.abbreviation }}{{ motion.reference }} + {% regroup motion.divisions.all by venue_group as unique_venues %} + {% for venue_group in unique_venues %} + {{ venue_group.grouper.short_name }}, + {% endfor %} + + {% for division in motion.divisions.all %} + + {{ division.name }}, + + {% endfor %} + {{ motion.text }}{% if motion.flagged %}{% endif %}
      +
      +
      + {% endif %} + +
    +{% endblock content %} diff --git a/tabbycat/motions/templates/public_motions.html b/tabbycat/motions/templates/public_motions.html new file mode 100644 index 00000000000..a6ac577dde3 --- /dev/null +++ b/tabbycat/motions/templates/public_motions.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} +{% load debate_tags %} +{% load static %} + +{% block head-title %}Motions{% endblock %} +{% block page-title %}Motions{% endblock %} + +{% block content %} + + {# The context `rounds` contains all rounds before or at the current round, #} + {# so `rounds` is guaranteed to be non-empty. #} + {% for round in rounds %} +
    +
    +

    {{ round.name }}

    +
    +
      + {% if round.motions_released %} + {% for motion in round.motion_set.all %} +
    • {{ motion.text }}
    • + {% empty %} +
    • There are no motions available for this round.
    • + {% endfor %} + {% else %} +
    • The motions for this round have not been released.
    • + {% endif %} +
    +
    + {% endfor %} + +
    +{% endblock content %} diff --git a/tabbycat/motions/templates/show.html b/tabbycat/motions/templates/show.html new file mode 100644 index 00000000000..68eab048aeb --- /dev/null +++ b/tabbycat/motions/templates/show.html @@ -0,0 +1,40 @@ +{% extends "base.html" %} +{% load add_field_css %} +{% load debate_tags %} + +{% block nav %}
    {% endblock %} +{% block header %}{% endblock %} + +{% block content %} + +
    +
    +
    + +
    +
    +
    + + + +{% endblock content %} diff --git a/tabbycat/motions/urls_admin.py b/tabbycat/motions/urls_admin.py new file mode 100644 index 00000000000..5e645e2d665 --- /dev/null +++ b/tabbycat/motions/urls_admin.py @@ -0,0 +1,21 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^edit/$', + views.EditMotionsView.as_view(), + name='motions-edit'), + url(r'^assign/$', + views.motions_assign, + name='motions_assign'), + url(r'^release/$', + views.ReleaseMotionsView.as_view(), + name='motions-release'), + url(r'^unrelease/$', + views.UnreleaseMotionsView.as_view(), + name='motions-unrelease'), + url(r'^display/$', + views.DisplayMotionsView.as_view(), + name='motions-display'), +] diff --git a/tabbycat/motions/urls_public.py b/tabbycat/motions/urls_public.py new file mode 100644 index 00000000000..f2616c65b96 --- /dev/null +++ b/tabbycat/motions/urls_public.py @@ -0,0 +1,7 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^$', views.PublicMotionsView.as_view(), name='motions-public'), +] diff --git a/tabbycat/motions/views.py b/tabbycat/motions/views.py new file mode 100644 index 00000000000..13e47e37d12 --- /dev/null +++ b/tabbycat/motions/views.py @@ -0,0 +1,136 @@ +from django.shortcuts import render +from django.db.models import Q +from django.forms import ModelForm +from django.forms.models import modelformset_factory +from django.forms.widgets import CheckboxSelectMultiple +from django.forms.models import ModelMultipleChoiceField +from django.views.generic.base import TemplateView + +from actionlog.mixins import LogActionMixin +from actionlog.models import ActionLogEntry +from divisions.models import Division +from tournaments.mixins import PublicTournamentPageMixin, RoundMixin +from utils.misc import redirect_round +from utils.mixins import ModelFormSetView, PostOnlyRedirectView, SuperuserRequiredMixin +from utils.views import admin_required, round_view + +from .models import Motion + + +class PublicMotionsView(PublicTournamentPageMixin, TemplateView): + public_page_preference = 'public_motions' + + def using_division_motions(self): + tournament = self.get_tournament() + return tournament.pref('enable_divisions') and tournament.pref('enable_division_motions') + + def get_template_names(self): + if self.using_division_motions(): + return ['public_division_motions.html'] + else: + return ['public_motions.html'] + + def get_context_data(self, **kwargs): + tournament = self.get_tournament() + order_by = 'seq' if tournament.pref('public_motions_order') == 'forward' else '-seq' + + # Include rounds whether *either* motions are released *or* it's this + # round or a previous round. The template checks motion_released again + # and displays a "not released" message if motions are not released. + filter_q = Q(motions_released=True) + if not self.using_division_motions(): + filter_q |= Q(seq__lte=tournament.current_round.seq) + + kwargs['rounds'] = tournament.round_set.filter(filter_q).order_by( + order_by).prefetch_related('motion_set') + return super().get_context_data(**kwargs) + + +class EditMotionsView(SuperuserRequiredMixin, LogActionMixin, RoundMixin, ModelFormSetView): + # Django doesn't have a class-based view for formsets, so this implements + # the form processing analogously to FormView, with less decomposition. + # See also: participants.views.PublicConfirmShiftView. + + template_name = 'edit.html' + action_log_type = ActionLogEntry.ACTION_TYPE_MOTION_EDIT + formset_factory_kwargs = dict(can_delete=True, extra=3, exclude=['round']) + formset_model = Motion + + def get_formset_queryset(self): + return self.get_round().motion_set.all() + + def formset_valid(self, formset): + motions = formset.save(commit=False) + round = self.get_round() + for motion in motions: + motion.round = round + motion.save() + self.log_action(motion=motion) + for motion in formset.deleted_objects: + motion.delete() + return redirect_round('draw', self.get_round()) + + +@admin_required +@round_view +def motions_assign(request, round): + + class MyModelChoiceField(ModelMultipleChoiceField): + def label_from_instance(self, obj): + return "D%s @ %s" % ( + obj.name, + obj.venue_group.short_name, + ) + + class ModelAssignForm(ModelForm): + divisions = MyModelChoiceField( + widget=CheckboxSelectMultiple, + queryset=Division.objects.filter(tournament=round.tournament).order_by('venue_group')) + + class Meta: + model = Motion + fields = ("divisions",) + + motion_form_set = modelformset_factory(Motion, ModelAssignForm, extra=0, fields=['divisions']) + + if request.method == 'POST': + formset = motion_form_set(request.POST) + formset.save() # Should be checking for validity but on a deadline and was buggy + if 'submit' in request.POST: + return redirect_round('draw', round) + + formset = motion_form_set(queryset=Motion.objects.filter(round=round)) + return render(request, "assign.html", dict(formset=formset)) + + +class BaseReleaseMotionsView(SuperuserRequiredMixin, LogActionMixin, RoundMixin, PostOnlyRedirectView): + + round_redirect_pattern_name = 'draw' + + def post(self, request, *args, **kwargs): + round = self.get_round() + round.motions_released = self.motions_released + round.save() + self.log_action() + return super().post(request, *args, **kwargs) + + +class ReleaseMotionsView(BaseReleaseMotionsView): + + action_log_type = ActionLogEntry.ACTION_TYPE_MOTIONS_RELEASE + motions_released = True + + +class UnreleaseMotionsView(BaseReleaseMotionsView): + + action_log_type = ActionLogEntry.ACTION_TYPE_MOTIONS_UNRELEASE + motions_released = False + + +class DisplayMotionsView(SuperuserRequiredMixin, RoundMixin, TemplateView): + + template_name = 'show.html' + + def get_context_data(self, **kwargs): + kwargs['motions'] = self.get_round().motion_set.all() + return super().get_context_data(**kwargs) diff --git a/options/__init__.py b/tabbycat/options/__init__.py similarity index 100% rename from options/__init__.py rename to tabbycat/options/__init__.py diff --git a/options/admin.py b/tabbycat/options/admin.py similarity index 100% rename from options/admin.py rename to tabbycat/options/admin.py index ac249e9853d..f28f4e39c6e 100644 --- a/options/admin.py +++ b/tabbycat/options/admin.py @@ -1,9 +1,11 @@ from django.contrib import admin from dynamic_preferences.admin import PerInstancePreferenceAdmin +from dynamic_preferences.models import GlobalPreferenceModel, UserPreferenceModel from .models import TournamentPreferenceModel + # ============================================================================== # Preferences # ============================================================================== @@ -13,7 +15,5 @@ class TournamentPreferenceAdmin(PerInstancePreferenceAdmin): admin.site.register(TournamentPreferenceModel, TournamentPreferenceAdmin) - -from dynamic_preferences.models import GlobalPreferenceModel, UserPreferenceModel admin.site.unregister(GlobalPreferenceModel) admin.site.unregister(UserPreferenceModel) diff --git a/options/apps.py b/tabbycat/options/apps.py similarity index 68% rename from options/apps.py rename to tabbycat/options/apps.py index 4ec01d6dbfd..31901466a55 100644 --- a/options/apps.py +++ b/tabbycat/options/apps.py @@ -1,5 +1,6 @@ from django.apps import AppConfig + class OptionsConfig(AppConfig): name = 'options' - verbose_name = "Tournament Options" \ No newline at end of file + verbose_name = "Tournament Options" diff --git a/options/dynamic_preferences_registry.py b/tabbycat/options/dynamic_preferences_registry.py similarity index 90% rename from options/dynamic_preferences_registry.py rename to tabbycat/options/dynamic_preferences_registry.py index 790c545db42..85a6690ba67 100644 --- a/options/dynamic_preferences_registry.py +++ b/tabbycat/options/dynamic_preferences_registry.py @@ -1,12 +1,16 @@ -from dynamic_preferences.types import BooleanPreference, ChoicePreference, StringPreference, IntegerPreference, FloatPreference, Section +from dynamic_preferences.types import BooleanPreference, ChoicePreference, FloatPreference, IntegerPreference, Section, StringPreference + +from standings.teams import TeamStandingsGenerator + from .types import MultiValueChoicePreference from .models import tournament_preferences_registry -from standings.teams import TeamStandingsGenerator + # ============================================================================== scoring = Section('scoring') # ============================================================================== + @tournament_preferences_registry.register class MinimumSpeakerScore(FloatPreference): help_text = "Minimum allowed score for substantive speeches" @@ -15,6 +19,7 @@ class MinimumSpeakerScore(FloatPreference): verbose_name = 'Minimum speaker score' default = 68.0 + @tournament_preferences_registry.register class MaximumSpeakerScore(FloatPreference): verbose_name = 'Maximum speaker score' @@ -23,6 +28,7 @@ class MaximumSpeakerScore(FloatPreference): name = 'score_max' default = 82.0 + @tournament_preferences_registry.register class SpeakerScoreStep(FloatPreference): verbose_name = 'Speaker score step' @@ -31,6 +37,7 @@ class SpeakerScoreStep(FloatPreference): name = 'score_step' default = 1.0 + @tournament_preferences_registry.register class MinimumReplyScore(FloatPreference): help_text = "Minimum allowed score for reply speeches" @@ -48,6 +55,7 @@ class MaximumReplyScore(FloatPreference): name = 'reply_score_max' default = 41.0 + @tournament_preferences_registry.register class ReplyScoreStep(FloatPreference): help_text = "Score steps allowed for reply speeches, e.g. full points (1) or half points (0.5)" @@ -56,6 +64,7 @@ class ReplyScoreStep(FloatPreference): name = 'reply_score_step' default = 0.5 + @tournament_preferences_registry.register class MaximumMargin(FloatPreference): help_text = "The largest amount by which one team can beat another (0 means no limit)" @@ -64,6 +73,7 @@ class MaximumMargin(FloatPreference): name = 'maximum_margin' default = 0.0 + @tournament_preferences_registry.register class MarginIncludesDissent(BooleanPreference): help_text = "If checked, a team's winning margin includes dissenting adjudicators" @@ -76,6 +86,7 @@ class MarginIncludesDissent(BooleanPreference): draw_rules = Section('draw_rules') # ============================================================================== + @tournament_preferences_registry.register class VotingScore(FloatPreference): help_text = "The auto-allocator will only take adjudicators at or above this score as voting panellists" @@ -84,6 +95,7 @@ class VotingScore(FloatPreference): name = 'adj_min_voting_score' default = 1.5 + @tournament_preferences_registry.register class AdjConflictPenalty(IntegerPreference): help_text = "Penalty applied by auto-allocator for adjudicator-team conflict" @@ -92,6 +104,7 @@ class AdjConflictPenalty(IntegerPreference): name = "adj_conflict_penalty" default = 1000000 + @tournament_preferences_registry.register class AdjHistoryPenalty(IntegerPreference): help_text = "Penalty applied by auto-allocator for adjudicator-team history" @@ -100,6 +113,7 @@ class AdjHistoryPenalty(IntegerPreference): name = "adj_history_penalty" default = 10000 + @tournament_preferences_registry.register class AvoidSameInstitution(BooleanPreference): help_text = "If checked, the draw will try to avoid pairing teams against their own institution" @@ -108,6 +122,7 @@ class AvoidSameInstitution(BooleanPreference): name = "avoid_same_institution" default = True + @tournament_preferences_registry.register class AvoidTeamHistory(BooleanPreference): help_text = "If checked, the draw will try to avoid having teams see each other twice" @@ -116,6 +131,7 @@ class AvoidTeamHistory(BooleanPreference): name = "avoid_team_history" default = True + @tournament_preferences_registry.register class TeamInstitutionPenalty(IntegerPreference): help_text = "Penalty applied by conflict avoidance method for teams seeing their own institution" @@ -124,6 +140,7 @@ class TeamInstitutionPenalty(IntegerPreference): name = "team_institution_penalty" default = 1 + @tournament_preferences_registry.register class TeamHistoryPenalty(IntegerPreference): help_text = "Penalty applied by conflict avoidance method for teams seeing each other twice or more" @@ -132,6 +149,7 @@ class TeamHistoryPenalty(IntegerPreference): name = "team_history_penalty" default = 1000 + @tournament_preferences_registry.register class DrawOddBracket(ChoicePreference): help_text = "How odd brackets are resolved (see documentation for further details)" @@ -149,6 +167,7 @@ class DrawOddBracket(ChoicePreference): ) default = 'intermediate_bubble_up_down' + @tournament_preferences_registry.register class DrawSideAllocations(ChoicePreference): help_text = "How affirmative/negative positions are assigned (see documentation for further details)" @@ -163,6 +182,7 @@ class DrawSideAllocations(ChoicePreference): ) default = 'balance' + @tournament_preferences_registry.register class DrawPairingMethod(ChoicePreference): help_text = "Slide: 1 vs 6, 2 vs 7, …. Fold: 1 vs 10, 2 vs 9, …. Adjacent: 1 vs 2, 3 vs 4, …." @@ -178,6 +198,7 @@ class DrawPairingMethod(ChoicePreference): ) default = 'slide' + @tournament_preferences_registry.register class DrawAvoidConflicts(ChoicePreference): help_text = "Method used to try to avoid teams facing each other multiple times or their own institution (see documentation for further details)" @@ -190,6 +211,7 @@ class DrawAvoidConflicts(ChoicePreference): ) default = 'one_up_one_down' + @tournament_preferences_registry.register class SkipAdjCheckins(BooleanPreference): help_text = "Automatically make all adjudicators available for all rounds" @@ -198,6 +220,7 @@ class SkipAdjCheckins(BooleanPreference): name = "draw_skip_adj_checkins" default = False + @tournament_preferences_registry.register class HidePanellistPosition(BooleanPreference): help_text = "Hide panellist positions in the UI (and don't allocate them)" @@ -206,6 +229,7 @@ class HidePanellistPosition(BooleanPreference): name = "no_panellist_position" default = False + @tournament_preferences_registry.register class HideTraineePosition(BooleanPreference): help_text = "Hide trainee positions in the UI (and don't allocate them)" @@ -218,22 +242,39 @@ class HideTraineePosition(BooleanPreference): feedback = Section('feedback') # ============================================================================== + +@tournament_preferences_registry.register +class FeedbackIntroduction(StringPreference): + help_text = "Any explanatory text needed to introduce the feedback form" + verbose_name = "Feedback introduction/explanation" + section = feedback + name = 'feedback_introduction' + default = '' + + def get_field_kwargs(self): + kwargs = super().get_field_kwargs() + kwargs['required'] = False + return kwargs + + @tournament_preferences_registry.register class MinimumAdjScore(FloatPreference): - help_text = "Minimum possible adjudicator score" + help_text = "Minimum possible adjudicator score that can be given" verbose_name = 'Minimum adjudicator score' section = feedback name = 'adj_min_score' default = 0.0 + @tournament_preferences_registry.register class MaximumAdjScore(FloatPreference): - help_text = "Maximum possible adjudicator score" + help_text = "Maximum possible adjudicator score that can be given" verbose_name = 'Maximum adjudicator score' section = feedback name = 'adj_max_score' default = 5.0 + @tournament_preferences_registry.register class ShowUnaccredited(BooleanPreference): help_text = "Show if an adjudicator is a novice (unaccredited)" @@ -242,6 +283,7 @@ class ShowUnaccredited(BooleanPreference): name = 'show_unaccredited' default = False + @tournament_preferences_registry.register class ScoreReturnLocation(StringPreference): help_text = "The location to return scoresheets to, printed on pre-printed ballots" @@ -250,6 +292,7 @@ class ScoreReturnLocation(StringPreference): name = 'score_return_location' default = 'TBA' + @tournament_preferences_registry.register class FeedbackReturnLocation(StringPreference): help_text = "The location to return feedback to, printed on pre-printed feedback forms" @@ -258,20 +301,35 @@ class FeedbackReturnLocation(StringPreference): name = 'feedback_return_location' default = 'TBA' + @tournament_preferences_registry.register -class PanellistFeedbackEnabled(BooleanPreference): - help_text = "Allow feedback to be submitted by panellists" - verbose_name = "Panellist feedback enabled" +class FeedbackPaths(ChoicePreference): + help_text = "Used to inform available choices in the feedback forms (both online and printed) and feedback progress" + verbose_name = "Allow and expect feedback to be submitted by" section = feedback - name = 'panellist_feedback_enabled' - default = True + name = 'feedback_paths' + choices = ( + ('minimal', 'Chairs on panellists and trainees, teams on orallists'), + ('with-p-on-c', 'Panellists on chairs, chairs on panellists and trainees, teams on orallists'), + ('all-adjs', 'All adjudicators (including trainees) on each other, teams on orallists'), + ) + default = 'minimal' +@tournament_preferences_registry.register +class ShowUnexpectedFeedback(BooleanPreference): + verbose_name = "Show unexpected feedback submissions in participants pages" + help_text = "Displays unexpected feedback with a question mark symbol; only relevant if public participants and feedback progress are both enabled" + section = feedback + name = 'show_unexpected_feedback' + default = True + # ============================================================================== debate_rules = Section('debate_rules') # ============================================================================== + @tournament_preferences_registry.register class SubstantiveSpeakers(IntegerPreference): help_text = "How many substantive speakers on a team" @@ -303,6 +361,7 @@ class MotionVetoes(BooleanPreference): standings = Section('standings') # ============================================================================== + @tournament_preferences_registry.register class StandingsMissedDebates(IntegerPreference): help_text = "The number of debates a speaker can miss and still be on the speaker tab" @@ -311,6 +370,7 @@ class StandingsMissedDebates(IntegerPreference): name = "standings_missed_debates" default = 1 + @tournament_preferences_registry.register class RankSpeakersBy(ChoicePreference): help_text = "How speakers are ranked on the speaker tab" @@ -323,6 +383,7 @@ class RankSpeakersBy(ChoicePreference): ) default = 'total' + @tournament_preferences_registry.register class TeamStandingsPrecedence(MultiValueChoicePreference): help_text = "Metrics to use to rank teams (see documentation for further details)" @@ -334,6 +395,7 @@ class TeamStandingsPrecedence(MultiValueChoicePreference): allow_empty = True default = ['points', 'speaks_avg'] + @tournament_preferences_registry.register class TeamStandingsExtraMetrics(MultiValueChoicePreference): help_text = "Metrics not used to rank teams" @@ -349,6 +411,7 @@ class TeamStandingsExtraMetrics(MultiValueChoicePreference): tab_release = Section('tab_release') # ============================================================================== + @tournament_preferences_registry.register class TeamTabReleased(BooleanPreference): help_text = "Enables public display of the team tab. Intended for use after the tournament." @@ -357,6 +420,7 @@ class TeamTabReleased(BooleanPreference): name = "team_tab_released" default = False + @tournament_preferences_registry.register class SpeakerTabReleased(BooleanPreference): help_text = "Enables public display of the speaker tab. Intended for use after the tournament." @@ -365,6 +429,7 @@ class SpeakerTabReleased(BooleanPreference): name = "speaker_tab_released" default = False + @tournament_preferences_registry.register class ProsTabReleased(BooleanPreference): help_text = "Enables public display of a pro-speakers only tab. Intended for use after the tournament." @@ -373,6 +438,7 @@ class ProsTabReleased(BooleanPreference): name = "pros_tab_released" default = False + @tournament_preferences_registry.register class NovicesTabReleased(BooleanPreference): help_text = "Enables public display of a novice-speakers only tab. Intended for use after the tournament." @@ -381,6 +447,7 @@ class NovicesTabReleased(BooleanPreference): name = "novices_tab_released" default = False + @tournament_preferences_registry.register class RepliesTabReleased(BooleanPreference): help_text = "Enables public display of the replies tab. Intended for use after the tournament." @@ -389,6 +456,7 @@ class RepliesTabReleased(BooleanPreference): name = "replies_tab_released" default = False + @tournament_preferences_registry.register class MotionTabReleased(BooleanPreference): help_text = "Enables public display of the motions tab. Intended for use after the tournament." @@ -397,6 +465,7 @@ class MotionTabReleased(BooleanPreference): name = "motion_tab_released" default = False + @tournament_preferences_registry.register class BallotsReleased(BooleanPreference): help_text = "Enables public display of every adjudicator's ballot. Intended for use after the tournament." @@ -406,10 +475,20 @@ class BallotsReleased(BooleanPreference): default = False +@tournament_preferences_registry.register +class AllResultsReleased(BooleanPreference): + help_text = "This releases all the results for all rounds (including silent and break rounds). Do so only after the tournament is finished!" + verbose_name = "Release all round results to public" + section = tab_release + name = "all_results_released" + default = False + + # ============================================================================== data_entry = Section('data_entry') # ============================================================================== + @tournament_preferences_registry.register class PublicBallots(BooleanPreference): help_text = "Enables public interface to add ballots using normal URLs" @@ -418,6 +497,7 @@ class PublicBallots(BooleanPreference): name = "public_ballots" default = False + @tournament_preferences_registry.register class PublicBallotsRandomised(BooleanPreference): help_text = "Enables public interface to add ballots using randomised URLs" @@ -426,6 +506,7 @@ class PublicBallotsRandomised(BooleanPreference): name = "public_ballots_randomised" default = False + @tournament_preferences_registry.register class PublicFeedback(BooleanPreference): help_text = "Enables public interface to add feedback using normal URLs" @@ -434,6 +515,7 @@ class PublicFeedback(BooleanPreference): name = "public_feedback" default = False + @tournament_preferences_registry.register class PublicFeedbackRandomised(BooleanPreference): help_text = "Enables public interface to add feedback using randomised URLs" @@ -442,6 +524,7 @@ class PublicFeedbackRandomised(BooleanPreference): name = "public_feedback_randomised" default = False + @tournament_preferences_registry.register class PublicUsePassword(BooleanPreference): help_text = "If checked, users must enter a password when submitting public feedback and ballots" @@ -450,6 +533,7 @@ class PublicUsePassword(BooleanPreference): name = "public_use_password" default = False + @tournament_preferences_registry.register class PublicPassword(StringPreference): help_text = "Value of the password required for public submissions, if passwords are required" @@ -458,6 +542,7 @@ class PublicPassword(StringPreference): name = "public_password" default = 'Enter Password' + @tournament_preferences_registry.register class DisableBallotConfirmation(BooleanPreference): help_text = "Bypasses double checking by setting ballots to be automatically confirmed" @@ -466,6 +551,7 @@ class DisableBallotConfirmation(BooleanPreference): name = "disable_ballot_confirms" default = False + @tournament_preferences_registry.register class EnableMotions(BooleanPreference): help_text = "If checked, ballots require a motion to be entered" @@ -478,6 +564,7 @@ class EnableMotions(BooleanPreference): public_features = Section('public_features') # ============================================================================== + @tournament_preferences_registry.register class PublicParticipants(BooleanPreference): help_text = "Enables the public page listing all participants in the tournament" @@ -486,6 +573,16 @@ class PublicParticipants(BooleanPreference): name = "public_participants" default = False + +@tournament_preferences_registry.register +class PublicDiversity(BooleanPreference): + help_text = "Enables the public page listing diversity statistics" + verbose_name = "Enable public view of diversity info" + section = public_features + name = "public_diversity" + default = False + + @tournament_preferences_registry.register class PublicBreakCategories(BooleanPreference): help_text = "If the participants list is enabled, displays break category eligibility on that page" @@ -494,6 +591,7 @@ class PublicBreakCategories(BooleanPreference): name = "public_break_categories" default = False + @tournament_preferences_registry.register class PublicSideAllocations(BooleanPreference): help_text = "Enables the public page listing pre-allocated sides" @@ -502,6 +600,7 @@ class PublicSideAllocations(BooleanPreference): name = "public_side_allocations" default = False + @tournament_preferences_registry.register class PublicDraw(BooleanPreference): help_text = "Enables the public page showing released draws" @@ -510,6 +609,7 @@ class PublicDraw(BooleanPreference): name = "public_draw" default = False + @tournament_preferences_registry.register class PublicResults(BooleanPreference): help_text = "Enables the public page showing results of non-silent rounds" @@ -518,6 +618,7 @@ class PublicResults(BooleanPreference): name = "public_results" default = False + @tournament_preferences_registry.register class PublicMotions(BooleanPreference): help_text = "Enables the public page showing released motions" @@ -526,6 +627,7 @@ class PublicMotions(BooleanPreference): name = "public_motions" default = False + @tournament_preferences_registry.register class PublicTeamStandings(BooleanPreference): help_text = "Enables the public page showing team standings, showing wins only (not speaker scores or ranking)" @@ -534,6 +636,16 @@ class PublicTeamStandings(BooleanPreference): name = "public_team_standings" default = False + +@tournament_preferences_registry.register +class PublicRecordPages(BooleanPreference): + help_text = "Enables the public page for each team and adjudicator showing their records" + verbose_name = "Enable public record pages" + section = public_features + name = "public_record" + default = True + + @tournament_preferences_registry.register class PublicBreakingTeams(BooleanPreference): help_text = "Enables the public page showing the team breaks. Intended for use after the break announcement." @@ -542,6 +654,7 @@ class PublicBreakingTeams(BooleanPreference): name = "public_breaking_teams" default = False + @tournament_preferences_registry.register class PublicBreakingAdjs(BooleanPreference): help_text = "Enables the public page showing breaking adjudicators. Intended for use after the break announcement." @@ -550,6 +663,7 @@ class PublicBreakingAdjs(BooleanPreference): name = "public_breaking_adjs" default = False + @tournament_preferences_registry.register class FeedbackProgress(BooleanPreference): help_text = "Enables the public page detailing who has unsubmitted feedback" @@ -562,6 +676,7 @@ class FeedbackProgress(BooleanPreference): ui_options = Section('ui_options') # ============================================================================== + @tournament_preferences_registry.register class ShowSplittingAdjudicators(BooleanPreference): help_text = "If showing results to public, show splitting adjudicators in them" @@ -570,14 +685,16 @@ class ShowSplittingAdjudicators(BooleanPreference): section = ui_options default = False + @tournament_preferences_registry.register class ShowMotionsInResults(BooleanPreference): - help_text = "If showing results to public, show which motions were selected in the summary" + help_text = "If showing results to public, show which motions were selected in the record" verbose_name = 'Show motions in results' section = ui_options name = 'show_motions_in_results' default = False + @tournament_preferences_registry.register class ShowEmoji(BooleanPreference): help_text = "Enables emoji in the draw" @@ -586,6 +703,7 @@ class ShowEmoji(BooleanPreference): name = 'show_emoji' default = True + @tournament_preferences_registry.register class ShowInstitutions(BooleanPreference): help_text = "Shows the institutions column where appropriate" @@ -594,6 +712,7 @@ class ShowInstitutions(BooleanPreference): name = 'show_institutions' default = True + @tournament_preferences_registry.register class ShowNovices(BooleanPreference): help_text = "Indicates next to a speaker's name if they are a novice" @@ -602,6 +721,7 @@ class ShowNovices(BooleanPreference): name = 'show_novices' default = False + @tournament_preferences_registry.register class ShowSpeakersInDraw(BooleanPreference): help_text = "Enables a hover element on every team's name showing that team's speakers" @@ -610,6 +730,7 @@ class ShowSpeakersInDraw(BooleanPreference): name = 'show_speakers_in_draw' default = True + @tournament_preferences_registry.register class ShowAllDraws(BooleanPreference): help_text = "If showing draws to public, show all (past and future) released draws" @@ -618,8 +739,9 @@ class ShowAllDraws(BooleanPreference): name = 'show_all_draws' default = False + @tournament_preferences_registry.register -class PublicMotionsDescending(ChoicePreference): +class PublicMotionsOrder(ChoicePreference): help_text = "Order in which are listed by round in the public view" verbose_name = "Order to display motions" section = ui_options @@ -634,6 +756,7 @@ class PublicMotionsDescending(ChoicePreference): league_options = Section('league_options') # ============================================================================== + @tournament_preferences_registry.register class PublicDivisions(BooleanPreference): help_text = "Enables public interface to see divisions" @@ -642,6 +765,7 @@ class PublicDivisions(BooleanPreference): name = "public_divisions" default = False + @tournament_preferences_registry.register class EnableDivisions(BooleanPreference): help_text = "Enables the sorting and display of teams into divisions" @@ -650,6 +774,7 @@ class EnableDivisions(BooleanPreference): name = "enable_divisions" default = False + @tournament_preferences_registry.register class EnablePostponements(BooleanPreference): help_text = "Enables debates to have their status set to postponed" @@ -658,38 +783,43 @@ class EnablePostponements(BooleanPreference): name = "enable_postponements" default = False + @tournament_preferences_registry.register -class enable_forfeits(BooleanPreference): +class EnableForfeits(BooleanPreference): help_text = "Allows debates to be marked as wins by forfeit" verbose_name = "Enable forfeits" section = league_options name = "enable_forfeits" default = False + @tournament_preferences_registry.register -class enable_division_motions(BooleanPreference): +class EnableDivisionMotions(BooleanPreference): help_text = "Enables assigning motions to a division" verbose_name = "Enable division motions" section = league_options name = "enable_division_motions" default = False + @tournament_preferences_registry.register -class minimum_division_size(IntegerPreference): +class MinimumDivisionSize(IntegerPreference): help_text = "Smallest allowed size for a division" verbose_name = "Minimum division size" section = league_options name = "minimum_division_size" default = 5 + @tournament_preferences_registry.register -class ideal_division_size(IntegerPreference): +class IdealDivisionSize(IntegerPreference): help_text = "Ideal size for a division" verbose_name = "Ideal division size" section = league_options name = "ideal_division_size" default = 6 + @tournament_preferences_registry.register class MaximumDivisionSize(IntegerPreference): help_text = "Largest allowed size for a division" @@ -698,6 +828,7 @@ class MaximumDivisionSize(IntegerPreference): name = "maximum_division_size" default = 8 + @tournament_preferences_registry.register class EnableFlaggedMotions(BooleanPreference): help_text = "Allow particular motions to be flagged as contentious" @@ -715,6 +846,7 @@ class EnableAdjNotes(BooleanPreference): name = "enable_adj_notes" default = False + @tournament_preferences_registry.register class EnableVenueGroups(BooleanPreference): help_text = "Enables the display of venue groups" @@ -723,6 +855,7 @@ class EnableVenueGroups(BooleanPreference): name = "enable_venue_groups" default = False + @tournament_preferences_registry.register class EnableVenueTimes(BooleanPreference): help_text = "Enables specific dates and times to be set for debates" @@ -731,6 +864,7 @@ class EnableVenueTimes(BooleanPreference): name = "enable_debate_scheduling" default = False + @tournament_preferences_registry.register class EnableVenueOverlaps(BooleanPreference): help_text = "Allow and automatically debates to be placed in the first room" @@ -739,6 +873,7 @@ class EnableVenueOverlaps(BooleanPreference): name = "enable_venue_overlaps" default = False + @tournament_preferences_registry.register class ShareAdjs(BooleanPreference): help_text = 'Use shared adjudicators (those without a set tournament) in this tournament' @@ -747,6 +882,7 @@ class ShareAdjs(BooleanPreference): name = "share_adjs" default = False + @tournament_preferences_registry.register class ShareVenues(BooleanPreference): help_text = 'Use shared venues (those without a set tournament) in this tournament' @@ -755,6 +891,7 @@ class ShareVenues(BooleanPreference): name = "share_venues" default = False + @tournament_preferences_registry.register class DuplicateAdjs(BooleanPreference): help_text = "If unchecked, adjudicators can only be given one room per round" @@ -763,9 +900,10 @@ class DuplicateAdjs(BooleanPreference): name = "duplicate_adjs" default = False + @tournament_preferences_registry.register class AdjAllocationConfirmations(BooleanPreference): - help_text ='Allow links to be sent to adjudicators that allow them to confirm shifts' + help_text = 'Allow links to be sent to adjudicators that allow them to confirm shifts' verbose_name = "Adjudicator allocation confirmations" section = league_options name = "allocation_confirmations" diff --git a/options/fields.py b/tabbycat/options/fields.py similarity index 95% rename from options/fields.py rename to tabbycat/options/fields.py index e5e5e051aff..33e72f6111c 100644 --- a/options/fields.py +++ b/tabbycat/options/fields.py @@ -1,4 +1,4 @@ -from django.forms import MultiValueField, MultiWidget, ChoiceField, Select +from django.forms import ChoiceField, MultiValueField, MultiWidget, Select EMPTY_CHOICE = '__no_choice__' diff --git a/options/forms.py b/tabbycat/options/forms.py similarity index 72% rename from options/forms.py rename to tabbycat/options/forms.py index d807301fd50..eb4d4447b79 100644 --- a/options/forms.py +++ b/tabbycat/options/forms.py @@ -2,11 +2,11 @@ from .dynamic_preferences_registry import tournament_preferences_registry + class TournamentPreferenceForm(PreferenceForm): registry = tournament_preferences_registry def tournament_preference_form_builder(instance, preferences=[], **kwargs): - return preference_form_builder(TournamentPreferenceForm, preferences, model={'instance': instance}, **kwargs) - - + return preference_form_builder( + TournamentPreferenceForm, preferences, model={'instance': instance}, **kwargs) diff --git a/options/migrations/0001_initial.py b/tabbycat/options/migrations/0001_initial.py similarity index 100% rename from options/migrations/0001_initial.py rename to tabbycat/options/migrations/0001_initial.py diff --git a/options/migrations/0002_option_tournament.py b/tabbycat/options/migrations/0002_option_tournament.py similarity index 100% rename from options/migrations/0002_option_tournament.py rename to tabbycat/options/migrations/0002_option_tournament.py diff --git a/options/migrations/0003_auto_20160111_1950.py b/tabbycat/options/migrations/0003_auto_20160111_1950.py similarity index 100% rename from options/migrations/0003_auto_20160111_1950.py rename to tabbycat/options/migrations/0003_auto_20160111_1950.py diff --git a/options/migrations/0004_auto_20160120_1359.py b/tabbycat/options/migrations/0004_auto_20160120_1359.py similarity index 100% rename from options/migrations/0004_auto_20160120_1359.py rename to tabbycat/options/migrations/0004_auto_20160120_1359.py diff --git a/options/migrations/0005_auto_20160228_1838.py b/tabbycat/options/migrations/0005_auto_20160228_1838.py similarity index 100% rename from options/migrations/0005_auto_20160228_1838.py rename to tabbycat/options/migrations/0005_auto_20160228_1838.py diff --git a/tabbycat/options/migrations/0006_convert_panellist_feedback_preference.py b/tabbycat/options/migrations/0006_convert_panellist_feedback_preference.py new file mode 100644 index 00000000000..73fbcaaf703 --- /dev/null +++ b/tabbycat/options/migrations/0006_convert_panellist_feedback_preference.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +# This is a data migration. It was written manually and its purpose is to +# convert the old "panellist_feedback_enabled" preference to the new +# "feedback_paths" preference. For it to work, you must *not* have run +# `python manage.py checkpreferences` (or `dj checkpreferences`) after commit +# 32e52f9 ("Remove deprecated panellist_feedback_enabled option #350"), which +# removes the old preference. Note that on a Heroku instance, this means that +# commits 32e52f9 through 385d428 ("Implement and close #351") must never have +# been deployed, since the post-compile script runs checkpreferences. +# +# If the old preference doesn't exist, this data migration silently fails. + +from __future__ import unicode_literals + +from django.db import migrations + +TRUE_CONSTANTS = ("True", "true", "TRUE", "1", "YES", "Yes", "yes") + + +def convert_panellist_feedback_preference(apps, schema_editor): + TournamentPreferenceModel = apps.get_model("options", "TournamentPreferenceModel") + + old_prefs = TournamentPreferenceModel.objects.filter(section="feedback", + name="panellist_feedback_enabled") + + for pref in old_prefs: + + # Ordinarily, we're not really meant to access the `raw_value` field + # directly. But with data migrations the model we're dealing with (the + # historical version) doesn't actually have any of the non-field + # properties (i.e., `pref.value` would raise an AttributeError), so we + # don't really have a choice here. + new_value = "with-p-on-c" if pref.raw_value in TRUE_CONSTANTS else "minimal" + + # If there already exists a preference, leave it alone. + if not TournamentPreferenceModel.objects.filter(section="feedback", + name="feedback_paths", instance_id=pref.instance_id).exists(): + TournamentPreferenceModel.objects.create(section="feedback", + name="feedback_paths", instance_id=pref.instance_id, raw_value=new_value) + + # The checkpreferences command would do this, but since this preference + # doesn't exist anymore, we may as well delete it now. + pref.delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('options', '0005_auto_20160228_1838'), + ] + + operations = [ + migrations.RunPython(convert_panellist_feedback_preference), + ] diff --git a/results/migrations/__init__.py b/tabbycat/options/migrations/__init__.py similarity index 100% rename from results/migrations/__init__.py rename to tabbycat/options/migrations/__init__.py diff --git a/options/models.py b/tabbycat/options/models.py similarity index 100% rename from options/models.py rename to tabbycat/options/models.py diff --git a/options/presets.py b/tabbycat/options/presets.py similarity index 90% rename from options/presets.py rename to tabbycat/options/presets.py index a2fa5f1aef0..0f927f290be 100644 --- a/options/presets.py +++ b/tabbycat/options/presets.py @@ -16,7 +16,7 @@ def __init__(self): self.scoring__reply_score_min = 34.0 self.scoring__reply_score_max = 41.0 self.scoring__reply_score_step = 0.5 - self.scoring__maximum_margin = 15.0 # TODO= check this + self.scoring__maximum_margin = 15.0 # TODO= check this # Draws self.draw_rules__avoid_same_institution = True self.draw_rules__avoid_team_history = True @@ -30,7 +30,7 @@ def __init__(self): self.debate_rules__motion_vetoes_enabled = True self.data_entry__enable_motions = True # Standings Rules - self.standings__standings_missed_debates = 2 # TODO= check this + self.standings__standings_missed_debates = 2 # TODO= check this self.standings__team_standings_precedence = ['wins', 'speaks_sum'] self.standings__rank_speakers_by = 'total' @@ -50,6 +50,7 @@ def __init__(self): # UI Options self.ui_options__show_novices = True + class NZEastersPreferences(AustralsPreferences): """ 2 vs 2 with replies, chosen motions, chosen sides, and novice statuses.""" def __init__(self): @@ -72,8 +73,8 @@ def __init__(self): self.draw_rules__draw_odd_bracket = 'intermediate' self.draw_rules__draw_pairing_method = 'fold' self.draw_rules__draw_avoid_conflicts = 'off' - self.draw_rules__avoid_same_institution = False # TODO: CHECK - self.draw_rules__avoid_team_history = False # TODO: CHECK + self.draw_rules__avoid_same_institution = False # TODO: CHECK + self.draw_rules__avoid_team_history = False # TODO: CHECK # UI Options self.ui_options__show_novices = True @@ -115,21 +116,21 @@ def __init__(self): self.show_in_list = True # Rules source = http://www.alcheringa.in/pdrules.pdf # Scoring - self.scoring__score_min = 69.0 # From Rules Book - self.scoring__score_max = 81.0 # From Rules Book + self.scoring__score_min = 69.0 # From Rules Book + self.scoring__score_max = 81.0 # From Rules Book self.scoring__score_step = 1.0 - self.scoring__reply_score_min = 34.5 # Not specified; assuming half of substantive - self.scoring__reply_score_max = 42.0 # Not specified; assuming half of substantive + self.scoring__reply_score_min = 34.5 # Not specified; assuming half of substantive + self.scoring__reply_score_max = 42.0 # Not specified; assuming half of substantive self.scoring__reply_score_step = 0.5 - self.scoring__maximum_margin = 0.0 # TODO= check this - self.scoring__margin_includes_dissenters = True # From Rules:10.9.5 + self.scoring__maximum_margin = 0.0 # TODO= check this + self.scoring__margin_includes_dissenters = True # From Rules:10.9.5 # # Draws self.draw_rules__avoid_same_institution = False self.draw_rules__avoid_team_history = True - self.draw_rules__draw_odd_bracket = 'pullup_top' # From Rules 10.3.1 - self.draw_rules__draw_side_allocations = 'balance' # From Rules 10.6 - self.draw_rules__draw_pairing_method = 'slide' # From rules 10.5 - self.draw_rules__draw_avoid_conflicts = 'one_up_one_down' # From rules 10.6.4 + self.draw_rules__draw_odd_bracket = 'pullup_top' # From Rules 10.3.1 + self.draw_rules__draw_side_allocations = 'balance' # From Rules 10.6 + self.draw_rules__draw_pairing_method = 'slide' # From rules 10.5 + self.draw_rules__draw_avoid_conflicts = 'one_up_one_down' # From rules 10.6.4 # # Debate Rules self.debate_rules__substantive_speakers = 3 self.debate_rules__reply_scores_enabled = True @@ -138,10 +139,10 @@ def __init__(self): # self.standings__team_standings_precedence = 'australs' # TODO: need a new standings rule self.standings__team_standings_precedence = ['wins', 'speaks_sum'] # Feedback - self.feedback__adj_min_score = 1.0 # Explicit in the rules - self.feedback__adj_max_score = 5.0 # Explicit in the rules + self.feedback__adj_min_score = 1.0 # Explicit in the rules + self.feedback__adj_max_score = 5.0 # Explicit in the rules # UI Options - self.public_features__feedback_progress = True # Feedback is compulsory + self.public_features__feedback_progress = True # Feedback is compulsory class WADLPreferences(PreferencesPreset): @@ -190,6 +191,7 @@ def __init__(self): self.league_options__enable_forfeits = True self.league_options__enable_division_motions = True self.league_options__allocation_confirmations = True + self.league_options__enable_mass_draws = True class PublicInformation(PreferencesPreset): diff --git a/options/serializers.py b/tabbycat/options/serializers.py similarity index 99% rename from options/serializers.py rename to tabbycat/options/serializers.py index 992ba586cf6..3e24fc90568 100644 --- a/options/serializers.py +++ b/tabbycat/options/serializers.py @@ -1,5 +1,6 @@ from dynamic_preferences.serializers import BaseSerializer + class MultiValueSerializer(BaseSerializer): separator = "//" diff --git a/options/templates/preferences_index.html b/tabbycat/options/templates/preferences_index.html similarity index 100% rename from options/templates/preferences_index.html rename to tabbycat/options/templates/preferences_index.html diff --git a/options/templates/preferences_presets_apply.html b/tabbycat/options/templates/preferences_presets_apply.html similarity index 100% rename from options/templates/preferences_presets_apply.html rename to tabbycat/options/templates/preferences_presets_apply.html diff --git a/options/templates/preferences_presets_confirm.html b/tabbycat/options/templates/preferences_presets_confirm.html similarity index 100% rename from options/templates/preferences_presets_confirm.html rename to tabbycat/options/templates/preferences_presets_confirm.html diff --git a/options/templates/preferences_section_set.html b/tabbycat/options/templates/preferences_section_set.html similarity index 87% rename from options/templates/preferences_section_set.html rename to tabbycat/options/templates/preferences_section_set.html index 77df9e3cc9f..38dad9ba596 100644 --- a/options/templates/preferences_section_set.html +++ b/tabbycat/options/templates/preferences_section_set.html @@ -7,9 +7,10 @@ {% block page-subnav-sections %} {% if form.errors %} -
    +
    - Please correct the errors below {{ form.errors }} + Please correct the errors below. + {{ form.non_field_errors }}
    {% endif %} {% endblock %} @@ -33,7 +34,7 @@ {{ field.help_text }} {% if field.errors %} - {{ field.errors }} +
    {{ field.errors }}
    {% endif %}
    diff --git a/options/types.py b/tabbycat/options/types.py similarity index 95% rename from options/types.py rename to tabbycat/options/types.py index f4ffb4ec736..b7b417c6185 100644 --- a/options/types.py +++ b/tabbycat/options/types.py @@ -1,7 +1,9 @@ from dynamic_preferences.types import BasePreferenceType + from .fields import MultiValueChoiceField from .serializers import MultiValueSerializer + class MultiValueChoicePreference(BasePreferenceType): choices = () @@ -15,4 +17,4 @@ def get_field_kwargs(self): field_kwargs['nfields'] = self.nfields field_kwargs['choices'] = self.choices or self.field_attribute['initial'] field_kwargs['allow_empty'] = self.allow_empty - return field_kwargs \ No newline at end of file + return field_kwargs diff --git a/options/urls.py b/tabbycat/options/urls.py similarity index 96% rename from options/urls.py rename to tabbycat/options/urls.py index 7015ce28a3e..fe6b4f40189 100644 --- a/options/urls.py +++ b/tabbycat/options/urls.py @@ -1,6 +1,4 @@ from django.conf.urls import url -from django.core.urlresolvers import reverse -from utils.views import * from . import views diff --git a/options/views.py b/tabbycat/options/views.py similarity index 97% rename from options/views.py rename to tabbycat/options/views.py index 36de790ec7c..0db9a749311 100644 --- a/options/views.py +++ b/tabbycat/options/views.py @@ -1,23 +1,24 @@ import inspect -from django import forms -from django.core.urlresolvers import reverse +from django.contrib import messages from django.http import Http404 from django.utils.text import slugify from django.views.generic import TemplateView +from django.shortcuts import render from dynamic_preferences.views import PreferenceFormView from actionlog.mixins import LogActionMixin from actionlog.models import ActionLogEntry from tournaments.mixins import TournamentMixin from utils.mixins import SuperuserRequiredMixin -from utils.views import * +from utils.views import admin_required, tournament_view from utils.misc import reverse_tournament from . import presets from .forms import tournament_preference_form_builder from .dynamic_preferences_registry import tournament_preferences_registry + @admin_required @tournament_view def tournament_config_index(request, t): @@ -120,7 +121,6 @@ def tournament_preference_apply(request, t, preset_name): context['preset_title'] = selected_preset[0][1]().name context['preferences'] = preset_preferences - return render(request, 'preferences_presets_apply.html', context) @@ -128,4 +128,3 @@ class TournamentPreferenceApplyView(TemplateView): preset = None template_name = "preferences_presets_apply.html" - diff --git a/results/templates/__init__.py b/tabbycat/participants/__init__.py similarity index 100% rename from results/templates/__init__.py rename to tabbycat/participants/__init__.py diff --git a/participants/admin.py b/tabbycat/participants/admin.py similarity index 89% rename from participants/admin.py rename to tabbycat/participants/admin.py index 3f3c9b2caac..10250c5a53b 100644 --- a/participants/admin.py +++ b/tabbycat/participants/admin.py @@ -1,12 +1,14 @@ from django.contrib import admin from django import forms -from .models import Region, Institution, Speaker, Adjudicator, Team from draw.models import TeamPositionAllocation -from adjallocation.models import AdjudicatorConflict, AdjudicatorAdjudicatorConflict, AdjudicatorInstitutionConflict +from adjallocation.models import AdjudicatorAdjudicatorConflict, AdjudicatorConflict, AdjudicatorInstitutionConflict from adjfeedback.models import AdjudicatorTestScoreHistory from venues.models import TeamVenueConstraint +from .models import Adjudicator, Institution, Region, Speaker, Team + + # ============================================================================== # Region # ============================================================================== @@ -17,6 +19,7 @@ class RegionAdmin(admin.ModelAdmin): admin.site.register(Region, RegionAdmin) + # ============================================================================== # Institution # ============================================================================== @@ -29,12 +32,13 @@ class InstitutionAdmin(admin.ModelAdmin): admin.site.register(Institution, InstitutionAdmin) + # ============================================================================== # Speaker # ============================================================================== class SpeakerAdmin(admin.ModelAdmin): - list_display = ('name', 'team', 'novice') + list_display = ('name', 'team', 'novice', 'gender') search_fields = ('name', ) raw_id_fields = ('team', ) @@ -67,14 +71,14 @@ class Meta: def clean_url_key(self): return self.cleaned_data[ - 'url_key'] or None # So that the url key can be unique and also set to blank + 'url_key'] or None # So that the url key can be unique and be blank class TeamAdmin(admin.ModelAdmin): form = TeamForm - list_display = ('long_name', 'short_reference', 'emoji', 'institution', + list_display = ('long_name', 'short_name', 'emoji', 'institution', 'division', 'tournament') - search_fields = ('reference', 'short_reference', 'institution__name', + search_fields = ('reference', 'short_name', 'institution__name', 'institution__code', 'tournament__name') list_filter = ('tournament', 'division', 'institution', 'break_categories') inlines = (SpeakerInline, TeamPositionAllocationInline, @@ -88,6 +92,7 @@ def get_queryset(self, request): admin.site.register(Team, TeamAdmin) + # ============================================================================== # Adjudicator # ============================================================================== @@ -122,13 +127,13 @@ class Meta: def clean_url_key(self): return self.cleaned_data[ - 'url_key'] or None # So that the url key can be unique and also set to blank + 'url_key'] or None # So that the url key can be unique and be blank class AdjudicatorAdmin(admin.ModelAdmin): form = AdjudicatorForm list_display = ('name', 'institution', 'tournament', 'novice', - 'independent') + 'independent', 'adj_core', 'gender') search_fields = ('name', 'tournament__name', 'institution__name', diff --git a/tabbycat/participants/emoji.py b/tabbycat/participants/emoji.py new file mode 100644 index 00000000000..b44121525f1 --- /dev/null +++ b/tabbycat/participants/emoji.py @@ -0,0 +1,1299 @@ +# -*- coding: utf-8 -*- + +# With thanks to emojipedia.org + +EMOJI_LIST = ( + # Unicode Version 1.1 (these all render using primitive icons) + # DOESNT SHOW ("☺️", "☺️"), # White Smiling Face + # DOESNT SHOW ("☹", ""), # White Frowning Face + # DOESNT SHOW ("☝️", "☝️"), # White Up Pointing Index + # DOESNT SHOW ("✌️", "✌️"), # Victory Hand + # DOESNT SHOW ("✍", ""), # Writing Hand + # DOESNT SHOW ("❤️", "❤️"), # Heavy Black Heart + # DOESNT SHOW ("❣", ""), # Heavy Heart Exclamation Mark Ornament + # DOESNT SHOW ("☠", ""), # Skull and Crossbones + # DOESNT SHOW ("♨️", "♨️"), # Hot Springs + # DOESNT SHOW ("✈️", "✈️"), # Airplane + # DOESNT SHOW ("⌛", "⌛"), # Hourglass + # DOESNT SHOW ("⌚", "⌚"), # Watch + # LAME ("♈", ""), # Aries + # LAME ("♉", ""), # Taurus + # LAME ("♊", ""), # Gemini + # LAME ("♋", ""), # Cancer + # LAME ("♌", ""), # Leo + # LAME ("♍", ""), # Virgo + # LAME ("♎", ""), # Libra + # LAME ("♏", ""), # Scorpius + # LAME ("♐", ""), # Sagittarius + # LAME ("♑", ""), # Capricorn + # LAME ("♒", ""), # Aquarius + # LAME ("♓", ""), # Pisces + # DOESNT SHOW ("☀️", "☀️"), # Black Sun With Rays + # DOESNT SHOW ("☁️", "☁️"), # Cloud + # DOESNT SHOW ("☂", ""), # Umbrella + # DOESNT SHOW ("❄️", "❄️"), # Snowflake + # DOESNT SHOW ("☃", "☃"), # Snowman + # Doesn't show (" Comet", ""), # + # DOESNT SHOW ("♠️", "♠️"), # Black Spade Suit + # DOESNT SHOW ("♥️", "♥️"), # Black Heart Suit + # DOESNT SHOW ("♦️", "♦️"), # Black Diamond Suit + # DOESNT SHOW ("♣️", "♣️"), # Black Club Suit + # LAME ("▶️", ""), # Black Right-Pointing Triangle + # LAME ("◀️", ""), # Black Left-Pointing Triangle + # DOESNT SHOW ("☎️", "☎️"), # Black Telephone + # DOESNT SHOW ("⌨", ""), # Keyboard + # DOESNT SHOW ("✉️", "✉️"), # Envelope + # DOESNT SHOW ("✏️", "✏️"), # Pencil + # DOESNT SHOW ("✒️", "✒️"), # Black Nib + # DOESNT SHOW ("✂️", "✂️"), # Black Scissors + # LAME ("↗️", ""), # North East Arrow + # LAME ("➡️", ""), # Black Rightwards Arrow + # LAME ("↘️", ""), # South East Arrow + # LAME ("↙️", ""), # South West Arrow + # LAME ("↖️", ""), # North West Arrow + # LAME ("↕️", ""), # Up Down Arrow + # LAME ("↔️", ""), # Left Right Arrow + # LAME ("↩️", ""), # Leftwards Arrow With Hook + # LAME ("↪️", ""), # Rightwards Arrow With Hook + # OFFENSIVE ("✡", ""), # Star of David + # OFFENSIVE ("☸", ""), # Wheel of Dharma + # OFFENSIVE ("☯", ""), # Yin Yang + # OFFENSIVE ("✝", ""), # Latin Cross + # OFFENSIVE ("☦", ""), # Orthodox Cross + # OFFENSIVE ("☪", ""), # Star and Crescent + # OFFENSIVE ("☮", ""), # Peace Symbol + # OFFENSIVE ("☢", ""), # Radioactive Sign + # OFFENSIVE ("☣", ""), # Biohazard Sign + # DOESNT SHOW ("☑️", "☑️"), # Ballot Box With Check + # LAME ("✔️", ""), # Heavy Check Mark + # LAME ("✖️", ""), # Heavy Multiplication X + # LAME ("✳️", ""), # Eight Spoked Asterisk + # LAME ("✴️", ""), # Eight Pointed Black Star + # LAME ("❇️", ""), # Sparkle + # DOESNT SHOW ("‼️", "‼️"), # Double Exclamation Mark + # LAME ("〰️", ""), # Wavy Dash + # LAME ("©️", ""), # Copyright Sign + # LAME ("®️", ""), # Registered Sign + # LAME ("™️", ""), # Trade Mark Sign + # LAME ("Ⓜ️", ""), # Circled Latin Capital Letter M + # LAME ("㊗️", ""), # Circled Ideograph Congratulation + # LAME ("㊙️", ""), # Circled Ideograph Secret + # LAME ("▪️", ""), # Black Small Square + # LAME ("▫️", ""), # White Small Square + # Unicode Version 3.0 + # ("#⃣️", "#⃣️"), # Keycap Number Sign + # ("*⃣", "*⃣"), # Keycap Asterisk + # ("0⃣️", "0⃣️"), # Keycap Digit Zero + # ("1⃣️", "1⃣️"), # Keycap Digit One + # ("2⃣️", "2⃣️"), # Keycap Digit Two + # LAME ("3⃣️", ""), # Keycap Digit Three + # LAME ("4⃣️", ""), # Keycap Digit Four + # LAME ("5⃣️", ""), # Keycap Digit Five + # LAME ("6⃣️", ""), # Keycap Digit Six + # LAME ("7⃣️", ""), # Keycap Digit Seven + # LAME ("8⃣️", ""), # Keycap Digit Eight + # LAME ("9⃣️", ""), # Keycap Digit Nine + # DOESNT SHOW ("⁉️", "⁉️"), # Exclamation Question Mark + # LAME ("ℹ️", ""), # Information Source + # Unicode Version 3.2 + # LAME ("⤴️", ""), # Arrow Pointing Rightwards Then Curving Upwards + # LAME ("⤵️", ""), # Arrow Pointing Rightwards Then Curving Downwards + # DOESNT SHOW ("♻️", "♻️"), # Black Universal Recycling Symbol + # LAME ("〽️", ""), # Part Alternation Mark + # LAME ("◻️", ""), # White Medium Square + # LAME ("◼️", ""), # Black Medium Square + # LAME ("◽", ""), # White Medium Small Square + # LAME ("◾", ""), # Black Medium Small Square + # Unicode Version 4.0 + ("☕", "☕"), # Hot Beverage + # DOESN’T SHOW("⚠️", "⚠️"), # Warning Sign + # DOESN’T SHOW ("☔", ""), # Umbrella With Rain Drops + # LAME ("⏏", ""), # Eject Symbol + # LAME ("⬆️", ""), # Upwards Black Arrow + # LAME ("⬇️", ""), # Downwards Black Arrow + # LAME ("⬅️", ""), # Leftwards Black Arrow + # DOESN’T SHOW ("⚡", ""), # High Voltage Sign + # Unicode Version 4.1 + # DOESN’T SHOW ("☘", ""), # Shamrock + # DOESN’T SHOW ("⚓", ""), # Anchor + # DOESN’T SHOW ("♿", ""), # Wheelchair Symbol + # DOESN’T SHOW ("⚒", ""), # Hammer and Pick + # DOESN’T SHOW ("⚙", ""), # Gear + # DOESN’T SHOW ("⚗", ""), # Alembic + # DOESN’T SHOW ("⚖", ""), # Scales + # DOESN’T SHOW ("⚔", ""), # Crossed Swords + # DOESN’T SHOW ("⚰", ""), # Coffin + # DOESN’T SHOW ("⚱", ""), # Funeral Urn + # DOESN’T SHOW ("⚜", ""), # Fleur-De-Lis + # DOESN’T SHOW ("⚛", ""), # Atom Symbol + # LAME ("⚪", ""), # Medium White Circle + # LAME ("⚫", ""), # Medium Black Circle + # Unicode Version 5.1 + # LAME ("🀄", ""), # Mahjong Tile Red Dragon + # DOESNT SHOW ("⭐", "⭐"), # White Medium Star + # LAME ("⬛", ""), # Black Large Square + # LAME ("⬜", ""), # White Large Square + # Unicode Version 5.2 + ("⛑", "⛑"), # Helmet With White Cross + ("⛰", "⛰"), # Mountain + ("⛪", "⛪"), # Church + # LAME ("⛲", ""), # Fountain + # LAME ("⛺", ""), # Tent + # LAME ("⛽", ""), # Fuel Pump + ("⛵", "⛵"), # Sailboat + # LAME ("⛴", ""), # Ferry + ("⛔", "⛔"), # No Entry + ("⛅", "⛅"), # Sun Behind Cloud + ("⛈", "⛈"), # Thunder Cloud and Rain + ("⛱", "⛱"), # Umbrella on Ground + ("⛄", "⛄"), # Snowman Without Snow + ("⚽", "⚽"), # Soccer Ball + # DOESN"T SHOW ("⚾", ""), # Baseball + # LAME ("⛳", ""), # Flag in Hole + # LAME ("⛸", ""), # Ice Skate + # LAME ("⛷", ""), # Skier + # LAME ("⛹", ""), # Person With Ball + ("⛏", "⛏"), # Pick + # OFFENSIVE ("⛓", ""), # Chains + # LAME ("⛩", ""), # Shinto Shrine + # LAME ("⭕", ""), # Heavy Large Circle + # LAME ("❗", ""), # Heavy Exclamation Mark Symbol + # LAME ("🅿️", ""), # Negative Squared Latin Capital Letter P + # LAME ("🈯", ""), # Squared CJK Unified Ideograph-6307 + # LAME ("🈚", ""), # Squared CJK Unified Ideograph-7121 + # Unicode Version 6.0 + ("😁", "😁"), # Grinning Face With Smiling Eyes + ("😂", "😂"), # Face With Tears of Joy + # TOO SIMILAR ("😃", ""), # Smiling Face With Open Mouth + ("😄", "😄"), # Smiling Face With Open Mouth and Smiling Eyes + # TOO SIMILAR ("😅", ""), # Smiling Face With Open Mouth and Cold Sweat + ("😆", "😆"), # Smiling Face With Open Mouth and Tightly-Closed Eyes + ("😉", "😉"), # Winking Face + ("😊", "😊"), # Smiling Face With Smiling Eyes + # TOO SIMILAR ("😋", ""), # Face Savouring Delicious Food + ("😎", "😎"), # Smiling Face With Sunglasses + ("😍", "😍"), # Smiling Face With Heart-Shaped Eyes + ("😘", "😘"), # Face Throwing a Kiss + # TOO SIMILAR ("😚", ""), # Kissing Face With Closed Eyes + ("😇", "😇"), # Smiling Face With Halo + ("😐", "😐"), # Neutral Face + # TOO SIMILAR ("😶", ""), # Face Without Mouth + ("😏", "😏"), # Smirking Face + # TOO SIMILAR ("😣", ""), # Persevering Face + ("😥", "😥"), # Disappointed but Relieved Face + # TOO SIMILAR ("😪", ""), # Sleepy Face + # TOO SIMILAR ("😫", ""), # Tired Face + # TOO SIMILAR ("😌", ""), # Relieved Face + ("😜", "😜"), # Face With Stuck-Out Tongue and Winking Eye + # TOO SIMILAR ("😝", ""), # Face With Stuck-Out Tongue and Tightly-Closed Eyes + # TOO SIMILAR ("😒", ""), # Unamused Face + # TOO SIMILAR ("😓", ""), # Face With Cold Sweat + # TOO SIMILAR ("😔", ""), # Pensive Face + ("😖", "😖"), # Confounded Face + ("😷", "😷"), # Face With Medical Mask + ("😲", "😲"), # Astonished Face + ("😞", "😞"), # Disappointed Face + # TOO SIMILAR ("😤", ""), # Face With Look of Triumph + # TOO SIMILAR ("😢", ""), # Crying Face + ("😭", "😭"), # Loudly Crying Face + # TOO SIMILAR ("😨", ""), # Fearful Face + # TOO SIMILAR ("😩", ""), # Weary Face + ("😰", "😰"), # Face With Open Mouth and Cold Sweat + ("😱", "😱"), # Face Screaming in Fear + ("😳", "😳"), # Flushed Face + ("😵", "😵"), # Dizzy Face + ("😡", "😡"), # Pouting Face + # TOO SIMILAR ("😠", ""), # Angry Face + ("👿", "👿"), # Imp + # TOO SIMILAR ("😈", ""), # Smiling Face With Horns + # LAME ("👦", ""), # Boy + # LAME ("👧", ""), # Girl + # LAME ("👨", ""), # Man + ("👩", "👩"), # Woman + ("👴", "👴"), # Older Man + ("👵", "👵"), # Older Woman + ("👶", "👶"), # Baby + # LAME ("👱", ""), # Person With Blond Hair + ("👮", "👮"), # Police Officer + # OFFENSIVE ("👲", ""), # Man With Gua Pi Mao + # OFFENSIVE ("👳", ""), # Man With Turban + ("👷", "👷"), # Construction Worker + ("👸", "👸"), # Princess + ("💂", "💂"), # Guardsman + ("🎅", "🎅"), # Father Christmas + ("👼", "👼"), # Baby Angel + # USED BY UI ("👯", ""), # Woman With Bunny Ears // for bulk adding teams and team tab/standings + # LAME ("💆", ""), # Face Massage + # LAME ("💇", ""), # Haircut + ("👰", "👰"), # Bride With Veil + # LAME ("🙍", ""), # Person Frowning + # LAME ("🙎", ""), # Person With Pouting Face + ("🙅", "🙅"), # Face With No Good Gesture + ("🙆", "🙆"), # Face With OK Gesture + # USED BY UI ("💁", ""), # Information Desk Person // for reply standings + ("🙋", "🙋"), # Happy Person Raising One Hand + ("🙇", "🙇"), # Person Bowing Deeply + ("🙌", "🙌"), # Person Raising Both Hands in Celebration + ("🙏", "🙏"), # Person With Folded Hands + # LAME ("👤", ""), # Bust in Silhouette + # LAME ("👥", ""), # Busts in Silhouette + # LAME ("🚶", ""), # Pedestrian + # LAME ("🏃", ""), # Runner + ("💃", "💃"), # Dancer + # TOO SIMILAR ("💏", ""), # Kiss + ("💑", "💑"), # Couple With Heart + ("👪", "👪"), # Family + ("👫", "👫"), # Man and Woman Holding Hands + ("👬", "👬"), # Two Men Holding Hands + ("👭", "👭"), # Two Women Holding Hands + ("💪", "💪"), # Flexed Biceps + # LAME ("👈", ""), # White Left Pointing Backhand Index + # LAME ("👉", ""), # White Right Pointing Backhand Index + ("👆", "👆"), # White Up Pointing Backhand Index + # LAME ("👇", ""), # White Down Pointing Backhand Index + ("✊", "✊"), # Raised Fist + ("✋", "✋"), # Raised Hand + ("👊", "👊"), # Fisted Hand Sign + ("👌", "👌"), # OK Hand Sign + ("👍", "👍"), # Thumbs Up Sign + ("👎", "👎"), # Thumbs Down Sign + # USED BY UI ("👋", "👋"), # Waving Hand Sign // for the welcome pages + # LAME ("👏", ""), # Clapping Hands Sign + ("👐", "👐"), # Open Hands Sign + ("💅", "💅"), # Nail Polish + # LAME ("👣", ""), # Footprints + # USED BY UI ("👀", ""), # Eyes // for the draw pages + ("👂", "👂"), # Ear + ("👃", "👃"), # Nose + ("👅", "👅"), # Tongue + ("👄", "👄"), # Mouth + # TOO SIMILAR ("💋", ""), # Kiss Mark + ("💘", "💘"), # Heart With Arrow + # TOO SIMILAR ("💓", ""), # Beating Heart + ("💔", "💔"), # Broken Heart + # TOO SIMILAR ("💕", ""), # Two Hearts + ("💖", "💖"), # Sparkling Heart + # TOO SIMILAR ("💗", ""), # Growing Heart + # TOO SIMILAR ("💙", ""), # Blue Heart + # TOO SIMILAR ("💚", ""), # Green Heart + # TOO SIMILAR ("💛", ""), # Yellow Heart + # TOO SIMILAR ("💜", ""), # Purple Heart + # TOO SIMILAR ("💝", ""), # Heart With Ribbon + # TOO SIMILAR ("💞", ""), # Revolving Hearts + # LAME ("💟", ""), # Heart Decoration + ("💌", "💌"), # Love Letter + ("💧", "💧"), # Droplet + # LAME ("💤", ""), # Sleeping Symbol + # LAME ("💢", ""), # Anger Symbol + ("💣", "💣"), # Bomb + ("💥", "💥"), # Collision Symbol + ("💦", "💦"), # Splashing Sweat Symbol + ("💨", "💨"), # Dash Symbol + # LAME ("💫", ""), # Dizzy Symbol + # LAME ("💬", ""), # Speech Balloon + # LAME ("💭", ""), # Thought Balloon + ("👓", "👓"), # Eyeglasses + ("👔", "👔"), # Necktie + # LAME ("👕", ""), # T-Shirt + # LAME ("👖", ""), # Jeans + # LAME ("👗", ""), # Dress + # LAME ("👘", ""), # Kimono + ("👙", "👙"), # Bikini + # LAME ("👚", ""), # Womans Clothes + # LAME ("👛", ""), # Purse + ("👜", "👜"), # Handbag + # LAME ("👝", ""), # Pouch + # LAME ("🎒", ""), # School Satchel + # LAME ("👞", ""), # Mans Shoe + ("👟", "👟"), # Athletic Shoe + ("👠", "👠"), # High-Heeled Shoe + # LAME ("👡", ""), # Womans Sandal + # LAME ("👢", ""), # Womans Boots + # USED BY UI ("👑", ""), # Crown // for the break pages + ("👒", "👒"), # Womans Hat + ("🎩", "🎩"), # Top Hat + ("💄", "💄"), # Lipstick + ("💍", "💍"), # Ring + ("💎", "💎"), # Gem Stone + # LAME ("👹", ""), # Japanese Ogre + # LAME ("👺", ""), # Japanese Goblin + ("👻", "👻"), # Ghost + ("💀", "💀"), # Skull + ("👽", "👽"), # Extraterrestrial Alien + ("👾", "👾"), # Alien Monster + ("💩", "💩"), # Pile of Poo + ("🐵", ""), # Monkey Face + ("🙈", ""), # See-No-Evil Monkey + ("🙉", ""), # Hear-No-Evil Monkey + ("🙊", ""), # Speak-No-Evil Monkey + # OFFENSIVE("🐒", ""), # Monkey + ("🐶", "🐶"), # Dog Face + # TOO SIMILAR ("🐕", ""), # Dog + ("🐩", ""), # Poodle + # TOO SIMILAR ("🐺", ""), # Wolf Face + # ("🐱", ""), # Cat Face // USED BY UI + # ("😸", ""), # Grinning Cat Face With Smiling Eyes // USED BY UI + # ("😹", ""), # Cat Face With Tears of Joy // USED BY UI + # ("😺", ""), # Smiling Cat Face With Open Mouth // USED BY UI + # ("😻", ""), # Smiling Cat Face With Heart-Shaped Eyes // USED BY UI + # ("😼", ""), # Cat Face With Wry Smile // USED BY UI + # ("😽", ""), # Kissing Cat Face With Closed Eyes // USED BY UI + # ("😾", ""), # Pouting Cat Face // USED BY UI + # ("😿", ""), # Crying Cat Face // USED BY UI + # ("🙀", ""), # Weary Cat Face // USED BY UI + # LAME ("🐈", ""), # Cat + ("🐯", "🐯"), # Tiger Face + # LAME ("🐅", ""), # Tiger + # LAME ("🐆", ""), # Leopard + ("🐴", "🐴"), # Horse Face + # LAME ("🐎", ""), # Horse + ("🐮", "🐮"), # Cow Face + # LAME ("🐂", ""), # Ox + # LAME ("🐃", ""), # Water Buffalo + # LAME ("🐄", ""), # Cow + ("🐷", "🐷"), # Pig Face + # LAME ("🐖", ""), # Pig + # LAME ("🐗", ""), # Boar + # LAME ("🐽", ""), # Pig Nose + # LAME ("🐏", ""), # Ram + ("🐑", "🐑"), # Sheep + # LAME ("🐐", ""), # Goat + # LAME ("🐪", ""), # Dromedary Camel + # LAME ("🐫", ""), # Bactrian Camel + # LAME ("🐘", ""), # Elephant + ("🐭", "🐭"), # Mouse Face + # LAME ("🐁", ""), # Mouse + # LAME ("🐀", ""), # Rat + ("🐹", "🐹"), # Hamster Face + ("🐰", "🐰"), # Rabbit Face + # LAME ("🐇", ""), # Rabbit + ("🐻", "🐻"), # Bear Face + ("🐨", "🐨"), # Koala + ("🐼", "🐼"), # Panda Face + # LAME ("🐾", ""), # Paw Prints + ("🐔", "🐔"), # Chicken + # LAME ("🐓", ""), # Rooster + # LAME ("🐣", ""), # Hatching Chick + # LAME ("🐤", ""), # Baby Chick + # LAME ("🐥", ""), # Front-Facing Baby Chick + ("🐦", "🐦"), # Bird + ("🐧", "🐧"), # Penguin + ("🐸", "🐸"), # Frog Face + # LAME ("🐊", ""), # Crocodile + # LAME ("🐢", ""), # Turtle + ("🐍", "🐍"), # Snake + ("🐲", "🐲"), # Dragon Face + # LAME ("🐉", ""), # Dragon + ("🐳", "🐳"), # Spouting Whale + # TOO SIMILAR ("🐋", ""), # Whale + # TOO SIMILAR ("🐬", ""), # Dolphin + ("🐟", "🐟"), # Fish + # LAME ("🐠", ""), # Tropical Fish + # LAME ("🐡", ""), # Blowfish + ("🐙", "🐙"), # Octopus + ("🐚", "🐚"), # Spiral Shell + # LAME ("🐌", ""), # Snail + # LAME ("🐛", ""), # Bug + # LAME ("🐜", ""), # Ant + ("🐝", "🐝"), # Honeybee + # LAME ("🐞", ""), # Lady Beetle + # LAME ("💐", ""), # Bouquet + ("🌸", "🌸"), # Cherry Blossom + # LAME ("💮", ""), # White Flower + ("🌹", "🌹"), # Rose + # LAME ("🌺", ""), # Hibiscus + ("🌻", "🌻"), # Sunflower + # LAME ("🌼", ""), # Blossom + ("🌷", "🌷"), # Tulip + ("🌱", ""), # Seedling + # LAME ("🌲", ""), # Evergreen Tree + # LAME ("🌳", ""), # Deciduous Tree + # LAME ("🌴", ""), # Palm Tree + ("🌵", "🌵"), # Cactus + # LAME ("🌾", ""), # Ear of Rice + # LAME ("🌿", ""), # Herb + ("🍀", ""), # Four Leaf Clover + ("🍁", "🍁"), # Maple Leaf + # LAME ("🍂", ""), # Fallen Leaf + # LAME ("🍃", ""), # Leaf Fluttering in Wind + ("🍇", "🍇"), # Grapes + # LAME ("🍈", ""), # Melon + ("🍉", "🍉"), # Watermelon + ("🍊", "🍊"), # Tangerine + ("🍋", "🍋"), # Lemon + ("🍌", "🍌"), # Banana + ("🍍", "🍍"), # Pineapple + ("🍎", "🍎"), # Red Apple + # TOO SIMILAR ("🍏", ""), # Green Apple + # TOO SIMILAR ("🍐", ""), # Pear + ("🍑", "🍑"), # Peach + ("🍒", "🍒"), # Cherries + ("🍓", "🍓"), # Strawberry + ("🍅", "🍅"), # Tomato + ("🍆", "🍆"), # Aubergine + ("🌽", "🌽"), # Ear of Maize + ("🍄", "🍄"), # Mushroom + # LAME ("🌰", ""), # Chestnut + ("🍞", "🍞"), # Bread + # LAME ("🍖", ""), # Meat on Bone + # LAME ("🍗", ""), # Poultry Leg + ("🍔", "🍔"), # Hamburger + # LAME ("🍟", ""), # French Fries + ("🍕", "🍕"), # Slice of Pizza + # LAME ("🍲", ""), # Pot of Food + # LAME ("🍱", ""), # Bento Box + # LAME ("🍘", ""), # Rice Cracker + ("🍙", ""), # Rice Ball + # LAME ("🍚", ""), # Cooked Rice + # LAME ("🍛", ""), # Curry and Rice + # LAME ("🍜", ""), # Steaming Bowl + # LAME ("🍝", ""), # Spaghetti + # LAME ("🍠", ""), # Roasted Sweet Potato + # LAME ("🍢", ""), # Oden + # LAME ("🍣", ""), # Sushi + # LAME ("🍤", ""), # Fried Shrimp + # LAME ("🍥", ""), # Fish Cake With Swirl Design + # LAME ("🍡", ""), # Dango + # LAME ("🍦", ""), # Soft Ice Cream + # LAME ("🍧", ""), # Shaved Ice + ("🍨", "🍨"), # Ice Cream + ("🍩", "🍩"), # Doughnut + ("🍪", "🍪"), # Cookie + # LAME ("🎂", ""), # Birthday Cake + ("🍰", "🍰"), # Shortcake + # LAME ("🍫", ""), # Chocolate Bar + # LAME ("🍬", ""), # Candy + ("🍭", "🍭"), # Lollipop + # LAME ("🍮", ""), # Custard + # LAME ("🍯", ""), # Honey Pot + ("🍼", "🍼"), # Baby Bottle + # LAME ("🍵", ""), # Teacup Without Handle + # LAME ("🍶", ""), # Sake Bottle and Cup + ("🍷", "🍷"), # Wine Glass + ("🍸", "🍸"), # Cocktail Glass + ("🍹", "🍹"), # Tropical Drink + ("🍺", "🍺"), # Beer Mug + # TOO SIMILAR ("🍻", ""), # Clinking Beer Mugs + ("🍴", "🍴"), # Fork and Knife + # LAME ("🍳", ""), # Cooking + # LAME ("🌍", ""), # Earth Globe Europe-Africa + # LAME ("🌎", ""), # Earth Globe Americas + # LAME ("🌏", ""), # Earth Globe Asia-Australia + # LAME ("🌐", ""), # Globe With Meridians + ("🌋", "🌋"), # Volcano + # LAME ("🗻", ""), # Mount Fuji + ("🏠", "🏠"), # House Building + # LAME ("🏡", ""), # House With Garden + ("🏢", "🏢"), # Office Building + # TOO SIMILAR ("🏣", ""), # Japanese Post Office + # TOO SIMILAR ("🏤", ""), # European Post Office + # TOO SIMILAR ("🏥", ""), # Hospital + # TOO SIMILAR ("🏦", ""), # Bank + # TOO SIMILAR ("🏨", ""), # Hotel + ("🏩", "🏩"), # Love Hotel + # TOO SIMILAR ("🏪", ""), # Convenience Store + # TOO SIMILAR ("🏫", ""), # School + # TOO SIMILAR ("🏬", ""), # Department Store + # TOO SIMILAR ("🏭", ""), # Factory + # TOO SIMILAR ("🏯", ""), # Japanese Castle + # TOO SIMILAR ("🏰", ""), # European Castle + # TOO SIMILAR ("💒", ""), # Wedding + # TOO SIMILAR ("🗼", ""), # Tokyo Tower + # TOO SIMILAR ("🗽", ""), # Statue of Liberty + # TOO SIMILAR ("🗾", ""), # Silhouette of Japan + # TOO SIMILAR ("🌁", ""), # Foggy + # TOO SIMILAR ("🌃", ""), # Night With Stars + # TOO SIMILAR ("🌄", ""), # Sunrise Over Mountains + # TOO SIMILAR ("🌅", ""), # Sunrise + # TOO SIMILAR ("🌆", ""), # Cityscape at Dusk + # TOO SIMILAR ("🌇", ""), # Sunset Over Buildings + # TOO SIMILAR ("🌉", ""), # Bridge at Night + ("🌊", "🌊"), # Water Wave + # LAME ("🗿", ""), # Moyai + # LAME ("🌌", ""), # Milky Way + # LAME ("🎠", ""), # Carousel Horse + # LAME ("🎡", ""), # Ferris Wheel + # LAME ("🎢", ""), # Roller Coaster + # LAME ("💈", ""), # Barber Pole + # USED BY THE UI ("🎪", ""), # Circus Tent // venue checkins/adding + # LAME ("🎭", ""), # Performing Arts + ("🎨", "🎨"), # Artist Palette + # LAME ("🎰", ""), # Slot Machine + # LAME ("🚂", ""), # Steam Locomotive + ("🚃", "🚃"), # Railway Car + ("🚄", "🚄"), # High-Speed Train + # TOO SIMILAR ("🚅", ""), # High-Speed Train With Bullet Nose + # TOO SIMILAR ("🚆", ""), # Train + # TOO SIMILAR ("🚇", ""), # Metro + # TOO SIMILAR ("🚈", ""), # Light Rail + # TOO SIMILAR ("🚉", ""), # Station + # TOO SIMILAR ("🚊", ""), # Tram + ("🚝", "🚝"), # Monorail + # TOO SIMILAR ("🚞", ""), # Mountain Railway + # TOO SIMILAR ("🚋", ""), # Tram Car + # TOO SIMILAR ("🚌", ""), # Bus + ("🚍", "🚍"), # Oncoming Bus + # TOO SIMILAR ("🚎", ""), # Trolleybus + # TOO SIMILAR ("🚏", ""), # Bus Stop + # TOO SIMILAR ("🚐", ""), # Minibus + # TOO SIMILAR ("🚑", ""), # Ambulance + # TOO SIMILAR ("🚒", ""), # Fire Engine + # TOO SIMILAR ("🚓", ""), # Police Car + ("🚔", "🚔"), # Oncoming Police Car + # TOO SIMILAR ("🚕", ""), # Taxi + # TOO SIMILAR ("🚖", ""), # Oncoming Taxi + # TOO SIMILAR ("🚗", ""), # Automobile + ("🚘", "🚘"), # Oncoming Automobile + # TOO SIMILAR ("🚙", ""), # Recreational Vehicle + # TOO SIMILAR ("🚚", ""), # Delivery Truck + # TOO SIMILAR ("🚛", ""), # Articulated Lorry + # TOO SIMILAR ("🚜", ""), # Tractor + ("🚲", "🚲"), # Bicycle + # TOO SIMILAR ("🚳", ""), # No Bicycles + ("🚨", "🚨"), # Police Cars Revolving Light + # TOO SIMILAR ("🔱", ""), # Trident Emblem + ("🚣", "🚣"), # Rowboat + # LAME ("🚤", ""), # Speedboat + # LAME ("🚢", ""), # Ship + # LAME ("💺", ""), # Seat + ("🚁", "🚁"), # Helicopter + # LAME ("🚟", ""), # Suspension Railway + # LAME ("🚠", ""), # Mountain Cableway + # LAME ("🚡", ""), # Aerial Tramway + ("🚀", "🚀"), # Rocket + # LAME ("🏧", ""), # Automated Teller Machine + # LAME ("🚮", ""), # Put Litter in Its Place Symbol + # LAME ("🚥", ""), # Horizontal Traffic Light + ("🚦", "🚦"), # Vertical Traffic Light + ("🚧", "🚧"), # Construction Sign + ("🚫", "🚫"), # No Entry Sign + # LAME ("🚭", ""), # No Smoking Symbol + # LAME ("🚯", ""), # Do Not Litter Symbol + # LAME ("🚰", ""), # Potable Water Symbol + # LAME ("🚱", ""), # Non-Potable Water Symbol + ("🚷", "🚷"), # No Pedestrians + # LAME ("🚸", ""), # Children Crossing + # LAME ("🚹", ""), # Mens Symbol + # LAME ("🚺", ""), # Womens Symbol + ("🚻", "🚻"), # Restroom + # LAME ("🚼", ""), # Baby Symbol + # LAME ("🚾", ""), # Water Closet + # LAME ("🛂", ""), # Passport Control + # LAME ("🛃", ""), # Customs + # LAME ("🛄", ""), # Baggage Claim + # LAME ("🛅", ""), # Left Luggage + # LAME ("🚪", ""), # Door + ("🚽", "🚽"), # Toilet + ("🚿", "🚿"), # Shower + ("🛀", "🛀"), # Bath + # LAME ("🛁", ""), # Bathtub + ("⏳", "⏳"), # Hourglass With Flowing Sand + ("⏰", "⏰"), # Alarm Clock + # LAME ("⏱", ""), # Stopwatch + # LAME ("⏲", ""), # Timer Clock + # LAME ("🕛", ""), # Clock Face Twelve O'Clock + # LAME ("🕧", ""), # Clock Face Twelve-Thirty + # LAME ("🕐", ""), # Clock Face One O'Clock + # LAME ("🕜", ""), # Clock Face One-Thirty + # LAME ("🕑", ""), # Clock Face Two O'Clock + # LAME ("🕝", ""), # Clock Face Two-Thirty + # LAME ("🕒", ""), # Clock Face Three O'Clock + # LAME ("🕞", ""), # Clock Face Three-Thirty + # LAME ("🕓", ""), # Clock Face Four O'Clock + # LAME ("🕟", ""), # Clock Face Four-Thirty + # LAME ("🕔", ""), # Clock Face Five O'Clock + # LAME ("🕠", ""), # Clock Face Five-Thirty + # LAME ("🕕", ""), # Clock Face Six O'Clock + # LAME ("🕡", ""), # Clock Face Six-Thirty + # LAME ("🕖", ""), # Clock Face Seven O'Clock + # LAME ("🕢", ""), # Clock Face Seven-Thirty + # LAME ("🕗", ""), # Clock Face Eight O'Clock + # LAME ("🕣", ""), # Clock Face Eight-Thirty + # LAME ("🕘", ""), # Clock Face Nine O'Clock + # LAME ("🕤", ""), # Clock Face Nine-Thirty + # LAME ("🕙", ""), # Clock Face Ten O'Clock + # LAME ("🕥", ""), # Clock Face Ten-Thirty + # LAME ("🕚", ""), # Clock Face Eleven O'Clock + # LAME ("🕦", ""), # Clock Face Eleven-Thirty + # LAME ("⛎", ""), # Ophiuchus + ("🌑", "🌑"), # New Moon Symbol + # LAME ("🌒", ""), # Waxing Crescent Moon Symbol + # LAME ("🌓", ""), # First Quarter Moon Symbol + # LAME ("🌔", ""), # Waxing Gibbous Moon Symbol + ("🌕", "🌕"), # Full Moon Symbol + # LAME ("🌖", ""), # Waning Gibbous Moon Symbol + ("🌗", "🌗"), # Last Quarter Moon Symbol + # LAME ("🌘", ""), # Waning Crescent Moon Symbol + # LAME ("🌙", ""), # Crescent Moon + # OFFENSIVE("🌚", ""), # New Moon With Face + # LAME ("🌛", ""), # First Quarter Moon With Face + # LAME ("🌜", ""), # Last Quarter Moon With Face + # LAME ("🌝", ""), # Full Moon With Face + ("🌞", "🌞"), # Sun With Face + # LAME ("🌀", ""), # Cyclone + ("🌈", "🌈"), # Rainbow + ("🌂", "🌂"), # Closed Umbrella + ("🌟", "🌟"), # Glowing Star + # LAME ("🌠", ""), # Shooting Star + ("🔥", "🔥"), # Fire + ("🎃", "🎃"), # Jack-O-Lantern + ("🎄", "🎄"), # Christmas Tree + # LAME ("🎆", ""), # Fireworks + # LAME ("🎇", ""), # Firework Sparkler + # LAME ("✨", ""), # Sparkles + ("🎈", "🎈"), # Balloon + ("🎉", "🎉"), # Party Popper + # LAME ("🎊", ""), # Confetti Ball + # LAME ("🎋", ""), # Tanabata Tree + # LAME ("🎌", ""), # Crossed Flags + # LAME ("🎍", ""), # Pine Decoration + # LAME ("🎎", ""), # Japanese Dolls + # LAME ("🎏", ""), # Carp Streamer + # LAME ("🎐", ""), # Wind Chime + # LAME ("🎑", ""), # Moon Viewing Ceremony + ("🎓", "🎓"), # Graduation Cap + ("🎯", "🎯"), # Direct Hit + # LAME ("🎴", ""), # Flower Playing Cards + ("🎀", "🎀"), # Ribbon + # LAME ("🎁", ""), # Wrapped Present + # LAME ("🎫", ""), # Ticket + ("🏀", "🏀"), # Basketball and Hoop + ("🏈", "🏈"), # American Football + # TOO SIMILAR ("🏉", ""), # Rugby Football + ("🎾", "🎾"), # Tennis Racquet and Ball + ("🎱", "🎱"), # Billiards + # TOO SIMILAR ("🎳", ""), # Bowling + # LAME ("🎣", ""), # Fishing Pole and Fish + # LAME ("🎽", ""), # Running Shirt With Sash + # LAME ("🎿", ""), # Ski and Ski Boot + # LAME ("🏂", ""), # Snowboarder + # LAME ("🏄", ""), # Surfer + # LAME ("🏇", ""), # Horse Racing + # LAME ("🏊", ""), # Swimmer + # LAME ("🚴", ""), # Bicyclist + # LAME ("🚵", ""), # Mountain Bicyclist + # USED BY UI ("🏆", ""), # Trophy // for adding new tournament/list of tournaments + ("🎮", "🎮"), # Video Game + ("🎲", "🎲"), # Game Die + # LAME ("🃏", ""), # Playing Card Black Joker + # LAME ("🔇", ""), # Speaker With Cancellation Stroke + # LAME ("🔈", ""), # Speaker + # LAME ("🔉", ""), # Speaker With One Sound Wave + # LAME ("🔊", ""), # Speaker With Three Sound Waves + # USED BY UI ("📢", ""), # Public Address Loudspeaker // for public config settings + ("📣", "📣"), # Cheering Megaphone + ("📯", ""), # Postal Horn + ("🔔", "🔔"), # Bell + # ("🔕", ""), # Bell With Cancellation Stroke + # LAME ("🔀", ""), # Twisted Rightwards Arrows + # LAME ("🔁", ""), # Clockwise Rightwards and Leftwards Open Circle Arrows + # LAME ("🔂", ""), # Clockwise Rightwards and Leftwards Open Circle Arrows With Circled One Overlay + # LAME ("⏩", ""), # Black Right-Pointing Double Triangle + # LAME ("⏭", ""), # Black Right-Pointing Double Triangle With Vertical Bar + # LAME ("⏯", ""), # Black Right-Pointing Triangle With Double Vertical Bar + # LAME ("⏪", ""), # Black Left-Pointing Double Triangle + # LAME ("⏮", ""), # Black Left-Pointing Double Triangle With Vertical Bar + # LAME ("🔼", ""), # Up-Pointing Small Red Triangle + # LAME ("⏫", ""), # Black Up-Pointing Double Triangle + # LAME ("🔽", ""), # Down-Pointing Small Red Triangle + # LAME ("⏬", ""), # Black Down-Pointing Double Triangle + # LAME ("🎼", ""), # Musical Score + # LAME ("🎵", ""), # Musical Note + ("🎶", "🎶"), # Multiple Musical Notes + ("🎤", "🎤"), # Microphone + # LAME ("🎧", ""), # Headphone + # LAME ("🎷", ""), # Saxophone + # LAME ("🎸", ""), # Guitar + ("🎹", "🎹"), # Musical Keyboard + ("🎺", "🎺"), # Trumpet + ("🎻", "🎻"), # Violin + ("📻", "📻"), # Radio + ("📱", "📱"), # Mobile Phone + # LAME ("📳", ""), # Vibration Mode + # LAME ("📴", ""), # Mobile Phone Off + # TOO SIMILAR ("📲", ""), # Mobile Phone With Rightwards Arrow at Left + # LAME ("📵", ""), # No Mobile Phones + ("📞", "📞"), # Telephone Receiver + # LAME ("🔟", ""), # Keycap Ten + # LAME ("📶", ""), # Antenna With Bars + # LAME ("📟", ""), # Pager + # LAME ("📠", ""), # Fax Machine + ("🔋", "🔋"), # Battery + ("🔌", "🔌"), # Electric Plug + # LAME ("💻", ""), # Personal Computer + # LAME ("💽", ""), # Minidisc + ("💾", "💾"), # Floppy Disk + ("💿", "💿"), # Optical Disc + # LAME ("📀", ""), # DVD + # LAME ("🎥", ""), # Movie Camera + # LAME ("🎦", ""), # Cinema + ("🎬", "🎬"), # Clapper Board + # LAME ("📺", ""), # Television + ("📷", "📷"), # Camera + # LAME ("📹", ""), # Video Camera + # LAME ("📼", ""), # Videocassette + # LAME ("🔅", ""), # Low Brightness Symbol + # LAME ("🔆", ""), # High Brightness Symbol + ("🔍", "🔍"), # Left-Pointing Magnifying Glass + # LAME ("🔎", ""), # Right-Pointing Magnifying Glass + # LAME ("🔬", ""), # Microscope + ("🔭", "🔭"), # Telescope + # LAME ("📡", ""), # Satellite Antenna + ("💡", "💡"), # Electric Light Bulb + # LAME ("🔦", ""), # Electric Torch + # LAME ("🏮", ""), # Izakaya Lantern + # TOO SIMILAR ("📔", ""), # Notebook With Decorative Cover + ("📕", "📕"), # Closed Book + # TOO SIMILAR ("📖", ""), # Open Book + # TOO SIMILAR ("📗", ""), # Green Book + # TOO SIMILAR ("📘", ""), # Blue Book + # TOO SIMILAR ("📙", ""), # Orange Book + # TOO SIMILAR ("📚", ""), # Books + # TOO SIMILAR ("📓", ""), # Notebook + # TOO SIMILAR ("📒", ""), # Ledger + # TOO SIMILAR ("📃", ""), # Page With Curl + # TOO SIMILAR ("📜", ""), # Scroll + # TOO SIMILAR ("📄", ""), # Page Facing Up + ("📰", "📰"), # Newspaper + # TOO SIMILAR ("📑", ""), # Bookmark Tabs + # TOO SIMILAR ("🔖", ""), # Bookmark + ("💰", "💰"), # Money Bag + # TOO SIMILAR ("💴", ""), # Banknote With Yen Sign + # TOO SIMILAR ("💵", ""), # Banknote With Dollar Sign + # TOO SIMILAR ("💶", ""), # Banknote With Euro Sign + # TOO SIMILAR ("💷", ""), # Banknote With Pound Sign + ("💸", "💸"), # Money With Wings + # LAME ("💱", ""), # Currency Exchange + # LAME ("💲", ""), # Heavy Dollar Sign + # LAME ("💳", ""), # Credit Card + # LAME ("💹", ""), # Chart With Upwards Trend and Yen Sign + # LAME ("📧", ""), # E-Mail Symbol + # LAME ("📨", ""), # Incoming Envelope + # LAME ("📩", ""), # Envelope With Downwards Arrow Above + # LAME ("📤", ""), # Outbox Tray + # LAME ("📥", ""), # Inbox Tray + ("📦", ""), # Package + ("📫", "📫"), # Closed Mailbox With Raised Flag + # LAME ("📪", ""), # Closed Mailbox With Lowered Flag + # LAME ("📬", ""), # Open Mailbox With Raised Flag + # LAME ("📭", ""), # Open Mailbox With Lowered Flag + # LAME ("📮", ""), # Postbox + # LAME ("📝", ""), # Memo + ("💼", "💼"), # Briefcase + # LAME ("📁", ""), # File Folder + # LAME ("📂", ""), # Open File Folder + ("📅", "📅"), # Calendar + # LAME ("📆", ""), # Tear-Off Calendar + # LAME ("📇", ""), # Card Index + # LAME ("📈", ""), # Chart With Upwards Trend + # LAME ("📉", ""), # Chart With Downwards Trend + # LAME ("📊", ""), # Bar Chart + # LAME ("📋", ""), # Clipboard + # LAME ("📌", ""), # Pushpin + # LAME ("📍", ""), # Round Pushpin + # LAME ("📎", ""), # Paperclip + ("📏", "📏"), # Straight Ruler + ("📐", "📐"), # Triangular Ruler + # LAME ("📛", ""), # Name Badge + # USED BY UI ("🔒", ""), # Lock // Logout page + # USED BY UI ("🔓", ""), # Open Lock // Login page + # ("🔏", ""), # Lock With Ink Pen + # ("🔐", ""), # Closed Lock With Key + ("🔑", "🔑"), # Key + # LAME ("🔨", ""), # Hammer + # USED BY UI ("🔧", ""), # Wrench // for tournament config link + ("🔩", "🔩"), # Nut and Bolt + # LAME ("🔗", ""), # Link Symbol + # OFFENSIVE ("💉", ""), # Syringe + ("💊", ""), # Pill + ("🔪", "🔪"), # Hocho + ("🔫", "🔫"), # Pistol + ("🚬", "🚬"), # Smoking Symbol + ("🏁", ""), # Chequered Flag + # LAME ("🚩", ""), # Triangular Flag on Post + # LAME ("🇦🇫", ""), # Flag for Afghanistan + # LAME ("🇦🇽", ""), # Flag for Åland Islands + # LAME ("🇦🇱", ""), # Flag for Albania + # LAME ("🇩🇿", ""), # Flag for Algeria + # LAME ("🇦🇸", ""), # Flag for American Samoa + # LAME ("🇦🇩", ""), # Flag for Andorra + # LAME ("🇦🇴", ""), # Flag for Angola + # LAME ("🇦🇮", ""), # Flag for Anguilla + # ("🇦🇶", "🇦🇶"), # Flag for Antarctica + # LAME ("🇦🇬", ""), # Flag for Antigua & Barbuda + # LAME ("🇦🇷", ""), # Flag for Argentina + # LAME ("🇦🇲", ""), # Flag for Armenia + # LAME ("🇦🇼", ""), # Flag for Aruba + # LAME ("🇦🇨", ""), # Flag for Ascension Island + # ("🇦🇺", "🇦🇺"), # Flag for Australia + # ("🇦🇹", "🇦🇹"), # Flag for Austria + # LAME ("🇦🇿", ""), # Flag for Azerbaijan + # LAME ("🇧🇸", ""), # Flag for Bahamas + # LAME ("🇧🇭", ""), # Flag for Bahrain + # LAME ("🇧🇩", ""), # Flag for Bangladesh + # LAME ("🇧🇧", ""), # Flag for Barbados + # LAME ("🇧🇾", ""), # Flag for Belarus + # LAME ("🇧🇪", ""), # Flag for Belgium + # LAME ("🇧🇿", ""), # Flag for Belize + # LAME ("🇧🇯", ""), # Flag for Benin + # LAME ("🇧🇲", ""), # Flag for Bermuda + # LAME ("🇧🇹", ""), # Flag for Bhutan + # LAME ("🇧🇴", ""), # Flag for Bolivia + # LAME ("🇧🇦", ""), # Flag for Bosnia & Herzegovina + # LAME ("🇧🇼", ""), # Flag for Botswana + # LAME ("🇧🇻", ""), # Flag for Bouvet Island + # ("🇧🇷", "🇧🇷"), # Flag for Brazil + # LAME ("🇮🇴", ""), # Flag for British Indian Ocean Territory + # LAME ("🇻🇬", ""), # Flag for British Virgin Islands + # LAME ("🇧🇳", ""), # Flag for Brunei + # LAME ("🇧🇬", ""), # Flag for Bulgaria + # LAME ("🇧🇫", ""), # Flag for Burkina Faso + # LAME ("🇧🇮", ""), # Flag for Burundi + # LAME ("🇰🇭", ""), # Flag for Cambodia + # LAME ("🇨🇲", ""), # Flag for Cameroon + # ("🇨🇦", "🇨🇦"), # Flag for Canada + # LAME ("🇮🇨", ""), # Flag for Canary Islands + # LAME ("🇨🇻", ""), # Flag for Cape Verde + # LAME ("🇧🇶", ""), # Flag for Caribbean Netherlands + # LAME ("🇰🇾", ""), # Flag for Cayman Islands + # LAME ("🇨🇫", ""), # Flag for Central African Republic + # LAME ("🇪🇦", ""), # Flag for Ceuta & Melilla + # LAME ("🇹🇩", ""), # Flag for Chad + # ("🇨🇱", "🇨🇱"), # Flag for Chile + # ("🇨🇳", "🇨🇳"), # Flag for China + # LAME ("🇨🇽", ""), # Flag for Christmas Island + # LAME ("🇨🇵", ""), # Flag for Clipperton Island + # LAME ("🇨🇨", ""), # Flag for Cocos Islands + # LAME ("🇨🇴", ""), # Flag for Colombia + # LAME ("🇰🇲", ""), # Flag for Comoros + # LAME ("🇨🇬", ""), # Flag for Congo - Brazzaville + # LAME ("🇨🇩", ""), # Flag for Congo - Kinshasa + # LAME ("🇨🇰", ""), # Flag for Cook Islands + # LAME ("🇨🇷", ""), # Flag for Costa Rica + # LAME ("🇨🇮", ""), # Flag for Côte D’Ivoire + # LAME ("🇭🇷", ""), # Flag for Croatia + # LAME ("🇨🇺", ""), # Flag for Cuba + # LAME ("🇨🇼", ""), # Flag for Curaçao + # LAME ("🇨🇾", ""), # Flag for Cyprus + # ("🇨🇿", "🇨🇿"), # Flag for Czech Republic + # ("🇩🇰", "🇩🇰"), # Flag for Denmark + # LAME ("🇩🇬", ""), # Flag for Diego Garcia + # LAME ("🇩🇯", ""), # Flag for Djibouti + # LAME ("🇩🇲", ""), # Flag for Dominica + # LAME ("🇩🇴", ""), # Flag for Dominican Republic + # LAME ("🇪🇨", ""), # Flag for Ecuador + # ("🇪🇬", "🇪🇬"), # Flag for Egypt + # LAME ("🇸🇻", ""), # Flag for El Salvador + # LAME ("🇬🇶", ""), # Flag for Equatorial Guinea + # LAME ("🇪🇷", ""), # Flag for Eritrea + # LAME ("🇪🇪", ""), # Flag for Estonia + # LAME ("🇪🇹", ""), # Flag for Ethiopia + # ("🇪🇺", "🇪🇺"), # Flag for European Union + # LAME ("🇫🇰", ""), # Flag for Falkland Islands + # LAME ("🇫🇴", ""), # Flag for Faroe Islands + # LAME ("🇫🇯", ""), # Flag for Fiji + # LAME ("🇫🇮", ""), # Flag for Finland + # ("🇫🇷", "🇫🇷"), # Flag for France + # LAME ("🇬🇫", ""), # Flag for French Guiana + # LAME ("🇵🇫", ""), # Flag for French Polynesia + # LAME ("🇹🇫", ""), # Flag for French Southern Territories + # LAME ("🇬🇦", ""), # Flag for Gabon + # LAME ("🇬🇲", ""), # Flag for Gambia + # LAME ("🇬🇪", ""), # Flag for Georgia + # ("🇩🇪", "🇩🇪"), # Flag for Germany + # LAME ("🇬🇭", ""), # Flag for Ghana + # LAME ("🇬🇮", ""), # Flag for Gibraltar + # ("🇬🇷", "🇬🇷"), # Flag for Greece + # LAME ("🇬🇱", ""), # Flag for Greenland + # LAME ("🇬🇩", ""), # Flag for Grenada + # LAME ("🇬🇵", ""), # Flag for Guadeloupe + # LAME ("🇬🇺", ""), # Flag for Guam + # LAME ("🇬🇹", ""), # Flag for Guatemala + # LAME ("🇬🇬", ""), # Flag for Guernsey + # LAME ("🇬🇳", ""), # Flag for Guinea + # LAME ("🇬🇼", ""), # Flag for Guinea-Bissau + # LAME ("🇬🇾", ""), # Flag for Guyana + # LAME ("🇭🇹", ""), # Flag for Haiti + # LAME ("🇭🇲", ""), # Flag for Heard & McDonald Islands + # LAME ("🇭🇳", ""), # Flag for Honduras + # LAME ("🇭🇰", ""), # Flag for Hong Kong + # LAME ("🇭🇺", ""), # Flag for Hungary + # LAME ("🇮🇸", ""), # Flag for Iceland + # ("🇮🇳", "🇮🇳"), # Flag for India + # ("🇮🇩", "🇮🇩"), # Flag for Indonesia + # ("🇮🇷", "🇮🇷"), # Flag for Iran + # ("🇮🇶", "🇮🇶"), # Flag for Iraq + # ("🇮🇪", "🇮🇪"), # Flag for Ireland + # LAME ("🇮🇲", ""), # Flag for Isle of Man + # LAME ("🇮🇱", ""), # Flag for Israel + # ("🇮🇹", "🇮🇹"), # Flag for Italy + # LAME ("🇯🇲", ""), # Flag for Jamaica + # ("🇯🇵", "🇯🇵"), # Flag for Japan + # LAME ("🇯🇪", ""), # Flag for Jersey + # LAME ("🇯🇴", ""), # Flag for Jordan + # LAME ("🇰🇿", ""), # Flag for Kazakhstan + # LAME ("🇰🇪", ""), # Flag for Kenya + # LAME ("🇰🇮", ""), # Flag for Kiribati + # LAME ("🇽🇰", ""), # Flag for Kosovo + # LAME ("🇰🇼", ""), # Flag for Kuwait + # LAME ("🇰🇬", ""), # Flag for Kyrgyzstan + # LAME ("🇱🇦", ""), # Flag for Laos + # LAME ("🇱🇻", ""), # Flag for Latvia + # LAME ("🇱🇧", ""), # Flag for Lebanon + # LAME ("🇱🇸", ""), # Flag for Lesotho + # LAME ("🇱🇷", ""), # Flag for Liberia + # LAME ("🇱🇾", ""), # Flag for Libya + # LAME ("🇱🇮", ""), # Flag for Liechtenstein + # LAME ("🇱🇹", ""), # Flag for Lithuania + # LAME ("🇱🇺", ""), # Flag for Luxembourg + # LAME ("🇲🇴", ""), # Flag for Macau + # LAME ("🇲🇰", ""), # Flag for Macedonia + # LAME ("🇲🇬", ""), # Flag for Madagascar + # LAME ("🇲🇼", ""), # Flag for Malawi + # LAME ("🇲🇾", ""), # Flag for Malaysia + # LAME ("🇲🇻", ""), # Flag for Maldives + # LAME ("🇲🇱", ""), # Flag for Mali + # LAME ("🇲🇹", ""), # Flag for Malta + # LAME ("🇲🇭", ""), # Flag for Marshall Islands + # LAME ("🇲🇶", ""), # Flag for Martinique + # LAME ("🇲🇷", ""), # Flag for Mauritania + # LAME ("🇲🇺", ""), # Flag for Mauritius + # LAME ("🇾🇹", ""), # Flag for Mayotte + # ("🇲🇽", "🇲🇽"), # Flag for Mexico + # LAME ("🇫🇲", ""), # Flag for Micronesia + # LAME ("🇲🇩", ""), # Flag for Moldova + # LAME ("🇲🇨", ""), # Flag for Monaco + # LAME ("🇲🇳", ""), # Flag for Mongolia + # LAME ("🇲🇪", ""), # Flag for Montenegro + # LAME ("🇲🇸", ""), # Flag for Montserrat + # LAME ("🇲🇦", ""), # Flag for Morocco + # LAME ("🇲🇿", ""), # Flag for Mozambique + # LAME ("🇲🇲", ""), # Flag for Myanmar + # LAME ("🇳🇦", ""), # Flag for Namibia + # LAME ("🇳🇷", ""), # Flag for Nauru + # LAME ("🇳🇵", ""), # Flag for Nepal + # LAME ("🇳🇱", ""), # Flag for Netherlands + # LAME ("🇳🇨", ""), # Flag for New Caledonia + # ("🇳🇿", "🇳🇿"), # Flag for New Zealand + # LAME ("🇳🇮", ""), # Flag for Nicaragua + # LAME ("🇳🇪", ""), # Flag for Niger + # LAME ("🇳🇬", ""), # Flag for Nigeria + # LAME ("🇳🇺", ""), # Flag for Niue + # LAME ("🇳🇫", ""), # Flag for Norfolk Island + # LAME ("🇲🇵", ""), # Flag for Northern Mariana Islands + # LAME ("🇰🇵", ""), # Flag for North Korea + # ("🇳🇴", "🇳🇴"), # Flag for Norway + # LAME ("🇴🇲", ""), # Flag for Oman + # LAME ("🇵🇰", ""), # Flag for Pakistan + # LAME ("🇵🇼", ""), # Flag for Palau + # ("🇵🇸", "🇵🇸"), # Flag for Palestinian Territories + # LAME ("🇵🇦", ""), # Flag for Panama + # LAME ("🇵🇬", ""), # Flag for Papua New Guinea + # LAME ("🇵🇾", ""), # Flag for Paraguay + # ("🇵🇪", "🇵🇪"), # Flag for Peru + # LAME ("🇵🇭", ""), # Flag for Philippines + # LAME ("🇵🇳", ""), # Flag for Pitcairn Islands + # LAME ("🇵🇱", ""), # Flag for Poland + # LAME ("🇵🇹", ""), # Flag for Portugal + # LAME ("🇵🇷", ""), # Flag for Puerto Rico + # LAME ("🇶🇦", ""), # Flag for Qatar + # LAME ("🇷🇪", ""), # Flag for Réunion + # LAME ("🇷🇴", ""), # Flag for Romania + # ("🇷🇺", "🇷🇺"), # Flag for Russia + # LAME ("🇷🇼", ""), # Flag for Rwanda + # LAME ("🇼🇸", ""), # Flag for Samoa + # LAME ("🇸🇲", ""), # Flag for San Marino + # LAME ("🇸🇹", ""), # Flag for São Tomé & Príncipe + # LAME ("🇸🇦", ""), # Flag for Saudi Arabia + # LAME ("🇸🇳", ""), # Flag for Senegal + # LAME ("🇷🇸", ""), # Flag for Serbia + # LAME ("🇸🇨", ""), # Flag for Seychelles + # LAME ("🇸🇱", ""), # Flag for Sierra Leone + # LAME ("🇸🇬", ""), # Flag for Singapore + # LAME ("🇸🇽", ""), # Flag for Sint Maarten + # LAME ("🇸🇰", ""), # Flag for Slovakia + # LAME ("🇸🇮", ""), # Flag for Slovenia + # LAME ("🇸🇧", ""), # Flag for Solomon Islands + # LAME ("🇸🇴", ""), # Flag for Somalia + # ("🇿🇦", "🇿🇦"), # Flag for South Africa + # LAME ("🇬🇸", ""), # Flag for South Georgia & South Sandwich Islands + # ("🇰🇷", "🇰🇷"), # Flag for South Korea + # LAME ("🇸🇸", ""), # Flag for South Sudan + # ("🇪🇸", "🇪🇸"), # Flag for Spain + # LAME ("🇱🇰", ""), # Flag for Sri Lanka + # LAME ("🇧🇱", ""), # Flag for St. Barthélemy + # LAME ("🇸🇭", ""), # Flag for St. Helena + # LAME ("🇰🇳", ""), # Flag for St. Kitts & Nevis + # LAME ("🇱🇨", ""), # Flag for St. Lucia + # LAME ("🇲🇫", ""), # Flag for St. Martin + # LAME ("🇵🇲", ""), # Flag for St. Pierre & Miquelon + # LAME ("🇻🇨", ""), # Flag for St. Vincent & Grenadines + # LAME ("🇸🇩", ""), # Flag for Sudan + # LAME ("🇸🇷", ""), # Flag for Suriname + # LAME ("🇸🇯", ""), # Flag for Svalbard & Jan Mayen + # LAME ("🇸🇿", ""), # Flag for Swaziland + # ("🇸🇪", "🇸🇪"), # Flag for Sweden + # ("🇨🇭", "🇨🇭"), # Flag for Switzerland + # LAME ("🇸🇾", ""), # Flag for Syria + # LAME ("🇹🇼", ""), # Flag for Taiwan + # LAME ("🇹🇯", ""), # Flag for Tajikistan + # LAME ("🇹🇿", ""), # Flag for Tanzania + # LAME ("🇹🇭", ""), # Flag for Thailand + # LAME ("🇹🇱", ""), # Flag for Timor-Leste + # LAME ("🇹🇬", ""), # Flag for Togo + # LAME ("🇹🇰", ""), # Flag for Tokelau + # LAME ("🇹🇴", ""), # Flag for Tonga + # LAME ("🇹🇹", ""), # Flag for Trinidad & Tobago + # LAME ("🇹🇦", ""), # Flag for Tristan Da Cunha + # LAME ("🇹🇳", ""), # Flag for Tunisia + # ("🇹🇷", "🇹🇷"), # Flag for Turkey + # LAME ("🇹🇲", ""), # Flag for Turkmenistan + # LAME ("🇹🇨", ""), # Flag for Turks & Caicos Islands + # LAME ("🇹🇻", ""), # Flag for Tuvalu + # LAME ("🇺🇬", ""), # Flag for Uganda + # LAME ("🇺🇦", ""), # Flag for Ukraine + # LAME ("🇦🇪", ""), # Flag for United Arab Emirates + # ("🇬🇧", "🇬🇧"), # Flag for United Kingdom + # ("🇺🇸", "🇺🇸"), # Flag for United States + # LAME ("🇺🇾", ""), # Flag for Uruguay + # LAME ("🇺🇲", ""), # Flag for U.S. Outlying Islands + # LAME ("🇻🇮", ""), # Flag for U.S. Virgin Islands + # LAME ("🇺🇿", ""), # Flag for Uzbekistan + # LAME ("🇻🇺", ""), # Flag for Vanuatu + # ("🇻🇦", "🇻🇦"), # Flag for Vatican City + # LAME ("🇻🇪", ""), # Flag for Venezuela + # ("🇻🇳", "🇻🇳"), # Flag for Vietnam + # LAME ("🇼🇫", ""), # Flag for Wallis & Futuna + # LAME ("🇪🇭", ""), # Flag for Western Sahara + # LAME ("🇾🇪", ""), # Flag for Yemen + # LAME ("🇿🇲", ""), # Flag for Zambia + # LAME ("🇿🇼", ""), # Flag for Zimbabwe + # LAME ("🔃", ""), # Clockwise Downwards and Upwards Open Circle Arrows + # LAME ("🔄", ""), # Anticlockwise Downwards and Upwards Open Circle Arrows + # LAME ("🔙", ""), # Back With Leftwards Arrow Above + # LAME ("🔚", ""), # End With Leftwards Arrow Above + # LAME ("🔛", ""), # On With Exclamation Mark With Left Right Arrow Above + # LAME ("🔜", ""), # Soon With Rightwards Arrow Above + # LAME ("🔝", ""), # Top With Upwards Arrow Above + # LAME ("🔰", ""), # Japanese Symbol for Beginner + ("🔮", "🔮"), # Crystal Ball + # LAME ("🔯", ""), # Six Pointed Star With Middle Dot + # LAME ("✅", ""), # White Heavy Check Mark + ("❌", "❌"), # Cross Mark + # LAME ("❎", ""), # Negative Squared Cross Mark + # LAME ("➕", ""), # Heavy Plus Sign + # LAME ("➖", ""), # Heavy Minus Sign + # LAME ("➗", ""), # Heavy Division Sign + # LAME ("➰", ""), # Curly Loop + # LAME ("➿", ""), # Double Curly Loop + ("❓", "❓"), # Black Question Mark Ornament + # TOO SIMILAR ("❔", ""), # White Question Mark Ornament + # TOO SIMILAR ("❕", ""), # White Exclamation Mark Ornament + # USED BY UI ("💯", ""), # Hundred Points Symbol // Speaker tab + ("🔞", "🔞"), # No One Under Eighteen Symbol + # LAME ("🔠", ""), # Input Symbol for Latin Capital Letters + # LAME ("🔡", ""), # Input Symbol for Latin Small Letters + # LAME ("🔢", ""), # Input Symbol for Numbers + # LAME ("🔣", ""), # Input Symbol for Symbols + # LAME ("🔤", ""), # Input Symbol for Latin Letters + # LAME ("🅰️", ""), # Negative Squared Latin Capital Letter A + # LAME ("🆎", ""), # Negative Squared AB + # LAME ("🅱️", ""), # Negative Squared Latin Capital Letter B + # LAME ("🆑", ""), # Squared CL + ("🆒", "🆒"), # Squared Cool + # LAME ("🆓", ""), # Squared Free + # LAME ("🆔", ""), # Squared ID + # LAME ("🆕", ""), # Squared New + # LAME ("🆖", ""), # Squared NG + # LAME ("🅾️", ""), # Negative Squared Latin Capital Letter O + ("🆗", "🆗"), # Squared OK + ("🆘", "🆘"), # Squared SOS + # LAME ("🆙", ""), # Squared Up With Exclamation Mark + # LAME ("🆚", ""), # Squared Vs + # LAME ("🈁", ""), # Squared Katakana Koko + # LAME ("🈂️", ""), # Squared Katakana Sa + # LAME ("🈷️", ""), # Squared CJK Unified Ideograph-6708 + # LAME ("🈶", ""), # Squared CJK Unified Ideograph-6709 + # LAME ("🉐", ""), # Circled Ideograph Advantage + # LAME ("🈹", ""), # Squared CJK Unified Ideograph-5272 + # LAME ("🈲", ""), # Squared CJK Unified Ideograph-7981 + # LAME ("🉑", ""), # Circled Ideograph Accept + # LAME ("🈸", ""), # Squared CJK Unified Ideograph-7533 + # LAME ("🈴", ""), # Squared CJK Unified Ideograph-5408 + # LAME ("🈳", ""), # Squared CJK Unified Ideograph-7a7a + # LAME ("🈺", ""), # Squared CJK Unified Ideograph-55b6 + # LAME ("🈵", ""), # Squared CJK Unified Ideograph-6e80 + # LAME ("🔶", ""), # Large Orange Diamond + # LAME ("🔷", ""), # Large Blue Diamond + # LAME ("🔸", ""), # Small Orange Diamond + # LAME ("🔹", ""), # Small Blue Diamond + # LAME ("🔺", ""), # Up-Pointing Red Triangle + # LAME ("🔻", ""), # Down-Pointing Red Triangle + # LAME ("💠", ""), # Diamond Shape With a Dot Inside + # LAME ("🔘", ""), # Radio Button + # LAME ("🔲", ""), # Black Square Button + # LAME ("🔳", ""), # White Square Button + # LAME ("🔴", ""), # Large Red Circle + # LAME ("🔵", ""), # Large Blue Circle + # Unicode Version 6.1 + # TOO SIMILAR ("😀", ""), # Grinning Face + # TOO SIMILAR ("😗", ""), # Kissing Face + ("😙", "😙"), # Kissing Face With Smiling Eyes + ("😑", "😑"), # Expressionless Face + ("😮", "😮"), # Face With Open Mouth + # TOO SIMILAR ("😯", ""), # Hushed Face + ("😴", "😴"), # Sleeping Face + ("😛", "😛"), # Face With Stuck-Out Tongue + # TOO SIMILAR ("😕", ""), # Confused Face + # TOO SIMILAR ("😟", ""), # Worried Face + # TOO SIMILAR ("😦", ""), # Frowning Face With Open Mouth + ("😧", "😧"), # Anguished Face + ("😬", "😬"), # Grimacing Face + # Unicode Version 7.0 + # TOO SIMILAR ("🙂", ""), # Slightly Smiling Face + # TOO SIMILAR ("🙁", ""), # Slightly Frowning Face + ("🕵", "🕵"), # Sleuth or Spy + # LAME ("🗣", ""), # Speaking Head in Silhouette + # LAME ("🕴", ""), # Man in Business Suit Levitating + ("🖕", "🖕"), # Reversed Hand With Middle Finger Extended + ("🖖", "🖖"), # Raised Hand With Part Between Middle and Ring Fingers + # TOO SIMILAR ("🖐", ""), # Raised Hand With Fingers Splayed + ("👁", "👁"), # Eye + # LAME ("🕳", ""), # Hole + # LAME ("🗯", ""), # Right Anger Bubble + ("🕶", "🕶"), # Dark Sunglasses + ("🛍", "🛍"), # Shopping Bags + ("🐿", "🐿"), # Chipmunk + ("🕊", "🕊"), # Dove of Peace + ("🕷", "🕷"), # Spider + # LAME ("🕸", ""), # Spider Web + # LAME ("🏵", ""), # Rosette + ("🌶", "🌶"), # Hot Pepper + # LAME ("🍽", ""), # Fork and Knife With Plate + # LAME ("🗺", ""), # World Map + # LAME ("🏔", ""), # Snow Capped Mountain + # LAME ("🏕", ""), # Camping + # LAME ("🏖", ""), # Beach With Umbrella + # LAME ("🏜", ""), # Desert + # LAME ("🏝", ""), # Desert Island + # LAME ("🏞", ""), # National Park + # LAME ("🏟", ""), # Stadium + ("🏛", "🏛"), # Classical Building + # LAME ("🏗", ""), # Building Construction + # LAME ("🏘", ""), # House Buildings + # LAME ("🏙", ""), # Cityscape + # LAME ("🏚", ""), # Derelict House Building + # LAME ("🖼", ""), # Frame With Picture + ("🛢", "🛢"), # Oil Drum + # LAME ("🛣", ""), # Motorway + # LAME ("🛤", ""), # Railway Track + # LAME ("🛳", ""), # Passenger Ship + # LAME ("🛥", ""), # Motor Boat + # LAME ("🛩", ""), # Small Airplane + # LAME ("🛫", ""), # Airplane Departure + # LAME ("🛬", ""), # Airplane Arriving + # LAME ("🛰", ""), # Satellite + ("🛎", "🛎"), # Bellhop Bell + # LAME ("🛌", ""), # Sleeping Accommodation + # LAME ("🛏", ""), # Bed + # LAME ("🛋", ""), # Couch and Lamp + ("🕰", "🕰"), # Mantelpiece Clock + ("🌡", "🌡"), # Thermometer + ("🌤", "🌤"), # White Sun With Small Cloud + # LAME ("🌥", ""), # White Sun Behind Cloud + # LAME ("🌦", ""), # White Sun Behind Cloud With Rain + ("🌧", "🌧"), # Cloud With Rain + # LAME ("🌨", ""), # Cloud With Snow + ("🌩", "🌩"), # Cloud With Lightning + ("🌪", "🌪"), # Cloud With Tornado + ("🌫", "🌫"), # Fog + ("🌬", "🌬"), # Wind Blowing Face + ("🎖", "🎖"), # Military Medal + ("🎗", "🎗"), # Reminder Ribbon + ("🎞", "🎞"), # Film Frames + # LAME ("🎟", ""), # Admission Tickets + ("🏷", "🏷"), # Label + # LAME ("🏌", ""), # Golfer + # LAME ("🏋", ""), # Weight Lifter + # LAME ("🏎", ""), # Racing Car + # LAME ("🏍", ""), # Racing Motorcycle + ("🏅", "🏅"), # Sports Medal + ("🕹", "🕹"), # Joystick + # LAME ("⏸", ""), # Double Vertical Bar + # LAME ("⏹", ""), # Black Square for Stop + # LAME ("⏺", ""), # Black Circle for Record + ("🎙", "🎙"), # Studio Microphone + # LAME ("🎚", ""), # Level Slider + # LAME ("🎛", ""), # Control Knobs + ("🖥", "🖥"), # Desktop Computer + ("🖨", "🖨"), # Printer + # LAME ("🖱", ""), # Three Button Mouse + ("🖲", "🖲"), # Trackball + # LAME ("📽", ""), # Film Projector + # LAME ("📸", ""), # Camera With Flash + ("🕯", "🕯"), # Candle + # LAME ("🗞", ""), # Rolled-Up Newspaper + # LAME ("🗳", ""), # Ballot Box With Ballot + ("🖋", "🖋"), # Lower Left Fountain Pen + # LAME ("🖊", ""), # Lower Left Ballpoint Pen + # LAME ("🖌", ""), # Lower Left Paintbrush + # LAME ("🖍", ""), # Lower Left Crayon + # LAME ("🗂", ""), # Card Index Dividers + # LAME ("🗒", ""), # Spiral Note Pad + # LAME ("🗓", ""), # Spiral Calendar Pad + # LAME ("🖇", ""), # Linked Paperclips + # LAME ("🗃", ""), # Card File Box + # LAME ("🗄", ""), # File Cabinet + ("🗑", "🗑"), # Wastebasket + # LAME ("🗝", ""), # Old Key + # LAME ("🛠", ""), # Hammer and Wrench + # LAME ("🗜", ""), # Compression + ("🗡", "🗡"), # Dagger Knife + ("🛡", "🛡"), # Shield + ("🏳", "🏳"), # Waving White Flag + ("🏴", "🏴"), # Waving Black Flag + # LAME ("🕉", ""), # Om Symbol + # LAME ("🗨", ""), # Left Speech Bubble + # Unicode Version 8.0 + ("🤗", "🤗"), # Hugging Face + ("🤔", "🤔"), # Thinking Face + ("🙄", "🙄"), # Face With Rolling Eyes + ("🤐", "🤐"), # Zipper-Mouth Face + ("🤓", "🤓"), # Nerd Face + ("🙃", "🙃"), # Upside-Down Face + ("🤒", "🤒"), # Face With Thermometer + ("🤕", "🤕"), # Face With Head-Bandage + ("🤑", "🤑"), # Money-Mouth Face + # LAME ("🏻", ""), # Emoji Modifier Fitzpatrick Type-1-2 + # LAME ("🏼", ""), # Emoji Modifier Fitzpatrick Type-3 + # LAME ("🏽", ""), # Emoji Modifier Fitzpatrick Type-4 + # LAME ("🏾", ""), # Emoji Modifier Fitzpatrick Type-5 + # LAME ("🏿", ""), # Emoji Modifier Fitzpatrick Type-6 + ("🤘", "🤘"), # Sign of the Horns + ("📿", "📿"), # Prayer Beads + ("🤖", "🤖"), # Robot Face + ("🦁", "🦁"), # Lion Face + ("🦄", "🦄"), # Unicorn Face + # LAME ("🦃", ""), # Turkey + ("🦀", "🦀"), # Crab + # LAME ("🦂", ""), # Scorpion + ("🧀", "🧀"), # Cheese Wedge + ("🌭", "🌭"), # Hot Dog + ("🌮", "🌮"), # Taco + # LAME ("🌯", ""), # Burrito + ("🍿", "🍿"), # Popcorn + ("🍾", "🍾"), # Bottle With Popping Cork + # LAME ("🏺", ""), # Amphora + # LAME ("🛐", ""), # Place of Worship + # OFFENSIVE ("🕋", ""), # Kaaba + # OFFENSIVE ("🕌", ""), # Mosque + # OFFENSIVE ("🕍", ""), # Synagogue + # OFFENSIVE ("🕎", ""), # Menorah With Nine Branches + ("🏏", "🏏"), # Cricket Bat and Ball + ("🏐", "🏐"), # Volleyball + # TOO SIMILAR ("🏑", ""), # Field Hockey Stick and Ball + # TOO SIMILAR ("🏒", ""), # Ice Hockey Stick and Puck + ("🏓", "🏓"), # Table Tennis Paddle and Ball + # TOO SIMILAR ("🏸", ""), # Badminton Racquet and Shuttlecock + ("🏹", "🏹"), # Bow and Arrow +) diff --git a/participants/management/commands/convertteamnames.py b/tabbycat/participants/management/commands/convertteamnames.py similarity index 71% rename from participants/management/commands/convertteamnames.py rename to tabbycat/participants/management/commands/convertteamnames.py index a685dfb89d0..59e6ebf61cc 100644 --- a/participants/management/commands/convertteamnames.py +++ b/tabbycat/participants/management/commands/convertteamnames.py @@ -1,5 +1,6 @@ from utils.management.base import TournamentCommand + class Command(TournamentCommand): help = "Removes institution codes from team names and enables 'use institution prefix' on them. " \ @@ -10,19 +11,22 @@ class Command(TournamentCommand): def add_arguments(self, parser): super(Command, self).add_arguments(parser) - parser.add_argument("--dry-run", action="store_true", help="Show what it would convert, but do not actually convert") + parser.add_argument("--dry-run", action="store_true", + help="Show what it would convert, but do not actually convert") def handle_tournament(self, tournament, **options): for team in tournament.team_set.all(): if team.reference.startswith(team.institution.code + " "): new_reference = team.reference[len(team.institution.code):].strip() - self.stdout.write("{verb} team {!r} from {} to {!r}".format(team.reference, team.institution.code, new_reference, - verb="Would rename" if options["dry_run"] else "Renaming")) + self.stdout.write("{verb} team {!r} from {} to {!r}".format( + team.reference, team.institution.code, new_reference, + verb="Would rename" if options["dry_run"] else "Renaming")) if options["dry_run"]: team.reference = new_reference team.use_institution_prefix = True team.save() else: - self.stdout.write("{verb} team {!r} from {} alone".format(team.reference, team.institution.code, - verb="Would leave" if options["dry_run"] else "Leaving")) + self.stdout.write("{verb} team {!r} from {} alone".format( + team.reference, team.institution.code, + erb="Would leave" if options["dry_run"] else "Leaving")) diff --git a/tabbycat/participants/management/commands/resaveteams.py b/tabbycat/participants/management/commands/resaveteams.py new file mode 100644 index 00000000000..294d7f90237 --- /dev/null +++ b/tabbycat/participants/management/commands/resaveteams.py @@ -0,0 +1,16 @@ +from utils.management.base import TournamentCommand + + +class Command(TournamentCommand): + + help = "Resaves all teams which updates their short and long name fields. " \ + "This shouldn't generally be necessary, because the names are " \ + "auto-populated whenever institutions and teams are saved, but it " \ + "can be used when there was a mishap with team names." + + def handle_tournament(self, tournament, **options): + for team in tournament.team_set.all(): + old_names = team.long_name + " (" + team.short_name + ")" + team.save() + new_names = team.long_name + " (" + team.short_name + ")" + self.stdout.write("Resaved %s as %s" % (old_names, new_names)) diff --git a/participants/migrations/0001_initial.py b/tabbycat/participants/migrations/0001_initial.py similarity index 100% rename from participants/migrations/0001_initial.py rename to tabbycat/participants/migrations/0001_initial.py diff --git a/participants/migrations/0002_auto_20160103_1927.py b/tabbycat/participants/migrations/0002_auto_20160103_1927.py similarity index 100% rename from participants/migrations/0002_auto_20160103_1927.py rename to tabbycat/participants/migrations/0002_auto_20160103_1927.py diff --git a/participants/migrations/0003_auto_20160109_1834.py b/tabbycat/participants/migrations/0003_auto_20160109_1834.py similarity index 100% rename from participants/migrations/0003_auto_20160109_1834.py rename to tabbycat/participants/migrations/0003_auto_20160109_1834.py diff --git a/participants/migrations/0004_auto_20160112_1348.py b/tabbycat/participants/migrations/0004_auto_20160112_1348.py similarity index 100% rename from participants/migrations/0004_auto_20160112_1348.py rename to tabbycat/participants/migrations/0004_auto_20160112_1348.py diff --git a/participants/migrations/0005_auto_20160112_1448.py b/tabbycat/participants/migrations/0005_auto_20160112_1448.py similarity index 100% rename from participants/migrations/0005_auto_20160112_1448.py rename to tabbycat/participants/migrations/0005_auto_20160112_1448.py diff --git a/participants/migrations/0006_auto_20160127_2233.py b/tabbycat/participants/migrations/0006_auto_20160127_2233.py similarity index 100% rename from participants/migrations/0006_auto_20160127_2233.py rename to tabbycat/participants/migrations/0006_auto_20160127_2233.py diff --git a/participants/migrations/0007_remove_team_emoji_seq.py b/tabbycat/participants/migrations/0007_remove_team_emoji_seq.py similarity index 100% rename from participants/migrations/0007_remove_team_emoji_seq.py rename to tabbycat/participants/migrations/0007_remove_team_emoji_seq.py diff --git a/participants/migrations/0008_auto_20160128_2152.py b/tabbycat/participants/migrations/0008_auto_20160128_2152.py similarity index 100% rename from participants/migrations/0008_auto_20160128_2152.py rename to tabbycat/participants/migrations/0008_auto_20160128_2152.py diff --git a/participants/migrations/0009_auto_20160201_2012.py b/tabbycat/participants/migrations/0009_auto_20160201_2012.py similarity index 100% rename from participants/migrations/0009_auto_20160201_2012.py rename to tabbycat/participants/migrations/0009_auto_20160201_2012.py diff --git a/participants/migrations/0010_auto_20160202_1955.py b/tabbycat/participants/migrations/0010_auto_20160202_1955.py similarity index 100% rename from participants/migrations/0010_auto_20160202_1955.py rename to tabbycat/participants/migrations/0010_auto_20160202_1955.py diff --git a/participants/migrations/0011_auto_20160228_1838.py b/tabbycat/participants/migrations/0011_auto_20160228_1838.py similarity index 100% rename from participants/migrations/0011_auto_20160228_1838.py rename to tabbycat/participants/migrations/0011_auto_20160228_1838.py diff --git a/participants/migrations/0012_auto_20160402_1609.py b/tabbycat/participants/migrations/0012_auto_20160402_1609.py similarity index 100% rename from participants/migrations/0012_auto_20160402_1609.py rename to tabbycat/participants/migrations/0012_auto_20160402_1609.py diff --git a/participants/migrations/0013_auto_20160507_1521.py b/tabbycat/participants/migrations/0013_auto_20160507_1521.py similarity index 100% rename from participants/migrations/0013_auto_20160507_1521.py rename to tabbycat/participants/migrations/0013_auto_20160507_1521.py diff --git a/tabbycat/participants/migrations/0014_auto_20160621_1129.py b/tabbycat/participants/migrations/0014_auto_20160621_1129.py new file mode 100644 index 00000000000..bf54179ca43 --- /dev/null +++ b/tabbycat/participants/migrations/0014_auto_20160621_1129.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-06-21 11:29 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('participants', '0013_auto_20160507_1521'), + ] + + operations = [ + migrations.AlterField( + model_name='team', + name='division', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='divisions.Division'), + ), + ] diff --git a/tabbycat/participants/migrations/0015_add_team_short_name_add_team_long_name.py b/tabbycat/participants/migrations/0015_add_team_short_name_add_team_long_name.py new file mode 100644 index 00000000000..25f7957e24f --- /dev/null +++ b/tabbycat/participants/migrations/0015_add_team_short_name_add_team_long_name.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-08 00:46 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('participants', '0014_auto_20160621_1129'), + ] + + operations = [ + migrations.AddField( + model_name='team', + name='long_name', + field=models.CharField(default="Team names aren't set; please finish applying database migrations", help_text='The full name of the team, including institution name. This is autogenerated, so do not edit this yourself.', max_length=200, verbose_name='Long name (autogenerated)'), + preserve_default=False, + ), + migrations.AddField( + model_name='team', + name='short_name', + field=models.CharField(default='No short name, please finish migrations', help_text='The name shown in the draw, including institution name. This is autogenerated, so do not edit this yourself.', max_length=50, verbose_name='Short name (autogenerated)'), + preserve_default=False, + ), + ] diff --git a/tabbycat/participants/migrations/0016_populate_team_names.py b/tabbycat/participants/migrations/0016_populate_team_names.py new file mode 100644 index 00000000000..e997cb8f7a7 --- /dev/null +++ b/tabbycat/participants/migrations/0016_populate_team_names.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +# This is a data migration. It was written manually and its purpose is to +# populate the fields added by the migration +# 0015_add_team_short_name_add_team_long_name. + +from __future__ import unicode_literals + +from django.db import migrations + + +def _construct_short_name(team): + institution = team.institution + name = team.short_reference or team.reference + if team.use_institution_prefix: + if institution.code: + return institution.code + " " + name + else: + return institution.abbreviation + " " + name + else: + return name + +def _construct_long_name(team): + institution = team.institution + if team.use_institution_prefix: + return institution.name + " " + team.reference + else: + return team.reference + +def populate_team_names(apps, schema_editor): + Team = apps.get_model("participants", "Team") + for team in Team.objects.all(): + team.short_name = _construct_short_name(team) + team.long_name = _construct_long_name(team) + team.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('participants', '0015_add_team_short_name_add_team_long_name'), + ] + + operations = [ + migrations.RunPython(populate_team_names), + ] diff --git a/tabbycat/participants/migrations/0017_auto_20160708_1054.py b/tabbycat/participants/migrations/0017_auto_20160708_1054.py new file mode 100644 index 00000000000..adb921ff06a --- /dev/null +++ b/tabbycat/participants/migrations/0017_auto_20160708_1054.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-08 10:54 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('participants', '0016_populate_team_names'), + ] + + operations = [ + migrations.AlterField( + model_name='team', + name='long_name', + field=models.CharField(editable=False, help_text='The full name of the team, including institution name. (This is autogenerated.)', max_length=200, verbose_name='Long name'), + ), + migrations.AlterField( + model_name='team', + name='short_name', + field=models.CharField(editable=False, help_text='The name shown in the draw, including institution name. (This is autogenerated.)', max_length=50, verbose_name='Short name'), + ), + ] diff --git a/tabbycat/participants/migrations/0018_auto_20160712_1955.py b/tabbycat/participants/migrations/0018_auto_20160712_1955.py new file mode 100644 index 00000000000..e4198e34094 --- /dev/null +++ b/tabbycat/participants/migrations/0018_auto_20160712_1955.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-12 19:55 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('participants', '0017_auto_20160708_1054'), + ] + + operations = [ + migrations.AlterModelOptions( + name='person', + options={}, + ), + ] diff --git a/tabbycat/participants/migrations/0019_allow_blank_team_reference.py b/tabbycat/participants/migrations/0019_allow_blank_team_reference.py new file mode 100644 index 00000000000..1e8995e41c3 --- /dev/null +++ b/tabbycat/participants/migrations/0019_allow_blank_team_reference.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.8 on 2016-08-14 15:50 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('participants', '0018_auto_20160712_1955'), + ] + + operations = [ + migrations.AlterField( + model_name='team', + name='reference', + field=models.CharField(blank=True, help_text='Do not include institution name (see "uses institutional prefix" below)', max_length=150, verbose_name='Full name/suffix'), + ), + migrations.AlterField( + model_name='team', + name='short_reference', + field=models.CharField(blank=True, help_text='The name shown in the draw. Do not include institution name (see "uses institutional prefix" below)', max_length=35, verbose_name='Short name/suffix'), + ), + ] diff --git a/results/tests/__init__.py b/tabbycat/participants/migrations/__init__.py similarity index 100% rename from results/tests/__init__.py rename to tabbycat/participants/migrations/__init__.py diff --git a/participants/models.py b/tabbycat/participants/models.py similarity index 66% rename from participants/models.py rename to tabbycat/participants/models.py index b13757faefb..1f11334781a 100644 --- a/participants/models.py +++ b/tabbycat/participants/models.py @@ -1,12 +1,19 @@ +import logging +from warnings import warn + +from django.core.cache import cache +from django.core.exceptions import ValidationError from django.db import models -from django.utils.functional import cached_property from django.db.models import signals -from django.core.exceptions import ObjectDoesNotExist -from django.core.cache import cache from django.utils.functional import cached_property + from tournaments.models import Round +from utils.managers import LookupByNameFieldsMixin + from .emoji import EMOJI_LIST +logger = logging.getLogger(__name__) + class Region(models.Model): name = models.CharField(db_index=True, max_length=100) @@ -16,28 +23,17 @@ def __str__(self): return '%s' % (self.name) -class InstitutionManager(models.Manager): - def lookup(self, name, **kwargs): - """Queries for an institution with matching name in any of the three - name fields.""" - for field in ('code', 'name', 'abbreviation'): - try: - kwargs[field] = name - return self.get(**kwargs) - except ObjectDoesNotExist: - kwargs.pop(field) - raise self.model.DoesNotExist("No institution matching '%s'" % name) +class InstitutionManager(LookupByNameFieldsMixin, models.Manager): + name_fields = ['code', 'name', 'abbreviation'] class Institution(models.Model): name = models.CharField( max_length=100, - help_text= - "The institution's full name, e.g., \"University of Cambridge\", \"Victoria University of Wellington\"") + help_text="The institution's full name, e.g., \"University of Cambridge\", \"Victoria University of Wellington\"") code = models.CharField( max_length=20, - help_text= - "What the institution is typically called for short, e.g., \"Cambridge\", \"Vic Wellington\"") + help_text="What the institution is typically called for short, e.g., \"Cambridge\", \"Vic Wellington\"") abbreviation = models.CharField( max_length=8, default="", @@ -48,7 +44,7 @@ class Institution(models.Model): @property def venue_preferences(self): - return self.institutionvenuepreference_set.all().order_by('-priority') + return self.institutionvenueconstraint_set.all().order_by('-priority') class Meta: unique_together = [('name', 'code')] @@ -65,6 +61,17 @@ def short_code(self): return self.code[:5] +def update_team_names_from_institution(sender, instance, created, **kwargs): + teams = instance.team_set.all() + if len(teams) > 0: + logger.info("Updating names of all %d teams from institution %s" % (len(teams), instance.name,)) + for team in teams: + team.save() + +# Update all team names when an institution is saved +signals.post_save.connect(update_team_names_from_institution, sender=Institution) + + class Person(models.Model): name = models.CharField(max_length=40, db_index=True) barcode_id = models.IntegerField(blank=True, null=True) @@ -72,8 +79,7 @@ class Person(models.Model): phone = models.CharField(max_length=40, blank=True, null=True) novice = models.BooleanField( default=False, - help_text= - "Novice status is indicated on the tab, and may have its own Break Category or Top Speakers Tab") + help_text="Novice status is indicated on the tab, and may have its own Break Category or Top Speakers Tab") checkin_message = models.TextField(blank=True) notes = models.TextField(blank=True, null=True) @@ -81,75 +87,64 @@ class Person(models.Model): GENDER_MALE = 'M' GENDER_FEMALE = 'F' GENDER_OTHER = 'O' - GENDER_CHOICES = ((GENDER_MALE, 'Male'), - (GENDER_FEMALE, 'Female'), - (GENDER_OTHER, 'Other'), ) + GENDER_CHOICES = ((GENDER_MALE, 'Male'), + (GENDER_FEMALE, 'Female'), + (GENDER_OTHER, 'Other')) gender = models.CharField( max_length=1, choices=GENDER_CHOICES, blank=True, null=True, - help_text= - "Gender is displayed in the adjudicator allocation interface, and nowhere else") + help_text="Gender is displayed in the adjudicator allocation interface, and nowhere else") pronoun = models.CharField( max_length=10, blank=True, null=True, - help_text= - "If printing ballots using Tabbycat there is the option to pre-print pronouns") + help_text="If printing ballots using Tabbycat there is the option to pre-print pronouns") @property def has_contact(self): return bool(self.email or self.phone) - class Meta: - ordering = ['name'] +class TeamManager(LookupByNameFieldsMixin, models.Manager): + name_fields = ['short_name', 'long_name'] -class TeamManager(models.Manager): def get_queryset(self): - return super(TeamManager, - self).get_queryset().select_related('institution') - - def lookup(self, name, **kwargs): - """Queries for a team with a matching name.""" - # TODO could be improved to take in a better range of fields - try: - institution_name, reference = name.rsplit(None, 1) - except: - print("Error in", repr(name)) - raise - institution_name = institution_name.strip() - institution = Institution.objects.lookup(institution_name) - return self.get(institution=institution, reference=reference, **kwargs) + return super().get_queryset().select_related('institution') class Team(models.Model): reference = models.CharField( max_length=150, - verbose_name="Full name or suffix", - help_text= - "Do not include institution name (see \"uses institutional prefix\" below)") + verbose_name="Full name/suffix", + help_text="Do not include institution name (see \"uses institutional prefix\" below)", + blank=True) short_reference = models.CharField( max_length=35, verbose_name="Short name/suffix", - help_text= - "The name shown in the draw. Do not include institution name (see \"uses institutional prefix\" below)") + help_text="The name shown in the draw. Do not include institution name (see \"uses institutional prefix\" below)", + blank=True) + + short_name = models.CharField(max_length=50, editable=False, verbose_name="Short name", + help_text="The name shown in the draw, including institution name. (This is autogenerated.)") + long_name = models.CharField(max_length=200, editable=False, verbose_name="Long name", + help_text="The full name of the team, including institution name. (This is autogenerated.)") + emoji = models.CharField(max_length=2, blank=True, null=True, choices=EMOJI_LIST) institution = models.ForeignKey(Institution) tournament = models.ForeignKey('tournaments.Tournament') - division = models.ForeignKey('tournaments.Division', + division = models.ForeignKey('divisions.Division', blank=True, null=True, on_delete=models.SET_NULL) use_institution_prefix = models.BooleanField( default=False, verbose_name="Uses institutional prefix", - help_text= - "If ticked, a team called \"1\" from Victoria will be shown as \"Victoria 1\" ") + help_text="If ticked, a team called \"1\" from Victoria will be shown as \"Victoria 1\" ") url_key = models.SlugField(blank=True, null=True, unique=True, @@ -184,28 +179,26 @@ class Meta: def __str__(self): return "[{}] {}".format(self.tournament.slug, self.short_name) - @property - def short_name(self): - institution = self.get_cached_institution() - if self.short_reference: - name = self.short_reference + def _construct_short_name(self): + institution = self.institution + reference = self.short_reference or self.reference + if self.use_institution_prefix: + short_name = institution.code or institution.abbreviation + if reference: + short_name += " " + reference + return short_name else: - name = self.reference - if self.use_institution_prefix is True: - if self.institution.code: - return str(institution.code + " " + name) - else: - return str(institution.abbreviation + " " + name) + return reference + + def _construct_long_name(self): + institution = self.institution + if self.use_institution_prefix: + long_name = institution.name + if self.reference: + long_name += " " + self.reference + return long_name else: - return str(name) - - @property - def long_name(self): - institution = self.get_cached_institution() - if self.use_institution_prefix is True: - return str(institution.name + " " + self.reference) - else: - return str(self.reference) + return self.reference @property def region(self): @@ -218,8 +211,7 @@ def break_categories_nongeneral(self): @property def break_categories_str(self): categories = self.break_categories_nongeneral - return "(" + ", ".join(c.name - for c in categories) + ")" if categories else "" + return ", ".join(c.name for c in categories) if categories else "" def break_rank_for_category(self, category): from breakqual.models import BreakingTeam @@ -253,21 +245,26 @@ def get_debates(self, before_round): def debates(self): return self.get_debates(None) - @cached_property + @property def wins_count(self): - from results.models import TeamScore - wins = TeamScore.objects.filter(ballot_submission__confirmed=True, - debate_team__team=self, - win=True).count() - return wins + try: + return self._wins_count + except AttributeError: + from results.models import TeamScore + self._wins_count = TeamScore.objects.filter(ballot_submission__confirmed=True, + debate_team__team=self, + win=True).count() + return self._wins_count @cached_property def speakers(self): - return self.speaker_set.all().select_related('person_ptr') + return self.speaker_set.all() def seen(self, other, before_round=None): - debates = self.get_debates(before_round) - return len([1 for d in debates if other in d]) + queryset = self.debateteam_set.filter(debate__debateteam__team=other) + if before_round: + queryset = queryset.filter(debate__round__seq__lt=before_round) + return queryset.count() def same_institution(self, other): return self.institution_id == other.institution_id @@ -291,6 +288,22 @@ def get_cached_institution(self): cache.set(cached_key, cached_value, None) return cached_value + def clean(self): + # Require reference and short_reference if use_institution_prefix is False + errors = {} + if not self.use_institution_prefix and not self.reference: + errors['reference'] = "Teams must have a full name if they don't use the institutional prefix." + if not self.use_institution_prefix and not self.short_reference: + errors['short_reference'] = "Teams must have a short name if they don't use the institutional prefix." + if errors: + raise ValidationError(errors) + + def save(self, *args, **kwargs): + # Override the short and long names before saving + self.short_name = self._construct_short_name() + self.long_name = self._construct_long_name() + super().save(*args, **kwargs) + def update_team_cache(sender, instance, created, **kwargs): cached_key = "%s_%s_%s" % ('teamid', instance.id, '_institution__object') @@ -374,25 +387,31 @@ def is_unaccredited(self): def region(self): return self.institution.region + def weighted_score(self, feedback_weight): + feedback_score = self._feedback_score() + if feedback_score is None: + feedback_score = 0 + feedback_weight = 0 + return self.test_score * (1 - feedback_weight) + (feedback_weight * feedback_score) + @cached_property def score(self): + warn("Adjudicator.score is inefficient; consider using Adjudicator.weighted_score() instead.", stacklevel=2) if self.tournament: weight = self.tournament.current_round.feedback_weight else: - weight = 1 # For shared ajudicators - - feedback_score = self._feedback_score() - if feedback_score is None: - feedback_score = 0 - weight = 0 - - return self.test_score * (1 - weight) + (weight * feedback_score) + weight = 1 # For shared ajudicators + return self.weighted_score(weight) def _feedback_score(self): - from adjallocation.models import DebateAdjudicator - return self.adjudicatorfeedback_set.filter(confirmed=True).exclude( - source_adjudicator__type=DebateAdjudicator.TYPE_TRAINEE).aggregate( - avg=models.Avg('score'))['avg'] + try: + return self._feedback_score_cache + except AttributeError: + from adjallocation.models import DebateAdjudicator + self._feedback_score_cache = self.adjudicatorfeedback_set.filter(confirmed=True).exclude( + source_adjudicator__type=DebateAdjudicator.TYPE_TRAINEE).aggregate( + avg=models.Avg('score'))['avg'] + return self._feedback_score_cache @property def feedback_score(self): diff --git a/tabbycat/participants/prefetch.py b/tabbycat/participants/prefetch.py new file mode 100644 index 00000000000..fa0c551dde8 --- /dev/null +++ b/tabbycat/participants/prefetch.py @@ -0,0 +1,50 @@ +from django.db.models import Avg, Count + +from adjallocation.models import DebateAdjudicator +from adjfeedback.models import AdjudicatorFeedback +from participants.models import Adjudicator, Team + + +def populate_win_counts(teams): + """Populates the `_win_count` attribute of the teams in `teams`. + Operates in-place.""" + + teams_by_id = {team.id: team for team in teams} + + teams_annotated = Team.objects.filter( + id__in=teams_by_id.keys(), + debateteam__teamscore__ballot_submission__confirmed=True, + debateteam__teamscore__win=True + ).annotate(win_count_annotation=Count('debateteam__teamscore')) + + for team in teams_annotated: + teams_by_id[team.id]._wins_count = team.win_count_annotation + + for team in teams: + if not hasattr(team, '_wins_count'): + team._wins_count = 0 + + +def populate_feedback_scores(adjudicators): + """Populates the `_feedback_score_cache` attribute of the adjudicators + in `adjudicators`. + Operates in-place.""" + + adjs_by_id = {adj.id: adj for adj in adjudicators} + + adjfeedbacks = AdjudicatorFeedback.objects.filter( + adjudicator_id__in=adjs_by_id.keys(), + confirmed=True + ).exclude(source_adjudicator__type=DebateAdjudicator.TYPE_TRAINEE) + + adjs_annotated = Adjudicator.objects.filter( + id__in=adjs_by_id.keys(), + adjudicatorfeedback__in=adjfeedbacks + ).annotate(feedback_score_annotation=Avg('adjudicatorfeedback__score')) + + for adj in adjs_annotated: + adjs_by_id[adj.id]._feedback_score_cache = adj.feedback_score_annotation + + for adj in adjudicators: + if not hasattr(adj, '_feedback_score_cache'): + adj._feedback_score_cache = None diff --git a/tabbycat/participants/templates/adjudicator_record.html b/tabbycat/participants/templates/adjudicator_record.html new file mode 100644 index 00000000000..7a9deaa9a2f --- /dev/null +++ b/tabbycat/participants/templates/adjudicator_record.html @@ -0,0 +1,157 @@ +{% extends "base_vue_table.html" %} +{% load debate_tags %} + +{% block page-subnav-sections %}{% endblock %} + +{% block content %} + +
    + + {% if pref.public_draw or admin_page %} +
    +
    +
    +

    + In This Round + ({{ current_round.name }}) + {% if admin_page and not draw_released %} + (Not Released to Public) + {% endif %} +

    +
    + + {% if draw_released or admin_page %} + {% if debateadjudicator %} + {% with debate=debateadjudicator.debate %} +
      + + {# Position, teams and venue #} +
    • + {{ adjudicator.name }} is + {% if debate.adjudicators|length > 1 %} + {% if debateadjudicator.type == debateadjudicator.TYPE_CHAIR %} + the + {% else %} + a + {% endif %} + {{ debateadjudicator.get_type_display|lower }} + {% endif %} + adjudicating + {{ debate.aff_team.short_name }} + vs + {{ debate.neg_team.short_name }} + in + {% if debate.venue.group %} + {{ debate.venue.group.short_name }} — + {% endif %} + {{ debate.venue.name }}. +
    • + + {# Round start time #} + {% if current_round.starts_at %} +
    • + The round begins at {{ current_round.starts_at }} +
    • + {% endif %} {# current_round.starts_at #} + + {# Adjudicators #} + {% if not pref.no_panellist_position or not pref.no_trainee_position %} +
    • + {% if debate.adjudicators|length > 1 %} + {% with adjudicators=debate.adjudicators %} + Adjudicator{{ adjudicators|length|pluralize }}: + {% for adj, adjtype in adjudicators.with_positions %} + + {{ adj.name }}{% if adjtype == adjudicators.POSITION_CHAIR %} Ⓒ{% elif adjtype == adjudicators.POSITION_TRAINEE %} Ⓣ{% endif %}{% if not forloop.last %},{% endif %} + {% endfor %} + {% endwith %} + {% else %} + There are no panellists or trainees assigned to this debate. + {% endif %} {# debate.adjudicators|length > 1 #} +
    • + {% endif %} {# not pref.no_panellist_position or not pref.no_trainee_position #} + + {# Motions #} + {% if pref.public_motions or admin_page %} +
    • + {% if current_round.motions_released or admin_page %} + {% if not current_round.motions_released %} + Motions are not released to public.
      + {% endif %} + {% if debate.round.motion_set.all|length == 1 %} + Motion: {{ debate.round.motion_set.first.text }} + {% else %} + {% for motion in debate.round.motion_set.all %} + Motion {{ motion.seq }}: {{ motion.text }}
      + {% endfor %} + {% endif %} + {% else %} {# elif not (current_round.motions_released or admin_page) #} + The motion(s) for this round haven't yet been released. + {% endif %} {# current_round.motions_released or admin_page #} +
    • + {% endif %} {# pref.public_motions or admin_page #} +
    + {% endwith %} + + {% else %} {# elif not debateadjudicator #} +
    + {{ adjudicator.name }} is not adjudicating this round. +
    + {% endif %} {# debateadjudicator #} + + {% else %} {# elif not (draw_released or admin_page) #} +
    + The draw for this round hasn't yet been released. +
    + {% endif %} {# draw_released or admin_page #} +
    +
    + {% endif %} {# pref.public_draw or admin_page #} + + {% if pref.public_participants or admin_page %} +
    +
    +
    +

    About {{ adjudicator.name }}

    +
    + +
      + +
    • + Institution: + {{ adjudicator.institution.name }} +
    • + {% if adjudicator.institution.region %} +
    • + Region: + {{ adjudicator.institution.region.name }} +
    • + {% endif %} + + {% if adjudicator.independent %} +
    • + {{ adjudicator.name }} is an independent adjudicator. +
    • + {% endif %} + + {% if adjudicator.adj_core %} +
    • + {{ adjudicator.name }} is on the adjudication core. +
    • + {% endif %} +
    +
    +
    + {% endif %} {# pref.public_participants or admin_page #} + +
    + + {% if pref.feedback_progress or admin_page %} + {% include "feedback_progress_panel.html" with participant_name=adjudicator.name %} + {% endif %} + + {% if pref.public_results or admin_page %} + {{ block.super }} {# this is the Vue table, which is populated with previous debates #} + {% endif %} + +{% endblock content %} diff --git a/tabbycat/participants/templates/confirm_shifts.html b/tabbycat/participants/templates/confirm_shifts.html new file mode 100644 index 00000000000..33eade2d8ca --- /dev/null +++ b/tabbycat/participants/templates/confirm_shifts.html @@ -0,0 +1,44 @@ +{% extends "base.html" %} +{% load debate_tags %} +{% load add_field_css %} + +{% block head-title %}Shift Check-In for {{ adjudicator.name }}{% endblock %} +{% block page-title %}Shift Check-In for {{ adjudicator.name }}{% endblock %} + +{% block content %} + +
    + {% csrf_token %} + {{ formset.management_form }} + +
    + {% for form in formset %} +
    +
    +
    +

    + {{ form.instance.debate.round.abbreviation }}: + {{ form.instance.debate.division.venue_group }} @ + {{ form.instance.debate.division.time_slot }} +

    +
    +
    +
    + {{ form }} +
    +
    +
    +
    + {% endfor %} +
    +
    +
    + +
    +
    + +
    + +{% endblock content %} diff --git a/tabbycat/participants/templates/feedback_progress_panel.html b/tabbycat/participants/templates/feedback_progress_panel.html new file mode 100644 index 00000000000..f5a5ef9e6e0 --- /dev/null +++ b/tabbycat/participants/templates/feedback_progress_panel.html @@ -0,0 +1,60 @@ +{# This snippet is used as part of the team_record.html and adjudicator_record.html templates. #} + +
    +
    +
    +
    +

    Feedback Returns

    +
    +
      + {% for tracker in feedback_progress.trackers %} + {% if tracker.fulfilled %} +
    • + {{ tracker.round.name }} + + Has submitted feedback for + {{ tracker.submission.adjudicator.name }} of + {{ tracker.submission.adjudicator.institution.code }} +
    • + {% elif tracker.expected and tracker.count == 0 %} +
    • + {{ tracker.round.name }} + + Has not submitted feedback for + {% for target in tracker.acceptable_targets %} + {% if not forloop.first and forloop.last %}or{% endif %} + {{ target.name }} of + {{ target.institution.code }}{% if not forloop.last %},{% endif %} + {% endfor %} + {% if tracker.acceptable_targets|length > 1 %} + (whoever gave the oral adjudication) + {% endif %} +
    • + {% elif tracker.expected %} +
    • + {{ tracker.round.name }} + + More feedback submissions than expected for this debate: + {% for submission in tracker.acceptable_submissions %} + {{ submission.adjudicator.name }} of + {{ submission.adjudicator.institution.code }}{% if not forloop.last %},{% endif %} + {% endfor %} +
    • + {% else %} {# if not tracker.fulfilled and not tracker.expected #} +
    • + {{ tracker.round.name }} + + Unexpected feedback submission for + {{ tracker.submission.adjudicator.name }} of + {{ tracker.submission.adjudicator.institution.code }} +
    • + {% endif %} + {% empty %} +
    • + {{ participant_name }} doesn't have any feedback to submit. +
    • + {% endfor %} +
    +
    +
    +
    \ No newline at end of file diff --git a/tabbycat/participants/templates/team_record.html b/tabbycat/participants/templates/team_record.html new file mode 100644 index 00000000000..034c543651c --- /dev/null +++ b/tabbycat/participants/templates/team_record.html @@ -0,0 +1,161 @@ +{% extends "base_vue_table.html" %} +{% load debate_tags %} + +{% block page-subnav-sections %}{% endblock %} + +{% block content %} + +
    + + {% if pref.public_draw or admin_page %} +
    +
    +
    +

    + In This Round + ({{ current_round.name }}) + {% if admin_page and not draw_released %} + (Not Released to Public) + {% endif %} +

    +
    + + {% if draw_released or admin_page %} + {% if debateteam %} +
      + + {# Position, opponent and venue #} +
    • + {{ team.short_name }} is debating + {% if debateteam.position != debateteam.POSITION_UNALLOCATED %} + as the {{ debateteam.get_position_display|lower }} team + {% endif %} + against + + {{ debateteam.opponent.team.short_name }} + in + {% if debate.venue.group %} + {{ debate.venue.group.short_name }} — + {% endif %} + {{ debateteam.debate.venue.name }}. +
    • + + {# Round start time #} + {% if current_round.starts_at %} +
    • + The round begins at {{ current_round.starts_at }} +
    • + {% endif %} {# current_round.starts_at #} + + {# Adjudicators #} +
    • + {% with adjudicators=debateteam.debate.adjudicators %} + Adjudicator{{ adjudicators|length|pluralize }}: + {% for adj, adjtype in adjudicators.with_positions %} + + {{ adj.name }}{% if adjtype == adjudicators.POSITION_CHAIR %} Ⓒ{% elif adjtype == adjudicators.POSITION_TRAINEE %} Ⓣ{% endif %}{% if not forloop.last %},{% endif %} + {% endfor %} + {% endwith %} +
    • + + {# Motions #} + {% if pref.public_motions or admin_page %} +
    • + {% if current_round.motions_released or admin_page %} + {% if not current_round.motions_released %} + Motions are not released to public.
      + {% endif %} + {% if debateteam.debate.round.motion_set.all|length == 1 %} + Motion: {{ debateteam.debate.round.motion_set.first.text }} + {% else %} + {% for motion in debateteam.debate.round.motion_set.all %} + Motion {{ motion.seq }}: {{ motion.text }}
      + {% endfor %} + {% endif %} + {% else %} {# elif not (current_round.motions_released or admin_page) #} + The motion(s) for this round haven't yet been released. + {% endif %} {# current_round.motions_released or admin_page #} +
    • + {% endif %} {# pref.public_motions or admin_page #} +
    + + {% else %} {# elif not debateteam #} +
    + {{ team.short_name }} does not have a debate this round. +
    + {% endif %} {# debateteam #} + + {% else %} {# elif not (draw_released or admin_page) #} +
    + The draw for this round hasn't yet been released. +
    + {% endif %} {# draw_released or admin_page #} +
    +
    + {% endif %} {# pref.public_draw or admin_page #} + + {% if pref.public_participants or admin_page %} +
    +
    +
    +

    About {{ team.short_name }}

    +
    + +
      + {% if team.reference != team.short_reference %} +
    • + Full name: + {{ team.long_name }} +
    • + {% endif %} + +
    • + Speakers: + {% for speaker in team.speakers %} + {{ speaker.name }}{% if not forloop.last %}, {% endif %} + {% endfor %} +
    • + + {% if team.division %} +
    • + Division: + {{ team.division.name }} +
    • + {% endif %} + + {% if pref.public_break_categories or admin_page %} +
    • + Eligible for: + {% for category in team.break_categories.all %} + {{ category.name }} Break{% if not forloop.last %}, {% endif %} + {% endfor %} +
    • + {% endif %} {# pref.public_break_categories or admin_page #} + +
    • + Institution: + {{ team.institution.name }} +
    • + {% if team.institution.region %} +
    • + Region: + {{ team.institution.region.name }} +
    • + {% endif %} + +
    +
    +
    + {% endif %} {# pref.public_participants or admin_page #} + +
    + + {% if pref.feedback_progress or admin_page %} + {% include "feedback_progress_panel.html" with participant_name=team.short_name %} + {% endif %} + + {% if pref.public_results or admin_page %} + {{ block.super }} {# this is the Vue table, which is populated with previous results #} + {% endif %} + +{% endblock content %} diff --git a/tabbycat/participants/tests/test_lookup.py b/tabbycat/participants/tests/test_lookup.py new file mode 100644 index 00000000000..aa2678838e0 --- /dev/null +++ b/tabbycat/participants/tests/test_lookup.py @@ -0,0 +1,66 @@ +from django.core.exceptions import ObjectDoesNotExist +from django.test import TestCase + +from tournaments.models import Tournament +from participants.models import Institution, Region, Team + + +class TestParticipantLookup(TestCase): + + def setUp(self): + self.tournament = Tournament.objects.create(slug="main") + self.region = Region.objects.create(tournament=self.tournament) + self.institution = Institution.objects.create(name="An Institution", code="Inst", + abbreviation="In.", region=self.region) + + # team1 uses institution prefix, team2 does not + self.team1 = Team.objects.create(institution=self.institution, reference="The First", + short_reference="1", use_institution_prefix=True, tournament=self.tournament) + self.team2 = Team.objects.create(institution=self.institution, reference="The Second", + short_reference="2", use_institution_prefix=False, tournament=self.tournament) + + def tearDown(self): + self.team1.delete() + self.team2.delete() + self.institution.delete() + self.region.delete() + self.tournament.delete() + + def test_institution_lookup(self): + self.assertEqual(Institution.objects.lookup("An Institution"), self.institution) + self.assertEqual(Institution.objects.lookup("Inst"), self.institution) + self.assertRaises(ObjectDoesNotExist, Institution.objects.lookup, "randomstring") + + def test_team_lookup(self): + self.assertEqual(Team.objects.lookup("An Institution The First"), self.team1) + self.assertEqual(Team.objects.lookup("Inst 1"), self.team1) + self.assertEqual(Team.objects.lookup("The Second"), self.team2) + self.assertEqual(Team.objects.lookup("2"), self.team2) + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "randomstring") + + def test_invalid_team_lookup(self): + # These names are inconsistent with the use_institution_prefix setting, so should fail lookup + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "The First") + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "1") + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "An Institution The Second") + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "Inst 2") + + def test_institution_lookup_with_region(self): + other_region = Region.objects.create(tournament=self.tournament) + self.assertEqual(Institution.objects.lookup("An Institution", region=self.region), self.institution) + self.assertEqual(Institution.objects.lookup("Inst", region=self.region), self.institution) + self.assertRaises(ObjectDoesNotExist, Institution.objects.lookup, "An Institution", region=other_region) + self.assertRaises(ObjectDoesNotExist, Institution.objects.lookup, "Inst", region=other_region) + other_region.delete() + + def test_team_lookup_with_tournament(self): + other_tournament = Tournament.objects.create(slug="other") + self.assertEqual(Team.objects.lookup("An Institution The First", tournament=self.tournament), self.team1) + self.assertEqual(Team.objects.lookup("Inst 1", tournament=self.tournament), self.team1) + self.assertEqual(Team.objects.lookup("The Second", tournament=self.tournament), self.team2) + self.assertEqual(Team.objects.lookup("2", tournament=self.tournament), self.team2) + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "An Institution The First", tournament=other_tournament) + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "Inst 1", tournament=other_tournament) + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "The Second", tournament=other_tournament) + self.assertRaises(ObjectDoesNotExist, Team.objects.lookup, "2", tournament=other_tournament) + other_tournament.delete() diff --git a/participants/tests/test_models.py b/tabbycat/participants/tests/test_models.py similarity index 83% rename from participants/tests/test_models.py rename to tabbycat/participants/tests/test_models.py index 4148f0cc05a..cbb9eccf71f 100644 --- a/participants/tests/test_models.py +++ b/tabbycat/participants/tests/test_models.py @@ -1,10 +1,13 @@ from utils.tests import BaseDebateTestCase -from ..models import Institution, Adjudicator + +from participants.models import Adjudicator, Institution + class TestInstitution(BaseDebateTestCase): def test_objects(self): self.failUnlessEqual(4, Institution.objects.count()) + class TestAdjudicator(BaseDebateTestCase): def test_objects(self): self.failUnlessEqual(8, Adjudicator.objects.count()) diff --git a/tabbycat/participants/tests/test_views.py b/tabbycat/participants/tests/test_views.py new file mode 100644 index 00000000000..a0a35419f63 --- /dev/null +++ b/tabbycat/participants/tests/test_views.py @@ -0,0 +1,16 @@ +from utils.tests import ConditionalTableViewTest, TestCase +from participants.models import Adjudicator, Speaker + + +class PublicParticipantsViewTestCase(ConditionalTableViewTest, TestCase): + + view_toggle = 'public_features__public_participants' + view_name = 'public_participants' + + def table_data_a(self): + # Check number of adjs matches + return Adjudicator.objects.filter(tournament=self.t).count() + + def table_data_b(self): + # Check number of speakers matches + return Speaker.objects.filter(team__tournament=self.t).count() diff --git a/tabbycat/participants/urls_admin.py b/tabbycat/participants/urls_admin.py new file mode 100644 index 00000000000..a291dd9f811 --- /dev/null +++ b/tabbycat/participants/urls_admin.py @@ -0,0 +1,15 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^records/$', + views.ParticipantRecordsListView.as_view(), + name='participants-records-list'), + url(r'^team/(?P\d+)/$', + views.TeamRecordView.as_view(), + name='participants-team-record'), + url(r'^adjudicator/(?P\d+)/$', + views.AdjudicatorRecordView.as_view(), + name='participants-adjudicator-record'), +] diff --git a/tabbycat/participants/urls_crosst.py b/tabbycat/participants/urls_crosst.py new file mode 100644 index 00000000000..d2112d209b7 --- /dev/null +++ b/tabbycat/participants/urls_crosst.py @@ -0,0 +1,12 @@ +from django.conf.urls import url + +from . import views + + +urlpatterns = [ + + url(r'^shifts/(?P\w+)/$', + views.PublicConfirmShiftView.as_view(), + name='participants-public-confirm-shift') + +] diff --git a/tabbycat/participants/urls_public.py b/tabbycat/participants/urls_public.py new file mode 100644 index 00000000000..e92c1a045c8 --- /dev/null +++ b/tabbycat/participants/urls_public.py @@ -0,0 +1,21 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^list/$', + views.PublicParticipantsListView.as_view(), + name='participants-public-list'), + + url(r'^team/(?P\d+)/$', + views.PublicTeamRecordView.as_view(), + name='participants-public-team-record'), + url(r'^adjudicator/(?P\d+)/$', + views.PublicAdjudicatorRecordView.as_view(), + name='participants-public-adjudicator-record'), + + url(r'^team_list/(?P\d+)/$', + views.TeamSpeakersJsonView.as_view(), + name='participants-team-speakers'), + +] diff --git a/tabbycat/participants/utils.py b/tabbycat/participants/utils.py new file mode 100644 index 00000000000..c2b2cb79b6a --- /dev/null +++ b/tabbycat/participants/utils.py @@ -0,0 +1,45 @@ +from django.db.models.expressions import RawSQL + +from tournaments.models import Round + +from .models import Region, Team + + +def regions_ordered(t): + '''Need to redo the region IDs so the CSS classes will be consistent. This + assumes there aren't huge amounts of regions, or dramatically different + regions between tournaments (which holds for big tournaments uses)''' + + regions = Region.objects.all().order_by('name') + data = [{ + 'seq': count + 1, + 'name': r.name, + 'id': r.id + } for count, r in enumerate(regions)] + return data + + +def get_side_counts(teams, position, seq): + """Returns a dict where keys are the team IDs in `teams`, and values are + the number of debates the team has had in position `position` in preliminary + rounds.""" + + team_ids = [team.id for team in teams] + + query = """ + SELECT DISTINCT COUNT(draw_debateteam.id) + FROM draw_debateteam + JOIN draw_debate ON draw_debateteam.debate_id = draw_debate.id + JOIN tournaments_round ON draw_debate.round_id = tournaments_round.id + WHERE participants_team.id = draw_debateteam.team_id + AND draw_debateteam.position = '{pos:s}' + AND tournaments_round.stage = '{stage:s}'""".format( + pos=position, stage=Round.STAGE_PRELIMINARY) + if seq is not None: + query += """ + AND tournaments_round.seq <= '{round:d}'""".format(round=seq) + + queryset = Team.objects.filter(id__in=team_ids).annotate( + side_count=RawSQL(query, ())) + + return {annotated_team.id: annotated_team.side_count for annotated_team in queryset} diff --git a/tabbycat/participants/views.py b/tabbycat/participants/views.py new file mode 100644 index 00000000000..aa57e4b270b --- /dev/null +++ b/tabbycat/participants/views.py @@ -0,0 +1,258 @@ +from django.conf import settings +from django.contrib import messages +from django.core.exceptions import ObjectDoesNotExist +from django.http import JsonResponse +from django.views.generic.base import View + +from adjallocation.models import DebateAdjudicator +from adjfeedback.progress import FeedbackProgressForAdjudicator, FeedbackProgressForTeam +from draw.prefetch import populate_opponents, populate_teams +from results.models import TeamScore +from results.prefetch import populate_confirmed_ballots, populate_wins +from tournaments.mixins import CrossTournamentPageMixin, PublicTournamentPageMixin, TournamentMixin +from tournaments.models import Round +from utils.misc import reverse_tournament +from utils.mixins import CacheMixin, SingleObjectByRandomisedUrlMixin, SingleObjectFromTournamentMixin +from utils.mixins import ModelFormSetView, SuperuserRequiredMixin, VueTableTemplateView +from utils.tables import TabbycatTableBuilder + +from .models import Adjudicator, Speaker, Team + + +class TeamSpeakersJsonView(CacheMixin, SingleObjectFromTournamentMixin, View): + + model = Team + pk_url_kwarg = 'team_id' + cache_timeout = settings.TAB_PAGES_CACHE_TIMEOUT + + def get(self, request, *args, **kwargs): + team = self.get_object() + speakers = team.speakers + data = {i: "
  • " + speaker.name + "
  • " for i, speaker in enumerate(speakers)} + return JsonResponse(data, safe=False) + + +class PublicParticipantsListView(PublicTournamentPageMixin, CacheMixin, VueTableTemplateView): + + public_page_preference = 'public_participants' + page_title = 'Participants' + page_emoji = '🚌' + + def get_tables(self): + t = self.get_tournament() + + adjudicators = t.adjudicator_set.select_related('institution') + adjs_table = TabbycatTableBuilder(view=self, title="Adjudicators", sort_key="Name") + adjs_table.add_adjudicator_columns(adjudicators) + + speakers = Speaker.objects.filter(team__tournament=t).select_related( + 'team', 'team__institution').prefetch_related('team__speaker_set') + speakers_table = TabbycatTableBuilder(view=self, title="Speakers", sort_key="Name") + speakers_table.add_speaker_columns(speakers) + speakers_table.add_team_columns([speaker.team for speaker in speakers]) + + return [adjs_table, speakers_table] + + +# ============================================================================== +# Team and adjudicator record pages +# ============================================================================== + +class ParticipantRecordsListView(SuperuserRequiredMixin, TournamentMixin, VueTableTemplateView): + + page_title = 'Team and Adjudicator Record Pages' + page_emoji = '🌸' + + def get_tables(self): + t = self.get_tournament() + + adjudicators = t.adjudicator_set.select_related('institution') + adjs_table = TabbycatTableBuilder(view=self, title="Adjudicators", sort_key="Name") + adjs_table.add_adjudicator_columns(adjudicators) + + teams = t.team_set.select_related('institution') + teams_table = TabbycatTableBuilder(view=self, title="Teams", sort_key="Name") + teams_table.add_team_columns(teams, key="Name") + + return [adjs_table, teams_table] + + +class BaseRecordView(SingleObjectFromTournamentMixin, VueTableTemplateView): + + allow_null_tournament = True + + def get_context_data(self, **kwargs): + kwargs['admin_page'] = self.admin + kwargs['draw_released'] = self.get_tournament().current_round.draw_status == Round.STATUS_RELEASED + return super().get_context_data(**kwargs) + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + return super().get(request, *args, **kwargs) + + +class BaseTeamRecordView(BaseRecordView): + + model = Team + template_name = 'team_record.html' + + def get_page_title(self): + return 'Record for ' + self.object.long_name + + def get_page_emoji(self): + if self.get_tournament().pref('show_emoji'): + return self.object.emoji + + def get_context_data(self, **kwargs): + tournament = self.get_tournament() + + try: + kwargs['debateteam'] = self.object.debateteam_set.get( + debate__round=tournament.current_round) + except ObjectDoesNotExist: + kwargs['debateteam'] = None + + kwargs['feedback_progress'] = FeedbackProgressForTeam(self.object, tournament) + + return super().get_context_data(**kwargs) + + def get_table(self): + """On team record pages, the table is the results table.""" + tournament = self.get_tournament() + teamscores = TeamScore.objects.filter(debate_team__team=self.object, + ballot_submission__confirmed=True, + debate_team__debate__round__seq__lt=tournament.current_round.seq, + debate_team__debate__round__draw_status=Round.STATUS_RELEASED, + debate_team__debate__round__silent=False).select_related( + 'debate_team__debate', 'debate_team__debate__round').prefetch_related( + 'debate_team__debate__debateadjudicator_set__adjudicator') + debates = [ts.debate_team.debate for ts in teamscores] + populate_opponents([ts.debate_team for ts in teamscores]) + populate_confirmed_ballots(debates, motions=True, ballotsets=True) + + table = TabbycatTableBuilder(view=self, title="Results", sort_key="Round") + table.add_round_column([debate.round for debate in debates]) + table.add_debate_result_by_team_columns(teamscores) + table.add_debate_adjudicators_column(debates, show_splits=True) + + if self.admin or tournament.pref('public_motions'): + table.add_motion_column([debate.confirmed_ballot.motion + if debate.confirmed_ballot else None for debate in debates]) + + table.add_debate_ballot_link_column(debates) + + return table + + +class BaseAdjudicatorRecordView(BaseRecordView): + + model = Adjudicator + template_name = 'adjudicator_record.html' + page_emoji = '⚖' + + def get_page_title(self): + return 'Record for ' + self.object.name + + def get_context_data(self, **kwargs): + tournament = self.get_tournament() + + try: + kwargs['debateadjudicator'] = self.object.debateadjudicator_set.get( + debate__round=tournament.current_round) + except ObjectDoesNotExist: + kwargs['debateadjudicator'] = None + + kwargs['feedback_progress'] = FeedbackProgressForAdjudicator(self.object, tournament) + + return super().get_context_data(**kwargs) + + def get_table(self): + """On adjudicator record pages, the table is the previous debates table.""" + tournament = self.get_tournament() + debateadjs = DebateAdjudicator.objects.filter(adjudicator=self.object, + debate__round__seq__lt=tournament.current_round.seq, + debate__round__draw_status=Round.STATUS_RELEASED, + debate__round__silent=False).select_related( + 'debate', 'debate__round').prefetch_related( + 'debate__debateadjudicator_set', 'debate__debateadjudicator_set__adjudicator') + debates = [da.debate for da in debateadjs] + populate_teams(debates) + populate_wins(debates) + populate_confirmed_ballots(debates, motions=True, ballotsets=True) + + table = TabbycatTableBuilder(view=self, title="Previous Rounds", sort_key="Round") + table.add_round_column([debate.round for debate in debates]) + table.add_debate_results_columns(debates) + table.add_debate_adjudicators_column(debates, show_splits=True, highlight_adj=self.object) + + if self.admin or tournament.pref('public_motions'): + table.add_motion_column([debate.confirmed_ballot.motion + if debate.confirmed_ballot else None for debate in debates]) + + table.add_debate_ballot_link_column(debates) + return table + + +class TeamRecordView(SuperuserRequiredMixin, BaseTeamRecordView): + admin = True + + +class AdjudicatorRecordView(SuperuserRequiredMixin, BaseAdjudicatorRecordView): + admin = True + + +class PublicTeamRecordView(PublicTournamentPageMixin, BaseTeamRecordView): + public_page_preference = 'public_record' + admin = False + + +class PublicAdjudicatorRecordView(PublicTournamentPageMixin, BaseAdjudicatorRecordView): + public_page_preference = 'public_record' + admin = False + + +# ============================================================================== +# Shift scheduling +# ============================================================================== + +class PublicConfirmShiftView(CrossTournamentPageMixin, SingleObjectByRandomisedUrlMixin, ModelFormSetView): + # Django doesn't have a class-based view for formsets, so this implements + # the form processing analogously to FormView, with less decomposition. + # See also: motions.views.EditMotionsView. + + public_page_preference = 'allocation_confirmations' + template_name = 'confirm_shifts.html' + formset_factory_kwargs = dict(can_delete=False, extra=0, fields=['timing_confirmed']) + model = Adjudicator + allow_null_tournament = True + formset_model = DebateAdjudicator + + def get_success_url(self): + return reverse_tournament('participants-public-confirm-shift', + self.get_tournament(), kwargs={'url_key': self.object.url_key}) + + def get_formset_queryset(self): + return self.object.debateadjudicator_set.all() + + def get_context_data(self, **kwargs): + kwargs['adjudicator'] = self.get_object() + return super().get_context_data(**kwargs) + + def formset_valid(self, formset): + messages.success(self.request, "Your shift check-ins have been saved") + return super().formset_valid(formset) + + def formset_invalid(self, formset): + messages.error(self.request, "Whoops! There was a problem with the form.") + return super().formset_invalid(formset) + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + return super().get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + return super().post(request, *args, **kwargs) + + def put(self, request, *args, **kwargs): + return self.post(request, *args, **kwargs) diff --git a/standings/__init__.py b/tabbycat/printing/__init__.py similarity index 100% rename from standings/__init__.py rename to tabbycat/printing/__init__.py diff --git a/draw/templates/division_sheets_list.html b/tabbycat/printing/templates/division_sheets_list.html similarity index 63% rename from draw/templates/division_sheets_list.html rename to tabbycat/printing/templates/division_sheets_list.html index afa4f34c8f4..8a63a8868fe 100644 --- a/draw/templates/division_sheets_list.html +++ b/tabbycat/printing/templates/division_sheets_list.html @@ -9,12 +9,14 @@
    -

    Master Sheets

    +

    Master Sheets

    @@ -24,12 +26,14 @@

    Master Sheets

    -

    Room Sheets

    +

    Room Sheets

    diff --git a/draw/templates/printing/feedback_list.html b/tabbycat/printing/templates/feedback_list.html similarity index 60% rename from draw/templates/printing/feedback_list.html rename to tabbycat/printing/templates/feedback_list.html index d3a267d1dc8..bf5d9c0f831 100644 --- a/draw/templates/printing/feedback_list.html +++ b/tabbycat/printing/templates/feedback_list.html @@ -1,4 +1,4 @@ -{% extends "printing/printables_list.html" %} +{% extends "printables_list.html" %} {% block head-title %} {{ ballots|length }} Feedback Forms for {{ round.abbreviation }} @@ -11,24 +11,16 @@ {% endblock content %} - -{% block extra-js %} - - {% include "vue/import-vue.html" %} - {% include "vue/printables/base-ballot.vue" %} - {% include "vue/printables/base-ballot-header.vue" %} - {% include "vue/printables/base-ballot-footer.vue" %} - {% include "vue/printables/base-scoresheet.vue" %} - {% include "vue/printables/base-feedback.vue" %} +{% block js %} + {{ block.super }} -{% endblock extra-js %} +{% endblock js %} diff --git a/tabbycat/printing/templates/feedback_url_sheets.html b/tabbycat/printing/templates/feedback_url_sheets.html new file mode 100644 index 00000000000..279d475a1ef --- /dev/null +++ b/tabbycat/printing/templates/feedback_url_sheets.html @@ -0,0 +1,48 @@ +{% extends "base.html" %} +{% load debate_tags %} + +{% block page-title %}Printable Feedback URLs{% endblock %} + +{% block header %}{% endblock %} +{% block nav %}{% endblock %} +{% block footer %}{% endblock footer %} + +{% block page-alerts %} +
    + This page is designed to be printed as double sided A4 sheets, with the + outside facing side showing the team/adj name and the inside facing side + showing the URL. Use CTRL-P to print. +
    +{% endblock %} + +{% block content %} + + {% for adj in adjs %} +
    +
    + Feedback URL for {{ adj.name }} ({{ adj.institution.code }}) +
    +
    +


    + Please bookmark the following URL, you will use it to submit feedback + throughout the tournament: +

    + {% tournament_absurl adjfeedback-public-add-from-adjudicator-randomised adj.url_key %} +
    + {% endfor %} + + {% for team in teams %} +
    +
    + Feedback URL for {{ team.short_name }} +
    +
    +


    + Please bookmark the following URL, you will use it to submit feedback + throughout the tournament: +

    + {% tournament_absurl adjfeedback-public-add-from-team-randomised team.url_key %} +
    + {% endfor %} + +{% endblock content %} diff --git a/draw/templates/printing/master_sheets_view.html b/tabbycat/printing/templates/master_sheets_view.html similarity index 92% rename from draw/templates/printing/master_sheets_view.html rename to tabbycat/printing/templates/master_sheets_view.html index 6520dff6d7a..f8989452dd4 100644 --- a/draw/templates/printing/master_sheets_view.html +++ b/tabbycat/printing/templates/master_sheets_view.html @@ -2,7 +2,7 @@ {% load debate_tags %} {% block head-title %} - +
    Master Sheet for Debates at {{ base_venue_group.short_name }} in {{ round.name }}
    {% endblock %} {% block page-title %} Master Sheet for Debates at {{ venue_group.short_name }} @@ -19,7 +19,7 @@
    -

    {{ tournament.short_name }}

    +

    {{ tournament.short_name }}

    @@ -82,7 +82,7 @@

    {{ tournament.short_name }}

    -

    Additional Comments from the Head Ajudicator

    +

    Additional Comments from the Head Ajudicator

    diff --git a/draw/templates/printing/printables_list.html b/tabbycat/printing/templates/printables_list.html similarity index 88% rename from draw/templates/printing/printables_list.html rename to tabbycat/printing/templates/printables_list.html index 2bf837e6aa5..54c193f14d1 100644 --- a/draw/templates/printing/printables_list.html +++ b/tabbycat/printing/templates/printables_list.html @@ -6,10 +6,10 @@ {% block page-alerts %}
    - Use CTRL+P for printing or saving to PDF. Be sure to set the appropriate orientation, to turn off headers/footers and turn on background graphics. Works best in Safari or Firefox.) + Use CTRL+P for printing or saving to PDF. Be sure to set the appropriate orientation, to turn off headers/footers and turn on background graphics. Works best in Safari or Firefox.
    {% endblock %} {% block extra-css %} - + {% endblock extra-css %} diff --git a/draw/templates/printing/room_sheets_view.html b/tabbycat/printing/templates/room_sheets_view.html similarity index 78% rename from draw/templates/printing/room_sheets_view.html rename to tabbycat/printing/templates/room_sheets_view.html index 500b356616c..6f818e950ea 100644 --- a/draw/templates/printing/room_sheets_view.html +++ b/tabbycat/printing/templates/room_sheets_view.html @@ -2,7 +2,7 @@ {% load debate_tags %} {% block head-title %} - +
    Room Sheets for Debates at {{ base_venue_group.short_name }} in {{ round.name }}
    {% endblock %} {% block page-title %} Room Sheets for Debates at {{ venue_group.short_name }} @@ -22,14 +22,15 @@

    {{ venue.name }}

    {% for debate in venue.debates %}
    -

    {{ debate.round.tournament.short_name }} Division {{ debate.aff_team.division.name }}

    +

    + {{ debate.round.tournament.short_name }} Division + {{ debate.aff_team.division.name }} +

      - {% for motion in debate.division_motion %} -
    • - {{ motion.text }} -
    • - {% endfor %} +
    • + {{ debate.get_division_motions.text }} +
    • {% if debate.confirmed_ballot.forfeit %} {{ debate.time|time:"H:i" }} diff --git a/draw/templates/printing/scoresheet_list.html b/tabbycat/printing/templates/scoresheet_list.html similarity index 67% rename from draw/templates/printing/scoresheet_list.html rename to tabbycat/printing/templates/scoresheet_list.html index 25134f7d95e..83c041c550c 100644 --- a/draw/templates/printing/scoresheet_list.html +++ b/tabbycat/printing/templates/scoresheet_list.html @@ -1,4 +1,4 @@ -{% extends "printing/printables_list.html" %} +{% extends "printables_list.html" %} {% block head-title %} {{ ballots|length }} Scoresheets for {{ round.abbreviation }} @@ -8,22 +8,19 @@ {% block content %} - + {% endblock content %} -{% block extra-js %} - - {% include "vue/import-vue.html" %} - {% include "vue/printables/base-ballot.vue" %} +{% block js %} + {{ block.super }} -{% endblock extra-js %} +{% endblock js %} diff --git a/tabbycat/printing/urls_admin.py b/tabbycat/printing/urls_admin.py new file mode 100644 index 00000000000..36e1f18461b --- /dev/null +++ b/tabbycat/printing/urls_admin.py @@ -0,0 +1,30 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + + url(r'^round/(?P\d+)/print/scoresheets/$', + views.PrintScoreSheetsView.as_view(), + name='draw_print_scoresheets'), + + url(r'^round/(?P\d+)/print/feedback/$', + views.PrintFeedbackFormsView.as_view(), + name='draw_print_feedback'), + + url(r'^round/(?P\d+)/master_sheets/list/$', + views.MasterSheetsListView.as_view(), + name='master_sheets_list'), + + url(r'^round/(?P\d+)/master_sheets/venue_group/(?P\d+)/$', + views.MasterSheetsView.as_view(), + name='master_sheets_view'), + + url(r'^round/(?P\d+)/room_sheets_view/venue_group/(?P\d+)/$', + views.RoomSheetsView.as_view(), + name='room_sheets_view'), + + url(r'^feedback_urls_sheets/', + views.FeedbackURLsView.as_view(), + name='feedback_urls_sheets'), +] diff --git a/tabbycat/printing/views.py b/tabbycat/printing/views.py new file mode 100644 index 00000000000..0bbbec43290 --- /dev/null +++ b/tabbycat/printing/views.py @@ -0,0 +1,202 @@ +import json + +from django.views.generic.base import TemplateView + +from adjfeedback.models import AdjudicatorFeedbackQuestion +from adjfeedback.utils import expected_feedback_targets +from draw.models import Debate +from motions.models import Motion +from participants.models import Adjudicator +from tournaments.mixins import RoundMixin, TournamentMixin +from tournaments.models import Tournament +from utils.mixins import SuperuserRequiredMixin +from venues.models import Venue, VenueGroup + + +class MasterSheetsListView(SuperuserRequiredMixin, RoundMixin, TemplateView): + template_name = 'division_sheets_list.html' + + def get_context_data(self, **kwargs): + kwargs['standings'] = VenueGroup.objects.all() + kwargs['venue_groups'] = VenueGroup.objects.all() + return super().get_context_data(**kwargs) + + +class MasterSheetsView(SuperuserRequiredMixin, RoundMixin, TemplateView): + template_name = 'master_sheets_view.html' + + def get_context_data(self, **kwargs): + venue_group_id = self.kwargs['venue_group_id'] + base_venue_group = VenueGroup.objects.get(id=venue_group_id) + active_tournaments = Tournament.objects.filter(active=True) + for tournament in list(active_tournaments): + tournament.debates = Debate.objects.select_related( + 'division', 'division__venue_group__short_name', 'round', + 'round__tournament').filter( + # All Debates, with a matching round, at the same venue group name + round__seq=round.seq, + round__tournament=tournament, + # Hack - remove when venue groups are unified + division__venue_group__short_name=base_venue_group.short_name + ).order_by('round', 'division__venue_group__short_name', 'division') + + kwargs['base_venue_group'] = base_venue_group + kwargs['active_tournaments'] = active_tournaments + return super().get_context_data(**kwargs) + + +class RoomSheetsView(SuperuserRequiredMixin, RoundMixin, TemplateView): + template_name = 'room_sheets_view.html' + + def get_context_data(self, **kwargs): + venue_group_id = self.kwargs['venue_group_id'] + base_venue_group = VenueGroup.objects.get(id=venue_group_id) + venues = Venue.objects.filter(group=base_venue_group) + + for venue in venues: + venue.debates = Debate.objects.filter( + # All Debates, with a matching round, at the same venue group name + round__seq=round.seq, + venue=venue + ).select_related('round__tournament__short_name').order_by('round__tournament__seq') + + kwargs['base_venue_group'] = base_venue_group + kwargs['venues'] = venues + return super().get_context_data(**kwargs) + + +class PrintFeedbackFormsView(RoundMixin, SuperuserRequiredMixin, TemplateView): + + template_name = 'feedback_list.html' + + def from_team(self): + return AdjudicatorFeedbackQuestion.objects.filter( + tournament=self.get_round().tournament, from_team=True).exists() + + def from_adj(self): + return AdjudicatorFeedbackQuestion.objects.filter( + tournament=self.get_round().tournament, from_adj=True).exists() + + def questions_json_dict(self): + questions = [] + for q in self.get_round().tournament.adj_feedback_questions: + q_set = { + 'text': q.text, 'seq': q.seq, 'type': q.answer_type, + 'required': json.dumps(q.answer_type), + 'from_team': json.dumps(q.from_team), + 'from_adj': json.dumps(q.from_adj), + } + if q.choices: + q_set['choice_options'] = q.choices.split(AdjudicatorFeedbackQuestion.CHOICE_SEPARATOR) + elif q.min_value is not None and q.max_value is not None: + q_set['choice_options'] = q.choices_for_number_scale + + questions.append(q_set) + return questions + + def construct_info(self, venue, source, source_p, target, target_p): + source_n = source.name if hasattr(source, 'name') else source.short_name + return { + 'room': "%s %s" % (venue.name if venue else "", "(" + venue.group.short_name + ")" if venue and venue.group else '', ), + 'authorInstitution': source.institution.code, + 'author': source_n, 'authorPosition': source_p, + 'target': target.name, 'targetPosition': target_p + } + + def get_context_data(self, **kwargs): + kwargs['questions'] = self.questions_json_dict() + kwargs['ballots'] = [] + + feedback_paths_option = self.get_tournament().pref('feedback_paths') + draw = self.get_round().debate_set_with_prefetches(ordering=( + 'venue__group__name', 'venue__name')) + + for debate in draw: + chair = debate.adjudicators.chair + if not chair: + continue + + if self.from_team(): + for team in debate.teams: + kwargs['ballots'].append(self.construct_info( + debate.venue, team, "Team", chair, "")) + + if self.from_adj(): + debateadjs = debate.debateadjudicator_set.all() + for debateadj in debateadjs: + sadj = debateadj.adjudicator + spos = debate.adjudicators.get_position(sadj) + targets = expected_feedback_targets(debateadj, feedback_paths=feedback_paths_option, + debate=debate) + for tadj, tpos in targets: + kwargs['ballots'].append(self.construct_info( + debate.venue, sadj, spos, tadj, tpos)) + + return super().get_context_data(**kwargs) + + +class PrintScoreSheetsView(RoundMixin, SuperuserRequiredMixin, TemplateView): + + template_name = 'scoresheet_list.html' + + def get_context_data(self, **kwargs): + kwargs['motions'] = Motion.objects.filter(round=self.get_round()).values('text').order_by('seq') + kwargs['ballots'] = [] + + draw = self.get_round().debate_set_with_prefetches(ordering=( + 'venue__group__name', 'venue__name',)) + + for debate in draw: + debate_info = { + 'room': "%s %s" % (debate.venue.name, "(" + debate.venue.group.short_name + ")" if debate.venue.group else '', ), + 'aff': debate.aff_team.short_name, + 'affEmoji': debate.aff_team.emoji, + 'affSpeakers': [s.name for s in debate.aff_team.speakers], + 'neg': debate.neg_team.short_name, + 'negEmoji': debate.neg_team.emoji, + 'negSpeakers': [s.name for s in debate.neg_team.speakers], + 'panel': [] + } + for adj, position in debate.adjudicators.with_positions(): + debate_info['panel'].append({ + 'name': adj.name, + 'institution': adj.institution.code, + 'position': position + }) + + if len(debate_info['panel']) is 0: + ballot_data = { + 'author': "_______________________________________________", + 'authorInstitution': "", + 'authorPosition': "", + } + ballot_data.update(debate_info) # Extend with debateInfo keys + kwargs['ballots'].append(ballot_data) + else: + for adj in (a for a in debate_info['panel'] if a['position'] != "t"): + ballot_data = { + 'author': adj['name'], + 'authorInstitution': adj['institution'], + 'authorPosition': adj['position'], + } + ballot_data.update(debate_info) # Extend with debateInfo keys + kwargs['ballots'].append(ballot_data) + + return super().get_context_data(**kwargs) + + +class FeedbackURLsView(TournamentMixin, SuperuserRequiredMixin, TemplateView): + + template_name = 'feedback_url_sheets.html' + + def get_context_data(self, **kwargs): + tournament = self.get_tournament() + kwargs['teams'] = tournament.team_set.all().order_by('institution', 'reference') + if not tournament.pref('share_adjs'): + kwargs['adjs'] = tournament.adjudicator_set.all().order_by('name') + else: + kwargs['adjs'] = Adjudicator.objects.all().order_by('name') + kwargs['exists'] = tournament.adjudicator_set.filter(url_key__isnull=False).exists() or \ + tournament.team_set.filter(url_key__isnull=False).exists() + kwargs['tournament_slug'] = tournament.slug + return super().get_context_data(**kwargs) diff --git a/standings/templatetags/__init__.py b/tabbycat/results/__init__.py similarity index 100% rename from standings/templatetags/__init__.py rename to tabbycat/results/__init__.py diff --git a/results/admin.py b/tabbycat/results/admin.py similarity index 54% rename from results/admin.py rename to tabbycat/results/admin.py index 442a42f1b98..69c5e03d41c 100644 --- a/results/admin.py +++ b/tabbycat/results/admin.py @@ -1,82 +1,74 @@ from django.contrib import admin -from .models import BallotSubmission, TeamScore, SpeakerScore, SpeakerScore, SpeakerScoreByAdj -from participants.models import Team, Speaker, Adjudicator -from tournaments.models import Round -from results.models import SpeakerScore + +from .models import BallotSubmission, SpeakerScore, SpeakerScoreByAdj, TeamScore + +from utils.admin import BaseModelAdmin + # ============================================================================== # BallotSubmission # ============================================================================== -_bs_round = lambda o: o.debate.round.seq -_bs_round.short_description = 'Round' - -class BallotSubmissionAdmin(admin.ModelAdmin): - list_display = ('id', 'debate', _bs_round, 'timestamp', 'submitter_type', 'submitter', 'confirmer') +class BallotSubmissionAdmin(admin.ModelAdmin, BaseModelAdmin): + list_display = ('id', 'debate', 'get_round', 'timestamp', 'submitter_type', 'submitter', 'confirmer') search_fields = ('debate__debateteam__team__reference', 'debate__debateteam__team__institution__code') - raw_id_fields = ('debate','motion') + raw_id_fields = ('debate', 'motion') list_filter = ('debate__round', 'submitter', 'confirmer') # This incurs a massive performance hit - #inlines = (SpeakerScoreByAdjInline, SpeakerScoreInline, TeamScoreInline) + # inlines = (SpeakerScoreByAdjInline, SpeakerScoreInline, TeamScoreInline) admin.site.register(BallotSubmission, BallotSubmissionAdmin) + # ============================================================================== # TeamScore # ============================================================================== -_ts_round = lambda o: o.debate_team.debate.round.seq -_ts_round.short_description = 'Round' -_ts_team = lambda o: o.debate_team.team -_ts_team.short_description = 'Team' - -class TeamScoreAdmin(admin.ModelAdmin): - list_display = ('id', 'ballot_submission', _ts_round, _ts_team, 'score') +class TeamScoreAdmin(admin.ModelAdmin, BaseModelAdmin): + list_display = ('id', 'ballot_submission', 'get_round', 'get_team', 'score') search_fields = ('debate_team__debate__round__seq', 'debate_team__team__reference', 'debate_team__team__institution__code') - raw_id_fields = ('ballot_submission','debate_team') + admin.site.register(TeamScore, TeamScoreAdmin) + # ============================================================================== # SpeakerScore # ============================================================================== -_ss_speaker = lambda o: o.speaker.name -_ss_speaker.short_description = 'Speaker' - -class SpeakerScoreAdmin(admin.ModelAdmin): - list_display = ('id', 'ballot_submission', _ts_round, _ts_team, 'position', _ss_speaker, 'score') +class SpeakerScoreAdmin(admin.ModelAdmin, BaseModelAdmin): + list_display = ('id', 'ballot_submission', 'get_round', 'get_team', 'position', 'get_speaker_name', 'score') search_fields = ('debate_team__debate__round__abbreviation', 'debate_team__team__reference', 'debate_team__team__institution__code', 'speaker__name') list_filter = ('score', 'debate_team__debate__round') - raw_id_fields = ('debate_team','ballot_submission') + raw_id_fields = ('debate_team', 'ballot_submission') def get_queryset(self, request): return super(SpeakerScoreAdmin, self).get_queryset(request).select_related( 'debate_team__debate__round', - 'debate_team__team__institution','debate_team__team__tournament', + 'debate_team__team__institution', 'debate_team__team__tournament', 'ballot_submission') admin.site.register(SpeakerScore, SpeakerScoreAdmin) + # ============================================================================== # SpeakerScoreByAdj # ============================================================================== -_ssba_speaker = lambda o: SpeakerScore.objects.filter(debate_team=o.debate_team, position=o.position)[0].speaker.name -_ssba_speaker.short_description = 'Speaker' -_ssba_adj = lambda o: o.debate_adjudicator.adjudicator.name -_ssba_adj.short_description = 'Adjudicator' - -class SpeakerScoreByAdjAdmin(admin.ModelAdmin): - list_display = ('id', 'ballot_submission', _ts_round, _ssba_adj, _ts_team, _ssba_speaker, 'position', 'score') +class SpeakerScoreByAdjAdmin(admin.ModelAdmin, BaseModelAdmin): + list_display = ('id', 'ballot_submission', 'get_round', 'get_adj_name', 'get_team', 'get_speaker_name_filter', 'position', 'score') search_fields = ('debate_team__debate__round__seq', 'debate_team__team__reference', 'debate_team__team__institution__code', 'debate_adjudicator__adjudicator__name') list_filter = ('debate_team__debate__round', 'debate_adjudicator__adjudicator__name') - raw_id_fields = ('debate_team','ballot_submission') + raw_id_fields = ('debate_team', 'ballot_submission') + + def get_speaker_name_filter(self, obj): + return SpeakerScore.objects.filter(debate_team=obj.debate_team, position=obj.position)[0].speaker.name + get_speaker_name_filter.short_description = 'Speaker' admin.site.register(SpeakerScoreByAdj, SpeakerScoreByAdjAdmin) diff --git a/results/dbutils.py b/tabbycat/results/dbutils.py similarity index 84% rename from results/dbutils.py rename to tabbycat/results/dbutils.py index 5ac7bfde49d..dc3d3ee29c2 100644 --- a/results/dbutils.py +++ b/tabbycat/results/dbutils.py @@ -4,36 +4,44 @@ These are mainly used in management commands, but in principle could be used by a front-end interface as well.""" +import random +import logging + +from django.contrib.auth import get_user_model + from draw.models import Debate from results.models import BallotSubmission -from django.contrib.auth import get_user_model from results.result import BallotSet -import random -import logging + logger = logging.getLogger(__name__) User = get_user_model() + def add_ballotsets_to_round(round, **kwargs): """Calls add_ballotset() for every debate in the given round.""" for debate in round.debate_set.all(): add_ballotset(debate, **kwargs) + def add_ballotsets_to_round_partial(round, num, **kwargs): """Calls ``add_ballotset()`` on ``num`` randomly-chosen debates in the given round.""" debates = random.sample(list(round.debate_set.all()), num) for debate in debates: add_ballotset(debate, **kwargs) + def delete_all_ballotsets_for_round(round): """Deletes all ballot sets from the given round.""" BallotSubmission.objects.filter(debate__round=round).delete() + def delete_ballotset(debate): """Deletes all ballot sets from the given debate.""" debate.ballotsubmission_set.all().delete() + def add_ballotset(debate, submitter_type, user, discarded=False, confirmed=False, - min_score=72, max_score=78, reply_random=False): + min_score=72, max_score=78, reply_random=False): """Adds a ballot set to a debate. ``debate`` is the Debate to which the ballot set should be added. @@ -46,8 +54,8 @@ def add_ballotset(debate, submitter_type, user, discarded=False, confirmed=False if discarded and confirmed: raise ValueError("Ballot can't be both discarded and confirmed!") - LAST_SUBSTANTIVE_POSITION = debate.round.tournament.LAST_SUBSTANTIVE_POSITION - REPLY_POSITION = debate.round.tournament.REPLY_POSITION + last_substantive_position = debate.round.tournament.LAST_SUBSTANTIVE_POSITION + reply_position = debate.round.tournament.REPLY_POSITION # Create a new BallotSubmission bsub = BallotSubmission(submitter_type=submitter_type, debate=debate) @@ -57,8 +65,9 @@ def add_ballotset(debate, submitter_type, user, discarded=False, confirmed=False def gen_results(): r = {'aff': (0,), 'neg': (0,)} + def do(): - s = [random.randint(min_score, max_score) for i in range(LAST_SUBSTANTIVE_POSITION)] + s = [random.randint(min_score, max_score) for i in range(last_substantive_position)] s.append(random.randint(min_score, max_score)/2) return s while sum(r['aff']) == sum(r['neg']): @@ -75,11 +84,11 @@ def do(): for side in ('aff', 'neg'): speakers = getattr(debate, '%s_team' % side).speakers - for i in range(1, LAST_SUBSTANTIVE_POSITION+1): + for i in range(1, last_substantive_position+1): bset.set_speaker(team=side, position=i, speaker=speakers[i - 1]) - reply_speaker = random.randint(0, LAST_SUBSTANTIVE_POSITION-1) if reply_random else 0 - bset.set_speaker(team=side, position=REPLY_POSITION, speaker=speakers[reply_speaker]) + reply_speaker = random.randint(0, last_substantive_position-1) if reply_random else 0 + bset.set_speaker(team=side, position=reply_position, speaker=speakers[reply_speaker]) for adj in debate.adjudicators.list: for pos in debate.round.tournament.POSITIONS: @@ -103,8 +112,8 @@ def do(): debate.result_status = Debate.STATUS_DRAFT debate.save() - logger.info("{debate} won by {team} on {motion}".format(debate=debate.matchup, - team=bset.aff_win and "affirmative" or "negative", - motion=bset.motion and bset.motion.reference or "")) + logger.info("{debate} won by {team} on {motion}".format( + debate=debate.matchup, team=bset.aff_win and "affirmative" or "negative", + motion=bset.motion and bset.motion.reference or "")) return bset diff --git a/results/forms.py b/tabbycat/results/forms.py similarity index 91% rename from results/forms.py rename to tabbycat/results/forms.py index 3267bc8270f..7c7f9d57f28 100644 --- a/results/forms.py +++ b/tabbycat/results/forms.py @@ -1,19 +1,23 @@ -from django import forms -from django.utils.translation import ugettext_lazy as _ import itertools -from collections import Counter import logging +from collections import Counter + +from django import forms +from django.utils.translation import ugettext_lazy as _ + from draw.models import Debate, DebateTeam from participants.models import Speaker, Team -from .result import BallotSet, ForfeitBallotSet +from .result import BallotSet, ForfeitBallotSet logger = logging.getLogger(__name__) + class FormConstructionError(Exception): pass + # ============================================================================== # Result/ballot custom fields # ============================================================================== @@ -42,11 +46,11 @@ def __init__(self, *args, **kwargs): """Takes an additional optional keyword argument: preferences, the Preferences register for the Tournament.""" - preferences = kwargs.pop('tournament_preferences') - if preferences: - min_value = preferences[self.CONFIG_MIN_VALUE_FIELD] - max_value = preferences[self.CONFIG_MAX_VALUE_FIELD] - step_value = preferences[self.CONFIG_STEP_VALUE_FIELD] + tournament = kwargs.pop('tournament') + if tournament: + min_value = tournament.pref(self.CONFIG_MIN_VALUE_FIELD) + max_value = tournament.pref(self.CONFIG_MAX_VALUE_FIELD) + step_value = tournament.pref(self.CONFIG_STEP_VALUE_FIELD) else: min_value = self.DEFAULT_MIN_VALUE max_value = self.DEFAULT_MAX_VALUE @@ -84,27 +88,30 @@ def check_value(self, value): _(msg), code='decimal' ) + class MotionModelChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): return "%d. %s" % (obj.seq, obj.text) + class SubstantiveScoreField(BaseScoreField): - CONFIG_MIN_VALUE_FIELD = 'scoring__score_min' - CONFIG_MAX_VALUE_FIELD = 'scoring__score_max' - CONFIG_STEP_VALUE_FIELD = 'scoring__score_step' + CONFIG_MIN_VALUE_FIELD = 'score_min' + CONFIG_MAX_VALUE_FIELD = 'score_max' + CONFIG_STEP_VALUE_FIELD = 'score_step' DEFAULT_MIN_VALUE = 68 DEFAULT_MAX_VALUE = 82 DEFAULT_STEP_VALUE = 1 class ReplyScoreField(BaseScoreField): - CONFIG_MIN_VALUE_FIELD = 'scoring__reply_score_min' - CONFIG_MAX_VALUE_FIELD = 'scoring__reply_score_max' - CONFIG_STEP_VALUE_FIELD = 'scoring__reply_score_step' + CONFIG_MIN_VALUE_FIELD = 'reply_score_min' + CONFIG_MAX_VALUE_FIELD = 'reply_score_max' + CONFIG_STEP_VALUE_FIELD = 'reply_score_step' DEFAULT_MIN_VALUE = 34 DEFAULT_MAX_VALUE = 41 DEFAULT_STEP_VALUE = 0.5 + # ============================================================================== # Result/ballot forms # ============================================================================== @@ -127,7 +134,7 @@ class BallotSetForm(forms.Form): def __init__(self, ballotsub, *args, **kwargs): self.ballotsub = ballotsub self.debate = ballotsub.debate - self.adjudicators = self.debate.adjudicators.list + self.adjudicators = list(self.debate.adjudicators.voting()) self.motions = self.debate.round.motion_set self.tournament = self.debate.round.tournament self.using_motions = self.tournament.pref('enable_motions') @@ -136,6 +143,7 @@ def __init__(self, ballotsub, *args, **kwargs): self.using_replies = self.tournament.pref('reply_scores_enabled') self.choosing_sides = self.tournament.pref('draw_side_allocations') == 'manual-ballot' self.bypassing_checks = self.tournament.pref('disable_ballot_confirms') + self.max_margin = self.tournament.pref('maximum_margin') self.forfeit_declared = False @@ -144,15 +152,15 @@ def __init__(self, ballotsub, *args, **kwargs): super(BallotSetForm, self).__init__(*args, **kwargs) self.POSITIONS = self.tournament.POSITIONS - self.LAST_SUBSTANTIVE_POSITION = self.tournament.LAST_SUBSTANTIVE_POSITION # also used in template - self.REPLY_POSITION = self.tournament.REPLY_POSITION # also used in template + self.LAST_SUBSTANTIVE_POSITION = self.tournament.LAST_SUBSTANTIVE_POSITION # also used in template + self.REPLY_POSITION = self.tournament.REPLY_POSITION # also used in template self._create_fields() self._set_tab_indices() self.initial = self._initial_data() @property - def SIDES_AND_POSITIONS(self): + def SIDES_AND_POSITIONS(self): # flake8: noqa return itertools.product(self.SIDES, self.POSITIONS) # -------------------------------------------------------------------------- @@ -229,11 +237,11 @@ def _create_fields(self): self.fields[self._fieldname_speaker(side, pos)] = forms.ModelChoiceField(queryset=queryset) # 4(b). Speaker scores - ScoreField = ReplyScoreField if (pos == self.REPLY_POSITION) else SubstantiveScoreField + scorefield = ReplyScoreField if (pos == self.REPLY_POSITION) else SubstantiveScoreField for adj in self.adjudicators: - self.fields[self._fieldname_score(adj, side, pos)] = ScoreField( - widget=forms.NumberInput(attrs={'class': 'required number'}), - tournament_preferences=self.tournament.preferences) + self.fields[self._fieldname_score(adj, side, pos)] = scorefield( + widget=forms.NumberInput(attrs={'class': 'required number'}), + tournament=self.tournament) # 5. If forfeits are enabled, don't require some fields and add the forfeit field if self.using_forfeits: @@ -253,15 +261,16 @@ def _create_fields(self): else: forfeiter = None - CHOICES = (('aff_forfeit', 'Forfeit by the Affirmative',), ('neg_forfeit', 'Forfeit by the Negative',)) - self.fields['forfeits'] = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES, initial=forfeiter, required=False) + choices = (('aff_forfeit', 'Forfeit by the Affirmative',), ('neg_forfeit', 'Forfeit by the Negative',)) + self.fields['forfeits'] = forms.ChoiceField(widget=forms.RadioSelect, choices=choices, initial=forfeiter, required=False) def _initial_data(self): """Generates dictionary of initial form data.""" ballotset = BallotSet(self.ballotsub) initial = {'debate_result_status': self.debate.result_status, - 'confirmed': ballotset.confirmed, 'discarded': ballotset.discarded} + 'confirmed': ballotset.confirmed, + 'discarded': ballotset.discarded} # When bypassing confirmations we just pre-check if self.bypassing_checks: @@ -337,7 +346,7 @@ def _set_tab_indices(self): except KeyError as e: logger.warning(e) - self.nexttabindex = i + 1 # for other UI elements in the tempate + self.nexttabindex = i + 1 # for other UI elements in the tempate # -------------------------------------------------------------------------- # Validation and save methods @@ -345,7 +354,6 @@ def _set_tab_indices(self): def clean(self): cleaned_data = super(BallotSetForm, self).clean() - errors = list() if cleaned_data.get('forfeits') in ["aff_forfeit", "neg_forfeit"]: self.forfeit_declared = True @@ -377,6 +385,12 @@ def clean(self): params={'adj': adj.name, 'adj_ins': adj.institution.code}, code='draw' )) + margin = abs(totals[0] - totals[1]) + if self.max_margin and margin > self.max_margin: + self.add_error(None, forms.ValidationError( + _("The margin (%(margin).1f) in the ballot of adjudicator %(adj)s (%(adj_ins)s) exceeds the maximum allowable margin (%(max_margin).1f)"), + params={'adj': adj.name, 'adj_ins': adj.institution.code, 'margin': margin, 'max_margin': self.max_margin}, code='max_margin' + )) # Pull team info again, in case it's changed since the form was loaded. if self.choosing_sides: @@ -399,8 +413,8 @@ def clean(self): if team is not None and speaker not in team.speakers: self.add_error(self._fieldname_speaker(side, pos), forms.ValidationError( _("The speaker %(speaker)s doesn't appear to be on team %(team)s."), - params={'speaker': speaker.name, 'team': team.short_name}, code='speaker_wrongteam' - )) + params={'speaker': speaker.name, 'team': team.short_name}, code='speaker_wrongteam') + ) speaker_counts[speaker] += 1 # The substantive speakers must be unique. @@ -420,7 +434,7 @@ def clean(self): self.add_error(self._fieldname_speaker(side, self.REPLY_POSITION), forms.ValidationError( _("The last substantive speaker and reply speaker for the %(side)s team can't be the same."), params={'side': self._LONG_NAME[side]}, code='reply_speaker_consecutive' - )) + )) # The reply speaker must have given a substantive speech. if speaker_counts[reply_speaker] == 0: @@ -488,7 +502,7 @@ def fake_speaker_selects(self): yield self['team_%d' % team.id] def adj_iter(self): - form = self # provide access in inner classes + form = self # provide access in inner classes class Position(object): def __init__(self, adj, pos): @@ -532,6 +546,5 @@ def position_iter(self): for i in form.POSITIONS: yield Position(self.adj, i) - for adj in self.adjudicators: yield AdjudicatorWrapper(adj) diff --git a/results/management/commands/fixballotstatuses.py b/tabbycat/results/management/commands/fixballotstatuses.py similarity index 86% rename from results/management/commands/fixballotstatuses.py rename to tabbycat/results/management/commands/fixballotstatuses.py index b54f374877e..667fb155578 100644 --- a/results/management/commands/fixballotstatuses.py +++ b/tabbycat/results/management/commands/fixballotstatuses.py @@ -1,10 +1,15 @@ from utils.management.base import TournamentCommand -from ...models import BallotSubmission + from draw.models import Debate +from ...models import BallotSubmission + + class Command(TournamentCommand): - help = "Makes discarded/confirmed fields of BallotSubmissions consistent with result_status field of Debates. Not guaranteed to be minimalist with changes." + help = "Makes discarded/confirmed fields of BallotSubmissions consistent " \ + "with result_status field of Debates. Not guaranteed to be " \ + "minimalist with changes." def handle_tournament(self, tournament, **options): for bsub in BallotSubmission.objects.filter(debate__round__tournament=tournament): @@ -21,4 +26,4 @@ def handle_tournament(self, tournament, **options): new = (bsub.discarded, bsub.confirmed) if original != new: self.stdout.write("{} changed from {} to {}".format(bsub, original, new)) - bsub.save() \ No newline at end of file + bsub.save() diff --git a/results/management/commands/generateresults.py b/tabbycat/results/management/commands/generateresults.py similarity index 62% rename from results/management/commands/generateresults.py rename to tabbycat/results/management/commands/generateresults.py index dab853f767b..9e5bfbe9974 100644 --- a/results/management/commands/generateresults.py +++ b/tabbycat/results/management/commands/generateresults.py @@ -1,11 +1,10 @@ -from utils.management.base import RoundCommand, CommandError -from results.dbutils import add_ballotset, add_ballotsets_to_round, delete_ballotset, delete_all_ballotsets_for_round, add_ballotsets_to_round_partial - from django.contrib.auth import get_user_model -from tournaments.models import Round + +from adjallocation.models import DebateAdjudicator from draw.models import Debate from results.models import BallotSubmission -from adjallocation.models import DebateAdjudicator +from utils.management.base import CommandError, RoundCommand +from results.dbutils import add_ballotset, add_ballotsets_to_round, add_ballotsets_to_round_partial, delete_all_ballotsets_for_round, delete_ballotset OBJECT_TYPE_CHOICES = ["round", "debate"] SUBMITTER_TYPE_MAP = { @@ -14,23 +13,36 @@ } User = get_user_model() + class GenerateResultsCommandMixin: def add_arguments(self, parser): super(GenerateResultsCommandMixin, self).add_arguments(parser) - parser.add_argument("-T", "--submitter-type", type=str, help="Submitter type, either 'tabroom' or 'public'", choices=list(SUBMITTER_TYPE_MAP.keys()), default="tabroom") - parser.add_argument("-u", "--user", type=str, help="Username of submitter", default="random") + parser.add_argument("-T", "--submitter-type", type=str, + help="Submitter type, either 'tabroom' or 'public'", + choices=list(SUBMITTER_TYPE_MAP.keys()), default="tabroom") + parser.add_argument("-u", "--user", type=str, + help="Username of submitter", default="random") parser.add_argument("--create-user", help="Create user if it doesn't exist", action="store_true") status = parser.add_mutually_exclusive_group(required=True) - status.add_argument("-D", "--discarded", action="store_true", help="Make added ballot sets discarded") - status.add_argument("-d", "--draft", action="store_true", help="Make added ballot sets draft (neither discarded nor confirmed") - status.add_argument("-c", "--confirmed", action="store_true", help="Make added ballot sets confirmed") - - parser.add_argument("-m", "--min-score", type=float, help="Minimum speaker score (for substantive)", default=72) - parser.add_argument("-M", "--max-score", type=float, help="Maximum speaker score (for substantive)", default=78) - parser.add_argument("--reply-random", action="store_true", help="Choose reply speaker at random (rather than always use first speaker", default=False) + status.add_argument("-D", "--discarded", action="store_true", + help="Make added ballot sets discarded") + status.add_argument("-d", "--draft", action="store_true", + help="Make added ballot sets draft (neither discarded nor confirmed") + status.add_argument("-c", "--confirmed", action="store_true", + help="Make added ballot sets confirmed") + + parser.add_argument("-m", "--min-score", type=float, + help="Minimum speaker score (for substantive)", + default=72) + parser.add_argument("-M", "--max-score", type=float, + help="Maximum speaker score (for substantive)", + default=78) + parser.add_argument("--reply-random", action="store_true", + help="Choose reply speaker at random (rather than always use first speaker", + default=False) @staticmethod def _get_user(options): @@ -62,22 +74,30 @@ class Command(GenerateResultsCommandMixin, RoundCommand): def add_arguments(self, parser): super(Command, self).add_arguments(parser) - parser.add_argument("--debates", type=int, nargs="+", help="IDs of specific debates to add feedback to. Done in addition to rounds, if any.", default=[]) - parser.add_argument("--clean", help="Remove all associated ballot sets first", action="store_true") - parser.add_argument("-n", "--num-ballots", type=int, help="Number of ballot sets to add per round (default all) or debate (default 1)", default=None) + parser.add_argument("--debates", type=int, nargs="+", + help="IDs of specific debates to add feedback to. " + "Done in addition to rounds, if any.", default=[]) + parser.add_argument("--clean", + help="Remove all associated ballot sets first", + action="store_true") + parser.add_argument("-n", "--num-ballots", type=int, + help="Number of ballot sets to add per round " + "(default all) or debate (default 1)", default=None) def handle(self, *args, **options): if not self.get_rounds(options) and not options["debates"]: raise CommandError("No rounds or debates were given. (Use --help for more info.)") - super(Command, self).handle(*args, **options) # handles rounds + super(Command, self).handle(*args, **options) # Handles rounds for tournament in self.get_tournaments(options): for debate_id in options["debates"]: try: debate = Debate.objects.get(round__tournament=tournament, id=debate_id) except Debate.DoesNotExist: - self.stdout.write(self.style.WARNING("Warning: There is no debate with id {:d} for tournament {!r}, skipping".format(debate_id, tournament.slug))) + self.stdout.write(self.style.WARNING( + "Warning: There is no debate with id {:d} for " + "tournament {!r}, skipping".format(debate_id, tournament.slug))) self.handle_debate(debate, **options) def handle_round(self, round, **options): @@ -87,10 +107,13 @@ def handle_round(self, round, **options): try: if options["num_ballots"] is not None: - self.stdout.write(self.style.MIGRATE_HEADING("Generating ballot sets for {:d} randomly-chosen debates in {}...".format(options["num_ballots"], round.name))) + self.stdout.write(self.style.MIGRATE_HEADING( + "Generating ballot sets for {:d} randomly-chosen debates " + "in {}...".format(options["num_ballots"], round.name))) add_ballotsets_to_round_partial(round, options["num_ballots"], **self.ballotset_kwargs(options)) else: - self.stdout.write(self.style.MIGRATE_HEADING("Generating ballot sets for all debates in {}...".format(round.name))) + self.stdout.write(self.style.MIGRATE_HEADING( + "Generating ballot sets for all debates in {}...".format(round.name))) add_ballotsets_to_round(round, **self.ballotset_kwargs(options)) except ValueError as e: diff --git a/results/management/commands/removeblankballots.py b/tabbycat/results/management/commands/removeblankballots.py similarity index 98% rename from results/management/commands/removeblankballots.py rename to tabbycat/results/management/commands/removeblankballots.py index 5529c2fd01a..2d34d0d19d3 100644 --- a/results/management/commands/removeblankballots.py +++ b/tabbycat/results/management/commands/removeblankballots.py @@ -1,6 +1,8 @@ from utils.management.base import TournamentCommand + from ...models import BallotSubmission, SpeakerScoreByAdj + class Command(TournamentCommand): help = "Removes all blank ballot submissions, i.e. ones without any scores attached." @@ -16,4 +18,4 @@ def handle_tournament(self, tournament, **options): self.stdout.write("Deleting {:s}".format(str(bsub))) bsub.delete() else: - self.stdout.write("Would delete {:s}".format(str(bsub))) \ No newline at end of file + self.stdout.write("Would delete {:s}".format(str(bsub))) diff --git a/results/management/commands/uniquifyballotversions.py b/tabbycat/results/management/commands/uniquifyballotversions.py similarity index 83% rename from results/management/commands/uniquifyballotversions.py rename to tabbycat/results/management/commands/uniquifyballotversions.py index 4224576ab1f..473c30665a3 100644 --- a/results/management/commands/uniquifyballotversions.py +++ b/tabbycat/results/management/commands/uniquifyballotversions.py @@ -1,7 +1,6 @@ -from utils.management.base import TournamentCommand from draw.models import Debate -from ...models import BallotSubmission -from collections import Counter +from utils.management.base import TournamentCommand + class Command(TournamentCommand): @@ -18,8 +17,8 @@ def handle_tournament(self, tournament, **options): for i, bsub in enumerate(bsubs, start=1): if bsub.version != i: self.stdout.write("{verb} from version {old:d} to {new:d}: {bsub:s}".format( - verb="Would change" if options["dry_run"] else "Changing", - old=bsub.version, new=i, bsub=str(bsub))) + verb="Would change" if options["dry_run"] else "Changing", + old=bsub.version, new=i, bsub=str(bsub))) elif options["verbosity"] >= 3: self.stdout.write("Stays version {:d}: {bsub:s}".format(bsub.version, bsub=str(bsub))) if not options["dry_run"]: diff --git a/results/migrations/0001_initial.py b/tabbycat/results/migrations/0001_initial.py similarity index 100% rename from results/migrations/0001_initial.py rename to tabbycat/results/migrations/0001_initial.py diff --git a/results/migrations/0002_auto_20160109_1834.py b/tabbycat/results/migrations/0002_auto_20160109_1834.py similarity index 100% rename from results/migrations/0002_auto_20160109_1834.py rename to tabbycat/results/migrations/0002_auto_20160109_1834.py diff --git a/results/migrations/0003_auto_20160207_1618.py b/tabbycat/results/migrations/0003_auto_20160207_1618.py similarity index 100% rename from results/migrations/0003_auto_20160207_1618.py rename to tabbycat/results/migrations/0003_auto_20160207_1618.py diff --git a/results/migrations/0004_auto_20160228_1838.py b/tabbycat/results/migrations/0004_auto_20160228_1838.py similarity index 100% rename from results/migrations/0004_auto_20160228_1838.py rename to tabbycat/results/migrations/0004_auto_20160228_1838.py diff --git a/standings/tests/__init__.py b/tabbycat/results/migrations/__init__.py similarity index 100% rename from standings/tests/__init__.py rename to tabbycat/results/migrations/__init__.py diff --git a/results/mixins.py b/tabbycat/results/mixins.py similarity index 99% rename from results/mixins.py rename to tabbycat/results/mixins.py index f6281a24738..2b674d0db84 100644 --- a/results/mixins.py +++ b/tabbycat/results/mixins.py @@ -1,6 +1,8 @@ -from .models import Submission from utils.misc import get_ip_address +from .models import Submission + + class TabroomSubmissionFieldsMixin: """Mixin that provides retrieval of appropriate fields for the Submission instance, used with forms that are submitted by tabroom officials. It is up diff --git a/results/models.py b/tabbycat/results/models.py similarity index 85% rename from results/models.py rename to tabbycat/results/models.py index a0b37afe4dc..1b1aca5609a 100644 --- a/results/models.py +++ b/tabbycat/results/models.py @@ -1,11 +1,12 @@ +import logging +from threading import Lock + from django.db import models -from django.utils.functional import cached_property from django.conf import settings -from django.core.exceptions import ValidationError, ObjectDoesNotExist, MultipleObjectsReturned -from threading import Lock +from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist, ValidationError + from .result import BallotSet -import logging logger = logging.getLogger(__name__) @@ -89,9 +90,9 @@ def save(self, *args, **kwargs): super(Submission, self).save(*args, **kwargs) def clean(self): + super().clean() if self.submitter_type == self.SUBMITTER_TABROOM and self.submitter is None: - raise ValidationError( - "A tab room ballot must have a user associated.") + raise ValidationError("A tab room ballot must have a user associated.") class BallotSubmission(Submission): @@ -119,7 +120,7 @@ def __str__(self): time=('' if self.timestamp is None else str( self.timestamp.isoformat()))) - @cached_property + @property def ballot_set(self): if not hasattr(self, "_ballot_set"): self._ballot_set = BallotSet(self) @@ -127,15 +128,14 @@ def ballot_set(self): def clean(self): # The motion must be from the relevant round - super(BallotSubmission, self).clean() + super().clean() if self.motion.round != self.debate.round: raise ValidationError( "Debate is in round {:d} but motion ({:s}) is from round {:d}".format( self.debate.round, self.motion.reference, self.motion.round)) if self.confirmed and self.discarded: - raise ValidationError( - "A ballot can't be both confirmed and discarded!") + raise ValidationError("A ballot can't be both confirmed and discarded!") def is_identical(self, other): """Returns True if all data fields are the same. Returns False in any @@ -178,9 +178,9 @@ def check(this, other_set, fields): return True # For further discussion - #submitter_name = models.CharField(max_length=40, null=True) # only relevant for public submissions - #submitter_email = models.EmailField(max_length=254, blank=True, null=True) # only relevant for public submissions - #submitter_phone = models.CharField(max_length=40, blank=True, null=True) # only relevant for public submissions + # submitter_name = models.CharField(max_length=40, null=True) # only relevant for public submissions + # submitter_email = models.EmailField(max_length=254, blank=True, null=True) # only relevant for public submissions + # submitter_phone = models.CharField(max_length=40, blank=True, null=True) # only relevant for public submissions class SpeakerScoreByAdj(models.Model): @@ -201,6 +201,13 @@ class Meta: def debate(self): return self.debate_team.debate + def clean(self): + super().clean() + if (self.debate_team.debate != self.debate_adjudicator.debate or + self.debate_team.debate != self.ballot_submission.debate): + raise ValidationError("The debate team, debate adjudicator and ballot " + "submission must all relate to the same debate.") + class TeamScore(models.Model): """Stores information about a team's result in a debate. This is all @@ -216,7 +223,8 @@ class TeamScore(models.Model): win = models.NullBooleanField() score = ScoreField() - forfeit = models.BooleanField(default=False, blank=False, null=False, + forfeit = models.BooleanField( + default=False, blank=False, null=False, help_text="Debate was a forfeit (True for both winning and forfeiting teams)") class Meta: @@ -227,8 +235,7 @@ class SpeakerScoreManager(models.Manager): use_for_related_fields = True def get_queryset(self): - return super(SpeakerScoreManager, - self).get_queryset().select_related('speaker') + return super().get_queryset().select_related('speaker') class SpeakerScore(models.Model): @@ -249,3 +256,12 @@ class SpeakerScore(models.Model): class Meta: unique_together = [('debate_team', 'speaker', 'position', 'ballot_submission')] + + def clean(self): + super().clean() + if self.debate_team.team != self.speaker.team: + raise ValidationError("The debate team and speaker must be from the " + "same team.") + if self.ballot_submission.debate != self.debate_team.debate: + raise ValidationError("The ballot submission and debate team must " + "relate to the same debate.") diff --git a/tabbycat/results/prefetch.py b/tabbycat/results/prefetch.py new file mode 100644 index 00000000000..c1af480ec23 --- /dev/null +++ b/tabbycat/results/prefetch.py @@ -0,0 +1,144 @@ +"""Functions that prefetch data for efficiency.""" + +from adjallocation.models import DebateAdjudicator +from draw.models import DebateTeam +from motions.models import DebateTeamMotionPreference + +from .models import BallotSubmission, SpeakerScore, SpeakerScoreByAdj, TeamScore +from .result import BallotSet, Scoresheet + + +def populate_wins(debates): + """Sets an attribute `_win` on each DebateTeam in each Debate, representing + whether they won the debate. For best results, the caller should already + have run populate_teams(debates) in draw/prefetch.py before calling this + function. + + This can be used for efficiency, since it retrieves all of the + information in bulk in a single SQL query. Operates in-place. + """ + + debateteams = [dt for debate in debates for dt in [debate.aff_dt, debate.neg_dt]] + debateteams_by_id = {dt.id: dt for dt in debateteams} + + teamscores = TeamScore.objects.filter(debate_team__debate__in=debates, ballot_submission__confirmed=True) + + for teamscore in teamscores: + debateteam = debateteams_by_id[teamscore.debate_team_id] + debateteam._win = teamscore.win + + # populate the attribute for DebateTeams that don't have a result + for debateteam in debateteams: + if not hasattr(debateteam, "_win"): + debateteam._win = None + + +def populate_confirmed_ballots(debates, motions=False, ballotsets=False): + """Sets an attribute `_confirmed_ballot` on each Debate, each being the + BallotSubmission instance for that debate. + + All of the debates are assumed to be from the same tournament as the first. + + This can be used for efficiency, since it retrieves all of the + information in bulk in a single SQL query. Operates in-place. + + For best performance, the debates should already have + debateadjudicator_set__adjudicator prefetched. + """ + debates_by_id = {debate.id: debate for debate in debates} + confirmed_ballots = BallotSubmission.objects.filter(debate__in=debates, confirmed=True) + if motions: + confirmed_ballots = confirmed_ballots.select_related('motion') + if ballotsets: + confirmed_ballots = confirmed_ballots.select_related('debate') # BallotSet fetches the debate + + for ballotsub in confirmed_ballots: + debate = debates_by_id[ballotsub.debate_id] + debate._confirmed_ballot = ballotsub + + # populate the attribute for Debates that don't have a confirmed ballot + for debate in debates: + if not hasattr(debate, "_confirmed_ballot"): + debate._confirmed_ballot = None + + try: + POSITIONS = debates[0].round.tournament.POSITIONS # noqa + except IndexError: + return + + if ballotsets: + + debateteams_by_debate_id = {} + ballotsets_by_debate_id = {} + ballotsets_by_ballotsub_id = {} + + # Populate debateteams + debateteams = DebateTeam.objects.filter(debate__in=debates).select_related('team') + for dt in debateteams: + debateteams_by_debate_id.setdefault(dt.debate_id, []).append(dt) + + # Create the BallotSets + # --------------------- + for ballotsub in confirmed_ballots: + ballotset = BallotSet(ballotsub, load=False) + ballotset.debate = debates_by_id[ballotsub.debate_id] # this instance is probably prefetched + ballotset.POSITIONS = POSITIONS + ballotset.update_debateteams(debateteams_by_debate_id[ballotsub.debate_id]) + ballotset.init_blank_buffer() + ballotset._adjudicator_sheets = {} + ballotset._sheets_created = True + + ballotsub._ballot_set = ballotset + ballotsets_by_debate_id[ballotsub.debate_id] = ballotset + ballotsets_by_ballotsub_id[ballotsub.id] = ballotset + + # Populate speaker positions + speakerscores = SpeakerScore.objects.filter( + ballot_submission__in=confirmed_ballots).select_related('debate_team') + for ss in speakerscores: + ballotset = ballotsets_by_ballotsub_id[ss.ballot_submission_id] + ballotset.speakers[ss.debate_team][ss.position] = ss.speaker + + # Populate teamscores + teamscores = TeamScore.objects.filter( + ballot_submission__in=confirmed_ballots).select_related('debate_team') + for ts in teamscores: + ballotset = ballotsets_by_ballotsub_id[ts.ballot_submission_id] + ballotset.teamscore_objects[ts.debate_team] = ts.debate_team + + # Populate motion vetoes + dtmps = DebateTeamMotionPreference.objects.filter( + ballot_submission__in=confirmed_ballots, preference=3).select_related( + 'debate_team', 'motion') + for dtmp in dtmps: + ballotset = ballotsets_by_ballotsub_id[dtmp.ballot_submission_id] + ballotset.motion_veto[dtmp.debate_team] = dtmp.motion + + # Create the Scoresheets + # ---------------------- + scoresheets_by_debateadj_id = {} + debateadjs = DebateAdjudicator.objects.filter( + debate__in=ballotsets_by_debate_id.keys()).exclude( + type=DebateAdjudicator.TYPE_TRAINEE).select_related('adjudicator') + for da in debateadjs: + ballotset = ballotsets_by_debate_id[da.debate_id] + scoresheet = Scoresheet(ballotset.ballotsub, da.adjudicator, load=False) + scoresheet.da = da + scoresheet.POSITIONS = POSITIONS + scoresheet.update_debateteams(debateteams_by_debate_id[da.debate_id]) + scoresheet.init_blank_buffer() + + ballotset._adjudicator_sheets[da.adjudicator] = scoresheet + scoresheets_by_debateadj_id[da.id] = scoresheet + + ssbas = SpeakerScoreByAdj.objects.filter(debate_team__debate__in=debates, + ballot_submission__in=confirmed_ballots, + debate_adjudicator__in=debateadjs).select_related('debate_team') + for ssba in ssbas: + scoresheet = scoresheets_by_debateadj_id[ssba.debate_adjudicator_id] + scoresheet._set_score(ssba.debate_team, ssba.position, ssba.score) + + # Finally, check that everything is in order + # ------------------------------------------ + for ballotsub in confirmed_ballots: + ballotsub.ballot_set.assert_loaded() diff --git a/results/result.py b/tabbycat/results/result.py similarity index 63% rename from results/result.py rename to tabbycat/results/result.py index afa84d5bcfe..28ad0ccbd90 100644 --- a/results/result.py +++ b/tabbycat/results/result.py @@ -1,13 +1,89 @@ from functools import wraps from statistics import mean + from django.core.exceptions import ObjectDoesNotExist -from adjallocation.models import DebateAdjudicator + +from adjallocation.allocation import AdjudicatorAllocation from draw.models import DebateTeam + class ResultError(RuntimeError): pass -class Scoresheet(object): + +class ResultBuffer: + """Provides functionality common to both Scoresheet and BallotSet.""" + + SIDES = [DebateTeam.POSITION_AFFIRMATIVE, DebateTeam.POSITION_NEGATIVE] + SIDE_KEYS = { + DebateTeam.POSITION_AFFIRMATIVE: 'aff', + DebateTeam.POSITION_NEGATIVE: 'neg', + } + + def __init__(self, ballotsub, load=True): + """Base constructor. Populates `ballotsub`, `debate` and `dts`. + It's on subclasses to do the rest. The base constructor does *not* call + `assert_loaded()`, since subclasses may have more to do for themselves. + Subclasses should call `assert_loaded()` at the end of their + constructors. + + If `load` is False, the constructor will not load any data from the + database (at all). It is then the responsibility of the caller to do so; + the instance will crash otherwise, as the relevant attributes will not + be created. (For example, populate_confirmed_ballots() does this in + prefetch.py.) External constructors can use `assert_loaded()` to check + that data was loaded correctly. + """ + self.ballotsub = ballotsub + self.debate = ballotsub.debate + + if load: + # If updating any of the database loading, be sure also to update + # populate_confirmed_ballots() in prefetch.py. + self.POSITIONS = self.debate.round.tournament.POSITIONS + self.update_debateteams(self.debate.debateteam_set.all()) + + def _dt(self, team): + """Extracts a DebateTeam from a given team argument. The argument can be + either a Team or 'aff'/'neg'.""" + try: + return self._dts_lookup[team] + except KeyError: + raise ValueError("The team %s is not in the debate for this scoresheet." % team) + + def update_debateteams(self, debateteams): + """Updates the self.dts list, and self._other and self._dts_lookup dicts.""" + + self.dts = list(debateteams) + assert len(self.dts) == 2, "There aren't two DebateTeams in this debate: %s." % self.debate + + self._dts_lookup = {dt.team: dt for dt in debateteams} + + for dt in debateteams: + if dt.position == DebateTeam.POSITION_UNALLOCATED: + continue + key = self.SIDE_KEYS[dt.position] + self._dts_lookup[key] = dt + + self._other = {debateteams[0]: debateteams[1], debateteams[1]: debateteams[0]} + + def assert_loaded(self): + """Verifies that the self.dts dict is correctly set up. Returns the + aff and neg DebateTeams as a convenience for subclasses.""" + + assert hasattr(self, 'POSITIONS') + assert len(self.dts) == 2 + assert isinstance(self.dts, list) # order needs to be consistent + assert all(dt.team in self._dts_lookup for dt in self.dts) + assert all(dt in self._other for dt in self.dts) + + assert len(self._dts_lookup) == 2 or len(self._dts_lookup) == 4 + if len(self.dts) == 4: # known sides + assert 'aff' in self._dts_lookup + assert 'neg' in self._dts_lookup + + +class Scoresheet(ResultBuffer): """Representation of a single adjudicator's scoresheet in a single ballot submission, providing an interface that abstracts away database operations. Each instance initializes itself with the appropriate data on construction. @@ -28,26 +104,55 @@ class Scoresheet(object): self.data[debateteam][pos] = score. This is known as the "buffer".""" - def __init__(self, ballotsub, adjudicator): - self.ballotsub = ballotsub - self.debate = ballotsub.debate + def __init__(self, ballotsub, adjudicator, load=True): + """Constructor. + `ballotsub` must be a BallotSubmission. + `adjudicator` must be an Adjudicator. + + If `load` is False, the constructor will not load any data from the + database (at all). It is then the responsibility of the caller to do so; + the instance will crash otherwise, as the relevant attributes will not + be created. (For example, in prefetch.py, populate_confirmed_ballots() + uses this to load Scoresheets in bulk.) Callers can use + Scoresheet.assert_load() to check that data was loaded correctly. + """ + super().__init__(ballotsub, load=load) + self.adjudicator = adjudicator - self.da = self.debate.debateadjudicator_set.get(adjudicator=adjudicator) - self.dts = self.debate.debateteam_set.all() # note, this is a QuerySet - self.POSITIONS = self.debate.round.tournament.POSITIONS - self.data = {dt: dict.fromkeys(self.POSITIONS, None) for dt in self.dts} - for dt in self.dts: - self._load_team(dt) - def _dt(self, team): - """Extracts a DebateTeam from a given team argument. The argument can be - either a Team or 'aff'/'neg'.""" - if team in ['aff', 'neg']: - return self.debate.get_dt(team) + if load: + # If updating any of the database loading, be sure also to update + # populate_confirmed_ballots() in prefetch.py. + self.da = self.debate.debateadjudicator_set.get(adjudicator=adjudicator) + self.init_blank_buffer() + for dt in self.dts: + self._load_team(dt) + self.assert_loaded() + + # -------------------------------------------------------------------------- + # Initialisation methods (external initialisers may find these helpful) + # -------------------------------------------------------------------------- + + def init_blank_buffer(self): try: - return self.dts.get(team=team) - except ObjectDoesNotExist: - raise ValueError("The team %s is not in the debate for this scoresheet." % team) + self.data = {dt: dict.fromkeys(self.POSITIONS, None) for dt in self.dts} + except AttributeError: + if not hasattr(self, 'dts') or not hasattr(self, 'POSITIONS'): + raise AttributeError("Scoresheet must have dts and POSITIONS attributes before init_blank_buffer() is called.") + else: + raise + + def assert_loaded(self): + """Verifies that all essential internal variables are correctly set up. + Specifically, it checks that keys in internal dicts are present as + expected and no more, but it does not check any of their types. + Raises an AssertionError if something is wrong. + """ + super().assert_loaded() + assert self.da.adjudicator_id == self.adjudicator.id + for dt in self.dts: + assert len(self.data[dt]) == len(self.POSITIONS) + assert all(p in self.data[dt] for p in self.POSITIONS) # -------------------------------------------------------------------------- # Load and save methods @@ -55,13 +160,11 @@ def _dt(self, team): @property def is_complete(self): - return all(all(self.data[dt][p] is not None for p in self.POSITIONS) \ - for dt in self.dts) + return all(self.data[dt][p] is not None for dt in self.dts for p in self.POSITIONS) def save(self): """Saves the information in this instance to the database.""" assert self.is_complete, "Tried to save scoresheet when it is incomplete" - self.ballotsub.speakerscorebyadj_set.filter(debate_adjudicator=self.da).delete() for dt in self.dts: self._save_team(dt) @@ -69,7 +172,7 @@ def _load_team(self, dt): """Loads the scores for the given DebateTeam from the database into the buffer.""" scores = self.ballotsub.speakerscorebyadj_set.filter( - debate_adjudicator=self.da, debate_team=dt) + debate_adjudicator=self.da, debate_team=dt) for ss in scores: self._set_score(dt, ss.position, ss.score) @@ -77,11 +180,11 @@ def _save_team(self, dt): """Saves the scores in the buffer for the given DebateTeam, to the database.""" for pos in self.POSITIONS: - self.ballotsub.speakerscorebyadj_set.create( + self.ballotsub.speakerscorebyadj_set.update_or_create( debate_adjudicator=self.da, debate_team=dt, position=pos, - score=self._get_score(dt, pos), + defaults=dict(score=self._get_score(dt, pos)) ) # -------------------------------------------------------------------------- @@ -127,15 +230,14 @@ def _get_winner(self): incomplete or if it is a draw.""" if not self.is_complete: return None - dts = list(self.dts) # fix order for loops - totals = [self._get_total(dt) for dt in dts] + totals = [self._get_total(dt) for dt in self.dts] max_total = max(totals) if totals.count(max_total) > 1: return None - for dt, total in zip(dts, totals): + for dt, total in zip(self.dts, totals): if total == max_total: return dt - raise RuntimeError("Unexpected error") # this should never happen + raise RuntimeError("Unexpected error") # this should never happen # -------------------------------------------------------------------------- # Side-specific methods @@ -158,7 +260,7 @@ def neg_win(self): return self.neg_score > self.aff_score -class BallotSet(object): +class BallotSet(ResultBuffer): """Representation of a set of ballots for a debate in a single ballot submission, providing an interface that abstracts away database operations. In particular, this class makes it easier for views and forms to work with a @@ -178,45 +280,75 @@ class BallotSet(object): - Calculates the majority-average speaker scores. """ - - def __init__(self, ballotsub): + def __init__(self, ballotsub, load=True): """Constructor. - 'ballotsub' must be a BallotSubmission. + `ballotsub` must be a BallotSubmission. + + If `load` is False, the constructor will not load any data from the + database (at all). It is then the responsibility of the caller to do so; + the instance will crash otherwise, as the relevant attributes will not + be created. (For example, in prefetch.py, populate_confirmed_ballots() + uses this to load BallotSets in bulk.) Callers can use + BallotSet.assert_load() to check that data was loaded correctly. """ - self.ballotsub = ballotsub - self.debate = ballotsub.debate - self.adjudicators = self.debate.adjudicators.list - self.dts = self.debate.debateteam_set.all() # note, this is a QuerySet - assert self.dts.count() == 2, "There aren't two DebateTeams in this debate: %s." % self.debate - - self.SIDES = (DebateTeam.POSITION_AFFIRMATIVE, DebateTeam.POSITION_NEGATIVE) - self.POSITIONS = self.debate.round.tournament.POSITIONS + super().__init__(ballotsub, load=load) self._sheets_created = False self._decision_calculated = False self._adjudicator_sheets = None - self.speakers = {dt: {} for dt in self.dts} - self.motion_veto = dict.fromkeys(self.dts, None) - - # Values from the database are returned if requested before - # self.adjudicator_sheets is called, for efficiency. - self.teamscore_objects = dict.fromkeys(self.dts, None) - - self._other = {self.dts[0]: self.dts[1], self.dts[1]: self.dts[0]} + if load: + # If updating any of the database loading, be sure also to update + # populate_confirmed_ballots() in prefetch.py. + self.init_blank_buffer() + for dt in self.dts: + self._load_team(dt) + self.assert_loaded() - for dt in self.dts: - self._load_team(dt) + # -------------------------------------------------------------------------- + # Initialisation methods (external initialisers may find these helpful) + # -------------------------------------------------------------------------- - def _dt(self, team): - """Extracts a DebateTeam from a given team argument. The argument can be - either a Team or 'aff'/'neg'.""" - if team in ['aff', 'neg']: - return self.debate.get_dt(team) + def init_blank_buffer(self): + """Initialises the data attributes. External initialisers might find + this helpful. The `self.dts` and `self.POSITIONS` attributes must be set + prior to calling this function.""" try: - return self.dts.get(team=team) - except ObjectDoesNotExist: - raise ValueError("The team %s is not in the debate for this scoresheet." % team) + self.speakers = {dt: dict.fromkeys(self.POSITIONS, None) for dt in self.dts} + self.motion_veto = dict.fromkeys(self.dts, None) + + # Values from the database are returned if requested before + # self.adjudicator_sheets is called, for efficiency. + self.teamscore_objects = dict.fromkeys(self.dts, None) + + except AttributeError: + if not hasattr(self, 'dts') or not hasattr(self, 'POSITIONS'): + raise AttributeError("The BallotSet instance must have dts and POSITIONS attributes before init_blank_buffer() is called.") + else: + raise + + def assert_loaded(self): + """Verifies that all essential internal variables are correctly set up. + Specifically, it checks that keys in internal dicts are present as + expected and no more, but it does not check any of their types. + Raises an AssertionError if something is wrong. + """ + super().assert_loaded() + for dt in self.dts: + assert dt in self.speakers + assert dt in self.motion_veto + assert dt in self.teamscore_objects + assert len(self.speakers[dt]) == len(self.POSITIONS) + assert all(pos in self.speakers[dt] for pos in self.POSITIONS) + assert len(self.speakers) == 2 + assert len(self.motion_veto) == 2 + assert len(self.teamscore_objects) == 2 + + if self._sheets_created: + assert isinstance(self._adjudicator_sheets, dict) + for adj, scoresheet in self._adjudicator_sheets.items(): + assert adj == scoresheet.adjudicator + scoresheet.assert_loaded() # -------------------------------------------------------------------------- # Load and save methods @@ -226,18 +358,22 @@ def _dt(self, team): def adjudicator_sheets(self): if self._adjudicator_sheets is None: self._adjudicator_sheets = {a: Scoresheet(self.ballotsub, a) - for a in self.adjudicators} + for a in self.debate.adjudicators.voting()} self._sheets_created = True return self._adjudicator_sheets @property def is_complete(self): - return all(sheet.is_complete for sheet in self.adjudicator_sheets.values()) + if not all(sheet.is_complete for sheet in self.adjudicator_sheets.values()): + return False + if not all(self.speakers[dt][p] is not None for dt in self.dts for p in self.POSITIONS): + return False + return True def save(self): assert self.is_complete, "Tried to save ballot set when it is incomplete" - self.ballotsub.save() # need BallotSubmission object to exist first + self.ballotsub.save() # need BallotSubmission object to exist first for sheet in self.adjudicator_sheets.values(): sheet.save() self._calc_decision() @@ -248,7 +384,7 @@ def save(self): def _load_team(self, dt): """Loads the scores for the given DebateTeam from the database into the buffer.""" - for ss in self.ballotsub.speakerscore_set.filter(debate_team=dt): + for ss in self.ballotsub.speakerscore_set.filter(debate_team=dt).select_related('speaker'): self.speakers[dt][ss.position] = ss.speaker # ignore the speaker score itself, just look at SpeakerScoreByAdjs @@ -259,7 +395,7 @@ def _load_team(self, dt): try: dtmp = self.ballotsub.debateteammotionpreference_set.get( - debate_team=dt, preference=3) + debate_team=dt, preference=3) self.motion_veto[dt] = dtmp.motion except ObjectDoesNotExist: self.motion_veto[dt] = None @@ -271,22 +407,18 @@ def _save_team(self, dt): points = self._get_points(dt) win = self._get_win(dt) margin = self._get_margin(dt) - self.ballotsub.teamscore_set.filter(debate_team=dt).delete() - self.ballotsub.teamscore_set.create(debate_team=dt, score=total, - points=points, win=win, margin=margin) + self.ballotsub.teamscore_set.update_or_create(debate_team=dt, + defaults=dict(score=total, points=points, win=win, margin=margin)) - self.ballotsub.speakerscore_set.filter(debate_team=dt).delete() for pos in self.POSITIONS: speaker = self.speakers[dt][pos] score = self._get_avg_score(dt, pos) - self.ballotsub.speakerscore_set.create(debate_team=dt, - speaker=speaker, score=score, position=pos) + self.ballotsub.speakerscore_set.update_or_create(debate_team=dt, + speaker=speaker, position=pos, defaults=dict(score=score)) - self.ballotsub.debateteammotionpreference_set.filter(debate_team=dt, - preference=3).delete() if self.motion_veto[dt] is not None: - self.ballotsub.debateteammotionpreference_set.create(debate_team=dt, - preference=3, motion=self.motion_veto[dt]) + self.ballotsub.debateteammotionpreference_set.update_or_create( + debate_team=dt, preference=3, defaults=dict(motion=self.motion_veto[dt])) # -------------------------------------------------------------------------- # Data setting and retrieval (speakers and per-adjudicator scores) @@ -301,7 +433,7 @@ def set_sides(self, *teams): for position, dt in zip(self.SIDES, dts): dt.position = position dt.save() - self.dts = self.debate.debateteam_set.all() # refresh self.dts + self.update_debateteams(self.debate.debateteam_set.all()) # refresh self.dts def get_speaker(self, team, position): """Returns the speaker object for team/position.""" @@ -399,7 +531,7 @@ def _calc_decision(self): counts = {dt: len(adjs) for dt, adjs in self._adjs_by_dt.items()} max_count = max(counts.values()) # check that we have a majority - if max_count < len(self.adjudicators) // 2 + 1: + if max_count < self.debate.adjudicators.num_voting // 2 + 1: raise ResultError("No team had a majority in %s." % self.debate.matchup) for dt, count in counts.items(): # set self._winner @@ -409,7 +541,7 @@ def _calc_decision(self): self._decision_calculated = True - def _requires_decision(default): + def _requires_decision(default): # flake8: noqa def wrap(func): @wraps(func) def wrapped(self, *args, **kwargs): @@ -444,8 +576,7 @@ def _get_avg_total(self, dt): return mean(self.adjudicator_sheets[adj]._get_total(dt) for adj in self.majority_adj) def _dissenting_inclusive_score(self, dt): - return mean(self.adjudicator_sheets[adj]._get_total(dt) for adj in self.adjudicators) - + return mean(self.adjudicator_sheets[adj]._get_total(dt) for adj in self.debate.adjudicators.voting()) # Abstracted to not be tied to wins def _get_points(self, dt): @@ -535,26 +666,24 @@ def neg_motion_veto(self, new): # Methods for UI display # -------------------------------------------------------------------------- - def _is_trainee(self, adj): - da = self.debate.debateadjudicator_set.get(adjudicator=adj) - return da.type == DebateAdjudicator.TYPE_TRAINEE - @property def adjudicator_results(self): - """Iterator. Each iteration is a 3-tuple (adjtype, adj, split), where - adjtype is a DebateAdjudicator.TYPE_* constant, adj is an Adjudicator - object, and split is True if the adjudicator was in the minority and - not a trainee, False if the adjudicator was in the majority or is a - trainee. If there is no available result, split is always False.""" + """Iterator. Each iteration is a 3-tuple (adj, adjtype, split), where + adjtype is a AdjudicatorAllocation.POSITION_* constant, adj is an + Adjudicator object, and split is True if the adjudicator was in the + minority and not a trainee, False if the adjudicator was in the majority + or is a trainee. If there is no available result, split is always + False.""" + try: self._calc_decision() except (ResultError, AssertionError): - for adjtype, adj in self.debate.adjudicators: - yield adjtype, adj, False + for adj, adjtype in self.debate.adjudicators.with_positions(): + yield adj, adjtype, False else: - for adjtype, adj in self.debate.adjudicators: - yield adjtype, adj, (adj not in self.majority_adj and - adjtype != DebateAdjudicator.TYPE_TRAINEE) + for adj, adjtype in self.debate.adjudicators.with_positions(): + split = (adj not in self.majority_adj and adjtype != AdjudicatorAllocation.POSITION_TRAINEE) + yield adj, adjtype, split @property def sheet_iter(self): @@ -569,8 +698,8 @@ def sheet_iter(self): print pos.name, pos.speaker, pos.score print sheet.neg_score, sheet.neg_win """ - REPLY_POSITION = self.debate.round.tournament.REPLY_POSITION - POSITIONS = self.debate.round.tournament.POSITIONS + reply_position = self.debate.round.tournament.REPLY_POSITION + positions = self.debate.round.tournament.POSITIONS ballotset = self # provide access in inner classes class Position(object): @@ -582,7 +711,7 @@ def __init__(self, sheet, side, pos): @property def name(self): - return "Reply" if (self.pos == REPLY_POSITION) else str(self.pos) + return "Reply" if (self.pos == reply_position) else str(self.pos) @property def speaker(self): @@ -599,7 +728,7 @@ def __init__(self, adj): self.adjudicator = adj def position_iter(self, side): - for pos in POSITIONS: + for pos in positions: yield Position(self.sheet, side, pos) @property @@ -626,7 +755,7 @@ def aff_win(self): def neg_win(self): return self.sheet.neg_win - for adj in self.adjudicators: + for adj in self.debate.adjudicators.voting(): yield ScoresheetWrapper(adj) @@ -639,10 +768,9 @@ def __init__(self, ballotsub, forfeiter): """ self.ballotsub = ballotsub self.debate = ballotsub.debate - self.adjudicators = self.debate.adjudicators.list self.forfeiter = forfeiter self.motion_veto = None - self.dts = self.debate.debateteam_set.all() # note, this is a QuerySet + self.dts = self.debate.debateteam_set.all() # Note, this is a QuerySet def _save_team(self, dt): if self.forfeiter == dt: @@ -652,10 +780,10 @@ def _save_team(self, dt): points = 1 win = True - # Note: forfeited debates have fake scores/margins, thus the affects_average toggle - self.ballotsub.teamscore_set.filter(debate_team=dt).delete() - self.ballotsub.teamscore_set.create(debate_team=dt, points=points, - win=win, score=0, margin=0, forfeit=True) + # The `forfeit` flag indicates that the ballot should not count as part + # of averages. + self.ballotsub.teamscore_set.update_or_create(debate_team=dt, + default=dict(points=points, win=win, score=0, margin=0, forfeit=True)) def save(self): self.ballotsub.forfeit = self.forfeiter diff --git a/tabbycat/results/tables.py b/tabbycat/results/tables.py new file mode 100644 index 00000000000..ec8e065f150 --- /dev/null +++ b/tabbycat/results/tables.py @@ -0,0 +1,93 @@ +from utils.misc import reverse_tournament +from utils.tables import TabbycatTableBuilder + + +class ResultsTableBuilder(TabbycatTableBuilder): + """Painfully construct the edit links; this is the only case where + a cell has multiple links; hence the creating HTML directly""" + + def get_status_meta(self, debate): + if debate.aff_team.type == 'B' or debate.neg_team.type == 'B': + return "glyphicon-fast-forward", 5, "Bye Debate" + elif debate.result_status == debate.STATUS_NONE and not debate.ballot_in: + return "glyphicon-remove text-danger", 0, "No Ballot" + elif debate.result_status == debate.STATUS_NONE and debate.ballot_in: + return "glyphicon-inbox text-warning", 1, "Ballot is In" + elif debate.result_status == debate.STATUS_DRAFT: + return "glyphicon-adjust text-info", 2, "Ballot is Unconfirmed" + elif debate.result_status == debate.STATUS_CONFIRMED: + return "glyphicon-ok text-success", 3, "Ballot is Confirmed" + elif debate.result_status == debate.STATUS_POSTPONED: + return "glyphicon-pause", 4, "Debate was Postponed" + else: + raise ValueError('Debate has no discernable status') + + def add_ballot_status_columns(self, debates, key="Status"): + + status_header = { + 'key': key, + 'tooltip': "Status of this debate's ballot", + 'icon': "glyphicon-th-list", + } + status_cell = [{ + 'icon': self.get_status_meta(debate)[0], + 'sort': self.get_status_meta(debate)[1], + 'tooltip': self.get_status_meta(debate)[2] + } for debate in debates] + self.add_column(status_header, status_cell) + + def get_ballot_text(self, debate): + ballotsets_info = " " + + # These are prefetched, so sort using Python rather than generating an SQL query + ballotsubmissions = sorted(debate.ballotsubmission_set.all(), key=lambda x: x.version) + + for ballotset in ballotsubmissions: + if not self.admin and ballotset.discarded: + continue + + link = reverse_tournament('edit_ballotset', + self.tournament, + kwargs={'ballotsub_id': ballotset.id}) + ballotsets_info += "" + + if ballotset.confirmed: + edit_status = "Re-edit v" + str(ballotset.version) + elif self.admin: + edit_status = "Edit v" + str(ballotset.version) + else: + edit_status = "Review v" + str(ballotset.version) + + if ballotset.discarded: + ballotsets_info += "" + edit_status + " discarded; " + else: + ballotsets_info += edit_status + "" + + if ballotset.submitter_type == ballotset.SUBMITTER_TABROOM: + ballotsets_info += " entered by " + ballotset.submitter.username + "" + elif ballotset.submitter_type == ballotset.SUBMITTER_PUBLIC: + ballotsets_info += " a public submission by " + ballotset.ip_address + "" + + ballotsets_info += "
      " + + if all(x.discarded for x in ballotsubmissions): + link = reverse_tournament('new_ballotset', + self.tournament, + kwargs={'debate_id': debate.id}) + ballotsets_info += "Enter Ballot" + + return ballotsets_info + + def add_ballot_entry_columns(self, debates): + + entry_header = {'key': 'EB', 'icon': "glyphicon-plus"} + entry_cells = [{'text': self.get_ballot_text(d)} for d in debates] + self.add_column(entry_header, entry_cells) + + if self.tournament.pref('enable_postponements'): + postpones_header = {'key': 'Postpone'} + postpones_cells = [{ + 'text': 'Un-Postpone' if d.result_status == d.STATUS_POSTPONED else 'Postpone', + 'link': reverse_tournament('toggle_postponed', self.tournament, kwargs={'debate_id': d.id}) + } for d in debates] + self.add_column(postpones_header, postpones_cells) diff --git a/tournaments/__init__.py b/tabbycat/results/templates/__init__.py similarity index 100% rename from tournaments/__init__.py rename to tabbycat/results/templates/__init__.py diff --git a/results/templates/assistant_enter_results.html b/tabbycat/results/templates/assistant_enter_results.html similarity index 96% rename from results/templates/assistant_enter_results.html rename to tabbycat/results/templates/assistant_enter_results.html index 75306765692..b47be68fc5c 100644 --- a/results/templates/assistant_enter_results.html +++ b/tabbycat/results/templates/assistant_enter_results.html @@ -18,7 +18,9 @@
      -

      {% if new %}Save{% else %}Check{% endif %}

      +

      + {% if new %}Save{% else %}Check{% endif %} +

      {% if disable_confirm %}
      You can't confirm this ballot set because you entered it. @@ -48,7 +50,7 @@

      {% if new %}Save{% else %}Check{% endif %}

      {% endblock content %} -{% block extra-js %} +{% block js %} {{ block.super }} -{% endblock extra-js %} +{% endblock js %} diff --git a/results/templates/enter_results.html b/tabbycat/results/templates/enter_results.html similarity index 87% rename from results/templates/enter_results.html rename to tabbycat/results/templates/enter_results.html index d00afc864ff..7bce1829489 100644 --- a/results/templates/enter_results.html +++ b/tabbycat/results/templates/enter_results.html @@ -11,7 +11,9 @@ {% block page-title %}{{ debate.matchup }} {{ debate.round.name }} @ {% if debate.division.venue_group %}{{ debate.division.venue_group.short_name }} {% endif %}{{ debate.venue.name }}{% endblock %} {% block page-subnav-sections %} {% if not new %} - Create a new ballot set for this debate + + Create a new ballot set for this debate + {% endif %} {% endblock %} @@ -25,10 +27,9 @@ {% include "enter_results_ballot_set.html" %}
      -
      -

      Ballot Status

      +

      Ballot Status

      @@ -61,7 +62,10 @@

      Ballot Status

      -

      Debate Status (for the debate itself, not just this particular ballot set)

      +

      + Debate Status (for the debate itself, not just this + particular ballot set) +

      @@ -83,11 +87,12 @@

      Debate Status (for the debate itself, not just this particular ballot {% endblock content %} -{% block extra-js %} - +{% block js %} + {{ block.super }} + {% endblock %} diff --git a/tabbycat/results/templates/enter_results_ballot_set.html b/tabbycat/results/templates/enter_results_ballot_set.html new file mode 100644 index 00000000000..2b623993255 --- /dev/null +++ b/tabbycat/results/templates/enter_results_ballot_set.html @@ -0,0 +1,171 @@ +{% load add_field_css %} +{% load debate_tags %} + +
      + + {% if form.errors %} +
      +

      There are some problems with this scoresheet. Please review and correct them.

      + {% if form.non_field_errors %} +

      General errors:

      +
      {{ form.non_field_errors }}
      + {% endif %} +
      + {% endif %} + + {% if form.choose_sides %} +
      + +
      + {{ form.choose_sides|addcss:"form-control choose-sides required" }} + {{ form.choose_sides.errors }} +
      +
      + + {% endif %} + + + {% if pref.enable_motions or pref.enable_motions %} +
      +
      +
      +
      +

      Motion

      +
      +
      + {% if pref.enable_motions %} +
      + +
      + {{ form.motion|addcss:"form-control motion required" }} + {{ form.motion.errors }} +
      +
      + {% endif %} + {% if pref.motion_vetoes_enabled %} +
      + +
      + {{ form.aff_motion_veto|addcss:"form-control motion" }} + {{ form.aff_motion_veto.errors }} +
      +
      +
      + +
      + {{ form.neg_motion_veto|addcss:"form-control motion" }} + {{ form.neg_motion_veto.errors }} +
      +
      + {% endif %} +
      +
      +
      +
      + {% endif %} + + {% for adj in form.adj_iter %} +
      +
      +
      +
      +

      Ballot from {{ adj.adj }} + {% if pref.side_allocations_unknown == 'manual-ballot' %} +

      Assign sides before entering scores

      + {% endif %} +

      +
      +
      +
      +
      +
      + +
      + {% for position in adj.position_iter %} +
      + +
      + {% if forloop.parentloop.first %} + {{ position.aff_speaker|addcss:"form-control js-speaker required aff-speaker" }} + {{ position.aff_speaker.errors }} + {% else %} +
      + {% endif %} +
      +
      + {{ position.aff_score }} + {{ position.aff_score_errors }} + {{ position.aff_score.errors }} +
      +
      + {% endfor %} +
      + +
      +
      +
      00
      +
      +0
      +
      +
      +
      +
      +
      +
      + +
      + {% for position in adj.position_iter %} +
      + +
      + {% if forloop.parentloop.first %} + {{ position.neg_speaker|addcss:"form-control js-speaker required neg-speaker" }} + {{ position.neg_speaker.errors }} + {% else %} +
      + {% endif %} +
      +
      + {{ position.neg_score }} + {{ position.neg_score_errors }} + {{ position.neg_score.errors }} +
      +
      + {% endfor %} +
      + +
      +
      +
      +0
      +
      +0
      +
      +
      +
      +
      +
      +
      +
      +
      +
      + {% endfor %} + + {% if pref.enable_forfeits %} +
      +
      +
      +
      +

      Forfeits

      +
      +
      + {{ form.forfeits|addcss:"form-control" }} + {{ form.forfeits.errors }} +
      +
      +
      +
      + {% endif %} + +
      diff --git a/results/templates/other_ballots_list.html b/tabbycat/results/templates/other_ballots_list.html similarity index 100% rename from results/templates/other_ballots_list.html rename to tabbycat/results/templates/other_ballots_list.html diff --git a/results/templates/public_add_ballot.html b/tabbycat/results/templates/public_add_ballot.html similarity index 77% rename from results/templates/public_add_ballot.html rename to tabbycat/results/templates/public_add_ballot.html index 5fc28a3c28d..62a743638a1 100644 --- a/results/templates/public_add_ballot.html +++ b/tabbycat/results/templates/public_add_ballot.html @@ -6,7 +6,7 @@ {% block sub-title %}(click your name on this list){% endblock %} {% block content %} -

    +
    @@ -34,15 +34,3 @@ {% endfor %}
    Adj
    {% endblock %} - -{% block extra-js %} - {{ block.super }} - -{% endblock extra-js %} diff --git a/results/templates/public_add_ballot_unreleased.html b/tabbycat/results/templates/public_add_ballot_unreleased.html similarity index 100% rename from results/templates/public_add_ballot_unreleased.html rename to tabbycat/results/templates/public_add_ballot_unreleased.html diff --git a/results/templates/public_ballot_set.html b/tabbycat/results/templates/public_ballot_set.html similarity index 92% rename from results/templates/public_ballot_set.html rename to tabbycat/results/templates/public_ballot_set.html index 0311cfd6289..2ba12bb9f8a 100644 --- a/results/templates/public_ballot_set.html +++ b/tabbycat/results/templates/public_ballot_set.html @@ -26,7 +26,7 @@
    -

    Motion

    +

    Motion

    {{ ballot_set.motion.text }} @@ -37,7 +37,7 @@

    Motion

    -

    From {{ sheet.adjudicator }}

    +

    From {{ sheet.adjudicator }}

    @@ -58,7 +58,7 @@

    From {{ sheet.adjudicator }}

    {% endfor %}
    -
    +
    {{ sheet.aff_score }}
    @@ -81,7 +81,7 @@

    From {{ sheet.adjudicator }}

    {% endfor %}
    -
    +
    {{ sheet.neg_score }}
    diff --git a/results/templates/public_enter_results.html b/tabbycat/results/templates/public_enter_results.html similarity index 96% rename from results/templates/public_enter_results.html rename to tabbycat/results/templates/public_enter_results.html index a67e0543a81..72fdaf1d99f 100644 --- a/results/templates/public_enter_results.html +++ b/tabbycat/results/templates/public_enter_results.html @@ -62,9 +62,11 @@ {% endblock content %} -{% block extra-js %} +{% block js %} + {{ block.super }} - + + + + + {{ block.super }} +{% endblock js %} diff --git a/standings/templates/standings_base.html b/tabbycat/standings/templates/standings_base.html similarity index 79% rename from standings/templates/standings_base.html rename to tabbycat/standings/templates/standings_base.html index b1a0d06e83f..5d1a4a01cc4 100644 --- a/standings/templates/standings_base.html +++ b/tabbycat/standings/templates/standings_base.html @@ -1,37 +1,41 @@ -{% extends "base.html" %} +{% extends "base_vue_table.html" %} {% load debate_tags %} {% block page-subnav-sections %} - Standings Overview + Overview - Team Standings + Teams {% if pref.enable_divisions %} - Division Standings + Divisions {% endif %} - Speaker Standings + Speakers {% if pref.show_novices %} - Pros Standings + Pros - Novices Standings + Novices {% endif %} {% if pref.reply_scores_enabled %} - Replies Standings + Replies {% endif %} - Motion Balance + Motions Balance + + Diversity Overview + + {{ block.super }} {% endblock %} diff --git a/standings/templates/standings_index.html b/tabbycat/standings/templates/standings_index.html similarity index 89% rename from standings/templates/standings_index.html rename to tabbycat/standings/templates/standings_index.html index 36ec1d06e33..c91403b5872 100644 --- a/standings/templates/standings_index.html +++ b/tabbycat/standings/templates/standings_index.html @@ -3,7 +3,9 @@ {% load debate_tags %} {% block head-title %}📊Standings{% endblock %} -{% block page-title %}{% endblock %} +{% block page-title %}Standings{% endblock %} + +{% block standings_active %}active{% endblock %} {% block content %} @@ -13,7 +15,7 @@
    -

    Top Speaker Scores

    +

    Top Speaker Scores

      @@ -37,7 +39,7 @@

      Top Speaker Scores

      -

      Top Debate Margins

      +

      Top Debate Margins

        @@ -45,7 +47,7 @@

        Top Debate Margins

        {% for top_margin in top_margins %}
      • {{ top_margin.debate_team.team.short_name }} vs - {{ top_margin.debate_team.opposition.team.short_name }} in + {{ top_margin.debate_team.opponent.team.short_name }} in {{ top_margin.debate_team.debate.round.abbreviation }} {{ top_margin.margin|floatformat }}
      • @@ -63,7 +65,7 @@

        Top Debate Margins

        -

        Most Popular Motions

        +

        Most Popular Motions

          @@ -91,7 +93,7 @@

          Most Popular Motions

          -

          Bottom Speaker Scores

          +

          Bottom Speaker Scores

            @@ -115,7 +117,7 @@

            Bottom Speaker Scores

            -

            Closest Debate Margins

            +

            Closest Debate Margins

              @@ -123,7 +125,7 @@

              Closest Debate Margins

              {% for bottom_margin in bottom_margins %}
            • {{ bottom_margin.debate_team.team.short_name }} vs - {{ bottom_margin.debate_team.opposition.team.short_name }} in + {{ bottom_margin.debate_team.opponent.team.short_name }} in {{ bottom_margin.debate_team.debate.round.abbreviation }} {{ bottom_margin.margin|floatformat }}
            • @@ -141,7 +143,7 @@

              Closest Debate Margins

              -

              Least Popular Motions

              +

              Least Popular Motions

                diff --git a/utils/management/__init__.py b/tabbycat/standings/templatetags/__init__.py similarity index 100% rename from utils/management/__init__.py rename to tabbycat/standings/templatetags/__init__.py diff --git a/standings/templatetags/metricformat.py b/tabbycat/standings/templatetags/standingsformat.py similarity index 54% rename from standings/templatetags/metricformat.py rename to tabbycat/standings/templatetags/standingsformat.py index b3a5c876f74..fab4eb61be8 100644 --- a/standings/templatetags/metricformat.py +++ b/tabbycat/standings/templatetags/standingsformat.py @@ -2,9 +2,20 @@ register = template.Library() + @register.filter def metricformat(value): if isinstance(value, float): return "{0:.2f}".format(value) else: return str(value) + + +@register.filter +def rankingformat(value): + if value[0] is None: + return "" + string = str(value[0]) + if value[1]: + string += "=" + return string diff --git a/utils/templatetags/__init__.py b/tabbycat/standings/tests/__init__.py similarity index 100% rename from utils/templatetags/__init__.py rename to tabbycat/standings/tests/__init__.py diff --git a/standings/tests/generate_testdata.py b/tabbycat/standings/tests/generate_testdata.py similarity index 93% rename from standings/tests/generate_testdata.py rename to tabbycat/standings/tests/generate_testdata.py index 72023a31767..05ce30af142 100644 --- a/standings/tests/generate_testdata.py +++ b/tabbycat/standings/tests/generate_testdata.py @@ -22,8 +22,9 @@ # Comment out this line and add a new line setting up results to use doctored # scores. -results = [{debate: {team: {"score": round(random.normalvariate(75*3.5, 10)*2)/2} - for team in debate} for debate in rd} for rd in DRAW_FOR_WHOLE_TOURNAMENT] +results = [{debate: {team: {"score": round( + random.normalvariate(75*3.5, 10)*2)/2} for team in debate} for debate in rd} + for rd in DRAW_FOR_WHOLE_TOURNAMENT] # For example: # results = [{'AB': {'A': {'score': 269.5}, 'B': {'score': 254.0}}, @@ -57,8 +58,8 @@ "speaks_sum": sum(teamscore["score"] for teamscore in teamscores), "margin_sum": sum(teamscore["margin"] for teamscore in teamscores), "points": sum(teamscore["points"] for teamscore in teamscores), - "draw_strength": 0, # initialize - "against": dict.fromkeys([t for t in TEAMS if t is not team], "n/a"), # initialize + "draw_strength": 0, # Initialize + "against": dict.fromkeys([t for t in TEAMS if t is not team], "n/a"), # Initialize } # Build up standings metrics that require reference to opponents @@ -90,4 +91,4 @@ print("Test data, to be copied to test:") print("--------------------------------") pprint.pprint(testdata, width=100) -print("") \ No newline at end of file +print("") diff --git a/standings/tests/test_standings.py b/tabbycat/standings/tests/test_standings.py similarity index 97% rename from standings/tests/test_standings.py rename to tabbycat/standings/tests/test_standings.py index 6c954141afa..6206bf0d128 100644 --- a/standings/tests/test_standings.py +++ b/tabbycat/standings/tests/test_standings.py @@ -2,8 +2,8 @@ from ..teams import TeamStandingsGenerator -from tournaments.models import Tournament, Round -from participants.models import Institution, Team, Speaker, Adjudicator +from tournaments.models import Round, Tournament +from participants.models import Adjudicator, Institution, Team from venues.models import Venue from draw.models import Debate, DebateTeam from adjallocation.models import DebateAdjudicator @@ -58,7 +58,6 @@ class TestBasicStandings(TestCase): 'CD': {'C': {'margin': -13.5, 'points': 0, 'score': 246.5, 'win': False}, 'D': {'margin': 13.5, 'points': 1, 'score': 260.0, 'win': True}}}]} - rankings = ('rank',) def setup_testdata(self, testdata): @@ -118,4 +117,4 @@ def test_standings(self): # TODO check that WBW is correct when not in first metrics # TODO check that it doesn't break when not all metrics present - # TODO check that it works for different rounds \ No newline at end of file + # TODO check that it works for different rounds diff --git a/tabbycat/standings/urls_admin.py b/tabbycat/standings/urls_admin.py new file mode 100644 index 00000000000..93e7d3c4520 --- /dev/null +++ b/tabbycat/standings/urls_admin.py @@ -0,0 +1,37 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + + url(r'^$', + views.StandingsIndexView.as_view(), + name='standings-index'), + url(r'^team/$', + views.TeamStandingsView.as_view(), + name='standings-team'), + url(r'^division/$', + views.DivisionStandingsView.as_view(), + name='standings-division'), + + url(r'^speaker/$', + views.SpeakerStandingsView.as_view(), + name='standings-speaker'), + url(r'^novices/$', + views.NoviceStandingsView.as_view(), + name='standings-novice'), + url(r'^pros/$', + views.ProStandingsView.as_view(), + name='standings-pro'), + url(r'^reply/$', + views.ReplyStandingsView.as_view(), + name='standings-reply'), + + url(r'^motions/$', + views.MotionStandingsView.as_view(), + name='standings-motion'), + url(r'^diversity/$', + views.DiversityStandingsView.as_view(), + name='standings-diversity'), + +] diff --git a/standings/urls_public.py b/tabbycat/standings/urls_public.py similarity index 87% rename from standings/urls_public.py rename to tabbycat/standings/urls_public.py index 607ca61b35a..e2f862d0b9c 100644 --- a/standings/urls_public.py +++ b/tabbycat/standings/urls_public.py @@ -24,4 +24,7 @@ url(r'^motions/$', views.PublicMotionsTabView.as_view(), name='standings-public-tab-motions'), + url(r'^diversity/$', + views.PublicDiversityStandingsView.as_view(), + name='standings-public-diversity'), ] diff --git a/standings/views.py b/tabbycat/standings/views.py similarity index 55% rename from standings/views.py rename to tabbycat/standings/views.py index aeb0a765e7a..5a06b7d0bfe 100644 --- a/standings/views.py +++ b/tabbycat/standings/views.py @@ -1,19 +1,24 @@ -from django.db.models import Count -from django.views.generic.base import View, ContextMixin, TemplateView +import json + +from django.views.generic.base import TemplateView from django.conf import settings -from django.shortcuts import render +from django.contrib import messages +from django.db.models import Count import motions.statistics as motion_statistics from motions.models import Motion -from participants.models import Team, Speaker -from results.models import TeamScore, SpeakerScore -from tournaments.mixins import RoundMixin, PublicTournamentPageMixin +from participants.models import Speaker, Team +from results.models import SpeakerScore, TeamScore +from tournaments.mixins import PublicTournamentPageMixin, RoundMixin, TournamentMixin from tournaments.models import Round -from utils.mixins import SuperuserRequiredMixin +from utils.mixins import SuperuserRequiredMixin, VueTableTemplateView +from utils.tables import TabbycatTableBuilder +from .diversity import get_diversity_data_sets from .teams import TeamStandingsGenerator from .speakers import SpeakerStandingsGenerator -from .round_results import add_team_round_results, add_team_round_results_public, add_speaker_round_results +from .round_results import add_speaker_round_results, add_team_round_results, add_team_round_results_public +from .templatetags.standingsformat import metricformat class StandingsIndexView(SuperuserRequiredMixin, RoundMixin, TemplateView): @@ -24,19 +29,19 @@ def get_context_data(self, **kwargs): round = self.get_round() speaks = SpeakerScore.objects.filter(ballot_submission__confirmed=True).exclude( - position=round.tournament.REPLY_POSITION).select_related('debate_team__debate__round') + position=round.tournament.REPLY_POSITION).select_related('debate_team__debate__round') kwargs["top_speaks"] = speaks.order_by('-score')[:10] kwargs["bottom_speaks"] = speaks.order_by('score')[:10] - margins = TeamScore.objects.filter(ballot_submission__confirmed=True, - margin__gte=0).select_related( - 'debate_team__team', 'debate_team__debate__round', - 'debate_team__team__institution') + margins = TeamScore.objects.filter( + ballot_submission__confirmed=True, margin__gte=0).select_related( + 'debate_team__team', 'debate_team__debate__round', + 'debate_team__team__institution') kwargs["top_margins"] = margins.order_by('-margin')[:10] kwargs["bottom_margins"] = margins.order_by('margin')[:10] motions = Motion.objects.filter(round__seq__lte=round.seq).annotate( - Count('ballotsubmission')) + Count('ballotsubmission')) kwargs["top_motions"] = motions.order_by('-ballotsubmission__count')[:10] kwargs["bottom_motions"] = motions.order_by('ballotsubmission__count')[:10] @@ -56,32 +61,55 @@ def populate_result_missing(self, standings): pass +# ============================================================================== +# Shared standings +# ============================================================================== + +class StandingsView(RoundMixin, VueTableTemplateView): + pass + + # ============================================================================== # Speaker standings # ============================================================================== -class BaseSpeakerStandingsView(RoundMixin, ContextMixin, View): +class BaseSpeakerStandingsView(StandingsView): """Base class for views that display speaker standings.""" rankings = ('rank',) - def get(self, request, *args, **kwargs): + def get_standings(self): tournament = self.get_tournament() round = self.get_round() speakers = self.get_speakers() metrics, extra_metrics = self.get_metrics() rank_filter = self.get_rank_filter() - generator = SpeakerStandingsGenerator(metrics, self.rankings, extra_metrics, - rank_filter=rank_filter) + generator = SpeakerStandingsGenerator(metrics, self.rankings, + extra_metrics, + rank_filter=rank_filter) standings = generator.generate(speakers, round=round) rounds = tournament.prelim_rounds(until=round).order_by('seq') self.add_round_results(standings, rounds) self.populate_result_missing(standings) - context = self.get_context_data(standings=standings, rounds=rounds) - return render(request, self.template_name, context) + return standings, rounds + + def get_table(self): + standings, rounds = self.get_standings() + table = TabbycatTableBuilder(view=self, sort_key="Rk") + + table.add_ranking_columns(standings) + table.add_speaker_columns([info.speaker for info in standings]) + table.add_team_columns([info.speaker.team for info in standings]) + + scores_headers = [round.abbreviation for round in rounds] + scores_data = [list(map(metricformat, standing.scores)) for standing in standings] + table.add_columns(scores_headers, scores_data) + table.add_metric_columns(standings) + + return table def get_rank_filter(self): return None @@ -93,10 +121,12 @@ def populate_result_missing(self, standings): class BaseStandardSpeakerStandingsView(BaseSpeakerStandingsView): """The standard speaker standings view.""" + page_title = 'Speaker Tab' + page_emoji = '💯' def get_speakers(self): return Speaker.objects.filter(team__tournament=self.get_tournament()).select_related( - 'team', 'team__institution', 'team__tournament') + 'team', 'team__institution', 'team__tournament').prefetch_related('team__speaker_set') def get_metrics(self): method = self.get_tournament().pref('rank_speakers_by') @@ -108,7 +138,7 @@ def get_metrics(self): def get_rank_filter(self): tournament = self.get_tournament() total_prelim_rounds = tournament.round_set.filter( - stage=Round.STAGE_PRELIMINARY, seq__lte=self.get_round().seq).count() + stage=Round.STAGE_PRELIMINARY, seq__lte=self.get_round().seq).count() missable_debates = tournament.pref('standings_missed_debates') minimum_debates_needed = total_prelim_rounds - missable_debates return lambda info: info.metrics["speeches_count"] >= minimum_debates_needed @@ -118,56 +148,58 @@ def add_round_results(self, standings, rounds): class SpeakerStandingsView(SuperuserRequiredMixin, BaseStandardSpeakerStandingsView): - template_name = 'speakers.html' + template_name = 'standings_base.html' class PublicSpeakerTabView(PublicTabMixin, BaseStandardSpeakerStandingsView): public_page_preference = 'speaker_tab_released' - template_name = 'public_speaker_tab.html' class BaseNoviceStandingsView(BaseStandardSpeakerStandingsView): """Speaker standings view for novices.""" - - template_name = 'novices.html' + page_title = 'Novice Speaker Standings' def get_speakers(self): return super().get_speakers().filter(novice=True) class NoviceStandingsView(SuperuserRequiredMixin, BaseNoviceStandingsView): - template_name = 'novices.html' + template_name = 'standings_base.html' class PublicNoviceTabView(PublicTabMixin, BaseNoviceStandingsView): public_page_preference = 'novices_tab_released' - template_name = 'public_novices_tab.html' class BaseProStandingsView(BaseStandardSpeakerStandingsView): """Speaker standings view for non-novices (pro, varsity).""" + page_title = 'Pros Speaker Standings' + def get_speakers(self): return super().get_speakers().filter(novice=False) class ProStandingsView(SuperuserRequiredMixin, BaseProStandingsView): - template_name = 'speakers.html' + template_name = 'standings_base.html' class PublicProTabView(PublicTabMixin, BaseProStandingsView): public_page_preference = 'pros_tab_released' - template_name = 'public_pros_tab.html' class BaseReplyStandingsView(BaseSpeakerStandingsView): """Speaker standings view for replies.""" + page_title = 'Reply Speaker Standings' + page_emoji = '💁' def get_speakers(self): tournament = self.get_tournament() - return Speaker.objects.filter(team__tournament=tournament, - speakerscore__position=tournament.REPLY_POSITION).select_related( - 'team', 'team__institution', 'team__tournament').distinct() + return Speaker.objects.filter( + team__tournament=tournament, + speakerscore__position=tournament.REPLY_POSITION).select_related( + 'team', 'team__institution', 'team__tournament').prefetch_related( + 'team__speaker_set').distinct() def get_metrics(self): return ('replies_avg',), ('replies_stddev', 'replies_count') @@ -186,36 +218,28 @@ def populate_result_missing(self, standings): class ReplyStandingsView(SuperuserRequiredMixin, BaseReplyStandingsView): - template_name = 'replies.html' + template_name = 'standings_base.html' class PublicReplyTabView(PublicTabMixin, BaseReplyStandingsView): public_page_preference = 'replies_tab_released' - template_name = 'public_reply_tab.html' # ============================================================================== # Team standings # ============================================================================== -class BaseTeamStandingsView(RoundMixin, ContextMixin, View): +class BaseTeamStandingsView(StandingsView): """Base class for views that display team standings.""" - def get_context_data(self, **kwargs): - if 'show_ballots' not in kwargs: - kwargs['show_ballots'] = self.show_ballots() - if 'round' not in kwargs: - kwargs['round'] = self.get_round() - return super().get_context_data(**kwargs) + page_title = 'Team Standings' + page_emoji = '👯' - def show_ballots(self): - return False - - def get(self, request, *args, **kwargs): + def get_standings(self): tournament = self.get_tournament() round = self.get_round() - teams = tournament.team_set.exclude(type=Team.TYPE_BYE).select_related('institution') + teams = tournament.team_set.exclude(type=Team.TYPE_BYE).select_related('institution').prefetch_related('speaker_set') metrics = tournament.pref('team_standings_precedence') extra_metrics = tournament.pref('team_standings_extra_metrics') generator = TeamStandingsGenerator(metrics, self.rankings, extra_metrics) @@ -225,9 +249,23 @@ def get(self, request, *args, **kwargs): add_team_round_results(standings, rounds) self.populate_result_missing(standings) - context = self.get_context_data(standings=standings, rounds=rounds) + return standings, rounds + + def get_table(self): + standings, rounds = self.get_standings() - return render(request, self.template_name, context) + table = TabbycatTableBuilder(view=self, sort_key="Rk") + table.add_ranking_columns(standings) + table.add_team_columns([info.team for info in standings], + show_divisions=self.get_tournament().pref('enable_divisions')) + + table.add_standings_results_columns(standings, rounds, self.show_ballots()) + table.add_metric_columns(standings) + + return table + + def show_ballots(self): + return False def populate_result_missing(self, standings): for info in standings: @@ -237,13 +275,15 @@ def populate_result_missing(self, standings): class TeamStandingsView(SuperuserRequiredMixin, BaseTeamStandingsView): """The standard team standings view.""" rankings = ('rank',) - template_name = 'teams.html' + template_name = 'standings_base.html' class DivisionStandingsView(SuperuserRequiredMixin, BaseTeamStandingsView): """Special team standings view that also shows rankings within divisions.""" rankings = ('rank', 'division') - template_name = 'divisions.html' + page_title = 'Division Standings' + page_emoji = '👯' + template_name = 'standings_base.html' class PublicTeamTabView(PublicTabMixin, BaseTeamStandingsView): @@ -254,59 +294,109 @@ class PublicTeamTabView(PublicTabMixin, BaseTeamStandingsView): "team tab".""" public_page_preference = 'team_tab_released' rankings = ('rank',) - template_name = 'public_team_tab.html' def show_ballots(self): return self.get_tournament().pref('ballots_released') + # ============================================================================== # Motion standings # ============================================================================== -class BaseMotionStandingsView(RoundMixin, TemplateView): +class BaseMotionStandingsView(RoundMixin, VueTableTemplateView): - def get_context_data(self, **kwargs): - kwargs["motions"] = motion_statistics.statistics(round=self.get_round()) - return super().get_context_data(**kwargs) + page_title = 'Motions Tab' + page_emoji = '💭' + + def get_table(self): + motions = motion_statistics.statistics(round=self.get_round()) + table = TabbycatTableBuilder(view=self, sort_key="Order") + + table.add_round_column([motion.round for motion in motions]) + table.add_motion_column(motions, show_order=True) + table.add_column("Selected", [motion.chosen_in for motion in motions]) + if self.get_tournament().pref('motion_vetoes_enabled'): + table.add_column("Aff Vetoes", [motion.aff_vetoes for motion in motions]) + table.add_column("Neg Vetoes", [motion.neg_vetoes for motion in motions]) + table.add_column("Aff Wins", [motion.aff_wins for motion in motions]) + table.add_column("Neg Wins", [motion.neg_wins for motion in motions]) + return table class MotionStandingsView(SuperuserRequiredMixin, BaseMotionStandingsView): - template_name = 'motions.html' + template_name = 'standings_base.html' class PublicMotionsTabView(PublicTabMixin, BaseMotionStandingsView): public_page_preference = 'motion_tab_released' - template_name = 'public_motions_tab.html' # ============================================================================== # Current team standings (win-loss records only) # ============================================================================== -class PublicCurrentTeamStandingsView(PublicTournamentPageMixin, TemplateView): +class PublicCurrentTeamStandingsView(PublicTournamentPageMixin, VueTableTemplateView): + public_page_preference = 'public_team_standings' - template_name = 'public_team_standings.html' + page_title = 'Current Team Standings' + page_emoji = '🌟' - def get_context_data(self, **kwargs): + def get_table(self): tournament = self.get_tournament() # Find the most recent non-silent preliminary round - round = tournament.current_round if tournament.release_all else tournament.current_round.prev + round = tournament.current_round if tournament.pref('all_results_released') else tournament.current_round.prev while round is not None and (round.silent or round.stage != Round.STAGE_PRELIMINARY): round = round.prev - if round is not None and round.silent is False: - teams = tournament.team_set.order_by('institution__code', 'reference') # obscure true rankings, in case client disabled JavaScript - rounds = tournament.prelim_rounds(until=round).filter(silent=False).order_by('seq') - add_team_round_results_public(teams, rounds) + if round is None or round.silent: + return TabbycatTableBuilder() # empty (as precaution) - kwargs["teams"] = teams - kwargs["rounds"] = rounds - kwargs["round"] = round + teams = tournament.team_set.prefetch_related('speaker_set').order_by( + 'institution__code', 'reference') # Obscure true rankings, in case client disabled JavaScript + rounds = tournament.prelim_rounds(until=round).filter(silent=False).order_by('seq') - else: - kwargs["teams"] = [] - kwargs["rounds"] = [] - kwargs["round"] = None + add_team_round_results_public(teams, rounds) + # pre-sort, as Vue tables can't do two sort keys + teams = sorted(teams, key=lambda t: (-t.wins, t.short_name)) + + table = TabbycatTableBuilder(view=self, sort_order='desc') + table.add_team_columns(teams) + table.add_column("Wins", [team.wins for team in teams]) + table.add_team_results_columns(teams, rounds) + + messages.info(self.request, "This list is sorted by wins, and then by " + "team name within each group — it does not indicate each team's " + "ranking withing each group.") + + return table + + +# ============================================================================== +# Diversity +# ============================================================================== + +class BaseDiversityStandingsView(TournamentMixin, TemplateView): + + template_name = 'diversity.html' + for_public = False + + def get_context_data(self, **kwargs): + tournament = self.get_tournament() + all_data = get_diversity_data_sets(tournament, self.for_public) + kwargs['regions'] = all_data['regions'] + kwargs['data_sets'] = json.dumps(all_data) + kwargs['for_public'] = self.for_public return super().get_context_data(**kwargs) + + +class DiversityStandingsView(SuperuserRequiredMixin, BaseDiversityStandingsView): + + for_public = False + + +class PublicDiversityStandingsView(PublicTabMixin, BaseDiversityStandingsView): + + public_page_preference = 'public_diversity' + for_public = True diff --git a/tabbycat/static/build.js b/tabbycat/static/build.js new file mode 100644 index 00000000000..60404873933 --- /dev/null +++ b/tabbycat/static/build.js @@ -0,0 +1,10738 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + setTimeout(drainQueue, 0); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],2:[function(require,module,exports){ +var Vue // late bind +var map = Object.create(null) +var shimmed = false +var isBrowserify = false + +/** + * Determine compatibility and apply patch. + * + * @param {Function} vue + * @param {Boolean} browserify + */ + +exports.install = function (vue, browserify) { + if (shimmed) return + shimmed = true + + Vue = vue + isBrowserify = browserify + + exports.compatible = !!Vue.internalDirectives + if (!exports.compatible) { + console.warn( + '[HMR] vue-loader hot reload is only compatible with ' + + 'Vue.js 1.0.0+.' + ) + return + } + + // patch view directive + patchView(Vue.internalDirectives.component) + console.log('[HMR] Vue component hot reload shim applied.') + // shim router-view if present + var routerView = Vue.elementDirective('router-view') + if (routerView) { + patchView(routerView) + console.log('[HMR] vue-router hot reload shim applied.') + } +} + +/** + * Shim the view directive (component or router-view). + * + * @param {Object} View + */ + +function patchView (View) { + var unbuild = View.unbuild + View.unbuild = function (defer) { + if (!this.hotUpdating) { + var prevComponent = this.childVM && this.childVM.constructor + removeView(prevComponent, this) + // defer = true means we are transitioning to a new + // Component. Register this new component to the list. + if (defer) { + addView(this.Component, this) + } + } + // call original + return unbuild.call(this, defer) + } +} + +/** + * Add a component view to a Component's hot list + * + * @param {Function} Component + * @param {Directive} view - view directive instance + */ + +function addView (Component, view) { + var id = Component && Component.options.hotID + if (id) { + if (!map[id]) { + map[id] = { + Component: Component, + views: [], + instances: [] + } + } + map[id].views.push(view) + } +} + +/** + * Remove a component view from a Component's hot list + * + * @param {Function} Component + * @param {Directive} view - view directive instance + */ + +function removeView (Component, view) { + var id = Component && Component.options.hotID + if (id) { + map[id].views.$remove(view) + } +} + +/** + * Create a record for a hot module, which keeps track of its construcotr, + * instnaces and views (component directives or router-views). + * + * @param {String} id + * @param {Object} options + */ + +exports.createRecord = function (id, options) { + if (typeof options === 'function') { + options = options.options + } + if (typeof options.el !== 'string' && typeof options.data !== 'object') { + makeOptionsHot(id, options) + map[id] = { + Component: null, + views: [], + instances: [] + } + } +} + +/** + * Make a Component options object hot. + * + * @param {String} id + * @param {Object} options + */ + +function makeOptionsHot (id, options) { + options.hotID = id + injectHook(options, 'created', function () { + var record = map[id] + if (!record.Component) { + record.Component = this.constructor + } + record.instances.push(this) + }) + injectHook(options, 'beforeDestroy', function () { + map[id].instances.$remove(this) + }) +} + +/** + * Inject a hook to a hot reloadable component so that + * we can keep track of it. + * + * @param {Object} options + * @param {String} name + * @param {Function} hook + */ + +function injectHook (options, name, hook) { + var existing = options[name] + options[name] = existing + ? Array.isArray(existing) + ? existing.concat(hook) + : [existing, hook] + : [hook] +} + +/** + * Update a hot component. + * + * @param {String} id + * @param {Object|null} newOptions + * @param {String|null} newTemplate + */ + +exports.update = function (id, newOptions, newTemplate) { + var record = map[id] + // force full-reload if an instance of the component is active but is not + // managed by a view + if (!record || (record.instances.length && !record.views.length)) { + console.log('[HMR] Root or manually-mounted instance modified. Full reload may be required.') + if (!isBrowserify) { + window.location.reload() + } else { + // browserify-hmr somehow sends incomplete bundle if we reload here + return + } + } + if (!isBrowserify) { + // browserify-hmr already logs this + console.log('[HMR] Updating component: ' + format(id)) + } + var Component = record.Component + // update constructor + if (newOptions) { + // in case the user exports a constructor + Component = record.Component = typeof newOptions === 'function' + ? newOptions + : Vue.extend(newOptions) + makeOptionsHot(id, Component.options) + } + if (newTemplate) { + Component.options.template = newTemplate + } + // handle recursive lookup + if (Component.options.name) { + Component.options.components[Component.options.name] = Component + } + // reset constructor cached linker + Component.linker = null + // reload all views + record.views.forEach(function (view) { + updateView(view, Component) + }) + // flush devtools + if (window.__VUE_DEVTOOLS_GLOBAL_HOOK__) { + window.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit('flush') + } +} + +/** + * Update a component view instance + * + * @param {Directive} view + * @param {Function} Component + */ + +function updateView (view, Component) { + if (!view._bound) { + return + } + view.Component = Component + view.hotUpdating = true + // disable transitions + view.vm._isCompiled = false + // save state + var state = extractState(view.childVM) + // remount, make sure to disable keep-alive + var keepAlive = view.keepAlive + view.keepAlive = false + view.mountComponent() + view.keepAlive = keepAlive + // restore state + restoreState(view.childVM, state, true) + // re-eanble transitions + view.vm._isCompiled = true + view.hotUpdating = false +} + +/** + * Extract state from a Vue instance. + * + * @param {Vue} vm + * @return {Object} + */ + +function extractState (vm) { + return { + cid: vm.constructor.cid, + data: vm.$data, + children: vm.$children.map(extractState) + } +} + +/** + * Restore state to a reloaded Vue instance. + * + * @param {Vue} vm + * @param {Object} state + */ + +function restoreState (vm, state, isRoot) { + var oldAsyncConfig + if (isRoot) { + // set Vue into sync mode during state rehydration + oldAsyncConfig = Vue.config.async + Vue.config.async = false + } + // actual restore + if (isRoot || !vm._props) { + vm.$data = state.data + } else { + Object.keys(state.data).forEach(function (key) { + if (!vm._props[key]) { + // for non-root, only restore non-props fields + vm.$data[key] = state.data[key] + } + }) + } + // verify child consistency + var hasSameChildren = vm.$children.every(function (c, i) { + return state.children[i] && state.children[i].cid === c.constructor.cid + }) + if (hasSameChildren) { + // rehydrate children + vm.$children.forEach(function (c, i) { + restoreState(c, state.children[i]) + }) + } + if (isRoot) { + Vue.config.async = oldAsyncConfig + } +} + +function format (id) { + return id.match(/[^\/]+\.vue$/)[0] +} + +},{}],3:[function(require,module,exports){ +(function (process,global){ +/*! + * Vue.js v1.0.25 + * (c) 2016 Evan You + * Released under the MIT License. + */ +'use strict'; + +function set(obj, key, val) { + if (hasOwn(obj, key)) { + obj[key] = val; + return; + } + if (obj._isVue) { + set(obj._data, key, val); + return; + } + var ob = obj.__ob__; + if (!ob) { + obj[key] = val; + return; + } + ob.convert(key, val); + ob.dep.notify(); + if (ob.vms) { + var i = ob.vms.length; + while (i--) { + var vm = ob.vms[i]; + vm._proxy(key); + vm._digest(); + } + } + return val; +} + +/** + * Delete a property and trigger change if necessary. + * + * @param {Object} obj + * @param {String} key + */ + +function del(obj, key) { + if (!hasOwn(obj, key)) { + return; + } + delete obj[key]; + var ob = obj.__ob__; + if (!ob) { + if (obj._isVue) { + delete obj._data[key]; + obj._digest(); + } + return; + } + ob.dep.notify(); + if (ob.vms) { + var i = ob.vms.length; + while (i--) { + var vm = ob.vms[i]; + vm._unproxy(key); + vm._digest(); + } + } +} + +var hasOwnProperty = Object.prototype.hasOwnProperty; +/** + * Check whether the object has the property. + * + * @param {Object} obj + * @param {String} key + * @return {Boolean} + */ + +function hasOwn(obj, key) { + return hasOwnProperty.call(obj, key); +} + +/** + * Check if an expression is a literal value. + * + * @param {String} exp + * @return {Boolean} + */ + +var literalValueRE = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/; + +function isLiteral(exp) { + return literalValueRE.test(exp); +} + +/** + * Check if a string starts with $ or _ + * + * @param {String} str + * @return {Boolean} + */ + +function isReserved(str) { + var c = (str + '').charCodeAt(0); + return c === 0x24 || c === 0x5F; +} + +/** + * Guard text output, make sure undefined outputs + * empty string + * + * @param {*} value + * @return {String} + */ + +function _toString(value) { + return value == null ? '' : value.toString(); +} + +/** + * Check and convert possible numeric strings to numbers + * before setting back to data + * + * @param {*} value + * @return {*|Number} + */ + +function toNumber(value) { + if (typeof value !== 'string') { + return value; + } else { + var parsed = Number(value); + return isNaN(parsed) ? value : parsed; + } +} + +/** + * Convert string boolean literals into real booleans. + * + * @param {*} value + * @return {*|Boolean} + */ + +function toBoolean(value) { + return value === 'true' ? true : value === 'false' ? false : value; +} + +/** + * Strip quotes from a string + * + * @param {String} str + * @return {String | false} + */ + +function stripQuotes(str) { + var a = str.charCodeAt(0); + var b = str.charCodeAt(str.length - 1); + return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str; +} + +/** + * Camelize a hyphen-delmited string. + * + * @param {String} str + * @return {String} + */ + +var camelizeRE = /-(\w)/g; + +function camelize(str) { + return str.replace(camelizeRE, toUpper); +} + +function toUpper(_, c) { + return c ? c.toUpperCase() : ''; +} + +/** + * Hyphenate a camelCase string. + * + * @param {String} str + * @return {String} + */ + +var hyphenateRE = /([a-z\d])([A-Z])/g; + +function hyphenate(str) { + return str.replace(hyphenateRE, '$1-$2').toLowerCase(); +} + +/** + * Converts hyphen/underscore/slash delimitered names into + * camelized classNames. + * + * e.g. my-component => MyComponent + * some_else => SomeElse + * some/comp => SomeComp + * + * @param {String} str + * @return {String} + */ + +var classifyRE = /(?:^|[-_\/])(\w)/g; + +function classify(str) { + return str.replace(classifyRE, toUpper); +} + +/** + * Simple bind, faster than native + * + * @param {Function} fn + * @param {Object} ctx + * @return {Function} + */ + +function bind(fn, ctx) { + return function (a) { + var l = arguments.length; + return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx); + }; +} + +/** + * Convert an Array-like object to a real Array. + * + * @param {Array-like} list + * @param {Number} [start] - start index + * @return {Array} + */ + +function toArray(list, start) { + start = start || 0; + var i = list.length - start; + var ret = new Array(i); + while (i--) { + ret[i] = list[i + start]; + } + return ret; +} + +/** + * Mix properties into target object. + * + * @param {Object} to + * @param {Object} from + */ + +function extend(to, from) { + var keys = Object.keys(from); + var i = keys.length; + while (i--) { + to[keys[i]] = from[keys[i]]; + } + return to; +} + +/** + * Quick object check - this is primarily used to tell + * Objects from primitive values when we know the value + * is a JSON-compliant type. + * + * @param {*} obj + * @return {Boolean} + */ + +function isObject(obj) { + return obj !== null && typeof obj === 'object'; +} + +/** + * Strict object type check. Only returns true + * for plain JavaScript objects. + * + * @param {*} obj + * @return {Boolean} + */ + +var toString = Object.prototype.toString; +var OBJECT_STRING = '[object Object]'; + +function isPlainObject(obj) { + return toString.call(obj) === OBJECT_STRING; +} + +/** + * Array type check. + * + * @param {*} obj + * @return {Boolean} + */ + +var isArray = Array.isArray; + +/** + * Define a property. + * + * @param {Object} obj + * @param {String} key + * @param {*} val + * @param {Boolean} [enumerable] + */ + +function def(obj, key, val, enumerable) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }); +} + +/** + * Debounce a function so it only gets called after the + * input stops arriving after the given wait period. + * + * @param {Function} func + * @param {Number} wait + * @return {Function} - the debounced function + */ + +function _debounce(func, wait) { + var timeout, args, context, timestamp, result; + var later = function later() { + var last = Date.now() - timestamp; + if (last < wait && last >= 0) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + result = func.apply(context, args); + if (!timeout) context = args = null; + } + }; + return function () { + context = this; + args = arguments; + timestamp = Date.now(); + if (!timeout) { + timeout = setTimeout(later, wait); + } + return result; + }; +} + +/** + * Manual indexOf because it's slightly faster than + * native. + * + * @param {Array} arr + * @param {*} obj + */ + +function indexOf(arr, obj) { + var i = arr.length; + while (i--) { + if (arr[i] === obj) return i; + } + return -1; +} + +/** + * Make a cancellable version of an async callback. + * + * @param {Function} fn + * @return {Function} + */ + +function cancellable(fn) { + var cb = function cb() { + if (!cb.cancelled) { + return fn.apply(this, arguments); + } + }; + cb.cancel = function () { + cb.cancelled = true; + }; + return cb; +} + +/** + * Check if two values are loosely equal - that is, + * if they are plain objects, do they have the same shape? + * + * @param {*} a + * @param {*} b + * @return {Boolean} + */ + +function looseEqual(a, b) { + /* eslint-disable eqeqeq */ + return a == b || (isObject(a) && isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false); + /* eslint-enable eqeqeq */ +} + +var hasProto = ('__proto__' in {}); + +// Browser environment sniffing +var inBrowser = typeof window !== 'undefined' && Object.prototype.toString.call(window) !== '[object Object]'; + +// detect devtools +var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + +// UA sniffing for working around browser-specific quirks +var UA = inBrowser && window.navigator.userAgent.toLowerCase(); +var isIE = UA && UA.indexOf('trident') > 0; +var isIE9 = UA && UA.indexOf('msie 9.0') > 0; +var isAndroid = UA && UA.indexOf('android') > 0; +var isIos = UA && /(iphone|ipad|ipod|ios)/i.test(UA); +var iosVersionMatch = isIos && UA.match(/os ([\d_]+)/); +var iosVersion = iosVersionMatch && iosVersionMatch[1].split('_'); + +// detecting iOS UIWebView by indexedDB +var hasMutationObserverBug = iosVersion && Number(iosVersion[0]) >= 9 && Number(iosVersion[1]) >= 3 && !window.indexedDB; + +var transitionProp = undefined; +var transitionEndEvent = undefined; +var animationProp = undefined; +var animationEndEvent = undefined; + +// Transition property/event sniffing +if (inBrowser && !isIE9) { + var isWebkitTrans = window.ontransitionend === undefined && window.onwebkittransitionend !== undefined; + var isWebkitAnim = window.onanimationend === undefined && window.onwebkitanimationend !== undefined; + transitionProp = isWebkitTrans ? 'WebkitTransition' : 'transition'; + transitionEndEvent = isWebkitTrans ? 'webkitTransitionEnd' : 'transitionend'; + animationProp = isWebkitAnim ? 'WebkitAnimation' : 'animation'; + animationEndEvent = isWebkitAnim ? 'webkitAnimationEnd' : 'animationend'; +} + +/** + * Defer a task to execute it asynchronously. Ideally this + * should be executed as a microtask, so we leverage + * MutationObserver if it's available, and fallback to + * setTimeout(0). + * + * @param {Function} cb + * @param {Object} ctx + */ + +var nextTick = (function () { + var callbacks = []; + var pending = false; + var timerFunc; + function nextTickHandler() { + pending = false; + var copies = callbacks.slice(0); + callbacks = []; + for (var i = 0; i < copies.length; i++) { + copies[i](); + } + } + + /* istanbul ignore if */ + if (typeof MutationObserver !== 'undefined' && !hasMutationObserverBug) { + var counter = 1; + var observer = new MutationObserver(nextTickHandler); + var textNode = document.createTextNode(counter); + observer.observe(textNode, { + characterData: true + }); + timerFunc = function () { + counter = (counter + 1) % 2; + textNode.data = counter; + }; + } else { + // webpack attempts to inject a shim for setImmediate + // if it is used as a global, so we have to work around that to + // avoid bundling unnecessary code. + var context = inBrowser ? window : typeof global !== 'undefined' ? global : {}; + timerFunc = context.setImmediate || setTimeout; + } + return function (cb, ctx) { + var func = ctx ? function () { + cb.call(ctx); + } : cb; + callbacks.push(func); + if (pending) return; + pending = true; + timerFunc(nextTickHandler, 0); + }; +})(); + +var _Set = undefined; +/* istanbul ignore if */ +if (typeof Set !== 'undefined' && Set.toString().match(/native code/)) { + // use native Set when available. + _Set = Set; +} else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = function () { + this.set = Object.create(null); + }; + _Set.prototype.has = function (key) { + return this.set[key] !== undefined; + }; + _Set.prototype.add = function (key) { + this.set[key] = 1; + }; + _Set.prototype.clear = function () { + this.set = Object.create(null); + }; +} + +function Cache(limit) { + this.size = 0; + this.limit = limit; + this.head = this.tail = undefined; + this._keymap = Object.create(null); +} + +var p = Cache.prototype; + +/** + * Put into the cache associated with . + * Returns the entry which was removed to make room for + * the new entry. Otherwise undefined is returned. + * (i.e. if there was enough room already). + * + * @param {String} key + * @param {*} value + * @return {Entry|undefined} + */ + +p.put = function (key, value) { + var removed; + + var entry = this.get(key, true); + if (!entry) { + if (this.size === this.limit) { + removed = this.shift(); + } + entry = { + key: key + }; + this._keymap[key] = entry; + if (this.tail) { + this.tail.newer = entry; + entry.older = this.tail; + } else { + this.head = entry; + } + this.tail = entry; + this.size++; + } + entry.value = value; + + return removed; +}; + +/** + * Purge the least recently used (oldest) entry from the + * cache. Returns the removed entry or undefined if the + * cache was empty. + */ + +p.shift = function () { + var entry = this.head; + if (entry) { + this.head = this.head.newer; + this.head.older = undefined; + entry.newer = entry.older = undefined; + this._keymap[entry.key] = undefined; + this.size--; + } + return entry; +}; + +/** + * Get and register recent use of . Returns the value + * associated with or undefined if not in cache. + * + * @param {String} key + * @param {Boolean} returnEntry + * @return {Entry|*} + */ + +p.get = function (key, returnEntry) { + var entry = this._keymap[key]; + if (entry === undefined) return; + if (entry === this.tail) { + return returnEntry ? entry : entry.value; + } + // HEAD--------------TAIL + // <.older .newer> + // <--- add direction -- + // A B C E + if (entry.newer) { + if (entry === this.head) { + this.head = entry.newer; + } + entry.newer.older = entry.older; // C <-- E. + } + if (entry.older) { + entry.older.newer = entry.newer; // C. --> E + } + entry.newer = undefined; // D --x + entry.older = this.tail; // D. --> E + if (this.tail) { + this.tail.newer = entry; // E. <-- D + } + this.tail = entry; + return returnEntry ? entry : entry.value; +}; + +var cache$1 = new Cache(1000); +var filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g; +var reservedArgRE = /^in$|^-?\d+/; + +/** + * Parser state + */ + +var str; +var dir; +var c; +var prev; +var i; +var l; +var lastFilterIndex; +var inSingle; +var inDouble; +var curly; +var square; +var paren; +/** + * Push a filter to the current directive object + */ + +function pushFilter() { + var exp = str.slice(lastFilterIndex, i).trim(); + var filter; + if (exp) { + filter = {}; + var tokens = exp.match(filterTokenRE); + filter.name = tokens[0]; + if (tokens.length > 1) { + filter.args = tokens.slice(1).map(processFilterArg); + } + } + if (filter) { + (dir.filters = dir.filters || []).push(filter); + } + lastFilterIndex = i + 1; +} + +/** + * Check if an argument is dynamic and strip quotes. + * + * @param {String} arg + * @return {Object} + */ + +function processFilterArg(arg) { + if (reservedArgRE.test(arg)) { + return { + value: toNumber(arg), + dynamic: false + }; + } else { + var stripped = stripQuotes(arg); + var dynamic = stripped === arg; + return { + value: dynamic ? arg : stripped, + dynamic: dynamic + }; + } +} + +/** + * Parse a directive value and extract the expression + * and its filters into a descriptor. + * + * Example: + * + * "a + 1 | uppercase" will yield: + * { + * expression: 'a + 1', + * filters: [ + * { name: 'uppercase', args: null } + * ] + * } + * + * @param {String} s + * @return {Object} + */ + +function parseDirective(s) { + var hit = cache$1.get(s); + if (hit) { + return hit; + } + + // reset parser state + str = s; + inSingle = inDouble = false; + curly = square = paren = 0; + lastFilterIndex = 0; + dir = {}; + + for (i = 0, l = str.length; i < l; i++) { + prev = c; + c = str.charCodeAt(i); + if (inSingle) { + // check single quote + if (c === 0x27 && prev !== 0x5C) inSingle = !inSingle; + } else if (inDouble) { + // check double quote + if (c === 0x22 && prev !== 0x5C) inDouble = !inDouble; + } else if (c === 0x7C && // pipe + str.charCodeAt(i + 1) !== 0x7C && str.charCodeAt(i - 1) !== 0x7C) { + if (dir.expression == null) { + // first filter, end of expression + lastFilterIndex = i + 1; + dir.expression = str.slice(0, i).trim(); + } else { + // already has filter + pushFilter(); + } + } else { + switch (c) { + case 0x22: + inDouble = true;break; // " + case 0x27: + inSingle = true;break; // ' + case 0x28: + paren++;break; // ( + case 0x29: + paren--;break; // ) + case 0x5B: + square++;break; // [ + case 0x5D: + square--;break; // ] + case 0x7B: + curly++;break; // { + case 0x7D: + curly--;break; // } + } + } + } + + if (dir.expression == null) { + dir.expression = str.slice(0, i).trim(); + } else if (lastFilterIndex !== 0) { + pushFilter(); + } + + cache$1.put(s, dir); + return dir; +} + +var directive = Object.freeze({ + parseDirective: parseDirective +}); + +var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g; +var cache = undefined; +var tagRE = undefined; +var htmlRE = undefined; +/** + * Escape a string so it can be used in a RegExp + * constructor. + * + * @param {String} str + */ + +function escapeRegex(str) { + return str.replace(regexEscapeRE, '\\$&'); +} + +function compileRegex() { + var open = escapeRegex(config.delimiters[0]); + var close = escapeRegex(config.delimiters[1]); + var unsafeOpen = escapeRegex(config.unsafeDelimiters[0]); + var unsafeClose = escapeRegex(config.unsafeDelimiters[1]); + tagRE = new RegExp(unsafeOpen + '((?:.|\\n)+?)' + unsafeClose + '|' + open + '((?:.|\\n)+?)' + close, 'g'); + htmlRE = new RegExp('^' + unsafeOpen + '((?:.|\\n)+?)' + unsafeClose + '$'); + // reset cache + cache = new Cache(1000); +} + +/** + * Parse a template text string into an array of tokens. + * + * @param {String} text + * @return {Array | null} + * - {String} type + * - {String} value + * - {Boolean} [html] + * - {Boolean} [oneTime] + */ + +function parseText(text) { + if (!cache) { + compileRegex(); + } + var hit = cache.get(text); + if (hit) { + return hit; + } + if (!tagRE.test(text)) { + return null; + } + var tokens = []; + var lastIndex = tagRE.lastIndex = 0; + var match, index, html, value, first, oneTime; + /* eslint-disable no-cond-assign */ + while (match = tagRE.exec(text)) { + /* eslint-enable no-cond-assign */ + index = match.index; + // push text token + if (index > lastIndex) { + tokens.push({ + value: text.slice(lastIndex, index) + }); + } + // tag token + html = htmlRE.test(match[0]); + value = html ? match[1] : match[2]; + first = value.charCodeAt(0); + oneTime = first === 42; // * + value = oneTime ? value.slice(1) : value; + tokens.push({ + tag: true, + value: value.trim(), + html: html, + oneTime: oneTime + }); + lastIndex = index + match[0].length; + } + if (lastIndex < text.length) { + tokens.push({ + value: text.slice(lastIndex) + }); + } + cache.put(text, tokens); + return tokens; +} + +/** + * Format a list of tokens into an expression. + * e.g. tokens parsed from 'a {{b}} c' can be serialized + * into one single expression as '"a " + b + " c"'. + * + * @param {Array} tokens + * @param {Vue} [vm] + * @return {String} + */ + +function tokensToExp(tokens, vm) { + if (tokens.length > 1) { + return tokens.map(function (token) { + return formatToken(token, vm); + }).join('+'); + } else { + return formatToken(tokens[0], vm, true); + } +} + +/** + * Format a single token. + * + * @param {Object} token + * @param {Vue} [vm] + * @param {Boolean} [single] + * @return {String} + */ + +function formatToken(token, vm, single) { + return token.tag ? token.oneTime && vm ? '"' + vm.$eval(token.value) + '"' : inlineFilters(token.value, single) : '"' + token.value + '"'; +} + +/** + * For an attribute with multiple interpolation tags, + * e.g. attr="some-{{thing | filter}}", in order to combine + * the whole thing into a single watchable expression, we + * have to inline those filters. This function does exactly + * that. This is a bit hacky but it avoids heavy changes + * to directive parser and watcher mechanism. + * + * @param {String} exp + * @param {Boolean} single + * @return {String} + */ + +var filterRE = /[^|]\|[^|]/; +function inlineFilters(exp, single) { + if (!filterRE.test(exp)) { + return single ? exp : '(' + exp + ')'; + } else { + var dir = parseDirective(exp); + if (!dir.filters) { + return '(' + exp + ')'; + } else { + return 'this._applyFilters(' + dir.expression + // value + ',null,' + // oldValue (null for read) + JSON.stringify(dir.filters) + // filter descriptors + ',false)'; // write? + } + } +} + +var text = Object.freeze({ + compileRegex: compileRegex, + parseText: parseText, + tokensToExp: tokensToExp +}); + +var delimiters = ['{{', '}}']; +var unsafeDelimiters = ['{{{', '}}}']; + +var config = Object.defineProperties({ + + /** + * Whether to print debug messages. + * Also enables stack trace for warnings. + * + * @type {Boolean} + */ + + debug: false, + + /** + * Whether to suppress warnings. + * + * @type {Boolean} + */ + + silent: false, + + /** + * Whether to use async rendering. + */ + + async: true, + + /** + * Whether to warn against errors caught when evaluating + * expressions. + */ + + warnExpressionErrors: true, + + /** + * Whether to allow devtools inspection. + * Disabled by default in production builds. + */ + + devtools: process.env.NODE_ENV !== 'production', + + /** + * Internal flag to indicate the delimiters have been + * changed. + * + * @type {Boolean} + */ + + _delimitersChanged: true, + + /** + * List of asset types that a component can own. + * + * @type {Array} + */ + + _assetTypes: ['component', 'directive', 'elementDirective', 'filter', 'transition', 'partial'], + + /** + * prop binding modes + */ + + _propBindingModes: { + ONE_WAY: 0, + TWO_WAY: 1, + ONE_TIME: 2 + }, + + /** + * Max circular updates allowed in a batcher flush cycle. + */ + + _maxUpdateCount: 100 + +}, { + delimiters: { /** + * Interpolation delimiters. Changing these would trigger + * the text parser to re-compile the regular expressions. + * + * @type {Array} + */ + + get: function get() { + return delimiters; + }, + set: function set(val) { + delimiters = val; + compileRegex(); + }, + configurable: true, + enumerable: true + }, + unsafeDelimiters: { + get: function get() { + return unsafeDelimiters; + }, + set: function set(val) { + unsafeDelimiters = val; + compileRegex(); + }, + configurable: true, + enumerable: true + } +}); + +var warn = undefined; +var formatComponentName = undefined; + +if (process.env.NODE_ENV !== 'production') { + (function () { + var hasConsole = typeof console !== 'undefined'; + + warn = function (msg, vm) { + if (hasConsole && !config.silent) { + console.error('[Vue warn]: ' + msg + (vm ? formatComponentName(vm) : '')); + } + }; + + formatComponentName = function (vm) { + var name = vm._isVue ? vm.$options.name : vm.name; + return name ? ' (found in component: <' + hyphenate(name) + '>)' : ''; + }; + })(); +} + +/** + * Append with transition. + * + * @param {Element} el + * @param {Element} target + * @param {Vue} vm + * @param {Function} [cb] + */ + +function appendWithTransition(el, target, vm, cb) { + applyTransition(el, 1, function () { + target.appendChild(el); + }, vm, cb); +} + +/** + * InsertBefore with transition. + * + * @param {Element} el + * @param {Element} target + * @param {Vue} vm + * @param {Function} [cb] + */ + +function beforeWithTransition(el, target, vm, cb) { + applyTransition(el, 1, function () { + before(el, target); + }, vm, cb); +} + +/** + * Remove with transition. + * + * @param {Element} el + * @param {Vue} vm + * @param {Function} [cb] + */ + +function removeWithTransition(el, vm, cb) { + applyTransition(el, -1, function () { + remove(el); + }, vm, cb); +} + +/** + * Apply transitions with an operation callback. + * + * @param {Element} el + * @param {Number} direction + * 1: enter + * -1: leave + * @param {Function} op - the actual DOM operation + * @param {Vue} vm + * @param {Function} [cb] + */ + +function applyTransition(el, direction, op, vm, cb) { + var transition = el.__v_trans; + if (!transition || + // skip if there are no js hooks and CSS transition is + // not supported + !transition.hooks && !transitionEndEvent || + // skip transitions for initial compile + !vm._isCompiled || + // if the vm is being manipulated by a parent directive + // during the parent's compilation phase, skip the + // animation. + vm.$parent && !vm.$parent._isCompiled) { + op(); + if (cb) cb(); + return; + } + var action = direction > 0 ? 'enter' : 'leave'; + transition[action](op, cb); +} + +var transition = Object.freeze({ + appendWithTransition: appendWithTransition, + beforeWithTransition: beforeWithTransition, + removeWithTransition: removeWithTransition, + applyTransition: applyTransition +}); + +/** + * Query an element selector if it's not an element already. + * + * @param {String|Element} el + * @return {Element} + */ + +function query(el) { + if (typeof el === 'string') { + var selector = el; + el = document.querySelector(el); + if (!el) { + process.env.NODE_ENV !== 'production' && warn('Cannot find element: ' + selector); + } + } + return el; +} + +/** + * Check if a node is in the document. + * Note: document.documentElement.contains should work here + * but always returns false for comment nodes in phantomjs, + * making unit tests difficult. This is fixed by doing the + * contains() check on the node's parentNode instead of + * the node itself. + * + * @param {Node} node + * @return {Boolean} + */ + +function inDoc(node) { + if (!node) return false; + var doc = node.ownerDocument.documentElement; + var parent = node.parentNode; + return doc === node || doc === parent || !!(parent && parent.nodeType === 1 && doc.contains(parent)); +} + +/** + * Get and remove an attribute from a node. + * + * @param {Node} node + * @param {String} _attr + */ + +function getAttr(node, _attr) { + var val = node.getAttribute(_attr); + if (val !== null) { + node.removeAttribute(_attr); + } + return val; +} + +/** + * Get an attribute with colon or v-bind: prefix. + * + * @param {Node} node + * @param {String} name + * @return {String|null} + */ + +function getBindAttr(node, name) { + var val = getAttr(node, ':' + name); + if (val === null) { + val = getAttr(node, 'v-bind:' + name); + } + return val; +} + +/** + * Check the presence of a bind attribute. + * + * @param {Node} node + * @param {String} name + * @return {Boolean} + */ + +function hasBindAttr(node, name) { + return node.hasAttribute(name) || node.hasAttribute(':' + name) || node.hasAttribute('v-bind:' + name); +} + +/** + * Insert el before target + * + * @param {Element} el + * @param {Element} target + */ + +function before(el, target) { + target.parentNode.insertBefore(el, target); +} + +/** + * Insert el after target + * + * @param {Element} el + * @param {Element} target + */ + +function after(el, target) { + if (target.nextSibling) { + before(el, target.nextSibling); + } else { + target.parentNode.appendChild(el); + } +} + +/** + * Remove el from DOM + * + * @param {Element} el + */ + +function remove(el) { + el.parentNode.removeChild(el); +} + +/** + * Prepend el to target + * + * @param {Element} el + * @param {Element} target + */ + +function prepend(el, target) { + if (target.firstChild) { + before(el, target.firstChild); + } else { + target.appendChild(el); + } +} + +/** + * Replace target with el + * + * @param {Element} target + * @param {Element} el + */ + +function replace(target, el) { + var parent = target.parentNode; + if (parent) { + parent.replaceChild(el, target); + } +} + +/** + * Add event listener shorthand. + * + * @param {Element} el + * @param {String} event + * @param {Function} cb + * @param {Boolean} [useCapture] + */ + +function on(el, event, cb, useCapture) { + el.addEventListener(event, cb, useCapture); +} + +/** + * Remove event listener shorthand. + * + * @param {Element} el + * @param {String} event + * @param {Function} cb + */ + +function off(el, event, cb) { + el.removeEventListener(event, cb); +} + +/** + * For IE9 compat: when both class and :class are present + * getAttribute('class') returns wrong value... + * + * @param {Element} el + * @return {String} + */ + +function getClass(el) { + var classname = el.className; + if (typeof classname === 'object') { + classname = classname.baseVal || ''; + } + return classname; +} + +/** + * In IE9, setAttribute('class') will result in empty class + * if the element also has the :class attribute; However in + * PhantomJS, setting `className` does not work on SVG elements... + * So we have to do a conditional check here. + * + * @param {Element} el + * @param {String} cls + */ + +function setClass(el, cls) { + /* istanbul ignore if */ + if (isIE9 && !/svg$/.test(el.namespaceURI)) { + el.className = cls; + } else { + el.setAttribute('class', cls); + } +} + +/** + * Add class with compatibility for IE & SVG + * + * @param {Element} el + * @param {String} cls + */ + +function addClass(el, cls) { + if (el.classList) { + el.classList.add(cls); + } else { + var cur = ' ' + getClass(el) + ' '; + if (cur.indexOf(' ' + cls + ' ') < 0) { + setClass(el, (cur + cls).trim()); + } + } +} + +/** + * Remove class with compatibility for IE & SVG + * + * @param {Element} el + * @param {String} cls + */ + +function removeClass(el, cls) { + if (el.classList) { + el.classList.remove(cls); + } else { + var cur = ' ' + getClass(el) + ' '; + var tar = ' ' + cls + ' '; + while (cur.indexOf(tar) >= 0) { + cur = cur.replace(tar, ' '); + } + setClass(el, cur.trim()); + } + if (!el.className) { + el.removeAttribute('class'); + } +} + +/** + * Extract raw content inside an element into a temporary + * container div + * + * @param {Element} el + * @param {Boolean} asFragment + * @return {Element|DocumentFragment} + */ + +function extractContent(el, asFragment) { + var child; + var rawContent; + /* istanbul ignore if */ + if (isTemplate(el) && isFragment(el.content)) { + el = el.content; + } + if (el.hasChildNodes()) { + trimNode(el); + rawContent = asFragment ? document.createDocumentFragment() : document.createElement('div'); + /* eslint-disable no-cond-assign */ + while (child = el.firstChild) { + /* eslint-enable no-cond-assign */ + rawContent.appendChild(child); + } + } + return rawContent; +} + +/** + * Trim possible empty head/tail text and comment + * nodes inside a parent. + * + * @param {Node} node + */ + +function trimNode(node) { + var child; + /* eslint-disable no-sequences */ + while ((child = node.firstChild, isTrimmable(child))) { + node.removeChild(child); + } + while ((child = node.lastChild, isTrimmable(child))) { + node.removeChild(child); + } + /* eslint-enable no-sequences */ +} + +function isTrimmable(node) { + return node && (node.nodeType === 3 && !node.data.trim() || node.nodeType === 8); +} + +/** + * Check if an element is a template tag. + * Note if the template appears inside an SVG its tagName + * will be in lowercase. + * + * @param {Element} el + */ + +function isTemplate(el) { + return el.tagName && el.tagName.toLowerCase() === 'template'; +} + +/** + * Create an "anchor" for performing dom insertion/removals. + * This is used in a number of scenarios: + * - fragment instance + * - v-html + * - v-if + * - v-for + * - component + * + * @param {String} content + * @param {Boolean} persist - IE trashes empty textNodes on + * cloneNode(true), so in certain + * cases the anchor needs to be + * non-empty to be persisted in + * templates. + * @return {Comment|Text} + */ + +function createAnchor(content, persist) { + var anchor = config.debug ? document.createComment(content) : document.createTextNode(persist ? ' ' : ''); + anchor.__v_anchor = true; + return anchor; +} + +/** + * Find a component ref attribute that starts with $. + * + * @param {Element} node + * @return {String|undefined} + */ + +var refRE = /^v-ref:/; + +function findRef(node) { + if (node.hasAttributes()) { + var attrs = node.attributes; + for (var i = 0, l = attrs.length; i < l; i++) { + var name = attrs[i].name; + if (refRE.test(name)) { + return camelize(name.replace(refRE, '')); + } + } + } +} + +/** + * Map a function to a range of nodes . + * + * @param {Node} node + * @param {Node} end + * @param {Function} op + */ + +function mapNodeRange(node, end, op) { + var next; + while (node !== end) { + next = node.nextSibling; + op(node); + node = next; + } + op(end); +} + +/** + * Remove a range of nodes with transition, store + * the nodes in a fragment with correct ordering, + * and call callback when done. + * + * @param {Node} start + * @param {Node} end + * @param {Vue} vm + * @param {DocumentFragment} frag + * @param {Function} cb + */ + +function removeNodeRange(start, end, vm, frag, cb) { + var done = false; + var removed = 0; + var nodes = []; + mapNodeRange(start, end, function (node) { + if (node === end) done = true; + nodes.push(node); + removeWithTransition(node, vm, onRemoved); + }); + function onRemoved() { + removed++; + if (done && removed >= nodes.length) { + for (var i = 0; i < nodes.length; i++) { + frag.appendChild(nodes[i]); + } + cb && cb(); + } + } +} + +/** + * Check if a node is a DocumentFragment. + * + * @param {Node} node + * @return {Boolean} + */ + +function isFragment(node) { + return node && node.nodeType === 11; +} + +/** + * Get outerHTML of elements, taking care + * of SVG elements in IE as well. + * + * @param {Element} el + * @return {String} + */ + +function getOuterHTML(el) { + if (el.outerHTML) { + return el.outerHTML; + } else { + var container = document.createElement('div'); + container.appendChild(el.cloneNode(true)); + return container.innerHTML; + } +} + +var commonTagRE = /^(div|p|span|img|a|b|i|br|ul|ol|li|h1|h2|h3|h4|h5|h6|code|pre|table|th|td|tr|form|label|input|select|option|nav|article|section|header|footer)$/i; +var reservedTagRE = /^(slot|partial|component)$/i; + +var isUnknownElement = undefined; +if (process.env.NODE_ENV !== 'production') { + isUnknownElement = function (el, tag) { + if (tag.indexOf('-') > -1) { + // http://stackoverflow.com/a/28210364/1070244 + return el.constructor === window.HTMLUnknownElement || el.constructor === window.HTMLElement; + } else { + return (/HTMLUnknownElement/.test(el.toString()) && + // Chrome returns unknown for several HTML5 elements. + // https://code.google.com/p/chromium/issues/detail?id=540526 + // Firefox returns unknown for some "Interactive elements." + !/^(data|time|rtc|rb|details|dialog|summary)$/.test(tag) + ); + } + }; +} + +/** + * Check if an element is a component, if yes return its + * component id. + * + * @param {Element} el + * @param {Object} options + * @return {Object|undefined} + */ + +function checkComponentAttr(el, options) { + var tag = el.tagName.toLowerCase(); + var hasAttrs = el.hasAttributes(); + if (!commonTagRE.test(tag) && !reservedTagRE.test(tag)) { + if (resolveAsset(options, 'components', tag)) { + return { id: tag }; + } else { + var is = hasAttrs && getIsBinding(el, options); + if (is) { + return is; + } else if (process.env.NODE_ENV !== 'production') { + var expectedTag = options._componentNameMap && options._componentNameMap[tag]; + if (expectedTag) { + warn('Unknown custom element: <' + tag + '> - ' + 'did you mean <' + expectedTag + '>? ' + 'HTML is case-insensitive, remember to use kebab-case in templates.'); + } else if (isUnknownElement(el, tag)) { + warn('Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? For recursive components, ' + 'make sure to provide the "name" option.'); + } + } + } + } else if (hasAttrs) { + return getIsBinding(el, options); + } +} + +/** + * Get "is" binding from an element. + * + * @param {Element} el + * @param {Object} options + * @return {Object|undefined} + */ + +function getIsBinding(el, options) { + // dynamic syntax + var exp = el.getAttribute('is'); + if (exp != null) { + if (resolveAsset(options, 'components', exp)) { + el.removeAttribute('is'); + return { id: exp }; + } + } else { + exp = getBindAttr(el, 'is'); + if (exp != null) { + return { id: exp, dynamic: true }; + } + } +} + +/** + * Option overwriting strategies are functions that handle + * how to merge a parent option value and a child option + * value into the final value. + * + * All strategy functions follow the same signature: + * + * @param {*} parentVal + * @param {*} childVal + * @param {Vue} [vm] + */ + +var strats = config.optionMergeStrategies = Object.create(null); + +/** + * Helper that recursively merges two data objects together. + */ + +function mergeData(to, from) { + var key, toVal, fromVal; + for (key in from) { + toVal = to[key]; + fromVal = from[key]; + if (!hasOwn(to, key)) { + set(to, key, fromVal); + } else if (isObject(toVal) && isObject(fromVal)) { + mergeData(toVal, fromVal); + } + } + return to; +} + +/** + * Data + */ + +strats.data = function (parentVal, childVal, vm) { + if (!vm) { + // in a Vue.extend merge, both should be functions + if (!childVal) { + return parentVal; + } + if (typeof childVal !== 'function') { + process.env.NODE_ENV !== 'production' && warn('The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); + return parentVal; + } + if (!parentVal) { + return childVal; + } + // when parentVal & childVal are both present, + // we need to return a function that returns the + // merged result of both functions... no need to + // check if parentVal is a function here because + // it has to be a function to pass previous merges. + return function mergedDataFn() { + return mergeData(childVal.call(this), parentVal.call(this)); + }; + } else if (parentVal || childVal) { + return function mergedInstanceDataFn() { + // instance merge + var instanceData = typeof childVal === 'function' ? childVal.call(vm) : childVal; + var defaultData = typeof parentVal === 'function' ? parentVal.call(vm) : undefined; + if (instanceData) { + return mergeData(instanceData, defaultData); + } else { + return defaultData; + } + }; + } +}; + +/** + * El + */ + +strats.el = function (parentVal, childVal, vm) { + if (!vm && childVal && typeof childVal !== 'function') { + process.env.NODE_ENV !== 'production' && warn('The "el" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); + return; + } + var ret = childVal || parentVal; + // invoke the element factory if this is instance merge + return vm && typeof ret === 'function' ? ret.call(vm) : ret; +}; + +/** + * Hooks and param attributes are merged as arrays. + */ + +strats.init = strats.created = strats.ready = strats.attached = strats.detached = strats.beforeCompile = strats.compiled = strats.beforeDestroy = strats.destroyed = strats.activate = function (parentVal, childVal) { + return childVal ? parentVal ? parentVal.concat(childVal) : isArray(childVal) ? childVal : [childVal] : parentVal; +}; + +/** + * Assets + * + * When a vm is present (instance creation), we need to do + * a three-way merge between constructor options, instance + * options and parent options. + */ + +function mergeAssets(parentVal, childVal) { + var res = Object.create(parentVal || null); + return childVal ? extend(res, guardArrayAssets(childVal)) : res; +} + +config._assetTypes.forEach(function (type) { + strats[type + 's'] = mergeAssets; +}); + +/** + * Events & Watchers. + * + * Events & watchers hashes should not overwrite one + * another, so we merge them as arrays. + */ + +strats.watch = strats.events = function (parentVal, childVal) { + if (!childVal) return parentVal; + if (!parentVal) return childVal; + var ret = {}; + extend(ret, parentVal); + for (var key in childVal) { + var parent = ret[key]; + var child = childVal[key]; + if (parent && !isArray(parent)) { + parent = [parent]; + } + ret[key] = parent ? parent.concat(child) : [child]; + } + return ret; +}; + +/** + * Other object hashes. + */ + +strats.props = strats.methods = strats.computed = function (parentVal, childVal) { + if (!childVal) return parentVal; + if (!parentVal) return childVal; + var ret = Object.create(null); + extend(ret, parentVal); + extend(ret, childVal); + return ret; +}; + +/** + * Default strategy. + */ + +var defaultStrat = function defaultStrat(parentVal, childVal) { + return childVal === undefined ? parentVal : childVal; +}; + +/** + * Make sure component options get converted to actual + * constructors. + * + * @param {Object} options + */ + +function guardComponents(options) { + if (options.components) { + var components = options.components = guardArrayAssets(options.components); + var ids = Object.keys(components); + var def; + if (process.env.NODE_ENV !== 'production') { + var map = options._componentNameMap = {}; + } + for (var i = 0, l = ids.length; i < l; i++) { + var key = ids[i]; + if (commonTagRE.test(key) || reservedTagRE.test(key)) { + process.env.NODE_ENV !== 'production' && warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + key); + continue; + } + // record a all lowercase <-> kebab-case mapping for + // possible custom element case error warning + if (process.env.NODE_ENV !== 'production') { + map[key.replace(/-/g, '').toLowerCase()] = hyphenate(key); + } + def = components[key]; + if (isPlainObject(def)) { + components[key] = Vue.extend(def); + } + } + } +} + +/** + * Ensure all props option syntax are normalized into the + * Object-based format. + * + * @param {Object} options + */ + +function guardProps(options) { + var props = options.props; + var i, val; + if (isArray(props)) { + options.props = {}; + i = props.length; + while (i--) { + val = props[i]; + if (typeof val === 'string') { + options.props[val] = null; + } else if (val.name) { + options.props[val.name] = val; + } + } + } else if (isPlainObject(props)) { + var keys = Object.keys(props); + i = keys.length; + while (i--) { + val = props[keys[i]]; + if (typeof val === 'function') { + props[keys[i]] = { type: val }; + } + } + } +} + +/** + * Guard an Array-format assets option and converted it + * into the key-value Object format. + * + * @param {Object|Array} assets + * @return {Object} + */ + +function guardArrayAssets(assets) { + if (isArray(assets)) { + var res = {}; + var i = assets.length; + var asset; + while (i--) { + asset = assets[i]; + var id = typeof asset === 'function' ? asset.options && asset.options.name || asset.id : asset.name || asset.id; + if (!id) { + process.env.NODE_ENV !== 'production' && warn('Array-syntax assets must provide a "name" or "id" field.'); + } else { + res[id] = asset; + } + } + return res; + } + return assets; +} + +/** + * Merge two option objects into a new one. + * Core utility used in both instantiation and inheritance. + * + * @param {Object} parent + * @param {Object} child + * @param {Vue} [vm] - if vm is present, indicates this is + * an instantiation merge. + */ + +function mergeOptions(parent, child, vm) { + guardComponents(child); + guardProps(child); + if (process.env.NODE_ENV !== 'production') { + if (child.propsData && !vm) { + warn('propsData can only be used as an instantiation option.'); + } + } + var options = {}; + var key; + if (child['extends']) { + parent = typeof child['extends'] === 'function' ? mergeOptions(parent, child['extends'].options, vm) : mergeOptions(parent, child['extends'], vm); + } + if (child.mixins) { + for (var i = 0, l = child.mixins.length; i < l; i++) { + var mixin = child.mixins[i]; + var mixinOptions = mixin.prototype instanceof Vue ? mixin.options : mixin; + parent = mergeOptions(parent, mixinOptions, vm); + } + } + for (key in parent) { + mergeField(key); + } + for (key in child) { + if (!hasOwn(parent, key)) { + mergeField(key); + } + } + function mergeField(key) { + var strat = strats[key] || defaultStrat; + options[key] = strat(parent[key], child[key], vm, key); + } + return options; +} + +/** + * Resolve an asset. + * This function is used because child instances need access + * to assets defined in its ancestor chain. + * + * @param {Object} options + * @param {String} type + * @param {String} id + * @param {Boolean} warnMissing + * @return {Object|Function} + */ + +function resolveAsset(options, type, id, warnMissing) { + /* istanbul ignore if */ + if (typeof id !== 'string') { + return; + } + var assets = options[type]; + var camelizedId; + var res = assets[id] || + // camelCase ID + assets[camelizedId = camelize(id)] || + // Pascal Case ID + assets[camelizedId.charAt(0).toUpperCase() + camelizedId.slice(1)]; + if (process.env.NODE_ENV !== 'production' && warnMissing && !res) { + warn('Failed to resolve ' + type.slice(0, -1) + ': ' + id, options); + } + return res; +} + +var uid$1 = 0; + +/** + * A dep is an observable that can have multiple + * directives subscribing to it. + * + * @constructor + */ +function Dep() { + this.id = uid$1++; + this.subs = []; +} + +// the current target watcher being evaluated. +// this is globally unique because there could be only one +// watcher being evaluated at any time. +Dep.target = null; + +/** + * Add a directive subscriber. + * + * @param {Directive} sub + */ + +Dep.prototype.addSub = function (sub) { + this.subs.push(sub); +}; + +/** + * Remove a directive subscriber. + * + * @param {Directive} sub + */ + +Dep.prototype.removeSub = function (sub) { + this.subs.$remove(sub); +}; + +/** + * Add self as a dependency to the target watcher. + */ + +Dep.prototype.depend = function () { + Dep.target.addDep(this); +}; + +/** + * Notify all subscribers of a new value. + */ + +Dep.prototype.notify = function () { + // stablize the subscriber list first + var subs = toArray(this.subs); + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update(); + } +}; + +var arrayProto = Array.prototype; +var arrayMethods = Object.create(arrayProto) + +/** + * Intercept mutating methods and emit events + */ + +;['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) { + // cache original method + var original = arrayProto[method]; + def(arrayMethods, method, function mutator() { + // avoid leaking arguments: + // http://jsperf.com/closure-with-arguments + var i = arguments.length; + var args = new Array(i); + while (i--) { + args[i] = arguments[i]; + } + var result = original.apply(this, args); + var ob = this.__ob__; + var inserted; + switch (method) { + case 'push': + inserted = args; + break; + case 'unshift': + inserted = args; + break; + case 'splice': + inserted = args.slice(2); + break; + } + if (inserted) ob.observeArray(inserted); + // notify change + ob.dep.notify(); + return result; + }); +}); + +/** + * Swap the element at the given index with a new value + * and emits corresponding event. + * + * @param {Number} index + * @param {*} val + * @return {*} - replaced element + */ + +def(arrayProto, '$set', function $set(index, val) { + if (index >= this.length) { + this.length = Number(index) + 1; + } + return this.splice(index, 1, val)[0]; +}); + +/** + * Convenience method to remove the element at given index or target element reference. + * + * @param {*} item + */ + +def(arrayProto, '$remove', function $remove(item) { + /* istanbul ignore if */ + if (!this.length) return; + var index = indexOf(this, item); + if (index > -1) { + return this.splice(index, 1); + } +}); + +var arrayKeys = Object.getOwnPropertyNames(arrayMethods); + +/** + * By default, when a reactive property is set, the new value is + * also converted to become reactive. However in certain cases, e.g. + * v-for scope alias and props, we don't want to force conversion + * because the value may be a nested value under a frozen data structure. + * + * So whenever we want to set a reactive property without forcing + * conversion on the new value, we wrap that call inside this function. + */ + +var shouldConvert = true; + +function withoutConversion(fn) { + shouldConvert = false; + fn(); + shouldConvert = true; +} + +/** + * Observer class that are attached to each observed + * object. Once attached, the observer converts target + * object's property keys into getter/setters that + * collect dependencies and dispatches updates. + * + * @param {Array|Object} value + * @constructor + */ + +function Observer(value) { + this.value = value; + this.dep = new Dep(); + def(value, '__ob__', this); + if (isArray(value)) { + var augment = hasProto ? protoAugment : copyAugment; + augment(value, arrayMethods, arrayKeys); + this.observeArray(value); + } else { + this.walk(value); + } +} + +// Instance methods + +/** + * Walk through each property and convert them into + * getter/setters. This method should only be called when + * value type is Object. + * + * @param {Object} obj + */ + +Observer.prototype.walk = function (obj) { + var keys = Object.keys(obj); + for (var i = 0, l = keys.length; i < l; i++) { + this.convert(keys[i], obj[keys[i]]); + } +}; + +/** + * Observe a list of Array items. + * + * @param {Array} items + */ + +Observer.prototype.observeArray = function (items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]); + } +}; + +/** + * Convert a property into getter/setter so we can emit + * the events when the property is accessed/changed. + * + * @param {String} key + * @param {*} val + */ + +Observer.prototype.convert = function (key, val) { + defineReactive(this.value, key, val); +}; + +/** + * Add an owner vm, so that when $set/$delete mutations + * happen we can notify owner vms to proxy the keys and + * digest the watchers. This is only called when the object + * is observed as an instance's root $data. + * + * @param {Vue} vm + */ + +Observer.prototype.addVm = function (vm) { + (this.vms || (this.vms = [])).push(vm); +}; + +/** + * Remove an owner vm. This is called when the object is + * swapped out as an instance's $data object. + * + * @param {Vue} vm + */ + +Observer.prototype.removeVm = function (vm) { + this.vms.$remove(vm); +}; + +// helpers + +/** + * Augment an target Object or Array by intercepting + * the prototype chain using __proto__ + * + * @param {Object|Array} target + * @param {Object} src + */ + +function protoAugment(target, src) { + /* eslint-disable no-proto */ + target.__proto__ = src; + /* eslint-enable no-proto */ +} + +/** + * Augment an target Object or Array by defining + * hidden properties. + * + * @param {Object|Array} target + * @param {Object} proto + */ + +function copyAugment(target, src, keys) { + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + def(target, key, src[key]); + } +} + +/** + * Attempt to create an observer instance for a value, + * returns the new observer if successfully observed, + * or the existing observer if the value already has one. + * + * @param {*} value + * @param {Vue} [vm] + * @return {Observer|undefined} + * @static + */ + +function observe(value, vm) { + if (!value || typeof value !== 'object') { + return; + } + var ob; + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + ob = value.__ob__; + } else if (shouldConvert && (isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue) { + ob = new Observer(value); + } + if (ob && vm) { + ob.addVm(vm); + } + return ob; +} + +/** + * Define a reactive property on an Object. + * + * @param {Object} obj + * @param {String} key + * @param {*} val + */ + +function defineReactive(obj, key, val) { + var dep = new Dep(); + + var property = Object.getOwnPropertyDescriptor(obj, key); + if (property && property.configurable === false) { + return; + } + + // cater for pre-defined getter/setters + var getter = property && property.get; + var setter = property && property.set; + + var childOb = observe(val); + Object.defineProperty(obj, key, { + enumerable: true, + configurable: true, + get: function reactiveGetter() { + var value = getter ? getter.call(obj) : val; + if (Dep.target) { + dep.depend(); + if (childOb) { + childOb.dep.depend(); + } + if (isArray(value)) { + for (var e, i = 0, l = value.length; i < l; i++) { + e = value[i]; + e && e.__ob__ && e.__ob__.dep.depend(); + } + } + } + return value; + }, + set: function reactiveSetter(newVal) { + var value = getter ? getter.call(obj) : val; + if (newVal === value) { + return; + } + if (setter) { + setter.call(obj, newVal); + } else { + val = newVal; + } + childOb = observe(newVal); + dep.notify(); + } + }); +} + + + +var util = Object.freeze({ + defineReactive: defineReactive, + set: set, + del: del, + hasOwn: hasOwn, + isLiteral: isLiteral, + isReserved: isReserved, + _toString: _toString, + toNumber: toNumber, + toBoolean: toBoolean, + stripQuotes: stripQuotes, + camelize: camelize, + hyphenate: hyphenate, + classify: classify, + bind: bind, + toArray: toArray, + extend: extend, + isObject: isObject, + isPlainObject: isPlainObject, + def: def, + debounce: _debounce, + indexOf: indexOf, + cancellable: cancellable, + looseEqual: looseEqual, + isArray: isArray, + hasProto: hasProto, + inBrowser: inBrowser, + devtools: devtools, + isIE: isIE, + isIE9: isIE9, + isAndroid: isAndroid, + isIos: isIos, + iosVersionMatch: iosVersionMatch, + iosVersion: iosVersion, + hasMutationObserverBug: hasMutationObserverBug, + get transitionProp () { return transitionProp; }, + get transitionEndEvent () { return transitionEndEvent; }, + get animationProp () { return animationProp; }, + get animationEndEvent () { return animationEndEvent; }, + nextTick: nextTick, + get _Set () { return _Set; }, + query: query, + inDoc: inDoc, + getAttr: getAttr, + getBindAttr: getBindAttr, + hasBindAttr: hasBindAttr, + before: before, + after: after, + remove: remove, + prepend: prepend, + replace: replace, + on: on, + off: off, + setClass: setClass, + addClass: addClass, + removeClass: removeClass, + extractContent: extractContent, + trimNode: trimNode, + isTemplate: isTemplate, + createAnchor: createAnchor, + findRef: findRef, + mapNodeRange: mapNodeRange, + removeNodeRange: removeNodeRange, + isFragment: isFragment, + getOuterHTML: getOuterHTML, + mergeOptions: mergeOptions, + resolveAsset: resolveAsset, + checkComponentAttr: checkComponentAttr, + commonTagRE: commonTagRE, + reservedTagRE: reservedTagRE, + get warn () { return warn; } +}); + +var uid = 0; + +function initMixin (Vue) { + /** + * The main init sequence. This is called for every + * instance, including ones that are created from extended + * constructors. + * + * @param {Object} options - this options object should be + * the result of merging class + * options and the options passed + * in to the constructor. + */ + + Vue.prototype._init = function (options) { + options = options || {}; + + this.$el = null; + this.$parent = options.parent; + this.$root = this.$parent ? this.$parent.$root : this; + this.$children = []; + this.$refs = {}; // child vm references + this.$els = {}; // element references + this._watchers = []; // all watchers as an array + this._directives = []; // all directives + + // a uid + this._uid = uid++; + + // a flag to avoid this being observed + this._isVue = true; + + // events bookkeeping + this._events = {}; // registered callbacks + this._eventsCount = {}; // for $broadcast optimization + + // fragment instance properties + this._isFragment = false; + this._fragment = // @type {DocumentFragment} + this._fragmentStart = // @type {Text|Comment} + this._fragmentEnd = null; // @type {Text|Comment} + + // lifecycle state + this._isCompiled = this._isDestroyed = this._isReady = this._isAttached = this._isBeingDestroyed = this._vForRemoving = false; + this._unlinkFn = null; + + // context: + // if this is a transcluded component, context + // will be the common parent vm of this instance + // and its host. + this._context = options._context || this.$parent; + + // scope: + // if this is inside an inline v-for, the scope + // will be the intermediate scope created for this + // repeat fragment. this is used for linking props + // and container directives. + this._scope = options._scope; + + // fragment: + // if this instance is compiled inside a Fragment, it + // needs to reigster itself as a child of that fragment + // for attach/detach to work properly. + this._frag = options._frag; + if (this._frag) { + this._frag.children.push(this); + } + + // push self into parent / transclusion host + if (this.$parent) { + this.$parent.$children.push(this); + } + + // merge options. + options = this.$options = mergeOptions(this.constructor.options, options, this); + + // set ref + this._updateRef(); + + // initialize data as empty object. + // it will be filled up in _initData(). + this._data = {}; + + // call init hook + this._callHook('init'); + + // initialize data observation and scope inheritance. + this._initState(); + + // setup event system and option events. + this._initEvents(); + + // call created hook + this._callHook('created'); + + // if `el` option is passed, start compilation. + if (options.el) { + this.$mount(options.el); + } + }; +} + +var pathCache = new Cache(1000); + +// actions +var APPEND = 0; +var PUSH = 1; +var INC_SUB_PATH_DEPTH = 2; +var PUSH_SUB_PATH = 3; + +// states +var BEFORE_PATH = 0; +var IN_PATH = 1; +var BEFORE_IDENT = 2; +var IN_IDENT = 3; +var IN_SUB_PATH = 4; +var IN_SINGLE_QUOTE = 5; +var IN_DOUBLE_QUOTE = 6; +var AFTER_PATH = 7; +var ERROR = 8; + +var pathStateMachine = []; + +pathStateMachine[BEFORE_PATH] = { + 'ws': [BEFORE_PATH], + 'ident': [IN_IDENT, APPEND], + '[': [IN_SUB_PATH], + 'eof': [AFTER_PATH] +}; + +pathStateMachine[IN_PATH] = { + 'ws': [IN_PATH], + '.': [BEFORE_IDENT], + '[': [IN_SUB_PATH], + 'eof': [AFTER_PATH] +}; + +pathStateMachine[BEFORE_IDENT] = { + 'ws': [BEFORE_IDENT], + 'ident': [IN_IDENT, APPEND] +}; + +pathStateMachine[IN_IDENT] = { + 'ident': [IN_IDENT, APPEND], + '0': [IN_IDENT, APPEND], + 'number': [IN_IDENT, APPEND], + 'ws': [IN_PATH, PUSH], + '.': [BEFORE_IDENT, PUSH], + '[': [IN_SUB_PATH, PUSH], + 'eof': [AFTER_PATH, PUSH] +}; + +pathStateMachine[IN_SUB_PATH] = { + "'": [IN_SINGLE_QUOTE, APPEND], + '"': [IN_DOUBLE_QUOTE, APPEND], + '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH], + ']': [IN_PATH, PUSH_SUB_PATH], + 'eof': ERROR, + 'else': [IN_SUB_PATH, APPEND] +}; + +pathStateMachine[IN_SINGLE_QUOTE] = { + "'": [IN_SUB_PATH, APPEND], + 'eof': ERROR, + 'else': [IN_SINGLE_QUOTE, APPEND] +}; + +pathStateMachine[IN_DOUBLE_QUOTE] = { + '"': [IN_SUB_PATH, APPEND], + 'eof': ERROR, + 'else': [IN_DOUBLE_QUOTE, APPEND] +}; + +/** + * Determine the type of a character in a keypath. + * + * @param {Char} ch + * @return {String} type + */ + +function getPathCharType(ch) { + if (ch === undefined) { + return 'eof'; + } + + var code = ch.charCodeAt(0); + + switch (code) { + case 0x5B: // [ + case 0x5D: // ] + case 0x2E: // . + case 0x22: // " + case 0x27: // ' + case 0x30: + // 0 + return ch; + + case 0x5F: // _ + case 0x24: + // $ + return 'ident'; + + case 0x20: // Space + case 0x09: // Tab + case 0x0A: // Newline + case 0x0D: // Return + case 0xA0: // No-break space + case 0xFEFF: // Byte Order Mark + case 0x2028: // Line Separator + case 0x2029: + // Paragraph Separator + return 'ws'; + } + + // a-z, A-Z + if (code >= 0x61 && code <= 0x7A || code >= 0x41 && code <= 0x5A) { + return 'ident'; + } + + // 1-9 + if (code >= 0x31 && code <= 0x39) { + return 'number'; + } + + return 'else'; +} + +/** + * Format a subPath, return its plain form if it is + * a literal string or number. Otherwise prepend the + * dynamic indicator (*). + * + * @param {String} path + * @return {String} + */ + +function formatSubPath(path) { + var trimmed = path.trim(); + // invalid leading 0 + if (path.charAt(0) === '0' && isNaN(path)) { + return false; + } + return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed; +} + +/** + * Parse a string path into an array of segments + * + * @param {String} path + * @return {Array|undefined} + */ + +function parse(path) { + var keys = []; + var index = -1; + var mode = BEFORE_PATH; + var subPathDepth = 0; + var c, newChar, key, type, transition, action, typeMap; + + var actions = []; + + actions[PUSH] = function () { + if (key !== undefined) { + keys.push(key); + key = undefined; + } + }; + + actions[APPEND] = function () { + if (key === undefined) { + key = newChar; + } else { + key += newChar; + } + }; + + actions[INC_SUB_PATH_DEPTH] = function () { + actions[APPEND](); + subPathDepth++; + }; + + actions[PUSH_SUB_PATH] = function () { + if (subPathDepth > 0) { + subPathDepth--; + mode = IN_SUB_PATH; + actions[APPEND](); + } else { + subPathDepth = 0; + key = formatSubPath(key); + if (key === false) { + return false; + } else { + actions[PUSH](); + } + } + }; + + function maybeUnescapeQuote() { + var nextChar = path[index + 1]; + if (mode === IN_SINGLE_QUOTE && nextChar === "'" || mode === IN_DOUBLE_QUOTE && nextChar === '"') { + index++; + newChar = '\\' + nextChar; + actions[APPEND](); + return true; + } + } + + while (mode != null) { + index++; + c = path[index]; + + if (c === '\\' && maybeUnescapeQuote()) { + continue; + } + + type = getPathCharType(c); + typeMap = pathStateMachine[mode]; + transition = typeMap[type] || typeMap['else'] || ERROR; + + if (transition === ERROR) { + return; // parse error + } + + mode = transition[0]; + action = actions[transition[1]]; + if (action) { + newChar = transition[2]; + newChar = newChar === undefined ? c : newChar; + if (action() === false) { + return; + } + } + + if (mode === AFTER_PATH) { + keys.raw = path; + return keys; + } + } +} + +/** + * External parse that check for a cache hit first + * + * @param {String} path + * @return {Array|undefined} + */ + +function parsePath(path) { + var hit = pathCache.get(path); + if (!hit) { + hit = parse(path); + if (hit) { + pathCache.put(path, hit); + } + } + return hit; +} + +/** + * Get from an object from a path string + * + * @param {Object} obj + * @param {String} path + */ + +function getPath(obj, path) { + return parseExpression(path).get(obj); +} + +/** + * Warn against setting non-existent root path on a vm. + */ + +var warnNonExistent; +if (process.env.NODE_ENV !== 'production') { + warnNonExistent = function (path, vm) { + warn('You are setting a non-existent path "' + path.raw + '" ' + 'on a vm instance. Consider pre-initializing the property ' + 'with the "data" option for more reliable reactivity ' + 'and better performance.', vm); + }; +} + +/** + * Set on an object from a path + * + * @param {Object} obj + * @param {String | Array} path + * @param {*} val + */ + +function setPath(obj, path, val) { + var original = obj; + if (typeof path === 'string') { + path = parse(path); + } + if (!path || !isObject(obj)) { + return false; + } + var last, key; + for (var i = 0, l = path.length; i < l; i++) { + last = obj; + key = path[i]; + if (key.charAt(0) === '*') { + key = parseExpression(key.slice(1)).get.call(original, original); + } + if (i < l - 1) { + obj = obj[key]; + if (!isObject(obj)) { + obj = {}; + if (process.env.NODE_ENV !== 'production' && last._isVue) { + warnNonExistent(path, last); + } + set(last, key, obj); + } + } else { + if (isArray(obj)) { + obj.$set(key, val); + } else if (key in obj) { + obj[key] = val; + } else { + if (process.env.NODE_ENV !== 'production' && obj._isVue) { + warnNonExistent(path, obj); + } + set(obj, key, val); + } + } + } + return true; +} + +var path = Object.freeze({ + parsePath: parsePath, + getPath: getPath, + setPath: setPath +}); + +var expressionCache = new Cache(1000); + +var allowedKeywords = 'Math,Date,this,true,false,null,undefined,Infinity,NaN,' + 'isNaN,isFinite,decodeURI,decodeURIComponent,encodeURI,' + 'encodeURIComponent,parseInt,parseFloat'; +var allowedKeywordsRE = new RegExp('^(' + allowedKeywords.replace(/,/g, '\\b|') + '\\b)'); + +// keywords that don't make sense inside expressions +var improperKeywords = 'break,case,class,catch,const,continue,debugger,default,' + 'delete,do,else,export,extends,finally,for,function,if,' + 'import,in,instanceof,let,return,super,switch,throw,try,' + 'var,while,with,yield,enum,await,implements,package,' + 'protected,static,interface,private,public'; +var improperKeywordsRE = new RegExp('^(' + improperKeywords.replace(/,/g, '\\b|') + '\\b)'); + +var wsRE = /\s/g; +var newlineRE = /\n/g; +var saveRE = /[\{,]\s*[\w\$_]+\s*:|('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`)|new |typeof |void /g; +var restoreRE = /"(\d+)"/g; +var pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/; +var identRE = /[^\w$\.](?:[A-Za-z_$][\w$]*)/g; +var literalValueRE$1 = /^(?:true|false|null|undefined|Infinity|NaN)$/; + +function noop() {} + +/** + * Save / Rewrite / Restore + * + * When rewriting paths found in an expression, it is + * possible for the same letter sequences to be found in + * strings and Object literal property keys. Therefore we + * remove and store these parts in a temporary array, and + * restore them after the path rewrite. + */ + +var saved = []; + +/** + * Save replacer + * + * The save regex can match two possible cases: + * 1. An opening object literal + * 2. A string + * If matched as a plain string, we need to escape its + * newlines, since the string needs to be preserved when + * generating the function body. + * + * @param {String} str + * @param {String} isString - str if matched as a string + * @return {String} - placeholder with index + */ + +function save(str, isString) { + var i = saved.length; + saved[i] = isString ? str.replace(newlineRE, '\\n') : str; + return '"' + i + '"'; +} + +/** + * Path rewrite replacer + * + * @param {String} raw + * @return {String} + */ + +function rewrite(raw) { + var c = raw.charAt(0); + var path = raw.slice(1); + if (allowedKeywordsRE.test(path)) { + return raw; + } else { + path = path.indexOf('"') > -1 ? path.replace(restoreRE, restore) : path; + return c + 'scope.' + path; + } +} + +/** + * Restore replacer + * + * @param {String} str + * @param {String} i - matched save index + * @return {String} + */ + +function restore(str, i) { + return saved[i]; +} + +/** + * Rewrite an expression, prefixing all path accessors with + * `scope.` and generate getter/setter functions. + * + * @param {String} exp + * @return {Function} + */ + +function compileGetter(exp) { + if (improperKeywordsRE.test(exp)) { + process.env.NODE_ENV !== 'production' && warn('Avoid using reserved keywords in expression: ' + exp); + } + // reset state + saved.length = 0; + // save strings and object literal keys + var body = exp.replace(saveRE, save).replace(wsRE, ''); + // rewrite all paths + // pad 1 space here because the regex matches 1 extra char + body = (' ' + body).replace(identRE, rewrite).replace(restoreRE, restore); + return makeGetterFn(body); +} + +/** + * Build a getter function. Requires eval. + * + * We isolate the try/catch so it doesn't affect the + * optimization of the parse function when it is not called. + * + * @param {String} body + * @return {Function|undefined} + */ + +function makeGetterFn(body) { + try { + /* eslint-disable no-new-func */ + return new Function('scope', 'return ' + body + ';'); + /* eslint-enable no-new-func */ + } catch (e) { + if (process.env.NODE_ENV !== 'production') { + /* istanbul ignore if */ + if (e.toString().match(/unsafe-eval|CSP/)) { + warn('It seems you are using the default build of Vue.js in an environment ' + 'with Content Security Policy that prohibits unsafe-eval. ' + 'Use the CSP-compliant build instead: ' + 'http://vuejs.org/guide/installation.html#CSP-compliant-build'); + } else { + warn('Invalid expression. ' + 'Generated function body: ' + body); + } + } + return noop; + } +} + +/** + * Compile a setter function for the expression. + * + * @param {String} exp + * @return {Function|undefined} + */ + +function compileSetter(exp) { + var path = parsePath(exp); + if (path) { + return function (scope, val) { + setPath(scope, path, val); + }; + } else { + process.env.NODE_ENV !== 'production' && warn('Invalid setter expression: ' + exp); + } +} + +/** + * Parse an expression into re-written getter/setters. + * + * @param {String} exp + * @param {Boolean} needSet + * @return {Function} + */ + +function parseExpression(exp, needSet) { + exp = exp.trim(); + // try cache + var hit = expressionCache.get(exp); + if (hit) { + if (needSet && !hit.set) { + hit.set = compileSetter(hit.exp); + } + return hit; + } + var res = { exp: exp }; + res.get = isSimplePath(exp) && exp.indexOf('[') < 0 + // optimized super simple getter + ? makeGetterFn('scope.' + exp) + // dynamic getter + : compileGetter(exp); + if (needSet) { + res.set = compileSetter(exp); + } + expressionCache.put(exp, res); + return res; +} + +/** + * Check if an expression is a simple path. + * + * @param {String} exp + * @return {Boolean} + */ + +function isSimplePath(exp) { + return pathTestRE.test(exp) && + // don't treat literal values as paths + !literalValueRE$1.test(exp) && + // Math constants e.g. Math.PI, Math.E etc. + exp.slice(0, 5) !== 'Math.'; +} + +var expression = Object.freeze({ + parseExpression: parseExpression, + isSimplePath: isSimplePath +}); + +// we have two separate queues: one for directive updates +// and one for user watcher registered via $watch(). +// we want to guarantee directive updates to be called +// before user watchers so that when user watchers are +// triggered, the DOM would have already been in updated +// state. + +var queue = []; +var userQueue = []; +var has = {}; +var circular = {}; +var waiting = false; + +/** + * Reset the batcher's state. + */ + +function resetBatcherState() { + queue.length = 0; + userQueue.length = 0; + has = {}; + circular = {}; + waiting = false; +} + +/** + * Flush both queues and run the watchers. + */ + +function flushBatcherQueue() { + var _again = true; + + _function: while (_again) { + _again = false; + + runBatcherQueue(queue); + runBatcherQueue(userQueue); + // user watchers triggered more watchers, + // keep flushing until it depletes + if (queue.length) { + _again = true; + continue _function; + } + // dev tool hook + /* istanbul ignore if */ + if (devtools && config.devtools) { + devtools.emit('flush'); + } + resetBatcherState(); + } +} + +/** + * Run the watchers in a single queue. + * + * @param {Array} queue + */ + +function runBatcherQueue(queue) { + // do not cache length because more watchers might be pushed + // as we run existing watchers + for (var i = 0; i < queue.length; i++) { + var watcher = queue[i]; + var id = watcher.id; + has[id] = null; + watcher.run(); + // in dev build, check and stop circular updates. + if (process.env.NODE_ENV !== 'production' && has[id] != null) { + circular[id] = (circular[id] || 0) + 1; + if (circular[id] > config._maxUpdateCount) { + warn('You may have an infinite update loop for watcher ' + 'with expression "' + watcher.expression + '"', watcher.vm); + break; + } + } + } + queue.length = 0; +} + +/** + * Push a watcher into the watcher queue. + * Jobs with duplicate IDs will be skipped unless it's + * pushed when the queue is being flushed. + * + * @param {Watcher} watcher + * properties: + * - {Number} id + * - {Function} run + */ + +function pushWatcher(watcher) { + var id = watcher.id; + if (has[id] == null) { + // push watcher into appropriate queue + var q = watcher.user ? userQueue : queue; + has[id] = q.length; + q.push(watcher); + // queue the flush + if (!waiting) { + waiting = true; + nextTick(flushBatcherQueue); + } + } +} + +var uid$2 = 0; + +/** + * A watcher parses an expression, collects dependencies, + * and fires callback when the expression value changes. + * This is used for both the $watch() api and directives. + * + * @param {Vue} vm + * @param {String|Function} expOrFn + * @param {Function} cb + * @param {Object} options + * - {Array} filters + * - {Boolean} twoWay + * - {Boolean} deep + * - {Boolean} user + * - {Boolean} sync + * - {Boolean} lazy + * - {Function} [preProcess] + * - {Function} [postProcess] + * @constructor + */ +function Watcher(vm, expOrFn, cb, options) { + // mix in options + if (options) { + extend(this, options); + } + var isFn = typeof expOrFn === 'function'; + this.vm = vm; + vm._watchers.push(this); + this.expression = expOrFn; + this.cb = cb; + this.id = ++uid$2; // uid for batching + this.active = true; + this.dirty = this.lazy; // for lazy watchers + this.deps = []; + this.newDeps = []; + this.depIds = new _Set(); + this.newDepIds = new _Set(); + this.prevError = null; // for async error stacks + // parse expression for getter/setter + if (isFn) { + this.getter = expOrFn; + this.setter = undefined; + } else { + var res = parseExpression(expOrFn, this.twoWay); + this.getter = res.get; + this.setter = res.set; + } + this.value = this.lazy ? undefined : this.get(); + // state for avoiding false triggers for deep and Array + // watchers during vm._digest() + this.queued = this.shallow = false; +} + +/** + * Evaluate the getter, and re-collect dependencies. + */ + +Watcher.prototype.get = function () { + this.beforeGet(); + var scope = this.scope || this.vm; + var value; + try { + value = this.getter.call(scope, scope); + } catch (e) { + if (process.env.NODE_ENV !== 'production' && config.warnExpressionErrors) { + warn('Error when evaluating expression ' + '"' + this.expression + '": ' + e.toString(), this.vm); + } + } + // "touch" every property so they are all tracked as + // dependencies for deep watching + if (this.deep) { + traverse(value); + } + if (this.preProcess) { + value = this.preProcess(value); + } + if (this.filters) { + value = scope._applyFilters(value, null, this.filters, false); + } + if (this.postProcess) { + value = this.postProcess(value); + } + this.afterGet(); + return value; +}; + +/** + * Set the corresponding value with the setter. + * + * @param {*} value + */ + +Watcher.prototype.set = function (value) { + var scope = this.scope || this.vm; + if (this.filters) { + value = scope._applyFilters(value, this.value, this.filters, true); + } + try { + this.setter.call(scope, scope, value); + } catch (e) { + if (process.env.NODE_ENV !== 'production' && config.warnExpressionErrors) { + warn('Error when evaluating setter ' + '"' + this.expression + '": ' + e.toString(), this.vm); + } + } + // two-way sync for v-for alias + var forContext = scope.$forContext; + if (forContext && forContext.alias === this.expression) { + if (forContext.filters) { + process.env.NODE_ENV !== 'production' && warn('It seems you are using two-way binding on ' + 'a v-for alias (' + this.expression + '), and the ' + 'v-for has filters. This will not work properly. ' + 'Either remove the filters or use an array of ' + 'objects and bind to object properties instead.', this.vm); + return; + } + forContext._withLock(function () { + if (scope.$key) { + // original is an object + forContext.rawValue[scope.$key] = value; + } else { + forContext.rawValue.$set(scope.$index, value); + } + }); + } +}; + +/** + * Prepare for dependency collection. + */ + +Watcher.prototype.beforeGet = function () { + Dep.target = this; +}; + +/** + * Add a dependency to this directive. + * + * @param {Dep} dep + */ + +Watcher.prototype.addDep = function (dep) { + var id = dep.id; + if (!this.newDepIds.has(id)) { + this.newDepIds.add(id); + this.newDeps.push(dep); + if (!this.depIds.has(id)) { + dep.addSub(this); + } + } +}; + +/** + * Clean up for dependency collection. + */ + +Watcher.prototype.afterGet = function () { + Dep.target = null; + var i = this.deps.length; + while (i--) { + var dep = this.deps[i]; + if (!this.newDepIds.has(dep.id)) { + dep.removeSub(this); + } + } + var tmp = this.depIds; + this.depIds = this.newDepIds; + this.newDepIds = tmp; + this.newDepIds.clear(); + tmp = this.deps; + this.deps = this.newDeps; + this.newDeps = tmp; + this.newDeps.length = 0; +}; + +/** + * Subscriber interface. + * Will be called when a dependency changes. + * + * @param {Boolean} shallow + */ + +Watcher.prototype.update = function (shallow) { + if (this.lazy) { + this.dirty = true; + } else if (this.sync || !config.async) { + this.run(); + } else { + // if queued, only overwrite shallow with non-shallow, + // but not the other way around. + this.shallow = this.queued ? shallow ? this.shallow : false : !!shallow; + this.queued = true; + // record before-push error stack in debug mode + /* istanbul ignore if */ + if (process.env.NODE_ENV !== 'production' && config.debug) { + this.prevError = new Error('[vue] async stack trace'); + } + pushWatcher(this); + } +}; + +/** + * Batcher job interface. + * Will be called by the batcher. + */ + +Watcher.prototype.run = function () { + if (this.active) { + var value = this.get(); + if (value !== this.value || + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated; but only do so if this is a + // non-shallow update (caused by a vm digest). + (isObject(value) || this.deep) && !this.shallow) { + // set new value + var oldValue = this.value; + this.value = value; + // in debug + async mode, when a watcher callbacks + // throws, we also throw the saved before-push error + // so the full cross-tick stack trace is available. + var prevError = this.prevError; + /* istanbul ignore if */ + if (process.env.NODE_ENV !== 'production' && config.debug && prevError) { + this.prevError = null; + try { + this.cb.call(this.vm, value, oldValue); + } catch (e) { + nextTick(function () { + throw prevError; + }, 0); + throw e; + } + } else { + this.cb.call(this.vm, value, oldValue); + } + } + this.queued = this.shallow = false; + } +}; + +/** + * Evaluate the value of the watcher. + * This only gets called for lazy watchers. + */ + +Watcher.prototype.evaluate = function () { + // avoid overwriting another watcher that is being + // collected. + var current = Dep.target; + this.value = this.get(); + this.dirty = false; + Dep.target = current; +}; + +/** + * Depend on all deps collected by this watcher. + */ + +Watcher.prototype.depend = function () { + var i = this.deps.length; + while (i--) { + this.deps[i].depend(); + } +}; + +/** + * Remove self from all dependencies' subcriber list. + */ + +Watcher.prototype.teardown = function () { + if (this.active) { + // remove self from vm's watcher list + // this is a somewhat expensive operation so we skip it + // if the vm is being destroyed or is performing a v-for + // re-render (the watcher list is then filtered by v-for). + if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) { + this.vm._watchers.$remove(this); + } + var i = this.deps.length; + while (i--) { + this.deps[i].removeSub(this); + } + this.active = false; + this.vm = this.cb = this.value = null; + } +}; + +/** + * Recrusively traverse an object to evoke all converted + * getters, so that every nested property inside the object + * is collected as a "deep" dependency. + * + * @param {*} val + */ + +var seenObjects = new _Set(); +function traverse(val, seen) { + var i = undefined, + keys = undefined; + if (!seen) { + seen = seenObjects; + seen.clear(); + } + var isA = isArray(val); + var isO = isObject(val); + if (isA || isO) { + if (val.__ob__) { + var depId = val.__ob__.dep.id; + if (seen.has(depId)) { + return; + } else { + seen.add(depId); + } + } + if (isA) { + i = val.length; + while (i--) traverse(val[i], seen); + } else if (isO) { + keys = Object.keys(val); + i = keys.length; + while (i--) traverse(val[keys[i]], seen); + } + } +} + +var text$1 = { + + bind: function bind() { + this.attr = this.el.nodeType === 3 ? 'data' : 'textContent'; + }, + + update: function update(value) { + this.el[this.attr] = _toString(value); + } +}; + +var templateCache = new Cache(1000); +var idSelectorCache = new Cache(1000); + +var map = { + efault: [0, '', ''], + legend: [1, '
                ', '
                '], + tr: [2, '', '
                '], + col: [2, '', '
                '] +}; + +map.td = map.th = [3, '', '
                ']; + +map.option = map.optgroup = [1, '']; + +map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '', '
                ']; + +map.g = map.defs = map.symbol = map.use = map.image = map.text = map.circle = map.ellipse = map.line = map.path = map.polygon = map.polyline = map.rect = [1, '', '']; + +/** + * Check if a node is a supported template node with a + * DocumentFragment content. + * + * @param {Node} node + * @return {Boolean} + */ + +function isRealTemplate(node) { + return isTemplate(node) && isFragment(node.content); +} + +var tagRE$1 = /<([\w:-]+)/; +var entityRE = /&#?\w+?;/; +var commentRE = /\n \n {{ cellData[\"sort\"] }}\n \n\n \n \n \n \n {{ cellData[\"emoji\"] }}\n \n\n \n \n\n \n \n\n \n\n \n\n \n\n\n\n" +if (module.hot) {(function () { module.hot.accept() + var hotAPI = require("vue-hot-reload-api") + hotAPI.install(require("vue"), true) + if (!hotAPI.compatible) return + if (!module.hot.data) { + hotAPI.createRecord("_v-5290d11a", module.exports) + } else { + hotAPI.update("_v-5290d11a", module.exports, (typeof module.exports === "function" ? module.exports.options : module.exports).template) + } +})()} +},{"vue":3,"vue-hot-reload-api":2}],7:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = { + template: '#smart-header', + props: { + headerData: Object, + headerIndex: Number, + sortOrder: Number, + sortIndex: Number + }, + computed: { + sortClasses: function sortClasses() { + if (this.sortIndex === this.headerIndex && this.sortOrder < 0) { + classes = "text-success glyphicon-sort-by-attributes-alt"; + } else if (this.sortIndex === this.headerIndex && this.sortOrder > 0) { + classes = "text-success glyphicon-sort-by-attributes"; + } else { + classes = "text-muted glyphicon-sort"; + } + return classes; + } + }, + methods: { + showTooltip: function showTooltip(event) { + $(event.target).tooltip('show'); + }, + notifySortByHeader: function notifySortByHeader() { + // Notify the parent table to all rows by this index + this.$dispatch('receiveSortByHeader', this.headerIndex); + } + } +}; +if (module.exports.__esModule) module.exports = module.exports.default +;(typeof module.exports === "function"? module.exports.options: module.exports).template = "\n\n\n\n \n\n \n \n\n \n\n \n\n \n\n\n\n" +if (module.hot) {(function () { module.hot.accept() + var hotAPI = require("vue-hot-reload-api") + hotAPI.install(require("vue"), true) + if (!hotAPI.compatible) return + if (!module.hot.data) { + hotAPI.createRecord("_v-1298d676", module.exports) + } else { + hotAPI.update("_v-1298d676", module.exports, (typeof module.exports === "function" ? module.exports.options : module.exports).template) + } +})()} +},{"vue":3,"vue-hot-reload-api":2}],8:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _Header = require('./Header.vue'); + +var _Header2 = _interopRequireDefault(_Header); + +var _Cell = require('./Cell.vue'); + +var _Cell2 = _interopRequireDefault(_Cell); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Vue.filter('caseInsensitiveOrderBy', function (arr, sortIndex, reverse) { +// // This is basically a copy of Vue's native orderBy except we are overriding +// // the last part to see if the cell has custom sort attributes +// var order = (reverse && reverse < 0) ? -1 : 1 +// // sort on a copy to avoid mutating original array +// return arr.slice().sort(function (a, b) { +// // Check if cell has custom sorting +// if (a[sortIndex] && b[sortIndex] && typeof(a[sortIndex].sort) !== 'undefined') { +// a = a[sortIndex].sort +// b = b[sortIndex].sort +// } else if (a[sortIndex] && b[sortIndex] && typeof(a[sortIndex].text) !== 'undefined') { +// a = a[sortIndex].text +// b = b[sortIndex].text +// } else { +// console.log('Error sorting; sort key probably doesnt exist'); +// } +// return a === b ? 0 : a > b ? order : -order +// }) + +// }); + +exports.default = { + template: '#smart-table', + props: { + tableHeaders: Array, + tableContent: Array, + filterKey: String, + defaultSortKey: String, + defaultSortOrder: String, + tableClass: String + }, + components: { + Header: _Header2.default, + Cell: _Cell2.default + }, + data: function data() { + return { + sortIndex: this.getDefaultSortIndex(), + sortOrder: this.getDefaultSortOrder() + }; + }, + methods: { + getDefaultSortOrder: function getDefaultSortOrder() { + if (this.defaultSortOrder === "desc") { + return -1; + } else { + return 1; + } + }, + getDefaultSortIndex: function getDefaultSortIndex() { + // Find the index of the column that matches the default sorting key + var index = null; + if (typeof this.tableHeaders !== 'undefined') { + // Check table is not empty + for (var i = 0; i < this.tableHeaders.length; i++) { + if (this.defaultSortKey !== "") { + if (this.tableHeaders[i].key === this.defaultSortKey) { + index = i; + } + } else { + index = 0; // if defaultSortKey is not set + } + } + } + return index; + } + }, + events: { + receiveSortByHeader: function receiveSortByHeader(headerIndex) { + // Set the current sorting key; flip it (x * -1) if already in place + // We have to modify the original .data so that the computed props will update + if (this.sortIndex === headerIndex) { + this.sortOrder = this.sortOrder * -1; + } else { + this.sortOrder = 1; + } + this.sortIndex = headerIndex; + } + }, + computed: { + rows: function rows() { + var rows = []; + for (var i = 0; i < this.tableContent.length; i++) { + // For each row and cell type push it to the master list + var rowCells = []; + for (var j = 0; j < this.tableContent[i].length; j++) { + rowCells.push(this.tableContent[i][j]); + } + rows.push(rowCells); + }; + return rows; + }, + headers: function headers() { + // For each cell in the rows push its head value to a consolidated list + var headers = []; + if (typeof this.tableContent[0] !== 'undefined') { + // Check table is not empty + for (var i = 0; i < this.tableHeaders.length; i++) { + headers.push(this.tableHeaders[i]); + } + } + return headers; + } + } +}; +if (module.exports.__esModule) module.exports = module.exports.default +;(typeof module.exports === "function"? module.exports.options: module.exports).template = "\n\n\n \n \n \n \n \n \n \n \n \n \n \n
                No Data Available
                \n\n" +if (module.hot) {(function () { module.hot.accept() + var hotAPI = require("vue-hot-reload-api") + hotAPI.install(require("vue"), true) + if (!hotAPI.compatible) return + if (!module.hot.data) { + hotAPI.createRecord("_v-2a780546", module.exports) + } else { + hotAPI.update("_v-2a780546", module.exports, (typeof module.exports === "function" ? module.exports.options : module.exports).template) + } +})()} +},{"./Cell.vue":6,"./Header.vue":7,"vue":3,"vue-hot-reload-api":2}]},{},[4]); diff --git a/static/favicon.ico b/tabbycat/static/favicon.ico similarity index 100% rename from static/favicon.ico rename to tabbycat/static/favicon.ico diff --git a/static/admin/css/ie.css b/tabbycat/static/jet/css/themes/img/icon-no.svg similarity index 100% rename from static/admin/css/ie.css rename to tabbycat/static/jet/css/themes/img/icon-no.svg diff --git a/tournaments/templates/vue.js b/tabbycat/static/jquery-ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from tournaments/templates/vue.js rename to tabbycat/static/jquery-ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/venues/__init__.py b/tabbycat/static/jquery-ui/themes/base/images/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from venues/__init__.py rename to tabbycat/static/jquery-ui/themes/base/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/venues/migrations/__init__.py b/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png similarity index 100% rename from venues/migrations/__init__.py rename to tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png b/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png b/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png b/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png b/tabbycat/static/jquery-ui/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/tabbycat/static/jquery-ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-icons_222222_256x240.png b/tabbycat/static/jquery-ui/themes/base/images/ui-icons_222222_256x240.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-icons_2e83ff_256x240.png b/tabbycat/static/jquery-ui/themes/base/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-icons_454545_256x240.png b/tabbycat/static/jquery-ui/themes/base/images/ui-icons_454545_256x240.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-icons_888888_256x240.png b/tabbycat/static/jquery-ui/themes/base/images/ui-icons_888888_256x240.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/static/jquery-ui/themes/base/images/ui-icons_cd0a0a_256x240.png b/tabbycat/static/jquery-ui/themes/base/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/templates/400.html b/tabbycat/templates/400.html similarity index 100% rename from templates/400.html rename to tabbycat/templates/400.html diff --git a/templates/403.html b/tabbycat/templates/403.html similarity index 100% rename from templates/403.html rename to tabbycat/templates/403.html diff --git a/templates/404.html b/tabbycat/templates/404.html similarity index 100% rename from templates/404.html rename to tabbycat/templates/404.html diff --git a/templates/500.html b/tabbycat/templates/500.html similarity index 100% rename from templates/500.html rename to tabbycat/templates/500.html diff --git a/tabbycat/templates/base.html b/tabbycat/templates/base.html new file mode 100644 index 00000000000..c54767490a4 --- /dev/null +++ b/tabbycat/templates/base.html @@ -0,0 +1,135 @@ +{% load static %}{% load debate_tags %} + + + + + + + {% if page_title %}{{ page_title }}{% else %}{% block page-title %}{% endblock %}{% endif %} + + + + {% block extra-css %}{% endblock %} + + + + + + + + {% block body %} + + {% block nav %} + {% if 'admin/' in request.path and user.is_superuser %} + + + {% endif %} + + {% block modals %} + + {% endblock %} + + {% endblock body %} + + {% block js %} + {% if user.is_authenticated %} + + {% else %} + + {% endif %} + {% endblock js %} + + + {% if not debug %} + + {% endif %} + + + diff --git a/tabbycat/templates/base_vue_table.html b/tabbycat/templates/base_vue_table.html new file mode 100644 index 00000000000..1aec412e392 --- /dev/null +++ b/tabbycat/templates/base_vue_table.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} +{% load debate_tags %} + +{% block content %} + +{% endblock content %} + +{% block js %} + + {{ block.super }} +{% endblock js %} diff --git a/templates/footer.html b/tabbycat/templates/footer.html similarity index 92% rename from templates/footer.html rename to tabbycat/templates/footer.html index 18175174853..772e39736c9 100644 --- a/templates/footer.html +++ b/tabbycat/templates/footer.html @@ -11,11 +11,11 @@ Help {% if user.is_authenticated %} -
              • +
              • 🔒Logout of {{ user }}
              • {% else %} -
              • +
              • 🔓Login
              • {% endif %} @@ -28,7 +28,7 @@ created by Qi-Shan, Chuan-Zheng, and Philip. - Want to setup your own copy? + Want to set up your own copy?
                Check out Debatekeeper for time-keeping on Android devices and debatingballot.com for ballot templates. diff --git a/tabbycat/templates/js-bundles/admin.js b/tabbycat/templates/js-bundles/admin.js new file mode 100644 index 00000000000..014de736349 --- /dev/null +++ b/tabbycat/templates/js-bundles/admin.js @@ -0,0 +1,113 @@ +// Vue and the main app +var Vue = require('vue'); +import vueBases from './main.js'; + +// Redefine so they can be edited +var vueComponents = vueBases.baseComponents; +var vueData = vueBases.baseData; +var vueMethods = {}, vueCreated = null, vueFilters = {}, vueEvents = {}; + +//------------------------------------------------------------------------------ +// Adj Allocation +//------------------------------------------------------------------------------ + +import AllocationContainer from '../js-vue/allocations/AllocationContainer.vue' + +if (typeof allAdjudicators !== 'undefined' && allAdjudicators !== null) { + // All vue data table views must provide this base tablesData in the template + vueComponents['AllocationContainer'] = AllocationContainer; + vueData['allDebates'] = allDebates; + vueData['allAdjudicators'] = allAdjudicators; + vueData['allTeams'] = allTeams; + vueData['allRegions'] = allRegions; + vueData['allCategories'] = allCategories; + vueData['roundInfo'] = roundInfo; +} + +//------------------------------------------------------------------------------ +// Tournament Homepage +//------------------------------------------------------------------------------ + +import UpdatesList from '../js-vue/UpdatesList.vue' +import BallotsGraph from '../js-vue/graphs/BallotsGraph.vue' + +if (typeof updateActionsURL !== 'undefined' && updateResultsURL !== 'undefined') { + vueComponents['UpdatesList'] = UpdatesList; + vueComponents['BallotsGraph'] = BallotsGraph; + vueData = { + latestActions: 'loading', + latestResults: 'loading', + pollFrequency: 30000, // 30 seconds + updateActionsURL: updateActionsURL, // From template + updateResultsURL: updateResultsURL, // From template + }; + vueMethods['updateActions'] = function() { + this.fetchData(updateActionsURL, 'actions'); + }; + vueMethods['updateResults'] = function() { + this.fetchData(updateResultsURL, 'results'); + }; + vueMethods['fetchData'] = function (apiURL, resource) { + var xhr = new XMLHttpRequest() + var self = this + xhr.open('GET', apiURL) + xhr.onload = function () { + if (resource === 'actions') { + self.latestActions = JSON.parse(xhr.responseText); + setTimeout(self.updateActions, self.pollFrequency); + } else { + self.latestResults = JSON.parse(xhr.responseText); + setTimeout(self.updateResults, self.pollFrequency); + } + } + xhr.send() + } + vueCreated = function () { + this.updateActions() + this.updateResults() + }; +} + +//------------------------------------------------------------------------------ +// Printables +//------------------------------------------------------------------------------ + +import Ballot from '../js-vue/printables/Ballot.vue' + +if (typeof printableBaseData !== 'undefined' && printableBaseData !== null) { + vueData = printableBaseData; // From Template + vueComponents['Ballot'] = Ballot; +} + +//------------------------------------------------------------------------------ +// Divisons Allocator +//------------------------------------------------------------------------------ + +import DivisionDroppable from '../js-vue/draganddrops/DivisionDroppable.vue' +import UnallocatedDivisionTeams from '../js-vue/allocations/UnallocatedDivisionTeams.vue' +import TeamDraggable from '../js-vue/draganddrops/TeamDraggable.vue' + +if (typeof divisionsBaseData !== 'undefined' && divisionsBaseData !== null) { + vueData = divisionsBaseData; // From Template + vueMethods = divisionsMethods; // From Template + vueEvents = divisionsEvents; // From Template + vueComponents['DivisionDroppable'] = DivisionDroppable; + vueComponents['TeamDraggable'] = TeamDraggable; + vueComponents['UnallocatedDivisionTeams'] = UnallocatedDivisionTeams; +} + +//------------------------------------------------------------------------------ +// Main Vue Instance +//------------------------------------------------------------------------------ + +if (typeof bypassMainVue === 'undefined') { + new Vue({ + el: 'body', + components: vueComponents, + created: vueCreated, + data: vueData, + events: vueEvents, + filters: vueFilters, + methods: vueMethods + }); +} diff --git a/tabbycat/templates/js-bundles/main.js b/tabbycat/templates/js-bundles/main.js new file mode 100644 index 00000000000..3bf5ec46f33 --- /dev/null +++ b/tabbycat/templates/js-bundles/main.js @@ -0,0 +1,76 @@ +// The base template with universal or near-universal functionality (imported on all pages) + +//------------------------------------------------------------------------------ +// jQuery and Boostrap +//------------------------------------------------------------------------------ + +var $ = require("jquery"); +global.jQuery = $; // Set for bootstrap +window.$ = $; // Set for browser window +require("bootstrap"); + +// Mount global jquery stuff here +$(document).ready(function(){ + // Enable hover tooltips for all elements + $('[data-toggle=tooltip]').tooltip({ + 'html': true, + 'placement': 'top' + }); + // Disable buttons post submission + $('.submit-disable').on('click', function () { + var $btn = $(this).button('loading'); + }); + // Make larger click targets for checkboxes in tables + $('.checkbox-target').on('click', function (e) { + if (e.target == this) { // Don't trigger when clicking the input itself + var checkBox = $("input[type=checkbox]", this).first(); + checkBox.prop("checked", !checkBox.prop("checked")); + checkBox.trigger("change"); + } + }); +}); + +// Add alerts programmatically +$.fn.extend({ + showAlert: function(alerttype, message, timeout) { + $('#messages-container').append('
                ' + message + '
                '); + if (timeout && timeout !== 0) { + setTimeout(function() { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs + $("#alertdiv").alert('close'); + }, timeout); + } + } +}); + +//------------------------------------------------------------------------------ +// Vues +//------------------------------------------------------------------------------ + +// Plugin mounting points for components/data +var baseComponents = {} +var baseData = {} + +// Table-based Views +import TablesContainer from '../js-vue/tables/TablesContainer.vue' + +if (typeof tablesData !== 'undefined' && tablesData !== null) { + // All vue data table views must provide this base tablesData in the template + baseComponents['TablesContainer'] = TablesContainer; + baseData['tablesData'] = tablesData; +} + +// Graph-based Views +import TextDisplay from '../js-vue/graphs/TextDisplay.vue' +import DonutChart from '../js-vue/graphs/DonutChart.vue' + +if (typeof graphsData !== 'undefined' && graphsData !== null) { + baseComponents['TextDisplay'] = TextDisplay + baseComponents['DonutChart'] = DonutChart + baseData['graphsData'] = graphsData +} + +// For admin modules +export default { + baseComponents: baseComponents, + baseData: baseData, +} \ No newline at end of file diff --git a/tabbycat/templates/js-bundles/public.js b/tabbycat/templates/js-bundles/public.js new file mode 100644 index 00000000000..3849e37d8d0 --- /dev/null +++ b/tabbycat/templates/js-bundles/public.js @@ -0,0 +1,19 @@ +// Vue and the main app +var Vue = require('vue'); +import vueBases from './main.js'; + +// Redefine so they can be edited +var vueComponents = vueBases.baseComponents; +var vueData = vueBases.baseData; + +//------------------------------------------------------------------------------ +// Main Vue Instance +//------------------------------------------------------------------------------ + +if (typeof bypassMainVue === 'undefined') { + new Vue({ + el: 'body', + components: vueComponents, + data: vueData + }); +} \ No newline at end of file diff --git a/adjallocation/templates/js/draw_adjs_edit_allocation.js b/tabbycat/templates/js-standalones/draw_adjs_edit_allocation.js similarity index 98% rename from adjallocation/templates/js/draw_adjs_edit_allocation.js rename to tabbycat/templates/js-standalones/draw_adjs_edit_allocation.js index f0a54e9460f..f811c1e99ae 100644 --- a/adjallocation/templates/js/draw_adjs_edit_allocation.js +++ b/tabbycat/templates/js-standalones/draw_adjs_edit_allocation.js @@ -15,8 +15,9 @@ function removeConflictClasses(el) { } function removeUnusedRow(oldHolder) { - var old_row = oldHolder.parent(); // Get the - unusedAdjTable.row(old_row).remove().draw(); + var old_row = oldHolder.parent()[0]; // Get the + // Below is buggy; but disabling only makes a few extra lines in the table + // unusedAdjTable.row(old_row).remove().draw(); } function rebindHoverEvents(el) { @@ -286,6 +287,7 @@ $('#auto_allocate').click(function() { btn.attr("disabled", false); } }); + }); $('#save_allocation').click(function() { diff --git a/adjallocation/templates/js/draw_adjs_edit_flags.js b/tabbycat/templates/js-standalones/draw_adjs_edit_flags.js similarity index 100% rename from adjallocation/templates/js/draw_adjs_edit_flags.js rename to tabbycat/templates/js-standalones/draw_adjs_edit_flags.js diff --git a/results/templates/js/enter_results.js b/tabbycat/templates/js-standalones/enter_results.js similarity index 95% rename from results/templates/js/enter_results.js rename to tabbycat/templates/js-standalones/enter_results.js index 1be95145a83..dc9173de843 100644 --- a/results/templates/js/enter_results.js +++ b/tabbycat/templates/js-standalones/enter_results.js @@ -18,6 +18,8 @@ function refresh_totals(scoresheet) { $scoresheet = $(scoresheet); $aff_total = $('.aff_total', $scoresheet); $neg_total = $('.neg_total', $scoresheet); + $aff_margin = $('.aff_margin', $scoresheet); + $neg_margin = $('.neg_margin', $scoresheet); var aff = sum($('.aff.score input', $scoresheet)); var neg = sum($('.neg.score input', $scoresheet)); @@ -27,12 +29,18 @@ function refresh_totals(scoresheet) { if (aff > neg) { $aff_total.addClass('btn-success').removeClass('btn-danger'); $neg_total.addClass('btn-danger').removeClass('btn-success'); + $aff_margin.text("+" + Number(aff - neg)); + $neg_margin.text(Number(neg - aff)); } else if (neg > aff) { $aff_total.addClass('btn-danger').removeClass('btn-success'); $neg_total.addClass('btn-success').removeClass('btn-danger'); + $aff_margin.text(Number(aff - neg)); + $neg_margin.text("+" + Number(neg - aff)); } else { $aff_total.addClass('btn-danger').removeClass('btn-success'); $neg_total.addClass('btn-danger').removeClass('btn-success'); + $aff_margin.text(Number(aff - neg)); + $neg_margin.text(Number(neg - aff)); } } diff --git a/tabbycat/templates/js-vendor/jquery-ui.min.js b/tabbycat/templates/js-vendor/jquery-ui.min.js new file mode 100644 index 00000000000..5824d1292db --- /dev/null +++ b/tabbycat/templates/js-vendor/jquery-ui.min.js @@ -0,0 +1,13 @@ +/*! jQuery UI - v1.11.4 - 2015-03-11 +* http://jqueryui.com +* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js +* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ + +(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return"area"===r?(n=t.parentNode,a=n.name,t.href&&a&&"map"===n.nodeName.toLowerCase()?(o=e("img[usemap='#"+a+"']")[0],!!o&&i(o)):!1):(/^(input|select|textarea|button|object)$/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}function s(e){for(var t,i;e.length&&e[0]!==document;){if(t=e.css("position"),("absolute"===t||"relative"===t||"fixed"===t)&&(i=parseInt(e.css("zIndex"),10),!isNaN(i)&&0!==i))return i;e=e.parent()}return 0}function n(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.regional.en=e.extend(!0,{},this.regional[""]),this.regional["en-US"]=e.extend(!0,{},this.regional.en),this.dpDiv=a(e("
                "))}function a(t){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(i,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",o)}function o(){e.datepicker._isDisabledDatepicker(v.inline?v.dpDiv.parent()[0]:v.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))}function r(t,i){e.extend(t,i);for(var s in i)null==i[s]&&(t[s]=i[s]);return t}function h(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+"px")})},e.fn["outer"+i]=function(t,n){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var l=0,u=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,n=u.call(arguments,1),a=0,o=n.length;o>a;a++)for(i in n[a])s=n[a][i],n[a].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(n){var a="string"==typeof n,o=u.call(arguments,1),r=this;return a?this.each(function(){var i,a=e.data(this,s);return"instance"===n?(r=a,!1):a?e.isFunction(a[n])&&"_"!==n.charAt(0)?(i=a[n].apply(a,o),i!==a&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+n+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+n+"'")}):(o.length&&(n=e.widget.extend.apply(null,[n].concat(o))),this.each(function(){var t=e.data(this,s);t?(t.option(n||{}),t._init&&t._init()):e.data(this,s,new i(n,this))})),r}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
                ",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=l++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget;var d=!1;e(document).mouseup(function(){d=!1}),e.widget("ui.mouse",{version:"1.11.4",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!d){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var i=this,s=1===t.which,n="string"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return i._mouseMove(e)},this._mouseUpDelegate=function(e){return i._mouseUp(e)},this.document.bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),d=!0,!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button)return this._mouseUp(t);if(!t.which)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),d=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),function(){function t(e,t,i){return[parseFloat(e[0])*(p.test(e[0])?t/100:1),parseFloat(e[1])*(p.test(e[1])?i/100:1)]}function i(t,i){return parseInt(e.css(t,i),10)||0}function s(t){var i=t[0];return 9===i.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(i)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,u=/top|center|bottom/,d=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,p=/%$/,f=e.fn.position;e.position={scrollbarWidth:function(){if(void 0!==n)return n;var t,i,s=e("
                "),a=s.children()[0];return e("body").append(s),t=a.offsetWidth,s.css("overflow","scroll"),i=a.offsetWidth,t===i&&(i=s[0].clientWidth),s.remove(),n=t-i},getScrollInfo:function(t){var i=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),s=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),n="scroll"===i||"auto"===i&&t.widthi?"left":t>0?"right":"center",vertical:0>a?"top":s>0?"bottom":"middle"};d>m&&m>r(t+i)&&(h.horizontal="center"),c>g&&g>r(s+a)&&(h.vertical="middle"),h.important=o(r(t),r(i))>o(r(s),r(a))?"horizontal":"vertical",n.using.call(this,e,h)}),u.offset(e.extend(M,{using:l}))})},e.ui.position={fit:{left:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=e.left-t.collisionPosition.marginLeft,h=n-r,l=r+t.collisionWidth-a-n;t.collisionWidth>a?h>0&&0>=l?(i=e.left+h+t.collisionWidth-a-n,e.left+=h-i):e.left=l>0&&0>=h?n:h>l?n+a-t.collisionWidth:n:h>0?e.left+=h:l>0?e.left-=l:e.left=o(e.left-r,e.left)},top:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollTop:s.offset.top,a=t.within.height,r=e.top-t.collisionPosition.marginTop,h=n-r,l=r+t.collisionHeight-a-n;t.collisionHeight>a?h>0&&0>=l?(i=e.top+h+t.collisionHeight-a-n,e.top+=h-i):e.top=l>0&&0>=h?n:h>l?n+a-t.collisionHeight:n:h>0?e.top+=h:l>0?e.top-=l:e.top=o(e.top-r,e.top)}},flip:{left:function(e,t){var i,s,n=t.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=e.left-t.collisionPosition.marginLeft,u=l-h,d=l+t.collisionWidth-o-h,c="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,p="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,f=-2*t.offset[0];0>u?(i=e.left+c+p+f+t.collisionWidth-o-a,(0>i||r(u)>i)&&(e.left+=c+p+f)):d>0&&(s=e.left-t.collisionPosition.marginLeft+c+p+f-h,(s>0||d>r(s))&&(e.left+=c+p+f))},top:function(e,t){var i,s,n=t.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=e.top-t.collisionPosition.marginTop,u=l-h,d=l+t.collisionHeight-o-h,c="top"===t.my[1],p=c?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,f="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,m=-2*t.offset[1];0>u?(s=e.top+p+f+m+t.collisionHeight-o-a,(0>s||r(u)>s)&&(e.top+=p+f+m)):d>0&&(i=e.top-t.collisionPosition.marginTop+p+f+m-h,(i>0||d>r(i))&&(e.top+=p+f+m))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,i,s,n,o,r=document.getElementsByTagName("body")[0],h=document.createElement("div");t=document.createElement(r?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},r&&e.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(o in s)t.style[o]=s[o];t.appendChild(h),i=r||document.documentElement,i.insertBefore(t,i.firstChild),h.style.cssText="position: absolute; left: 10.7432222px;",n=e(h).offset().left,a=n>10&&11>n,t.innerHTML="",i.removeChild(t)}()}(),e.ui.position,e.widget("ui.accordion",{version:"1.11.4",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").removeUniqueId(),this._destroyIcons(),e=this.headers.next().removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&(this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)),void 0)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,s=this.headers.length,n=this.headers.index(t.target),a=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:a=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:a=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:a=this.headers[0];break;case i.END:a=this.headers[s-1]}a&&(e(t.target).attr("tabIndex",-1),e(a).attr("tabIndex",0),a.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var e=this.headers,t=this.panels;this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-state-default ui-corner-all"),this.panels=this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide(),t&&(this._off(e.not(this.headers)),this._off(t.not(this.panels)))},_refresh:function(){var t,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(){var t=e(this),i=t.uniqueId().attr("id"),s=t.next(),n=s.uniqueId().attr("id");t.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(t=n.height(),this.element.siblings(":visible").each(function(){var i=e(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(t-=i.outerHeight(!0))}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===s&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n[0]===s[0],o=a&&i.collapsible,r=o?e():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:o?e():n,newPanel:r};t.preventDefault(),a&&!i.collapsible||this._trigger("beforeActivate",t,l)===!1||(i.active=o?!1:this.headers.index(n),this.active=a?e():n,this._toggle(l),s.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),a||(n.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&n.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var i=t.newPanel,s=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,t):(s.hide(),i.show(),this._toggleComplete(t)),s.attr({"aria-hidden":"true"}),s.prev().attr({"aria-selected":"false","aria-expanded":"false"}),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===parseInt(e(this).attr("tabIndex"),10)}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(e,t,i){var s,n,a,o=this,r=0,h=e.css("box-sizing"),l=e.length&&(!t.length||e.index()",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},items:"> *",menus:"ul",position:{my:"left-1 top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item":function(e){e.preventDefault()},"click .ui-menu-item":function(t){var i=e(t.target);!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&e(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){if(!this.previousFilter){var i=e(t.currentTarget); +i.siblings(".ui-state-active").removeClass("ui-state-active"),this.focus(t,i)}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var i=this.active||this.element.find(this.options.items).eq(0);t||this.focus(e,i)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){this._closeOnDocumentClick(e)&&this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-menu-icons ui-front").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").removeUniqueId().removeClass("ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){var i,s,n,a,o=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:o=!1,s=this.previousFilter||"",n=String.fromCharCode(t.keyCode),a=!1,clearTimeout(this.filterTimer),n===s?a=!0:n=s+n,i=this._filterMenuItems(n),i=a&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(t.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(t,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}o&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.is("[aria-haspopup='true']")?this.expand(e):this.select(e))},refresh:function(){var t,i,s=this,n=this.options.icons.submenu,a=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),a.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-front").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),i=t.parent(),s=e("").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);i.attr("aria-haspopup","true").prepend(s),t.attr("aria-labelledby",i.attr("id"))}),t=a.add(this.element),i=t.find(this.options.items),i.not(".ui-menu-item").each(function(){var t=e(this);s._isDivider(t)&&t.addClass("ui-widget-content ui-menu-divider")}),i.not(".ui-menu-item, .ui-menu-divider").addClass("ui-menu-item").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){"icons"===e&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},focus:function(e,t){var i,s;this.blur(e,e&&"focus"===e.type),this._scrollIntoView(t),this.active=t.first(),s=this.active.addClass("ui-state-focus").removeClass("ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").addClass("ui-state-active"),e&&"keydown"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=t.children(".ui-menu"),i.length&&e&&/^mouse/.test(e.type)&&this._startOpening(i),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,n=t.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=t.outerHeight(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),"true"===e.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var i=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(t,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(t),this.activeMenu=s},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find(".ui-state-active").not(".ui-state-focus").removeClass("ui-state-active")},_closeOnDocumentClick:function(t){return!e(t.target).closest(".ui-menu").length},_isDivider:function(e){return!/[^\-\u2014\u2013\s]/.test(e.text())},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,i){var s;this.active&&(s="first"===e||"last"===e?this.active["first"===e?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[e+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[t]()),this.focus(i,s)},nextPage:function(t){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=e(this),0>i.offset().top-s-n}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(t),void 0)},previousPage:function(t){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=e(this),i.offset().top-s+n>0}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items).first())),void 0):(this.next(t),void 0)},_hasScroll:function(){return this.element.outerHeight()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,void 0;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),void 0):(this._searchTimeout(e),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(e),this._change(e),void 0)}}),this._initSource(),this.menu=e("
                  ").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:n})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&e.trim(s).length&&(this.liveRegion.children().hide(),e("
                  ").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),i=this.menu.element.is(":visible"),s=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;(!t||t&&!i&&!s)&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length").text(i.label).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[e](t),void 0):(this.search(null,t),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.children().hide(),e("
                  ").text(i).appendTo(this.liveRegion))}}),e.ui.autocomplete;var c,p="ui-button ui-widget ui-state-default ui-corner-all",f="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",m=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},g=function(t){var i=t.name,s=t.form,n=e([]);return i&&(i=i.replace(/'/g,"\\'"),n=s?e(s).find("[name='"+i+"'][type=radio]"):e("[name='"+i+"'][type=radio]",t.ownerDocument).filter(function(){return!this.form})),n};e.widget("ui.button",{version:"1.11.4",defaultElement:"").addClass(this._triggerClass).html(a?e("").attr({src:a,alt:n,title:n}):n)),t[r?"before":"after"](i.trigger),i.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,i,s,n,a=new Date(2009,11,20),o=this._get(e,"dateFormat");o.match(/[DM]/)&&(t=function(e){for(i=0,s=0,n=0;e.length>n;n++)e[n].length>i&&(i=e[n].length,s=n);return s},a.setMonth(t(this._get(e,o.match(/MM/)?"monthNames":"monthNamesShort"))),a.setDate(t(this._get(e,o.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),e.input.attr("size",this._formatDate(e,a).length)}},_inlineDatepicker:function(t,i){var s=e(t);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),e.data(t,"datepicker",i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(t),i.dpDiv.css("display","block"))},_dialogDatepicker:function(t,i,s,n,a){var o,h,l,u,d,c=this._dialogInst;return c||(this.uuid+=1,o="dp"+this.uuid,this._dialogInput=e(""),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),c=this._dialogInst=this._newInst(this._dialogInput,!1),c.settings={},e.data(this._dialogInput[0],"datepicker",c)),r(c.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(c,i):i,this._dialogInput.val(i),this._pos=a?a.length?a:[a.pageX,a.pageY]:null,this._pos||(h=document.documentElement.clientWidth,l=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[h/2-100+u,l/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),c.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],"datepicker",c),this},_destroyDatepicker:function(t){var i,s=e(t),n=e.data(t,"datepicker");s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),e.removeData(t,"datepicker"),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty(),v===n&&(v=null))},_enableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,"datepicker");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,"datepicker");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,"datepicker")}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(t,i,s){var n,a,o,h,l=this._getInst(t);return 2===arguments.length&&"string"==typeof i?"defaults"===i?e.extend({},e.datepicker._defaults):l?"all"===i?e.extend({},l.settings):this._get(l,i):null:(n=i||{},"string"==typeof i&&(n={},n[i]=s),l&&(this._curInst===l&&this._hideDatepicker(),a=this._getDateDatepicker(t,!0),o=this._getMinMaxDate(l,"min"),h=this._getMinMaxDate(l,"max"),r(l.settings,n),null!==o&&void 0!==n.dateFormat&&void 0===n.minDate&&(l.settings.minDate=this._formatDate(l,o)),null!==h&&void 0!==n.dateFormat&&void 0===n.maxDate&&(l.settings.maxDate=this._formatDate(l,h)),"disabled"in n&&(n.disabled?this._disableDatepicker(t):this._enableDatepicker(t)),this._attachments(e(t),l),this._autoSize(l),this._setDate(l,a),this._updateAlternate(l),this._updateDatepicker(l)),void 0)},_changeDatepicker:function(e,t,i){this._optionDatepicker(e,t,i)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var i=this._getInst(e);i&&(this._setDate(i,t),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(e,t){var i=this._getInst(e);return i&&!i.inline&&this._setDateFromField(i,t),i?this._getDate(i):null},_doKeyDown:function(t){var i,s,n,a=e.datepicker._getInst(t.target),o=!0,r=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),o=!1;break;case 13:return n=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",a.dpDiv),n[0]&&e.datepicker._selectDay(t.target,a.selectedMonth,a.selectedYear,n[0]),i=e.datepicker._get(a,"onSelect"),i?(s=e.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,"stepBigMonths"):-e.datepicker._get(a,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,"stepBigMonths"):+e.datepicker._get(a,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),o=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),o=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?1:-1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,"stepBigMonths"):-e.datepicker._get(a,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),o=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?-1:1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,"stepBigMonths"):+e.datepicker._get(a,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),o=t.ctrlKey||t.metaKey;break;default:o=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):o=!1;o&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var i,s,n=e.datepicker._getInst(t.target); +return e.datepicker._get(n,"constrainInput")?(i=e.datepicker._possibleChars(e.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==t.charCode?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||" ">s||!i||i.indexOf(s)>-1):void 0},_doKeyUp:function(t){var i,s=e.datepicker._getInst(t.target);if(s.input.val()!==s.lastVal)try{i=e.datepicker.parseDate(e.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,e.datepicker._getFormatConfig(s)),i&&(e.datepicker._setDateFromField(s),e.datepicker._updateAlternate(s),e.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,n,a,o,h,l,u;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),n=e.datepicker._get(i,"beforeShow"),a=n?n.apply(t,[t,i]):{},a!==!1&&(r(i.settings,a),i.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(i),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),o=!1,e(t).parents().each(function(){return o|="fixed"===e(this).css("position"),!o}),h={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(i),h=e.datepicker._checkOffset(i,h,o),i.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":o?"fixed":"absolute",display:"none",left:h.left+"px",top:h.top+"px"}),i.inline||(l=e.datepicker._get(i,"showAnim"),u=e.datepicker._get(i,"duration"),i.dpDiv.css("z-index",s(e(t))+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[l]?i.dpDiv.show(l,e.datepicker._get(i,"showOptions"),u):i.dpDiv[l||"show"](l?u:null),e.datepicker._shouldFocusInput(i)&&i.input.focus(),e.datepicker._curInst=i))}},_updateDatepicker:function(t){this.maxRows=4,v=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t);var i,s=this._getNumberOfMonths(t),n=s[1],a=17,r=t.dpDiv.find("."+this._dayOverClass+" a");r.length>0&&o.apply(r.get(0)),t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&t.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",a*n+"em"),t.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(i=t.yearshtml,setTimeout(function(){i===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),i=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&!e.input.is(":focus")},_checkOffset:function(t,i,s){var n=t.dpDiv.outerWidth(),a=t.dpDiv.outerHeight(),o=t.input?t.input.outerWidth():0,r=t.input?t.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:e(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:e(document).scrollTop());return i.left-=this._get(t,"isRTL")?n-o:0,i.left-=s&&i.left===t.input.offset().left?e(document).scrollLeft():0,i.top-=s&&i.top===t.input.offset().top+r?e(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+r):0),i},_findPos:function(t){for(var i,s=this._getInst(t),n=this._get(s,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[n?"previousSibling":"nextSibling"];return i=e(t).offset(),[i.left,i.top]},_hideDatepicker:function(t){var i,s,n,a,o=this._curInst;!o||t&&o!==e.data(t,"datepicker")||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){e.datepicker._tidyDialog(o)},e.effects&&(e.effects.effect[i]||e.effects[i])?o.dpDiv.hide(i,e.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(e.datepicker._curInst){var i=e(t.target),s=e.datepicker._getInst(i[0]);(i[0].id!==e.datepicker._mainDivId&&0===i.parents("#"+e.datepicker._mainDivId).length&&!i.hasClass(e.datepicker.markerClassName)&&!i.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||i.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==s)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,i,s){var n=e(t),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(t){var i,s=e(t),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(t,i,s){var n=e(t),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(t,i,s,n){var a,o=e(t);e(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(o[0])||(a=this._getInst(o[0]),a.selectedDay=a.currentDay=e("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(t,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(t){var i=e(t);this._selectDate(i,"")},_selectDate:function(t,i){var s,n=e(t),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.input&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var i,s,n,a=this._get(t,"altField");a&&(i=this._get(t,"altFormat")||this._get(t,"dateFormat"),s=this._getDate(t),n=this.formatDate(i,s,this._getFormatConfig(t)),e(a).each(function(){e(this).val(n)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,""]},iso8601Week:function(e){var t,i=new Date(e.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),t=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((t-i)/864e5)/7)+1},parseDate:function(t,i,s){if(null==t||null==i)throw"Invalid arguments";if(i="object"==typeof i?""+i:i+"",""===i)return null;var n,a,o,r,h=0,l=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=typeof l?l:(new Date).getFullYear()%100+parseInt(l,10),d=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,c=(s?s.dayNames:null)||this._defaults.dayNames,p=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,f=(s?s.monthNames:null)||this._defaults.monthNames,m=-1,g=-1,v=-1,y=-1,b=!1,_=function(e){var i=t.length>n+1&&t.charAt(n+1)===e;return i&&n++,i},x=function(e){var t=_(e),s="@"===e?14:"!"===e?20:"y"===e&&t?4:"o"===e?3:2,n="y"===e?s:1,a=RegExp("^\\d{"+n+","+s+"}"),o=i.substring(h).match(a);if(!o)throw"Missing number at position "+h;return h+=o[0].length,parseInt(o[0],10)},w=function(t,s,n){var a=-1,o=e.map(_(t)?n:s,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(o,function(e,t){var s=t[1];return i.substr(h,s.length).toLowerCase()===s.toLowerCase()?(a=t[0],h+=s.length,!1):void 0}),-1!==a)return a+1;throw"Unknown name at position "+h},k=function(){if(i.charAt(h)!==t.charAt(n))throw"Unexpected literal at position "+h;h++};for(n=0;t.length>n;n++)if(b)"'"!==t.charAt(n)||_("'")?k():b=!1;else switch(t.charAt(n)){case"d":v=x("d");break;case"D":w("D",d,c);break;case"o":y=x("o");break;case"m":g=x("m");break;case"M":g=w("M",p,f);break;case"y":m=x("y");break;case"@":r=new Date(x("@")),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case"!":r=new Date((x("!")-this._ticksTo1970)/1e4),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case"'":_("'")?k():b=!0;break;default:k()}if(i.length>h&&(o=i.substr(h),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===m?m=(new Date).getFullYear():100>m&&(m+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=m?0:-100)),y>-1)for(g=1,v=y;;){if(a=this._getDaysInMonth(m,g-1),a>=v)break;g++,v-=a}if(r=this._daylightSavingAdjust(new Date(m,g-1,v)),r.getFullYear()!==m||r.getMonth()+1!==g||r.getDate()!==v)throw"Invalid date";return r},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,i){if(!t)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,o=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,r=(i?i.monthNames:null)||this._defaults.monthNames,h=function(t){var i=e.length>s+1&&e.charAt(s+1)===t;return i&&s++,i},l=function(e,t,i){var s=""+t;if(h(e))for(;i>s.length;)s="0"+s;return s},u=function(e,t,i,s){return h(e)?s[t]:i[t]},d="",c=!1;if(t)for(s=0;e.length>s;s++)if(c)"'"!==e.charAt(s)||h("'")?d+=e.charAt(s):c=!1;else switch(e.charAt(s)){case"d":d+=l("d",t.getDate(),2);break;case"D":d+=u("D",t.getDay(),n,a);break;case"o":d+=l("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":d+=l("m",t.getMonth()+1,2);break;case"M":d+=u("M",t.getMonth(),o,r);break;case"y":d+=h("y")?t.getFullYear():(10>t.getYear()%100?"0":"")+t.getYear()%100;break;case"@":d+=t.getTime();break;case"!":d+=1e4*t.getTime()+this._ticksTo1970;break;case"'":h("'")?d+="'":c=!0;break;default:d+=e.charAt(s)}return d},_possibleChars:function(e){var t,i="",s=!1,n=function(i){var s=e.length>t+1&&e.charAt(t+1)===i;return s&&t++,s};for(t=0;e.length>t;t++)if(s)"'"!==e.charAt(t)||n("'")?i+=e.charAt(t):s=!1;else switch(e.charAt(t)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=e.charAt(t)}return i},_get:function(e,t){return void 0!==e.settings[t]?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var i=this._get(e,"dateFormat"),s=e.lastVal=e.input?e.input.val():null,n=this._getDefaultDate(e),a=n,o=this._getFormatConfig(e);try{a=this.parseDate(i,s,o)||n}catch(r){s=t?"":s}e.selectedDay=a.getDate(),e.drawMonth=e.selectedMonth=a.getMonth(),e.drawYear=e.selectedYear=a.getFullYear(),e.currentDay=s?a.getDate():0,e.currentMonth=s?a.getMonth():0,e.currentYear=s?a.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,i,s){var n=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},a=function(i){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),i,e.datepicker._getFormatConfig(t))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,a=n.getFullYear(),o=n.getMonth(),r=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":r+=parseInt(l[1],10);break;case"w":case"W":r+=7*parseInt(l[1],10);break;case"m":case"M":o+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o));break;case"y":case"Y":a+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o))}l=h.exec(i)}return new Date(a,o,r)},o=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return o=o&&"Invalid Date"==""+o?s:o,o&&(o.setHours(0),o.setMinutes(0),o.setSeconds(0),o.setMilliseconds(0)),this._daylightSavingAdjust(o)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,i){var s=!t,n=e.selectedMonth,a=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),n===e.selectedMonth&&a===e.selectedYear||i||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(s?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&""===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var i=this._get(t,"stepMonths"),s="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){e.datepicker._adjustDate(s,-i,"M")},next:function(){e.datepicker._adjustDate(s,+i,"M")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(s)},selectDay:function(){return e.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return e.datepicker._selectMonthYear(s,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,i,s,n,a,o,r,h,l,u,d,c,p,f,m,g,v,y,b,_,x,w,k,T,D,S,M,C,N,A,P,I,H,z,F,E,O,j,W,L=new Date,R=this._daylightSavingAdjust(new Date(L.getFullYear(),L.getMonth(),L.getDate())),Y=this._get(e,"isRTL"),B=this._get(e,"showButtonPanel"),J=this._get(e,"hideIfNoPrevNext"),q=this._get(e,"navigationAsDateFormat"),K=this._getNumberOfMonths(e),V=this._get(e,"showCurrentAtPos"),U=this._get(e,"stepMonths"),Q=1!==K[0]||1!==K[1],G=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),X=this._getMinMaxDate(e,"min"),$=this._getMinMaxDate(e,"max"),Z=e.drawMonth-V,et=e.drawYear;if(0>Z&&(Z+=12,et--),$)for(t=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-K[0]*K[1]+1,$.getDate())),t=X&&X>t?X:t;this._daylightSavingAdjust(new Date(et,Z,1))>t;)Z--,0>Z&&(Z=11,et--);for(e.drawMonth=Z,e.drawYear=et,i=this._get(e,"prevText"),i=q?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z-U,1)),this._getFormatConfig(e)):i,s=this._canAdjustMonth(e,-1,et,Z)?""+i+"":J?"":""+i+"",n=this._get(e,"nextText"),n=q?this.formatDate(n,this._daylightSavingAdjust(new Date(et,Z+U,1)),this._getFormatConfig(e)):n,a=this._canAdjustMonth(e,1,et,Z)?""+n+"":J?"":""+n+"",o=this._get(e,"currentText"),r=this._get(e,"gotoCurrent")&&e.currentDay?G:R,o=q?this.formatDate(o,r,this._getFormatConfig(e)):o,h=e.inline?"":"",l=B?"
                  "+(Y?h:"")+(this._isInRange(e,r)?"":"")+(Y?"":h)+"
                  ":"",u=parseInt(this._get(e,"firstDay"),10),u=isNaN(u)?0:u,d=this._get(e,"showWeek"),c=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),f=this._get(e,"monthNames"),m=this._get(e,"monthNamesShort"),g=this._get(e,"beforeShowDay"),v=this._get(e,"showOtherMonths"),y=this._get(e,"selectOtherMonths"),b=this._getDefaultDate(e),_="",w=0;K[0]>w;w++){for(k="",this.maxRows=4,T=0;K[1]>T;T++){if(D=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),S=" ui-corner-all",M="",Q){if(M+="
                  "}for(M+="
                  "+(/all|left/.test(S)&&0===w?Y?a:s:"")+(/all|right/.test(S)&&0===w?Y?s:a:"")+this._generateMonthYearHeader(e,Z,et,X,$,w>0||T>0,f,m)+"
                  "+"",C=d?"":"",x=0;7>x;x++)N=(x+u)%7,C+="";for(M+=C+"",A=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,A)),P=(this._getFirstDayOfMonth(et,Z)-u+7)%7,I=Math.ceil((P+A)/7),H=Q?this.maxRows>I?this.maxRows:I:I,this.maxRows=H,z=this._daylightSavingAdjust(new Date(et,Z,1-P)),F=0;H>F;F++){for(M+="",E=d?"":"",x=0;7>x;x++)O=g?g.apply(e.input?e.input[0]:null,[z]):[!0,""],j=z.getMonth()!==Z,W=j&&!y||!O[0]||X&&X>z||$&&z>$,E+="",z.setDate(z.getDate()+1),z=this._daylightSavingAdjust(z);M+=E+""}Z++,Z>11&&(Z=0,et++),M+="
                  "+this._get(e,"weekHeader")+"=5?" class='ui-datepicker-week-end'":"")+">"+""+p[N]+"
                  "+this._get(e,"calculateWeek")(z)+""+(j&&!v?" ":W?""+z.getDate()+"":""+z.getDate()+"")+"
                  "+(Q?"
                  "+(K[0]>0&&T===K[1]-1?"
                  ":""):""),k+=M}_+=k}return _+=l,e._keyEvent=!1,_},_generateMonthYearHeader:function(e,t,i,s,n,a,o,r){var h,l,u,d,c,p,f,m,g=this._get(e,"changeMonth"),v=this._get(e,"changeYear"),y=this._get(e,"showMonthAfterYear"),b="
                  ",_="";if(a||!g)_+=""+o[t]+"";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,_+=""}if(y||(b+=_+(!a&&g&&v?"":" ")),!e.yearshtml)if(e.yearshtml="",a||!v)b+=""+i+"";else{for(d=this._get(e,"yearRange").split(":"),c=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?i+parseInt(e.substring(1),10):e.match(/[+\-].*/)?c+parseInt(e,10):parseInt(e,10);return isNaN(t)?c:t},f=p(d[0]),m=Math.max(f,p(d[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,e.yearshtml+="",b+=e.yearshtml,e.yearshtml=null}return b+=this._get(e,"yearSuffix"),y&&(b+=(!a&&g&&v?"":" ")+_),b+="
                  "},_adjustInstDate:function(e,t,i){var s=e.drawYear+("Y"===i?t:0),n=e.drawMonth+("M"===i?t:0),a=Math.min(e.selectedDay,this._getDaysInMonth(s,n))+("D"===i?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(s,n,a)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var i=this._getMinMaxDate(e,"min"),s=this._getMinMaxDate(e,"max"),n=i&&i>t?i:t;return s&&n>s?s:n},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,i,s){var n=this._getNumberOfMonths(e),a=this._daylightSavingAdjust(new Date(i,s+(0>t?t:n[0]*n[1]),1));return 0>t&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(e,a)},_isInRange:function(e,t){var i,s,n=this._getMinMaxDate(e,"min"),a=this._getMinMaxDate(e,"max"),o=null,r=null,h=this._get(e,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),o=parseInt(i[0],10),r=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(o+=s),i[1].match(/[+\-].*/)&&(r+=s)),(!n||t.getTime()>=n.getTime())&&(!a||t.getTime()<=a.getTime())&&(!o||t.getFullYear()>=o)&&(!r||r>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t="string"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,i,s){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var n=t?"object"==typeof t?t:this._daylightSavingAdjust(new Date(s,i,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),n,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e("#"+e.datepicker._mainDivId).length&&e("body").append(e.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof t||"isDisabled"!==t&&"getDate"!==t&&"widget"!==t?"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof t?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(i)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i))},e.datepicker=new n,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.11.4",e.datepicker,e.widget("ui.draggable",e.ui.mouse,{version:"1.11.4",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),"handle"===e&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var i=this.options;return this._blurActiveElement(t),this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=e(this);return e("
                  ").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var i=this.document[0];if(this.handleElement.is(t.target))try{i.activeElement&&"body"!==i.activeElement.nodeName.toLowerCase()&&e(i.activeElement).blur()}catch(s){}},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===e(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._normalizeRightBottom(),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(e){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:e.pageX-this.offset.left,top:e.pageY-this.offset.top}},_mouseDrag:function(t,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this.handleElement.addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.handleElement.removeClass("ui-draggable-handle")},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper),n=s?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options,a=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,e(a).width()-this.helperProportions.width-this.margins.left,(e(a).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0) +},_convertPositionTo:function(e,t){t||(t=this.position);var i="absolute"===e?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:t.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(e,t){var i,s,n,a,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.lefti[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a),"y"===o.axis&&(h=this.originalPageX),"x"===o.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i,s){var n=e.extend({},i,{item:s.element});s.sortables=[],e(s.options.connectToSortable).each(function(){var i=e(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",t,n))})},stop:function(t,i,s){var n=e.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,e.each(s.sortables,function(){var e=this;e.isOver?(e.isOver=0,s.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,n))})},drag:function(t,i,s){e.each(s.sortables,function(){var n=!1,a=this;a.positionAbs=s.positionAbs,a.helperProportions=s.helperProportions,a.offset.click=s.offset.click,a._intersectsWith(a.containerCache)&&(n=!0,e.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==a&&this._intersectsWith(this.containerCache)&&e.contains(a.element[0],this.element[0])&&(n=!1),n})),n?(a.isOver||(a.isOver=1,s._parent=i.helper.parent(),a.currentItem=i.helper.appendTo(a.element).data("ui-sortable-item",!0),a.options._helper=a.options.helper,a.options.helper=function(){return i.helper[0]},t.target=a.currentItem[0],a._mouseCapture(t,!0),a._mouseStart(t,!0,!0),a.offset.click.top=s.offset.click.top,a.offset.click.left=s.offset.click.left,a.offset.parent.left-=s.offset.parent.left-a.offset.parent.left,a.offset.parent.top-=s.offset.parent.top-a.offset.parent.top,s._trigger("toSortable",t),s.dropped=a.element,e.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,a.fromOutside=s),a.currentItem&&(a._mouseDrag(t),i.position=a.position)):a.isOver&&(a.isOver=0,a.cancelHelperRemoval=!0,a.options._revert=a.options.revert,a.options.revert=!1,a._trigger("out",t,a._uiHash(a)),a._mouseStop(t,!0),a.options.revert=a.options._revert,a.options.helper=a.options._helper,a.placeholder&&a.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(t),i.position=s._generatePosition(t,!0),s._trigger("fromSortable",t),s.dropped=!1,e.each(s.sortables,function(){this.refreshPositions()}))})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,i,s){var n=e("body"),a=s.options;n.css("cursor")&&(a._cursor=n.css("cursor")),n.css("cursor",a.cursor)},stop:function(t,i,s){var n=s.options;n._cursor&&e("body").css("cursor",n._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("opacity")&&(a._opacity=n.css("opacity")),n.css("opacity",a.opacity)},stop:function(t,i,s){var n=s.options;n._opacity&&e(i.helper).css("opacity",n._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(e,t,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,i,s){var n=s.options,a=!1,o=s.scrollParentNotHidden[0],r=s.document[0];o!==r&&"HTML"!==o.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+o.offsetHeight-t.pageY=0;c--)h=s.snapElements[c].left-s.margins.left,l=h+s.snapElements[c].width,u=s.snapElements[c].top-s.margins.top,d=u+s.snapElements[c].height,h-m>v||g>l+m||u-m>b||y>d+m||!e.contains(s.snapElements[c].item.ownerDocument,s.snapElements[c].item)?(s.snapElements[c].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(n=m>=Math.abs(u-b),a=m>=Math.abs(d-y),o=m>=Math.abs(h-v),r=m>=Math.abs(l-g),n&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||a||o||r,"outer"!==f.snapMode&&(n=m>=Math.abs(u-y),a=m>=Math.abs(d-b),o=m>=Math.abs(h-g),r=m>=Math.abs(l-v),n&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d-s.helperProportions.height,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[c].snapping&&(n||a||o||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=n||a||o||r||p)}}),e.ui.plugin.add("draggable","stack",{start:function(t,i,s){var n,a=s.options,o=e.makeArray(e(a.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});o.length&&(n=parseInt(e(o[0]).css("zIndex"),10)||0,e(o).each(function(t){e(this).css("zIndex",n+t)}),this.css("zIndex",n+o.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("zIndex")&&(a._zIndex=n.css("zIndex")),n.css("zIndex",a.zIndex)},stop:function(t,i,s){var n=s.options;n._zIndex&&e(i.helper).css("zIndex",n._zIndex)}}),e.ui.draggable,e.widget("ui.resizable",e.ui.mouse,{version:"1.11.4",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(e){return parseInt(e,10)||0},_isNumber:function(e){return!isNaN(parseInt(e,10))},_hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return t[s]>0?!0:(t[s]=1,n=t[s]>0,t[s]=0,n)},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(e("
                  ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=e(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
                  "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=e(this.handles[i]),this._on(this.handles[i],{mousedown:o._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var i,s,n,a=this.options,o=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),a.containment&&(i+=e(a.containment).scrollLeft()||0,s+=e(a.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:o.width(),height:o.height()},this.originalSize=this._helper?{width:o.outerWidth(),height:o.outerHeight()}:{width:o.width(),height:o.height()},this.sizeDiff={width:o.outerWidth()-o.width(),height:o.outerHeight()-o.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof a.aspectRatio?a.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===n?this.axis+"-resize":n),o.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var i,s,n=this.originalMousePosition,a=this.axis,o=t.pageX-n.left||0,r=t.pageY-n.top||0,h=this._change[a];return this._updatePrevProperties(),h?(i=h.apply(this,[t,o,r]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var e={};return this.position.top!==this.prevPosition.top&&(e.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(e.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(e.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(e.height=this.size.height+"px"),this.helper.css(e),e},_updateVirtualBoundaries:function(e){var t,i,s,n,a,o=this.options;a={minWidth:this._isNumber(o.minWidth)?o.minWidth:0,maxWidth:this._isNumber(o.maxWidth)?o.maxWidth:1/0,minHeight:this._isNumber(o.minHeight)?o.minHeight:0,maxHeight:this._isNumber(o.maxHeight)?o.maxHeight:1/0},(this._aspectRatio||e)&&(t=a.minHeight*this.aspectRatio,s=a.minWidth/this.aspectRatio,i=a.maxHeight*this.aspectRatio,n=a.maxWidth/this.aspectRatio,t>a.minWidth&&(a.minWidth=t),s>a.minHeight&&(a.minHeight=s),a.maxWidth>i&&(a.maxWidth=i),a.maxHeight>n&&(a.maxHeight=n)),this._vBoundaries=a},_updateCache:function(e){this.offset=this.helper.offset(),this._isNumber(e.left)&&(this.position.left=e.left),this._isNumber(e.top)&&(this.position.top=e.top),this._isNumber(e.height)&&(this.size.height=e.height),this._isNumber(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,i=this.size,s=this.axis;return this._isNumber(e.height)?e.width=e.height*this.aspectRatio:this._isNumber(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===s&&(e.left=t.left+(i.width-e.width),e.top=null),"nw"===s&&(e.top=t.top+(i.height-e.height),e.left=t.left+(i.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,i=this.axis,s=this._isNumber(e.width)&&t.maxWidth&&t.maxWidthe.width,o=this._isNumber(e.height)&&t.minHeight&&t.minHeight>e.height,r=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,l=/sw|nw|w/.test(i),u=/nw|ne|n/.test(i);return a&&(e.width=t.minWidth),o&&(e.height=t.minHeight),s&&(e.width=t.maxWidth),n&&(e.height=t.maxHeight),a&&l&&(e.left=r-t.minWidth),s&&l&&(e.left=r-t.maxWidth),o&&u&&(e.top=h-t.minHeight),n&&u&&(e.top=h-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_getPaddingPlusBorderDimensions:function(e){for(var t=0,i=[],s=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],n=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];4>t;t++)i[t]=parseInt(s[t],10)||0,i[t]+=parseInt(n[t],10)||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var e,t=0,i=this.helper||this.element;this._proportionallyResizeElements.length>t;t++)e=this._proportionallyResizeElements[t],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(e)),e.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
                  "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,i,s,n,a,o,r,h=e(this).resizable("instance"),l=h.options,u=h.element,d=l.containment,c=d instanceof e?d.get(0):/parent/.test(d)?u.parent().get(0):d;c&&(h.containerElement=e(c),/document/.test(d)||d===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(c),i=[],e(["Top","Right","Left","Bottom"]).each(function(e,s){i[e]=h._num(t.css("padding"+s))}),h.containerOffset=t.offset(),h.containerPosition=t.position(),h.containerSize={height:t.innerHeight()-i[3],width:t.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,a=h.containerSize.width,o=h._hasScroll(c,"left")?c.scrollWidth:a,r=h._hasScroll(c)?c.scrollHeight:n,h.parentData={element:c,left:s.left,top:s.top,width:o,height:r}))},resize:function(t){var i,s,n,a,o=e(this).resizable("instance"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,d={top:0,left:0},c=o.containerElement,p=!0;c[0]!==document&&/static/.test(c.css("position"))&&(d=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-d.left),u&&(o.size.height=o.size.width/o.aspectRatio,p=!1),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio,p=!1),o.position.top=o._helper?h.top:0),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a?(o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top):(o.offset.left=o.element.offset().left,o.offset.top=o.element.offset().top),i=Math.abs(o.sizeDiff.width+(o._helper?o.offset.left-d.left:o.offset.left-h.left)),s=Math.abs(o.sizeDiff.height+(o._helper?o.offset.top-d.top:o.offset.top-h.top)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio,p=!1)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio,p=!1)),p||(o.position.left=o.prevPosition.left,o.position.top=o.prevPosition.top,o.size.width=o.prevSize.width,o.size.height=o.prevSize.height)},stop:function(){var t=e(this).resizable("instance"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).resizable("instance"),i=t.options;e(i.alsoResize).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})},resize:function(t,i){var s=e(this).resizable("instance"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0};e(n.alsoResize).each(function(){var t=e(this),s=e(this).data("ui-resizable-alsoresize"),n={},a=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(a,function(e,t){var i=(s[t]||0)+(r[t]||0);i&&i>=0&&(n[t]=i||null)}),t.css(n)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t,i=e(this).resizable("instance"),s=i.options,n=i.size,a=i.originalSize,o=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,u=h[1]||1,d=Math.round((n.width-a.width)/l)*l,c=Math.round((n.height-a.height)/u)*u,p=a.width+d,f=a.height+c,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,v=s.minWidth&&s.minWidth>p,y=s.minHeight&&s.minHeight>f;s.grid=h,v&&(p+=l),y&&(f+=u),m&&(p-=l),g&&(f-=u),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=o.top-c):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=o.left-d):((0>=f-u||0>=p-l)&&(t=i._getPaddingPlusBorderDimensions(this)),f-u>0?(i.size.height=f,i.position.top=o.top-c):(f=u-t.height,i.size.height=f,i.position.top=o.top+a.height-f),p-l>0?(i.size.width=p,i.position.left=o.left-d):(p=l-t.width,i.size.width=p,i.position.left=o.left+a.width-p))}}),e.ui.resizable,e.widget("ui.dialog",{version:"1.11.4",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"Close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._untrackInstance(),this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i,s=this;if(this._isOpen&&this._trigger("beforeClose",t)!==!1){if(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),!this.opener.filter(":focusable").focus().length)try{i=this.document[0].activeElement,i&&"body"!==i.nodeName.toLowerCase()&&e(i).blur()}catch(n){}this._hide(this.uiDialog,this.options.hide,function(){s._trigger("close",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,i){var s=!1,n=this.uiDialog.siblings(".ui-front:visible").map(function(){return+e(this).css("z-index")}).get(),a=Math.max.apply(null,n);return a>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",a+1),s=!0),s&&!i&&this._trigger("focus",t),s},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"),void 0)},_focusTabbable:function(){var e=this._focusedElement;e||(e=this.element.find("[autofocus]")),e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("
                  ").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),void 0; +if(t.keyCode===e.ui.keyCode.TAB&&!t.isDefaultPrevented()){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");t.target!==n[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==s[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){n.focus()}),t.preventDefault()):(this._delay(function(){s.focus()}),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("
                  ").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html(" "),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("
                  ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("
                  ").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),void 0):(e.each(i,function(i,s){var n,a;s=e.isFunction(s)?{click:s,text:i}:s,s=e.extend({type:"button"},s),n=s.click,s.click=function(){n.apply(t.element[0],arguments)},a={icons:s.icons,text:s.showText},delete s.icons,delete s.showText,e("",s).button(a).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,t(n))},drag:function(e,s){i._trigger("drag",e,t(s))},stop:function(n,a){var o=a.offset.left-i.document.scrollLeft(),r=a.offset.top-i.document.scrollTop();s.position={my:"left top",at:"left"+(o>=0?"+":"")+o+" "+"top"+(r>=0?"+":"")+r,of:i.window},e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,t(a))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,s=this.options,n=s.resizable,a=this.uiDialog.css("position"),o="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:o,start:function(s,n){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,t(n))},resize:function(e,s){i._trigger("resize",e,t(s))},stop:function(n,a){var o=i.uiDialog.offset(),r=o.left-i.document.scrollLeft(),h=o.top-i.document.scrollTop();s.height=i.uiDialog.height(),s.width=i.uiDialog.width(),s.position={my:"left top",at:"left"+(r>=0?"+":"")+r+" "+"top"+(h>=0?"+":"")+h,of:i.window},e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,t(a))}}).css("position",a)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._makeFocusTarget(),this._focusedElement=e(t.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var t=this._trackingInstances(),i=e.inArray(this,t);-1!==i&&t.splice(i,1)},_trackingInstances:function(){var e=this.document.data("ui-dialog-instances");return e||(e=[],this.document.data("ui-dialog-instances",e)),e},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,n={};e.each(t,function(e,t){i._setOption(e,t),e in i.sizeRelatedOptions&&(s=!0),e in i.resizableRelatedOptions&&(n[e]=t)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(e,t){var i,s,n=this.uiDialog;"dialogClass"===e&&n.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=n.is(":data(ui-draggable)"),i&&!t&&n.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(s=n.is(":data(ui-resizable)"),s&&!t&&n.resizable("destroy"),s&&"string"==typeof t&&n.resizable("option","handles",t),s||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),e=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),t=Math.max(0,s.minHeight-e),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-e):"none","auto"===s.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("
                  ").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=!0;this._delay(function(){t=!1}),this.document.data("ui-dialog-overlays")||this._on(this.document,{focusin:function(e){t||this._allowInteraction(e)||(e.preventDefault(),this._trackingInstances()[0]._focusTabbable())}}),this.overlay=e("
                  ").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1)}},_destroyOverlay:function(){if(this.options.modal&&this.overlay){var e=this.document.data("ui-dialog-overlays")-1;e?this.document.data("ui-dialog-overlays",e):this.document.unbind("focusin").removeData("ui-dialog-overlays"),this.overlay.remove(),this.overlay=null}}}),e.widget("ui.droppable",{version:"1.11.4",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(s)?s:function(e){return e.is(s)},this.proportions=function(){return arguments.length?(t=arguments[0],void 0):t?t:t={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this.element.addClass("ui-droppable")},_addToManager:function(t){e.ui.ddmanager.droppables[t]=e.ui.ddmanager.droppables[t]||[],e.ui.ddmanager.droppables[t].push(this)},_splice:function(e){for(var t=0;e.length>t;t++)e[t]===this&&e.splice(t,1)},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];this._splice(t),this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){if("accept"===t)this.accept=e.isFunction(i)?i:function(e){return e.is(i)};else if("scope"===t){var s=e.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(t,i)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=e(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(i,{offset:i.element.offset()}),i.options.tolerance,t)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(){function e(e,t,i){return e>=t&&t+i>e}return function(t,i,s,n){if(!i.offset)return!1;var a=(t.positionAbs||t.position.absolute).left+t.margins.left,o=(t.positionAbs||t.position.absolute).top+t.margins.top,r=a+t.helperProportions.width,h=o+t.helperProportions.height,l=i.offset.left,u=i.offset.top,d=l+i.proportions().width,c=u+i.proportions().height;switch(s){case"fit":return a>=l&&d>=r&&o>=u&&c>=h;case"intersect":return a+t.helperProportions.width/2>l&&d>r-t.helperProportions.width/2&&o+t.helperProportions.height/2>u&&c>h-t.helperProportions.height/2;case"pointer":return e(n.pageY,u,i.proportions().height)&&e(n.pageX,l,i.proportions().width);case"touch":return(o>=u&&c>=o||h>=u&&c>=h||u>o&&h>c)&&(a>=l&&d>=a||r>=l&&d>=r||l>a&&r>d);default:return!1}}}(),e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue e}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance,i),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return e(this).droppable("instance").options.scope===n}),a.length&&(s=e(a[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}},e.ui.droppable;var y="ui-effects-",b=e;e.effects={effect:{}},function(e,t){function i(e,t,i){var s=d[t.type]||{};return null==e?i||!t.def?null:t.def:(e=s.floor?~~e:parseFloat(e),isNaN(e)?t.def:s.mod?(e+s.mod)%s.mod:0>e?0:e>s.max?s.max:e)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(e,a){var o,r=a.re.exec(i),h=r&&a.parse(r),l=a.space||"rgba";return h?(o=s[l](h),s[u[l].cache]=o[u[l].cache],n=s._rgba=o._rgba,!1):t}),n.length?("0,0,0,0"===n.join()&&e.extend(n,a.transparent),s):a[i]}function n(e,t,i){return i=(i+1)%1,1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+6*(t-e)*(2/3-i):e}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[2.55*e[1],2.55*e[2],2.55*e[3],e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],l=e.Color=function(t,i,s,n){return new e.Color.fn.parse(t,i,s,n)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},d={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},c=l.support={},p=e("

                  ")[0],f=e.each;p.style.cssText="background-color:rgba(1,1,1,.5)",c.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),l.fn=e.extend(l.prototype,{parse:function(n,o,r,h){if(n===t)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=e(n).css(o),o=t);var d=this,c=e.type(n),p=this._rgba=[];return o!==t&&(n=[n,o,r,h],c="array"),"string"===c?this.parse(s(n)||a._default):"array"===c?(f(u.rgba.props,function(e,t){p[t.idx]=i(n[t.idx],t)}),this):"object"===c?(n instanceof l?f(u,function(e,t){n[t.cache]&&(d[t.cache]=n[t.cache].slice())}):f(u,function(t,s){var a=s.cache;f(s.props,function(e,t){if(!d[a]&&s.to){if("alpha"===e||null==n[e])return;d[a]=s.to(d._rgba)}d[a][t.idx]=i(n[e],t,!0)}),d[a]&&0>e.inArray(null,d[a].slice(0,3))&&(d[a][3]=1,s.from&&(d._rgba=s.from(d[a])))}),this):t},is:function(e){var i=l(e),s=!0,n=this;return f(u,function(e,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(e,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:t})),s}),s},_space:function(){var e=[],t=this;return f(u,function(i,s){t[s.cache]&&e.push(i)}),e.pop()},transition:function(e,t){var s=l(e),n=s._space(),a=u[n],o=0===this.alpha()?l("transparent"):this,r=o[a.cache]||a.to(o._rgba),h=r.slice();return s=s[a.cache],f(a.props,function(e,n){var a=n.idx,o=r[a],l=s[a],u=d[n.type]||{};null!==l&&(null===o?h[a]=l:(u.mod&&(l-o>u.mod/2?o+=u.mod:o-l>u.mod/2&&(o-=u.mod)),h[a]=i((l-o)*t+o,n)))}),this[n](h)},blend:function(t){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(t)._rgba;return l(e.map(i,function(e,t){return(1-s)*n[t]+s*e}))},toRgbaString:function(){var t="rgba(",i=e.map(this._rgba,function(e,t){return null==e?t>2?1:0:e});return 1===i[3]&&(i.pop(),t="rgb("),t+i.join()+")"},toHslaString:function(){var t="hsla(",i=e.map(this.hsla(),function(e,t){return null==e&&(e=t>2?1:0),t&&3>t&&(e=Math.round(100*e)+"%"),e});return 1===i[3]&&(i.pop(),t="hsl("),t+i.join()+")"},toHexString:function(t){var i=this._rgba.slice(),s=i.pop();return t&&i.push(~~(255*s)),"#"+e.map(i,function(e){return e=(e||0).toString(16),1===e.length?"0"+e:e}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,u.hsla.to=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t,i,s=e[0]/255,n=e[1]/255,a=e[2]/255,o=e[3],r=Math.max(s,n,a),h=Math.min(s,n,a),l=r-h,u=r+h,d=.5*u;return t=h===r?0:s===r?60*(n-a)/l+360:n===r?60*(a-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=d?l/u:l/(2-u),[Math.round(t)%360,i,d,null==o?1:o]},u.hsla.from=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t=e[0]/360,i=e[1],s=e[2],a=e[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,t+1/3)),Math.round(255*n(r,o,t)),Math.round(255*n(r,o,t-1/3)),a]},f(u,function(s,n){var a=n.props,o=n.cache,h=n.to,u=n.from;l.fn[s]=function(s){if(h&&!this[o]&&(this[o]=h(this._rgba)),s===t)return this[o].slice();var n,r=e.type(s),d="array"===r||"object"===r?s:arguments,c=this[o].slice();return f(a,function(e,t){var s=d["object"===r?e:t.idx];null==s&&(s=c[t.idx]),c[t.idx]=i(s,t)}),u?(n=l(u(c)),n[o]=c,n):l(c)},f(a,function(t,i){l.fn[t]||(l.fn[t]=function(n){var a,o=e.type(n),h="alpha"===t?this._hsla?"hsla":"rgba":s,l=this[h](),u=l[i.idx];return"undefined"===o?u:("function"===o&&(n=n.call(this,u),o=e.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=u+parseFloat(a[2])*("+"===a[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(t){var i=t.split(" ");f(i,function(t,i){e.cssHooks[i]={set:function(t,n){var a,o,r="";if("transparent"!==n&&("string"!==e.type(n)||(a=s(n)))){if(n=l(a||n),!c.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?t.parentNode:t;(""===r||"transparent"===r)&&o&&o.style;)try{r=e.css(o,"backgroundColor"),o=o.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{t.style[i]=n}catch(h){}}},e.fx.step[i]=function(t){t.colorInit||(t.start=l(t.elem,i),t.end=l(t.end),t.colorInit=!0),e.cssHooks[i].set(t.elem,t.start.transition(t.end,t.pos))}})},l.hook(o),e.cssHooks.borderColor={expand:function(e){var t={};return f(["Top","Right","Bottom","Left"],function(i,s){t["border"+s+"Color"]=e}),t}},a=e.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(b),function(){function t(t){var i,s,n=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[e.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function i(t,i){var s,a,o={};for(s in i)a=i[s],t[s]!==a&&(n[s]||(e.fx.step[s]||!isNaN(parseFloat(a)))&&(o[s]=a));return o}var s=["add","remove","toggle"],n={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,i){e.fx.step[i]=function(e){("none"!==e.end&&!e.setAttr||1===e.pos&&!e.setAttr)&&(b.style(e.elem,i,e.end),e.setAttr=!0)}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e.effects.animateClass=function(n,a,o,r){var h=e.speed(a,o,r);return this.queue(function(){var a,o=e(this),r=o.attr("class")||"",l=h.children?o.find("*").addBack():o;l=l.map(function(){var i=e(this);return{el:i,start:t(this)}}),a=function(){e.each(s,function(e,t){n[t]&&o[t+"Class"](n[t])})},a(),l=l.map(function(){return this.end=t(this.el[0]),this.diff=i(this.start,this.end),this}),o.attr("class",r),l=l.map(function(){var t=this,i=e.Deferred(),s=e.extend({},h,{queue:!1,complete:function(){i.resolve(t)}});return this.el.animate(this.diff,s),i.promise()}),e.when.apply(e,l.get()).done(function(){a(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),h.complete.call(o[0])})})},e.fn.extend({addClass:function(t){return function(i,s,n,a){return s?e.effects.animateClass.call(this,{add:i},s,n,a):t.apply(this,arguments)}}(e.fn.addClass),removeClass:function(t){return function(i,s,n,a){return arguments.length>1?e.effects.animateClass.call(this,{remove:i},s,n,a):t.apply(this,arguments)}}(e.fn.removeClass),toggleClass:function(t){return function(i,s,n,a,o){return"boolean"==typeof s||void 0===s?n?e.effects.animateClass.call(this,s?{add:i}:{remove:i},n,a,o):t.apply(this,arguments):e.effects.animateClass.call(this,{toggle:i},s,n,a)}}(e.fn.toggleClass),switchClass:function(t,i,s,n,a){return e.effects.animateClass.call(this,{add:i,remove:t},s,n,a)}})}(),function(){function t(t,i,s,n){return e.isPlainObject(t)&&(i=t,t=t.effect),t={effect:t},null==i&&(i={}),e.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||e.fx.speeds[i])&&(n=s,s=i,i={}),e.isFunction(s)&&(n=s,s=null),i&&e.extend(t,i),s=s||i.duration,t.duration=e.fx.off?0:"number"==typeof s?s:s in e.fx.speeds?e.fx.speeds[s]:e.fx.speeds._default,t.complete=n||i.complete,t}function i(t){return!t||"number"==typeof t||e.fx.speeds[t]?!0:"string"!=typeof t||e.effects.effect[t]?e.isFunction(t)?!0:"object"!=typeof t||t.effect?!1:!0:!0}e.extend(e.effects,{version:"1.11.4",save:function(e,t){for(var i=0;t.length>i;i++)null!==t[i]&&e.data(y+t[i],e[0].style[t[i]])},restore:function(e,t){var i,s;for(s=0;t.length>s;s++)null!==t[s]&&(i=e.data(y+t[s]),void 0===i&&(i=""),e.css(t[s],i))},setMode:function(e,t){return"toggle"===t&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var i,s;switch(e[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=e[0]/t.height}switch(e[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=e[1]/t.width}return{x:s,y:i}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var i={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},s=e("

                  ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:t.width(),height:t.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return t.wrap(s),(t[0]===a||e.contains(t[0],a))&&e(a).focus(),s=t.parent(),"static"===t.css("position")?(s.css({position:"relative"}),t.css({position:"relative"})):(e.extend(i,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,s){i[s]=t.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(n),s.css(i).show()},removeWrapper:function(t){var i=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===i||e.contains(t[0],i))&&e(i).focus()),t},setTransition:function(t,i,s,n){return n=n||{},e.each(i,function(e,i){var a=t.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),e.fn.extend({effect:function(){function i(t){function i(){e.isFunction(a)&&a.call(n[0]),e.isFunction(t)&&t()}var n=e(this),a=s.complete,r=s.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),i()):o.call(n[0],s,i)}var s=t.apply(this,arguments),n=s.mode,a=s.queue,o=e.effects.effect[s.effect];return e.fx.off||!o?n?this[n](s.duration,s.complete):this.each(function(){s.complete&&s.complete.call(this)}):a===!1?this.each(i):this.queue(a||"fx",i)},show:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="show",this.effect.call(this,n)}}(e.fn.show),hide:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="hide",this.effect.call(this,n)}}(e.fn.hide),toggle:function(e){return function(s){if(i(s)||"boolean"==typeof s)return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)}}(e.fn.toggle),cssUnit:function(t){var i=this.css(t),s=[];return e.each(["em","px","%","pt"],function(e,t){i.indexOf(t)>0&&(s=[parseFloat(i),t])}),s}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,i){t[i]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return 0===e||1===e?e:-Math.pow(2,8*(e-1))*Math.sin((80*(e-1)-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){for(var t,i=4;((t=Math.pow(2,--i))-1)/11>e;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*t-2)/22-e,2)}}),e.each(t,function(t,i){e.easing["easeIn"+t]=i,e.easing["easeOut"+t]=function(e){return 1-i(1-e)},e.easing["easeInOut"+t]=function(e){return.5>e?i(2*e)/2:1-i(-2*e+2)/2}})}(),e.effects,e.effects.effect.blind=function(t,i){var s,n,a,o=e(this),r=/up|down|vertical/,h=/up|left|vertical|horizontal/,l=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(o,t.mode||"hide"),d=t.direction||"up",c=r.test(d),p=c?"height":"width",f=c?"top":"left",m=h.test(d),g={},v="show"===u;o.parent().is(".ui-effects-wrapper")?e.effects.save(o.parent(),l):e.effects.save(o,l),o.show(),s=e.effects.createWrapper(o).css({overflow:"hidden"}),n=s[p](),a=parseFloat(s.css(f))||0,g[p]=v?n:0,m||(o.css(c?"bottom":"right",0).css(c?"top":"left","auto").css({position:"absolute"}),g[f]=v?a:n+a),v&&(s.css(p,0),m||s.css(f,a+n)),s.animate(g,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){"hide"===u&&o.hide(),e.effects.restore(o,l),e.effects.removeWrapper(o),i()}})},e.effects.effect.bounce=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(o,t.mode||"effect"),l="hide"===h,u="show"===h,d=t.direction||"up",c=t.distance,p=t.times||5,f=2*p+(u||l?1:0),m=t.duration/f,g=t.easing,v="up"===d||"down"===d?"top":"left",y="up"===d||"left"===d,b=o.queue(),_=b.length;for((u||l)&&r.push("opacity"),e.effects.save(o,r),o.show(),e.effects.createWrapper(o),c||(c=o["top"===v?"outerHeight":"outerWidth"]()/3),u&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,y?2*-c:2*c).animate(a,m,g)),l&&(c/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(y?"-=":"+=")+c,o.animate(n,m,g).animate(a,m,g),c=l?2*c:c/2;l&&(n={opacity:0},n[v]=(y?"-=":"+=")+c,o.animate(n,m,g)),o.queue(function(){l&&o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}),_>1&&b.splice.apply(b,[1,0].concat(b.splice(_,f+1))),o.dequeue()},e.effects.effect.clip=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(o,t.mode||"hide"),l="show"===h,u=t.direction||"vertical",d="vertical"===u,c=d?"height":"width",p=d?"top":"left",f={};e.effects.save(o,r),o.show(),s=e.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[c](),l&&(n.css(c,0),n.css(p,a/2)),f[c]=l?a:0,f[p]=l?0:a/2,n.animate(f,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){l||o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}})},e.effects.effect.drop=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","opacity","height","width"],o=e.effects.setMode(n,t.mode||"hide"),r="show"===o,h=t.direction||"left",l="up"===h||"down"===h?"top":"left",u="up"===h||"left"===h?"pos":"neg",d={opacity:r?1:0};e.effects.save(n,a),n.show(),e.effects.createWrapper(n),s=t.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(l,"pos"===u?-s:s),d[l]=(r?"pos"===u?"+=":"-=":"pos"===u?"-=":"+=")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.explode=function(t,i){function s(){b.push(this),b.length===d*c&&n()}function n(){p.css({visibility:"visible"}),e(b).remove(),m||p.hide(),i()}var a,o,r,h,l,u,d=t.pieces?Math.round(Math.sqrt(t.pieces)):3,c=d,p=e(this),f=e.effects.setMode(p,t.mode||"hide"),m="show"===f,g=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/c),y=Math.ceil(p.outerHeight()/d),b=[];for(a=0;d>a;a++)for(h=g.top+a*y,u=a-(d-1)/2,o=0;c>o;o++)r=g.left+o*v,l=o-(c-1)/2,p.clone().appendTo("body").wrap("
                  ").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*y}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:y,left:r+(m?l*v:0),top:h+(m?u*y:0),opacity:m?0:1}).animate({left:r+(m?0:l*v),top:h+(m?0:u*y),opacity:m?1:0},t.duration||500,t.easing,s)},e.effects.effect.fade=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:t.duration,easing:t.easing,complete:i})},e.effects.effect.fold=function(t,i){var s,n,a=e(this),o=["position","top","bottom","left","right","height","width"],r=e.effects.setMode(a,t.mode||"hide"),h="show"===r,l="hide"===r,u=t.size||15,d=/([0-9]+)%/.exec(u),c=!!t.horizFirst,p=h!==c,f=p?["width","height"]:["height","width"],m=t.duration/2,g={},v={};e.effects.save(a,o),a.show(),s=e.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],d&&(u=parseInt(d[1],10)/100*n[l?0:1]),h&&s.css(c?{height:0,width:u}:{height:u,width:0}),g[f[0]]=h?n[0]:u,v[f[1]]=h?n[1]:0,s.animate(g,m,t.easing).animate(v,m,t.easing,function(){l&&a.hide(),e.effects.restore(a,o),e.effects.removeWrapper(a),i()})},e.effects.effect.highlight=function(t,i){var s=e(this),n=["backgroundImage","backgroundColor","opacity"],a=e.effects.setMode(s,t.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),e.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===a&&s.hide(),e.effects.restore(s,n),i()}})},e.effects.effect.size=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],h=["position","top","bottom","left","right","overflow","opacity"],l=["width","height","overflow"],u=["fontSize"],d=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],c=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),f=t.restore||"effect"!==p,m=t.scale||"both",g=t.origin||["middle","center"],v=o.css("position"),y=f?r:h,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===t.mode&&"show"===p?(o.from=t.to||b,o.to=t.from||s):(o.from=t.from||("show"===p?b:s),o.to=t.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===m||"both"===m)&&(a.from.y!==a.to.y&&(y=y.concat(d),o.from=e.effects.setTransition(o,d,a.from.y,o.from),o.to=e.effects.setTransition(o,d,a.to.y,o.to)),a.from.x!==a.to.x&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,a.from.x,o.from),o.to=e.effects.setTransition(o,c,a.to.x,o.to))),("content"===m||"both"===m)&&a.from.y!==a.to.y&&(y=y.concat(u).concat(l),o.from=e.effects.setTransition(o,u,a.from.y,o.from),o.to=e.effects.setTransition(o,u,a.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),g&&(n=e.effects.getBaseline(g,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===m||"both"===m)&&(d=d.concat(["marginTop","marginBottom"]).concat(u),c=c.concat(["marginLeft","marginRight"]),l=r.concat(d).concat(c),o.find("*[width]").each(function(){var i=e(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()}; +f&&e.effects.save(i,l),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=e.effects.setTransition(i,d,a.from.y,i.from),i.to=e.effects.setTransition(i,d,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=e.effects.setTransition(i,c,a.from.x,i.from),i.to=e.effects.setTransition(i,c,a.to.x,i.to)),i.css(i.from),i.animate(i.to,t.duration,t.easing,function(){f&&e.effects.restore(i,l)})})),o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),e.effects.restore(o,y),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,i){var s=parseInt(i,10),n=e?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),e.effects.removeWrapper(o),i()}})},e.effects.effect.scale=function(t,i){var s=e(this),n=e.extend(!0,{},t),a=e.effects.setMode(s,t.mode||"effect"),o=parseInt(t.percent,10)||(0===parseInt(t.percent,10)?0:"hide"===a?0:100),r=t.direction||"both",h=t.origin,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},u={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=h||["middle","center"],n.restore=!0),n.from=t.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:l),n.to={height:l.height*u.y,width:l.width*u.x,outerHeight:l.outerHeight*u.y,outerWidth:l.outerWidth*u.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},e.effects.effect.puff=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||"hide"),a="hide"===n,o=parseInt(t.percent,10)||150,r=o/100,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?h:{height:h.height*r,width:h.width*r,outerHeight:h.outerHeight*r,outerWidth:h.outerWidth*r}}),s.effect(t)},e.effects.effect.pulsate=function(t,i){var s,n=e(this),a=e.effects.setMode(n,t.mode||"show"),o="show"===a,r="hide"===a,h=o||"hide"===a,l=2*(t.times||5)+(h?1:0),u=t.duration/l,d=0,c=n.queue(),p=c.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),d=1),s=1;l>s;s++)n.animate({opacity:d},u,t.easing),d=1-d;n.animate({opacity:d},u,t.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&c.splice.apply(c,[1,0].concat(c.splice(p,l+1))),n.dequeue()},e.effects.effect.shake=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","height","width"],o=e.effects.setMode(n,t.mode||"effect"),r=t.direction||"left",h=t.distance||20,l=t.times||3,u=2*l+1,d=Math.round(t.duration/u),c="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},m={},g={},v=n.queue(),y=v.length;for(e.effects.save(n,a),n.show(),e.effects.createWrapper(n),f[c]=(p?"-=":"+=")+h,m[c]=(p?"+=":"-=")+2*h,g[c]=(p?"-=":"+=")+2*h,n.animate(f,d,t.easing),s=1;l>s;s++)n.animate(m,d,t.easing).animate(g,d,t.easing);n.animate(m,d,t.easing).animate(f,d/2,t.easing).queue(function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}),y>1&&v.splice.apply(v,[1,0].concat(v.splice(y,u+1))),n.dequeue()},e.effects.effect.slide=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","width","height"],o=e.effects.setMode(n,t.mode||"show"),r="show"===o,h=t.direction||"left",l="up"===h||"down"===h?"top":"left",u="up"===h||"left"===h,d={};e.effects.save(n,a),n.show(),s=t.distance||n["top"===l?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(l,u?isNaN(s)?"-"+s:-s:s),d[l]=(r?u?"+=":"-=":u?"-=":"+=")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.transfer=function(t,i){var s=e(this),n=e(t.to),a="fixed"===n.css("position"),o=e("body"),r=a?o.scrollTop():0,h=a?o.scrollLeft():0,l=n.offset(),u={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},d=s.offset(),c=e("
                  ").appendTo(document.body).addClass(t.className).css({top:d.top-r,left:d.left-h,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(u,t.duration,t.easing,function(){c.remove(),i()})},e.widget("ui.progressbar",{version:"1.11.4",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=e("
                  ").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return void 0===e?this.options.value:(this.options.value=this._constrainedValue(e),this._refreshValue(),void 0)},_constrainedValue:function(e){return void 0===e&&(e=this.options.value),this.indeterminate=e===!1,"number"!=typeof e&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){"max"===e&&(t=Math.max(this.min,t)),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass("ui-corner-right",t===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=e("
                  ").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}}),e.widget("ui.selectable",e.ui.mouse,{version:"1.11.4",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),i=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
                  ")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger("start",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=e.data(this,"selectable-item");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,"selectable-item");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",t,{selecting:n.element}):i._trigger("unselecting",t,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):"fit"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",t,{unselected:s.element})}),e(".ui-selecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",t,{selected:s.element})}),this._trigger("stop",t),this.helper.remove(),!1}}),e.widget("ui.selectmenu",{version:"1.11.4",defaultElement:"",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},i=this.element;return e.each(["min","max","step"],function(e,s){var n=i.attr(s);void 0!==n&&n.length&&(t[s]=n)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e),void 0)},mousewheel:function(e,t){if(t){if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()}},"mousedown .ui-spinner-button":function(t){function i(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(t)!==!1&&this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){return e(t.currentTarget).hasClass("ui-state-active")?this._start(t)===!1?!1:(this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*e.height())&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var i=this.options,s=e.ui.keyCode;switch(t.keyCode){case s.UP:return this._repeat(null,1,t),!0;case s.DOWN:return this._repeat(null,-1,t),!0;case s.PAGE_UP:return this._repeat(null,i.page,t),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,t),!0}return!1},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""+""+""+""+""},_start:function(e){return this.spinning||this._trigger("start",e)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(e,t,i){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,i)},e),this._spin(t*this.options.step,i)},_spin:function(e,t){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+e*this._increment(this.counter)),this.spinning&&this._trigger("spin",t,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(t){var i=this.options.incremental;return i?e.isFunction(i)?i(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return null!==this.options.min&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=""+e,i=t.indexOf(".");return-1===i?0:t.length-i-1},_adjustValue:function(e){var t,i,s=this.options;return t=null!==s.min?s.min:0,i=e-t,i=Math.round(i/s.step)*s.step,e=t+i,e=parseFloat(e.toFixed(this._precision())),null!==s.max&&e>s.max?s.max:null!==s.min&&s.min>e?s.min:e},_stop:function(e){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e))},_setOption:function(e,t){if("culture"===e||"numberFormat"===e){var i=this._parse(this.element.val());return this.options[e]=t,this.element.val(this._format(i)),void 0}("max"===e||"min"===e||"step"===e)&&"string"==typeof t&&(t=this._parse(t)),"icons"===e&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(t.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(t.down)),this._super(e,t),"disabled"===e&&(this.widget().toggleClass("ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable"))},_setOptions:h(function(e){this._super(e)}),_parse:function(e){return"string"==typeof e&&""!==e&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),""===e||isNaN(e)?null:e},_format:function(e){return""===e?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var e=this.value();return null===e?!1:e===this._adjustValue(e)},_value:function(e,t){var i;""!==e&&(i=this._parse(e),null!==i&&(t||(i=this._adjustValue(i)),e=this._format(i))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:h(function(e){this._stepUp(e)}),_stepUp:function(e){this._start()&&(this._spin((e||1)*this.options.step),this._stop())},stepDown:h(function(e){this._stepDown(e)}),_stepDown:function(e){this._start()&&(this._spin((e||1)*-this.options.step),this._stop())},pageUp:h(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:h(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){return arguments.length?(h(this._value).call(this,e),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),e.widget("ui.tabs",{version:"1.11.4",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var e=/#.*$/;return function(t){var i,s;t=t.cloneNode(!1),i=t.href.replace(e,""),s=location.href.replace(e,"");try{i=decodeURIComponent(i)}catch(n){}try{s=decodeURIComponent(s)}catch(n){}return t.hash.length>1&&i===s}}(),_create:function(){var t=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible),this._processTabs(),i.active=this._initialActive(),e.isArray(i.disabled)&&(i.disabled=e.unique(i.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):e(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var t=this.options.active,i=this.options.collapsible,s=location.hash.substring(1);return null===t&&(s&&this.tabs.each(function(i,n){return e(n).attr("aria-controls")===s?(t=i,!1):void 0}),null===t&&(t=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===t||-1===t)&&(t=this.tabs.length?0:!1)),t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),-1===t&&(t=i?!1:0)),!i&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var i=e(this.document[0].activeElement).closest("li"),s=this.tabs.index(i),n=!0;if(!this._handlePageNav(t)){switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:s++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:n=!1,s--;break;case e.ui.keyCode.END:s=this.anchors.length-1;break;case e.ui.keyCode.HOME:s=0;break;case e.ui.keyCode.SPACE:return t.preventDefault(),clearTimeout(this.activating),this._activate(s),void 0;case e.ui.keyCode.ENTER:return t.preventDefault(),clearTimeout(this.activating),this._activate(s===this.options.active?!1:s),void 0;default:return}t.preventDefault(),clearTimeout(this.activating),s=this._focusNextTab(s,n),t.ctrlKey||t.metaKey||(i.attr("aria-selected","false"),this.tabs.eq(s).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",s)},this.delay))}},_panelKeydown:function(t){this._handlePageNav(t)||t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){return t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(t,i){function s(){return t>n&&(t=0),0>t&&(t=n),t}for(var n=this.tabs.length-1;-1!==e.inArray(s(),this.options.disabled);)t=i?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):"disabled"===e?(this._setupDisabled(t),void 0):(this._super(e,t),"collapsible"===e&&(this.element.toggleClass("ui-tabs-collapsible",t),t||this.options.active!==!1||this._activate(0)),"event"===e&&this._setupEvents(t),"heightStyle"===e&&this._setupHeightStyle(t),void 0)},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,i=this.tablist.children(":has(a[href])");t.disabled=e.map(i.filter(".ui-state-disabled"),function(e){return i.index(e)}),this._processTabs(),t.active!==!1&&this.anchors.length?this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=e()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this,i=this.tabs,s=this.anchors,n=this.panels; +this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist").delegate("> li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(i,s){var n,a,o,r=e(s).uniqueId().attr("id"),h=e(s).closest("li"),l=h.attr("aria-controls");t._isLocal(s)?(n=s.hash,o=n.substring(1),a=t.element.find(t._sanitizeSelector(n))):(o=h.attr("aria-controls")||e({}).uniqueId()[0].id,n="#"+o,a=t.element.find(n),a.length||(a=t._createPanel(o),a.insertAfter(t.panels[i-1]||t.tablist)),a.attr("aria-live","polite")),a.length&&(t.panels=t.panels.add(a)),l&&h.data("ui-tabs-aria-controls",l),h.attr({"aria-controls":o,"aria-labelledby":r}),a.attr("aria-labelledby",r)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel"),i&&(this._off(i.not(this.tabs)),this._off(s.not(this.anchors)),this._off(n.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("
                  ").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var i,s=0;i=this.tabs[s];s++)t===!0||-1!==e.inArray(s,t)?e(i).addClass("ui-state-disabled").attr("aria-disabled","true"):e(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var i={};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(e){e.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var i,s=this.element.parent();"fill"===t?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=e(this),s=t.css("position");"absolute"!==s&&"fixed"!==s&&(i-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,i-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===t&&(i=0,this.panels.each(function(){i=Math.max(i,e(this).height("").height())}).height(i))},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?e():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):e(),u={oldTab:s,oldPanel:l,newTab:r?e():a,newPanel:h};t.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",t,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?e():a,this.xhr&&this.xhr.abort(),l.length||h.length||e.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),t),this._toggle(t,u))},_toggle:function(t,i){function s(){a.running=!1,a._trigger("activate",t,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr("aria-hidden","true"),i.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr("aria-hidden","false"),i.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(t){var i,s=this._findActive(t);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return"string"==typeof e&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tablist.unbind(this.eventNamespace),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),i=t.data("ui-tabs-aria-controls");i?t.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(t){var i=this.options.disabled;i!==!1&&(void 0===t?i=!1:(t=this._getIndex(t),i=e.isArray(i)?e.map(i,function(e){return e!==t?e:null}):e.map(this.tabs,function(e,i){return i!==t?i:null})),this._setupDisabled(i))},disable:function(t){var i=this.options.disabled;if(i!==!0){if(void 0===t)i=!0;else{if(t=this._getIndex(t),-1!==e.inArray(t,i))return;i=e.isArray(i)?e.merge([t],i).sort():[t]}this._setupDisabled(i)}},load:function(t,i){t=this._getIndex(t);var s=this,n=this.tabs.eq(t),a=n.find(".ui-tabs-anchor"),o=this._getPanelForTab(n),r={tab:n,panel:o},h=function(e,t){"abort"===t&&s.panels.stop(!1,!0),n.removeClass("ui-tabs-loading"),o.removeAttr("aria-busy"),e===s.xhr&&delete s.xhr};this._isLocal(a[0])||(this.xhr=e.ajax(this._ajaxSettings(a,i,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(n.addClass("ui-tabs-loading"),o.attr("aria-busy","true"),this.xhr.done(function(e,t,n){setTimeout(function(){o.html(e),s._trigger("load",i,r),h(n,t)},1)}).fail(function(e,t){setTimeout(function(){h(e,t)},1)})))},_ajaxSettings:function(t,i,s){var n=this;return{url:t.attr("href"),beforeSend:function(t,a){return n._trigger("beforeLoad",i,e.extend({jqXHR:t,ajaxSettings:a},s))}}},_getPanelForTab:function(t){var i=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}}),e.widget("ui.tooltip",{version:"1.11.4",options:{content:function(){var t=e(this).attr("title")||"";return e("").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_addDescribedBy:function(t,i){var s=(t.attr("aria-describedby")||"").split(/\s+/);s.push(i),t.data("ui-tooltip-id",i).attr("aria-describedby",e.trim(s.join(" ")))},_removeDescribedBy:function(t){var i=t.data("ui-tooltip-id"),s=(t.attr("aria-describedby")||"").split(/\s+/),n=e.inArray(i,s);-1!==n&&s.splice(n,1),t.removeData("ui-tooltip-id"),s=e.trim(s.join(" ")),s?t.attr("aria-describedby",s):t.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable(),this.liveRegion=e("
                  ").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body)},_setOption:function(t,i){var s=this;return"disabled"===t?(this[i?"_disable":"_enable"](),this.options[t]=i,void 0):(this._super(t,i),"content"===t&&e.each(this.tooltips,function(e,t){s._updateContent(t.element)}),void 0)},_disable:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event("blur");n.target=n.currentTarget=s.element[0],t.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).removeAttr("title")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var i=this,s=e(t?t.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),t&&"mouseover"===t.type&&s.parents().each(function(){var t,s=e(this);s.data("ui-tooltip-open")&&(t=e.Event("blur"),t.target=t.currentTarget=this,i.close(t,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._registerCloseHandlers(t,s),this._updateContent(s,t))},_updateContent:function(e,t){var i,s=this.options.content,n=this,a=t?t.type:null;return"string"==typeof s?this._open(t,e,s):(i=s.call(e[0],function(i){n._delay(function(){e.data("ui-tooltip-open")&&(t&&(t.type=a),this._open(t,e,i))})}),i&&this._open(t,e,i),void 0)},_open:function(t,i,s){function n(e){l.of=e,o.is(":hidden")||o.position(l)}var a,o,r,h,l=e.extend({},this.options.position);if(s){if(a=this._find(i))return a.tooltip.find(".ui-tooltip-content").html(s),void 0;i.is("[title]")&&(t&&"mouseover"===t.type?i.attr("title",""):i.removeAttr("title")),a=this._tooltip(i),o=a.tooltip,this._addDescribedBy(i,o.attr("id")),o.find(".ui-tooltip-content").html(s),this.liveRegion.children().hide(),s.clone?(h=s.clone(),h.removeAttr("id").find("[id]").removeAttr("id")):h=s,e("
                  ").html(h).appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:n}),n(t)):o.position(e.extend({of:i},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(r=this.delayedShow=setInterval(function(){o.is(":visible")&&(n(l.of),clearInterval(r))},e.fx.interval)),this._trigger("open",t,{tooltip:o})}},_registerCloseHandlers:function(t,i){var s={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var s=e.Event(t);s.currentTarget=i[0],this.close(s,!0)}}};i[0]!==this.element[0]&&(s.remove=function(){this._removeTooltip(this._find(i).tooltip)}),t&&"mouseover"!==t.type||(s.mouseleave="close"),t&&"focusin"!==t.type||(s.focusout="close"),this._on(!0,i,s)},close:function(t){var i,s=this,n=e(t?t.currentTarget:this.element),a=this._find(n);return a?(i=a.tooltip,a.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&!n.attr("title")&&n.attr("title",n.data("ui-tooltip-title")),this._removeDescribedBy(n),a.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(e(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),t&&"mouseleave"===t.type&&e.each(this.parents,function(t,i){e(i.element).attr("title",i.title),delete s.parents[t]}),a.closing=!0,this._trigger("close",t,{tooltip:i}),a.hiding||(a.closing=!1)),void 0):(n.removeData("ui-tooltip-open"),void 0)},_tooltip:function(t){var i=e("
                  ").attr("role","tooltip").addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||"")),s=i.uniqueId().attr("id");return e("
                  ").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),this.tooltips[s]={element:t,tooltip:i}},_find:function(e){var t=e.data("ui-tooltip-id");return t?this.tooltips[t]:null},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event("blur"),a=s.element;n.target=n.currentTarget=a[0],t.close(n,!0),e("#"+i).remove(),a.data("ui-tooltip-title")&&(a.attr("title")||a.attr("title",a.data("ui-tooltip-title")),a.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}})}); \ No newline at end of file diff --git a/tabbycat/templates/js-vue/FeedbackCards.vue b/tabbycat/templates/js-vue/FeedbackCards.vue new file mode 100644 index 00000000000..93afe7b5324 --- /dev/null +++ b/tabbycat/templates/js-vue/FeedbackCards.vue @@ -0,0 +1,35 @@ + + + + diff --git a/tabbycat/templates/js-vue/UpdatesList.vue b/tabbycat/templates/js-vue/UpdatesList.vue new file mode 100644 index 00000000000..a991e5c98d4 --- /dev/null +++ b/tabbycat/templates/js-vue/UpdatesList.vue @@ -0,0 +1,22 @@ + + + + diff --git a/tabbycat/templates/js-vue/allocations/AllocationActions.vue b/tabbycat/templates/js-vue/allocations/AllocationActions.vue new file mode 100644 index 00000000000..485bcc9765c --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/AllocationActions.vue @@ -0,0 +1,147 @@ + + + diff --git a/tabbycat/templates/js-vue/allocations/AllocationContainer.vue b/tabbycat/templates/js-vue/allocations/AllocationContainer.vue new file mode 100644 index 00000000000..e933a1f0524 --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/AllocationContainer.vue @@ -0,0 +1,222 @@ + + + diff --git a/tabbycat/templates/js-vue/allocations/Debate.vue b/tabbycat/templates/js-vue/allocations/Debate.vue new file mode 100644 index 00000000000..372a1a17950 --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/Debate.vue @@ -0,0 +1,214 @@ + + + diff --git a/tabbycat/templates/js-vue/allocations/DebateAdjudicator.vue b/tabbycat/templates/js-vue/allocations/DebateAdjudicator.vue new file mode 100644 index 00000000000..f66766d389d --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/DebateAdjudicator.vue @@ -0,0 +1,168 @@ + + + diff --git a/tabbycat/templates/js-vue/allocations/DebateImportance.vue b/tabbycat/templates/js-vue/allocations/DebateImportance.vue new file mode 100644 index 00000000000..95cf4da9916 --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/DebateImportance.vue @@ -0,0 +1,45 @@ + + + diff --git a/tabbycat/templates/js-vue/allocations/DebateTeam.vue b/tabbycat/templates/js-vue/allocations/DebateTeam.vue new file mode 100644 index 00000000000..0792f8e50a6 --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/DebateTeam.vue @@ -0,0 +1,93 @@ + + + diff --git a/tabbycat/templates/js-vue/allocations/PositionDroppable.vue b/tabbycat/templates/js-vue/allocations/PositionDroppable.vue new file mode 100644 index 00000000000..f8e3bccdda5 --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/PositionDroppable.vue @@ -0,0 +1,58 @@ + + + \ No newline at end of file diff --git a/tabbycat/templates/js-vue/allocations/UnallocatedAdjudicators.vue b/tabbycat/templates/js-vue/allocations/UnallocatedAdjudicators.vue new file mode 100644 index 00000000000..162dbb305b1 --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/UnallocatedAdjudicators.vue @@ -0,0 +1,43 @@ + + + \ No newline at end of file diff --git a/tabbycat/templates/js-vue/allocations/UnallocatedDivisionTeams.vue b/tabbycat/templates/js-vue/allocations/UnallocatedDivisionTeams.vue new file mode 100644 index 00000000000..aa492aec740 --- /dev/null +++ b/tabbycat/templates/js-vue/allocations/UnallocatedDivisionTeams.vue @@ -0,0 +1,42 @@ + + + \ No newline at end of file diff --git a/tabbycat/templates/js-vue/draganddrops/DivisionDroppable.vue b/tabbycat/templates/js-vue/draganddrops/DivisionDroppable.vue new file mode 100644 index 00000000000..fbf1c78c572 --- /dev/null +++ b/tabbycat/templates/js-vue/draganddrops/DivisionDroppable.vue @@ -0,0 +1,90 @@ + + + + diff --git a/tabbycat/templates/js-vue/draganddrops/TeamDraggable.vue b/tabbycat/templates/js-vue/draganddrops/TeamDraggable.vue new file mode 100644 index 00000000000..dceb4c34253 --- /dev/null +++ b/tabbycat/templates/js-vue/draganddrops/TeamDraggable.vue @@ -0,0 +1,127 @@ + + + diff --git a/tabbycat/templates/js-vue/graphs/BallotsGraph.vue b/tabbycat/templates/js-vue/graphs/BallotsGraph.vue new file mode 100644 index 00000000000..7bef2e258aa --- /dev/null +++ b/tabbycat/templates/js-vue/graphs/BallotsGraph.vue @@ -0,0 +1,110 @@ + + + \ No newline at end of file diff --git a/tabbycat/templates/js-vue/graphs/DonutChart.vue b/tabbycat/templates/js-vue/graphs/DonutChart.vue new file mode 100644 index 00000000000..67fe9d1a489 --- /dev/null +++ b/tabbycat/templates/js-vue/graphs/DonutChart.vue @@ -0,0 +1,106 @@ + + + diff --git a/tabbycat/templates/js-vue/graphs/FeedbackTrend.vue b/tabbycat/templates/js-vue/graphs/FeedbackTrend.vue new file mode 100644 index 00000000000..a4836d59c45 --- /dev/null +++ b/tabbycat/templates/js-vue/graphs/FeedbackTrend.vue @@ -0,0 +1,146 @@ + + + \ No newline at end of file diff --git a/tabbycat/templates/js-vue/graphs/TextDisplay.vue b/tabbycat/templates/js-vue/graphs/TextDisplay.vue new file mode 100644 index 00000000000..54b5c71d4a4 --- /dev/null +++ b/tabbycat/templates/js-vue/graphs/TextDisplay.vue @@ -0,0 +1,52 @@ + + + diff --git a/tabbycat/templates/js-vue/mixins/AjaxMixin.vue b/tabbycat/templates/js-vue/mixins/AjaxMixin.vue new file mode 100644 index 00000000000..64bdb92a260 --- /dev/null +++ b/tabbycat/templates/js-vue/mixins/AjaxMixin.vue @@ -0,0 +1,27 @@ + diff --git a/tabbycat/templates/js-vue/mixins/ConflictsCalculatorMixin.vue b/tabbycat/templates/js-vue/mixins/ConflictsCalculatorMixin.vue new file mode 100644 index 00000000000..a43fcedd303 --- /dev/null +++ b/tabbycat/templates/js-vue/mixins/ConflictsCalculatorMixin.vue @@ -0,0 +1,104 @@ + diff --git a/tabbycat/templates/js-vue/mixins/ConflictsHighlightsMixin.vue b/tabbycat/templates/js-vue/mixins/ConflictsHighlightsMixin.vue new file mode 100644 index 00000000000..fdc5dbefbc9 --- /dev/null +++ b/tabbycat/templates/js-vue/mixins/ConflictsHighlightsMixin.vue @@ -0,0 +1,49 @@ + diff --git a/tabbycat/templates/js-vue/mixins/DiversityHighlightsMixin.vue b/tabbycat/templates/js-vue/mixins/DiversityHighlightsMixin.vue new file mode 100644 index 00000000000..6baa7e3d79b --- /dev/null +++ b/tabbycat/templates/js-vue/mixins/DiversityHighlightsMixin.vue @@ -0,0 +1,70 @@ + diff --git a/tabbycat/templates/js-vue/mixins/DraggableMixin.vue b/tabbycat/templates/js-vue/mixins/DraggableMixin.vue new file mode 100644 index 00000000000..be7be79702e --- /dev/null +++ b/tabbycat/templates/js-vue/mixins/DraggableMixin.vue @@ -0,0 +1,40 @@ + diff --git a/tabbycat/templates/js-vue/mixins/DroppableMixin.vue b/tabbycat/templates/js-vue/mixins/DroppableMixin.vue new file mode 100644 index 00000000000..a339c3b8750 --- /dev/null +++ b/tabbycat/templates/js-vue/mixins/DroppableMixin.vue @@ -0,0 +1,41 @@ + diff --git a/tabbycat/templates/js-vue/mixins/PopoverMixin.vue b/tabbycat/templates/js-vue/mixins/PopoverMixin.vue new file mode 100644 index 00000000000..f94c94412ff --- /dev/null +++ b/tabbycat/templates/js-vue/mixins/PopoverMixin.vue @@ -0,0 +1,55 @@ + diff --git a/tabbycat/templates/js-vue/printables/Ballot.vue b/tabbycat/templates/js-vue/printables/Ballot.vue new file mode 100644 index 00000000000..9f2cccbf7bc --- /dev/null +++ b/tabbycat/templates/js-vue/printables/Ballot.vue @@ -0,0 +1,32 @@ + + + diff --git a/tabbycat/templates/js-vue/printables/BallotFooter.vue b/tabbycat/templates/js-vue/printables/BallotFooter.vue new file mode 100644 index 00000000000..35456dd7d0d --- /dev/null +++ b/tabbycat/templates/js-vue/printables/BallotFooter.vue @@ -0,0 +1,32 @@ + + + diff --git a/tabbycat/templates/js-vue/printables/BallotHeader.vue b/tabbycat/templates/js-vue/printables/BallotHeader.vue new file mode 100644 index 00000000000..518796b389f --- /dev/null +++ b/tabbycat/templates/js-vue/printables/BallotHeader.vue @@ -0,0 +1,31 @@ + + + diff --git a/templates/vue/printables/base-feedback.vue b/tabbycat/templates/js-vue/printables/Feedback.vue similarity index 54% rename from templates/vue/printables/base-feedback.vue rename to tabbycat/templates/js-vue/printables/Feedback.vue index 7ed6cdcc598..4be18e5791b 100644 --- a/templates/vue/printables/base-feedback.vue +++ b/tabbycat/templates/js-vue/printables/Feedback.vue @@ -1,11 +1,11 @@ - + -{% include "vue/printables/feedback-question.vue" %} diff --git a/tabbycat/templates/js-vue/printables/FeedbackQuestion.vue b/tabbycat/templates/js-vue/printables/FeedbackQuestion.vue new file mode 100644 index 00000000000..56fbd470178 --- /dev/null +++ b/tabbycat/templates/js-vue/printables/FeedbackQuestion.vue @@ -0,0 +1,83 @@ + + + diff --git a/templates/vue/printables/base-scoresheet.vue b/tabbycat/templates/js-vue/printables/Scoresheet.vue similarity index 78% rename from templates/vue/printables/base-scoresheet.vue rename to tabbycat/templates/js-vue/printables/Scoresheet.vue index f9e78e37dba..710398bbab7 100644 --- a/templates/vue/printables/base-scoresheet.vue +++ b/tabbycat/templates/js-vue/printables/Scoresheet.vue @@ -1,15 +1,16 @@ - + -{% include "vue/printables/team-scores.vue" %} diff --git a/templates/vue/printables/team-scores.vue b/tabbycat/templates/js-vue/printables/TeamScores.vue similarity index 82% rename from templates/vue/printables/team-scores.vue rename to tabbycat/templates/js-vue/printables/TeamScores.vue index 7ab89e35ba5..bc5072a8917 100644 --- a/templates/vue/printables/team-scores.vue +++ b/tabbycat/templates/js-vue/printables/TeamScores.vue @@ -1,14 +1,14 @@ - + - diff --git a/tabbycat/templates/js-vue/tables/Cell.vue b/tabbycat/templates/js-vue/tables/Cell.vue new file mode 100644 index 00000000000..5ca4a9d9a70 --- /dev/null +++ b/tabbycat/templates/js-vue/tables/Cell.vue @@ -0,0 +1,81 @@ + + + diff --git a/tabbycat/templates/js-vue/tables/Header.vue b/tabbycat/templates/js-vue/tables/Header.vue new file mode 100644 index 00000000000..18e2526cd59 --- /dev/null +++ b/tabbycat/templates/js-vue/tables/Header.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/tabbycat/templates/js-vue/tables/Table.vue b/tabbycat/templates/js-vue/tables/Table.vue new file mode 100644 index 00000000000..ef2befbcb97 --- /dev/null +++ b/tabbycat/templates/js-vue/tables/Table.vue @@ -0,0 +1,146 @@ + + + diff --git a/tabbycat/templates/js-vue/tables/TablesContainer.vue b/tabbycat/templates/js-vue/tables/TablesContainer.vue new file mode 100644 index 00000000000..870aacfafb1 --- /dev/null +++ b/tabbycat/templates/js-vue/tables/TablesContainer.vue @@ -0,0 +1,58 @@ + + + diff --git a/tabbycat/templates/nav/admin_nav.html b/tabbycat/templates/nav/admin_nav.html new file mode 100644 index 00000000000..4c7a1bad9d9 --- /dev/null +++ b/tabbycat/templates/nav/admin_nav.html @@ -0,0 +1,144 @@ +{% load debate_tags %} + + + + diff --git a/templates/nav/assistant_nav.html b/tabbycat/templates/nav/assistant_nav.html similarity index 84% rename from templates/nav/assistant_nav.html rename to tabbycat/templates/nav/assistant_nav.html index 1106c93b0c2..bfee1531126 100644 --- a/templates/nav/assistant_nav.html +++ b/tabbycat/templates/nav/assistant_nav.html @@ -10,5 +10,5 @@
                • Division Sheets
                • {% endif %}
                • - View Draw + View Draw
                • diff --git a/templates/nav/public_nav.html b/tabbycat/templates/nav/public_nav.html similarity index 79% rename from templates/nav/public_nav.html rename to tabbycat/templates/nav/public_nav.html index 18f4f2bc254..17ff11b2b71 100644 --- a/templates/nav/public_nav.html +++ b/tabbycat/templates/nav/public_nav.html @@ -27,7 +27,7 @@ {% endif %} {% if pref.motion_tab_released > 0 %} -
                • +
                • Motions Tab
                • {% endif %} @@ -36,7 +36,7 @@ {% if pref.public_draw and pref.team_tab_released == 0 %} {% if pref.show_all_draws == 0 %}
                • - + Draw for {{ current_round.name }}
                • @@ -46,11 +46,11 @@
                  diff --git a/tournaments/templates/randomised_urls.html b/tabbycat/tournaments/templates/randomised_urls.html similarity index 54% rename from tournaments/templates/randomised_urls.html rename to tabbycat/tournaments/templates/randomised_urls.html index 042740c617f..adec5121f8b 100644 --- a/tournaments/templates/randomised_urls.html +++ b/tabbycat/tournaments/templates/randomised_urls.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "feedback_base.html" %} {% load debate_tags %} {% block head-title %}Randomised URLs{% endblock %} @@ -7,6 +7,7 @@ {% block content %}
                  +

                  {% if exists %} The randomised URLs for public ballot and/or feedback submission are given below. @@ -16,9 +17,10 @@ participants, and are too worried about fraud to use a publicly accessible page where anyone can enter any submission. The URLs will look something like this: - {% tournament_absurl adjfeedback-public-add-from-team-randomised "9dnFlP3Z" %}. + {% tournament_absurl adjfeedback-public-add-from-team-randomised "9dnflp3z" %}. {% endif %}

                  +

                  Anyone with the URLs can access the relevant data entry page. The idea is that it's hard to guess another key (the random-looking string), so you should make each URL accessible only to the team or adjudicator in question, @@ -29,54 +31,60 @@ instead, on the tournament configuration page.

                  -{% if exists %} + {% if exists %} -

                  If you want to delete these, run this command in a shell on your server: - python manage.py randomisedurls delete --tournament {{ tournament_slug }}.

                  - {% if not pref.public_ballots_randomised and not pref.public_feedback_randomised and not pref.allocation_confirmations %} -
                  - The public ballots randomised and public feedback - randomised configuration settings are both disabled. These URLs - will not work unless you enable them on the +

                  If you want to delete these, run this command in a shell on your server: + python manage.py randomisedurls delete --tournament {{ tournament_slug }}

                  +

                  If you want to print these for distribution, use this page. +

                  If you have speaker and adjudicator emails entered, you can email these + + out using this page. + {% if not pref.public_ballots_randomised and not pref.public_feedback_randomised and not pref.allocation_confirmations %} +

                  + The public ballots randomised and public feedback + randomised configuration settings are both disabled. These URLs + will not work unless you enable them on the - tournament - configuration - page. -
                  - {% endif %} - {% if pref.public_ballots and pref.public_ballots_randomised %} -
                  - The public ballots (non-randomised) configuration setting - is enabled, which means that the - page in the public - interface from which anyone can enter any ballot, without knowing any - special URLs, is enabled. This defeats the purpose of the public - ballots randomised setting. You may wish to consider disabling - the non-randomised setting on the - tournament - configuration - page. -
                  - {% endif %} - {% if pref.public_feedback and pref.public_feedback_randomised %} -
                  - The public feedback (non-randomised) configuration - setting is enabled, which means that the - page in the - public interface from which anyone can enter any feedback, without - knowing any special URLs, is enabled. This defeats the purpose of the - public feedback randomised setting. You may wish to - consider disabling the non-randomised settings on the - tournament - configuration - page. -
                  - {% endif %} -
                  + tournament + configuration + page. +
                  + {% endif %} + {% if pref.public_ballots and pref.public_ballots_randomised %} +
                  + The public ballots (non-randomised) configuration setting + is enabled, which means that the + page in the public + interface from which anyone can enter any ballot, without knowing any + special URLs, is enabled. This defeats the purpose of the public + ballots randomised setting. You may wish to consider disabling + the non-randomised setting on the + tournament + configuration + page. +
                  + {% endif %} + {% if pref.public_feedback and pref.public_feedback_randomised %} +
                  + The public feedback (non-randomised) configuration + setting is enabled, which means that the + page in the + public interface from which anyone can enter any feedback, without + knowing any special URLs, is enabled. This defeats the purpose of the + public feedback randomised setting. You may wish to + consider disabling the non-randomised settings on the + tournament + configuration + page. +
                  + {% endif %} + +
                  - +
                  @@ -95,25 +103,26 @@ {% for adj in adjs %} - - {% if adj.url_key %} - {% if pref.public_feedback_randomised %} - - {% endif %} - {% if pref.public_ballots_randomised %} - - {% endif %} - {% if pref.allocation_confirmations %} - - {% endif %} - {% else %} - - {% endif %} + + {% if adj.url_key %} + {% if pref.public_feedback_randomised %} + + {% endif %} + {% if pref.public_ballots_randomised %} + + {% endif %} + {% if pref.allocation_confirmations %} + + {% endif %} + {% else %} + + {% endif %} {% empty %} @@ -128,7 +137,7 @@ {% if pref.public_feedback_randomised %}
                  -
                  Adjudicator
                  {{ adj.name }} - {% tournament_absurl adjfeedback-public-add-from-adjudicator-randomised adj.url_key %} - - {% tournament_absurl public_new_ballotset_key adj.url_key %} - {% tournament_absurl public_confirm_shift_key adj.url_key %}no URLno URL + {{ adj.name }} + {% tournament_absurl adjfeedback-public-add-from-adjudicator-randomised adj.url_key %} + + {% tournament_absurl public_new_ballotset_key adj.url_key %} + {% url 'participants-public-confirm-shift' adj.url_key %}no URLno URL
                  +
                  diff --git a/tabbycat/tournaments/templates/randomised_urls_email_list.html b/tabbycat/tournaments/templates/randomised_urls_email_list.html new file mode 100644 index 00000000000..3967b3ebc7c --- /dev/null +++ b/tabbycat/tournaments/templates/randomised_urls_email_list.html @@ -0,0 +1,80 @@ +{% extends "feedback_base.html" %} +{% load debate_tags %} + +{% block head-title %}Randomised URLs{% endblock %} +{% block page-title %}Randomised URLs{% endblock %} + +{% block content %} + + + {% csrf_token %} + + + +
                  +
                  +
                  +
                  Adjudicators With Email Addresses
                  +
                  + {% for adj in adjs %} + {% if adj.url_key and adj.email %} + {{ adj.name }}, {{ adj.email }}, {% tournament_absurl adjfeedback-public-add-from-adjudicator-randomised adj.url_key %}
                  + {% endif %} + {% endfor %} +
                  +
                  +
                  +
                  +
                  +
                  Teams With Email Addresses
                  +
                  + {% for team in teams %} + {% if team.url_key %} + {% for speaker in team.speakers %} + {% if speaker.email %} + {{ team.short_name }}, {{ speaker.name }}, {{ speaker.email }}, {% tournament_absurl adjfeedback-public-add-from-team-randomised team.url_key %}
                  + {% endif %} + {% endfor %} + {% endif %} + {% endfor %} +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  Adjudicators Without Email Addresses
                  +
                  + {% for adj in adjs %} + {% if adj.url_key %} + {% if not adj.email %} + {{ adj.name }}, No Email, {% tournament_absurl adjfeedback-public-add-from-adjudicator-randomised adj.url_key %}
                  + {% endif %} + {% endif %} + {% endfor %} +
                  +
                  +
                  +
                  +
                  +
                  Teams Without Email Addresses
                  +
                  + {% for team in teams %} + {% if team.url_key %} + {% for speaker in team.speakers %} + {% if not speaker.email %} + {{ team.short_name }}, {{ speaker.name }}, No Email
                  + {% endif %} + {% endfor %} + {% endif %} + {% endfor %} +
                  +
                  +
                  +
                  + +{% endblock content %} diff --git a/tournaments/templates/round_increment_check.html b/tabbycat/tournaments/templates/round_increment_check.html similarity index 65% rename from tournaments/templates/round_increment_check.html rename to tabbycat/tournaments/templates/round_increment_check.html index cb622437c31..81a54cb7237 100644 --- a/tournaments/templates/round_increment_check.html +++ b/tabbycat/tournaments/templates/round_increment_check.html @@ -24,7 +24,7 @@ {% endblock %} -{% block content %} +{% block page-alerts %} {% if increment_ok %}
                  @@ -38,4 +38,20 @@
                  {% endif %} + {% if pref.public_results > 0 %} +
                  + The "show public results" setting is on and this round + {% if round.is_silent %} + is marked as a silent round, so no results + will show on the public page when you advance. + {% else %} + is not marked as a silent round so the results + will show on the public page when you advance. + {% endif %}
                  + A round can be marked/unmarked as silent in the + edit database area + under Tournaments > Rounds. +
                  + {% endif %} + {% endblock %} diff --git a/tournaments/templates/site_index.html b/tabbycat/tournaments/templates/site_index.html similarity index 77% rename from tournaments/templates/site_index.html rename to tabbycat/tournaments/templates/site_index.html index 40a3a4fbd6e..89ebad828e7 100644 --- a/tournaments/templates/site_index.html +++ b/tabbycat/tournaments/templates/site_index.html @@ -15,9 +15,8 @@ {% for tournament in tournaments %}
                • - 🔧{{ tournament.name }} + 🔧Admin area for {{ tournament.name }} - ADMIN SITE
                • @@ -27,14 +26,19 @@ {% else %} 🏆 {% endif %} - {{ tournament.name }} + Public area for {{ tournament.name }} - PUBLIC SITE
                • {% endfor %} + {% if user.is_superuser %} +
                • +   + Edit database area +
                • - Create new tournament + Create new tournament
                • + {% endif %} {% else %}

                  It looks like there aren't any tournaments on this site. Would you like @@ -43,7 +47,6 @@ {% endif %} {% else %} - {% for tournament in tournaments %}

                • @@ -55,22 +58,21 @@ There are currently no tournaments set up on this site.

                  {% endfor %} - {% endif %} {% if tournaments.0.preferences.league_options__enable_mass_draws %}
                • - + 🎪All Draws by Venue
                • - + 🏢All Draws by School
                • - + 👯All Teams and Divisions
                • diff --git a/tabbycat/tournaments/templates/tournament_index.html b/tabbycat/tournaments/templates/tournament_index.html new file mode 100644 index 00000000000..c1140725d8f --- /dev/null +++ b/tabbycat/tournaments/templates/tournament_index.html @@ -0,0 +1,85 @@ +{% extends "base.html" %} +{% load static %} +{% load debate_tags %} + +{% block page-title %}Dashboard{% endblock %} +{% block head-title %}Tournament Overview{% endblock %} + +{% block sub-title %} + {{ round.name }} is {{ round.get_draw_status_display.lower }} + (this page will refresh its data automatically) +{% endblock %} + +{% block content %} + + {% if blank %} +
                  +

                  + Welcome to your new tournament! The next step is to + import your initial tournament data: the institutions, teams, adjudicators + and venues that are in your tournament. There are a number of ways to do + this. For small-to-medium tournaments, you can use the visual + data importer. + (This is also the Setup > Import Data link on the left.) +

                  +

                  For more information, please consult our + + documentation on importing initial data + . +

                  +
                  + {% endif %} + +
                  +
                  +

                  + Number of Ballots In +

                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +

                  Latest Actions

                  +
                    + +
                  • + Loading... +
                  • +
                  • + No Actions In +
                  • +
                  +
                  +
                  +

                  Latest Results

                  +
                    + +
                  • + Loading... +
                  • +
                  • + No Results In +
                  • +
                  +
                  +
                  + +{% endblock content %} + +{% block js %} + + {{ block.super }} +{% endblock %} diff --git a/tabbycat/tournaments/tests/__init__.py b/tabbycat/tournaments/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/tournaments/tests/test_lookup.py b/tabbycat/tournaments/tests/test_lookup.py new file mode 100644 index 00000000000..030918a39d8 --- /dev/null +++ b/tabbycat/tournaments/tests/test_lookup.py @@ -0,0 +1,28 @@ +from django.core.exceptions import ObjectDoesNotExist +from django.test import TestCase + +from tournaments.models import Round, Tournament + + +class TestRoundLookup(TestCase): + + def setUp(self): + self.tournament = Tournament.objects.create() + self.rd = Round.objects.create(tournament=self.tournament, name="A Test Round", abbreviation="ATR", seq=1) + + def tearDown(self): + self.rd.delete() + self.tournament.delete() + + def test_lookup(self): + self.assertEqual(Round.objects.lookup("A Test Round"), self.rd) + self.assertEqual(Round.objects.lookup("ATR"), self.rd) + self.assertRaises(ObjectDoesNotExist, Round.objects.lookup, "randomstring") + + def test_lookup_with_tournament(self): + other_tournament = Tournament.objects.create(slug="other") + self.assertEqual(Round.objects.lookup("A Test Round", tournament=self.tournament), self.rd) + self.assertEqual(Round.objects.lookup("ATR", tournament=self.tournament), self.rd) + self.assertRaises(ObjectDoesNotExist, Round.objects.lookup, "A Test Round", tournament=other_tournament) + self.assertRaises(ObjectDoesNotExist, Round.objects.lookup, "ATR", tournament=other_tournament) + other_tournament.delete() diff --git a/tabbycat/tournaments/urls.py b/tabbycat/tournaments/urls.py new file mode 100644 index 00000000000..1693b9513a5 --- /dev/null +++ b/tabbycat/tournaments/urls.py @@ -0,0 +1,96 @@ +from django.conf.urls import include, url + +from . import views + +urlpatterns = [ + + url(r'^$', + views.TournamentPublicHomeView.as_view(), + name='tournament-public-index'), + url(r'^admin/overview/$', + views.TournamentAdminHomeView.as_view(), + name='tournament-admin-home'), + + url(r'^admin/round/(?P\d+)/round_increment_check/$', + views.RoundIncrementConfirmView.as_view(), + name='round_increment_check'), + url(r'^admin/round/(?P\d+)/round_increment/$', + views.RoundIncrementView.as_view(), + name='round_increment'), + + # Action Logs App + url(r'^admin/action_log/', + include('actionlog.urls')), + + # Allocations App + url(r'^admin/allocations/round/(?P\d+)/', + include('adjallocation.urls')), + + # Availabilities App + url(r'^admin/availability/round/(?P\d+)/', + include('availability.urls')), + + # Breaks App + url(r'^break/', + include('breakqual.urls_public')), + url(r'^admin/break/', + include('breakqual.urls_admin')), + + # Divisions App + url(r'^divisions/', + include('divisions.urls')), + + # Draws App + url(r'^draw/', + include('draw.urls_public')), + url(r'^admin/draw/', + include('draw.urls_admin')), + + # Feedbacks App + url(r'^feedback/', + include('adjfeedback.urls_public')), + url(r'^admin/feedback/', + include('adjfeedback.urls_admin')), + + # Importer App + url(r'^admin/import/', + include('importer.urls')), + + # Motions App + url(r'^motions/', + include('motions.urls_public')), + url(r'^admin/motions/round/(?P\d+)/', + include('motions.urls_admin')), + + # Options App + url(r'^admin/options/', + include('options.urls')), + + # Printing App + url(r'^participants/', + include('printing.urls_admin')), + + # Participants App + url(r'^participants/', + include('participants.urls_public')), + url(r'^admin/participants/', + include('participants.urls_admin')), + + # Results App + url(r'^results/', + include('results.urls_public')), + url(r'^admin/results/', + include('results.urls_admin')), + + # Standings App + url(r'^standings/', + include('standings.urls_public')), + url(r'^tab/', + include('standings.urls_public')), + url(r'^admin/standings/round/(?P\d+)/', + include('standings.urls_admin')), + + # Venues App + url(r'^admin/venues/', + include('venues.urls_admin')), +] diff --git a/tabbycat/tournaments/utils.py b/tabbycat/tournaments/utils.py new file mode 100644 index 00000000000..11f14c5f74c --- /dev/null +++ b/tabbycat/tournaments/utils.py @@ -0,0 +1,51 @@ +import itertools + +from .models import Round + +BREAK_ROUND_NAMES = [ + ('Grand Final', 'GF'), + ('Semifinals', 'SF'), + ('Quarterfinals', 'QF'), + ('Octofinals', 'OF'), + ('Double-Octofinals', 'DOF'), + ('Triple-Octofinals', 'TOF'), +] + + +def auto_make_rounds(tournament, num_rounds): + """Makes the number of rounds specified. The first one is random and the + rest are all power-paired. The last one is silent. This is intended as a + convenience function. For anything more complicated, a more advanced import + method should be used.""" + for i in range(1, num_rounds+1): + Round( + tournament=tournament, + seq=i, + name='Round %d' % i, + abbreviation='R%d' % i, + stage=Round.STAGE_PRELIMINARY, + draw_type=Round.DRAW_RANDOM if (i == 1) else Round.DRAW_POWERPAIRED, + feedback_weight=min((i-1)*0.1, 0.5), + silent=(i == num_rounds), + ).save() + + +def auto_make_break_rounds(tournament, num_prelim, num_break, break_category): + """Makes the number of break rounds specified. This is intended as a + convenience function. For anything more complicated, a more advanced import + method should be used.""" + + break_rounds = itertools.chain(BREAK_ROUND_NAMES, itertools.repeat(('Unknown break round', 'UBR'))) + + for i, (name, abbr) in zip(range(num_break), break_rounds): + Round( + tournament=tournament, + break_category=break_category, + seq=num_prelim+num_break-i, + stage=Round.STAGE_ELIMINATION, + name=name, + abbreviation=abbr, + draw_type=Round.DRAW_FIRSTBREAK if i == num_break-1 else Round.DRAW_BREAK, + feedback_weight=0.5, + silent=True, + ).save() diff --git a/tabbycat/tournaments/views.py b/tabbycat/tournaments/views.py new file mode 100644 index 00000000000..d355f905748 --- /dev/null +++ b/tabbycat/tournaments/views.py @@ -0,0 +1,166 @@ +import logging +from threading import Lock + +from django.conf import settings +from django.contrib import messages +from django.contrib.auth import authenticate, get_user_model, login +from django.contrib.auth.mixins import LoginRequiredMixin +from django.core.urlresolvers import reverse, reverse_lazy +from django.http import Http404, HttpResponse +from django.shortcuts import redirect +from django.views.generic.base import RedirectView, TemplateView +from django.views.generic.edit import CreateView, FormView + +from draw.models import Debate +from utils.forms import SuperuserCreationForm +from utils.misc import redirect_round, redirect_tournament +from utils.mixins import CacheMixin, PostOnlyRedirectView, SuperuserRequiredMixin + +from .forms import TournamentForm +from .mixins import RoundMixin, TournamentMixin +from .models import Tournament + +User = get_user_model() +logger = logging.getLogger(__name__) + + +class PublicSiteIndexView(TemplateView): + template_name = 'site_index.html' + + def get(self, request, *args, **kwargs): + tournaments = Tournament.objects.all() + if tournaments.count() == 1 and not request.user.is_authenticated(): + logger.debug('One tournament only, user is: %s, redirecting to tournament-public-index', request.user) + return redirect_tournament('tournament-public-index', tournaments.first()) + elif not tournaments.exists() and not User.objects.exists(): + logger.debug('No users and no tournaments, redirecting to blank-site-start') + return redirect('blank-site-start') + else: + return super().get(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs['tournaments'] = Tournament.objects.all() + return super().get_context_data(**kwargs) + + +class TournamentPublicHomeView(CacheMixin, TournamentMixin, TemplateView): + template_name = 'public_tournament_index.html' + cache_timeout = 10 # Set slower to show new indexes so it will show new pages + + +class TournamentAdminHomeView(LoginRequiredMixin, TournamentMixin, TemplateView): + template_name = "tournament_index.html" + + def get_context_data(self, **kwargs): + tournament = self.get_tournament() + round = tournament.current_round + assert(round is not None) + kwargs["round"] = round + kwargs["readthedocs_version"] = settings.READTHEDOCS_VERSION + kwargs["blank"] = not (tournament.team_set.exists() or tournament.adjudicator_set.exists() or tournament.venue_set.exists()) + return super().get_context_data(**kwargs) + + def get(self, request, *args, **kwargs): + tournament = self.get_tournament() + if tournament.current_round is None: + if self.request.user.is_superuser: + tournament.current_round = tournament.round_set.order_by('seq').first() + if tournament.current_round is None: + return HttpResponse('

                  Error: This tournament has no rounds; ' + ' you\'ll need to add some in the ' + 'Edit Database area.

                  ') + messages.warning(self.request, "The current round wasn't set, " + "so it's been automatically set to the first round.") + logger.warning("Automatically set current round to {}".format(tournament.current_round)) + tournament.save() + self.request.tournament = tournament # Update for context processors + else: + raise Http404() + return super().get(self, request, *args, **kwargs) + + +class RoundIncrementConfirmView(SuperuserRequiredMixin, RoundMixin, TemplateView): + template_name = 'round_increment_check.html' + + def get(self, request, *args, **kwargs): + round = self.get_round() + current_round = self.get_tournament().current_round + if round != current_round: + messages.warning(self.request, 'You are trying to advance to ' + + round.name + ' but the current round is ' + current_round.name + + ' — advance to ' + round.prev.name + ' first!') + return redirect_round('results', self.get_tournament().current_round) + else: + return super().get(self, request, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs['num_unconfirmed'] = self.get_round().get_draw().filter( + result_status__in=[Debate.STATUS_NONE, Debate.STATUS_DRAFT]).count() + kwargs['increment_ok'] = kwargs['num_unconfirmed'] == 0 + return super().get_context_data(**kwargs) + + +class RoundIncrementView(SuperuserRequiredMixin, PostOnlyRedirectView, RoundMixin): + + def post(self, request, *args, **kwargs): + self.get_tournament().advance_round() + return redirect_round('availability_index', self.get_tournament().current_round) + + +class BlankSiteStartView(FormView): + """This view is presented to the user when there are no tournaments and no + user accounts. It prompts the user to create a first superuser. It rejects + all requests, GET or POST, if there exists any user account in the + system.""" + + form_class = SuperuserCreationForm + template_name = "blank_site_start.html" + lock = Lock() + success_url = reverse_lazy('tabbycat-index') + + def get(self, request): + if User.objects.exists(): + logger.error("Tried to get the blank-site-start view when a user account already exists.") + return redirect('tabbycat-index') + + return super().get(request) + + def post(self, request): + with self.lock: + if User.objects.exists(): + logger.error("Tried to post the blank-site-start view when a user account already exists.") + messages.error(request, "Whoops! It looks like someone's already created the first user account. Please log in.") + return redirect('login') + + return super().post(request) + + def form_valid(self, form): + form.save() + user = authenticate(username=self.request.POST['username'], password=self.request.POST['password1']) + login(self.request, user) + messages.success(self.request, "Welcome! You've created an account for %s." % user.username) + + return super().form_valid(form) + + +class CreateTournamentView(SuperuserRequiredMixin, CreateView): + """This view allows a logged-in superuser to create a new tournament.""" + + model = Tournament + form_class = TournamentForm + template_name = "create_tournament.html" + + +class TournamentPermanentRedirectView(RedirectView): + """Redirect old-style /t//... URLs to new-style //... URLs.""" + + url = "/%(slug)s/%(page)s" + permanent = True + + def get_redirect_url(self, *args, **kwargs): + slug = kwargs['slug'] + if not Tournament.objects.filter(slug=slug).exists(): + logger.error("Tried to redirect non-existent tournament slug '%s'" % slug) + raise Http404("There isn't a tournament with slug '%s'." % slug) + return super().get_redirect_url(*args, **kwargs) diff --git a/urls.py b/tabbycat/urls.py similarity index 68% rename from urls.py rename to tabbycat/urls.py index c7b5e393b51..65af0e10551 100644 --- a/urls.py +++ b/tabbycat/urls.py @@ -1,13 +1,13 @@ -import django.contrib.auth.views as auth_views -import tournaments.views - from django.conf import settings -from django.conf.urls import * +from django.conf.urls import include, url from django.contrib import admin, messages -from django.contrib.auth.signals import user_logged_out, user_logged_in +from django.contrib.auth import views as auth_views +from django.contrib.auth.signals import user_logged_in, user_logged_out from django.dispatch import receiver from django.views.generic.base import RedirectView +import tournaments.views + admin.autodiscover() # ============================================================================== @@ -18,42 +18,61 @@ # Indices url(r'^$', - tournaments.views.index, + tournaments.views.PublicSiteIndexView.as_view(), name='tabbycat-index'), - url(r'^t/(?P[-\w_]+)/', - include('tournaments.urls')), url(r'^start/', tournaments.views.BlankSiteStartView.as_view(), name='blank-site-start'), - url(r'^tournament/create/', + url(r'^create/', tournaments.views.CreateTournamentView.as_view(), name='tournament-create'), # Admin area url(r'^jet/', include('jet.urls', 'jet')), - url(r'^admin/', + url(r'^database/', include(admin.site.urls)), + url(r'^admin/(?P[-\w_/]*)$', + RedirectView.as_view(url='/database/%(page)s', permanent=True)), # Accounts url(r'^accounts/login/$', auth_views.login, - name='auth-login'), + name='login'), url(r'^accounts/logout/$', auth_views.logout, - {'next_page': '/'}), + {'next_page': '/'}, + name='logout'), # Favicon for old browsers that ignore the head link url(r'^favicon\.ico$', - RedirectView.as_view(url='/static/favicon.ico')) + RedirectView.as_view(url='/static/favicon.ico')), + + # Redirect for old-style tournament URLs + # Avoid keyword argument name 'tournament_slug' to avoid triggering DebateMiddleware + url(r'^t/(?P[-\w_]+)/(?P[-\w_/]*)$', + tournaments.views.TournamentPermanentRedirectView.as_view()), + + # Tournament URLs + url(r'^(?P[-\w_]+)/', + include('tournaments.urls')), + + # Participants Cross Tournament + url(r'^participants/', + include('participants.urls_crosst')), + + # Draws Cross Tournament + url(r'^draw/', + include('draw.urls_crosst')) ] if settings.DEBUG: import debug_toolbar - urlpatterns += [ + urlpatterns.insert(-1, # insert before the tournament URLs catch-all # Only serve debug toolbar when on DEBUG url(r'^__debug__/', include(debug_toolbar.urls)), - ] + ) + # ============================================================================== # Logout/Login Confirmations @@ -74,6 +93,7 @@ def on_user_logged_in(sender, request, **kwargs): else: # should never happen, but just in case messages.success(request, 'Welcome! You just logged in!') + # ============================================================================== # Redirect Method # ============================================================================== diff --git a/tabbycat/utils/__init__.py b/tabbycat/utils/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tabbycat/utils/admin.py b/tabbycat/utils/admin.py new file mode 100644 index 00000000000..7d508838c54 --- /dev/null +++ b/tabbycat/utils/admin.py @@ -0,0 +1,47 @@ +''' General utilities for extending filters/lists in the admin area''' + +# ============================================================================== +# Utilities +# ============================================================================== + + +class BaseModelAdmin(): + + def get_round(self, obj): + if hasattr(obj, 'debate'): + return obj.debate.round.seq + else: + return obj.debate_team.debate.round.abbreviation + get_round.short_description = 'Round' + + def get_team(self, obj): + return obj.debate_team.team + get_team.short_description = 'Team' + + def get_speaker_name(self, obj): + return obj.speaker.name + get_speaker_name.short_description = 'Speaker' + + def get_adj_name(self, obj): + return obj.debate_adjudicator.adjudicator.name + get_speaker_name.short_description = 'Adjudicator' + + def get_tournament(self, obj): + if hasattr(obj, 'round'): + return obj.round.tournament + else: + return obj.debate.round.tournament + + get_tournament.short_description = 'Tournament' + + def get_team_position(self, obj): + return obj.debate_team.position + get_team_position.short_description = 'Position' + + def get_motion_ref(self, obj): + return obj.motion.reference + get_motion_ref.short_description = 'Motion' + + def get_confirmed(self, obj): + return obj.ballot_submission.confirmed + get_confirmed.short_description = 'Confirmed' diff --git a/utils/context_processors.py b/tabbycat/utils/context_processors.py similarity index 93% rename from utils/context_processors.py rename to tabbycat/utils/context_processors.py index 2988aa0e66d..4cf73b78686 100644 --- a/utils/context_processors.py +++ b/tabbycat/utils/context_processors.py @@ -1,6 +1,7 @@ -from tournaments.models import Tournament from django.conf import settings +from tournaments.models import Tournament + def debate_context(request): @@ -27,7 +28,9 @@ def debate_context(request): def get_menu_highlight(request): - if "side_allocations" in request.path: + if "overview" in request.path: + return {"overview_nav": True} + elif "sides" in request.path: return {'sides_nav': True} elif "availability" in request.path: return {'availability_nav': True} @@ -39,6 +42,8 @@ def get_menu_highlight(request): return {'divisions_nav': True} elif "draw" in request.path: return {'draw_nav': True} + elif "diversity" in request.path: + return {'diversity_nav': True} elif "feedback" in request.path and "add" in request.path: return {'enter_feedback_nav': True} elif "feedback_progress" in request.path: diff --git a/utils/forms.py b/tabbycat/utils/forms.py similarity index 92% rename from utils/forms.py rename to tabbycat/utils/forms.py index caed5c1adda..1d11c057d53 100644 --- a/utils/forms.py +++ b/tabbycat/utils/forms.py @@ -1,5 +1,4 @@ from django import forms -from django.utils.translation import ugettext as _ from django.contrib.auth.forms import UserCreationForm diff --git a/tabbycat/utils/management/__init__.py b/tabbycat/utils/management/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/utils/management/base.py b/tabbycat/utils/management/base.py similarity index 92% rename from utils/management/base.py rename to tabbycat/utils/management/base.py index 3f4b54ef374..3c43b119f16 100644 --- a/utils/management/base.py +++ b/tabbycat/utils/management/base.py @@ -1,8 +1,9 @@ +import logging + from django.core.management.base import BaseCommand, CommandError -from tournaments.models import Tournament, Round + from settings import TABBYCAT_APPS -from argparse import ArgumentTypeError -import logging +from tournaments.models import Round, Tournament def _set_log_level(level): @@ -30,8 +31,7 @@ def add_arguments(self, parser): action="append", dest="tournament_selection", metavar="TOURNAMENT", - help= - "Slug of tournament(s), required if there is more than one tournament. " + help="Slug of tournament(s), required if there is more than one tournament. " "Can be specified multiple times to run the command on multiple tournaments.") tournaments_group.add_argument( "--all-tournaments", @@ -53,13 +53,13 @@ def get_tournaments(self, options): pass elif options["all_tournaments"]: - if tournament_option: + if options["tournament_selection"]: raise CommandError( "You can't use --tournament and --all-tournaments together.") options["__tournaments__"] = list(Tournament.objects.all()) elif not options["tournament_selection"]: - # if there is only one tournament, that'll do. + # If there is only one tournament, that'll do. if Tournament.objects.count() > 1: raise CommandError( "You must specify a tournament, because there is more than one tournament in the database.") @@ -174,7 +174,7 @@ def _get_round(self, tournament, specifier): return tournament.round_set.get(**{spectype: specifier}) except Round.DoesNotExist: raise CommandError("The tournament {tournament!r} has no round with {type} {spec!r}".format( - tournament=tournament.slug, type=spectype, spec=specifier)) + tournament=tournament.slug, type=spectype, spec=specifier)) def get_rounds(self, options): """Returns a list of rounds implied by command-line arguments. @@ -190,9 +190,9 @@ def get_rounds(self, options): if options.get("all_rounds", False): rounds.extend(tournament.round_set.all()) if options.get("prelim_rounds", False): - rounds.extend(tournament.prelim_rounds.all()) + rounds.extend(tournament.prelim_rounds().all()) if options.get("break_rounds", False): - rounds.extend(tournament.break_rounds.all()) + rounds.extend(tournament.break_rounds().all()) if not rounds and self.rounds_required: raise CommandError("No rounds were given. (Use --help for more info.)") @@ -201,12 +201,10 @@ def get_rounds(self, options): def _confirm_rounds(self, rounds, **options): if not options["confirm"]: - self.stdout.write(self.style.WARNING( - "WARNING! You are about to {} from the following rounds:".format( - self.confirm_round_destruction))) + self.stdout.write(self.style.WARNING("WARNING! You are about to {} from the following rounds:".format(self.confirm_round_destruction))) for r in rounds: self.stdout.write(self.style.WARNING(" [{t}]: {r}".format( - t=r.tournament.name, r=r.name))) + t=r.tournament.name, r=r.name))) response = input("Are you sure? ") if response != "yes": raise CommandError("Cancelled by user.") diff --git a/utils/management/commands/clear_cache.py b/tabbycat/utils/management/commands/clearcache.py similarity index 76% rename from utils/management/commands/clear_cache.py rename to tabbycat/utils/management/commands/clearcache.py index 635e26897ab..ad3b601e105 100644 --- a/utils/management/commands/clear_cache.py +++ b/tabbycat/utils/management/commands/clearcache.py @@ -1,5 +1,5 @@ -from django.core.management.base import BaseCommand, CommandError from django.core.cache import cache +from django.core.management.base import BaseCommand class Command(BaseCommand): diff --git a/utils/management/commands/randomisedurls.py b/tabbycat/utils/management/commands/randomisedurls.py similarity index 89% rename from utils/management/commands/randomisedurls.py rename to tabbycat/utils/management/commands/randomisedurls.py index b6e82128bc7..20544609031 100644 --- a/utils/management/commands/randomisedurls.py +++ b/tabbycat/utils/management/commands/randomisedurls.py @@ -1,8 +1,9 @@ -from utils.management.base import TournamentCommand -from ...urlkeys import populate_url_keys, delete_url_keys -from tournaments.models import Tournament from argparse import ArgumentParser +from utils.management.base import TournamentCommand + +from ...urlkeys import delete_url_keys, populate_url_keys + class Command(TournamentCommand): @@ -63,9 +64,8 @@ def populate_url_keys(self, relatedmanager): model_name = relatedmanager.model._meta.verbose_name_plural.lower() if existing.exists(): - self.stdout.write(self.style.WARNING( - "Skipping {0:d} {1:s} that already have randomised URLs. Use --overwrite to overwrite them.".format( - existing.count(), model_name))) + self.stdout.write(self.style.WARNING("Skipping {0:d} {1:s} that already have randomised URLs. Use --overwrite to overwrite them.".format( + existing.count(), model_name))) self.stdout.write("Generating randomised URLs for {0:d} {1:s}".format( queryset.count(), model_name)) diff --git a/utils/management/commands/simulaterounds.py b/tabbycat/utils/management/commands/simulaterounds.py similarity index 94% rename from utils/management/commands/simulaterounds.py rename to tabbycat/utils/management/commands/simulaterounds.py index 9d00de799ab..77663745e48 100644 --- a/utils/management/commands/simulaterounds.py +++ b/tabbycat/utils/management/commands/simulaterounds.py @@ -1,17 +1,18 @@ -from adjallocation.hungarian import HungarianAllocator +from django.contrib.auth import get_user_model + from adjallocation.allocator import allocate_adjudicators +from adjallocation.hungarian import HungarianAllocator from draw.models import Debate from draw.manager import DrawManager -from utils.management.base import RoundCommand, CommandError -from venues.allocator import allocate_venues from results.dbutils import add_ballotsets_to_round -from results.management.commands.generateresults import GenerateResultsCommandMixin, SUBMITTER_TYPE_MAP +from results.management.commands.generateresults import GenerateResultsCommandMixin from tournaments.models import Round - -from django.contrib.auth import get_user_model +from utils.management.base import RoundCommand +from venues.allocator import allocate_venues User = get_user_model() + class Command(GenerateResultsCommandMixin, RoundCommand): help = "Adds draws and results to the database" diff --git a/tabbycat/utils/managers.py b/tabbycat/utils/managers.py new file mode 100644 index 00000000000..5657f145b8e --- /dev/null +++ b/tabbycat/utils/managers.py @@ -0,0 +1,21 @@ +from django.core.exceptions import ObjectDoesNotExist + + +class LookupByNameFieldsMixin: + """Adds the ability to look up by searching a number of name fields for an + exact match. For example, a model might have short names, long names and + abbreviations; this mixin would allow lookups that will match any of the + three. + + This mixin should be added to managers (not models).""" + + name_fields = [] + + def lookup(self, name, **kwargs): + for field in self.name_fields: + try: + kwargs[field] = name + return self.get(**kwargs) + except ObjectDoesNotExist: + kwargs.pop(field) + raise self.model.DoesNotExist("No %s matching '%s'" % (self.model._meta.verbose_name, name)) diff --git a/utils/middleware.py b/tabbycat/utils/middleware.py similarity index 96% rename from utils/middleware.py rename to tabbycat/utils/middleware.py index 4c8415357c2..23fdca457b0 100644 --- a/utils/middleware.py +++ b/tabbycat/utils/middleware.py @@ -1,7 +1,7 @@ +from django.core.cache import cache from django.shortcuts import get_object_or_404 -from tournaments.models import Tournament, Round -from django.core.cache import cache +from tournaments.models import Round, Tournament class DebateMiddleware(object): diff --git a/utils/misc.py b/tabbycat/utils/misc.py similarity index 56% rename from utils/misc.py rename to tabbycat/utils/misc.py index 7a8fc6cd7f7..83ef857107d 100644 --- a/utils/misc.py +++ b/tabbycat/utils/misc.py @@ -10,23 +10,23 @@ def get_ip_address(request): return ip -def redirect_tournament(to, tournament, **kwargs): - return redirect(to, tournament_slug=tournament.slug, **kwargs) +def redirect_tournament(to, tournament, *args, **kwargs): + return redirect(to, tournament_slug=tournament.slug, *args, **kwargs) -def reverse_tournament(to, tournament, **kwargs): +def reverse_tournament(to, tournament, *args, **kwargs): kwargs.setdefault('kwargs', {}) kwargs['kwargs']['tournament_slug'] = tournament.slug - return reverse(to, **kwargs) + return reverse(to, *args, **kwargs) -def redirect_round(to, round, **kwargs): +def redirect_round(to, round, *args, **kwargs): return redirect(to, tournament_slug=round.tournament.slug, - round_seq=round.seq, **kwargs) + round_seq=round.seq, *args, **kwargs) -def reverse_round(to, round, **kwargs): +def reverse_round(to, round, *args, **kwargs): kwargs.setdefault('kwargs', {}) kwargs['kwargs']['tournament_slug'] = round.tournament.slug kwargs['kwargs']['round_seq'] = round.seq - return reverse(to, **kwargs) + return reverse(to, *args, **kwargs) diff --git a/tabbycat/utils/mixins.py b/tabbycat/utils/mixins.py new file mode 100644 index 00000000000..610de9cc167 --- /dev/null +++ b/tabbycat/utils/mixins.py @@ -0,0 +1,228 @@ +import json +import logging + +from django.conf import settings +from django.contrib import messages +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin +from django.core.exceptions import ImproperlyConfigured +from django.core.urlresolvers import reverse_lazy +from django.db.models import Q +from django.forms.models import modelformset_factory +from django.http import HttpResponseRedirect, JsonResponse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_text +from django.views.decorators.cache import cache_page +from django.views.generic.base import ContextMixin, TemplateResponseMixin, TemplateView, View +from django.views.generic.detail import SingleObjectMixin + +from tournaments.mixins import TournamentMixin + +logger = logging.getLogger(__name__) + + +class PostOnlyRedirectView(View): + """Base class for views that only accept POST requests. + + Current implementation redirects to a specified page (by default the home + page) if a client tries to use a GET request, and shows and logs an error + message. We might change this in the future just to return HTTP status code + 405 (HTTP method not allowed). + + Views using this class probably want to override both `post()` and + `get_redirect_url()`. It is assumed that the same redirect will be desired + the same whether GET or POST is used; it's just that a GET request won't + do database edits. + + Note: The `post()` implementation of subclasses should call `super().post()` + rather than returning the redirect directly, in case we decide to make + `post()` smarter in the future. If there ever arises a need to distinguish + between the redirects in the GET and POST cases, new methods should be added + to this base class for this purpose. + """ + + redirect_url = reverse_lazy('tabbycat-index') + not_post_message = "Whoops! You're not meant to type that URL into your browser." + + def get_redirect_url(self, *args, **kwargs): + return self.redirect_url % kwargs + + def get(self, request, *args, **kwargs): + logger.error("Tried to access a POST-only view with a GET request") + messages.error(self.request, self.not_post_message) + return HttpResponseRedirect(self.get_redirect_url(*args, **kwargs)) + + def post(self, request, *args, **kwargs): + return HttpResponseRedirect(self.get_redirect_url(*args, **kwargs)) + + +class JsonDataResponseView(View): + """Mixings for views that dump back a json response""" + + def get_data(): + pass + + def get(self, request, *args, **kwargs): + self.request = request + return JsonResponse(self.get_data(), safe=False) + + +class SuperuserRequiredMixin(UserPassesTestMixin): + """Class-based view mixin. Requires user to be a superuser.""" + + def test_func(self): + return self.request.user.is_superuser + + +class SuperuserOrTabroomAssistantTemplateResponseMixin(LoginRequiredMixin, TemplateResponseMixin): + """Mixin for views that choose either a superuser view or an assistant view, + depending on the privileges of the user who is logged in. + + Views using this mixin must define the `superuser_template_name` and + `assistant_template_name` class attributes.""" + + superuser_template_name = None + assistant_template_name = None + + def get_template_names(self): + if self.request.user.is_superuser: + return [self.superuser_template_name] + else: + return [self.assistant_template_name] + + +class CacheMixin: + """Mixin for views that cache the page.""" + + cache_timeout = settings.PUBLIC_PAGE_CACHE_TIMEOUT + + @method_decorator(cache_page(cache_timeout)) + def dispatch(self, *args, **kwargs): + return super().dispatch(*args, **kwargs) + + +class SingleObjectFromTournamentMixin(SingleObjectMixin, TournamentMixin): + """Mixin for views that relate to a single object that is part of a + tournament. Like SingleObjectMixin, but restricts searches to the relevant + tournament.""" + + allow_null_tournament = False + + def get_queryset(self): + if self.allow_null_tournament: + return super().get_queryset().filter( + Q(tournament=self.get_tournament()) | Q(tournament__isnull=True) + ) + else: + return super().get_queryset().filter(tournament=self.get_tournament()) + + +class SingleObjectByRandomisedUrlMixin(SingleObjectFromTournamentMixin): + """Mixin for views that use URLs referencing objects by a randomised key. + This is just a `SingleObjectFromTournamentMixin` with some options set. + + Views using this mixin should have both a `url_key` group in their URL's + regular expression, and a primary key group (by default `pk`, inherited from + `SingleObjectMixin`, but this can be overridden). They should set the + `model` field of the class as they would for `SingleObjectMixin`. This model + should have a slug field called `url_key`. + """ + slug_field = 'url_key' + slug_url_kwarg = 'url_key' + + +class VueTableTemplateView(TemplateView): + """Mixing that provides shortcuts for adding data when building arrays that + will end up as rows within a Vue table. Each cell can be represented + either as a string value or a dictionary to enable richer inline content + (emoji, links, etc). Functions below return blocks of content (ie not just + a team name row, but also institution/category status as needed).""" + + template_name = 'base_vue_table.html' + + def get_context_data(self, **kwargs): + tables = self.get_tables() + kwargs["tables_count"] = list(range(len(tables))) + kwargs["tables_data"] = json.dumps([table.jsondict() for table in tables]) + return super().get_context_data(**kwargs) + + def get_table(self): + raise NotImplementedError("subclasses must implement get_table()") + + def get_tables(self): + return [self.get_table()] + + +class FormSetMixin(ContextMixin): + """Provides some functionality for formsets, analogously to FormMixin. + Only what is actually used in Tabbycat is implemented.""" + + success_url = None + + def get_context_data(self, **kwargs): + if 'formset' not in kwargs: + kwargs['formset'] = self.get_formset() + return super().get_context_data(**kwargs) + + def formset_valid(self, formset): + return HttpResponseRedirect(self.get_success_url()) + + def formset_invalid(self, formset): + return self.render_to_response(self.get_context_data(formset=formset)) + + def get_success_url(self): + if self.success_url: + # Forcing possible reverse_lazy evaluation + url = force_text(self.success_url) + else: + raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.") + return url + + +class ModelFormSetMixin(FormSetMixin): + """Provides some functionality for model formsets, analogously to + ModelFormMixin. Only what is actually used in Tabbycat is implemented.""" + + formset_factory_kwargs = {} + formset_model = None # not 'model' to avoid conflicts with SingleObjectMixin + + def get_formset_factory_kwargs(self): + return self.formset_factory_kwargs.copy() + + def get_formset_class(self): + return modelformset_factory(self.formset_model, **self.get_formset_factory_kwargs()) + + def get_formset_queryset(self): + return self.formset_model.objects.all() + + def get_formset(self): + formset_class = self.get_formset_class() + if self.request.method in ('POST', 'PUT'): + return formset_class(data=self.request.POST, files=self.request.FILES) + elif self.request.method == 'GET': + return formset_class(queryset=self.get_formset_queryset()) + + def formset_valid(self, formset): + formset.save() + return super().formset_valid(formset) + + +class ProcessFormSetView(View): + """Provides some functionality for model formsets, analogously to + ProcessFormView.""" + + def get(self, request, *args, **kwargs): + return self.render_to_response(self.get_context_data()) + + def post(self, request, *args, **kwargs): + formset = self.get_formset() + if formset.is_valid(): + return self.formset_valid(formset) + else: + return self.formset_invalid(formset) + + def put(self, request, *args, **kwargs): + return self.post(request, *args, **kwargs) + + +class ModelFormSetView(ModelFormSetMixin, TemplateResponseMixin, ProcessFormSetView): + pass diff --git a/tabbycat/utils/tables.py b/tabbycat/utils/tables.py new file mode 100644 index 00000000000..6e3e81bcaa9 --- /dev/null +++ b/tabbycat/utils/tables.py @@ -0,0 +1,667 @@ +from django.contrib.auth.mixins import LoginRequiredMixin +from django.utils import formats + +from adjallocation.allocation import AdjudicatorAllocation +from adjallocation.utils import adjudicator_conflicts_display +from draw.models import Debate, DebateTeam +from participants.models import Team +from participants.utils import get_side_counts +from standings.templatetags.standingsformat import metricformat, rankingformat +from utils.misc import reverse_tournament +from venues.utils import venue_conflicts_display + +from .mixins import SuperuserRequiredMixin + + +class BaseTableBuilder: + """Class for building tables that can be easily inserted into Vue tables, + Designed to be used with VueTableTemplateView. + + In the docstrings for this class: + - A *header dict* is a dict that contains a value under `"key"` that is a + string, and may optionally contain entries under `"tooltip"`, `"icon"`, + `"visible-sm"`, `"visible-md"` and `"visible-lg"`. + - A *cell dict* is a dict that contains a value under `"text"` that is a + string, and may optionally contain entries under `"sort"`, `"icon"`, + `"emoji"`, `"popover"` and `"link"`. + + """ + + def __init__(self, **kwargs): + self.headers = [] + self.data = [] + self.title = kwargs.get('title', "") + self.table_class = kwargs.get('table_class', "") + self.sort_key = kwargs.get('sort_key', '') + self.sort_order = kwargs.get('sort_order', '') + self.popovers = kwargs.get('popovers', True) + + @staticmethod + def _convert_header(header): + return {'key': header} if isinstance(header, str) else header + + @staticmethod + def _convert_cell(cell): + if isinstance(cell, int) or isinstance(cell, float): + return {'text': str(cell), + 'sort': cell} + if isinstance(cell, str): + return {'text': cell} + return cell + + def add_column(self, header, data): + """Adds a column to the table. + + - `header` must be either a string or a header dict (see class docstring). + - `data` must be a list of cells (in the column). Each cell should + either be a string or a cell dict (see class docstring). If this is + not the first column, then there must be as many elements in `data` as + there are in the existing columns. + """ + if len(self.data) > 0 and len(data) != len(self.data): + raise ValueError("data contains {new:d} rows, existing table has {existing:d}".format( + new=len(data), existing=len(self.data))) + + header = self._convert_header(header) + self.headers.append(header) + + data = map(self._convert_cell, data) + if len(self.data) == 0: + self.data = [[cell] for cell in data] + else: + for row, cell in zip(self.data, data): + row.append(cell) + + def add_boolean_column(self, header, data): + """Convenience function for adding a column based on boolean data. + + - `header` must be either a string or a header dict. + - `data` must be an iterable of booleans. + """ + cells = [{ + 'icon': 'glyphicon-ok' if datum else '', + 'sort': 1 if datum else 2, + } for datum in data] + self.add_column(header, cells) + + def add_columns(self, headers, data): + """Adds columns to the table. + + This method is intended for situations where it is easier to process + data by row while adding it to the table, than it is to process data + by column. In the latter case, use `add_column()` instead. + + - `headers` must be a list of strings or header dicts (or both). + - `data` must be a list of lists of cells, where each cell is a string + or cell dict. Each inner list corresponds to a row, and all inner + lists must contain the same number of elements, which must also match + the number of elements in `headers`. If there are no existing columns + in the table, then there must be as many inner lists as there are + existing columns. + """ + if len(self.data) > 0 and len(data) != len(self.data): + raise ValueError("data contains {new:d} rows, existing table has {existing:d}".format( + new=len(data), existing=len(self.data))) + + headers = map(self._convert_header, headers) + self.headers.extend(headers) + + if len(self.data) == 0: + self.data = [[self._convert_cell(cell) for cell in row] for row in data] + else: + for row, cells in zip(self.data, data): + cells = map(self._convert_cell, cells) + row.extend(cells) + + def jsondict(self): + """Returns the JSON dict for the table.""" + if self.popovers is False: + self._strip_popovers() + return { + 'head': self.headers, + 'data': self.data, + 'title': self.title, + 'class': self.table_class, + 'sort_key': self.sort_key, + 'sort_order': self.sort_order + } + + def _strip_popovers(self): + """Strips all popovers from the table. Used as an override in views + where popovers make no sense, like those intended for the projector + in general assembly.""" + for row in self.data: + for cell in row: + if 'popover' in cell: + del cell['popover'] + + +class TabbycatTableBuilder(BaseTableBuilder): + """Extends TableBuilder to add convenience functions specific to + Tabbycat.""" + + ADJ_SYMBOLS = { + AdjudicatorAllocation.POSITION_CHAIR: "Ⓒ", + AdjudicatorAllocation.POSITION_TRAINEE: "Ⓣ", + } + + ADJ_POSITION_NAMES = { + AdjudicatorAllocation.POSITION_CHAIR: "chair", + AdjudicatorAllocation.POSITION_PANELLIST: "panellist", + AdjudicatorAllocation.POSITION_TRAINEE: "trainee", + } + + def __init__(self, view=None, **kwargs): + """Constructor. + - If `tournament` is specified, it becomes the default tournament for + the builder. + - If `admin` is True (default is False), then relevant links will go + to the admin version rather than the public version. + - If `view` is specified, then `tournament` and `admin` are inferred + from `view`. This option is provided for convenience. + """ + if 'tournament' not in kwargs and hasattr(view, 'get_tournament'): + self.tournament = view.get_tournament() + else: + self.tournament = kwargs.get('tournament') + + if 'admin' not in kwargs and isinstance(view, SuperuserRequiredMixin) or \ + (isinstance(view, LoginRequiredMixin) and view.request.user.is_superuser): + self.admin = True + else: + self.admin = kwargs.get('admin', False) + + return super().__init__(**kwargs) + + @property + def _show_record_links(self): + return self.admin or self.tournament.pref('public_record') + + @property + def _show_speakers_in_draw(self): + return self.tournament.pref('show_speakers_in_draw') or self.admin + + def _adjudicator_record_link(self, adj): + adj_short_name = adj.name.split(" ")[0] + if self.admin: + return { + 'text': "View %s's Adjudication Record" % adj_short_name, + 'link': reverse_tournament('participants-adjudicator-record', + self.tournament, kwargs={'pk': adj.pk}) + } + elif self.tournament.pref('public_record'): + return { + 'text': "View %s's Adjudication Record" % adj_short_name, + 'link': reverse_tournament('participants-public-adjudicator-record', + self.tournament, kwargs={'pk': adj.pk}) + } + else: + return {'text': False, 'link': False} + + def _team_record_link(self, team): + if self.admin: + return { + 'text': "View %s's Team Record" % team.short_name, + 'link': reverse_tournament('participants-team-record', self.tournament, kwargs={'pk': team.pk}) + } + elif self.tournament.pref('public_record'): + return { + 'text': "View %s's Team Record" % team.short_name, + 'link': reverse_tournament('participants-public-team-record', self.tournament, kwargs={'pk': team.pk}) + } + else: + return {'text': False, 'link': False} + + def _team_cell(self, team, hide_emoji=True): + cell = { + 'text': team.short_name, + 'emoji': team.emoji if self.tournament.pref('show_emoji') and not hide_emoji else None, + 'sort': team.short_name, + 'class': 'team-name', + 'popover': {'title': team.long_name, 'content': []} + } + if self._show_speakers_in_draw: + cell['popover']['content'].append({'text': [" " + s.name for s in team.speakers]}) + if self._show_record_links: + cell['popover']['content'].append(self._team_record_link(team)) + return cell + + def _result_cell(self, ts, compress=False, show_score=False, show_ballots=False): + if not hasattr(ts, 'debate_team'): + return {'text': '-'} + + opp = ts.debate_team.opponent.team + + cell = { + 'text': " vs " + (opp.emoji or "…") if compress else opp.short_name, + 'popover': {'content': [{'text': ''}]} + } + result_popover = cell['popover']['content'][0] + if ts.win is True: + cell['icon'] = "glyphicon-arrow-up text-success" + cell['sort'] = 1 + result_popover['text'] = "Won against " + opp.long_name + elif ts.win is False: + cell['icon'] = "glyphicon-arrow-down text-danger" + cell['sort'] = 2 + result_popover['text'] = "Lost to " + opp.long_name + else: # None + cell['icon'] = "" + cell['sort'] = 3 + result_popover['text'] = "No result for debate against " + opp.long_name + + if show_score: + cell['subtext'] = metricformat(ts.score) + cell['popover']['content'].append( + {'text': 'Received %s team points' % metricformat(ts.score)}) + + if show_ballots: + cell['popover']['content'].append( + {'text': 'View Debate Ballot', 'link': reverse_tournament('public_ballots_view', + self.tournament, kwargs={'debate_id': ts.debate_team.debate.id})}) + + if self._show_speakers_in_draw: + cell['popover']['content'].append({'text': "Speakers in " + opp.short_name + ": " + ", ".join([s.name for s in opp.speakers])}) + + if self._show_record_links: + cell['popover']['content'].append( + self._team_record_link(opp)) + + return cell + + def add_round_column(self, rounds, key="Round"): + data = [{ + 'sort': round.seq, + 'text': round.abbreviation, + 'tooltip': round.name, + } for round in rounds] + self.add_column(key, data) + + def add_adjudicator_columns(self, adjudicators, hide_institution=False, + hide_metadata=False, subtext=None): + + adj_data = [] + for adj in adjudicators: + cell = {'text': adj.name} + if self._show_record_links: + cell['popover'] = {'content': [self._adjudicator_record_link(adj)]} + if subtext is 'institution': + cell['subtext'] = adj.institution.code + adj_data.append(cell) + self.add_column("Name", adj_data) + + if self.tournament.pref('show_institutions') and not hide_institution: + self.add_column({ + 'key': "Institution", + 'icon': 'glyphicon-home', + 'tooltip': "Institution", + }, [adj.institution.code for adj in adjudicators]) + + if not hide_metadata: + adjcore_header = { + 'key': 'adjcore', + 'tooltip': "Member of the Adjudication Core", + 'icon': 'glyphicon-sunglasses', + } + self.add_boolean_column(adjcore_header, [adj.adj_core for adj in adjudicators]) + + independent_header = { + 'key': 'independent', + 'tooltip': "Independent Adjudicator", + 'icon': 'glyphicon-knight', + } + self.add_boolean_column(independent_header, [adj.independent for adj in adjudicators]) + + if self.tournament.pref('show_unaccredited'): + accreddited_header = { + 'key': 'accredited', + 'tooltip': "Is Accredited", + 'icon': 'glyphicon-leaf', + } + self.add_boolean_column(accreddited_header, [adj.novice for adj in adjudicators]) + + def add_debate_adjudicators_column(self, debates, key="Adjudicators", show_splits=False, highlight_adj=None): + da_data = [] + + def construct_text(adjs_data): + adjs_list = [] + for a in adjs_data: + adj_str = a['adj'].name + symbol = self.ADJ_SYMBOLS.get(a['position']) + if symbol: + adj_str += " " + symbol + if a.get('split', False): + adj_str += " 💢" + if a['adj'] == highlight_adj: + adj_str = "" + adj_str + "" + adjs_list.append(adj_str) + return ', '.join(adjs_list) + + def construct_popover(adjs_data): + popover_data = [] + for a in adjs_data: + descriptors = [] + if a['position'] != AdjudicatorAllocation.POSITION_ONLY: + descriptors.append(self.ADJ_POSITION_NAMES[a['position']]) + descriptors.append("from %s" % a['adj'].institution.code) + if a.get('split', False): + descriptors.append("in minority") + + popover_data.append({'text': "%s (%s)" % (a['adj'].name, ", ".join(descriptors))}) + if self._show_record_links: + popover_data.append(self._adjudicator_record_link(a['adj'])) + + return popover_data + + for debate in debates: + adjs_data = [] + if show_splits and (self.admin or self.tournament.pref('show_splitting_adjudicators')) and debate.confirmed_ballot: + for adj, position, split in debate.confirmed_ballot.ballot_set.adjudicator_results: + adjs_data.append( + {'adj': adj, 'position': position, 'split': bool(split)}) + else: + for adj, position in debate.adjudicators.with_positions(): + adjs_data.append( + {'adj': adj, 'position': position}) + + if not debate.adjudicators.has_chair and debate.adjudicators.is_panel: + adjs_data[0]['type'] = 'O' + + da_data.append({ + 'text': construct_text(adjs_data), + 'popover': { + 'title': 'Debate Adjudicators', + 'content' : construct_popover(adjs_data) + } + }) + + self.add_column(key, da_data) + + def add_motion_column(self, motions, key="Motion", show_order=False): + if show_order and self.tournament.pref('enable_motions'): + self.add_column("Order", [{ + 'text': motion.seq, + 'sort': motion.round.seq + (motion.seq * 0.1) + } for motion in motions]) + + motion_data = [{ + 'text': motion.reference if motion.reference else '?', + 'popover': {'content' : [{'text': motion.text}]} + } if motion else "—" for motion in motions] + self.add_column(key, motion_data) + + def add_team_columns(self, teams, break_categories=False, hide_emoji=False, + show_divisions=True, hide_institution=False, key="Team"): + + if self.tournament.pref('enable_divisions') and show_divisions: + divisions_header = { + 'key': 'Division', + 'icon': 'glyphicon-th-list', + 'tooltip': 'Division' + } + divisions = ['D' + t.division.name if t.division else '' for t in teams] + self.add_column(divisions_header, divisions) + + team_data = [self._team_cell(team, hide_emoji=hide_emoji) + for team in teams] + self.add_column(key, team_data) + + if break_categories: + self.add_column("Categories", [", ".join(bc.name for bc in team.break_categories) for team in teams]) + + if self.tournament.pref('show_institutions') and not hide_institution: + self.add_column({ + 'key': "Institution", + 'icon': 'glyphicon-home', + 'tooltip': "Institution", + }, [team.institution.code for team in teams]) + + def add_team_pullup_columns(self, debates, standings): + pullups_header = { + 'key': "Pullups", + 'text': 'Pull', + 'tooltip': "Whether or not a team was a pull-up", + } + pullups_data = [] + for debate in debates: + a_team_standing = standings.get_standing(debate.aff_team) + a_is_pullup = abs(a_team_standing.metrics["points"] - debate.bracket) >= 1 + n_team_standing = standings.get_standing(debate.neg_team) + n_is_pullup = abs(n_team_standing.metrics["points"] - debate.bracket) >= 1 + text = 'Aff' if a_is_pullup else '' + text += 'Neg' if n_is_pullup else '' + pullups_data.append({ + 'sort': 1 if a_is_pullup or n_is_pullup else 0, + 'text': text + }) + self.add_column(pullups_header, pullups_data) + + def add_speaker_columns(self, speakers, key="Name"): + self.add_column(key, [speaker.name for speaker in speakers]) + if self.tournament.pref('show_novices'): + novice_header = { + 'key': "Novice", + 'icon': 'glyphicon-leaf', + 'tooltip': "Novice Status", + } + self.add_boolean_column(novice_header, [speaker.novice for speaker in speakers]) + + def add_room_rank_columns(self, debates): + header = { + 'key': "Room rank", + 'icon': 'glyphicon-stats', + 'tooltip': 'Room rank of this debate' + } + self.add_column(header, [debate.room_rank for debate in debates]) + + def add_debate_bracket_columns(self, debates): + header = { + 'key': "Bracket", + 'icon': 'glyphicon-stats', + 'tooltip': 'Bracket of this debate' + } + + def _fmt(x): + if int(x) == x: + return int(x) + return x + + self.add_column(header, [_fmt(debate.bracket) for debate in debates]) + + def add_debate_venue_columns(self, debates, with_times=True): + if self.tournament.pref('enable_divisions') and len(debates) > 0: + if debates[0].round.stage is debates[0].round.STAGE_PRELIMINARY: + divisions_header = { + 'key': 'Division', + 'icon': 'glyphicon-th-list', + 'tooltip': 'Division' + } + divisions_data = ['D' + d.division.name if d.division else '' for d in debates] + self.add_column(divisions_header, divisions_data) + + venue_header = { + 'key': "Venue", + 'icon': 'glyphicon-map-marker', + } + if self.tournament.pref('enable_venue_groups'): + venue_data = [ + debate.division.venue_group.short_name if debate.division + else (debate.venue.group.short_name + ' ' + debate.venue.name) if debate.venue and debate.venue.group + else debate.venue.name if debate.venue + else '' + for debate in debates + ] + else: + venue_data = [debate.venue.name if debate.venue else '' for debate in debates] + self.add_column(venue_header, venue_data) + + if with_times and self.tournament.pref('enable_debate_scheduling'): + times_headers = ["Date", "Time"] + times_data = [] + for debate in debates: + if debate.aff_team.type == Team.TYPE_BYE or debate.neg_team.type == Team.TYPE_BYE: + times_data.append(["", "Bye"]) + elif debate.result_status == Debate.STATUS_POSTPONED: + times_data.append(["", "Postponed"]) + elif debate.confirmed_ballot and debate.confirmed_ballot.forfeit: + times_data.append(["", "Forfeit"]) + else: + times_data.append([ + formats.date_format(debate.time, "D jS F"), + formats.date_format(debate.time, "h:i A")]) + self.add_columns(times_headers, times_data) + + def add_draw_conflicts_columns(self, debates): + venue_conflicts_by_debate = venue_conflicts_display(debates) + adjudicator_conflicts_by_debate = adjudicator_conflicts_display(debates) + conflicts_by_debate = [debate.draw_conflicts + adjudicator_conflicts_by_debate[debate] + venue_conflicts_by_debate[debate] + for debate in debates] + + conflicts_header = {'key': "Conflicts/Flags"} + conflicts_data = [{ + 'text': "
                  ".join(conflicts), + 'class': 'text-danger small' + } for conflicts in conflicts_by_debate] + self.add_column(conflicts_header, conflicts_data) + + def add_ranking_columns(self, standings, subset=None, prefix=' '): + standings_list = standings.get_standings(subset) if subset is not None else standings + headers = [{ + 'key': "%s" % (prefix[0] + info['abbr']).strip(), + 'tooltip': "%s" % (prefix + info['name']).title().strip(), + 'glyphicon': info['glyphicon'], + } for info in standings.rankings_info()] + data = [] + for standing in standings_list: + data.append([{ + 'text': rankingformat(ranking), + 'sort': ranking[0] or "99999", + } for ranking in standing.iterrankings()]) + self.add_columns(headers, data) + + def add_debate_ranking_columns(self, draw, standings): + # First half (ie all aff metrics) then second (ie all neg metrics) + self.add_ranking_columns(standings, subset=[d.aff_team for d in draw], prefix="Aff's ") + self.add_ranking_columns(standings, subset=[d.neg_team for d in draw], prefix="Neg's ") + + def add_metric_columns(self, standings, subset=None, prefix=' '): + standings_list = standings.get_standings(subset) if subset is not None else standings + headers = [{ + 'key': prefix[0] + info['abbr'], + 'tooltip': prefix + info['name'].title(), + 'glyphicon': info['glyphicon'], + } for info in standings.metrics_info()] + data = [list(map(metricformat, s.itermetrics())) for s in standings_list] + self.add_columns(headers, data) + + def add_debate_metric_columns(self, draw, standings): + # First half (ie all aff metrics) then second (ie all neg metrics) + self.add_metric_columns(standings, subset=[d.aff_team for d in draw], prefix="Aff's ") + self.add_metric_columns(standings, subset=[d.neg_team for d in draw], prefix="Neg's ") + + def highlight_rows_by_column_value(self, column): + highlighted_rows = [i for i in range(1, len(self.data)) + if self.data[i][column] != self.data[i-1][column]] + for i in highlighted_rows: + self.data[i] = [self._convert_cell(cell) for cell in self.data[i]] + for cell in self.data[i]: + cell['class'] = cell.get('class', '') + ' highlight-row' + + def add_sides_count(self, teams, round, team_type): + sides_counts = get_side_counts(teams, DebateTeam.POSITION_AFFIRMATIVE, round.seq) + if team_type is 'aff': + side_label = "affirmative" + side_key = "aaffs" + else: + side_label = "negative" + side_key = "naffs" + sides_header = { + 'key': side_key, + 'tooltip': 'Number of times the current ' + team_type + + ' has been in the ' + side_label + ' position before' + } + sides_data = [{ + 'text': str(sides_counts[t.id]), + } for t in teams] + self.add_column(sides_header, sides_data) + + def add_checkbox_columns(self, states, references, key): + state_header = {'key': key} + state_data = [{ + 'sort': state, + 'class': 'checkbox-target', + 'text': '' % (reference, 'checked' if state else ''), + } for state, reference in zip(states, references)] + self.add_column(state_header, state_data) + + def add_debate_ballot_link_column(self, debates): + ballot_links_header = {'key': "Ballot", 'icon': 'glyphicon-search'} + + if self.admin: + ballot_links_data = [{ + 'text': "View/Edit Ballot", + 'link': reverse_tournament('edit_ballotset', self.tournament, kwargs={'ballotsub_id': debate.confirmed_ballot.id}) + } if debate.confirmed_ballot else "" for debate in debates] + self.add_column(ballot_links_header, ballot_links_data) + + elif self.tournament.pref('ballots_released'): + ballot_links_header = {'key': "Ballot", 'icon': 'glyphicon-search'} + ballot_links_data = [{ + 'text': "View Ballot", + 'link': reverse_tournament('public_ballots_view', self.tournament, kwargs={'debate_id': debate.id}) + } if debate else "" for debate in debates] + self.add_column(ballot_links_header, ballot_links_data) + + def add_debate_result_by_team_columns(self, teamscores): + """Takes an iterable of TeamScore objects.""" + + results_data = [self._result_cell(ts) for ts in teamscores] + self.add_column("Result", results_data) + self.add_column("Side", [ts.debate_team.get_position_display() for ts in teamscores]) + + def add_team_results_columns(self, teams, rounds): + """ Takes an iterable of Teams, assumes their round_results match rounds""" + for round_seq, round in enumerate(rounds): + results = [self._result_cell( + t.round_results[round_seq]) for t in teams] + self.add_column(round.abbreviation, results) + + def add_debate_results_columns(self, debates): + results_data = [] + for debate in debates: + row = [] + for pos in ('aff', 'neg'): + try: + debateteam = debate.get_dt(pos) + team = debate.get_team(pos) + except DebateTeam.DoesNotExist: + row.append("-") + continue + + cell = self._team_cell(team, hide_emoji=True) + + if debateteam.win is True: + cell['popover']['title'] += "—won" + cell['icon'] = "glyphicon-arrow-up text-success" + elif debateteam.win is False: + cell['popover']['title'] += "—lost" + cell['icon'] = "glyphicon-arrow-down text-danger" + else: # None + cell['popover']['title'] += "—no result" + cell['icon'] = "" + + row.append(cell) + results_data.append(row) + + self.add_columns(["Affirmative", "Negative"], results_data) + + def add_standings_results_columns(self, standings, rounds, show_ballots): + + for round_seq, round in enumerate(rounds): + results = [self._result_cell( + s.round_results[round_seq], + compress=True, + show_score=True, + show_ballots=show_ballots + ) for s in standings] + self.add_column(round.abbreviation, results) diff --git a/tabbycat/utils/templatetags/__init__.py b/tabbycat/utils/templatetags/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/utils/templatetags/add_field_css.py b/tabbycat/utils/templatetags/add_field_css.py similarity index 100% rename from utils/templatetags/add_field_css.py rename to tabbycat/utils/templatetags/add_field_css.py diff --git a/utils/templatetags/debate_tags.py b/tabbycat/utils/templatetags/debate_tags.py similarity index 79% rename from utils/templatetags/debate_tags.py rename to tabbycat/utils/templatetags/debate_tags.py index eacc4f73c62..c571947b777 100644 --- a/utils/templatetags/debate_tags.py +++ b/tabbycat/utils/templatetags/debate_tags.py @@ -1,20 +1,18 @@ +import os +import re + from django import template -from django.utils.encoding import force_text from django.conf import settings from django.core.urlresolvers import reverse -from participants.emoji import EMOJI_LIST - -import re -import os register = template.Library() - STATIC_PATH = settings.MEDIA_ROOT version_cache = {} rx = re.compile(r'^(.*)\.(.*?)$') +@register.simple_tag def version(path_string, base_url=settings.MEDIA_URL): if not hasattr( @@ -35,36 +33,8 @@ def version(path_string, base_url=settings.MEDIA_URL): return base_url + path_string -register.simple_tag(version) - - -def aff_count(team, round): - if round is None: - return 0 - return team.get_aff_count(round.seq) - -register.simple_tag(aff_count) - - -def neg_count(team, round): - if round is None: - return 0 - return team.get_neg_count(round.seq) - -register.simple_tag(neg_count) - - - -@register.filter -def break_rank(team, round): - rank = team.break_rank_for_category(round.break_category) - if rank: - return "(Broke %s)" % rank - else: - return None - -register.simple_tag(break_rank) - +# TODO: deprecate when old allocations UI is +@register.simple_tag def team_status_classes(team): classes = list() if team.region is not None: @@ -74,9 +44,7 @@ def team_status_classes(team): return " ".join(classes) -register.simple_tag(team_status_classes) - - +@register.simple_tag def debate_draw_status_class(debate): if debate.aff_team.type == 'B' or debate.neg_team.type == 'B': return "active text-muted" @@ -87,9 +55,6 @@ def debate_draw_status_class(debate): return "active text-muted" -register.simple_tag(debate_draw_status_class) - - class RoundURLNode(template.Node): def __init__(self, view_name, round=None): self.view_name = view_name @@ -170,18 +135,17 @@ def times(number): return list(range(number)) -def divide(numberA, numberB): - return numberA / numberB - - -register.simple_tag(divide) +@register.simple_tag +def divide_to_int(number_a, number_b): + try: + return int(int(number_a) / int(number_b)) + except (ValueError, ZeroDivisionError): + return None -def percentage(numberA, numberB): - if numberB > 0: - return numberA / numberB * 100 +@register.simple_tag +def percentage(number_a, number_b): + if number_b > 0: + return number_a / number_b * 100 else: return 0 - - -register.simple_tag(percentage) diff --git a/tabbycat/utils/tests.py b/tabbycat/utils/tests.py new file mode 100644 index 00000000000..0e85fa4d42a --- /dev/null +++ b/tabbycat/utils/tests.py @@ -0,0 +1,122 @@ +import json +import logging + +from django.core.urlresolvers import reverse +from django.test import Client, TestCase + +from tournaments.models import Tournament +from participants.models import Adjudicator, Institution, Speaker, Team +from venues.models import Venue + + +class BaseTableViewTest(): + """Base class for testing table views; provides a default fixture and + methods for setting tournament/clients and validating data. If inheriting + classes are validating data they should overwrite table_data methods""" + + fixtures = ['completed_demo.json'] + view_name = None + round_seq = None + + def setUp(self): + self.t = Tournament.objects.first() + self.client = Client() + + def get_response(self): + if self.round_seq is not None: + return self.client.get(reverse(self.view_name, kwargs={ + 'tournament_slug': self.t.slug, 'round_seq': self.round_seq})) + else: + return self.client.get(reverse(self.view_name, kwargs={ + 'tournament_slug': self.t.slug})) + + def validate_table_data(self, r): + + if 'tableData' in r.context and self.table_data(): + data = len(json.loads(r.context['tableData'])) + self.assertEqual(self.table_data(), data) + + if 'tableDataA' in r.context and self.table_data_a(): + data_a = len(json.loads(r.context['tableDataA'])) + self.assertEqual(self.table_data_a(), data_a) + + if 'tableDataB' in r.context and self.table_data_b(): + data_b = len(json.loads(r.context['tableDataB'])) + self.assertEqual(self.table_data_b(), data_b) + + def table_data(self): + return False + + def table_data_a(self): + return False + + def table_data_b(self): + return False + + +class TableViewTest(BaseTableViewTest): + """For testing a view class that is always available. Inheriting classes + must also inherit from TestCase""" + + def test(self): + response = self.get_response() + # 200 OK should be issued if setting is not enabled + self.assertEqual(response.status_code, 200) + self.validate_table_data(response) + + +class ConditionalTableViewTest(BaseTableViewTest): + """For testing a view class that is conditionally shown depending on a + preference being set or not. Inheriting classes must also inherit from + TestCase and provide a view_toggle as a dynamic preferences path""" + + view_toggle = None + + def test_set_preference(self): + # Check a page IS resolving when the preference is set + self.t.preferences[self.view_toggle] = True + response = self.get_response() + + # 200 OK should be issued if setting is not enabled + self.assertEqual(response.status_code, 200) + self.validate_table_data(response) + + def test_unset_preference(self): + # Check a page is not resolving when the preference is not set + self.t.preferences[self.view_toggle] = False + + # Disable logging to silence the admin-page-only warning + logging.disable(logging.CRITICAL) + response = self.get_response() + logging.disable(logging.NOTSET) + + # 302 redirect shoould be issued if setting is not enabled + self.assertEqual(response.status_code, 302) + + +class BaseDebateTestCase(TestCase): + """Currently used in availability and participants tests as a pseudo fixture + to create teh basic data to simulate simple tournament functions""" + + def setUp(self): + super(BaseDebateTestCase, self).setUp() + # add test models + self.t = Tournament.objects.create(slug="tournament") + for i in range(4): + ins = Institution.objects.create(code="INS%s" % i, name="Institution %s" % i) + for j in range(3): + t = Team.objects.create(tournament=self.t, institution=ins, + reference="Team%s%s" % (i, j)) + for k in range(2): + Speaker.objects.create(team=t, name="Speaker%s%s%s" % (i, j, k)) + for j in range(2): + Adjudicator.objects.create(tournament=self.t, institution=ins, + name="Adjudicator%s%s" % (i, j), test_score=0) + + for i in range(8): + Venue.objects.create(name="Venue %s" % i, priority=i) + Venue.objects.create(name="IVenue %s" % i, priority=i) + + def tearDown(self): + self.t.delete() + Institution.objects.all().delete() diff --git a/utils/urlkeys.py b/tabbycat/utils/urlkeys.py similarity index 82% rename from utils/urlkeys.py rename to tabbycat/utils/urlkeys.py index 1c43f653e82..ed97e151d42 100644 --- a/utils/urlkeys.py +++ b/tabbycat/utils/urlkeys.py @@ -1,34 +1,36 @@ -import string -import random import logging +import random +import string + from django.db import IntegrityError + logger = logging.getLogger(__name__) def generate_url_key(length=8): """Generates a randomised URL key.""" - chars = string.ascii_lowercase + string.ascii_uppercase + string.digits + chars = string.ascii_lowercase + string.digits return ''.join(random.SystemRandom().choice(chars) for _ in range(length)) def populate_url_keys(queryset, length=8): """Populates the URL key field for every instance in the given QuerySet.""" - NUM_ATTEMPTS = 10 + num_attempts = 10 for instance in queryset: - for i in range(NUM_ATTEMPTS): + for i in range(num_attempts): instance.url_key = generate_url_key(length) try: instance.save() except IntegrityError: logger.warning( "URL key was not unique, trying again (%d of %d", i, - NUM_ATTEMPTS) + num_attempts) continue else: break else: logger.error("Could not generate unique URL for %r after %d tries", - instance, NUM_ATTEMPTS) + instance, num_attempts) return diff --git a/utils/views.py b/tabbycat/utils/views.py similarity index 79% rename from utils/views.py rename to tabbycat/utils/views.py index 2e85b2a13bc..63ee4929a3f 100644 --- a/utils/views.py +++ b/tabbycat/utils/views.py @@ -2,23 +2,19 @@ should use the Django class-based views framework, and use the mixins in mixins.py (in this directory) instead. """ - -from django.contrib.auth.decorators import user_passes_test, login_required -from django.contrib import messages -from django.conf import settings -from django.http import Http404, HttpResponseRedirect, HttpResponse, HttpResponseBadRequest -from django.template import RequestContext -from django.shortcuts import render, redirect, get_object_or_404 -from django.views.decorators.cache import cache_page -from django.core.cache import cache - from functools import wraps from warnings import warn + +from django.contrib.auth.decorators import user_passes_test +from django.http import HttpResponseBadRequest +from django.shortcuts import redirect + from .misc import get_ip_address as misc_get_ip_address from .misc import redirect_tournament as misc_redirect_tournament + def get_ip_address(request): - warn("utils.views.get_ip_address is deprecated, import from utils.misc instead") + warn("utils.views.get_ip_address is deprecated, import from utils.misc instead", stacklevel=2) return misc_get_ip_address(request) @@ -35,7 +31,7 @@ def foo(request, tournament_slug, *args, **kwargs): def redirect_tournament(to, tournament, **kwargs): - warn("utils.views.redirect_tournament is deprecated, import from utils.misc instead") + warn("utils.views.redirect_tournament is deprecated, import from utils.misc instead", stacklevel=2) return misc_redirect_tournament(to, tournament, **kwargs) @@ -65,11 +61,9 @@ def foo(request, tournament, round_seq, *args, **kwargs): def redirect_round(to, round, **kwargs): - warn("utils.views.redirect_round is deprecated, import from utils.misc instead") - return redirect(to, - tournament_slug=round.tournament.slug, - round_seq=round.seq, - *kwargs) + warn("utils.views.redirect_round is deprecated, import from utils.misc instead", stacklevel=2) + return redirect(to, tournament_slug=round.tournament.slug, + round_seq=round.seq, *kwargs) def public_optional_round_view(preference_option): @@ -96,4 +90,3 @@ def foo(request, *args, **kwargs): return view_fn(request, *args, **kwargs) return foo - diff --git a/tabbycat/venues/__init__.py b/tabbycat/venues/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/venues/admin.py b/tabbycat/venues/admin.py similarity index 61% rename from venues/admin.py rename to tabbycat/venues/admin.py index c371ba0936f..01fcb2c72f5 100644 --- a/venues/admin.py +++ b/tabbycat/venues/admin.py @@ -1,7 +1,8 @@ from django.contrib import admin -from .models import (VenueGroup, Venue, TeamVenueConstraint, - AdjudicatorVenueConstraint, InstitutionVenueConstraint, DivisionVenueConstraint) +from .models import ( + AdjudicatorVenueConstraint, DivisionVenueConstraint, + InstitutionVenueConstraint, TeamVenueConstraint, Venue, VenueGroup) class VenueGroupAdmin(admin.ModelAdmin): @@ -13,10 +14,16 @@ class VenueGroupAdmin(admin.ModelAdmin): class VenueAdmin(admin.ModelAdmin): - list_display = ('name', 'group', 'priority', 'tournament') + list_display = ('name', 'group_name', 'priority', 'tournament') list_filter = ('group', 'priority', 'tournament') search_fields = ('name',) + def group_name(self, obj): + if obj.group is None: + return None + return obj.group.name + group_name.short_description = 'Venue Group' + def get_queryset(self, request): return super(VenueAdmin, self).get_queryset(request).select_related('group') @@ -31,16 +38,23 @@ def get_queryset(self, request): class BaseVenueConstraintAdmin(admin.ModelAdmin): associate_field = None + associate_search_fields = () - common_list_display = ('venue_group', 'priority') - common_search_fields = ('venue_group', 'priority') + common_list_display = ('group_name', 'priority') + common_search_fields = ('venue_group__name', 'venue_group__short_name', 'priority') common_list_filter = ('venue_group', 'priority') + def group_name(self, obj): + if obj.venue_group is None: + return None + return obj.venue_group.name + group_name.short_description = 'Venue Group' + def get_list_display(self, request): return (self.associate_field,) + self.common_list_display def get_search_fields(self, request): - return (self.associate_field,) + self.common_search_fields + return self.associate_search_fields + self.common_search_fields def get_list_filter(self, request): return (self.associate_field,) + self.common_list_filter @@ -53,18 +67,22 @@ def raw_id_fields(self): @admin.register(TeamVenueConstraint) class TeamVenueConstraintAdmin(BaseVenueConstraintAdmin): associate_field = 'team' + associate_search_fields = ('team__short_name', 'team__long_name') @admin.register(AdjudicatorVenueConstraint) class AdjudicatorVenueConstraintAdmin(BaseVenueConstraintAdmin): associate_field = 'adjudicator' + associate_search_fields = ('adjudicator__name',) @admin.register(InstitutionVenueConstraint) class InstitutionVenueConstraintAdmin(BaseVenueConstraintAdmin): associate_field = 'institution' + associate_search_fields = ('institution__name', 'institution__code') @admin.register(DivisionVenueConstraint) class DivisionVenueConstraintAdmin(BaseVenueConstraintAdmin): - associate_field = 'division' \ No newline at end of file + associate_field = 'division' + associate_search_fields = ('division__name',) diff --git a/venues/allocator.py b/tabbycat/venues/allocator.py similarity index 78% rename from venues/allocator.py rename to tabbycat/venues/allocator.py index 1dad3539a07..9013d3b9c14 100644 --- a/venues/allocator.py +++ b/tabbycat/venues/allocator.py @@ -1,13 +1,16 @@ import logging import random + +from .models import AdjudicatorVenueConstraint, InstitutionVenueConstraint, TeamVenueConstraint + logger = logging.getLogger(__name__) -from .models import TeamVenueConstraint, AdjudicatorVenueConstraint, InstitutionVenueConstraint def allocate_venues(round, debates=None): allocator = VenueAllocator() allocator.allocate(round, debates) + class VenueAllocator: """Allocates venues in a draw to satisfy, as best it can, applicable venue constraints. @@ -21,7 +24,7 @@ class VenueAllocator: def allocate(self, round, debates=None): if debates is None: - debates = round.get_draw() + debates = round.debate_set_with_prefetches(speakers=False) self._all_venues = list(round.active_venues.order_by('-priority')) self._preferred_venues = self._all_venues[:len(debates)] @@ -32,6 +35,10 @@ def allocate(self, round, debates=None): unconstrained_venues = self.allocate_unconstrained_venues(unconstrained_debates) debate_venues.update(unconstrained_venues) + # this set is only non-empty if there were too few venues overall + debates_without_venues = [d for d in debates if d not in debate_venues] + debate_venues.update({debate: None for debate in debates_without_venues}) + self.save_venues(debate_venues) def collect_constraints(self, debates): @@ -49,7 +56,7 @@ def collect_constraints(self, debates): for debate in debates: teams = list(debate.teams) - adjudicators = [da[1] for da in debate.adjudicators] + adjudicators = [da for da in debate.adjudicators.all()] constraints = [] constraints.extend(TeamVenueConstraint.objects.filter(team__in=teams)) @@ -61,7 +68,9 @@ def collect_constraints(self, debates): if len(constraints) > 0: constraints.sort(key=lambda x: x.priority, reverse=True) debate_constraints.append((debate, constraints)) - logger.info("Constraints on {}: {}".format(debate, constraints)) + logger.info("Constraints on %s: %s", debate, constraints) + + debate_constraints.sort(key=lambda x: x[1][0].priority, reverse=True) return debate_constraints @@ -90,14 +99,16 @@ def allocate_constrained_venues(self, debate_constraints): # If we can't fulfil the highest constraint, bump it down the list. if len(eligible_venues) == 0: - logger.debug("Unfilfilled (highest): {}".format(highest_constraint)) + logger.debug("Unfilfilled (highest): %s", highest_constraint) if len(constraints) == 0: - logger.debug("{} is now unconstrained".format(debate)) - continue # failed all constraints, debate is now unconstrained + logger.debug("%s is now unconstrained", debate) + continue # Failed all constraints, debate is now unconstrained new_priority = constraints[0].priority for i, dc in enumerate(debate_constraints): if new_priority >= dc[1][0].priority: break + else: + i = 0 debate_constraints.insert(i, (debate, constraints)) continue @@ -107,10 +118,10 @@ def allocate_constrained_venues(self, debate_constraints): satisified_constraints = [] for constraint in constraints: if any(sc.subject == constraint.subject for sc in satisified_constraints): - continue # skip if we've already done a constraint for this team/adj/inst/div + continue # Skip if we've already done a constraint for this team/adj/inst/div constraint_venues = set(constraint.venue_group.venues) if eligible_venues.isdisjoint(constraint_venues): - logger.debug("Unfilfilled: {}".format(constraint)) + logger.debug("Unfilfilled: %s", constraint) else: eligible_venues &= constraint_venues satisified_constraints.append(constraint) @@ -118,7 +129,7 @@ def allocate_constrained_venues(self, debate_constraints): # If no eligible venues are preferred venues, drop the last preferred venue. preferred_venues = set(self._preferred_venues) if eligible_venues.isdisjoint(preferred_venues): - logger.debug("No preferred venues available: {}".format(debate)) + logger.debug("No preferred venues available: %s", debate) self._preferred_venues = self._preferred_venues[:-1] else: eligible_venues &= preferred_venues @@ -129,7 +140,7 @@ def allocate_constrained_venues(self, debate_constraints): self._all_venues.remove(venue) if venue in self._preferred_venues: self._preferred_venues.remove(venue) - logger.debug("Assigning {} to {}".format(venue, debate)) + logger.debug("Assigning %s to %s", venue, debate) return debate_venues @@ -137,14 +148,16 @@ def allocate_unconstrained_venues(self, debates): """Allocates unconstrained venues by randomly shuffling the remaining preferred venues.""" - assert len(self._preferred_venues) == len(debates), "{:d} preferred venues " \ - "but {:d} debates".format(len(self._preferred_venues), len(debates)) + if len(self._preferred_venues) != len(debates): + logger.critical("preferred venues to unconstrained debates mismatch: " + "%s preferred venues, %d debates", len(self._preferred_venues), len(debates)) + # we'll still keep going, since zip() stops at the end of the shorter list random.shuffle(debates) return {debate: venue for debate, venue in zip(debates, self._preferred_venues)} def save_venues(self, debate_venues): for debate, venue in debate_venues.items(): - logger.debug("Saving {} for {}".format(venue, debate)) + logger.debug("Saving %s for %s", venue, debate) debate.venue = venue debate.save() diff --git a/venues/management/commands/allocatevenues.py b/tabbycat/venues/management/commands/allocatevenues.py similarity index 83% rename from venues/management/commands/allocatevenues.py rename to tabbycat/venues/management/commands/allocatevenues.py index 47b51ae91be..8da74ddf23e 100644 --- a/venues/management/commands/allocatevenues.py +++ b/tabbycat/venues/management/commands/allocatevenues.py @@ -1,6 +1,8 @@ -from utils.management.base import RoundCommand, CommandError +from utils.management.base import RoundCommand + from ...allocator import allocate_venues + class Command(RoundCommand): help = "Assigns venues for all debates in a round (or rounds)." diff --git a/venues/migrations/0001_initial.py b/tabbycat/venues/migrations/0001_initial.py similarity index 100% rename from venues/migrations/0001_initial.py rename to tabbycat/venues/migrations/0001_initial.py diff --git a/venues/migrations/0002_auto_20160109_1834.py b/tabbycat/venues/migrations/0002_auto_20160109_1834.py similarity index 100% rename from venues/migrations/0002_auto_20160109_1834.py rename to tabbycat/venues/migrations/0002_auto_20160109_1834.py diff --git a/venues/migrations/0003_auto_20160201_2012.py b/tabbycat/venues/migrations/0003_auto_20160201_2012.py similarity index 100% rename from venues/migrations/0003_auto_20160201_2012.py rename to tabbycat/venues/migrations/0003_auto_20160201_2012.py diff --git a/venues/migrations/0004_auto_20160228_1838.py b/tabbycat/venues/migrations/0004_auto_20160228_1838.py similarity index 100% rename from venues/migrations/0004_auto_20160228_1838.py rename to tabbycat/venues/migrations/0004_auto_20160228_1838.py diff --git a/venues/migrations/0005_remove_venue_time.py b/tabbycat/venues/migrations/0005_remove_venue_time.py similarity index 100% rename from venues/migrations/0005_remove_venue_time.py rename to tabbycat/venues/migrations/0005_remove_venue_time.py diff --git a/venues/migrations/0006_auto_20160507_1521.py b/tabbycat/venues/migrations/0006_auto_20160507_1521.py similarity index 100% rename from venues/migrations/0006_auto_20160507_1521.py rename to tabbycat/venues/migrations/0006_auto_20160507_1521.py diff --git a/venues/migrations/0007_adjudicatorvenueconstraint_divisionvenueconstraint_institutionvenueconstraint_teamvenueconstraint.py b/tabbycat/venues/migrations/0007_adjudicatorvenueconstraint_divisionvenueconstraint_institutionvenueconstraint_teamvenueconstraint.py similarity index 100% rename from venues/migrations/0007_adjudicatorvenueconstraint_divisionvenueconstraint_institutionvenueconstraint_teamvenueconstraint.py rename to tabbycat/venues/migrations/0007_adjudicatorvenueconstraint_divisionvenueconstraint_institutionvenueconstraint_teamvenueconstraint.py diff --git a/tabbycat/venues/migrations/0008_auto_20160621_1129.py b/tabbycat/venues/migrations/0008_auto_20160621_1129.py new file mode 100644 index 00000000000..6b1435fc67a --- /dev/null +++ b/tabbycat/venues/migrations/0008_auto_20160621_1129.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-06-21 11:29 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('venues', '0007_adjudicatorvenueconstraint_divisionvenueconstraint_institutionvenueconstraint_teamvenueconstraint'), + ] + + operations = [ + migrations.AlterField( + model_name='divisionvenueconstraint', + name='division', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='divisions.Division'), + ), + ] diff --git a/tabbycat/venues/migrations/__init__.py b/tabbycat/venues/migrations/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/venues/models.py b/tabbycat/venues/models.py similarity index 83% rename from venues/models.py rename to tabbycat/venues/models.py index da7d3dad4ef..bea4ef57359 100644 --- a/venues/models.py +++ b/tabbycat/venues/models.py @@ -7,8 +7,7 @@ class VenueGroup(models.Model): team_capacity = models.IntegerField( blank=True, null=True, - help_text= - "The greatest possible number of teams that can debate in this venue group") + help_text="The greatest possible number of teams that can debate in this venue group") @property def divisions_count(self): @@ -29,9 +28,10 @@ class Venue(models.Model): name = models.CharField(max_length=40) group = models.ForeignKey(VenueGroup, blank=True, null=True) priority = models.IntegerField( - help_text="Venues with a higher priority number will be preferred in the draw") - tournament = models.ForeignKey('tournaments.Tournament', blank=True, null=True, db_index=True, - help_text="Venues not assigned to any tournament can be shared between tournaments") + help_text="Venues with a higher priority number will be preferred in the draw") + tournament = models.ForeignKey( + 'tournaments.Tournament', blank=True, null=True, db_index=True, + help_text="Venues not assigned to any tournament can be shared between tournaments") class Meta: ordering = ['group', 'name'] @@ -90,7 +90,7 @@ def subject(self): class DivisionVenueConstraint(BaseVenueConstraint): - division = models.ForeignKey('tournaments.Division') + division = models.ForeignKey('divisions.Division') @property def subject(self): diff --git a/tabbycat/venues/templates/venues_edit.html b/tabbycat/venues/templates/venues_edit.html new file mode 100644 index 00000000000..70aa15febf6 --- /dev/null +++ b/tabbycat/venues/templates/venues_edit.html @@ -0,0 +1,221 @@ +{% extends "base.html" %} +{% load static %} +{% load debate_tags %} + +{% block nav %}
                  {% endblock %} +{% block footer %}{% endblock %} + +{% block head-title %}Edit Venues for {{ round.abbreviation }}{% endblock %} +{% block page-title %}Edit Venues for {{ round.abbreviation }}{% endblock %} +{% block page-subnav-sections %} + Save Venues +
                  + {% csrf_token %} + + + Quit +{% endblock %} + +{% block extra-css %} + +{% endblock extra-css %} + +{% block content %} +
                  + +
                  +
                  Team
                  + + + + + + + +
                  Unused Venues
                  + {% for venue in round.unused_venues %} +
                  + {{ venue }} +
                  + {% endfor %} +
                  + +
                  + + {% with ndebates=round.debate_set.count nvenues=round.active_venues.count %} + {% if ndebates > nvenues %} +
                  + There are {{ ndebates }} debates in this round but only {{ nvenues }} venues. + + Check in more venues. +
                  + {% endif %} + {% endwith %} + +
                  + +
                  +
                  + + + + + {% if pref.enable_debate_scheduling %} + + {% endif %} + + + + + + + + {% for debate in draw %} + + + {% if pref.enable_debate_scheduling %} + + {% endif %} + + + {% include "tables/debate_adjudicators_compact.html" %} + + + {% endfor %} + +
                  TimeAffNegAdjsVenue
                  {{ debate.bracket }} + {% if debate.time %} + + {{ debate.time|time:'h:i A' }}
                  {{ debate.time|date:"D jS F" }} + {% endif %} +
                  + {% include "tables/team.html" with team=debate.aff_team %} + + {% include "tables/team.html" with team=debate.neg_team %} + + {% if debate.venue %} +
                  + {{ debate.venue }} +
                  + {% endif %} +
                  +
                  +
                  +
                  + +
                  +{% endblock content %} + +{% block js %} + {{ block.super }} + + + +{% endblock js %} \ No newline at end of file diff --git a/venues/urls_admin.py b/tabbycat/venues/urls_admin.py similarity index 99% rename from venues/urls_admin.py rename to tabbycat/venues/urls_admin.py index 7f80e2e0be6..d8d1f6f715d 100644 --- a/venues/urls_admin.py +++ b/tabbycat/venues/urls_admin.py @@ -12,4 +12,4 @@ url(r'^round/(?P\d+)/autoallocate/$', views.AutoAllocateVenuesView.as_view(), name='venues-auto-allocate'), -] \ No newline at end of file +] diff --git a/tabbycat/venues/utils.py b/tabbycat/venues/utils.py new file mode 100644 index 00000000000..9a3e50ca1ba --- /dev/null +++ b/tabbycat/venues/utils.py @@ -0,0 +1,41 @@ +from venues.models import AdjudicatorVenueConstraint, InstitutionVenueConstraint, TeamVenueConstraint + + +def _constraints_satisfied(constraints_dict, key, venue): + if key not in constraints_dict: + return True + constraints = constraints_dict[key] + return any(constraint.venue_group_id == venue.group_id for constraint in constraints) + + +def venue_conflicts_display(debates): + """Returns a dict mapping elements (debates) in `debates` to a list of + strings of explaining unfulfilled venue constraints for participants that + debate. A venue constraint (or more precisely, a set of venue constraints + relating to a single participant) is "unfulfilled" if the relevant + participant had constraints and *none* of their constraints were met.""" + + teamconstraints = {} + for constraint in TeamVenueConstraint.objects.filter(team__debateteam__debate__in=debates).distinct(): + teamconstraints.setdefault(constraint.team_id, []).append(constraint) + instconstraints = {} + for constraint in InstitutionVenueConstraint.objects.filter(institution__team__debateteam__debate__in=debates).distinct(): + instconstraints.setdefault(constraint.institution_id, []).append(constraint) + adjconstraints = {} + for constraint in AdjudicatorVenueConstraint.objects.filter(adjudicator__debateadjudicator__debate__in=debates).distinct(): + adjconstraints.setdefault(constraint.adjudicator_id, []).append(constraint) + + conflict_messages = {debate: [] for debate in debates} + for debate in debates: + venue = debate.venue + for team in debate.teams: + if not _constraints_satisfied(teamconstraints, team.id, venue): + conflict_messages[debate].append("Venue does not meet constraints of {}".format(team.short_name)) + if not _constraints_satisfied(instconstraints, team.institution_id, venue): + conflict_messages[debate].append("Venue does not meet constraints of institution {} ({})".format(team.institution.code, team.short_name)) + + for adjudicator in debate.adjudicators.all(): + if not _constraints_satisfied(adjconstraints, adjudicator.id, venue): + conflict_messages[debate].append("Venue does not meet constraints of {}".format(adjudicator.name)) + + return conflict_messages diff --git a/venues/views.py b/tabbycat/venues/views.py similarity index 82% rename from venues/views.py rename to tabbycat/venues/views.py index 7774c08f12d..f488b725b44 100644 --- a/venues/views.py +++ b/tabbycat/venues/views.py @@ -1,31 +1,29 @@ -from django.views.generic.base import TemplateView from django.http import HttpResponse +from django.views.generic import TemplateView, View from actionlog.mixins import LogActionMixin from actionlog.models import ActionLogEntry from draw.models import Debate from tournaments.mixins import RoundMixin -from utils.mixins import SuperuserRequiredMixin, PostOnlyRedirectView -from utils.misc import reverse_round +from utils.mixins import PostOnlyRedirectView, SuperuserRequiredMixin -from .models import Venue from .allocator import allocate_venues +from .models import Venue + class EditVenuesView(SuperuserRequiredMixin, RoundMixin, TemplateView): template_name = "venues_edit.html" def get_context_data(self, **kwargs): - kwargs['draw'] = self.get_round().get_draw() + kwargs['draw'] = self.get_round().debate_set_with_prefetches(speakers=False) return super().get_context_data(**kwargs) class AutoAllocateVenuesView(LogActionMixin, SuperuserRequiredMixin, RoundMixin, PostOnlyRedirectView): action_log_type = ActionLogEntry.ACTION_TYPE_VENUES_AUTOALLOCATE - - def get_redirect_url(self): - return reverse_round('venues-edit', self.get_round()) + round_redirect_pattern_name = 'venues-edit' def post(self, request, *args, **kwargs): allocate_venues(self.get_round()) @@ -33,7 +31,7 @@ def post(self, request, *args, **kwargs): return super().post(request, *args, **kwargs) -class SaveVenuesView(LogActionMixin, SuperuserRequiredMixin, RoundMixin, PostOnlyRedirectView): +class SaveVenuesView(LogActionMixin, SuperuserRequiredMixin, RoundMixin, View): action_log_type = ActionLogEntry.ACTION_TYPE_VENUES_SAVE diff --git a/wsgi.py b/tabbycat/wsgi.py similarity index 99% rename from wsgi.py rename to tabbycat/wsgi.py index 400df62d3dd..769f6981e58 100644 --- a/wsgi.py +++ b/tabbycat/wsgi.py @@ -1,13 +1,15 @@ -# Needed for WSGI Callable import os + +from django.core.cache.backends.memcached import BaseMemcachedCache +from django.core.wsgi import get_wsgi_application + +# Needed for WSGI Callable os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") # Needed for waitress/gunicorn serving -from django.core.wsgi import get_wsgi_application application = get_wsgi_application() # Fix django closing connection to MemCachier after every request (#11331) # Added as per: # https://devcenter.heroku.com/articles/django-memcache#optimize-performance -from django.core.cache.backends.memcached import BaseMemcachedCache BaseMemcachedCache.close = lambda self, **kwargs: None diff --git a/templates/base.html b/templates/base.html deleted file mode 100644 index ec6893022b7..00000000000 --- a/templates/base.html +++ /dev/null @@ -1,151 +0,0 @@ -{% load static %}{% load debate_tags %} - - - - - - - {% block page-title %}{% endblock %} - - - - {% block extra-css %}{% endblock %} - - - - - - - -{% block body %} - - {% block nav %} - {% if 'admin/' in request.path and user.is_superuser %} - {% include "nav/admin_nav.html" %} - - {% endif %} - - {% endblock body %} - - - - - - - {% block extra-js %}{% endblock extra-js %} - - - {% if not debug %} - - {% endif %} - - - diff --git a/templates/js/scroller.js b/templates/js/scroller.js deleted file mode 100644 index 9884d1ab961..00000000000 --- a/templates/js/scroller.js +++ /dev/null @@ -1,71 +0,0 @@ -$(document).ready( function() { - - $("#scroll_draw1").click(function(event){ - $('html, body').animate({ - scrollTop: $(document).height() - $(window).height()}, 40000, "linear"); - return false; - }); - $("#scroll_draw2").click(function(event){ - $('html, body').animate({ - scrollTop: $(document).height() - $(window).height()}, 80000, "linear"); - return false; - }); - $("#scroll_draw3").click(function(event){ - $('html, body').animate({ - scrollTop: $(document).height() - $(window).height()}, 120000, "linear"); - return false; - }); - $("#scroll_draw4").click(function(event){ - $('html, body').animate({ - scrollTop: $(document).height() - $(window).height()}, 160000, "linear"); - return false; - }); - $("#scroll_draw5").click(function(event){ - $('html, body').animate({ - scrollTop: $(document).height() - $(window).height()}, 200000, "linear"); - return false; - }); - - $("#tiny_text").click(function(event){ - $(this).siblings().removeClass("active"); - $(this).addClass("active"); - $("#draw").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-xs" ); - $(".fixedHeader table").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-xs" ); - return false; - }); - $("#small_text").click(function(event){ - $(this).siblings().removeClass("active"); - $(this).addClass("active"); - $("#draw").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-s" ); - $(".fixedHeader table").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-s" ); - return false; - }); - $("#medium_text").click(function(event){ - $(this).siblings().removeClass("active"); - $(this).addClass("active"); - $("#draw").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-m" ); - $(".fixedHeader table").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-m" ); - return false; - }); - $("#large_text").click(function(event){ - $(this).siblings().removeClass("active"); - $(this).addClass("active"); - $("#draw").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-l" ); - $(".fixedHeader table").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-l" ); - return false; - }); - $("#huge_text").click(function(event){ - $(this).siblings().removeClass("active"); - $(this).addClass("active"); - $("#draw").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-xl" ); - $(".fixedHeader table").removeClass( "draw-xs draw-s draw-m draw-l draw-xl" ).addClass( "draw-xl" ); - return false; - }); -}); - -$(document).keydown(function(e) { - e.stopPropagation(); - if (e.keyCode === 27 || e.keyCode === 38) { - $('html, body').stop() - } -}); diff --git a/templates/js/vendor/fixed-header.js b/templates/js/vendor/fixed-header.js deleted file mode 100644 index def89c2a7d3..00000000000 --- a/templates/js/vendor/fixed-header.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! - FixedHeader 2.1.1 - ©2010-2014 SpryMedia Ltd - datatables.net/license -*/ -var FixedHeader;!function(e,t,i){var o=function(o){return FixedHeader=function(e,t){if(!this instanceof FixedHeader)alert("FixedHeader warning: FixedHeader must be initialised with the 'new' keyword.");else{var i={aoCache:[],oSides:{top:!0,bottom:!1,left:0,right:0},oZIndexes:{top:104,bottom:103,left:102,right:101},oCloneOnDraw:{top:!1,bottom:!1,left:!0,right:!0},oMes:{iTableWidth:0,iTableHeight:0,iTableLeft:0,iTableRight:0,iTableTop:0,iTableBottom:0},oOffset:{top:0},nTable:null,bFooter:!1,bInitComplete:!1};this.fnGetSettings=function(){return i},this.fnUpdate=function(){this._fnUpdateClones(),this._fnUpdatePositions()},this.fnPosition=function(){this._fnUpdatePositions()};var a=o.fn.dataTable.Api?new o.fn.dataTable.Api(e).settings()[0]:e.fnSettings();a._oPluginFixedHeader=this,this.fnInit(a,t)}},FixedHeader.prototype={fnInit:function(t,i){var a=this.fnGetSettings(),n=this;this.fnInitSettings(a,i),""!==t.oScroll.sX||""!==t.oScroll.sY?alert("FixedHeader 2 is not supported with DataTables' scrolling mode at this time"):(a.nTable=t.nTable,t.aoDrawCallback.unshift({fn:function(){FixedHeader.fnMeasure(),n._fnUpdateClones.call(n),n._fnUpdatePositions.call(n)},sName:"FixedHeader"}),a.bFooter=0tfoot",a.nTable).length?!0:!1,a.oSides.top&&a.aoCache.push(n._fnCloneTable("fixedHeader","FixedHeader_Header",n._fnCloneThead)),a.oSides.bottom&&a.aoCache.push(n._fnCloneTable("fixedFooter","FixedHeader_Footer",n._fnCloneTfoot)),a.oSides.left&&a.aoCache.push(n._fnCloneTable("fixedLeft","FixedHeader_Left",n._fnCloneTLeft,a.oSides.left)),a.oSides.right&&a.aoCache.push(n._fnCloneTable("fixedRight","FixedHeader_Right",n._fnCloneTRight,a.oSides.right)),FixedHeader.afnScroll.push(function(){n._fnUpdatePositions.call(n)}),o(e).resize(function(){FixedHeader.fnMeasure(),n._fnUpdateClones.call(n),n._fnUpdatePositions.call(n)}),o(a.nTable).on("column-reorder.dt",function(){FixedHeader.fnMeasure(),n._fnUpdateClones(!0),n._fnUpdatePositions()}).on("column-visibility.dt",function(){FixedHeader.fnMeasure(),n._fnUpdateClones(!0),n._fnUpdatePositions()}),FixedHeader.fnMeasure(),n._fnUpdateClones(),n._fnUpdatePositions(),a.bInitComplete=!0)},fnInitSettings:function(e,t){t!==i&&(t.top!==i&&(e.oSides.top=t.top),t.bottom!==i&&(e.oSides.bottom=t.bottom),"boolean"==typeof t.left?e.oSides.left=t.left?1:0:t.left!==i&&(e.oSides.left=t.left),"boolean"==typeof t.right?e.oSides.right=t.right?1:0:t.right!==i&&(e.oSides.right=t.right),t.zTop!==i&&(e.oZIndexes.top=t.zTop),t.zBottom!==i&&(e.oZIndexes.bottom=t.zBottom),t.zLeft!==i&&(e.oZIndexes.left=t.zLeft),t.zRight!==i&&(e.oZIndexes.right=t.zRight),t.offsetTop!==i&&(e.oOffset.top=t.offsetTop),t.alwaysCloneTop!==i&&(e.oCloneOnDraw.top=t.alwaysCloneTop),t.alwaysCloneBottom!==i&&(e.oCloneOnDraw.bottom=t.alwaysCloneBottom),t.alwaysCloneLeft!==i&&(e.oCloneOnDraw.left=t.alwaysCloneLeft),t.alwaysCloneRight!==i)&&(e.oCloneOnDraw.right=t.alwaysCloneRight)},_fnCloneTable:function(e,i,a,n){var l,s=this.fnGetSettings();"absolute"!=o(s.nTable.parentNode).css("position")&&(s.nTable.parentNode.style.position="relative"),l=s.nTable.cloneNode(!1),l.removeAttribute("id");var d=t.createElement("div");return d.style.position="absolute",d.style.top="0px",d.style.left="0px",d.className+=" FixedHeader_Cloned "+e+" "+i,"fixedHeader"==e&&(d.style.zIndex=s.oZIndexes.top),"fixedFooter"==e&&(d.style.zIndex=s.oZIndexes.bottom),"fixedLeft"==e?d.style.zIndex=s.oZIndexes.left:"fixedRight"==e&&(d.style.zIndex=s.oZIndexes.right),l.style.margin="0",d.appendChild(l),t.body.appendChild(d),{nNode:l,nWrapper:d,sType:e,sPosition:"",sTop:"",sLeft:"",fnClone:a,iCells:n}},_fnMeasure:function(){var e=this.fnGetSettings(),t=e.oMes,i=o(e.nTable),a=i.offset(),n=this._fnSumScroll(e.nTable.parentNode,"scrollTop");this._fnSumScroll(e.nTable.parentNode,"scrollLeft"),t.iTableWidth=i.outerWidth(),t.iTableHeight=i.outerHeight(),t.iTableLeft=a.left+e.nTable.parentNode.scrollLeft,t.iTableTop=a.top+n,t.iTableRight=t.iTableLeft+t.iTableWidth,t.iTableRight=FixedHeader.oDoc.iWidth-t.iTableLeft-t.iTableWidth,t.iTableBottom=FixedHeader.oDoc.iHeight-t.iTableTop-t.iTableHeight},_fnSumScroll:function(e,t){for(var i=e[t];(e=e.parentNode)&&"HTML"!=e.nodeName&&"BODY"!=e.nodeName;)i=e[t];return i},_fnUpdatePositions:function(){var e=this.fnGetSettings();this._fnMeasure();for(var t=0,i=e.aoCache.length;i>t;t++)"fixedHeader"==e.aoCache[t].sType?this._fnScrollFixedHeader(e.aoCache[t]):"fixedFooter"==e.aoCache[t].sType?this._fnScrollFixedFooter(e.aoCache[t]):"fixedLeft"==e.aoCache[t].sType?this._fnScrollHorizontalLeft(e.aoCache[t]):this._fnScrollHorizontalRight(e.aoCache[t])},_fnUpdateClones:function(e){var t=this.fnGetSettings();e&&(t.bInitComplete=!1);for(var i=0,o=t.aoCache.length;o>i;i++)t.aoCache[i].fnClone.call(this,t.aoCache[i]);e&&(t.bInitComplete=!0)},_fnScrollHorizontalRight:function(e){var t=this.fnGetSettings().oMes,i=FixedHeader.oWin,a=FixedHeader.oDoc,n=e.nWrapper,l=o(n).outerWidth();i.iScrollRighto.iScrollTop+t.oOffset.top?(this._fnUpdateCache(e,"sPosition","absolute","position",a.style),this._fnUpdateCache(e,"sTop",i.iTableTop+"px","top",a.style),this._fnUpdateCache(e,"sLeft",i.iTableLeft+"px","left",a.style)):o.iScrollTop+t.oOffset.top>i.iTableTop+n?(this._fnUpdateCache(e,"sPosition","absolute","position",a.style),this._fnUpdateCache(e,"sTop",i.iTableTop+n+"px","top",a.style),this._fnUpdateCache(e,"sLeft",i.iTableLeft+"px","left",a.style)):(this._fnUpdateCache(e,"sPosition","fixed","position",a.style),this._fnUpdateCache(e,"sTop",t.oOffset.top+"px","top",a.style),this._fnUpdateCache(e,"sLeft",i.iTableLeft-o.iScrollLeft+"px","left",a.style))},_fnUpdateCache:function(e,t,i,o,a){e[t]!=i&&(a[o]=i,e[t]=i)},_fnClassUpdate:function(e,t){var i=this;("TR"===e.nodeName.toUpperCase()||"TH"===e.nodeName.toUpperCase()||"TD"===e.nodeName.toUpperCase()||"SPAN"===e.nodeName.toUpperCase())&&(t.className=e.className),o(e).children().each(function(a){i._fnClassUpdate(o(e).children()[a],o(t).children()[a])})},_fnCloneThead:function(e){var t=this.fnGetSettings(),i=e.nNode;if(t.bInitComplete&&!t.oCloneOnDraw.top)this._fnClassUpdate(o("thead",t.nTable)[0],o("thead",i)[0]);else{var a=o(t.nTable).outerWidth();for(e.nWrapper.style.width=a+"px",i.style.width=a+"px";0tr th",t.nTable).each(function(){n.push(o(this).width())}),o("thead>tr td",t.nTable).each(function(){l.push(o(this).width())}),o("thead>tr th",t.nTable).each(function(e){o("thead>tr th:eq("+e+")",i).width(n[e]),o(this).width(n[e])}),o("thead>tr td",t.nTable).each(function(e){o("thead>tr td:eq("+e+")",i).width(l[e]),o(this).width(l[e])}),o("th.sorting, th.sorting_desc, th.sorting_asc",i).bind("click",function(){this.blur()})}},_fnCloneTfoot:function(e){var t=this.fnGetSettings(),i=e.nNode;for(e.nWrapper.style.width=o(t.nTable).outerWidth()+"px";0tr th",t.nTable).each(function(e){o("tfoot:eq(0)>tr th:eq("+e+")",i).width(o(this).width())}),o("tfoot:eq(0)>tr td",t.nTable).each(function(e){o("tfoot:eq(0)>tr td:eq("+e+")",i).width(o(this).width())})},_fnCloneTLeft:function(e){for(var t=this.fnGetSettings(),i=e.nNode,a=o("tbody",t.nTable)[0];0e;e++)FixedHeader.afnScroll[e]()}),o.fn.dataTable.FixedHeader=FixedHeader,o.fn.DataTable.FixedHeader=FixedHeader};"function"==typeof define&&define.amd?define("datatables-fixedheader",["jquery","datatables"],o):jQuery&&!jQuery.fn.dataTable.FixedHeader&&o(jQuery,jQuery.fn.dataTable)}(window,document); diff --git a/templates/js/vendor/jquery.dataTables.min.js b/templates/js/vendor/jquery.dataTables.min.js deleted file mode 100644 index 7cad3e3e7fa..00000000000 --- a/templates/js/vendor/jquery.dataTables.min.js +++ /dev/null @@ -1,152 +0,0 @@ -/*! DataTables 1.10.0 - * ©2008-2014 SpryMedia Ltd - datatables.net/license - */ -(function(za,N,l){var M=function(g){function S(a){var b,c,d={};g.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),d[c]=e,"o"===b[1]&&S(a[e])});a._hungarianMap=d}function G(a,b,c){a._hungarianMap||S(a);var d;g.each(b,function(e){d=a._hungarianMap[e];if(d!==l&&(c||b[d]===l))"o"===d.charAt(0)?(b[d]||(b[d]={}),g.extend(!0,b[d],b[e]),G(a[d],b[d],c)):b[d]=b[e]})}function M(a){var b=p.defaults.oLanguage,c=a.sZeroRecords; -!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&D(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&D(a,a,"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&bb(a)}function cb(a){w(a,"ordering","bSort");w(a,"orderMulti","bSortMulti");w(a,"orderClasses","bSortClasses");w(a,"orderCellsTop","bSortCellsTop");w(a,"order","aaSorting");w(a,"orderFixed","aaSortingFixed");w(a,"paging","bPaginate"); -w(a,"pagingType","sPaginationType");w(a,"pageLength","iDisplayLength");w(a,"searching","bFilter")}function db(a){w(a,"orderable","bSortable");w(a,"orderData","aDataSort");w(a,"orderSequence","asSorting");w(a,"orderDataType","sortDataType")}function eb(a){var a=a.oBrowser,b=g("
                  ").css({position:"absolute",top:0,left:0,height:1,width:1,overflow:"hidden"}).append(g("
                  ").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(g('
                  ').css({width:"100%",height:10}))).appendTo("body"), -c=b.find(".test");a.bScrollOversize=100===c[0].offsetWidth;a.bScrollbarLeft=1!==c.offset().left;b.remove()}function fb(a,b,c,d,e,f){var h,i=!1;c!==l&&(h=c,i=!0);for(;d!==e;)a.hasOwnProperty(d)&&(h=i?b(h,a[d],d,a):a[d],i=!0,d+=f);return h}function Aa(a,b){var c=p.defaults.column,d=a.aoColumns.length,c=g.extend({},p.models.oColumn,c,{nTh:b?b:N.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols; -c[d]=g.extend({},p.models.oSearch,c[d]);fa(a,d,null)}function fa(a,b,c){var d=a.aoColumns[b],b=a.oClasses,e=g(d.nTh);if(!d.sWidthOrig){d.sWidthOrig=e.attr("width")||null;var f=(e.attr("style")||"").match(/width:\s*(\d+[pxem%])/);f&&(d.sWidthOrig=f[1])}c!==l&&null!==c&&(db(c),G(p.defaults.column,c),c.mDataProp!==l&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(d._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),g.extend(d,c),D(d,c,"sWidth","sWidthOrig"),"number"===typeof c.iDataSort&& -(d.aDataSort=[c.iDataSort]),D(d,c,"aDataSort"));var c=d.mData,h=T(c),i=d.mRender?T(d.mRender):null,f=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};d._bAttrSrc=g.isPlainObject(c)&&(f(c.sort)||f(c.type)||f(c.filter));d.fnGetData=function(a,b){var c=h(a,b);return d.mRender&&b&&""!==b?i(c,b,a):c};d.fnSetData=Ba(c);a.oFeatures.bSort||(d.bSortable=!1,e.addClass(b.sSortableNone));a=-1!==g.inArray("asc",d.asSorting);e=-1!==g.inArray("desc",d.asSorting);!d.bSortable||!a&&!e?(d.sSortingClass= -b.sSortableNone,d.sSortingClassJUI=""):a&&!e?(d.sSortingClass=b.sSortableAsc,d.sSortingClassJUI=b.sSortJUIAscAllowed):!a&&e?(d.sSortingClass=b.sSortableDesc,d.sSortingClassJUI=b.sSortJUIDescAllowed):(d.sSortingClass=b.sSortable,d.sSortingClassJUI=b.sSortJUI)}function U(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ca(a);for(var c=0,d=b.length;co[f])d(m.length+o[f],n);else if("string"===typeof o[f]){i=0;for(j=m.length;ib&&a[e]--; -1!=d&&c===l&&a.splice(d,1)}function la(a,b,c,d){var e=a.aoData[b],f;if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=ia(a,e).data;else{var h=e.anCells;if(h){c=0;for(f=h.length;c").appendTo(h));b=0;for(c=m.length;btr").attr("role","row");g(h).find(">tr>th, >tr>td").addClass(n.sHeaderTH);g(i).find(">tr>th, >tr>td").addClass(n.sFooterTH); -if(null!==i){a=a.aoFooter[0];b=0;for(c=a.length;b=a.fnRecordsDisplay()?0:h,a.iInitDisplayStart= --1);var h=a._iDisplayStart,n=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(i){if(!a.bDestroying&&!ib(a))return}else a.iDraw++;if(0!==j.length){f=i?a.aoData.length:n;for(i=i?0:h;i",{"class":e?d[0]:""}).append(g("",{valign:"top",colSpan:Y(a),"class":a.oClasses.sRowEmpty}).html(c))[0];t(a,"aoHeaderCallback","header",[g(a.nTHead).children("tr")[0],Ha(a),h,n,j]);t(a,"aoFooterCallback","footer",[g(a.nTFoot).children("tr")[0],Ha(a),h,n,j]);d=g(a.nTBody);d.children().detach();d.append(g(b));t(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function K(a,b){var c=a.oFeatures,d=c.bFilter; -c.bSort&&jb(a);d?aa(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);J(a)}function kb(a){var b=a.oClasses,c=g(a.nTable),c=g("
                  ").insertBefore(c),d=a.oFeatures,e=g("
                  ",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),h,i,j,n,m,o,k=0;k")[0];n=f[k+1];if("'"==n||'"'==n){m= -"";for(o=2;f[k+o]!=n;)m+=f[k+o],o++;"H"==m?m=b.sJUIHeader:"F"==m&&(m=b.sJUIFooter);-1!=m.indexOf(".")?(n=m.split("."),j.id=n[0].substr(1,n[0].length-1),j.className=n[1]):"#"==m.charAt(0)?j.id=m.substr(1,m.length-1):j.className=m;k+=o}e.append(j);e=g(j)}else if(">"==i)e=e.parent();else if("l"==i&&d.bPaginate&&d.bLengthChange)h=lb(a);else if("f"==i&&d.bFilter)h=mb(a);else if("r"==i&&d.bProcessing)h=nb(a);else if("t"==i)h=ob(a);else if("i"==i&&d.bInfo)h=pb(a);else if("p"==i&&d.bPaginate)h=qb(a);else if(0!== -p.ext.feature.length){j=p.ext.feature;o=0;for(n=j.length;o',h=a.oLanguage.sSearch,h=h.match(/_INPUT_/)?h.replace("_INPUT_",f):h+f,b=g("
                  ",{id:!e.f?c+"_filter":null,"class":b.sFilter}).append(g("
                  ").addClass(b.sLength); -a.aanFeatures.l||(j[0].id=c+"_length");b=a.oLanguage.sLengthMenu.split(/(_MENU_)/);j.children().append(1").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;d||c.fnInit(a,b,e);f.p||(b.id= -a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,j=a._iDisplayLength,g=a.fnRecordsDisplay(),m=-1===j,b=m?0:Math.ceil(b/j),j=m?1:Math.ceil(g/j),g=c(b,j),o,m=0;for(o=f.p.length;mf&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0> -d&&(d=0)):"next"==b?d+e",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&g(a.aanFeatures.r).css("display",b?"block":"none");t(a,null,"processing",[a,b])}function ob(a){var b= -g(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,h=b.children("caption"),i=h.length?h[0]._captionSide:null,j=g(b[0].cloneNode(!1)),n=g(b[0].cloneNode(!1)),m=b.children("tfoot");c.sX&&"100%"===b.attr("width")&&b.removeAttr("width");m.length||(m=null);c=g("
                  ",{"class":f.sScrollWrapper}).append(g("
                  ",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:s(d):"100%"}).append(g("
                  ", -{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(j.removeAttr("id").css("margin-left",0).append(b.children("thead")))).append("top"===i?h:null)).append(g("
                  ",{"class":f.sScrollBody}).css({overflow:"auto",height:!e?null:s(e),width:!d?null:s(d)}).append(b));m&&c.append(g("
                  ",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:s(d):"100%"}).append(g("
                  ",{"class":f.sScrollFootInner}).append(n.removeAttr("id").css("margin-left", -0).append(b.children("tfoot")))).append("bottom"===i?h:null));var b=c.children(),o=b[0],f=b[1],k=m?b[2]:null;d&&g(f).scroll(function(){var a=this.scrollLeft;o.scrollLeft=a;m&&(k.scrollLeft=a)});a.nScrollHead=o;a.nScrollBody=f;a.nScrollFoot=k;a.aoDrawCallback.push({fn:V,sName:"scrolling"});return c[0]}function V(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,f=b.iBarWidth,h=g(a.nScrollHead),i=h[0].style,j=h.children("div"),n=j[0].style,m=j.children("table"),j=a.nScrollBody,o=g(j),k=j.style,l=g(a.nScrollFoot).children("div"), -p=l.children("table"),r=g(a.nTHead),q=g(a.nTable),ba=q[0],L=ba.style,t=a.nTFoot?g(a.nTFoot):null,ca=a.oBrowser,v=ca.bScrollOversize,x,u,y,w,z,A=[],B=[],C=[],D,E=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};q.children("thead, tfoot").remove();z=r.clone().prependTo(q);x=r.find("tr");y=z.find("tr");z.find("th, td").removeAttr("tabindex");t&&(w=t.clone().prependTo(q),u=t.find("tr"),w=w.find("tr"));c||(k.width="100%",h[0].style.width= -"100%");g.each(ma(a,z),function(b,c){D=ga(a,b);c.style.width=a.aoColumns[D].sWidth});t&&F(function(a){a.style.width=""},w);b.bCollapse&&""!==e&&(k.height=o[0].offsetHeight+r[0].offsetHeight+"px");h=q.outerWidth();if(""===c){if(L.width="100%",v&&(q.find("tbody").height()>j.offsetHeight||"scroll"==o.css("overflow-y")))L.width=s(q.outerWidth()-f)}else""!==d?L.width=s(d):h==o.width()&&o.height()h-f&&(L.width=s(h))):L.width=s(h);h=q.outerWidth();F(E,y);F(function(a){C.push(a.innerHTML); -A.push(s(g(a).css("width")))},y);F(function(a,b){a.style.width=A[b]},x);g(y).height(0);t&&(F(E,w),F(function(a){B.push(s(g(a).css("width")))},w),F(function(a,b){a.style.width=B[b]},u),g(w).height(0));F(function(a,b){a.innerHTML='
                  '+C[b]+"
                  ";a.style.width=A[b]},y);t&&F(function(a,b){a.innerHTML="";a.style.width=B[b]},w);if(q.outerWidth()j.offsetHeight||"scroll"==o.css("overflow-y")?h+f:h;if(v&&(j.scrollHeight> -j.offsetHeight||"scroll"==o.css("overflow-y")))L.width=s(u-f);(""===c||""!==d)&&O(a,1,"Possible column misalignment",6)}else u="100%";k.width=s(u);i.width=s(u);t&&(a.nScrollFoot.style.width=s(u));!e&&v&&(k.height=s(ba.offsetHeight+f));e&&b.bCollapse&&(k.height=s(e),b=c&&ba.offsetWidth>j.offsetWidth?f:0,ba.offsetHeightj.clientHeight||"scroll"==o.css("overflow-y");ca="padding"+(ca.bScrollbarLeft? -"Left":"Right");n[ca]=m?f+"px":"0px";t&&(p[0].style.width=s(b),l[0].style.width=s(b),l[0].style[ca]=m?f+"px":"0px");o.scroll();if(a.bSorted||a.bFiltered)j.scrollTop=0}function F(a,b,c){for(var d=0,e=0,f=b.length,h,i;e"));i.find("tfoot th, tfoot td").css("width","");var p=i.find("tbody tr"),j=ma(a,i.find("thead")[0]);for(k=0;k").css("width",s(a)).appendTo(b||N.body),d=c[0].offsetWidth;c.remove(); -return d}function Bb(a,b){var c=a.oScroll;if(c.sX||c.sY)c=!c.sX?c.iBarWidth:0,b.style.width=s(g(b).outerWidth()-c)}function Ab(a,b){var c=Cb(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?g("").html(A(a,c,b,"display"))[0]:d.anCells[b]}function Cb(a,b){for(var c,d=-1,e=-1,f=0,h=a.aoData.length;fd&&(d=c.length,e=f);return e}function s(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function Db(){if(!p.__scrollbarWidth){var a= -g("

                  ").css({width:"100%",height:200,padding:0})[0],b=g("

                  ").css({position:"absolute",top:0,left:0,width:200,height:150,padding:0,overflow:"hidden",visibility:"hidden"}).append(a).appendTo("body"),c=a.offsetWidth;b.css("overflow","scroll");a=a.offsetWidth;c===a&&(a=b[0].clientWidth);b.remove();p.__scrollbarWidth=c-a}return p.__scrollbarWidth}function Q(a){var b,c,d=[],e=a.aoColumns,f,h,i,j;b=a.aaSortingFixed;c=g.isPlainObject(b);var n=[];f=function(a){a.length&&!g.isArray(a[0])?n.push(a):n.push.apply(n, -a)};g.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;ae?1:0,0!==c)return"asc"===g.dir?c:-c;c=d[a];e=d[b];return ce?1:0}):g.sort(function(a,b){var c,h,g,i,j=n.length,l=f[a]._aSortData,p=f[b]._aSortData;for(g=0;gh?1:0})}a.bSorted=!0}function Fb(a){for(var b,c, -d=a.aoColumns,e=Q(a),a=a.oLanguage.oAria,f=0,h=d.length;f/g,"");var g=c.nTh;g.removeAttribute("aria-sort");c.bSortable&&(0=f.length?0:b+1};c&&a.oFeatures.bSortMulti?(c=g.inArray(b,B(e,"0")),-1!==c?(b=h(e[c]),e[c][1]=f[b],e[c]._idx=b):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=h(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);K(a);"function"==typeof d&&d(a)}function Ka(a,b,c,d){var e=a.aoColumns[c];Ta(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Sa(a,c,b.shiftKey,d);"ssp"!==z(a)&&C(a,!1)},0)):Sa(a, -c,b.shiftKey,d))})}function sa(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=Q(a),e=a.oFeatures,f,h;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;ee?e+1:3));e=0;for(f=d.length;ee?e+1:3))}a.aLastSort=d}function Eb(a,b){var c=a.aoColumns[b],d=p.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,X(a,b)));for(var f,h=p.ext.type.order[c.sType+"-pre"],g=0,j=a.aoData.length;g< -j;g++)if(c=a.aoData[g],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[g]:A(a,g,b,"sort"),c._aSortData[b]=h?h(f):f}function ta(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={iCreate:+new Date,iStart:a._iDisplayStart,iLength:a._iDisplayLength,aaSorting:g.extend(!0,[],a.aaSorting),oSearch:g.extend(!0,{},a.oPreviousSearch),aoSearchCols:g.extend(!0,[],a.aoPreSearchCols),abVisCols:B(a.aoColumns,"bVisible")};t(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.fnStateSaveCallback.call(a.oInstance, -a,b)}}function Gb(a){var b,c,d=a.aoColumns;if(a.oFeatures.bStateSave){var e=a.fnStateLoadCallback.call(a.oInstance,a);if(e&&(b=t(a,"aoStateLoadParams","stateLoadParams",[a,e]),-1===g.inArray(!1,b)&&(b=a.iStateDuration,!(0=d.length?[0,a[1]]:a});g.extend(a.oPreviousSearch, -e.oSearch);g.extend(!0,a.aoPreSearchCols,e.aoSearchCols);var f=e.abVisCols;b=0;for(c=f.length;bb)b=0;a._iDisplayStart=b}function La(a,b){var c=a.renderer,d=p.ext.renderer[b];return g.isPlainObject(c)&& -c[b]?d[c[b]]||d._:"string"===typeof c?d[c]||d._:d._}function z(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function Ua(a,b){var c=[],c=Ib.numbers_length,d=Math.floor(c/2);b<=c?c=R(0,b):a<=d?(c=R(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=R(b-(c-2),b):(c=R(a-1,a+2),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function bb(a){g.each({num:function(b){return va(b,a)},"num-fmt":function(b){return va(b,a,Va)},"html-num":function(b){return va(b, -a,wa)},"html-num-fmt":function(b){return va(b,a,wa,Va)}},function(b,c){u.type.order[b+a+"-pre"]=c})}function Jb(a){return function(){var b=[ua(this[p.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return p.ext.internal[a].apply(this,b)}}var p,u,q,r,x,Wa={},Kb=/[\r\n]/g,wa=/<.*?>/g,Vb=/^[\d\+\-a-zA-Z]/,Sb=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Va=/[',$\u00a3\u20ac\u00a5%\u2009\u202F]/g,da=function(a){return!a||"-"===a?!0:!1},Lb=function(a){var b= -parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Mb=function(a,b){Wa[b]||(Wa[b]=RegExp(Oa(b),"g"));return"string"===typeof a?a.replace(/\./g,"").replace(Wa[b],"."):a},Xa=function(a,b,c){var d="string"===typeof a;b&&d&&(a=Mb(a,b));c&&d&&(a=a.replace(Va,""));return!a||"-"===a||!isNaN(parseFloat(a))&&isFinite(a)},Nb=function(a,b,c){return da(a)?!0:a&&"string"!==typeof a?null:Xa(a.replace(wa,""),b,c)?!0:null},B=function(a,b,c){var d=[],e=0,f=a.length;if(c!==l)for(;e")[0],Tb=qa.textContent!== -l,Ub=/<.*?>/g;p=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new q(ua(this[u.iApiIndex])):new q(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=g.isArray(a)&&(g.isArray(a[0])||g.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===l||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===l|| -a?b.draw(!1):(""!==d.sX||""!==d.sY)&&V(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===l||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],g=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,g);(c===l||c)&&d.draw();return g};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(!a)};this.fnFilter=function(a,b,c,d,e,g){e=this.api(!0);null=== -b||b===l?e.search(a,c,d,g):e.column(b).search(a,c,d,g);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==l){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==l||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==l?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"== -c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===l||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===l||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return ua(this[u.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()}; -this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var g=this.api(!0);c===l||null===c?g.row(b).data(a):g.cell(b,c).data(a);(e===l||e)&&g.columns.adjust();(d===l||d)&&g.draw();return 0};this.fnVersionCheck=u.fnVersionCheck;var b=this,c=a===l,d=this.length;c&&(a={});this.oApi=this.internal=u.internal;for(var e in p.ext.internal)e&&(this[e]=Jb(e));this.each(function(){var e={},h=1t<"F"ip>'),k.renderer)?g.isPlainObject(k.renderer)&&!k.renderer.header&&(k.renderer.header="jqueryui"):k.renderer="jqueryui":g.extend(n,p.ext.classes,h.oClasses);g(this).addClass(n.sTable);if(""!==k.oScroll.sX||""!==k.oScroll.sY)k.oScroll.iBarWidth=Db();!0===k.oScroll.sX&&(k.oScroll.sX= -"100%");k.iInitDisplayStart===l&&(k.iInitDisplayStart=h.iDisplayStart,k._iDisplayStart=h.iDisplayStart);null!==h.iDeferLoading&&(k.bDeferLoading=!0,i=g.isArray(h.iDeferLoading),k._iRecordsDisplay=i?h.iDeferLoading[0]:h.iDeferLoading,k._iRecordsTotal=i?h.iDeferLoading[1]:h.iDeferLoading);""!==h.oLanguage.sUrl?(k.oLanguage.sUrl=h.oLanguage.sUrl,g.getJSON(k.oLanguage.sUrl,null,function(a){M(a);G(m.oLanguage,a);g.extend(true,k.oLanguage,h.oLanguage,a);ra(k)}),e=!0):g.extend(!0,k.oLanguage,h.oLanguage); -null===h.asStripeClasses&&(k.asStripeClasses=[n.sStripeOdd,n.sStripeEven]);var i=k.asStripeClasses,r=g("tbody tr:eq(0)",this);-1!==g.inArray(!0,g.map(i,function(a){return r.hasClass(a)}))&&(g("tbody tr",this).removeClass(i.join(" ")),k.asDestroyStripes=i.slice());var o=[],q,i=this.getElementsByTagName("thead");0!==i.length&&($(k.aoHeader,i[0]),o=ma(k));if(null===h.aoColumns){q=[];i=0;for(j=o.length;i").appendTo(this));k.nTHead= -j[0];j=g(this).children("tbody");0===j.length&&(j=g("").appendTo(this));k.nTBody=j[0];j=g(this).children("tfoot");if(0===j.length&&0").appendTo(this);0===j.length||0===j.children().length?g(this).addClass(n.sNoFooter):0a?new q(b[a],this[a]):null},filter:function(a){var b=[];if(v.filter)b=v.filter.call(this,a,this);else for(var c=0,d=this.length;c");g("td",c).addClass(b).html(a)[0].colSpan=Y(d);e.push(c[0])}};if(g.isArray(a)||a instanceof g)for(var h=0,i=a.length;h=0?c:f.length+c];var e=typeof a==="string"?a.match(Xb):"";if(e)switch(e[2]){case "visIdx":case "visible":a=parseInt(e[1],10); -if(a<0){c=g.map(f,function(a,b){return a.bVisible?b:null});return[c[c.length+a]]}return[ga(b,a)];case "name":return g.map(h,function(a,b){return a===e[1]?b:null})}else return g(i).filter(a).map(function(){return g.inArray(this,i)}).toArray()})});c.selector.cols=a;c.selector.opts=b;return c});x("columns().header()","column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh})});x("columns().footer()","column().footer()",function(){return this.iterator("column", -function(a,b){return a.aoColumns[b].nTf})});x("columns().data()","column().data()",function(){return this.iterator("column-rows",function(a,b,c,d,e){for(var c=[],d=0,f=e.length;dd;return!0};p.isDataTable=p.fnIsDataTable=function(a){var b=g(a).get(0),c=!1;g.each(p.settings,function(a,e){if(e.nTable===b||e.nScrollHead===b||e.nScrollFoot===b)c=!0});return c};p.tables=p.fnTables=function(a){return jQuery.map(p.settings,function(b){if(!a||a&&g(b.nTable).is(":visible"))return b.nTable})};p.camelToHungarian=G;r("$()",function(a,b){var c=this.rows(b).nodes(), -c=g(c);return g([].concat(c.filter(a).toArray(),c.find(a).toArray()))});g.each(["on","one","off"],function(a,b){r(b+"()",function(){var a=Array.prototype.slice.call(arguments);-1===a[0].indexOf(".dt")&&(a[0]+=".dt");var d=g(this.tables().nodes());d[b].apply(d,a);return this})});r("clear()",function(){return this.iterator("table",function(a){ja(a)})});r("settings()",function(){return new q(this.context,this.context)});r("data()",function(){return this.iterator("table",function(a){return B(a.aoData, -"_aData")}).flatten()});r("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,f=b.nTBody,h=b.nTHead,i=b.nTFoot,j=g(e),f=g(f),n=g(b.nTableWrapper),m=g.map(b.aoData,function(a){return a.nTr}),l;b.bDestroying=!0;t(b,"aoDestroyCallback","destroy",[b]);a||(new q(b)).columns().visible(!0);n.unbind(".DT").find(":not(tbody *)").unbind(".DT");g(za).unbind(".DT-"+b.sInstance);e!=h.parentNode&&(j.children("thead").detach(),j.append(h)); -i&&e!=i.parentNode&&(j.children("tfoot").detach(),j.append(i));j.detach();n.detach();b.aaSorting=[];b.aaSortingFixed=[];sa(b);g(m).removeClass(b.asStripeClasses.join(" "));g("th, td",h).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);b.bJUI&&(g("th span."+d.sSortIcon+", td span."+d.sSortIcon,h).detach(),g("th, td",h).each(function(){var a=g("div."+d.sSortJUIWrapper,this);g(this).append(a.contents());a.detach()}));!a&&c&&c.insertBefore(e,b.nTableReinsertBefore); -f.children().detach();f.append(m);j.css("width",b.sDestroyWidth).removeClass(d.sTable);(l=b.asDestroyStripes.length)&&f.children().each(function(a){g(this).addClass(b.asDestroyStripes[a%l])});c=g.inArray(b,p.settings);-1!==c&&p.settings.splice(c,1)})});p.version="1.10.0";p.settings=[];p.models={};p.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};p.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null};p.models.oColumn= -{idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};p.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null, -aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null, -fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null, -iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"", -sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sUrl:"",sZeroRecords:"No matching records found"},oSearch:g.extend({},p.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null};S(p.defaults);p.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null, -mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};S(p.defaults.column);p.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1, -bScrollbarLeft:!1},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null, -nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:l,oAjaxData:l,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null, -oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==z(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==z(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null, -nScrollFoot:null,aLastSort:[],oPlugins:{}};p.ext=u={classes:{},errMode:"alert",feature:[],search:[],internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:p.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:p.version};g.extend(u,{afnFiltering:u.search,aTypes:u.type.detect,ofnSearch:u.type.search,oSort:u.type.order,afnSortData:u.order,aoFeatures:u.feature,oApi:u.internal,oStdClasses:u.classes,oPagination:u.pager}); -g.extend(p.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled", -sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"", -sJUIHeader:"",sJUIFooter:""});var ya="",ya="",E=ya+"ui-state-default",ea=ya+"css_right ui-icon ui-icon-",Rb=ya+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";g.extend(p.ext.oJUIClasses,p.ext.classes,{sPageButton:"fg-button ui-button "+E,sPageButtonActive:"ui-state-disabled",sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:E+" sorting_asc",sSortDesc:E+" sorting_desc",sSortable:E+" sorting", -sSortableAsc:E+" sorting_asc_disabled",sSortableDesc:E+" sorting_desc_disabled",sSortableNone:E+" sorting_disabled",sSortJUIAsc:ea+"triangle-1-n",sSortJUIDesc:ea+"triangle-1-s",sSortJUI:ea+"carat-2-n-s",sSortJUIAscAllowed:ea+"carat-1-n",sSortJUIDescAllowed:ea+"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+E,sScrollFoot:"dataTables_scrollFoot "+E,sHeaderTH:E,sFooterTH:E,sJUIHeader:Rb+" ui-corner-tl ui-corner-tr",sJUIFooter:Rb+ -" ui-corner-bl ui-corner-br"});var Ib=p.ext.pager;g.extend(Ib,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},simple_numbers:function(a,b){return["previous",Ua(a,b),"next"]},full_numbers:function(a,b){return["first","previous",Ua(a,b),"next","last"]},_numbers:Ua,numbers_length:7});g.extend(!0,p.ext.renderer,{pageButton:{_:function(a,b,c,d,e,f){var h=a.oClasses,i=a.oLanguage.oPaginate,j,l,m=0,o=function(b,d){var k,p,r,q,s=function(b){Ra(a,b.data.action, -true)};k=0;for(p=d.length;k").appendTo(b);o(r,q)}else{l=j="";switch(q){case "ellipsis":b.append("");break;case "first":j=i.sFirst;l=q+(e>0?"":" "+h.sPageButtonDisabled);break;case "previous":j=i.sPrevious;l=q+(e>0?"":" "+h.sPageButtonDisabled);break;case "next":j=i.sNext;l=q+(e",{"class":h.sPageButton+" "+l,"aria-controls":a.sTableId,"data-dt-idx":m,tabindex:a.iTabIndex,id:c===0&&typeof q==="string"?a.sTableId+"_"+q:null}).html(j).appendTo(b);Ta(r,{action:q},s);m++}}}},k=g(N.activeElement).data("dt-idx");o(g(b).empty(),d);k!==null&&g(b).find("[data-dt-idx="+k+"]").focus()}}});var va=function(a,b,c,d){if(!a||"-"===a)return-Infinity;b&&(a=Mb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};g.extend(u.type.order,{"date-pre":function(a){return Date.parse(a)|| -0},"html-pre":function(a){return!a?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return"string"===typeof a?a.toLowerCase():!a||!a.toString?"":a.toString()},"string-asc":function(a,b){return ab?1:0},"string-desc":function(a,b){return ab?-1:0}});bb("");g.extend(p.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Xa(a,c)?"num"+c:null},function(a){if(a&&!Vb.test(a))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||da(a)?"date": -null},function(a,b){var c=b.oLanguage.sDecimal;return Xa(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Nb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Nb(a,c,!0)?"html-num-fmt"+c:null},function(a){return da(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);g.extend(p.ext.type.search,{html:function(a){return da(a)?"":"string"===typeof a?a.replace(Kb," ").replace(wa,""):""},string:function(a){return da(a)?"":"string"===typeof a?a.replace(Kb, -" "):a}});g.extend(!0,p.ext.renderer,{header:{_:function(a,b,c,d){g(a.nTable).on("order.dt.DT",function(a,f,g,i){a=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(i[a]=="asc"?d.sSortAsc:i[a]=="desc"?d.sSortDesc:c.sSortingClass)})},jqueryui:function(a,b,c,d){var e=c.idx;g("
                  ").addClass(d.sSortJUIWrapper).append(b.contents()).append(g("").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);g(a.nTable).on("order.dt.DT",function(a,g,i,j){b.removeClass(d.sSortAsc+ -" "+d.sSortDesc).addClass(j[e]=="asc"?d.sSortAsc:j[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(j[e]=="asc"?d.sSortJUIAsc:j[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)})}}});p.render={number:function(a,b,c,d){return{display:function(e){var e=parseFloat(e),f=parseInt(e,10),e=c?(b+(e-f).toFixed(c)).substring(2):"";return(d||"")+f.toString().replace(/\B(?=(\d{3})+(?!\d))/g, -a)+e}}}};g.extend(p.ext.internal,{_fnExternApiFunc:Jb,_fnBuildAjax:na,_fnAjaxUpdate:ib,_fnAjaxParameters:rb,_fnAjaxUpdateDraw:sb,_fnAjaxDataSrc:oa,_fnAddColumn:Aa,_fnColumnOptions:fa,_fnAdjustColumnSizing:U,_fnVisibleToColumnIndex:ga,_fnColumnIndexToVisible:X,_fnVisbleColumns:Y,_fnGetColumns:W,_fnColumnTypes:Da,_fnApplyColumnDefs:gb,_fnHungarianMap:S,_fnCamelToHungarian:G,_fnLanguageCompat:M,_fnBrowserDetect:eb,_fnAddData:H,_fnAddTr:ha,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==l?b._DT_RowIndex: -null},_fnNodeToColumnIndex:function(a,b,c){return g.inArray(c,a.aoData[b].anCells)},_fnGetCellData:A,_fnSetCellData:Ea,_fnSplitObjNotation:Ga,_fnGetObjectDataFn:T,_fnSetObjectDataFn:Ba,_fnGetDataMaster:Ha,_fnClearTable:ja,_fnDeleteIndex:ka,_fnInvalidateRow:la,_fnGetRowElements:ia,_fnCreateTr:Fa,_fnBuildHead:hb,_fnDrawHead:I,_fnDraw:J,_fnReDraw:K,_fnAddOptionsHtml:kb,_fnDetectHeader:$,_fnGetUniqueThs:ma,_fnFeatureHtmlFilter:mb,_fnFilterComplete:aa,_fnFilterCustom:vb,_fnFilterColumn:ub,_fnFilter:tb, -_fnFilterCreateSearch:Na,_fnEscapeRegex:Oa,_fnFilterData:wb,_fnFeatureHtmlInfo:pb,_fnUpdateInfo:xb,_fnInfoMacros:yb,_fnInitialise:ra,_fnInitComplete:pa,_fnLengthChange:Pa,_fnFeatureHtmlLength:lb,_fnFeatureHtmlPaginate:qb,_fnPageChange:Ra,_fnFeatureHtmlProcessing:nb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:ob,_fnScrollDraw:V,_fnApplyToChildren:F,_fnCalculateColumnWidths:Ca,_fnThrottle:Ma,_fnConvertToWidth:zb,_fnScrollingWidthAdjust:Bb,_fnGetWidestNode:Ab,_fnGetMaxLenString:Cb,_fnStringToCss:s,_fnScrollBarWidth:Db, -_fnSortFlatten:Q,_fnSort:jb,_fnSortAria:Fb,_fnSortListener:Sa,_fnSortAttachListener:Ka,_fnSortingClasses:sa,_fnSortData:Eb,_fnSaveState:ta,_fnLoadState:Gb,_fnSettingsFromNode:ua,_fnLog:O,_fnMap:D,_fnBindAction:Ta,_fnCallbackReg:y,_fnCallbackFire:t,_fnLengthOverflow:Qa,_fnRenderer:La,_fnDataSource:z,_fnRowAttributes:Ia,_fnCalculateEnd:function(){}});g.fn.dataTable=p;g.fn.dataTableSettings=p.settings;g.fn.dataTableExt=p.ext;g.fn.DataTable=function(a){return g(this).dataTable(a).api()};g.each(p,function(a, -b){g.fn.DataTable[a]=b});return g.fn.dataTable};"function"===typeof define&&define.amd?define("datatables",["jquery"],M):"object"===typeof exports?M(require("jquery")):jQuery&&!jQuery.fn.dataTable&&M(jQuery)})(window,document); diff --git a/templates/nav/admin_nav.html b/templates/nav/admin_nav.html deleted file mode 100644 index 6522a9e5dd9..00000000000 --- a/templates/nav/admin_nav.html +++ /dev/null @@ -1,173 +0,0 @@ -{% load debate_tags %} - - diff --git a/templates/nav/top_nav_base.html b/templates/nav/top_nav_base.html deleted file mode 100644 index 833eeff5531..00000000000 --- a/templates/nav/top_nav_base.html +++ /dev/null @@ -1,45 +0,0 @@ -{% load debate_tags %} - - diff --git a/templates/scss/modules/base.scss b/templates/scss/modules/base.scss deleted file mode 100644 index 620884b2e28..00000000000 --- a/templates/scss/modules/base.scss +++ /dev/null @@ -1,43 +0,0 @@ -// GENERIC AESTHETICS -body { - background: #f3f4f9; -} -.white-bg { - background: #fff; -} -// LAYOUT -.vertical-spacing { - margin-bottom: $line-height-computed; -} -.no-bottom-padding { - padding-bottom: 0px; // Mostly for panel-body elements -} -// BASE ELEMENTS: HEADER -.head-title { - padding: 0 0 16px 5px; - small { - line-height: $font-size-h3 * $headings-line-height * 1.2; - } -} -.page-sub-nav { - .navbar-left .btn, .navbar-left .input-group { - margin-bottom: $line-height-computed; - } - .navbar-right { - padding-right: 15px; // compensate for the pull-rights negative margin - } - .btn-group-input { - // For the quick search; needs to fit within the row - display: inline-block; - max-width: 148px; - float: right; // Needed to fix spacing - margin-left: 3px; // Isn't receiving the left margin - .form-control { - height: 41px; - border-width: 1px; - } - } - .dropdown, form { - display: inline-block; // Need this to bring their alignment up - } -} diff --git a/templates/scss/modules/datavis.scss b/templates/scss/modules/datavis.scss deleted file mode 100644 index 4ac131c361a..00000000000 --- a/templates/scss/modules/datavis.scss +++ /dev/null @@ -1,29 +0,0 @@ -.d3-graph { - - .axis { - font-size: 11px; - } - // General Styles - .axis path, - .axis line { - fill: none; - stroke: #ccc; - shape-rendering: crispEdges; - } - - .d3-hoverable:hover { - cursor: pointer; - fill: black; - } - -} - -.d3-feedback-trend { - // For Feedback Page - .tick line, .axis line { - fill: none; - stroke: black; - opacity: 0.2; // Make axis look like ticks - } - -} diff --git a/templates/scss/modules/forms.scss b/templates/scss/modules/forms.scss deleted file mode 100644 index 74c42247941..00000000000 --- a/templates/scss/modules/forms.scss +++ /dev/null @@ -1,26 +0,0 @@ -// FORM ELEMENTS -// Actionable elements (buttons, navs) should be distinct -.btn { - font-family: $headings-font-family; - font-weight: $headings-font-weight; - padding: 10px 12px; -} -// Give buttons more padding -.form-control, -.form-control-parent input { - border-width: 2px; - border-radius: 6px; - height: 39px; -} -// Center number inputs -input[type=number] { - text-align: center; -} -// Labels in list groups need to vertically center with inputs -.list-group-item label { - padding-top: 10px; -} -// Don't pad form panels as the elements already have padding -.panel-body.form-panel { - padding-bottom: 0px; -} diff --git a/templates/scss/modules/interaction.scss b/templates/scss/modules/interaction.scss deleted file mode 100644 index 7a13e4d22fa..00000000000 --- a/templates/scss/modules/interaction.scss +++ /dev/null @@ -1,63 +0,0 @@ -// General hover elements -[data-toggle="popover"] { - border-bottom: 2px dotted #999; - &:hover { - cursor: help; - } -} - -// Dragging for Allocations -.vue-draggable { - // Don't let text selections get in the way of dragging - -moz-user-select: none; - -khtml-user-select: none; - -webkit-user-select: none; - user-select: none; - /* Required to make elements draggable in old WebKit */ - -khtml-user-drag: element; - -webkit-user-drag: element; - display: inline-block; - border: 1px solid #ccc; - // border-radius: 5px; - padding: 3px 6px 3px 0; - margin: 2px; - text-align: left; - // background: #fff; - // height: 32px; - // line-height: 32px; - // position: relative; - span { - padding: 6px 0 0 6px; - } - &:hover { - cursor: move; - } -} -.vue-is-dragging { - opacity: 0.5 !important; - cursor: move; -} -.vue-is-drag-enter { - // text-decoration: underline; - background: $state-success-bg; -} -// Hovers for Allocations -.slideover-info { - width: auto; - position: fixed; - height: 75px; - bottom: 0; - right: 15px; - left: 15px; - z-index: 1040; // See boostrap zindex list; this puts it above the navs -} -.expand-transition { - transition: all .3s ease; - height: default; -} -/* .expand-enter defines the starting state for entering */ -/* .expand-leave defines the ending state for leaving */ -.expand-enter, .expand-leave { - height: 0; - opacity: 0; -} diff --git a/templates/scss/modules/tables.scss b/templates/scss/modules/tables.scss deleted file mode 100644 index da7a4743c69..00000000000 --- a/templates/scss/modules/tables.scss +++ /dev/null @@ -1,177 +0,0 @@ -//------------------------------------------------------------------------------ -// Overall Layout -//------------------------------------------------------------------------------ - -.panel-body .table { - margin-bottom: 0; // Panel body has its own bottom padding - > tr:nth-of-type(odd) { - background-color: $table-bg-accent; // Force .table-striped style - } - > tbody > tr:hover td { - background-color: $table-bg-hover; - } - > tbody > tr.clickable:hover { - cursor: pointer; - } -} - -thead { - background: #fff; // Fixed header needs a background while scrolling - text-transform: uppercase; - font-size: $font-size-h6; -} - -.dataTables_filter { - display: none; // Hide the default search box -} - -//------------------------------------------------------------------------------ -// Sorting -//------------------------------------------------------------------------------ - -.table > thead > tr > th { - &.sorting, - &.sorting_asc, - &.sorting_desc, - &.sorting_asc_disabled, - &.sorting_desc_disabled { - cursor: pointer; - padding-right: 22px; // Leave space for the icon - position: relative; - } -} - -.sorting { - &::after { - content: '\e150'; - } - - &:hover { - color: $brand-success; - } -} - -.vue-sortable { - &:hover { - color: $brand-success; - cursor: pointer; - } -} - -.sorting_asc, -.sorting_desc, -.vue-sort-active { - color: $brand-success; -} - -.sorting_asc { - &::after { - content: '\e155'; - } -} - -.sorting_desc { - &::after { - content: '\e156'; - } -} - -table thead .sorting:after, -table thead .sorting_asc:after, -table thead .sorting_desc:after, -table thead .sorting_asc_disabled:after, -table thead .sorting_desc_disabled:after { - bottom: 8px; - display: block; - font-family: 'Glyphicons Halflings'; - position: absolute; - right: 8px; -} -// -// CELL STYLES -// -.table > tbody > tr > th, -.table > tbody > tr > td { - border-left: 0; - border-right: 0; -} - -//------------------------------------------------------------------------------ -// Row States -//------------------------------------------------------------------------------ - -.panel-body .table > tbody, -.panel-heading .btn-group { - @include table-row-variant('debate-status-in', $state-warning-bg); - .debate-status-in { - @include button-variant(darken($state-warning-bg, 70%), $state-warning-bg, $state-warning-bg); - a { - color: darken($state-warning-bg, 70%); - } - } - - @include table-row-variant('debate-status-unknown', $state-danger-bg); - .debate-status-unknown, - .debate-status-N { - @include button-variant(darken($state-danger-bg, 70%), $state-danger-bg, $state-danger-bg); - a { - color: darken($state-warning-bg, 70%); - } - } - - @include table-row-variant('debate-status-unconfirmed', lighten($brand-info, 40%)); - .debate-status-unconfirmed, - .debate-status-D { - @include button-variant(darken($brand-info, 30%), lighten($brand-info, 40%), lighten($brand-info, 40%)); - a { - color: darken($brand-info, 30%); - } - } - - @include table-row-variant('debate-status-confirmed', $state-success-bg); - .debate-status-confirmed, - .debate-status-C { - @include button-variant(darken($state-success-bg, 70%), $state-success-bg, $state-success-bg); - a { - color: darken($state-success-bg, 70%); - } - } - - @include table-row-variant('debate-status-postponed', $state-info-bg); - .debate-status-postponed, - .debate-status-P { - @include button-variant(darken($table-bg-active, 70%), $state-info-bg, $state-info-bg); - a { - color: darken($table-bg-active, 70%); - } - } - - @include table-row-variant('debate-status-bye', $table-bg-active); - .debate-status-bye { - @include button-variant(#000, $table-bg-active, $table-bg-active); - a { - color: darken($table-bg-active, 60%); - } - } - -} - -// -// SPECIFIC DECORATORS -// -.draw-with-standings .em { - font-weight: bold; - color: chocolate; - font-style: normal; -} - -.draw-with-standings .first-in-bracket { - border-top: 3px solid chocolate; -} - -.no-overflow { - max-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} diff --git a/templates/scss/modules/typography.scss b/templates/scss/modules/typography.scss deleted file mode 100644 index d73ea6c3f7f..00000000000 --- a/templates/scss/modules/typography.scss +++ /dev/null @@ -1,47 +0,0 @@ -@import '../partials/variables'; - -// WEB FONTS -@font-face { - font-family: 'LatoLatinWeb'; - src: url('/static/fonts/vendor/lato-regular.eot'); - src: url('/static/fonts/vendor/lato-regular.eot?#iefix') format('embedded-opentype'), - url('/static/fonts/vendor/lato-regular.woff2') format('woff2'), - url('/static/fonts/vendor/lato-regular.woff') format('woff'), - url('/static/fonts/vendor/lato-regular.ttf') format('truetype'); - font-weight: normal; - font-style: normal; - text-rendering: optimizeLegibility; -} - -// UTILITIES - -.text-muted { - color: $gray-light; -} - -// EMOJI -.emoji { - display: inline-block; - font-family: sans-serif; // Need to be a system font or they wont show - font-style: normal; - font-weight: normal; - margin-right: 1px; - min-width: 20px; -} -.small .emoji { - min-width: 13px; -} - -// BUTTONS -.nav { - // Actionable elements (buttons, navs) should be distinct - font-family: $headings-font-family; -} - -.nav-pills a.btn-default { - color: $brand-primary; -} - -.nav-tabs a { - letter-spacing: .5px; -} diff --git a/templates/scss/partials/variables.scss b/templates/scss/partials/variables.scss deleted file mode 100644 index fb9b293c78c..00000000000 --- a/templates/scss/partials/variables.scss +++ /dev/null @@ -1,21 +0,0 @@ -// Note these take precedences over bootstrap as they are not set as default -// Custom Typography -$font-family-sans-serif: "LatoLatinWeb", Helvetica, Arial, sans-serif; -$headings-font-family: Helvetica, Arial, sans-serif; -$headings-font-weight: bold; -// Custom Colors -$brand-primary: #3498db; -$brand-success: #43ca75; -$brand-info: #3b9ad8; -$brand-warning: #f0c230; -$brand-danger: #e34e42; -// Layout Colors -$table-bg-hover: #e3e3e3; -$sidebar-bg: #30404f; -$sidebar-bg-highlight: darken($sidebar-bg, 3); -$sidebar-muted-text: #adb6bf; -// Override Path -$icon-font-path: '/static/fonts/vendor/'; -// Layout -$sidebar-width: 155px; -$adj-button-width: 180px; diff --git a/templates/scss/style.scss b/templates/scss/style.scss deleted file mode 100644 index 16abda60940..00000000000 --- a/templates/scss/style.scss +++ /dev/null @@ -1,342 +0,0 @@ -//------------------------------------------------------------------------------ -// Bootstrap -//------------------------------------------------------------------------------ - -// Our overrides -@import 'partials/variables'; -// Core variables and mixins -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/mixins'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/variables'; -// Reset -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/normalize'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/print'; -// Core CSS -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/scaffolding'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/type'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/code'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/grid'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tables'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/forms'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/buttons'; -// Components -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/component-animations'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/glyphicons'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/dropdowns'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/button-groups'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/input-groups'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/navs'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/navbar'; -// @import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/breadcrumbs'; -// @import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/pagination'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/pager'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/labels'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/badges'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/jumbotron'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/thumbnails'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/alerts'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/progress-bars'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/media'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/list-group'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/panels'; -// @import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/wells'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/close'; -// Components w/ JavaScript -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/modals'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tooltip'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/popovers'; -// @import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/carousel'; -// Utility classes -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/utilities'; -@import '../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/responsive-utilities'; - -//------------------------------------------------------------------------------ -// Tabbycat -//------------------------------------------------------------------------------ - -@import 'modules/typography'; -@import 'modules/print'; -@import 'modules/nav'; -@import 'modules/footer'; -@import 'modules/tables'; -@import 'modules/forms'; -@import 'modules/base'; -@import 'modules/allocation'; -@import 'modules/interaction'; -@import 'modules/datavis'; - -//------------------------------------------------------------------------------ -// Below should be refactored -//------------------------------------------------------------------------------ - -.ui-helper-hidden-accessible { - display: none; // Remove when jquery UI is removed -} - -@import 'components/page-specific'; -@include text-emphasis-variant('.text-success', $brand-success); -@include text-emphasis-variant('.text-info', $brand-info); -@include text-emphasis-variant('.text-warning', $brand-warning); -@include text-emphasis-variant('.text-danger', $brand-danger); - -.no-vertical-spacing, -table.table > thead > tr > th.no-vertical-spacing, -table.table > tbody > tr > td.no-vertical-spacing { - padding-top: 0; - padding-bottom: 0; - margin-top: 0; - margin-bottom: 0; -} - -.no-horizontal-spacing, -table.table > thead > tr > th.no-horizontal-spacing, -table.table > tbody > tr > td.no-horizontal-spacing { - padding-left: 0; - padding-right: 0; - margin-left: 0; - margin-right: 0; -} - -.no-borders, -.table > thead > tr > th.no-borders, -.table > tbody > tr > td.no-borders { - border-bottom: 0; - border-top: 0; - border-left: 0; - border-right: 0; -} - -// For the collapsedmdouble menu -.navbar-nav { - @media (max-width: $screen-xs-max) { - &.navbar-left { - float: left; - width: 40%; - } - - &.navbar-right { - float: right; - width: 60%; - } - - .dropdown-menu .dropdown.open ul { - clear: both; - } - - .dropdown.open li { - display: block; - } - - .dropdown.open li a { - padding-left: 15px; - padding-right: 0; - } - - .dropdown.open .divider { - display: none; - } - - .dropdown.open .dropdown-menu {} - } -} -// Universal Style overrides -.page-header h1 { - margin-top: 0; // fixes button alignment easily -} - -[data-toggle='tooltip'] { - cursor: pointer; // for tooltips -} - -.alert-link { - text-decoration: underline; - font-weight: normal; -} - -.check_target { - cursor: pointer; -} -// Forms -#resultsForm { - overflow: hidden; -} - -input.error, -select.error, -.error input { - background: $state-danger-bg; - border-color: $state-danger-text; - color: $state-danger-text; -} - -.errorlist { - list-style-type: none; - margin: 0; - padding: 0; -} - -.error, -.errorlist li { - border-color: $state-danger-text; - color: $state-danger-text; -} - -.form-control-parent input { - @extend .form-control; -} - -.ballot-errors .errorlist { - list-style-type: disc; - margin: 0 2.5em; - padding: 0; -} - -.forfeits-group ul { - list-style-type: none; - - label { - width: 200px; - input[type='radio'].form-control { - float: left; - margin-right: 6px; - margin-top: -8px; - } - } - - li { - display: inline; - } -} - -input[type='radio'].form-control, -input[type='checkbox'].form-control { - display: inline; - margin-top: 0; - max-width: 20px; -} -// Modals -.modal-body { - overflow: auto; -} - -.modal-lg { - width: 98%; -} -// Tables - Specific -.adj-chair { - text-decoration: underline; -} - -.adj-trainee { - font-style: italic; -} -// Ballots -.scoresheet { - .score input { - width: 70px; - } - - .aff_total, - .neg_total { - width: 70px; - font-weight: bold; - cursor: default; - } -} - -.edit-ballot-link-discarded, -.edit-ballot-link-discarded:hover { - color: #808080; - text-decoration: line-through; -} - -// Motions -.assign-motions .list-group-item-text { - height: 54px; - overflow: hidden; -} - -// Scoresheets -.scoresheet-view { - .control-label { - text-align: right; - vertical-align: middle; - } - - .score { - width: 70px; - text-align: right; - } - - .total { - padding-top: 5px; - padding-bottom: 5px; - } - - .total.score { - font-weight: bold; - border-radius: 3px; - } - - .win { - background-color: #47a447; - color: white; - border-color: #398439; - } - - .loss { - background-color: #d2322d; - color: white; - border-color: #ac2925; - } - - .motion-veto { - text-decoration: line-through; - } -} - -.team-tab a.team-score { - // Darker than normal link, but not black - color: #285379; -} - -.feedback-integer-scale-table { - width: 100%; -} - -.feedback-integer-scale-table td { - text-align: center; -} - -.feedback-integer-scale-table input[type='radio'].form-control { - width: 20px; - margin: 0 auto; - vertical-align: middle; - display: block; -} - -.feedback-multiple-select .feedback-option { - display: inline-block; -} - -.feedback-multiple-select .feedback-option label { - margin-right: 20pt; -} - -.feedback-multiple-select input[type='checkbox'].form-control { - vertical-align: middle; - width: 20px; -} - -.forms-block-inline form { - display: inline-block; -} - -@media (max-width: $screen-xs-max) { - .page-header { - margin-top: 0; - } - - #header-options { - min-height: 82px; - } -} diff --git a/templates/tables/debate_icon.html b/templates/tables/debate_icon.html deleted file mode 100644 index 82311db6670..00000000000 --- a/templates/tables/debate_icon.html +++ /dev/null @@ -1,36 +0,0 @@ - - {% if debate.aff_team.type == 'B' or debate.neg_team.type == 'B' %} - - - - - {% elif debate.result_status == debate.STATUS_NONE %} - {% if not debate.ballot_in %} - - - - - {% else %} - - - - - {% endif %} - {% elif debate.result_status == debate.STATUS_DRAFT %} - - - - - {% elif debate.result_status == debate.STATUS_CONFIRMED %} - - - - - {% elif debate.result_status == debate.STATUS_POSTPONED %} - - - - - {% endif %} - - diff --git a/templates/tables/table_search.html b/templates/tables/table_search.html deleted file mode 100644 index 509639a1636..00000000000 --- a/templates/tables/table_search.html +++ /dev/null @@ -1,6 +0,0 @@ -
                  -
                  - - -
                  -
                  \ No newline at end of file diff --git a/templates/vue/division-droppable.vue b/templates/vue/division-droppable.vue deleted file mode 100644 index 716a6949f9e..00000000000 --- a/templates/vue/division-droppable.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - - - diff --git a/templates/vue/import-vue.html b/templates/vue/import-vue.html deleted file mode 100644 index b4cb53f4f06..00000000000 --- a/templates/vue/import-vue.html +++ /dev/null @@ -1,10 +0,0 @@ -{% load static %} -{% if debug %} - -{% else %} - -{% endif %} - diff --git a/templates/vue/printables/base-ballot-footer.vue b/templates/vue/printables/base-ballot-footer.vue deleted file mode 100644 index 17641e2521d..00000000000 --- a/templates/vue/printables/base-ballot-footer.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - diff --git a/templates/vue/printables/base-ballot-header.vue b/templates/vue/printables/base-ballot-header.vue deleted file mode 100644 index fa9e520c690..00000000000 --- a/templates/vue/printables/base-ballot-header.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - - - diff --git a/templates/vue/printables/base-ballot.vue b/templates/vue/printables/base-ballot.vue deleted file mode 100644 index 08f454cc162..00000000000 --- a/templates/vue/printables/base-ballot.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - - -{% include "vue/printables/base-ballot-header.vue" %} -{% include "vue/printables/base-ballot-footer.vue" %} -{% include "vue/printables/base-scoresheet.vue" %} -{% include "vue/printables/base-feedback.vue" %} - diff --git a/templates/vue/printables/feedback-question.vue b/templates/vue/printables/feedback-question.vue deleted file mode 100644 index b449fc41ef4..00000000000 --- a/templates/vue/printables/feedback-question.vue +++ /dev/null @@ -1,85 +0,0 @@ - - - - diff --git a/templates/vue/table.vue b/templates/vue/table.vue deleted file mode 100644 index a5f158906df..00000000000 --- a/templates/vue/table.vue +++ /dev/null @@ -1,56 +0,0 @@ - - - - - diff --git a/templates/vue/team-draggable.vue b/templates/vue/team-draggable.vue deleted file mode 100644 index b3236243da9..00000000000 --- a/templates/vue/team-draggable.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - - - diff --git a/tournaments/admin.py b/tournaments/admin.py deleted file mode 100644 index 25b70baa2f3..00000000000 --- a/tournaments/admin.py +++ /dev/null @@ -1,43 +0,0 @@ -from django.contrib import admin -from django import forms - -from .models import Tournament, Division, Round - -# ============================================================================== -# Tournament -# ============================================================================== - -class TournamentAdmin(admin.ModelAdmin): - list_display = ('name', 'seq', 'emoji', 'short_name', 'current_round') - ordering = ('seq', ) - - -admin.site.register(Tournament, TournamentAdmin) - -# ============================================================================== -# Division -# ============================================================================== - -class DivisionAdmin(admin.ModelAdmin): - list_display = ('name', 'tournament', 'venue_group', 'time_slot') - list_filter = ('tournament', 'venue_group') - search_fields = ('name', ) - ordering = ('tournament', 'name', ) - - -admin.site.register(Division, DivisionAdmin) - -# ============================================================================== -# Round -# ============================================================================== - -class RoundAdmin(admin.ModelAdmin): - list_display = ('name', 'tournament', 'seq', 'abbreviation', 'stage', - 'draw_type', 'draw_status', 'feedback_weight', 'silent', - 'motions_released', 'starts_at') - list_filter = ('tournament', ) - search_fields = ('name', 'seq', 'abbreviation', 'stage', 'draw_type', - 'draw_status') - - -admin.site.register(Round, RoundAdmin) diff --git a/tournaments/forms.py b/tournaments/forms.py deleted file mode 100644 index 1eeb0d72177..00000000000 --- a/tournaments/forms.py +++ /dev/null @@ -1,19 +0,0 @@ -from django.forms.fields import IntegerField -from django.forms import ModelForm -from .models import Tournament -from .utils import auto_make_rounds - -class TournamentForm(ModelForm): - - class Meta: - model = Tournament - fields = ('name', 'short_name', 'slug') - - num_prelim_rounds = IntegerField(min_value=1, label="Number of preliminary rounds") - - def save(self): - tournament = super(TournamentForm, self).save() - auto_make_rounds(tournament, self.cleaned_data["num_prelim_rounds"]) - tournament.current_round = tournament.round_set.first() - tournament.save() - return tournament diff --git a/tournaments/templates/division_allocations.html b/tournaments/templates/division_allocations.html deleted file mode 100644 index 7138b6a913f..00000000000 --- a/tournaments/templates/division_allocations.html +++ /dev/null @@ -1,108 +0,0 @@ -{% extends "base.html" %} -{% load debate_tags %} -{% load static %} - -{% block head-title %}Allocate Divisions{% endblock %} -{% block page-title %}Allocate Divisions{% endblock %} - -{% block page-subnav-sections %} - Auto Allocate Divisions - Add New Division - Auto Add Bye Teams -{% endblock %} - -{% block page-subnav-actions %} -
                  Preference Allocated:
                  -
                  -
                  1/2
                  -
                  3/4
                  -
                  5+
                  -
                  None
                  -
                  -{% endblock %} - -{% block content %} - - -
                  - -
                  - - - -
                  - -
                  -
                  - -
                  -
                  -

                  Teams without Divisions

                  -
                  -
                  - -
                  -
                  - -
                  -
                  - -
                  - -{% endblock content %} - -{% block extra-js %} - {% include "vue/import-vue.html" %} - {% include "vue/team-draggable.vue" %} - {% include "vue/division-droppable.vue" %} - - - -{% endblock extra-js %} diff --git a/tournaments/templates/tournament_index.html b/tournaments/templates/tournament_index.html deleted file mode 100644 index 657ba303d17..00000000000 --- a/tournaments/templates/tournament_index.html +++ /dev/null @@ -1,114 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} - -{% block page-title %}Dashboard{% endblock %} -{% block head-title %}Tournament Overview{% endblock %} -{% block body-id %}tournamentOverview{% endblock %} - -{% block sub-title %} - {{ round.name }} is {{ round.get_draw_status_display.lower }} - (this page will refresh its data automatically) -{% endblock %} - -{% block content %} - - {% if blank %} -
                  -

                  - Welcome to your new tournament! The next step is to - import your initial tournament data: the institutions, teams, adjudicators - and venues that are in your tournament. There are a number of ways to do - this. For small-to-medium tournaments, you can use the visual data importer. (This is also the - Setup > Import Data link on the left.) -

                  -

                  For more information, please consult our documentation on importing initial data.

                  -
                  - {% endif %} - -
                  -
                  -

                  - Number of Ballots In -

                  -
                  -
                  - -
                  -
                  -
                  -
                  - -
                  -
                  -

                  Latest Actions

                  -
                    - -
                  • No Actions In
                  • -
                  • Loading...
                  • -
                  -
                  -
                  -

                  Latest Results

                  -
                    - -
                  • No Results In
                  • -
                  • Loading...
                  • -
                  -
                  -
                  - -{% endblock content %} - -{% block extra-js %} - - -{% include "vue/import-vue.html" %} -{% include "vue/updates-list.vue" %} -{% include "vue/ballots-graph.vue" %} - - -{% endblock %} diff --git a/tournaments/templates/vue/ballots-graph.vue b/tournaments/templates/vue/ballots-graph.vue deleted file mode 100644 index c435d66470d..00000000000 --- a/tournaments/templates/vue/ballots-graph.vue +++ /dev/null @@ -1,124 +0,0 @@ - - - - - diff --git a/tournaments/templates/vue/updates-list.vue b/tournaments/templates/vue/updates-list.vue deleted file mode 100644 index 4e44a7403e4..00000000000 --- a/tournaments/templates/vue/updates-list.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - - - diff --git a/tournaments/urls.py b/tournaments/urls.py deleted file mode 100644 index b39fedddaba..00000000000 --- a/tournaments/urls.py +++ /dev/null @@ -1,112 +0,0 @@ -from django.conf.urls import * -from django.core.urlresolvers import reverse - -from . import views - -urlpatterns = [ - url(r'^$', - views.public_index, - name='tournament-public-index'), - url(r'^admin/overview/$', - views.TournamentAdminHomeView.as_view(), - name='tournament-admin-home'), - - #url(r'^admin/actions/$', 'action_log', name='action_log'), - - # TODO: 'core' app functionality? - url(r'^admin/round/(?P\d+)/round_increment_check/$', - views.round_increment_check, - name='round_increment_check'), - url(r'^admin/round/(?P\d+)/round_increment/$', - views.round_increment, - name='round_increment'), - - # Divisions Specific - url(r'^divisions/$', - views.public_divisions, - name='public_divisions'), - url(r'^admin/divisions/allocate/$', - views.division_allocations, - name='division_allocations'), - # POST METHODS - url(r'^admin/divisions/set_venue_group/$', - views.set_division_venue_group, - name='set_division_venue_group'), - url(r'^admin/divisions/set_team/$', - views.set_team_division, - name='set_team_division'), - url(r'^admin/divisions/set_time/$', - views.set_division_time, - name='set_division_time'), - # MANUAL ACTIONS - url(r'^admin/divisions/create/$', - views.create_division, - name='create_division'), - url(r'^admin/divisions/create_division_allocation/$', - views.create_division_allocation, - name='create_division_allocation'), - url(r'^admin/divisions/create_byes/$', - views.create_byes, - name='create_byes'), - - # WADL-specific; unclear if draws or participants - url(r'^all_tournaments_all_venues/$', - views.all_tournaments_all_venues, - name='all_tournaments_all_venues'), - url(r'^all_tournaments_all_venues/all_draws/(?P\d+)$', - views.all_draws_for_venue, - name='all_draws_for_venue'), - url(r'^all_tournaments_all_institutions/all_draws/(?P\d+)$', - views.all_draws_for_institution, - name='all_draws_for_institution'), - - # Action Logs App - url(r'^admin/action_log/', include('actionlog.urls')), - - # Allocations App - url(r'^admin/allocations/round/(?P\d+)/', - include('adjallocation.urls')), - - # Availabilities App - url(r'^admin/availability/round/(?P\d+)/', - include('availability.urls')), - - # Breaks App - url(r'^break/', include('breakqual.urls_public')), - url(r'^admin/break/', include('breakqual.urls_admin')), - - # Draws App - url(r'^draw/', include('draw.urls_public')), - url(r'^admin/draw/', include('draw.urls_admin')), - - # Feedbacks App - url(r'^feedback/', include('adjfeedback.urls_public')), - url(r'^admin/feedback/', include('adjfeedback.urls_admin')), - - # Importer App - url(r'^admin/import/', include('importer.urls')), - - # Motions App - url(r'^motions/', include('motions.urls_public')), - url(r'^admin/motions/round/(?P\d+)/', - include('motions.urls_admin')), - - # Options App - url(r'^admin/options/', include('options.urls')), - - # Participants App - url(r'^participants/', include('participants.urls_public')), - - # Results App - url(r'^results/', include('results.urls_public')), - url(r'^admin/results/', include('results.urls_admin')), - - # Standings App - url(r'^standings/', include('standings.urls_public')), - url(r'^tab/', include('standings.urls_public')), - url(r'^admin/standings/round/(?P\d+)/', - include('standings.urls_admin')), - - # Venues App - url(r'^admin/venues/', include('venues.urls_admin')), -] diff --git a/tournaments/utils.py b/tournaments/utils.py deleted file mode 100644 index a7cb5505a68..00000000000 --- a/tournaments/utils.py +++ /dev/null @@ -1,17 +0,0 @@ -from .models import Round - -def auto_make_rounds(tournament, num_rounds): - """Makes the number of rounds specified. The first one is random and the - rest are all power-paired. The last one is silent. This is intended as a - convenience function. For anything more complicated, a more advanced import - method should be used.""" - for i in range(1, num_rounds+1): - Round( - tournament=tournament, - seq=i, - name='Round %d' % i, - abbreviation='R%d' % i, - draw_type=Round.DRAW_RANDOM if (i == 1) else Round.DRAW_POWERPAIRED, - feedback_weight=min((i-1)*0.1, 0.5), - silent=(i == num_rounds), - ).save() \ No newline at end of file diff --git a/tournaments/views.py b/tournaments/views.py deleted file mode 100644 index cc9aa57373f..00000000000 --- a/tournaments/views.py +++ /dev/null @@ -1,307 +0,0 @@ -import json -import logging -logger = logging.getLogger(__name__) -from threading import Lock - -from django.conf import settings -from django.contrib.auth import authenticate, login, get_user_model -from django.contrib.auth.mixins import LoginRequiredMixin -User = get_user_model() -import django.contrib.messages as messages -from django.core import serializers -from django.core.urlresolvers import reverse_lazy -from django.views.generic.base import TemplateView -from django.views.generic.edit import FormView, CreateView - -from draw.models import Debate, DebateTeam -from participants.models import Team, Institution -from utils.forms import SuperuserCreationForm -from utils.mixins import SuperuserRequiredMixin -from utils.views import * -from utils.misc import redirect_tournament -from venues.models import VenueGroup, TeamVenueConstraint, InstitutionVenueConstraint - -from .forms import TournamentForm -from .mixins import TournamentMixin -from .models import Tournament, Division - -@cache_page(10) # Set slower to show new indexes so it will show new pages -@tournament_view -def public_index(request, t): - return render(request, 'public_tournament_index.html') - -def index(request): - tournaments = Tournament.objects.all() - if tournaments.count() == 1 and not request.user.is_authenticated(): - logger.debug('One tournament only, user is: %s, redirecting to tournament-public-index', request.user) - return redirect_tournament('tournament-public-index', tournaments.first()) - - elif not tournaments.exists() and not User.objects.exists(): - logger.debug('No users and no tournaments, redirecting to blank-site-start') - return redirect('blank-site-start') - - else: - return render(request, 'site_index.html', dict(tournaments=tournaments)) - -class TournamentAdminHomeView(LoginRequiredMixin, TournamentMixin, TemplateView): - - template_name = "tournament_index.html" - - def get_context_data(self, **kwargs): - tournament = self.get_tournament() - round = tournament.current_round - assert(round is not None) - kwargs["round"] = round - kwargs["readthedocs_version"] = settings.READTHEDOCS_VERSION - kwargs["blank"] = not (tournament.team_set.exists() or tournament.adjudicator_set.exists() or tournament.venue_set.exists()) - - draw = round.get_draw() - kwargs["total_ballots"] = draw.count() - stats_none = draw.filter(result_status=Debate.STATUS_NONE).count() - stats_draft = draw.filter(result_status=Debate.STATUS_DRAFT).count() - stats_confirmed = draw.filter(result_status=Debate.STATUS_CONFIRMED).count() - kwargs["stats"] = [[0,stats_confirmed], [0,stats_draft], [0,stats_none]] - - return super().get_context_data(**kwargs) - - def get(self, request, *args, **kwargs): - tournament = self.get_tournament() - if tournament.current_round is None: - if self.request.user.is_superuser: - tournament.current_round = tournament.round_set.order_by('seq').first() - if tournament.current_round is None: - return HttpResponse('

                  Error: This tournament has no rounds; you\'ll need to add some in the Edit Data area.

                  ') - messages.warning(self.request, "The current round wasn't set, so it's been automatically set to the first round.") - logger.warning("Automatically set current round to {}".format(tournament.current_round)) - tournament.save() - self.request.tournament = tournament # update for context processors - else: - raise Http404() - return super().get(self, request, *args, **kwargs) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('public_divisions') -def public_divisions(request, t): - divisions = Division.objects.filter(tournament=t).all().select_related('venue_group') - divisions = sorted(divisions, key=lambda x: x.name) - venue_groups = set(d.venue_group for d in divisions) - for uvg in venue_groups: - uvg.divisions = [d for d in divisions if d.venue_group == uvg] - - return render(request, 'public_divisions.html', dict(venue_groups=venue_groups)) - - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('enable_mass_draws') -def all_tournaments_all_venues(request, t): - venues = VenueGroup.objects.all() - return render(request, 'public_all_tournament_venues.html', dict(venues=venues)) - -@cache_page(settings.PUBLIC_PAGE_CACHE_TIMEOUT) -@public_optional_tournament_view('enable_mass_draws') -def all_draws_for_venue(request, t, venue_id): - venue_group = VenueGroup.objects.get(pk=venue_id) - debates = Debate.objects.filter(division__venue_group=venue_group).select_related( - 'round','round__tournament','division') - return render(request, 'public_all_draws_for_venue.html', dict( - venue_group=venue_group, debates=debates)) - - -@tournament_view -@public_optional_tournament_view('enable_mass_draws') -def all_draws_for_institution(request, t, institution_id): - # TODO: move to draws app - institution = Institution.objects.get(pk=institution_id) - debate_teams = DebateTeam.objects.filter(team__institution=institution).select_related( - 'debate', 'debate__division', 'debate__division__venue_group', 'debate__round') - debates = [dt.debate for dt in debate_teams] - - return render(request, 'public_all_draws_for_institution.html', dict( - institution=institution, debates=debates)) - - - -@admin_required -@round_view -def round_increment_check(request, round): - if round != request.tournament.current_round: # doesn't make sense if not current round - raise Http404() - num_unconfirmed = round.get_draw().filter(result_status__in=[Debate.STATUS_NONE, Debate.STATUS_DRAFT]).count() - increment_ok = num_unconfirmed == 0 - return render(request, "round_increment_check.html", dict(num_unconfirmed=num_unconfirmed, increment_ok=increment_ok)) - -@admin_required -@expect_post -@round_view -def round_increment(request, round): - if round != request.tournament.current_round: # doesn't make sense if not current round - raise Http404() - request.tournament.advance_round() - return redirect_round('availability_index', request.tournament.current_round ) - -@admin_required -@tournament_view -def division_allocations(request, t): - teams = list(Team.objects.filter(tournament=t).all().values( - 'id', 'short_reference', 'division', 'use_institution_prefix', 'institution__code', 'institution__id')) - - for team in teams: - team['institutional_preferences'] = list( - InstitutionVenueConstraint.objects.filter( - institution=team['institution__id']).values( - 'venue_group__short_name', 'priority', 'venue_group__id').order_by('-priority')) - team['team_preferences'] = list( - TeamVenueConstraint.objects.filter( - team=team['id']).values( - 'venue_group__short_name', 'priority', 'venue_group__id').order_by('-priority')) - - # team['institutional_preferences'] = "test" - # team['individual_preferences'] = "test" - - teams = json.dumps(teams) - - venue_groups = json.dumps(list( - VenueGroup.objects.all().values( - 'id', 'short_name', 'team_capacity'))) - - divisions = json.dumps(list(Division.objects.filter(tournament=t).all().values( - 'id', 'name', 'venue_group'))) - - return render(request, "division_allocations.html", dict( - teams=teams, divisions=divisions, venue_groups=venue_groups)) - -@admin_required -@tournament_view -def create_division(request, t): - division = Division.objects.create(name="temporary_name", tournament=t) - division.save() - division.name = "%s" % division.id - division.save() - return redirect_tournament('division_allocations', t) - -@admin_required -@tournament_view -def create_byes(request, t): - divisions = Division.objects.filter(tournament=t) - Team.objects.filter(tournament=t, type=Team.TYPE_BYE).delete() - for division in divisions: - teams_count = Team.objects.filter(division=division).count() - if teams_count % 2 != 0: - bye_institution, created = Institution.objects.get_or_create( - name="Byes", code="Byes") - bye_team = Team( - institution=bye_institution, - reference="Bye for Division " + division.name, - short_reference="Bye", - tournament=t, - division=division, - use_institution_prefix=False, - type=Team.TYPE_BYE - ).save() - - return redirect_tournament('division_allocations', t) - -@admin_required -@tournament_view -def create_division_allocation(request, t): - from tournaments.division_allocator import DivisionAllocator - - teams = list(Team.objects.filter(tournament=t)) - institutions = Institution.objects.all() - venue_groups = VenueGroup.objects.all() - - # Delete all existing divisions - this shouldn't affect teams (on_delete=models.SET_NULL)) - divisions = Division.objects.filter(tournament=t).delete() - - alloc = DivisionAllocator(teams=teams, divisions=divisions, venue_groups=venue_groups, tournament=t, institutions=institutions) - success = alloc.allocate() - - if success: - return redirect_tournament('division_allocations', t) - else: - return HttpResponseBadRequest("Couldn't create divisions") - -@admin_required -@expect_post -@tournament_view -def set_division_venue_group(request, t): - division = Division.objects.get(pk=int(request.POST['division'])) - if request.POST['venueGroup'] == '': - division.venue_group = None - else: - division.venue_group = VenueGroup.objects.get(pk=int(request.POST['venueGroup'])) - - print("saved venue group for for", division.name) - division.save() - return HttpResponse("ok") - -@admin_required -@expect_post -@tournament_view -def set_team_division(request, t): - team = Team.objects.get(pk=int(request.POST['team'])) - if request.POST['division'] == '': - team.division = None; - else: - team.division = Division.objects.get(pk=int(request.POST['division'])); - team.save() - print("saved divison for ", team.short_name) - - return HttpResponse("ok") - -@admin_required -@expect_post -@tournament_view -def set_division_time(request, t): - division = Division.objects.get(pk=int(request.POST['division'])) - if request.POST['division'] == '': - division = None; - else: - division.time_slot=request.POST['time'] - division.save(); - - return HttpResponse("ok") - - -class BlankSiteStartView(FormView): - """This view is presented to the user when there are no tournaments and no - user accounts. It prompts the user to create a first superuser. It rejects - all requests, GET or POST, if there exists any user account in the - system.""" - - form_class = SuperuserCreationForm - template_name = "blank_site_start.html" - lock = Lock() - success_url = reverse_lazy('tabbycat-index') - - def get(self, request): - if User.objects.exists(): - logger.error("Tried to get the blank-site-start view when a user account already exists.") - return redirect('tabbycat-index') - - return super().get(request) - - def post(self, request): - with self.lock: - if User.objects.exists(): - logger.error("Tried to post the blank-site-start view when a user account already exists.") - messages.error(request, "Whoops! It looks like someone's already created the first user account. Please log in.") - return redirect('auth-login') - - return super().post(request) - - def form_valid(self, form): - form.save() - user = authenticate(username=self.request.POST['username'], password=self.request.POST['password1']) - login(self.request, user) - messages.success(self.request, "Welcome! You've created an account for %s." % user.username) - - return super().form_valid(form) - -class CreateTournamentView(SuperuserRequiredMixin, CreateView): - """This view allows a logged-in superuser to create a new tournament.""" - - model = Tournament - form_class = TournamentForm - template_name = "create_tournament.html" diff --git a/utils/mixins.py b/utils/mixins.py deleted file mode 100644 index 19bea30f5ae..00000000000 --- a/utils/mixins.py +++ /dev/null @@ -1,108 +0,0 @@ -import logging -logger = logging.getLogger(__name__) - -from django.conf import settings -from django.contrib import messages -from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin -from django.core.urlresolvers import reverse_lazy -from django.http import HttpResponseRedirect -from django.utils.decorators import method_decorator -from django.views.decorators.cache import cache_page -from django.views.generic.base import View, TemplateResponseMixin -from django.views.generic.detail import SingleObjectMixin - -from tournaments.mixins import TournamentMixin - -from .misc import get_ip_address, redirect_tournament - - -class PostOnlyRedirectView(View): - """Base class for views that only accept POST requests. - - Current implementation redirects to a specified page (by default the home - page) if a client tries to use a GET request, and shows and logs an error - message. We might change this in the future just to return HTTP status code - 405 (HTTP method not allowed). - - Views using this class probably want to override both `post()` and - `get_redirect_url()`. It is assumed that the same redirect will be desired - the same whether GET or POST is used; it's just that a GET request won't - do database edits. - - Note: The `post()` implementation of subclasses should call `super().post()` - rather than returning the redirect directly, in case we decide to make - `post()` smarter in the future. If there ever arises a need to distinguish - between the redirects in the GET and POST cases, new methods should be added - to this base class for this purpose. - """ - - redirect_url = reverse_lazy('tabbycat-index') - not_post_message = "Whoops! You're not meant to type that URL into your browser." - - def get_redirect_url(self): - return self.redirect_url - - def get(self, request, *args, **kwargs): - logger.error("Tried to access a POST-only view with a GET request") - messages.error(self.request, self.not_post_message) - return HttpResponseRedirect(self.get_redirect_url()) - - def post(self, request, *args, **kwargs): - return HttpResponseRedirect(self.get_redirect_url()) - - -class SuperuserRequiredMixin(UserPassesTestMixin): - """Class-based view mixin. Requires user to be a superuser.""" - - def test_func(self): - return self.request.user.is_superuser - - -class SuperuserOrTabroomAssistantTemplateResponseMixin(LoginRequiredMixin, TemplateResponseMixin): - """Mixin for views that choose either a superuser view or an assistant view, - depending on the privileges of the user who is logged in. - - Views using this mixin must define the `superuser_template_name` and - `assistant_template_name` class attributes.""" - - superuser_template_name = None - assistant_template_name = None - - def get_template_names(self): - if self.request.user.is_superuser: - return [self.superuser_template_name] - else: - return [self.assistant_template_name] - - -class PublicCacheMixin: - """Mixin for views that cache the page.""" - - cache_timeout = settings.PUBLIC_PAGE_CACHE_TIMEOUT - - @method_decorator(cache_page(cache_timeout)) - def dispatch(self, *args, **kwargs): - return super().dispatch(*args, **kwargs) - - -class SingleObjectFromTournamentMixin(SingleObjectMixin, TournamentMixin): - """Mixin for views that relate to a single object that is part of a - tournament. Like SingleObjectMixin, but restricts searches to the relevant - tournament.""" - - def get_queryset(self): - return super().get_queryset().filter(tournament=self.get_tournament()) - - -class SingleObjectByRandomisedUrlMixin(SingleObjectFromTournamentMixin): - """Mixin for views that use URLs referencing objects by a randomised key. - This is just a `SingleObjectMixin` with some options set. - - Views using this mixin should have both a `url_key` group in their URL's - regular expression, and a primary key group (by default `pk`, inherited from - `SingleObjectMixin`, but this can be overridden). They should set the - `model` field of the class as they would for `SingleObjectMixin`. This model - should have a slug field called `url_key`. - """ - slug_field = 'url_key' - slug_url_kwarg = 'url_key' diff --git a/utils/tests.py b/utils/tests.py deleted file mode 100644 index 2bd1ee99fc6..00000000000 --- a/utils/tests.py +++ /dev/null @@ -1,38 +0,0 @@ -from django.test import TestCase -from tournaments.models import Tournament -from participants.models import Institution, Team, Speaker, Adjudicator -from venues.models import Venue - - -class BaseDebateTestCase(TestCase): - """Currently used in availability and participants tests as a pseudo fixture - to create teh basic data to simulate simple tournament functions""" - - def setUp(self): - super(BaseDebateTestCase, self).setUp() - # add test models - self.t = Tournament(slug="tournament") - self.t.save() - for i in range(4): - ins = Institution(code="INS%s"%i, name="Institution %s"%i) - ins.save() - for j in range(3): - team = Team(tournament=self.t, institution=ins, reference="Team%s%s" % (i,j)) - team.save() - for k in range(2): - speaker = Speaker(team=team, name="Speaker%s%s%s" % (i,j,k)) - speaker.save() - for j in range(2): - adj = Adjudicator(tournament=self.t, institution=ins, name="Adjudicator%s%s" % - (i,j), test_score=0) - adj.save() - - for i in range(8): - venue = Venue(name="Venue %s" % i) - venue.priority = i - venue.save() - - venue = Venue(name="IVenue %s" % i) - venue.priority = i - venue.save() - diff --git a/venues/conflicts.py b/venues/conflicts.py deleted file mode 100644 index 842c3a3c117..00000000000 --- a/venues/conflicts.py +++ /dev/null @@ -1,30 +0,0 @@ - -def _constraints_satisfied(constraints, venue): - """Returns True if either there are no constraints, or one constraint has - been meet. Returns False otherwise. `constraints` must be a query set.""" - return not constraints.exists() or constraints.filter(venue_group__venue=venue).exists() - -def venue_conflicts(debate): - """Returns a list of unfulfilled venue constraints for a debate. - A venue constraint is unfulfilled if, for a given participant, *none* of its - constraints were met. - - This function hits the database twice for each team and once for each adjudicator.""" - - conflicts = [] - venue = debate.venue - - for team in debate.teams: - constraints = team.teamvenueconstraint_set - if not _constraints_satisfied(constraints, venue): - conflicts.append("Venue does not meet constraints of team {}".format(team.short_name)) - constraints = team.institution.institutionvenueconstraint_set - if not _constraints_satisfied(constraints, venue): - conflicts.append("Venue does not meet constraints of institution {} ({})".format(team.institution.code, team.short_name)) - - for _, adjudicator in debate.adjudicators: - constraints = adjudicator.adjudicatorvenueconstraint_set - if not _constraints_satisfied(constraints, venue): - conflicts.append("Venue does not meet constraints of adjudicator {}".format(adjudicator.name)) - - return conflicts diff --git a/venues/templates/venues_edit.html b/venues/templates/venues_edit.html deleted file mode 100644 index a01e845443e..00000000000 --- a/venues/templates/venues_edit.html +++ /dev/null @@ -1,206 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load debate_tags %} - -{% block nav %}
                  {% endblock %} -{% block footer %}{% endblock %} - -{% block head-title %}Edit Venues for {{ round.abbreviation }}{% endblock %} -{% block page-title %}Edit Venues for {{ round.abbreviation }}{% endblock %} -{% block page-subnav-sections %} - {% include "tables/table_search.html" %} - Save Venues -
                  - {% csrf_token %} - -
                  - Quit -{% endblock %} - -{% block content %} -
                  - -
                  - - - - - - - - -
                  Unused Venues
                  - {% for venue in round.unused_venues %} -
                  - {{ venue }} -
                  - {% endfor %} -
                  - -
                  - -
                  - -
                  -
                  - - - - - {% if pref.enable_debate_scheduling %} - - {% endif %} - - - - - - - - {% for debate in draw %} - - - {% if pref.enable_debate_scheduling %} - - {% endif %} - - - {% include "tables/debate_adjudicators_compact.html" %} - - - {% endfor %} - -
                  TimeAffNegAdjsVenue
                  {{ debate.bracket }} - {% if debate.time %} - - {{ debate.time|time:'h:i A' }}
                  {{ debate.time|date:"D jS F" }} - {% endif %} -
                  - {% include "tables/team.html" with team=debate.aff_team %} - - {% include "tables/team.html" with team=debate.neg_team %} - - {% if debate.venue %} -
                  - {{ debate.venue }} -
                  - {% endif %} -
                  -
                  -
                  -
                  - -
                  -{% endblock content %} - -{% block extra-js %} - - -{% endblock extra-js %} diff --git a/venues/tests.py b/venues/tests.py deleted file mode 100644 index 7ce503c2dd9..00000000000 --- a/venues/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here.