Skip to content

Commit

Permalink
working /hacks; working grade results (with manually added data); adm…
Browse files Browse the repository at this point in the history
…in fixes
  • Loading branch information
jrdbnntt committed Feb 19, 2017
1 parent 47210c4 commit e18290c
Show file tree
Hide file tree
Showing 13 changed files with 209 additions and 25 deletions.
19 changes: 19 additions & 0 deletions api/migrations/0026_remove_judgingcriteria_devpost_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-19 08:56
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('api', '0025_auto_20170219_0255'),
]

operations = [
migrations.RemoveField(
model_name='judgingcriteria',
name='devpost_name',
),
]
32 changes: 32 additions & 0 deletions api/migrations/0027_auto_20170219_0407.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-19 09:07
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('api', '0026_remove_judgingcriteria_devpost_name'),
]

operations = [
migrations.AddField(
model_name='judgingassignment',
name='judge',
field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='api.JudgeInfo'),
preserve_default=False,
),
migrations.AlterField(
model_name='hack',
name='extra_judging_criteria',
field=models.ManyToManyField(blank=True, to='api.JudgingCriteria'),
),
migrations.AlterField(
model_name='judgingcriteria',
name='criteria_type',
field=models.SmallIntegerField(choices=[(0, 'Overall'), (1, 'Superlative'), (2, 'Manual')]),
),
]
22 changes: 14 additions & 8 deletions api/models/hack.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ class Hack(models.Model):
objects = HackManager()
hackathon = models.ForeignKey(to=Hackathon, on_delete=models.CASCADE)
table_number = models.IntegerField()
name = models.CharField(max_length=100) # Devpost "Submission Title"
description = models.TextField() # Devpost "Plain Description"
extra_judging_criteria = models.ManyToManyField(to=JudgingCriteria) # Devpost "Desired Prizes"
name = models.CharField(max_length=100) # Devpost "Submission Title"
description = models.TextField() # Devpost "Plain Description"
extra_judging_criteria = models.ManyToManyField(to=JudgingCriteria, blank=True) # Devpost "Desired Prizes"

def get_expo(self):
expo = JudgingExpo.objects.filter(
Expand All @@ -37,6 +37,15 @@ def get_expo_name(self) -> str:
return 'N/A'
return expo.name

def get_criteria_names(self) -> str:
names = []
for criteria in self.extra_judging_criteria.all():
names.append(criteria.name)
return ', '.join(names)

def __str__(self):
return self.name


@admin.register(Hack, site=hackfsu_admin)
class HackAdmin(admin.ModelAdmin):
Expand All @@ -52,8 +61,5 @@ def expo(obj: Hack):
return obj.get_expo_name()

@staticmethod
def extra_criteria(obj: Hack):
names = []
for criteria in obj.extra_judging_criteria.all():
names.append(criteria.name)
return ', '.join(names)
def extra_criteria(obj: Hack) -> str:
return obj.get_criteria_names()
2 changes: 1 addition & 1 deletion api/models/judging_assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class JudgingAssignment(models.Model):

hackathon = models.ForeignKey(to=Hackathon, on_delete=models.CASCADE)
hack = models.ForeignKey(to=Hack, on_delete=models.CASCADE)
judge = models.ForeignKey(to=JudgeInfo, on_delete=models.CASCADE),
judge = models.ForeignKey(to=JudgeInfo, on_delete=models.CASCADE)
status = models.SmallIntegerField(choices=STATUS_CHOICES, default=STATUS_PENDING)


Expand Down
10 changes: 6 additions & 4 deletions api/models/judging_criteria.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class JudgingCriteria(models.Model):
CRITERIA_TYPE_OVERALL = 0,
CRITERIA_TYPE_OVERALL = 0
CRITERIA_TYPE_SUPERLATIVE = 1
CRITERIA_TYPE_MANUAL = 2
CRITERIA_TYPE = (
Expand All @@ -15,18 +15,20 @@ class JudgingCriteria(models.Model):
)

hackathon = models.ForeignKey(to=Hackathon, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
name = models.CharField(max_length=50) # Must correspond EXACTLY with Devpost name
point_contribution = models.IntegerField()
criteria_type = models.SmallIntegerField(choices=CRITERIA_TYPE)
description_long = models.CharField(max_length=500) # Displayed in instructions
description_short = models.CharField(max_length=100) # Displayed next to score entry
devpost_name = models.CharField(max_length=200) # The name that should correspond with devpost csv 'Desired Prizes'

def __str__(self):
return self.name


@admin.register(JudgingCriteria, site=hackfsu_admin)
class JudgingCriteriaAdmin(admin.ModelAdmin):
list_filter = ('hackathon', 'criteria_type')
list_display = ('id', 'criteria_type', 'point_contribution', 'name', 'description_long', 'description_short')
list_display = ('id', 'criteria_type', 'name', 'point_contribution', 'description_long', 'description_short')
list_editable = ('criteria_type', 'point_contribution', 'name', 'description_long', 'description_short')
list_display_links = ('id',)
search_fields = ('name',)
Expand Down
32 changes: 25 additions & 7 deletions api/views/judge/get/grades.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@

def average_criteria_result(result):
""" Averages a single criteria section and determines point value """
result['contribution'] = 1.0 * result['running_total'] / result['times_graded'] * result['max_contribution']
result['contribution'] = 1.0 * result['running_total'] / result['times_graded'] / 100 * result['max_contribution']


def average_criteria_results(results):
def average_criteria_results(results: dict):
# Get point contributions for every criteria
for grade_group in results:
for criteria_result in grade_group:
for type_id, grade_group in results.items():
for result_id, criteria_result in grade_group.items():
average_criteria_result(criteria_result)

# Add overall grade (sum of overall criteria contributions)
final_grade = 0.0
for criteria_result in results[JudgingCriteria.CRITERIA_TYPE_OVERALL]:
for criteria_id, criteria_result in results[JudgingCriteria.CRITERIA_TYPE_OVERALL].items():
final_grade += criteria_result['contribution']
results[JudgingCriteria.CRITERIA_TYPE_OVERALL][CRITERIA_OVERALL_ID] = {
'running_total': final_grade,
'times_graded': results[JudgingCriteria.CRITERIA_TYPE_OVERALL][0]['times_graded'],
'times_graded': next(iter(results[JudgingCriteria.CRITERIA_TYPE_OVERALL].values()))['times_graded'],
'max_contribution': 100,
'contribution': final_grade
}
Expand All @@ -52,10 +52,12 @@ def work(self, request, req, res):
current_hack = None
current_hack_results = None
for grade in JudgingGrade.objects.filter(hackathon=hackathon).order_by('hack').all():
print('{} {} {}'.format(grade.hack.table_number, grade.criteria.name, grade.grade))
if current_hack != grade.hack:
if current_hack is not None:
# Accumulate and save final results
average_criteria_results(current_hack_results)
print('hack results', current_hack_results)
graded_hacks.append({
'hack': {
'name': current_hack.name,
Expand Down Expand Up @@ -84,14 +86,30 @@ def work(self, request, req, res):
result['running_total'] += grade.grade
result['times_graded'] += 1

# Do last hack
if current_hack is not None and current_hack_results is not None:
# Accumulate and save final results
average_criteria_results(current_hack_results)
print('hack results', current_hack_results)
graded_hacks.append({
'hack': {
'name': current_hack.name,
'table_number': current_hack.table_number
},
'results': current_hack_results
})

res['graded_hacks'] = graded_hacks

# Map criteria id to name
criteria_names = {
JudgingCriteria.CRITERIA_TYPE_OVERALL: dict(),
JudgingCriteria.CRITERIA_TYPE_SUPERLATIVE: dict()
}
for criteria in JudgingCriteria.objects.filter(hackathon=hackathon).all():
for criteria in JudgingCriteria.objects.filter(
hackathon=hackathon,
criteria_type__in=[JudgingCriteria.CRITERIA_TYPE_OVERALL, JudgingCriteria.CRITERIA_TYPE_SUPERLATIVE]
).distinct().all():
criteria_names[criteria.criteria_type][criteria.id] = criteria.name

res['criteria_names'] = criteria_names
Expand Down
6 changes: 1 addition & 5 deletions api/views/judge/get/hacks_with_criteria.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,10 @@ class HacksWithCriteriaView(ApiView):
def work(self, request, req, res):
hacks = []
for hack in Hack.objects.filter(hackathon=Hackathon.objects.current()):
criteria_names = []
for criteria in hack.extra_judging_criteria.filter(status=JudgingCriteria.CRITERIA_TYPE_MANUAL)\
.order_by('id').all():
criteria_names.append(criteria.name)
hacks.append({
'table_number': hack.table_number,
'name': hack.name,
'expo': hack.get_expo_name(),
'criteria': ', '.join(criteria_names)
'criteria': hack.get_criteria_names()
})
res['hacks'] = hacks
2 changes: 2 additions & 0 deletions webapp/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ def static_redirect(path):

url(r'^links/$', views.LinksPage.as_view()),

url(r'^hacks/$', views.HacksPage.as_view()),

# Shortcuts
url(r'^register/$', RedirectView.as_view(url='/registration/user')),
url(r'^register/hacker/$', RedirectView.as_view(url='/registration/user?attendee_type=hacker')),
Expand Down
1 change: 1 addition & 0 deletions webapp/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .index import IndexPage
from .help import HelpPage
from .links.index import LinksPage
from .hacks.index import HacksPage
from django.shortcuts import render


Expand Down
Empty file added webapp/views/hacks/__init__.py
Empty file.
18 changes: 18 additions & 0 deletions webapp/views/hacks/index.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
extends ../../_pug/standardLayout.pug

block vars
-
var pageName = "Submitted Hacks"
var viewDir = "/static/views/hacks"
var DataTables = true
block append scripts
script(src=`${viewDir}/script.js`)

block content
h1 Submitted Hacks
p If you do not see yourself or something is wrong, notify an organizer! This list was exported from Devpost and then imported into our internal judging system. Our system will ensure that your hack is graded in a fair and timely manner. Good luck!
p When it is not your turn to expo, check out the other hackers' projects!
p: b: i IF YOU ARE NOT AT YOUR TABLE YOU MAY BE DISQUALIFIED, STAY THERE.

table#hacks.table.table-striped.table-bordered(cellspacing="0" width="100%")
9 changes: 9 additions & 0 deletions webapp/views/hacks/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""
Public hack roster
"""

from hackfsu_com.views.generic import PageView


class HacksPage(PageView):
template_name = 'hacks/index.html'
81 changes: 81 additions & 0 deletions webapp/views/hacks/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Mentor help request view page
*/

(function($) {
'use strict';

var table = $('table#hacks');

var COLS = {
'Table Number': { data: 'table_number' },
'Hack Name': { data: 'name' },
'Expo': { data: 'expo' },
'Opt-In Prizes' : { data: 'criteria'}
};

/**
* Formats the table html
*/
function createTable(table, colData) {
var tableHead = $('<thead><tr></tr></thead>');
var tableHeadRow = tableHead.find('tr');

Object.keys(colData).forEach(function(columnName) {
tableHeadRow.append('<th>'+columnName+'</th>');
});

table.append(tableHead);
table.append('<tbody></tbody>');
}

/**
* Retrieves data
*/
function getData() {
var dfd = $.Deferred();

$.ajaxGet({
url: '/api/judge/get/hacks_with_criteria'
})
.done(function(res) {
dfd.resolve(res['hacks']);
})
.fail(function(err) {
dfd.reject(err);
});

return dfd.promise();
}

/**
* Populates the DataTable with help requests
*/
function populateTable(table, colData, data) {
var colNames = Object.keys(colData);

table.DataTable({
dom:
"<'row flex-align-center flex-wrap'<'col-sm-6'l><'col-sm-6'f>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
responsive: true,
lengthMenu: [[25, 50, 100, -1], [25, 50, 100, 'All']],
data: data,
columns: $.map(colData, function(data) {
return data;
}),
order: [
[colNames.indexOf('Table Number'), 'asc']
]
});
}

// Create page
createTable(table, COLS);
getData().done(function(data) {
populateTable(table, COLS, data);
});


})(jQuery);

0 comments on commit e18290c

Please sign in to comment.