Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[games][workshop] Big refactor:

- do not automatically create ws
- questions per assessment, not per workshop
- more than one group in the same time slot
  • Loading branch information...
commit 5dc45fd7af9eb4ddadff5c2cc2ce18902ab22e3b 1 parent 638cb76
@alexef alexef authored
View
9 wouso/core/user/templatetags/user.py
@@ -98,8 +98,9 @@ def spell_stock(player, spell):
return 'x%d' % stock if stock > 0 else '-'
@register.simple_tag
-def player_input(name):
+def player_input(name, id=None):
+ id = id if id else name
- return '<input type="hidden" name="{name}" id="ac_input_{name}_value" />' \
- '<input type="text" id="ac_input_{name}" class="ac_input big" />' \
- '<script>setAutocomplete("#ac_input_{name}");</script>'.format(name=name)
+ return '<input type="hidden" name="{name}" id="ac_input_{id}_value" />' \
+ '<input type="text" id="ac_input_{id}" class="ac_input big" />' \
+ '<script>setAutocomplete("#ac_input_{id}");</script>'.format(name=name, id=id)
View
4 wouso/games/workshop/admin.py
@@ -1,9 +1,9 @@
from django.contrib import admin
-from models import Schedule, Semigroup, Assesment, Workshop, Review, Answer
+from models import Schedule, Semigroup, Assessment, Workshop, Review, Answer
admin.site.register(Schedule)
admin.site.register(Semigroup)
-admin.site.register(Assesment)
+admin.site.register(Assessment)
admin.site.register(Workshop)
admin.site.register(Review)
admin.site.register(Answer)
View
76 wouso/games/workshop/cpanel.py
@@ -6,12 +6,12 @@
from models import WorkshopGame, Semigroup, Schedule
from wouso.core.decorators import staff_required
from wouso.core.user.models import Player
-from wouso.games.workshop.models import Workshop, Assesment, Review
+from wouso.games.workshop.models import Workshop, Assessment, Review
class AGForm(forms.ModelForm):
class Meta:
model = Semigroup
- fields = ('name', 'day', 'hour')
+ fields = ('name', 'day', 'hour', 'room')
@staff_required
def workshop_home(request, **kwargs):
@@ -74,16 +74,17 @@ def edit_spot(request, day, hour):
return redirect('ws_add_group')
if request.method == 'POST':
+ semigroup = get_object_or_404(Semigroup, pk=request.GET.get('semigroup'))
try:
player = Player.objects.get(pk=int(request.POST.get('player')))
except ValueError, Player.DoesNotExist:
pass
else:
- sg.add_player(player)
+ semigroup.add_player(player)
return render_to_response('workshop/cpanel/editspot.html',
{'module': 'workshop',
- 'semigroup': sg,
+ 'semigroups': sg,
},
context_instance=RequestContext(request)
)
@@ -178,13 +179,13 @@ def workshop_reviewers(request, workshop):
)
@staff_required
-def workshop_grade_assesment(request, assesment):
- assesment = get_object_or_404(Assesment, pk=assesment)
+def workshop_grade_assessment(request, assessment):
+ assessment = get_object_or_404(Assessment, pk=assessment)
assistant = request.user.get_profile()
if request.method == 'POST':
data = request.POST
- for a in assesment.answer_set.all():
+ for a in assessment.answer_set.all():
try:
grade = int(data.get('grade_%d' % a.id, ''))
except ValueError:
@@ -210,12 +211,63 @@ def workshop_grade_assesment(request, assesment):
r.review_grade = grade
r.review_reviewer = assistant
r.save()
- # Grade the entire assesment
- assesment.update_grade()
+ # Grade the entire assessment
+ assessment.update_grade()
- return render_to_response('workshop/cpanel/workshop_grade_assesment.html',
+ return render_to_response('workshop/cpanel/workshop_grade_assessment.html',
{'module': 'workshop',
- 'assesment': assesment,
+ 'assessment': assessment,
},
context_instance=RequestContext(request)
- )
+ )
+
+
+class WAForm(forms.ModelForm):
+ class Meta:
+ model = Workshop
+ exclude = ('start_at', 'active_until')
+
+
+@staff_required
+def workshop_add(request):
+ error = ''
+ if request.method == 'POST':
+ form = WAForm(request.POST)
+ if form.is_valid():
+ error = WorkshopGame.create_workshop(semigroup=form.cleaned_data['semigroup'],
+ date=form.cleaned_data['date'],
+ question_count=form.cleaned_data['question_count']
+ )
+ if not error:
+ return redirect('ws_workshops')
+ else:
+ form = WAForm()
+
+ return render_to_response('workshop/cpanel/workshop_add.html',
+ {'module': 'workshop', 'form': form, 'info': WorkshopGame, 'error': error},
+ context_instance=RequestContext(request)
+ )
+
+
+@staff_required
+def workshop_edit(request, workshop):
+ workshop = get_object_or_404(Workshop, pk=workshop)
+
+ pass
+
+
+@staff_required
+def workshop_start(request, workshop):
+ workshop = get_object_or_404(Workshop, pk=workshop)
+
+ workshop.start() # set start_at and active_until
+
+ return redirect('ws_workshops')
+
+@staff_required
+def workshop_stop(request, workshop):
+ workshop = get_object_or_404(Workshop, pk=workshop)
+
+ workshop.stop() # set active_until
+
+ return redirect('ws_workshops')
View
6 wouso/games/workshop/cpanel_urls.py
@@ -12,9 +12,13 @@
url(r'^schedule/edit/(?P<schedule>\d+)/$', 'schedule_change', name='ws_schedule_change'),
url(r'^workshops/$', 'workshops', name='ws_workshops'),
+ url(r'^workshops/add/$', 'workshop_add', name='ws_add_workshop'),
+ url(r'^workshops/edit/(?P<workshop>\d+)/$', 'workshop_edit', name='ws_edit_workshop'),
+ url(r'^workshops/start/(?P<workshop>\d+)/$', 'workshop_start', name='ws_start'),
+ url(r'^workshops/stop/(?P<workshop>\d+)/$', 'workshop_stop', name='ws_stop'),
url(r'^workshops/rev/(?P<workshop>\d+)/$', 'workshop_mark4review', name='ws_mark_for_review'),
url(r'^workshops/grd/(?P<workshop>\d+)/$', 'workshop_mark4grading', name='ws_mark_for_grading'),
url(r'^workshops/map/(?P<workshop>\d+)/$', 'workshop_reviewers', name='ws_reviewers_map'),
- url(r'^grade/assesment/(?P<assesment>\d+)/$', 'workshop_grade_assesment', name='ws_grade_assesment'),
+ url(r'^grade/assessment/(?P<assessment>\d+)/$', 'workshop_grade_assessment', name='ws_grade_assessment'),
)
View
195 wouso/games/workshop/models.py
@@ -1,3 +1,4 @@
+from random import shuffle
from datetime import datetime, time, timedelta
from django.db import models
from django.template.loader import render_to_string
@@ -13,11 +14,16 @@
(5, 'Friday'),
)
+ROOM_CHOICES = (
+ ('eg306', 'EG306'),
+ ('eg106', 'EG106'),
+)
+
class Schedule(Tag):
""" Schedule qpool tags per date intervals.
"""
- start_date = models.DateField()
- end_date = models.DateField()
+ start_date = models.DateField(default=datetime.today)
+ end_date = models.DateField(default=datetime.today)
@classmethod
def get_current_tags(cls, timestamp=None):
@@ -30,11 +36,17 @@ def is_active(self, timestamp=None):
timestamp = timestamp if timestamp else datetime.now()
return datetime.combine(self.start_date, time(0, 0, 0)) <= timestamp <= datetime.combine(self.end_date, time(23, 59, 59))
+
class Semigroup(PlayerGroup):
class Meta:
- unique_together = ('day', 'hour')
+ unique_together = ('day', 'hour', 'room')
day = models.IntegerField(choices=DAY_CHOICES)
hour = models.IntegerField(choices=zip(range(8, 22, 2), range(8, 22, 2)))
+ room = models.CharField(max_length=5, default='eg306', choices=ROOM_CHOICES, blank=True)
+
+ @property
+ def info(self):
+ return "spot: %s %d:00 room: %s" % (self.get_day_display(), self.hour, self.get_room_display())
def add_player(self, player):
""" Add player to semigroup, remove it from any other semigroups.
@@ -45,29 +57,43 @@ def add_player(self, player):
self.players.add(player)
@classmethod
- def get_by_day_and_hour(cls, day, hour):
+ def get_by_player(cls, player):
try:
- return cls.objects.get(day=day, hour=hour)
- except cls.DoesNotExist:
- return cls.objects.get_or_create(day=0, hour=0, name='default', owner=WorkshopGame.get_instance())[0]
+ return Semigroup.objects.filter(players=player).all()[0]
+ except:
+ return None
+
+ @classmethod
+ def get_by_day_and_hour(cls, day, hour):
+ """
+ Returns a list of groups in that timespan
+ """
+ qs = cls.objects.filter(day=day, hour=hour)
+ if qs.count():
+ return list(qs)
+
+ return [cls.objects.get_or_create(day=0, hour=0, name='default', owner=WorkshopGame.get_instance())[0]]
class Workshop(models.Model):
STATUSES = (
- (0, 'Started'),
+ (0, 'Ready'),
(1, 'Reviewing'),
(2, 'Grading'),
(3, 'Archived'),
)
semigroup = models.ForeignKey(Semigroup)
- date = models.DateField(auto_now_add=True)
+ date = models.DateField(default=datetime.today)
+ start_at = models.DateTimeField(blank=True, null=True)
active_until = models.DateTimeField(blank=True, null=True)
status = models.IntegerField(choices=STATUSES, default=0)
-
- questions = models.ManyToManyField(Question, blank=True)
+ question_count = models.IntegerField(default=4, blank=True)
def is_started(self):
return self.status == 0
+ def is_ready(self):
+ return self.status == 0
+
def is_active(self, timestamp=None):
timestamp = timestamp if timestamp else datetime.now()
if not self.active_until:
@@ -85,25 +111,57 @@ def set_gradable(self):
self.status = 2
self.save()
+ def get_or_create_assessment(self, player):
+ """ Return existing or new assessment for player
+ """
+ assessment, is_new = Assessment.objects.get_or_create(player=player, workshop=self)
+ if is_new:
+ questions = list(WorkshopGame.get_question_pool(self.date))
+ shuffle(questions)
+ for q in questions[:self.question_count]:
+ assessment.questions.add(q)
+ return assessment
+
+ def start(self, timestamp=None):
+ timestamp = timestamp if timestamp else datetime.now()
+
+ if self.is_ready():
+ self.start_at = timestamp
+ self.active_until = timestamp + timedelta(minutes=15)
+ self.save()
+ return True
+
+ return False
+
+ def stop(self):
+ if self.active_until > datetime.now():
+ self.active_until = datetime.now() - timedelta(seconds=1)
+ self.save()
+ return True
+ return False
+
def __unicode__(self):
return u"#%d - on %s" % (self.pk, self.date)
-class Assesment(models.Model):
+class Assessment(models.Model):
workshop = models.ForeignKey(Workshop)
- player = models.ForeignKey(Player, related_name='assesments')
+ player = models.ForeignKey(Player, related_name='assessments')
+ questions = models.ManyToManyField(Question, blank=True)
answered = models.BooleanField(default=False, blank=True)
time_start = models.DateTimeField(auto_now_add=True)
time_end = models.DateTimeField(blank=True, null=True)
- reviewers = models.ManyToManyField(Player, blank=True, related_name='assesments_review')
+ reviewers = models.ManyToManyField(Player, blank=True, related_name='assessments_review')
grade = models.IntegerField(blank=True, null=True)
+ reviewer_grade = models.IntegerField(blank=True, null=True)
+ final_grade = models.IntegerField(blank=True, null=True)
def set_answered(self, answers):
""" Set given answer dictionary.
"""
- for q in self.workshop.questions.all():
- a = Answer.objects.get_or_create(assesment=self, question=q)[0]
+ for q in self.questions.all():
+ a = Answer.objects.get_or_create(assessment=self, question=q)[0]
a.text = answers.get(q.id, '')
a.save()
self.answered = True
@@ -113,21 +171,27 @@ def set_answered(self, answers):
def update_grade(self):
""" Set grade as sum of every answer final grade
"""
- grade = Answer.objects.filter(assesment=self).aggregate(grade=models.Sum('grade'))['grade']
+ grade = Answer.objects.filter(assessment=self).aggregate(grade=models.Sum('grade'))['grade']
self.grade = grade
+ reviewer_grade = self.player.review_set.filter(answer__assessment=self).aggregate(grade=models.Sum('review_grade'))['grade']
+ self.reviewer_grade = reviewer_grade
+ try:
+ self.final_grade = (self.grade + self.reviewer_grade)/2
+ except TypeError: # one of the grades is None
+ self.final_grade = None
self.save()
@classmethod
def get_for_player_and_workshop(cls, player, workshop):
try:
return cls.objects.get(player=player, workshop=workshop)
- except:
+ except cls.DoesNotExist:
return None
__unicode__ = lambda self: u"#%d" % self.id
class Answer(models.Model):
- assesment = models.ForeignKey(Assesment)
+ assessment = models.ForeignKey(Assessment)
question = models.ForeignKey(Question, related_name='wsanswers')
text = models.TextField(max_length=2000)
@@ -150,7 +214,7 @@ class Review(models.Model):
review_grade = models.IntegerField(blank=True, null=True)
# Properties and methods
- workshop = property(lambda self: self.answer.assesment.workshop)
+ workshop = property(lambda self: self.answer.assessment.workshop)
__unicode__ = lambda self: u"%s by %s" % (self.feedback, self.reviewer)
class WorkshopGame(Game):
@@ -169,13 +233,13 @@ def get_spot(cls, timestamp=None):
""" Return the current laboratory as a day, hour pair
"""
timestamp = timestamp if timestamp else datetime.now()
- day = timestamp.weekday() + 1 # 1 = Monday, etc
+ day = (timestamp.weekday() + 1) % 7 + 1 # 1 = Monday, etc
hour = timestamp.hour - timestamp.hour % 2 # First lab starts at 8:00 AM
return day, hour
@classmethod
def get_semigroup(cls, timestamp=None):
- """ Return the semigroup having a laboratory right now.
+ """ Return the semigroup list having a laboratory right now.
"""
day, hour = cls.get_spot(timestamp)
return Semigroup.get_by_day_and_hour(day, hour)
@@ -189,43 +253,62 @@ def get_question_pool(cls, timestamp=None):
return questions
@classmethod
- def get_for_now(cls, timestamp=None, always=True):
- """ Return an workshop object or None.
+ def get_for_now(cls, timestamp=None):
+ """ Return a list of semigroups and workshops, or None if there isn't any workshop available.
Workshops are selected randomly from database.
"""
- # current semigroup
- semigroup = cls.get_semigroup(timestamp=timestamp)
+ day = timestamp.date() if timestamp else datetime.today()
- if not semigroup:
- return None
+ # current semigroup(s)
+ semigroups = cls.get_semigroup(timestamp=timestamp)
- # current tags and questions
- questions = cls.get_question_pool(timestamp=timestamp)
+ result = []
+ for s in semigroups:
+ result.append({'semigroup': s, 'workshop': cls.get_workshop(s, day)})
- if not questions:
- return None
-
- # Now decide if there is an workshop this week for this semigroup
- # TODO: magic. for now, always create one
- if always:
- return cls.get_or_create_workshop(semigroup, timestamp.date() if timestamp else datetime.today(), questions)
- return None
+ return result
@classmethod
def get_for_player_now(cls, player, timestamp=None):
- semigroup = cls.get_semigroup(timestamp=timestamp)
- if semigroup and player in semigroup.players.all():
- return cls.get_for_now(timestamp=timestamp)
+ timestamp = timestamp if timestamp else datetime.now()
+ ws = Workshop.objects.filter(start_at__lte=timestamp, active_until__gte=timestamp)
+ for w in ws:
+ if player in w.semigroup.players.all():
+ return w
+
return None
@classmethod
+ def get_workshop(cls, semigroup, date):
+ try:
+ return Workshop.objects.get(semigroup=semigroup, date=date)
+ except Workshop.DoesNotExist:
+ return None
+
+ @classmethod
+ def create_workshop(cls, semigroup, date, question_count=4):
+ """
+ Creates an workshop instance.
+
+ Returns: False if no error, string if error.
+ """
+ questions = cls.get_question_pool(date)
+
+ if not questions or questions.count() < question_count:
+ return "No questions for this date"
+
+ if cls.get_workshop(semigroup, date):
+ return "Workshop already exists for group at date"
+
+ Workshop.objects.create(semigroup=semigroup, date=date, question_count=question_count)
+
+ return False
+
+ @classmethod
def get_or_create_workshop(cls, semigroup, date, questions):
workshop, is_new = Workshop.objects.get_or_create(semigroup=semigroup, date=date)
if is_new:
- for q in questions:
- workshop.questions.add(q)
-
workshop.active_until = datetime.now() + timedelta(minutes=15)
workshop.save()
@@ -233,13 +316,13 @@ def get_or_create_workshop(cls, semigroup, date, questions):
@classmethod
def start_reviewing(cls, workshop):
- """ Set the reviewers for all assesments in this workshop
+ """ Set the reviewers for all assessments in this workshop
"""
- participating_players = [a.player for a in workshop.assesment_set.all()]
+ participating_players = [a.player for a in workshop.assessment_set.all()]
# TODO: magic, now only rotate
pp_rotated = [participating_players[-1]] + participating_players[:-1]
- for i,a in enumerate(workshop.assesment_set.all()):
+ for i,a in enumerate(workshop.assessment_set.all()):
a.reviewers.clear()
a.reviewers.add(pp_rotated[i])
@@ -251,10 +334,10 @@ def get_player_info(cls, player, workshop):
"""
Return information regarding specific workshop for the player
"""
- participated = Assesment.objects.filter(player=player, workshop=workshop).count() > 0
+ participated = Assessment.objects.filter(player=player, workshop=workshop).count() > 0
- reviews = Review.objects.filter(answer__assesment__workshop=workshop, reviewer=player)
- expected_reviews = Answer.objects.filter(assesment__in=player.assesments_review.all())
+ reviews = Review.objects.filter(answer__assessment__workshop=workshop, reviewer=player)
+ expected_reviews = Answer.objects.filter(assessment__in=player.assessments_review.all())
done = reviews.count() == expected_reviews.count()
@@ -268,10 +351,14 @@ def get_question_category(cls):
@classmethod
def get_sidebar_widget(cls, request):
player = request.user.get_profile()
- semigroup = cls.get_semigroup()
+ semigroups = cls.get_semigroup()
workshop = cls.get_for_player_now(player)
- assesment = Assesment.get_for_player_and_workshop(player, workshop)
- sm = request.user.get_profile() in semigroup.players.all() if semigroup else False
+ assessment = Assessment.get_for_player_and_workshop(player, workshop)
+ sm = False
+ for sg in semigroups:
+ if player in sg.players.all():
+ sm = True
+ break
return render_to_string('workshop/sidebar.html',
- {'semigroup': semigroup, 'workshop': workshop, 'semigroup_member': sm, 'assesment': assesment})
+ {'semigroups': semigroups, 'workshop': workshop, 'semigroup_member': sm, 'assessment': assessment})
View
8 wouso/games/workshop/templates/workshop/cpanel/editspot.html
@@ -3,6 +3,9 @@
{% load user %}
{% block tabcontent %}
+
+{% for semigroup in semigroups %}
+<h3>{{ semigroup.get_room_display }}</h3>
Semigroup: {{ semigroup }},
Spot: {% if semigroup.day %}day={{ semigroup.day }}, hour={{ semigroup.hour }}<a href="{% url ws_edit_group semigroup.pk %}">✍</a>.
{% else %}Any time where there isn't any other one.{% endif %}
@@ -22,9 +25,10 @@
</ul>
<p>Total: {{ semigroup.players.count }}.</p>
- <form action="" method="post">
- {% player_input 'player' %}
+ <form action="?semigroup={{semigroup.id}}" method="post">
+ {% player_input 'player' semigroup.id %}
{% csrf_token %}
<button type="submit">Add</button>
</form>
+{% endfor %}
{% endblock %}
View
6 wouso/games/workshop/templates/workshop/cpanel/index.html
@@ -26,7 +26,7 @@
{% if info %}
<p>
Current spot: {{ info.get_spot }}<br/>
- Current group: {{ info.get_semigroup }}<br/>
+ Current group: {{ info.get_semigroup|join:", " }}<br/>
Current qpool: {{ info.get_question_pool.count }}<br/>
</p>{% endif %}
{% endblock %}
@@ -47,7 +47,7 @@
{% for d in days %}
<td>
{% get_schedule d.0 h %}
- <a href="{% url ws_edit_spot d.0 h %}"></a>
+ <a href="{% url ws_edit_spot d.0 h %}">[✍]</a>
</td>
{% endfor %}
</tr>
@@ -57,6 +57,8 @@
<a class="button" href="{% url ws_add_group %}">Add semigroup</a>
<a class="button" href="{% url ws_edit_spot 0 0 %}">Default (testing)</a>
+ <br/>
+ <a class="button" href="{% url ws_add_workshop %}"><strong>Add workshop</strong></a>
{% endblock %}
</div>
</div>
View
13 wouso/games/workshop/templates/workshop/cpanel/workshop_add.html
@@ -0,0 +1,13 @@
+{% extends 'workshop/cpanel/index.html' %}
+
+{% block tabcontent %}
+
+<form action="" method="post">
+ <table>
+ {{ form.as_table }}
+ </table>
+ <button type="submit">Add</button>
+ {% csrf_token %}
+</form>
+
+{% endblock %}
View
10 ...tes/workshop/cpanel/workshop_grade_assesment.html → ...es/workshop/cpanel/workshop_grade_assessment.html
@@ -3,15 +3,15 @@
{% load user %}
{% load i18n %}
-{% block sectiontitle %}Workshop #{{ assesment.workshop.id }}{% endblock %}
+{% block sectiontitle %}Workshop #{{ assessment.workshop.id }}{% endblock %}
{% block tabcontent %}
-<p>Grading assesment #{{ assesment.id }}, of player: {% player_simple assesment.player %} for workshop {{ assesment.workshop }}:</p>
-<p>Final grade: {{ assesment.grade }}.</p>
+<p>Grading assessment #{{ assessment.id }}, of player: {% player_simple assessment.player %} for workshop {{ assessment.workshop }}:</p>
+<p>Final grade: {{ assessment.grade }}.</p>
<form method="post" action="">
<ul>
- {% for a in assesment.answer_set.all %}
+ {% for a in assessment.answer_set.all %}
<li>{{ forloop.counter }}. {{ a.question.text }}
<p> <em>{% trans 'Answer' %}:</em>
<tt>{{ a.text }}</tt>
@@ -53,5 +53,5 @@
<!--<button type="submit" name="submit" value="save_go_next">Save and see next</button>-->
</form>
-<a class="button" href="{% url ws_reviewers_map assesment.workshop.id %}">Back to review</a>
+<a class="button" href="{% url ws_reviewers_map assessment.workshop.id %}">Back to review</a>
{% endblock %}
View
10 wouso/games/workshop/templates/workshop/cpanel/workshop_map.html
@@ -5,19 +5,23 @@
{% block sectiontitle %}Workshop #{{ workshop.id }}{% endblock %}
{% block tabcontent %}
-<p>Assesments and reviewers:</p>
+<p>Assessments and reviewers:</p>
<table>
<tr>
<th colspan="2">Student</th>
<th>Grade</th>
+ <th>Review</th>
+ <th>Final</th>
</tr>
- {% for as in workshop.assesment_set.all %}
+ {% for as in workshop.assessment_set.all %}
<tr>
<td colspan="2">{{ as.player }}</td>
<td><strong>{{ as.grade }}</strong></td>
+ <td>{{ as.reviewer_grade }}</td>
+ <td>{{ as.final_grade }}</td>
<td>{% if workshop.is_gradable %}
- <a href="{% url ws_grade_assesment as.id %}">Grade</a>
+ <a href="{% url ws_grade_assessment as.id %}">Grade</a>
{% endif %}
</td>
</tr>
View
17 wouso/games/workshop/templates/workshop/cpanel/workshops.html
@@ -26,6 +26,8 @@
<tr>
<th>Id</th>
<th>Date</th>
+ <th>Start</th>
+ <th>End</th>
<th>Semigroup</th>
<th>Assesments</th>
<th>Status</th>
@@ -36,16 +38,24 @@
{{ w.id }}
</td>
<td>{{ w.date }}</td>
+ <td>{{ w.start_at|date:"H:i" }}</td>
+ <td>{{ w.active_until|date:"M. d, Y, H:i:s" }}</td>
<td>{{ w.semigroup }}</td>
<td align="right">{{ w.assesment_set.count }}</td>
- <td>{% if w.is_active %}Active until {{ w.active_until|date:"H:i" }}
- {% else %}Inactive, expired {{ w.active_until|date:"M. d, Y, H:i:s" }}
+ <td>{% if w.is_active %}Active
+ {% else %}Inactive
{% endif %}
<br/>
{{ w.get_status_display }}
</td>
<td>
<a href="{% url admin:workshop_workshop_change w.id %}">✍</a>
+ {% if not w.start_at %}
+ <a class="button" href="{% url ws_start w.id %}">Start</a>
+ {% endif %}
+ {% if w.is_started and w.is_active %}
+ <a class="button" href="{% url ws_stop w.id %}">Stop</a>
+ {% endif %}
{% if w.is_started and not w.is_active %}
<a href="{% url ws_mark_for_review w.id %}">Mark for review</a><br/>
{% endif %}
@@ -60,4 +70,7 @@
{% endfor %}
</table>
+ <br/>
+ <a class="button" href="{% url ws_add_workshop %}"><strong>Add workshop</strong></a>
+
{% endblock %}
View
8 wouso/games/workshop/templates/workshop/index.html
@@ -5,9 +5,13 @@
{% block sectiontitle %}{% trans 'Workshop' %}{% endblock %}
{% block sectioncontent %}
+<p>
+ {% trans 'Your semigroup:'%} {{ semigroup }} {{ semigroup.info }}
+</p>
+
<h4>{% trans 'Current workshop' %}</h4>
<p>{% if not workshop %}{% trans 'No current workshop' %}{% else %}
- {% if assesment.answered %}
+ {% if assessment.answered %}
{% trans 'Already answered' %}
{% else %}
{% if workshop.is_active %}
@@ -22,7 +26,7 @@
<h4>{% trans 'Past workshops' %}</h4>
<ul>
- {% for a in user.get_profile.assesments.all %}
+ {% for a in user.get_profile.assessments.all %}
<li>{{ a.workshop }}
{% if not a.workshop.is_active %}
<a href="{% url workshop_review a.workshop.id %}">{% trans 'Your reviews' %}</a>{% endif %}
View
4 wouso/games/workshop/templates/workshop/play.html
@@ -6,11 +6,11 @@
{% block sectioncontent %}
<p>Workshop available until: {{ workshop.active_until }}</p>
-<p>Assesment started: {{ assesment.time_start }}</p>
+<p>Assessment started: {{ assessment.time_start }}</p>
<form action="" method="post">
<table>
- {% for q in workshop.questions.all %}
+ {% for q in assessment.questions.all %}
<tr>
<td>{{ forloop.counter }}.</td>
<td>{{ q }}</td>
View
4 wouso/games/workshop/templates/workshop/results.html
@@ -6,9 +6,9 @@
{% block sectioncontent %}
-<p>{% trans "Your final grade is:" %} <strong>{{ assesment.grade }}</strong></p>
+<p>{% trans "Your final grade is:" %} <strong>{{ assessment.grade }}</strong></p>
<ul>
-{% for a in assesment.answer_set.all %}
+{% for a in assessment.answer_set.all %}
<li>{{ forloop.counter }}. {{ a.question.text }}
<p> <em>{% trans 'Your answer' %}:</em>
<tt>{{ a.text }}</tt>
View
2  wouso/games/workshop/templates/workshop/review.html
@@ -7,7 +7,7 @@
{% block sectioncontent %}
<ul>
- {% for as in assesments %}
+ {% for as in assessments %}
<li>{{ forloop.counter }}. {% trans 'Anonymous' %}
<ul>
View
2  wouso/games/workshop/templates/workshop/sidebar.html
@@ -5,7 +5,7 @@
{% block content %}
{% if semigroup_member %}
- {% trans 'Current semigroup:' %} {{ semigroup }}<br/>
+ {% trans 'Current semigroup:' %} {% for s in semigroups %}{{ s.name }} - {{ s.get_room_display }} {% endfor %}<br/>
{% if workshop %}
{% if workshop.is_active %}
{% if not assesment.answered %}
View
17 wouso/games/workshop/templatetags/workshop.py
@@ -1,25 +1,36 @@
+# coding=utf-8
from django import template
+from django.core.urlresolvers import reverse
from django.db.models import Sum
from wouso.games.workshop.models import Semigroup, Review
register = template.Library()
@register.simple_tag
+def semigroup(sg):
+ if not sg:
+ return ''
+
+ return u"%s [%d] %s <a href='%s'>✍</a>" % (sg.name, sg.players.count(),
+ sg.room, reverse('ws_edit_group', kwargs=dict(semigroup=sg.id)))
+
+
+@register.simple_tag
def get_schedule(day, hour):
- """ Render player name and level image with link to player's profile """
+ return ', '.join([semigroup(s) for s in Semigroup.get_by_day_and_hour(day, hour)])
- return Semigroup.get_by_day_and_hour(day, hour)
@register.simple_tag
def get_reviewer_grade(workshop, player):
""" Render sum of grades from reviewer
"""
- qs = Review.objects.filter(answer__assesment__workshop=workshop, reviewer=player)
+ qs = Review.objects.filter(answer__assessment__workshop=workshop, reviewer=player)
if not qs.count():
return None
else:
return qs.aggregate(grade=Sum('answer_grade'))['grade']
+
@register.simple_tag
def get_answer_feedback(answer, player):
""" Render the feedback text, if a review by player was given to answer
View
8 wouso/games/workshop/tests.py
@@ -14,7 +14,7 @@ def test_current_spot_semigroup(self):
self.assertEqual(spot_day, group.day)
self.assertEqual(spot_hour, group.hour)
- self.assertEqual(WorkshopGame.get_semigroup(timestamp=now), group)
+ self.assertEqual(WorkshopGame.get_semigroup(timestamp=now)[0], group)
def test_get_workshop_always(self):
now = datetime.now()
@@ -26,7 +26,7 @@ def test_get_workshop_always(self):
question = Question.objects.create()
question.tags.add(tag)
- ws = WorkshopGame.get_for_now(timestamp=now, always=True)
+ ws = WorkshopGame.get_for_now(timestamp=now)
self.assertTrue(ws)
@@ -41,8 +41,8 @@ def test_start_reviewing(self):
u1 = User.objects.create(username='u1').get_profile()
u2 = User.objects.create(username='u2').get_profile()
- a1 = Assesment.objects.create(player=u1, workshop=ws)
- a2 = Assesment.objects.create(player=u2, workshop=ws)
+ a1 = Assessment.objects.create(player=u1, workshop=ws)
+ a2 = Assessment.objects.create(player=u2, workshop=ws)
WorkshopGame.start_reviewing(ws)
View
47 wouso/games/workshop/views.py
@@ -3,58 +3,57 @@
from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.template.context import RequestContext
from django.utils.translation import ugettext as _
-from models import WorkshopGame
-from wouso.games.workshop.models import Assesment, Workshop, Answer, Review
+from models import WorkshopGame, Semigroup, Assessment, Workshop, Answer, Review
@login_required
def index(request, extra_context=None):
player = request.user.get_profile()
- assesment = Assesment.get_for_player_and_workshop(request.user.get_profile(), WorkshopGame.get_for_now())
+ assessment = WorkshopGame.get_for_player_now(player)
if not extra_context:
extra_context = {}
extra_context.update({'workshopgame': WorkshopGame, 'workshop': WorkshopGame.get_for_player_now(player),
- 'assesment': assesment})
+ 'assessment': assessment, 'semigroup': Semigroup.get_by_player(player)})
return render_to_response('workshop/index.html',
extra_context,
context_instance=RequestContext(request)
)
+
def do_error(request, error):
return index(request, extra_context={'error': error})
+
@login_required
def play(request):
"""
- Play current workshop or show expired message.
+ Play current workshop or show expired message.
"""
- workshop = WorkshopGame.get_for_now()
player = request.user.get_profile()
- error = ''
+ workshop = WorkshopGame.get_for_player_now(player=player)
if not workshop:
- return do_error(request, _('No current workshop'))
- elif player not in workshop.semigroup.players.all():
- return do_error(request, _('You are not in the current semigroup'))
- elif not workshop.is_active():
+ return do_error(request, _('No workshop for your semigroup'))
+
+ if not workshop.is_active():
return do_error(request, _('Workshop is not active'))
- assesment = Assesment.objects.get_or_create(player=player, workshop=workshop)[0]
- if assesment.answered:
+ assessment = workshop.get_or_create_assessment(player=player)
+ if assessment.answered:
return do_error(request, _('You have already answered this workshop'))
if request.method == 'POST':
answers = {}
- for q in workshop.questions.all():
+ for q in assessment.questions.all():
answers[q.id] = request.POST.get('answer_%d' % q.id)
- assesment.set_answered(answers)
+ assessment.set_answered(answers)
return redirect('workshop_index_view')
return render_to_response('workshop/play.html',
- {'assesment': assesment,
+ {'assessment': assessment,
'workshop': workshop},
context_instance=RequestContext(request)
)
@@ -64,12 +63,12 @@ def review(request, workshop):
player = request.user.get_profile()
workshop = get_object_or_404(Workshop, pk=workshop)
- assesment = Assesment.get_for_player_and_workshop(player, workshop)
+ assessment = Assessment.get_for_player_and_workshop(player, workshop)
- if not assesment:
+ if not assessment:
return do_error(request, _('Cannot review an workshop you did not participate to.'))
- assesments = player.assesments_review.filter(workshop=workshop)
+ assessments = player.assessments_review.filter(workshop=workshop)
if request.method == 'POST':
answer = get_object_or_404(Answer, pk=request.GET.get('a'))
@@ -80,9 +79,9 @@ def review(request, workshop):
review.save()
return render_to_response('workshop/review.html',
- {'assesment': assesment,
+ {'assessment': assessment,
'workshop': workshop,
- 'assesments': assesments},
+ 'assessments': assessments},
context_instance=RequestContext(request)
)
@@ -121,13 +120,13 @@ def results(request, workshop):
player = request.user.get_profile()
workshop = get_object_or_404(Workshop, pk=workshop)
- assesment = Assesment.get_for_player_and_workshop(player, workshop)
+ assessment = Assessment.get_for_player_and_workshop(player, workshop)
- if not assesment:
+ if not assessment:
return do_error(request, _('Cannot view results for an workshop you did not participate to.'))
return render_to_response('workshop/results.html',
- {'assesment': assesment,
+ {'assessment': assessment,
'workshop': workshop},
context_instance=RequestContext(request)
)
Please sign in to comment.
Something went wrong with that request. Please try again.