Skip to content

Commit

Permalink
Merge branch 'master' into feature/genetic-algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
Lancasterwu authored Mar 14, 2019
2 parents b1daf25 + 985b49f commit c7835b1
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 35 deletions.
19 changes: 16 additions & 3 deletions gatorgrouper/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,22 @@ class Meta:
class UploadCSVForm(forms.Form):
""" Form enabling the uploading of a CSV file to be used for grouping """

file = forms.FileField(label="Student data CSV file")
numgrp = forms.IntegerField(
min_value=2, max_value=25, label="Number of groups to create"
student_data = forms.FileField(label="Student data CSV file")
student_preferences = forms.FileField(
label="Student preferences CSV file", required=False
)
numgrp = forms.TypedChoiceField(
choices=[
(str(2 ** i), str(2 ** i)) for i in range(1, 5)
], # Restrict choices to powers of 2
coerce=int,
label="Number of groups to create",
)
preferences_weight = forms.FloatField(
label="Importance of an unmatched preference", initial=1.1, min_value=1.0
)
preferences_weight_match = forms.FloatField(
label="Importance of a matched preference", initial=1.25, min_value=1.0
)


Expand Down
23 changes: 19 additions & 4 deletions gatorgrouper/templates/gatorgrouper/upload_csv.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,32 @@
<div class="content-section">

<fieldset class="form-group">
<legend class="border-bottom mb-4">Create a New Assignment</legend>
<form action="/group/" method="post" enctype="multipart/form-data">
<legend class="border-bottom mb-4">Create Groups</legend>
<p>
GatorGrouper supports creating groups via an uploaded CSV file. To save your data and groups across multiple sessions, create an account today!
</p>
<form action="/upload-csv/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
{{ form.file.label_tag }}
<input type="file" name="file" class="btn btn-outline-info"/>
{{ form.student_data.label_tag }}
<input type="file" name="student_data" class="btn btn-outline-info"/>
</div>
<div class="form-group">
{{ form.student_preferences.label_tag }}
<input type="file" name="student_preferences" class="btn btn-outline-info"/>
</div>
<div class="form-group">
{{ form.numgrp.label_tag }}
{{ form.numgrp }}
</div>
<div class="form-group">
{{ form.preferences_weight.label_tag }}
{{ form.preferences_weight }}
</div>
<div class="form-group">
{{ form.preferences_weight_match.label_tag }}
{{ form.preferences_weight_match }}
</div>
</fieldset>
<input type="submit" value="Submit" class="btn btn-outline-info"/>
<small class="text-muted">Back to Dashboard</small>
Expand Down
17 changes: 17 additions & 0 deletions gatorgrouper/templates/gatorgrouper/viewing-groups-csv.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% extends "gatorgrouper/base.html" %}
{% block content %}

<div class="container">
<h2>Team Groupings</h2>
<div class="list-group">
{% for group in groups %}
<h4 class="list-group-item-heading">Team #{{ forloop.counter }}</h4>
<ul>
{% for student in group %}
<li class="list-group-item-text">{{ student | first }}</li>
{% endfor %}
</ul>
{% endfor %}
</div>
</div>
{% endblock %}
2 changes: 1 addition & 1 deletion gatorgrouper/templates/upload.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<html>
<body>
<form action="/group/" method="post" enctype="multipart/form-data">
<form action="/upload-csv/" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
Expand Down
1 change: 1 addition & 0 deletions gatorgrouper/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
path("group-result/", views.groupResult, name="Gatorgrouper-groups"),
path("add-students/", views.add_students, name="add-students"),
path("create-groups/", views.create_groups, name="create-groups"),
path("upload-csv/", views.upload_csv, name="upload-csv"),
]
84 changes: 57 additions & 27 deletions gatorgrouper/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
""" This is undocumented """
import csv
import re
from io import StringIO
from django.shortcuts import render, redirect
from django.forms import modelform_factory
Expand All @@ -11,6 +12,7 @@
from .models import Semester_Class, Student
from .models import Grouped_Student, Assignment
from .utils.gatherInfo import gatherStudents
from .utils.group_graph import group_graph_partition
from .utils.group_rrobin import group_rrobin_num_group
from .forms import UploadCSVForm, CreateGroupForm
from .forms import CustomUserCreationForm
Expand All @@ -21,18 +23,67 @@ def upload_csv(request):
if request.method == "POST":
form = UploadCSVForm(request.POST, request.FILES)
if form.is_valid():
responses = handle_uploaded_file(request.FILES["file"])
responses = parse_uploaded_csv(request.FILES["student_data"])
if request.FILES.get("student_preferences"):
preferences = parse_uploaded_csv(
request.FILES["student_preferences"], as_dict=True
)
else:
preferences = None
numgrp = form.cleaned_data["numgrp"]
groups = group_rrobin_num_group(responses, numgrp)
preferences_weight = form.cleaned_data["preferences_weight"]
preferences_weight_match = form.cleaned_data["preferences_weight_match"]
groups = group_graph_partition(
responses,
numgrp,
preferences=preferences,
preferences_weight=preferences_weight,
preferences_weight_match=preferences_weight_match,
)
return render(
request, "gatorgrouper/viewing-groups.html", {"groups": groups}
request, "gatorgrouper/viewing-groups-csv.html", {"groups": groups}
)
else:
form = UploadCSVForm()
return render(request, "gatorgrouper/upload_csv.html", {"form": form})


# Create your views here.
def parse_uploaded_csv(csvfile, as_dict=False):
"""
Transform uploded CSV data into list of student responses:
[["student name", True, False, ...], ...]
With the as_dict parameter set to True, transforms the CSV data into a dictionary of sets:
{"student name": {True, False, ...}, ...}
"""
f = StringIO(csvfile.read().decode("utf-8"))
csvdata = list(csv.reader(f, delimiter=","))

# transform into desired output
responses = list()
responses_dict = {}
for record in csvdata:
if as_dict:
responses_dict[record[0]] = set() # Create key in responses dictionary
temp = list()
temp.append(record[0].replace('"', ""))
for value in record[1:]:
if value.lower() == "true":
temp.append(True)
elif value.lower() == "false":
temp.append(False)
elif re.match(
r"[+-]?([0-9]*[.])?[0-9]+", value # pylint: disable=bad-continuation
): # Match a float with regex
temp.append(float(value))
else: # Keep the value as a string if no other type matches
temp.append(value)
if as_dict: # Assign the value to the responses set for this row
responses_dict[record[0]].add(value)
responses.append(temp)
return responses if not as_dict else responses_dict


def register(request):
""" This view loads the register page and handles the form """
if request.method == "POST":
Expand Down Expand Up @@ -72,28 +123,6 @@ def profile(request):
)


def handle_uploaded_file(csvfile):
"""
Transform uploded CSV data into list of student responses:
[["student name", True, False, ...]]
"""
f = StringIO(csvfile.read().decode("utf-8"))
csvdata = list(csv.reader(f, delimiter=","))

# transform into desired output
responses = list()
for record in csvdata:
temp = list()
temp.append(record[0].replace('"', ""))
for value in record[1:]:
if value.lower() == "true":
temp.append(True)
elif value.lower() == "false":
temp.append(False)
responses.append(temp)
return responses


def home(request):
""" Homepage view """

Expand Down Expand Up @@ -214,13 +243,14 @@ def add_students(request):
)


@login_required
def create_groups(request): # pylint: disable=too-many-locals
""" Created groups using gatorgrouper functions """
GroupedStudentFormSet = modelform_factory(
Grouped_Student, fields=("assignment_id",)
)
groups = []
if not request.user.is_authenticated:
return redirect("upload-csv")
# pylint: disable=too-many-nested-blocks
if request.method == "POST":
formset = GroupedStudentFormSet(request.POST)
Expand Down

0 comments on commit c7835b1

Please sign in to comment.