virtualcommons-svn Mailing List for Virtual Commons Experiment Software (Page 36)
Status: Beta
Brought to you by:
alllee
You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
(21) |
Aug
(31) |
Sep
(6) |
Oct
(15) |
Nov
(2) |
Dec
(9) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(4) |
Feb
(6) |
Mar
(12) |
Apr
(52) |
May
(14) |
Jun
(19) |
Jul
(81) |
Aug
(115) |
Sep
(36) |
Oct
(88) |
Nov
(46) |
Dec
(58) |
2010 |
Jan
(52) |
Feb
(55) |
Mar
(48) |
Apr
(15) |
May
(5) |
Jun
(38) |
Jul
(27) |
Aug
(24) |
Sep
(28) |
Oct
(1) |
Nov
(2) |
Dec
(29) |
2011 |
Jan
(87) |
Feb
(39) |
Mar
(63) |
Apr
(42) |
May
(26) |
Jun
(53) |
Jul
(23) |
Aug
(43) |
Sep
(37) |
Oct
(25) |
Nov
(4) |
Dec
(7) |
2012 |
Jan
(73) |
Feb
(79) |
Mar
(62) |
Apr
(28) |
May
(12) |
Jun
(2) |
Jul
(9) |
Aug
(1) |
Sep
(8) |
Oct
|
Nov
(3) |
Dec
(3) |
2013 |
Jan
(8) |
Feb
(16) |
Mar
(38) |
Apr
(74) |
May
(62) |
Jun
(15) |
Jul
(49) |
Aug
(19) |
Sep
(9) |
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(25) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <vir...@li...> - 2011-03-25 20:56:52
|
Subject: hg.virtualcommons 297 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/238d9a46e9cc changeset: 297:238d9a46e9cc user: Allen Lee <all...@as...> date: Fri Mar 25 01:02:41 2011 -0700 description: updated participant dashboard diffstat: vcweb/core/models.py | 5 ++--- vcweb/core/templates/participant-index.html | 13 ++++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diffs (48 lines): diff -r ef4547bd08af -r 238d9a46e9cc vcweb/core/models.py --- a/vcweb/core/models.py Thu Mar 24 17:51:01 2011 -0700 +++ b/vcweb/core/models.py Fri Mar 25 01:02:41 2011 -0700 @@ -262,12 +262,11 @@ @property def status_line(self): - return "%s: id %s, status: %s, round %s of %s" % ( + return "%s #%s, %s %s" % ( self.experiment_metadata.title, self.pk, self.get_status_display(), - self.current_round.sequence_number, - self.experiment_configuration.final_sequence_number) + self.current_round.sequence_label) @property def namespace(self): diff -r ef4547bd08af -r 238d9a46e9cc vcweb/core/templates/participant-index.html --- a/vcweb/core/templates/participant-index.html Thu Mar 24 17:51:01 2011 -0700 +++ b/vcweb/core/templates/participant-index.html Fri Mar 25 01:02:41 2011 -0700 @@ -2,6 +2,15 @@ {% block participant_socket_io %} {% endblock %} +{% block head %} +{{block.super}} +<script type='text/javascript'> + $(function() { + $('[title]').qtip({position: { corner: {target: 'topMiddle', tooltip: 'bottomMiddle'}}, style: { name: 'green', tip: 'bottomMiddle'} }); + }); +</script> + +{% endblock %} {% block title %} Virtual Commons Web Participant Dashboard @@ -20,9 +29,7 @@ <h4>{{experiments.0.get_status_display}}</h4> {% for experiment in experiments %} <div style='padding: 10px;' class='ui-state-highlight'> - <a href='{{ experiment.participant_url }}'> - <span class='icon-left ui-icon {{experiment_status|lower}}'></span>{{ experiment.status_line }} - </a> + <a title='This experiment is being run by {{experiment.experimenter}}' href='{{ experiment.participant_url }}'><span class='icon-left ui-icon {{experiment_status|lower}}'></span>{{ experiment.status_line }}, started {{experiment.current_round_start_time}}</a> </div> {% endfor %} {% endif %} |
From: <vir...@li...> - 2011-03-25 00:50:25
|
Subject: hg.virtualcommons 296 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/ef4547bd08af changeset: 296:ef4547bd08af user: Allen Lee <all...@as...> date: Thu Mar 24 17:51:01 2011 -0700 description: updating the participant dashboard diffstat: vcweb/core/templates/participant-index.html | 35 ++++++++--------- vcweb/forestry/templates/forestry/participate.html | 14 ++++-- vcweb/forestry/templates/forestry/wait.html | 4 +- vcweb/static/css/style.css | 3 +- 4 files changed, 28 insertions(+), 28 deletions(-) diffs (120 lines): diff -r 73a8f689c5d1 -r ef4547bd08af vcweb/core/templates/participant-index.html --- a/vcweb/core/templates/participant-index.html Thu Mar 24 14:00:01 2011 -0700 +++ b/vcweb/core/templates/participant-index.html Thu Mar 24 17:51:01 2011 -0700 @@ -8,28 +8,25 @@ {% endblock %} {% block page %} -<div class='info'> - Welcome back, {{participant}}. +<div class='info infoIcon ui-corner-all'> + Welcome back, {{participant}}. Experiments you're participating in are listed below. </div> +<div id='experiments'> {% for experiment_metadata, experiment_status_dict in experiment_dict.items %} -<h3> {{ experiment_metadata|title }} </h3> -<div id='experiments' class='notice'> - {% for experiment_status, experiments in experiment_status_dict.items %} - <h3>{{experiment_status|title}}</h3> - {% for experiment in experiments %} - <div class='ui-state-highlight ui-corner-all'> - <a href='{{ experiment.participant_url }}'> - <span class='icon-left ui-icon {{experiment_status|lower}}'></span> - {{ experiment.status_line }}, created {{experiment.date_created|date:"SHORT_DATETIME_FORMAT"}} - </a> - </div> - {% empty %} - <div class='ui-state-error ui-corner-all'><span class='icon-left ui-icon ui-icon-alert'></span>No <b>{{ experiment_status|lower }}</b> experiments</div> - {% endfor %} - {% endfor %} +<h3> {{ experiment_metadata.title }} </h3> +{% for experiment_status, experiments in experiment_status_dict.items %} +{% if experiments %} +<h4>{{experiments.0.get_status_display}}</h4> +{% for experiment in experiments %} +<div style='padding: 10px;' class='ui-state-highlight'> + <a href='{{ experiment.participant_url }}'> + <span class='icon-left ui-icon {{experiment_status|lower}}'></span>{{ experiment.status_line }} + </a> </div> -{% empty %} - {% endfor %} +{% endif %} +{% endfor %} +{% endfor %} +</div> {% endblock page %} diff -r 73a8f689c5d1 -r ef4547bd08af vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Thu Mar 24 14:00:01 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Thu Mar 24 17:51:01 2011 -0700 @@ -59,10 +59,14 @@ <span class='icon-left ui-icon ui-icon-info'></span> There are <b>{{ resource_level.value }}</b> trees left. </div> - <div class='ui-state-error'> - <span class='icon-left ui-icon ui-icon-info'></span> - Your current harvest decision is <b>{{ harvest_decision.value }}</b> - </div> + +{% if harvest_decision %} +<div class='alert alertIcon ui-corner-all'> + You have already made a harvest decision of <b>{{ harvest_decision.value }}</b>. You may change your decision until + the experimenter ends the round. +</div> +{% endif %} + {% if max_harvest_decision > 0 %} <form id='forestry-form' action='' method='post'> <div class='field'> @@ -71,7 +75,7 @@ <input id='harvest-decision-id' type="text" name='harvest_decision' class='required digits two-digits' maxlength='1'/> </div> <div class='field'> - <input type='submit' value='Save' /> + <input type='submit' value='Harvest' /> </div> </form> {% else %} diff -r 73a8f689c5d1 -r ef4547bd08af vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Thu Mar 24 14:00:01 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Thu Mar 24 17:51:01 2011 -0700 @@ -6,7 +6,7 @@ {% include "includes/tablesorter.html" %} <script type="text/javascript"> $(function() { - $('#participant-history').tablesorter({widgets: ['zebra']}); + $('#participant-history').tablesorter({widgets: ['zebra'], sortList: [[0, 0]] }); $('.tooltip').qtip({position: { corner: {target: 'topMiddle', tooltip: 'bottomMiddle'}}, style: { name: 'green', tip: 'bottomMiddle'} }); var s = getCachedSocket(); s.on('message', function(json_string) { @@ -57,7 +57,7 @@ <tr> <td> {% if harvest_round_data.round_in_progress %} - <div id='round-in-progress' class='alert alertIcon ui-corner-all tooltip' title='This round is still in progress so only your harvest decision for this round is being shown.'> + <div id='round-in-progress' style='line-height: 0.9em;' class='alert alertIcon ui-corner-all tooltip' title='This round is still in progress so only your harvest decision for this round is being shown.'> <span style='font-size: 0.8em;'>Round in progress</span> </div> {% endif %} diff -r 73a8f689c5d1 -r ef4547bd08af vcweb/static/css/style.css --- a/vcweb/static/css/style.css Thu Mar 24 14:00:01 2011 -0700 +++ b/vcweb/static/css/style.css Thu Mar 24 17:51:01 2011 -0700 @@ -101,7 +101,6 @@ margin: 5px 0px; padding: 15px 10px 15px 40px; background-position: 3px center; - line-height: 0.9em; } .errorIcon, .warningIcon, .alertIcon { background-image: url('/static/images/warning.png') @@ -165,7 +164,7 @@ background: url('/static/images/famfamfam/accept.png') center left no-repeat; } #experiments span.round_in_progress { - background: url('/static/images/famfamfam/arrow_refresh.png') center left no-repeat; + background: url('/static/images/famfamfam/bullet_go.png') center left no-repeat; } #experiments .rightArrow { margin: 0; |
From: <vir...@li...> - 2011-03-25 00:50:25
|
Subject: hg.virtualcommons 295 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/73a8f689c5d1 changeset: 295:73a8f689c5d1 user: Allen Lee <all...@as...> date: Thu Mar 24 14:00:01 2011 -0700 description: switching on event type, stubbing out submit events. Still need to figure out how to associate experiment type handlers with submit events to process their payloads appropriately. diffstat: vcweb/vcweb-tornadio.py | 33 ++++++++++++++++++++------------- 1 files changed, 20 insertions(+), 13 deletions(-) diffs (43 lines): diff -r f36c72e79fce -r 73a8f689c5d1 vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Thu Mar 24 13:35:33 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Thu Mar 24 14:00:01 2011 -0700 @@ -230,19 +230,26 @@ # FIXME: on_message / connect should add them to the list of participants if 'connect' in event.type: return - participant_group_relationship = connection_manager.get_participant_group_relationship(self) - current_round_data = participant_group_relationship.group.experiment.current_round_data - chat_message = ChatMessage.objects.create(participant_group_relationship=participant_group_relationship, - message=event.message, - round_data=current_round_data - ) - for participant_group_pk, connection in connection_manager.connections(participant_group_relationship.group): - connection.send(simplejson.dumps({ - "pk": chat_message.pk, - "date_created": chat_message.date_created.strftime("%H:%M:%S"), - "message" : chat_message.__unicode__(), - "message_type": 'chat', - })) + elif event.type == 'submit': + # FIXME: need to set this up so that this forwards to the appropriate + # experiment handler... + payload = event.message + logger.debug("payload is: " % payload) + + elif event.type == 'chat': + participant_group_relationship = connection_manager.get_participant_group_relationship(self) + current_round_data = participant_group_relationship.group.experiment.current_round_data + chat_message = ChatMessage.objects.create(participant_group_relationship=participant_group_relationship, + message=event.message, + round_data=current_round_data + ) + for participant_group_pk, connection in connection_manager.connections(participant_group_relationship.group): + connection.send(simplejson.dumps({ + "pk": chat_message.pk, + "date_created": chat_message.date_created.strftime("%H:%M:%S"), + "message" : chat_message.__unicode__(), + "message_type": 'chat', + })) def on_close(self): logger.debug("closing %s" % self) |
From: <vir...@li...> - 2011-03-24 20:35:03
|
Subject: hg.virtualcommons 294 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/f36c72e79fce changeset: 294:f36c72e79fce user: Allen Lee <all...@as...> date: Thu Mar 24 13:35:33 2011 -0700 description: more mucking about with the interface. TODO: add socket.io integration to wait page / submit harvest decisions and the experimenter monitor page diffstat: vcweb/core/templates/monitor.html | 2 +- vcweb/forestry/templates/forestry/wait.html | 18 ++++++++++++------ vcweb/static/css/style.css | 3 ++- vcweb/static/css/tablesorter/style.css | 4 ++-- 4 files changed, 17 insertions(+), 10 deletions(-) diffs (80 lines): diff -r 0ed97d7ae326 -r f36c72e79fce vcweb/core/templates/monitor.html --- a/vcweb/core/templates/monitor.html Thu Mar 24 12:59:22 2011 -0700 +++ b/vcweb/core/templates/monitor.html Thu Mar 24 13:35:33 2011 -0700 @@ -44,7 +44,7 @@ }); } } - var qtipOptions = {position: { corner: {target: 'topRight', tooltip: 'bottomLeft'}}, style: { name: 'dark', tip: 'bottomLeft'} }; + var qtipOptions = {position: { corner: {target: 'topMiddle', tooltip: 'bottomMiddle'}}, style: { name: 'dark', tip: 'bottomMiddle'} }; $(function() { var experimentMessageDiv = document.getElementById('experiment-messages'); registerCallbacks({{ experiment.round_data.count }}, {{ experiment.current_round.sequence_number }}); diff -r 0ed97d7ae326 -r f36c72e79fce vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Thu Mar 24 12:59:22 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Thu Mar 24 13:35:33 2011 -0700 @@ -37,16 +37,16 @@ </span> </p> -<h3>History</h3> +<h3>Participant History</h3> <div id='group-history'> {% if participant_history %} <table id='participant-history' class='tablesorter'> <thead> <tr> - <th>Round</th> - <th class='tooltip' title='The number of trees available to your group at the start of the round.'>Initial # trees (A)</th> - <th class='tooltip' title='The number of trees you harvested in this round.'>Your harvest decisions</th> - <th class='tooltip' title='The total number of trees harvested by your group in this round.'> + <th style='width:9em;'>Round</th> + <th style='width:9em;' class='tooltip' title='The number of trees available to your group at the start of the round.'>Initial # trees (A)</th> + <th style='width:8em;' class='tooltip' title='The number of trees you harvested in this round.'>Your harvest decisions</th> + <th style='width:12em;' class='tooltip' title='The total number of trees harvested by your group in this round.'> Total group harvest decisions (B) </th> <th class='tooltip' title='The trees that regrew during this round.'>Trees regrown (C)</th> @@ -55,7 +55,13 @@ <tbody> {% for harvest_round_data in participant_history %} <tr> - <td>{{harvest_round_data.round_configuration.display_label}} + <td> + {% if harvest_round_data.round_in_progress %} + <div id='round-in-progress' class='alert alertIcon ui-corner-all tooltip' title='This round is still in progress so only your harvest decision for this round is being shown.'> + <span style='font-size: 0.8em;'>Round in progress</span> + </div> + {% endif %} + {{harvest_round_data.round_configuration.display_label}} <br/><small>{{harvest_round_data.round_configuration.sequence_label}}</small></td> <td>{{harvest_round_data.original_number_of_trees}}</td> <td>{% if harvest_round_data.individual_harvest %} diff -r 0ed97d7ae326 -r f36c72e79fce vcweb/static/css/style.css --- a/vcweb/static/css/style.css Thu Mar 24 12:59:22 2011 -0700 +++ b/vcweb/static/css/style.css Thu Mar 24 13:35:33 2011 -0700 @@ -99,8 +99,9 @@ .errorIcon, .warningIcon, .alertIcon, .infoIcon, .smallInfoIcon, .contactIcon, .crossIcon { background-repeat: no-repeat; margin: 5px 0px; - padding: 15px 10px 15px 35px; + padding: 15px 10px 15px 40px; background-position: 3px center; + line-height: 0.9em; } .errorIcon, .warningIcon, .alertIcon { background-image: url('/static/images/warning.png') diff -r 0ed97d7ae326 -r f36c72e79fce vcweb/static/css/tablesorter/style.css --- a/vcweb/static/css/tablesorter/style.css Thu Mar 24 12:59:22 2011 -0700 +++ b/vcweb/static/css/tablesorter/style.css Thu Mar 24 13:35:33 2011 -0700 @@ -24,8 +24,8 @@ padding: 6px; border: 1px solid #CCC; background-color: #FFF; - vertical-align: top; - text-align: right; + vertical-align: center; + text-align: left; } table.tablesorter tbody tr.odd td { background-color:#F0F0F6; |
From: <vir...@li...> - 2011-03-24 19:58:52
|
Subject: hg.virtualcommons 293 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/0ed97d7ae326 changeset: 293:0ed97d7ae326 user: Allen Lee <all...@as...> date: Thu Mar 24 12:59:22 2011 -0700 description: improving wait page / debriefing interface with tooltips, tablesorter diffstat: vcweb/core/models.py | 11 +++-- vcweb/forestry/templates/forestry/wait.html | 25 +++++++++--- vcweb/forestry/views.py | 35 +++++++++-------- vcweb/static/css/tablesorter/asc.gif | vcweb/static/css/tablesorter/bg.gif | vcweb/static/css/tablesorter/desc.gif | vcweb/static/css/tablesorter/style.css | 41 ++++++++++++++++++++ vcweb/static/js/jquery.tablesorter.min.js | 4 ++ 8 files changed, 88 insertions(+), 28 deletions(-) diffs (219 lines): diff -r aa07e8956e54 -r 0ed97d7ae326 vcweb/core/models.py --- a/vcweb/core/models.py Thu Mar 24 09:45:07 2011 -0700 +++ b/vcweb/core/models.py Thu Mar 24 12:59:22 2011 -0700 @@ -16,7 +16,6 @@ logger = logging.getLogger(__name__) - """ Contains all data models used in the core as well as a number of helper functions. @@ -587,13 +586,15 @@ return Template(template_string).substitute(kwargs, round_number=self.display_number, participant_id=participant_id) def __unicode__(self): - return u"%s (%d of %d) > %s" % (self.display_label, self.sequence_number, self.experiment_configuration.final_sequence_number, self.experiment_configuration) + return u"%s > %s" % (self.display_label, self.experiment_configuration) @property def display_label(self): - if self.is_regular_round: - return u"Round %d" % self.round_number - return self.get_round_type_display() + return u"Round %d" % self.round_number if self.is_regular_round else self.get_round_type_display() + + @property + def sequence_label(self): + return u"(%d of %d)" % (self.sequence_number, self.experiment_configuration.final_sequence_number) class Meta: ordering = [ 'experiment_configuration', 'sequence_number', 'date_created' ] diff -r aa07e8956e54 -r 0ed97d7ae326 vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Thu Mar 24 09:45:07 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Thu Mar 24 12:59:22 2011 -0700 @@ -3,9 +3,11 @@ {{ block.super }} {% include "includes/participant.events.html" %} {% include "includes/socket.io.html" %} +{% include "includes/tablesorter.html" %} <script type="text/javascript"> $(function() { - // var s = connect(window.location.hostname, 8888, 'participant/{{participant_experiment_relationship.pk}}'); + $('#participant-history').tablesorter({widgets: ['zebra']}); + $('.tooltip').qtip({position: { corner: {target: 'topMiddle', tooltip: 'bottomMiddle'}}, style: { name: 'green', tip: 'bottomMiddle'} }); var s = getCachedSocket(); s.on('message', function(json_string) { var json = jQuery.parseJSON(json_string); @@ -37,15 +39,24 @@ <h3>History</h3> <div id='group-history'> - {% if all_harvest_round_data %} - <table class='debriefing'> + {% if participant_history %} + <table id='participant-history' class='tablesorter'> <thead> - <tr><th>Round</th><th>Original number of trees</th><th>Your harvest decisions</th><th>Your group's total harvest decisions</th><th>Regrowth</th><th>Number of trees left</th></tr> + <tr> + <th>Round</th> + <th class='tooltip' title='The number of trees available to your group at the start of the round.'>Initial # trees (A)</th> + <th class='tooltip' title='The number of trees you harvested in this round.'>Your harvest decisions</th> + <th class='tooltip' title='The total number of trees harvested by your group in this round.'> + Total group harvest decisions (B) + </th> + <th class='tooltip' title='The trees that regrew during this round.'>Trees regrown (C)</th> + <th class='tooltip' title='The number of trees available at the end of the round (A - B + C = D)'.>Final # trees (D)</th></tr> </thead> <tbody> - {% for harvest_round_data in all_harvest_round_data %} + {% for harvest_round_data in participant_history %} <tr> - <td>{{harvest_round_data.round_configuration}}</td> + <td>{{harvest_round_data.round_configuration.display_label}} + <br/><small>{{harvest_round_data.round_configuration.sequence_label}}</small></td> <td>{{harvest_round_data.original_number_of_trees}}</td> <td>{% if harvest_round_data.individual_harvest %} {{harvest_round_data.individual_harvest.value}} @@ -54,7 +65,7 @@ {%endif%} </td> <td>{{harvest_round_data.group_harvest.value}}</td> - <td>{{harvest_round_data.regrowth.value}}</td> + <td>{{harvest_round_data.group_regrowth.value}}</td> <td>{{harvest_round_data.final_number_of_trees}}</td> </tr> {% endfor %} diff -r aa07e8956e54 -r 0ed97d7ae326 vcweb/forestry/views.py --- a/vcweb/forestry/views.py Thu Mar 24 09:45:07 2011 -0700 +++ b/vcweb/forestry/views.py Thu Mar 24 12:59:22 2011 -0700 @@ -4,9 +4,8 @@ from django.http import Http404 from django.shortcuts import render_to_response, redirect from django.template.context import RequestContext -from vcweb import settings from vcweb.core.forms import QuizForm -from vcweb.core.models import is_participant, is_experimenter, Experiment, ParticipantGroupRelationship, ParticipantExperimentRelationship +from vcweb.core.models import is_participant, is_experimenter, Experiment from vcweb.core.decorators import participant_required, experimenter_required from vcweb.forestry.models import get_resource_level, get_max_harvest_decision, get_forestry_experiment_metadata, set_harvest_decision, get_harvest_decision, get_group_harvest, get_regrowth from vcweb.forestry.forms import HarvestDecisionForm @@ -61,28 +60,32 @@ logger.warning("No experiment available with id [%s]" % experiment_id) return redirect('core:experimenter_index') -class ParticipantHistory(object): +class HarvestRoundData(object): pass def generate_participant_history(participant_group_relationship): group = participant_group_relationship.group experiment = group.experiment - all_harvest_round_data = [] + participant_history = [] for round_data in experiment.playable_round_data: - p = ParticipantHistory() - p.round_configuration = round_data.round_configuration - p.individual_harvest = get_harvest_decision(participant_group_relationship, round_data=round_data) - p.group_harvest = get_group_harvest(group, round_data=round_data) - p.regrowth = get_regrowth(group, round_data=round_data) + data = HarvestRoundData() + data.round_configuration = round_data.round_configuration + data.individual_harvest = get_harvest_decision(participant_group_relationship, round_data=round_data) + data.group_harvest = get_group_harvest(group, round_data=round_data) + data.group_regrowth = get_regrowth(group, round_data=round_data) resource_level = get_resource_level(group, round_data=round_data) try: - p.original_number_of_trees = resource_level.value + p.group_harvest.value - p.regrowth.value + data.original_number_of_trees = resource_level.value + data.group_harvest.value - data.group_regrowth.value except AttributeError: pass - p.final_number_of_trees = resource_level.value - all_harvest_round_data.append(p) - logger.debug("all harvest round data: %s" % all_harvest_round_data) - return all_harvest_round_data + data.final_number_of_trees = resource_level.value + participant_history.append(data) + logger.debug("participant history: %s" % participant_history) + if experiment.is_round_in_progress: + last_round_data = participant_history[-1] + if experiment.current_round.pk == last_round_data.round_configuration.pk: + last_round_data.round_in_progress = True + return participant_history @participant_required def wait(request, experiment_id=None): @@ -91,11 +94,11 @@ participant = request.user.participant participant_experiment_relationship = participant.get_participant_experiment_relationship(experiment) participant_group_relationship = participant.get_participant_group_relationship(experiment) - all_harvest_round_data = generate_participant_history(participant_group_relationship) + participant_history = generate_participant_history(participant_group_relationship) return render_to_response('forestry/wait.html', { 'participant_experiment_relationship': participant_experiment_relationship, 'participant_group_relationship':participant_group_relationship, - 'all_harvest_round_data': all_harvest_round_data, + 'participant_history': participant_history, }, context_instance=RequestContext(request)) except Experiment.DoesNotExist: diff -r aa07e8956e54 -r 0ed97d7ae326 vcweb/static/css/tablesorter/asc.gif Binary file vcweb/static/css/tablesorter/asc.gif has changed diff -r aa07e8956e54 -r 0ed97d7ae326 vcweb/static/css/tablesorter/bg.gif Binary file vcweb/static/css/tablesorter/bg.gif has changed diff -r aa07e8956e54 -r 0ed97d7ae326 vcweb/static/css/tablesorter/desc.gif Binary file vcweb/static/css/tablesorter/desc.gif has changed diff -r aa07e8956e54 -r 0ed97d7ae326 vcweb/static/css/tablesorter/style.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vcweb/static/css/tablesorter/style.css Thu Mar 24 12:59:22 2011 -0700 @@ -0,0 +1,41 @@ +/* tables */ +table.tablesorter { + font-family: "Lucida Sans Unicode", "Bitstream Vera Sans", "Trebuchet Unicode MS", "Lucida Grande", Verdana, Helvetica, sans-serif; + background-color: #CDCDCD; + margin:10px 0px 15px; + font-size: 0.9em; + width: 100%; + text-align: left; +} +table.tablesorter thead tr th, table.tablesorter tfoot tr th { + background-color: #e6EEEE; + border: 1px solid #CCC; + font-size: 0.9em; + padding: 6px; +} +table.tablesorter thead tr .header { + background-image: url(/static/css/tablesorter/bg.gif); + background-repeat: no-repeat; + background-position: center right; + cursor: pointer; +} +table.tablesorter tbody td { + color: #3D3D3D; + padding: 6px; + border: 1px solid #CCC; + background-color: #FFF; + vertical-align: top; + text-align: right; +} +table.tablesorter tbody tr.odd td { + background-color:#F0F0F6; +} +table.tablesorter thead tr .headerSortUp { + background-image: url(/static/css/tablesorter/asc.gif); +} +table.tablesorter thead tr .headerSortDown { + background-image: url(/static/css/tablesorter/desc.gif); +} +table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp { + background-color: #8dbdd8; +} diff -r aa07e8956e54 -r 0ed97d7ae326 vcweb/static/js/jquery.tablesorter.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vcweb/static/js/jquery.tablesorter.min.js Thu Mar 24 12:59:22 2011 -0700 @@ -0,0 +1,4 @@ + +(function($){$.extend({tablesorter:new +function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,rows,-1,i);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,rows,rowIndex,cellIndex){var l=parsers.length,node=false,nodeValue=false,keepLooking=true;while(nodeValue==''&&keepLooking){rowIndex++;if(rows[rowIndex]){node=getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex);nodeValue=trimAndGetNodeText(table.config,node);if(table.config.debug){log('Checking if value was empty on row:'+rowIndex);}}else{keepLooking=false;}}for(var i=1;i<l;i++){if(parsers[i].is(nodeValue,table,node)){return parsers[i];}}return parsers[0];}function getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex){return rows[rowIndex].cells[cellIndex];}function trimAndGetNodeText(config,node){return $.trim(getElementText(config,node));}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=$(table.tBodies[0].rows[i]),cols=[];if(c.hasClass(table.config.cssChildRow)){cache.row[cache.row.length-1]=cache.row[cache.row.length-1].add(c);continue;}cache.row.push(c);for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c[0].cells[j]),table,c[0].cells[j]));}cols.push(cache.normalized.length);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){var text="";if(!node)return"";if(!config.supportsTextContent)config.supportsTextContent=node.textContent||false;if(config.textExtraction=="simple"){if(config.supportsTextContent){text=node.textContent;}else{if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){text=node.childNodes[0].innerHTML;}else{text=node.innerHTML;}}}else{if(typeof(config.textExtraction)=="function"){text=config.textExtraction(node);}else{text=$(node).text();}}return text;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){var pos=n[i][checkCell];rows.push(r[pos]);if(!table.config.appender){var l=r[pos].length;for(var j=0;j<l;j++){tableBody[0].appendChild(r[pos][j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false;var header_index=computeTableHeaderCellIndexes(table);$tableHeaders=$(table.config.selectorHeaders,table).each(function(index){this.column=header_index[this.parentNode.rowIndex+"-"+this.cellIndex];this.order=formatSortingOrder(table.config.sortInitialOrder);this.count=this.order;if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(checkHeaderOptionsSortingLocked(table,index))this.order=this.lockedOrder=checkHeaderOptionsSortingLocked(table,index);if(!this.sortDisabled){var $th=$(this).addClass(table.config.cssHeader);if(table.config.onRenderHeader)table.config.onRenderHeader.apply($th);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function computeTableHeaderCellIndexes(t){var matrix=[];var lookup={};var thead=t.getElementsByTagName('THEAD')[0];var trs=thead.getElementsByTagName('TR');for(var i=0;i<trs.length;i++){var cells=trs[i].cells;for(var j=0;j<cells.length;j++){var c=cells[j];var rowIndex=c.parentNode.rowIndex;var cellId=rowIndex+"-"+c.cellIndex;var rowSpan=c.rowSpan||1;var colSpan=c.colSpan||1 +var firstAvailCol;if(typeof(matrix[rowIndex])=="undefined"){matrix[rowIndex]=[];}for(var k=0;k<matrix[rowIndex].length+1;k++){if(typeof(matrix[rowIndex][k])=="undefined"){firstAvailCol=k;break;}}lookup[cellId]=firstAvailCol;for(var k=rowIndex;k<rowIndex+rowSpan;k++){if(typeof(matrix[k])=="undefined"){matrix[k]=[];}var matrixrow=matrix[k];for(var l=firstAvailCol;l<firstAvailCol+colSpan;l++){matrixrow[l]="x";}}}}return lookup;}function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){return(v.toLowerCase()=="desc")?1:0;}else{return(v==1)?1:0;}}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(table.config.parsers[c].type=="text")?((order==0)?makeSortFunction("text","asc",c):makeSortFunction("text","desc",c)):((order==0)?makeSortFunction("numeric","asc",c):makeSortFunction("numeric","desc",c));var e="e"+i;dynamicExp+="var "+e+" = "+s;dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";if(table.config.debug){benchmark("Evaling expression:"+dynamicExp,new Date());}eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function makeSortFunction(type,direction,index){var a="a["+index+"]",b="b["+index+"]";if(type=='text'&&direction=='asc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+a+" < "+b+") ? -1 : 1 )));";}else if(type=='text'&&direction=='desc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+b+" < "+a+") ? -1 : 1 )));";}else if(type=='numeric'&&direction=='asc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+a+" - "+b+"));";}else if(type=='numeric'&&direction=='desc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+b+" - "+a+"));";}};function makeSortText(i){return"((a["+i+"] < b["+i+"]) ? -1 : ((a["+i+"] > b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){var me=this;setTimeout(function(){me.config.parsers=buildParserCache(me,$headers);cache=buildCache(me);},1);}).bind("updateCell",function(e,cell){var config=this.config;var pos=[(cell.parentNode.rowIndex-1),cell.cellIndex];cache.normalized[pos[0]][pos[1]]=config.parsers[pos[1]].format(getElementText(config,cell),cell);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){return/^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g,'')));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLocaleLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}var $tr,row=-1,odd;$("tr:visible",table.tBodies[0]).each(function(i){$tr=$(this);if(!$tr.hasClass(table.config.cssChildRow))row++;odd=(row%2==0);$tr.removeClass(table.config.widgetZebra.css[odd?0:1]).addClass(table.config.widgetZebra.css[odd?1:0])});if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery); \ No newline at end of file |
From: <vir...@li...> - 2011-03-24 19:58:50
|
Subject: hg.virtualcommons 292 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/aa07e8956e54 changeset: 292:aa07e8956e54 user: Allen Lee <all...@as...> date: Thu Mar 24 09:45:07 2011 -0700 description: removing socket io from participant dashboard diffstat: vcweb/core/models.py | 2 +- vcweb/core/templates/base-participant.html | 2 ++ vcweb/core/templates/participant-index.html | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diffs (45 lines): diff -r 602813ab5ff7 -r aa07e8956e54 vcweb/core/models.py --- a/vcweb/core/models.py Wed Mar 23 22:35:11 2011 -0700 +++ b/vcweb/core/models.py Thu Mar 24 09:45:07 2011 -0700 @@ -593,7 +593,7 @@ def display_label(self): if self.is_regular_round: return u"Round %d" % self.round_number - return unicode(self.get_round_type_display()) + return self.get_round_type_display() class Meta: ordering = [ 'experiment_configuration', 'sequence_number', 'date_created' ] diff -r 602813ab5ff7 -r aa07e8956e54 vcweb/core/templates/base-participant.html --- a/vcweb/core/templates/base-participant.html Wed Mar 23 22:35:11 2011 -0700 +++ b/vcweb/core/templates/base-participant.html Thu Mar 24 09:45:07 2011 -0700 @@ -2,12 +2,14 @@ {% block head %} {{block.super}} + {% block participant_socket_io %} <script type='text/javascript' src='/static/js/jquery.validate.min.js'></script> {% include "includes/participant.events.html" %} {% include "includes/socket.io.html" %} <script type='text/javascript'> connect(window.location.hostname, 8888, 'participant/{{participant_experiment_relationship.pk}}'); </script> + {% endblock %} {% endblock %} {% block title %} diff -r 602813ab5ff7 -r aa07e8956e54 vcweb/core/templates/participant-index.html --- a/vcweb/core/templates/participant-index.html Wed Mar 23 22:35:11 2011 -0700 +++ b/vcweb/core/templates/participant-index.html Thu Mar 24 09:45:07 2011 -0700 @@ -1,7 +1,10 @@ {% extends "base-participant.html" %} +{% block participant_socket_io %} +{% endblock %} + {% block title %} -Virtual Commons Web Participant Interface +Virtual Commons Web Participant Dashboard {% endblock %} {% block page %} |
From: <vir...@li...> - 2011-03-24 19:58:50
|
Subject: hg.virtualcommons 291 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/602813ab5ff7 changeset: 291:602813ab5ff7 user: Allen Lee <all...@as...> date: Wed Mar 23 22:35:11 2011 -0700 description: improving default unicode display for round configurations, still needs some tweaking. diffstat: vcweb/core/models.py | 4 ++-- vcweb/vcweb-tornadio.py | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diffs (47 lines): diff -r 3772208ca15f -r 602813ab5ff7 vcweb/core/models.py --- a/vcweb/core/models.py Wed Mar 23 16:28:53 2011 -0700 +++ b/vcweb/core/models.py Wed Mar 23 22:35:11 2011 -0700 @@ -587,13 +587,13 @@ return Template(template_string).substitute(kwargs, round_number=self.display_number, participant_id=participant_id) def __unicode__(self): - return u"sequence %d, round %d, (%s | %s)" % (self.sequence_number, self.round_number, self.round_type, self.experiment_configuration) + return u"%s (%d of %d) > %s" % (self.display_label, self.sequence_number, self.experiment_configuration.final_sequence_number, self.experiment_configuration) @property def display_label(self): if self.is_regular_round: return u"Round %d" % self.round_number - return u"%s (%s)" % (self.get_round_type_display(), self.round_number) + return unicode(self.get_round_type_display()) class Meta: ordering = [ 'experiment_configuration', 'sequence_number', 'date_created' ] diff -r 3772208ca15f -r 602813ab5ff7 vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Wed Mar 23 16:28:53 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Wed Mar 23 22:35:11 2011 -0700 @@ -120,9 +120,13 @@ connection.send(ConnectionManager.refresh_json) def send_goto(self, connection, experiment, url): + notified_participants = [] json = goto_json(url) for (participant_group_pk, connection) in self.all_participants(connection, experiment): connection.send(json) + notified_participants.append(participant_group_pk) + return notified_participants + def send_to_experimenter(self, experimenter_tuple, json): (experimenter_pk, experiment_pk) = experimenter_tuple @@ -179,8 +183,9 @@ experiment_id = event.experiment_id experiment = Experiment.objects.get(pk=experiment_id) url = event.url - connection_manager.send_goto(self, experiment, url) + notified_participants = connection_manager.send_goto(self, experiment, url) self.send(info_json("Sent goto:%s to all participants" % url)) + logger.debug("sending all connected participants %s to %s" % (notified_participants, url)) def on_close(self): connection_manager.remove_experimenter(self) |
From: <vir...@li...> - 2011-03-23 23:28:32
|
Subject: hg.virtualcommons 290 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/3772208ca15f changeset: 290:3772208ca15f user: Allen Lee <all...@as...> date: Wed Mar 23 16:28:53 2011 -0700 description: fixing participant form jquery submit diffstat: vcweb/core/models.py | 10 +++++++++- vcweb/core/templates/experimenter-index.html | 2 +- vcweb/forestry/templates/forestry/participate.html | 22 +++++++++++----------- vcweb/vcweb-tornadio.py | 5 +++-- 4 files changed, 24 insertions(+), 15 deletions(-) diffs (134 lines): diff -r a3ce652901b3 -r 3772208ca15f vcweb/core/models.py --- a/vcweb/core/models.py Tue Mar 22 14:21:40 2011 -0700 +++ b/vcweb/core/models.py Wed Mar 23 16:28:53 2011 -0700 @@ -392,6 +392,14 @@ def get_template_path(self, name): return "%s/%s" % (self.namespace, name) + # XXX: decide whether or not to include this ability in the interface. + def move_to_previous_round(self): + if self.is_round_in_progress: + self.end_round() + self.current_round_elased_time = 0 + self.current_round_sequence_number = max(self.current_round_sequence_number - 1, 1) + self.save() + def advance_to_next_round(self): if self.is_round_in_progress: self.end_round() @@ -1168,7 +1176,7 @@ return self.round_data.round_configuration def __unicode__(self): - return u"data value {0}: {1} for participant {2}".format(self.parameter, self.value, self.participant_group_relationship) + return u"{0} : {1} for participant {2}".format(self.parameter, self.value, self.participant_group_relationship) class Meta: ordering = [ 'round_data', 'participant_group_relationship', 'parameter' ] diff -r a3ce652901b3 -r 3772208ca15f vcweb/core/templates/experimenter-index.html --- a/vcweb/core/templates/experimenter-index.html Tue Mar 22 14:21:40 2011 -0700 +++ b/vcweb/core/templates/experimenter-index.html Wed Mar 23 16:28:53 2011 -0700 @@ -25,7 +25,7 @@ {{e.status_line}} <ul class='horizontal' id='horizontal'> <li><a href='{{e.monitor_url}}'><img src='/static/images/famfamfam/zoom.png' alt='General experiment monitoring interface'/> monitor</a></li> - <li><a href='{{e.management_url}}'><img src='/static/images/famfamfam/application_go.png' alt='Custom management interface'/> manage (unfinished)</a></li> + <!-- <li><a href='{{e.management_url}}'><img src='/static/images/famfamfam/application_go.png' alt='Custom management interface'/> manage (unfinished)</a></li> --> <li><a href='{{e.stop_url}}' class='confirm-experiment-action' style='background-image:none;' ><img src='/static/images/famfamfam/stop.png' alt=''/> stop</a></li> </ul> </div> diff -r a3ce652901b3 -r 3772208ca15f vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Tue Mar 22 14:21:40 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Wed Mar 23 16:28:53 2011 -0700 @@ -3,7 +3,7 @@ {{ block.super }} <script type="text/javascript"> $(function() { - $("#forestryForm").validate({ + $("#forestry-form").validate({ rules: { harvest_decision: { required: true, @@ -17,10 +17,10 @@ } }, }); - $('#harvestDecisionId').focus(function() { + $('#harvest-decision-id').focus(function() { this.select(); }); - $('#harvestDecisionId').focus(); + $('#harvest-decision-id').focus(); var s = getCachedSocket(); s.on('message', function(json_string) { var json = jQuery.parseJSON(json_string); @@ -31,11 +31,11 @@ break; } }); - $('#submit-harvest-decision').click(function() { + $('#forestry-form').submit(function() { $(this).attr('disabled', true); - harvestDecisionValue = $('#harvestDecisionId').val(); - alert("harvest decision: " + harvestDecisionValue); - s.send(createSubmitEvent($('#harvestDecisionId').val())); + harvestDecisionValue = $('#harvest-decision-id').val(); + s.send(createSubmitEvent($('#harvest-decision-id').val())); + return true; }); }); </script> @@ -64,14 +64,14 @@ Your current harvest decision is <b>{{ harvest_decision.value }}</b> </div> {% if max_harvest_decision > 0 %} -<form id='forestryForm' action='' method='post'> +<form id='forestry-form' action='' method='post'> <div class='field'> <br/> - <label for='harvestDecisionId'>How many trees will you harvest this round? <br/><small><b>Choose a number between 0 and {{ max_harvest_decision }}</small></b>:</label> - <input id='harvestDecisionId' type="text" name='harvest_decision' class='required digits two-digits' maxlength='1'/> + <label for='harvest-decision-id'>How many trees will you harvest this round? <br/><small><b>Choose a number between 0 and {{ max_harvest_decision }}</small></b>:</label> + <input id='harvest-decision-id' type="text" name='harvest_decision' class='required digits two-digits' maxlength='1'/> </div> <div class='field'> - <input id='submit-harvest-decision' type='submit' value='Submit' /> + <input type='submit' value='Save' /> </div> </form> {% else %} diff -r a3ce652901b3 -r 3772208ca15f vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Tue Mar 22 14:21:40 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Wed Mar 23 16:28:53 2011 -0700 @@ -154,11 +154,11 @@ # FIXME: move to core tornado module? class ExperimenterHandler(SocketConnection): + # FIXME: add authentication def on_open(self, *args, **kwargs): try: extra = kwargs['extra'] logger.debug('%s received extra: %s' % (self, extra)) -# FIXME: add authentication experimenter_id = extra except Experimenter.DoesNotExist as e: logger.warning("Tried to establish connection but there isn't any experimenter with id %s" % experimenter_id) @@ -186,6 +186,7 @@ connection_manager.remove_experimenter(self) class ParticipantHandler(SocketConnection): + # FIXME: on_open authenticates or prepares the session def on_open(self, *args, **kwargs): # FIXME: verify user auth tokens extra = kwargs['extra'] @@ -221,9 +222,9 @@ def on_message(self, message, *args, **kwargs): logger.debug("received message %s from handler %s" % (message, self)) event = to_event(message) + # FIXME: on_message / connect should add them to the list of participants if 'connect' in event.type: return - # FIXME: add authentication participant_group_relationship = connection_manager.get_participant_group_relationship(self) current_round_data = participant_group_relationship.group.experiment.current_round_data chat_message = ChatMessage.objects.create(participant_group_relationship=participant_group_relationship, |
From: <vir...@li...> - 2011-03-22 21:21:34
|
Subject: hg.virtualcommons 289 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/a3ce652901b3 changeset: 289:a3ce652901b3 user: Allen Lee <all...@as...> date: Tue Mar 22 14:21:40 2011 -0700 description: fixing tests diffstat: vcweb/core/models.py | 14 +------------- vcweb/forestry/tests.py | 18 ++++++------------ 2 files changed, 7 insertions(+), 25 deletions(-) diffs (81 lines): diff -r 967433020ded -r a3ce652901b3 vcweb/core/models.py --- a/vcweb/core/models.py Mon Mar 21 17:02:54 2011 -0700 +++ b/vcweb/core/models.py Tue Mar 22 14:21:40 2011 -0700 @@ -462,20 +462,8 @@ status=Experiment.INACTIVE ) - def __unicode__(self): - return u"%s | #%s" % (self.experiment_metadata.title, self.pk) - - def ___eq___(self, other): - return self.pk == other.pk - - def ___cmp___(self, other): - return self.pk.___cmp___(other.pk) - - def ___hash___(self): - return self.pk.___hash___() - - + return u"%s #%s | %s" % (self.experiment_metadata.title, self.pk, self.experimenter) class RoundConfiguration(models.Model): # maps round type name to (description, default_template_name) diff -r 967433020ded -r a3ce652901b3 vcweb/forestry/tests.py --- a/vcweb/forestry/tests.py Mon Mar 21 17:02:54 2011 -0700 +++ b/vcweb/forestry/tests.py Tue Mar 22 14:21:40 2011 -0700 @@ -56,7 +56,7 @@ ''' def expected_resource_level(group): after_harvests = 100 - ((group.number % 5) * group.size) - after_regrowth = after_harvests + (after_harvests / 10) + after_regrowth = min(after_harvests + (after_harvests / 10), 100) return after_regrowth for group in e.groups.all(): @@ -67,11 +67,6 @@ for group in e.groups.all(): resource_level = get_resource_level(group) self.failUnlessEqual(resource_level.value, expected_resource_level(group)) - ''' - 2 groups, 2 rounds of data = 4 total group round data value - objects. - ''' - self.failUnlessEqual(GroupRoundDataValue.objects.count(), 4) def test_round_ended(self): e = self.test_round_setup() @@ -155,7 +150,7 @@ for e in self.all_data_rounds(): self.failIfEqual(current_round_data, e.current_round_data) current_round_data = e.current_round_data - for data_value in current_round_data.group_data_values.all(): + for data_value in current_round_data.group_data_values.filter(parameter__name='resource_level'): # test string conversion logger.debug("current round data: pk:%s value:%s unicode:%s" % (data_value.pk, data_value.value, data_value)) self.failUnless(data_value.pk > 0) @@ -168,18 +163,17 @@ data_value.save() self.failUnlessEqual(50, data_value.value) - self.failUnlessEqual(GroupRoundDataValue.objects.filter(experiment=e).count(), data_round_number * 2) self.failUnlessEqual(e.current_round_data.group_data_values.count(), GroupRoundDataValue.objects.filter(experiment=e, round_data=current_round_data).count()) - self.failUnlessEqual(e.parameters(scope=Parameter.GROUP_SCOPE).count(), 1) - self.failUnlessEqual(current_round_data.group_data_values.count(), 2) + self.failUnlessEqual(e.parameters(scope=Parameter.GROUP_SCOPE).count(), 3) data_round_number += 1 def test_data_parameters(self): e = self.experiment - self.failUnlessEqual(4, e.parameters().count(), 'Currently 4 group parameters') + # FIXME: horrible tests, improve + self.failUnlessEqual(6, e.parameters().count()) for data_param in e.parameters(scope=Parameter.GROUP_SCOPE).all(): logger.debug("inspecting data param %s" % data_param) - self.failUnlessEqual(data_param.type, 'int', 'Currently all data parameters for the forestry experiment are ints.') + self.failUnlessEqual(data_param.type, 'int', 'Currently all group data parameters for the forestry experiment are ints.') def create_participant_data_values(self): |
From: <vir...@li...> - 2011-03-22 00:03:02
|
Subject: hg.virtualcommons 288 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/967433020ded changeset: 288:967433020ded user: Allen Lee <all...@as...> date: Mon Mar 21 17:02:54 2011 -0700 description: fixing broken socket_io participant data, pushing socket connection into participant.events.html since pretty much every participant page requires a socket.io connection (excepting the participant dashboard currently) diffstat: vcweb/core/models.py | 12 ++- vcweb/core/templates/base-participant.html | 5 + vcweb/core/templates/includes/socket.io.html | 44 ++++++++------ vcweb/forestry/templates/forestry/chat.html | 77 ++++++++++++------------- vcweb/forestry/templates/forestry/participate.html | 4 +- vcweb/forestry/templates/forestry/wait.html | 3 +- vcweb/forestry/views.py | 1 + vcweb/vcweb-tornadio.py | 2 + 8 files changed, 80 insertions(+), 68 deletions(-) diffs (261 lines): diff -r aaf420944100 -r 967433020ded vcweb/core/models.py --- a/vcweb/core/models.py Sun Mar 20 23:19:51 2011 -0700 +++ b/vcweb/core/models.py Mon Mar 21 17:02:54 2011 -0700 @@ -176,7 +176,7 @@ ('COMPLETED', 'Completed')) (INACTIVE, ACTIVE, PAUSED, ROUND_IN_PROGRESS, COMPLETED) = [ choice[0] for choice in STATUS_CHOICES ] authentication_code = models.CharField(max_length=32, default="vcweb.auth.code") - current_round_sequence_number = models.PositiveIntegerField(default=0) + current_round_sequence_number = models.PositiveIntegerField(default=1) experimenter = models.ForeignKey(Experimenter, related_name='experiments') experiment_metadata = models.ForeignKey(ExperimentMetadata) experiment_configuration = models.ForeignKey(ExperimentConfiguration, @@ -325,7 +325,8 @@ @property def previous_round(self): - return self.get_round_configuration(max(self.current_round_sequence_number - 1, 0)) + # FIXME: loop instead w/ mod? + return self.get_round_configuration(max(self.current_round_sequence_number - 1, 1)) @property def has_next_round(self): @@ -349,6 +350,7 @@ def log(self, log_message): if log_message: self.activity_log.create(round_configuration=self.current_round, log_message=log_message) + def data_file_name(self, file_ext='csv'): return "%s_%s_%s.%s" % (slugify(self.experiment_metadata.title), self.pk, datetime.now().strftime("%d-%m-%y-%H%M"), file_ext) @@ -1017,12 +1019,12 @@ def get_participant_experiment_relationship(self, experiment): return ParticipantExperimentRelationship.objects.get(participant=self, experiment=experiment) + def get_participant_group_relationship(self, experiment): + return ParticipantGroupRelationship.objects.get_participant_group(self, experiment) + def get_participant_number(self, experiment): return ParticipantGroupRelationship.objects.get_participant_number(experiment, self) - def get_participant_group_relationship(self, experiment): - return ParticipantGroupRelationship.objects.get_participant_group(self, experiment) - def get_group(self, experiment): return ParticipantGroupRelationship.objects.get_group(experiment, self) diff -r aaf420944100 -r 967433020ded vcweb/core/templates/base-participant.html --- a/vcweb/core/templates/base-participant.html Sun Mar 20 23:19:51 2011 -0700 +++ b/vcweb/core/templates/base-participant.html Mon Mar 21 17:02:54 2011 -0700 @@ -3,6 +3,11 @@ {% block head %} {{block.super}} <script type='text/javascript' src='/static/js/jquery.validate.min.js'></script> + {% include "includes/participant.events.html" %} + {% include "includes/socket.io.html" %} + <script type='text/javascript'> + connect(window.location.hostname, 8888, 'participant/{{participant_experiment_relationship.pk}}'); + </script> {% endblock %} {% block title %} diff -r aaf420944100 -r 967433020ded vcweb/core/templates/includes/socket.io.html --- a/vcweb/core/templates/includes/socket.io.html Sun Mar 20 23:19:51 2011 -0700 +++ b/vcweb/core/templates/includes/socket.io.html Mon Mar 21 17:02:54 2011 -0700 @@ -4,26 +4,30 @@ </script> <script type="text/javascript"> +var cachedSocket; function connect(host, port, resource) { - if ( !host ) { - console.log("Tried to connect to invalid host, connecting to vcweb.asu.edu instead."); - host = "vcweb.asu.edu"; - } - if ( !port ) { - console.log("using default port 8888"); - port = 8888; - } - var s = new io.Socket(host, {"port": port, "resource": resource}); - s.connect(); - s.on("connect", function() { - console.log("Connecting."); - s.send(createConnectionEvent()); - }); - s.on('disconnect', function(data) { - console.log("received disconnect, reconnecting."); - s.connect(); - s.send(createReconnectionEvent()); - }); - return s; + if ( !host ) { + console.log("Tried to connect to invalid host, connecting to vcweb.asu.edu instead."); + host = "vcweb.asu.edu"; + } + if ( !port ) { + console.log("using default port 8888"); + port = 8888; + } + cachedSocket = new io.Socket(host, {"port": port, "resource": resource}); + cachedSocket.connect(); + cachedSocket.on('connect', function() { + console.log("Connecting to " + host + ":" + port + "/" + resource); + cachedSocket.send(createConnectionEvent()); + }); + cachedSocket.on('disconnect', function(data) { + console.log("received disconnect, reconnecting."); + cachedSocket.connect(); + cachedSocket.send(createReconnectionEvent()); + }); + return cachedSocket; +} +function getCachedSocket() { + return cachedSocket; } </script> diff -r aaf420944100 -r 967433020ded vcweb/forestry/templates/forestry/chat.html --- a/vcweb/forestry/templates/forestry/chat.html Sun Mar 20 23:19:51 2011 -0700 +++ b/vcweb/forestry/templates/forestry/chat.html Mon Mar 21 17:02:54 2011 -0700 @@ -1,47 +1,46 @@ {% extends "base-participant.html" %} {% block head %} - {{ block.super }} - {% include "includes/participant.events.html" %} - {% include "includes/socket.io.html" %} - <script type="text/javascript"> - $(function() { - var chatDiv = document.getElementById('chat-div'); - var s = connect(window.location.hostname, 8888, 'participant/{{participant_experiment_relationship.pk}}'); - s.on('message', function(json_string) { - var json = jQuery.parseJSON(json_string); - switch (json.message_type) { - case 'chat': - console.log("Received " + json.pk + " " + json.date_created + " " + json.message); - $("#chat-div").append( - $("<div class='ui-state-highlight' />") - .append($("<a />").attr("name", "" + json.pk) - .text("" + json.date_created)) - .append(" | ") - .append(json.message)); +{{ block.super }} +<script type="text/javascript"> + $(function() { + var chatDiv = document.getElementById('chat-div'); + // var s = connect(window.location.hostname, 8888, 'participant/{{participant_experiment_relationship.pk}}'); + var s = getCachedSocket(); + s.on('message', function(json_string) { + var json = jQuery.parseJSON(json_string); + switch (json.message_type) { + case 'chat': + console.log("Received " + json.pk + " " + json.date_created + " " + json.message); + $("#chat-div").append( + $("<div class='ui-state-highlight' />") + .append($("<a />").attr("name", "" + json.pk) + .text("" + json.date_created)) + .append(" | ") + .append(json.message)); // scroll to bottom - chatDiv.scrollTop = chatDiv.scrollHeight; - break; - case 'refresh': - location.reload(true); - break; - case 'goto': - location.href = json.url; - break; - } - }); - //send the message when submit is clicked - $('#chatform').submit(function (evt) { - var line = $('#chatText').val() - if (line) { - $('#chatText').val('') - s.send(createMessageEvent(line)); - } - return false; - }); - $('#chatText').focus(); chatDiv.scrollTop = chatDiv.scrollHeight; + break; + case 'refresh': + location.reload(true); + break; + case 'goto': + location.href = json.url; + break; + } }); - </script> + //send the message when submit is clicked + $('#chatform').submit(function (evt) { + var line = $('#chatText').val() + if (line) { + $('#chatText').val('') + s.send(createMessageEvent(line)); + } + return false; + }); + $('#chatText').focus(); + chatDiv.scrollTop = chatDiv.scrollHeight; + }); +</script> {% endblock %} {% block title %} Forestry Chat Round diff -r aaf420944100 -r 967433020ded vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Sun Mar 20 23:19:51 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Mon Mar 21 17:02:54 2011 -0700 @@ -1,8 +1,6 @@ {% extends "base-participant.html" %} {% block head %} {{ block.super }} -{% include "includes/participant.events.html" %} -{% include "includes/socket.io.html" %} <script type="text/javascript"> $(function() { $("#forestryForm").validate({ @@ -23,7 +21,7 @@ this.select(); }); $('#harvestDecisionId').focus(); - var s = connect(window.location.hostname, 8888, 'participant/{{participant_group_relationship.pk}}'); + var s = getCachedSocket(); s.on('message', function(json_string) { var json = jQuery.parseJSON(json_string); switch (json.message_type) { diff -r aaf420944100 -r 967433020ded vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Sun Mar 20 23:19:51 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Mon Mar 21 17:02:54 2011 -0700 @@ -5,7 +5,8 @@ {% include "includes/socket.io.html" %} <script type="text/javascript"> $(function() { - var s = connect(window.location.hostname, 8888, 'participant/{{participant_group_relationship.pk}}'); + // var s = connect(window.location.hostname, 8888, 'participant/{{participant_experiment_relationship.pk}}'); + var s = getCachedSocket(); s.on('message', function(json_string) { var json = jQuery.parseJSON(json_string); switch (json.message_type) { diff -r aaf420944100 -r 967433020ded vcweb/forestry/views.py --- a/vcweb/forestry/views.py Sun Mar 20 23:19:51 2011 -0700 +++ b/vcweb/forestry/views.py Mon Mar 21 17:02:54 2011 -0700 @@ -183,6 +183,7 @@ def play(request, experiment, participant): form = HarvestDecisionForm(request.POST or None) participant_group_relationship = participant.get_participant_group_relationship(experiment) + participant_experiment_relationship = participant.get_participant_experiment_relationship(experiment) harvest_decision = get_harvest_decision(participant_group_relationship) if form.is_valid(): resources_harvested = form.cleaned_data['harvest_decision'] diff -r aaf420944100 -r 967433020ded vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Sun Mar 20 23:19:51 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Mon Mar 21 17:02:54 2011 -0700 @@ -60,6 +60,8 @@ def get_participant_group_relationship(self, connection): if connection in self.connection_to_participant: (participant_pk, experiment_pk) = self.connection_to_participant[connection] + logger.debug("Looking for ParticipantGroupRelationship with tuple (%s, %s)" % + (participant_pk, experiment_pk)) return ParticipantGroupRelationship.objects.get(participant__pk=participant_pk, group__experiment__pk = experiment_pk) logger.debug("Didn't find connection %s in connection map %s." % (connection, self.connection_to_participant)) return None |
From: <vir...@li...> - 2011-03-21 06:17:57
|
Subject: hg.virtualcommons 287 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/aaf420944100 changeset: 287:aaf420944100 user: Allen Lee <all...@as...> date: Sun Mar 20 23:19:51 2011 -0700 description: lowercasing email on registration and auth check diffstat: vcweb/core/auth.py | 4 ++-- vcweb/core/forms.py | 3 ++- vcweb/core/views.py | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diffs (46 lines): diff -r 987a264b1b7a -r aaf420944100 vcweb/core/auth.py --- a/vcweb/core/auth.py Sun Mar 20 22:47:09 2011 -0700 +++ b/vcweb/core/auth.py Sun Mar 20 23:19:51 2011 -0700 @@ -21,10 +21,10 @@ def authenticate(self, username=None, password=None): if email_re.search(username): try: - user = User.objects.get(email=username) + user = User.objects.get(email=username.lower()) if user.check_password(password): return user - # check for and handle participants logging in with an auth? + # check for and handle participants logging in with an auth code? except User.DoesNotExist: return None return None diff -r 987a264b1b7a -r aaf420944100 vcweb/core/forms.py --- a/vcweb/core/forms.py Sun Mar 20 22:47:09 2011 -0700 +++ b/vcweb/core/forms.py Sun Mar 20 23:19:51 2011 -0700 @@ -1,4 +1,5 @@ from django import forms +from django.contrib.auth.models import User from django.forms import widgets from django.utils.translation import ugettext_lazy as _ @@ -16,7 +17,7 @@ institution = forms.CharField(widget=widgets.TextInput(attrs=REQUIRED_ATTRIBUTES)) def clean_email(self): - email = self.cleaned_data['email'] + email = self.cleaned_data['email'].lower() try: User.objects.get(email=email) except User.DoesNotExist: diff -r 987a264b1b7a -r aaf420944100 vcweb/core/views.py --- a/vcweb/core/views.py Sun Mar 20 22:47:09 2011 -0700 +++ b/vcweb/core/views.py Sun Mar 20 23:19:51 2011 -0700 @@ -59,7 +59,7 @@ if request.method == 'POST': form = RegistrationForm(request.POST) if form.is_valid(): - email = form.cleaned_data['email'] + email = form.cleaned_data['email'].lower() password = form.cleaned_data['password'] first_name = form.cleaned_data['first_name'] last_name = form.cleaned_data['last_name'] |
From: <vir...@li...> - 2011-03-21 05:45:14
|
Subject: hg.virtualcommons 286 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/987a264b1b7a changeset: 286:987a264b1b7a user: Allen Lee <all...@as...> date: Sun Mar 20 22:47:09 2011 -0700 description: making slug field not required in admin page diffstat: vcweb/core/models.py | 6 +++--- vcweb/fabfile.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diffs (53 lines): diff -r 8205d857525e -r 987a264b1b7a vcweb/core/models.py --- a/vcweb/core/models.py Sun Mar 20 21:27:22 2011 -0700 +++ b/vcweb/core/models.py Sun Mar 20 22:47:09 2011 -0700 @@ -146,7 +146,7 @@ return self.experiment_metadata.namespace def __unicode__(self): - return u"ExperimentConfiguration %s for %s" % (self.name, self.experiment_metadata) + return u"%s configuration for the %s" % (self.name, self.experiment_metadata) class Meta: ordering = ['experiment_metadata', 'creator', 'date_created'] @@ -213,7 +213,7 @@ short slug to use instead of pk FIXME: still needs to be implemented ''' - slug = models.SlugField(max_length=16, unique=True, null=True) + slug = models.SlugField(max_length=16, unique=True, null=True, blank=True) objects = ExperimentManager() @@ -589,7 +589,7 @@ return Template(template_string).substitute(kwargs, round_number=self.display_number, participant_id=participant_id) def __unicode__(self): - return u"Round %d, sequence: %d" % (self.round_number, self.sequence_number) + return u"sequence %d, round %d, (%s | %s)" % (self.sequence_number, self.round_number, self.round_type, self.experiment_configuration) @property def display_label(self): diff -r 8205d857525e -r 987a264b1b7a vcweb/fabfile.py --- a/vcweb/fabfile.py Sun Mar 20 21:27:22 2011 -0700 +++ b/vcweb/fabfile.py Sun Mar 20 22:47:09 2011 -0700 @@ -14,7 +14,7 @@ env.deploy_group = 'commons' env.virtualenv_path = '/opt/virtualenvs/%(project_name)s' % env env.deploy_path = '/opt/webapps/virtualcommons/' -# default to current working directory +# default to current working directory env.project_path = os.path.dirname(__file__) env.hosts = ['localhost'] env.hg_url = 'http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons' @@ -120,8 +120,8 @@ def setup(): setup_virtualenv() sudo('hg clone %(hg_url)s %(deploy_path)s' % env, pty=True, user=env.deploy_user) - sudo_chain('chown -R %(deploy_user)s:%(deploy_group)s %(deploy_path)s' % env, - 'chmod -R ug+rw %(deploy_path)s' % env, + sudo_chain('chown -R %(deploy_user)s:%(deploy_group)s %(deploy_path)s' % env, + 'chmod -R ug+rw %(deploy_path)s' % env, 'find %(deploy_path)s -type d -exec chmod ug+x {} \;' % env, pty=True) pip() |
From: <vir...@li...> - 2011-03-21 04:25:26
|
Subject: hg.virtualcommons 285 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/8205d857525e changeset: 285:8205d857525e user: Allen Lee <all...@as...> date: Sun Mar 20 21:27:22 2011 -0700 description: refactoring parameter code diffstat: vcweb/core/models.py | 6 +- vcweb/forestry/fixtures/initial_data.json | 297 ++++++++++++++++++-------------- vcweb/forestry/management.py | 8 +- vcweb/forestry/models.py | 21 +- vcweb/requirements.pip | 7 +- 5 files changed, 189 insertions(+), 150 deletions(-) diffs (543 lines): diff -r a7847446512b -r 8205d857525e vcweb/core/models.py --- a/vcweb/core/models.py Sun Mar 20 18:04:16 2011 -0700 +++ b/vcweb/core/models.py Sun Mar 20 21:27:22 2011 -0700 @@ -656,6 +656,7 @@ scope = models.CharField(max_length=32, choices=SCOPE_CHOICES, default=ROUND_SCOPE) name = models.CharField(max_length=255, unique=True) display_name = models.CharField(max_length=255, null=True, blank=True) + description = models.CharField(max_length=512, null=True, blank=True) type = models.CharField(max_length=32, choices=PARAMETER_TYPES) default_value_string = models.CharField(max_length=255, null=True, blank=True) date_created = models.DateTimeField(auto_now_add=True) @@ -870,7 +871,10 @@ def get_data_value(self, parameter=None, parameter_name=None, round_data=None): criteria = self._data_parameter_criteria(parameter=parameter, parameter_name=parameter_name, round_data=round_data) logger.debug("criteria: %s" % criteria) - return self.data_values.get_or_create(**criteria)[0] + data_value, created = self.data_values.get_or_create(**criteria) + if created: + logger.debug("Created new data value in get_data_value: %s" % data_value) + return data_value def _data_parameter_criteria(self, parameter=None, parameter_name=None, round_data=None): return dict([('parameter', parameter) if parameter else ('parameter__name', parameter_name), diff -r a7847446512b -r 8205d857525e vcweb/forestry/fixtures/initial_data.json --- a/vcweb/forestry/fixtures/initial_data.json Sun Mar 20 18:04:16 2011 -0700 +++ b/vcweb/forestry/fixtures/initial_data.json Sun Mar 20 21:27:22 2011 -0700 @@ -1,177 +1,177 @@ [ { "fields": { - "creator": 1, + "creator": 1, "experiment_metadata": [ "forestry" - ], - "is_public": true, - "max_group_size": 5, - "max_number_of_participants": 20, + ], + "is_public": true, + "max_group_size": 5, + "max_number_of_participants": 20, "name": "Forestry Default Configuration" - }, - "model": "core.experimentconfiguration", + }, + "model": "core.experimentconfiguration", "pk": 1 - }, + }, { - "pk": 2, - "model": "core.experimenter", + "pk": 2, + "model": "core.experimenter", "fields": { - "approved": true, - "user": 12, - "failed_password_attempts": 0, + "approved": true, + "user": 12, + "failed_password_attempts": 0, "institution": 1 } - }, + }, { "fields": { - "authentication_code": "TEST_FORESTRY", - "current_round_elapsed_time": 0, - "current_round_sequence_number": 1, - "duration": "1h", - "experiment_configuration": 1, - "experiment_metadata": 1, - "experimenter": 2, - "is_experimenter_driven": true, - "start_date_time": null, - "status": "INACTIVE", - "tick_duration": "10s", + "authentication_code": "TEST_FORESTRY", + "current_round_elapsed_time": 0, + "current_round_sequence_number": 1, + "duration": "1h", + "experiment_configuration": 1, + "experiment_metadata": 1, + "experimenter": 2, + "is_experimenter_driven": true, + "start_date_time": null, + "status": "INACTIVE", + "tick_duration": "10s", "total_elapsed_time": 0 - }, - "model": "core.experiment", + }, + "model": "core.experiment", "pk": 1 - }, + }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 0, - "experiment_configuration": 1, - "instructions": "Welcome to the forestry experiment.", - "last_modified": "2010-09-07 15:13:03", - "round_type": "INSTRUCTIONS", + "date_created": "2010-09-07 15:13:03", + "duration": 0, + "experiment_configuration": 1, + "instructions": "Welcome to the forestry experiment.", + "last_modified": "2010-09-07 15:13:03", + "round_type": "INSTRUCTIONS", "sequence_number": 1 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 1 - }, + }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 0, - "experiment_configuration": 1, - "instructions": "The following quiz is designed to ensure you understand the dynamics of this experiment.", - "last_modified": "2010-09-07 15:13:03", - "round_type": "PRACTICE", + "date_created": "2010-09-07 15:13:03", + "duration": 0, + "experiment_configuration": 1, + "instructions": "The following quiz is designed to ensure you understand the dynamics of this experiment.", + "last_modified": "2010-09-07 15:13:03", + "round_type": "PRACTICE", "sequence_number": 2 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 2 - }, + }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 60, - "experiment_configuration": 1, - "instructions": "This is a practice round.", - "last_modified": "2010-09-07 15:13:03", - "round_type": "PRACTICE", + "date_created": "2010-09-07 15:13:03", + "duration": 60, + "experiment_configuration": 1, + "instructions": "This is a practice round.", + "last_modified": "2010-09-07 15:13:03", + "round_type": "PRACTICE", "sequence_number": 3 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 3 - }, + }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 60, - "experiment_configuration": 1, - "instructions": "Chat round.", - "last_modified": "2010-09-07 15:13:03", - "round_type": "CHAT", + "date_created": "2010-09-07 15:13:03", + "duration": 60, + "experiment_configuration": 1, + "instructions": "Chat round.", + "last_modified": "2010-09-07 15:13:03", + "round_type": "CHAT", "sequence_number": 4 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 4 }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 60, - "experiment_configuration": 1, - "instructions": "This is a practice round.", - "last_modified": "2010-09-07 15:13:03", - "round_type": "PRACTICE", + "date_created": "2010-09-07 15:13:03", + "duration": 60, + "experiment_configuration": 1, + "instructions": "This is a practice round.", + "last_modified": "2010-09-07 15:13:03", + "round_type": "PRACTICE", "sequence_number": 5 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 5 }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 60, - "experiment_configuration": 1, - "instructions": "An actual forestry round.", - "last_modified": "2010-09-07 15:13:03", - "round_type": "REGULAR", + "date_created": "2010-09-07 15:13:03", + "duration": 60, + "experiment_configuration": 1, + "instructions": "An actual forestry round.", + "last_modified": "2010-09-07 15:13:03", + "round_type": "REGULAR", "display_number": 1, "sequence_number": 6 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 6 }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 60, - "experiment_configuration": 1, - "instructions": "Chat round.", - "last_modified": "2010-09-07 15:13:03", - "round_type": "CHAT", + "date_created": "2010-09-07 15:13:03", + "duration": 60, + "experiment_configuration": 1, + "instructions": "Chat round.", + "last_modified": "2010-09-07 15:13:03", + "round_type": "CHAT", "sequence_number": 7 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 7 }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 60, - "experiment_configuration": 1, - "instructions": "Forestry round", - "last_modified": "2010-09-07 15:13:03", - "round_type": "REGULAR", + "date_created": "2010-09-07 15:13:03", + "duration": 60, + "experiment_configuration": 1, + "instructions": "Forestry round", + "last_modified": "2010-09-07 15:13:03", + "round_type": "REGULAR", "display_number": 2, "sequence_number": 8 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 8 }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 60, - "experiment_configuration": 1, - "instructions": "Chat round.", - "last_modified": "2010-09-07 15:13:03", - "round_type": "CHAT", + "date_created": "2010-09-07 15:13:03", + "duration": 60, + "experiment_configuration": 1, + "instructions": "Chat round.", + "last_modified": "2010-09-07 15:13:03", + "round_type": "CHAT", "sequence_number": 9 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 9 }, { "fields": { - "date_created": "2010-09-07 15:13:03", - "duration": 60, - "experiment_configuration": 1, - "instructions": "Forestry round", - "last_modified": "2010-09-07 15:13:03", - "round_type": "REGULAR", + "date_created": "2010-09-07 15:13:03", + "duration": 60, + "experiment_configuration": 1, + "instructions": "Forestry round", + "last_modified": "2010-09-07 15:13:03", + "round_type": "REGULAR", "display_number": 3, "sequence_number": 10 - }, - "model": "core.roundconfiguration", + }, + "model": "core.roundconfiguration", "pk": 10 }, { @@ -180,10 +180,10 @@ "experiment_metadata": 1, "creator": 1, "type": "int", - "date_created": "2011-01-01 15:13:03", + "date_created": "2011-01-01 15:13:03", "scope": "participant" - }, - "model": "core.parameter", + }, + "model": "core.parameter", "pk": 1 }, { @@ -192,10 +192,10 @@ "experiment_metadata": 1, "creator": 1, "type": "int", - "date_created": "2011-01-01 15:13:07", + "date_created": "2011-01-01 15:13:07", "scope": "group" - }, - "model": "core.parameter", + }, + "model": "core.parameter", "pk": 2 }, { @@ -206,8 +206,8 @@ "type": "boolean", "scope": "round", "default_value_string": "true" - }, - "model": "core.parameter", + }, + "model": "core.parameter", "pk": 3 }, { @@ -218,17 +218,52 @@ "type": "int", "scope": "round", "default_value_string": 100 - }, - "model": "core.parameter", + }, + "model": "core.parameter", "pk": 4 }, { + "pk": 5, + "model": "core.parameter", + "fields": { + "experiment_metadata": 1, + "description": "Number of regrown trees for a given group in a given round.", + "display_name": "Group regrowth", + "name": "group_regrowth", + "creator": 1, + "default_value_string": "", + "last_modified": "2011-03-15 17:05:36", + "scope": "group", + "date_created": "2011-03-15 17:02:47", + "enum_choices": "", + "is_required": false, + "type": "int" + } + }, { + "pk": 6, + "model": "core.parameter", + "fields": { + "experiment_metadata": 1, + "display_name": "Group harvest", + "description": "The number of trees harvested by this group in this round.", + "name": "group_harvest", + "creator": 1, + "default_value_string": "", + "last_modified": "2011-03-15 17:04:24", + "scope": "group", + "date_created": "2011-03-15 17:04:24", + "enum_choices": "", + "is_required": false, + "type": "int" + } + }, + { "fields": { "round_configuration": 2, "parameter": [ "reset.resource_level" ], "boolean_value": "True" - }, - "model": "core.roundparametervalue", + }, + "model": "core.roundparametervalue", "pk": 8 }, { @@ -236,8 +271,8 @@ "round_configuration": 2, "parameter": [ "initial.resource_level" ], "int_value": 100 - }, - "model": "core.roundparametervalue", + }, + "model": "core.roundparametervalue", "pk": 9 }, { @@ -245,8 +280,8 @@ "round_configuration": 3, "parameter": [ "reset.resource_level" ], "boolean_value": "True" - }, - "model": "core.roundparametervalue", + }, + "model": "core.roundparametervalue", "pk": 1 }, { @@ -254,8 +289,8 @@ "round_configuration": 3, "parameter": [ "initial.resource_level" ], "int_value": 100 - }, - "model": "core.roundparametervalue", + }, + "model": "core.roundparametervalue", "pk": 2 }, { @@ -263,8 +298,8 @@ "round_configuration": 5, "parameter": [ "reset.resource_level" ], "boolean_value": "False" - }, - "model": "core.roundparametervalue", + }, + "model": "core.roundparametervalue", "pk": 3 } ] diff -r a7847446512b -r 8205d857525e vcweb/forestry/management.py --- a/vcweb/forestry/management.py Sun Mar 20 18:04:16 2011 -0700 +++ b/vcweb/forestry/management.py Sun Mar 20 21:27:22 2011 -0700 @@ -11,7 +11,10 @@ ''' creates the forestry ExperimentMetadata record if not already created. -is this any better than adding it to directly to initial_data.json? +XXX: also create forestry parameters here? + +FIXME: what are pros/cons for doing it this way vs adding it to initial_data.json +pro: don't have to hard-code pks and pk references.. ''' def post_syncdb_handler(sender, **kwargs): @@ -22,7 +25,8 @@ "title": "Forestry Web Experiment", "date_created": "2011-01-01" } - logger.debug("forestry: %s (%s)" % ExperimentMetadata.objects.get_or_create(**forestry_dict)) + forestry_metadata, created = ExperimentMetadata.objects.get_or_create(**forestry_dict) + logger.debug("forestry: %s (%s)" % (forestry_metadata, created)) post_syncdb.connect(post_syncdb_handler, sender=vcweb.core.models, dispatch_uid='forestry_metadata_creator') diff -r a7847446512b -r 8205d857525e vcweb/forestry/models.py --- a/vcweb/forestry/models.py Sun Mar 20 18:04:16 2011 -0700 +++ b/vcweb/forestry/models.py Sun Mar 20 21:27:22 2011 -0700 @@ -10,22 +10,19 @@ check all forestry experiments. ''' -# returns a GroupRoundDataValue. FIXME: duplication across get_group_harvest and get_regrowth +# returns GroupRoundDataValue. def get_resource_level(group=None, round_data=None): - return group.get_data_value(parameter=get_resource_level_parameter(), round_data=round_data) if group else None + return group.get_data_value(parameter=get_resource_level_parameter(), round_data=round_data) + +def get_group_harvest(group, round_data=None): + return group.get_data_value(parameter=get_group_harvest_parameter(), round_data=round_data) + +def get_regrowth(group, round_data=None): + return group.get_data_value(parameter=get_regrowth_parameter(), round_data=round_data) def has_resource_level(group=None): return group.has_data_parameter(parameter=get_resource_level_parameter()) -def get_group_harvest(group, round_data=None): - if round_data is None: - round_data = group.current_round_data - return group.get_data_value(parameter=get_group_harvest_parameter(), round_data=round_data) if group else None - -def get_regrowth(group, round_data=None): - if round_data is None: - round_data = group.current_round_data - return group.get_data_value(parameter=get_regrowth_parameter(), round_data=round_data) if group else None def get_harvest_decision(participant_group_relationship, round_data=None): if round_data is None: @@ -68,7 +65,7 @@ experiment_metadata=get_forestry_experiment_metadata()) def get_regrowth_parameter(): - return Parameter.objects.get(name='regrowth', + return Parameter.objects.get(name='group_regrowth', scope=Parameter.GROUP_SCOPE, experiment_metadata=get_forestry_experiment_metadata()) diff -r a7847446512b -r 8205d857525e vcweb/requirements.pip --- a/vcweb/requirements.pip Sun Mar 20 18:04:16 2011 -0700 +++ b/vcweb/requirements.pip Sun Mar 20 21:27:22 2011 -0700 @@ -1,13 +1,12 @@ Django +psycopg2 celery +tornadio +tornado django-celery -tornado -tornadio -psycopg2 kombu django-kombu django-dajaxice -# needed to run tests with ghettoq for some reason.. #django-unittest-depth #redis #beanstalkc |
From: <vir...@li...> - 2011-03-21 01:11:19
|
Subject: hg.virtualcommons 284 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/a7847446512b changeset: 284:a7847446512b user: Allen Lee <all...@as...> date: Sun Mar 20 18:04:16 2011 -0700 description: only providing participant history for playable rounds (regular or practice rounds) diffstat: vcweb/core/models.py | 7 ++++++- vcweb/forestry/views.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diffs (43 lines): diff -r 906ed355ed25 -r a7847446512b vcweb/core/models.py --- a/vcweb/core/models.py Wed Mar 16 18:18:40 2011 -0700 +++ b/vcweb/core/models.py Sun Mar 20 18:04:16 2011 -0700 @@ -295,6 +295,10 @@ return round_data @property + def playable_round_data(self): + return self.round_data.filter(round_configuration__round_type__in=RoundConfiguration.PLAYABLE_ROUND_CONFIGURATIONS) + + @property def all_quiz_questions(self): # FIXME: use generator expression? quiz_questions = list(self.default_quiz_questions.all()) @@ -482,6 +486,7 @@ ROUND_TYPES = (CHAT, DEBRIEFING, INSTRUCTIONS, PRACTICE, QUIZ, REGULAR) = sorted(ROUND_TYPES_DICT.keys()) ROUND_TYPE_CHOICES = [(round_type, ROUND_TYPES_DICT[round_type][0]) for round_type in ROUND_TYPES] + PLAYABLE_ROUND_CONFIGURATIONS = (PRACTICE, REGULAR) experiment_configuration = models.ForeignKey(ExperimentConfiguration, related_name='round_configurations') @@ -555,7 +560,7 @@ @property def is_playable_round(self): - return self.round_type in (RoundConfiguration.PRACTICE, RoundConfiguration.REGULAR) + return self.round_type in RoundConfiguration.PLAYABLE_ROUND_CONFIGURATIONS def get_parameter(self, name): parameter = Parameter.objects.get(name=name, scope=Parameter.ROUND_SCOPE) diff -r 906ed355ed25 -r a7847446512b vcweb/forestry/views.py --- a/vcweb/forestry/views.py Wed Mar 16 18:18:40 2011 -0700 +++ b/vcweb/forestry/views.py Sun Mar 20 18:04:16 2011 -0700 @@ -68,7 +68,7 @@ group = participant_group_relationship.group experiment = group.experiment all_harvest_round_data = [] - for round_data in experiment.round_data.all(): + for round_data in experiment.playable_round_data: p = ParticipantHistory() p.round_configuration = round_data.round_configuration p.individual_harvest = get_harvest_decision(participant_group_relationship, round_data=round_data) |
From: <vir...@li...> - 2011-03-17 01:17:17
|
Subject: hg.virtualcommons 283 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/906ed355ed25 changeset: 283:906ed355ed25 user: Allen Lee <all...@as...> date: Wed Mar 16 18:18:40 2011 -0700 description: changing chat messaging and removing socket_io context processor since window.location.hostname works just as well. diffstat: vcweb/core/context_processors.py | 2 -- vcweb/core/models.py | 13 +++++++------ vcweb/forestry/templates/forestry/chat.html | 12 ++++++++---- vcweb/settings.py | 3 --- vcweb/settings_production.py | 2 -- vcweb/vcweb-tornadio.py | 9 ++++----- 6 files changed, 19 insertions(+), 22 deletions(-) diffs (127 lines): diff -r 584fe7694e87 -r 906ed355ed25 vcweb/core/context_processors.py --- a/vcweb/core/context_processors.py Wed Mar 16 12:56:43 2011 -0700 +++ b/vcweb/core/context_processors.py Wed Mar 16 18:18:40 2011 -0700 @@ -3,5 +3,3 @@ def debug_mode(request): return {'debug_mode': settings.DEBUG} -def socket_io(request): - return {'socket_io_host' : settings.SOCKET_IO_HOST} diff -r 584fe7694e87 -r 906ed355ed25 vcweb/core/models.py --- a/vcweb/core/models.py Wed Mar 16 12:56:43 2011 -0700 +++ b/vcweb/core/models.py Wed Mar 16 18:18:40 2011 -0700 @@ -1112,11 +1112,6 @@ objects = ChatMessageManager() - def __unicode__(self): - """ return this participant's sequence number combined with the message """ - participant_number = self.participant_group_relationship.participant_number - return u"{0}: {1}".format(participant_number, self.message) - @property def group(self): return self.participant_group_relationship.group @@ -1132,9 +1127,15 @@ @property def as_html(self): return "<a name='{0}'>{1}</a> | {2}".format(self.pk, - self.date_created.strftime("%H:%S"), + self.date_created.strftime("%H:%M:%S"), self.__unicode__()) + + def __unicode__(self): + """ return this participant's sequence number combined with the message """ + participant_number = self.participant_group_relationship.participant_number + return u"{0}: {1}".format(participant_number, self.message) + class Meta: ordering = ['date_created'] diff -r 584fe7694e87 -r 906ed355ed25 vcweb/forestry/templates/forestry/chat.html --- a/vcweb/forestry/templates/forestry/chat.html Wed Mar 16 12:56:43 2011 -0700 +++ b/vcweb/forestry/templates/forestry/chat.html Wed Mar 16 18:18:40 2011 -0700 @@ -11,7 +11,13 @@ var json = jQuery.parseJSON(json_string); switch (json.message_type) { case 'chat': - $("#chat-div").append($("<div class='ui-state-highlight' />").append(json.message)) + console.log("Received " + json.pk + " " + json.date_created + " " + json.message); + $("#chat-div").append( + $("<div class='ui-state-highlight' />") + .append($("<a />").attr("name", "" + json.pk) + .text("" + json.date_created)) + .append(" | ") + .append(json.message)); // scroll to bottom chatDiv.scrollTop = chatDiv.scrollHeight; break; @@ -53,9 +59,7 @@ <div id='chat-div' class='chat notice ui-corner-all'> {% for chat_message in chat_messages %} <div class='ui-state-highlight'> - {% autoescape off %} - {{ chat_message.as_html }} - {% endautoescape %} + <a name='{{chat_message.pk}}'>{{chat_message.date_created|date:"G:i:s"}}</a> | {{chat_message}} </div> {% endfor %} </div> diff -r 584fe7694e87 -r 906ed355ed25 vcweb/settings.py --- a/vcweb/settings.py Wed Mar 16 12:56:43 2011 -0700 +++ b/vcweb/settings.py Wed Mar 16 18:18:40 2011 -0700 @@ -71,7 +71,6 @@ 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', # 'django.core.context_processors.static', - 'vcweb.core.context_processors.socket_io', ) MIDDLEWARE_CLASSES = ( @@ -112,8 +111,6 @@ DAJAXICE_MEDIA_PREFIX = "dajaxice" -SOCKET_IO_HOST = "vcweb.asu.edu" - EMAIL_HOST = "smtp.asu.edu" # celery rabbitmq/amqp configuration diff -r 584fe7694e87 -r 906ed355ed25 vcweb/settings_production.py --- a/vcweb/settings_production.py Wed Mar 16 12:56:43 2011 -0700 +++ b/vcweb/settings_production.py Wed Mar 16 18:18:40 2011 -0700 @@ -61,6 +61,4 @@ # Make this unique, and don't share it with anybody. SECRET_KEY = 'CUSTOMIZE_ME' -SOCKET_IO_HOST = "vcweb.asu.edu" EMAIL_HOST = "smtp.asu.edu" - diff -r 584fe7694e87 -r 906ed355ed25 vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Wed Mar 16 12:56:43 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Wed Mar 16 18:18:40 2011 -0700 @@ -213,11 +213,8 @@ })) except KeyError, e: logger.debug("no participant group relationship id %s" % e) - pass except ParticipantExperimentRelationship.DoesNotExist, e: - logger.debug("no participant group relationship with id %s (%s)" % - (participant_experiment_relationship_id, e)) - pass + logger.debug("no participant experiment relationship with id %s (%s)" % (relationship_id, e)) def on_message(self, message, *args, **kwargs): logger.debug("received message %s from handler %s" % (message, self)) @@ -233,7 +230,9 @@ ) for participant_group_pk, connection in connection_manager.connections(participant_group_relationship.group): connection.send(simplejson.dumps({ - "message" : chat_message.as_html, + "pk": chat_message.pk, + "date_created": chat_message.date_created.strftime("%H:%M:%S"), + "message" : chat_message.__unicode__(), "message_type": 'chat', })) |
From: <vir...@li...> - 2011-03-16 19:55:16
|
Subject: hg.virtualcommons 282 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/584fe7694e87 changeset: 282:584fe7694e87 user: Allen Lee <all...@as...> date: Wed Mar 16 12:56:43 2011 -0700 description: adding experimenter check to monitor (all experimenter_required functions should have it actually) and fixed participant_experiment_relationship reference in chat diffstat: vcweb/core/templates/includes/participant.events.html | 3 + vcweb/core/views.py | 7 +- vcweb/forestry/models.py | 4 +- vcweb/forestry/templates/forestry/chat.html | 2 +- vcweb/forestry/templates/forestry/includes/harvest-table.html | 4 +- vcweb/forestry/templates/forestry/participate.html | 8 ++- vcweb/forestry/templates/forestry/wait.html | 9 ++- vcweb/forestry/views.py | 43 +++++++------ vcweb/vcweb-tornadio.py | 2 +- 9 files changed, 50 insertions(+), 32 deletions(-) diffs (235 lines): diff -r ae453f04d057 -r 584fe7694e87 vcweb/core/templates/includes/participant.events.html --- a/vcweb/core/templates/includes/participant.events.html Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/core/templates/includes/participant.events.html Wed Mar 16 12:56:43 2011 -0700 @@ -22,4 +22,7 @@ function createChatEvent(message) { return createMessageEvent(message); } +function createSubmitEvent(message) { + return createMessageEvent(message, "submit"); +} </script> diff -r ae453f04d057 -r 584fe7694e87 vcweb/core/views.py --- a/vcweb/core/views.py Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/core/views.py Wed Mar 16 12:56:43 2011 -0700 @@ -141,15 +141,16 @@ @experimenter_required def monitor(request, experiment_id=None): - try : + try: experiment = Experiment.objects.get(pk=experiment_id) - return render_to_response('monitor.html', locals(), context_instance=RequestContext(request)) + if request.user.experimenter.pk == experiment.experimenter.pk: + return render_to_response('monitor.html', locals(), context_instance=RequestContext(request)) # redirect to experiment specific management page? except Experiment.DoesNotExist: error_message = "Tried to monitor non-existent experiment (id %s)" % experiment_id logger.warning(error_message) messages.warning(request, error_message) - return redirect('core:dashboard') + return redirect('core:dashboard') # FIXME: add data converter objects to write to csv, excel, etc. @experimenter_required diff -r ae453f04d057 -r 584fe7694e87 vcweb/forestry/models.py --- a/vcweb/forestry/models.py Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/forestry/models.py Wed Mar 16 12:56:43 2011 -0700 @@ -130,6 +130,8 @@ ''' only calculate new resource levels for practice or regular rounds ''' resource_level_parameter = get_resource_level_parameter() current_round_configuration = experiment.current_round +# FIXME: make a round parameter for this. + max_resource_level = 100 for group in experiment.groups.all(): # implements regrowth function inline if has_resource_level(group): @@ -147,7 +149,7 @@ regrowth = current_resource_level.value / 10 group.log("Regrowth: adding %s to current resource level %s" % (regrowth, current_resource_level.value)) set_regrowth(group, regrowth) - current_resource_level.value = current_resource_level.value + regrowth + current_resource_level.value = min(current_resource_level.value + regrowth, max_resource_level) current_resource_level.save() group.log("Transferring resource level %s to next round" % get_resource_level(group)) group.transfer_to_next_round(resource_level_parameter) diff -r ae453f04d057 -r 584fe7694e87 vcweb/forestry/templates/forestry/chat.html --- a/vcweb/forestry/templates/forestry/chat.html Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/forestry/templates/forestry/chat.html Wed Mar 16 12:56:43 2011 -0700 @@ -46,7 +46,7 @@ <div class='info ui-corner-all'> <span class='icon-left ui-icon ui-icon-info'></span> <b> - Hello, {{participant.get_full_name}}. + Hello, {{participant.full_name}}. You are participant {{ participant_group_relationship.participant_number }} in {{participant_group_relationship.group}}. </b> </div> diff -r ae453f04d057 -r 584fe7694e87 vcweb/forestry/templates/forestry/includes/harvest-table.html --- a/vcweb/forestry/templates/forestry/includes/harvest-table.html Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/forestry/templates/forestry/includes/harvest-table.html Wed Mar 16 12:56:43 2011 -0700 @@ -3,7 +3,7 @@ <h3>Maximum harvest table</h3> <table> <thead> - <tr><th>Current resource level</th><th>Maximum individual harvest level</th></tr> + <tr><th>Resource level</th><th>Maximum individual harvest</th></tr> </thead> <tbody> <tr class='harvest-5'><td>25-100</td><td>5</td></tr> @@ -14,4 +14,4 @@ <tr class='harvest-0'><td>0-4</td><td>0</td></tr> </tbody> </table> -</div> \ No newline at end of file +</div> diff -r ae453f04d057 -r 584fe7694e87 vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Wed Mar 16 12:56:43 2011 -0700 @@ -33,6 +33,12 @@ break; } }); + $('#submit-harvest-decision').click(function() { + $(this).attr('disabled', true); + harvestDecisionValue = $('#harvestDecisionId').val(); + alert("harvest decision: " + harvestDecisionValue); + s.send(createSubmitEvent($('#harvestDecisionId').val())); + }); }); </script> {% endblock %} @@ -67,7 +73,7 @@ <input id='harvestDecisionId' type="text" name='harvest_decision' class='required digits two-digits' maxlength='1'/> </div> <div class='field'> - <input type='submit' value='Submit' /> + <input id='submit-harvest-decision' type='submit' value='Submit' /> </div> </form> {% else %} diff -r ae453f04d057 -r 584fe7694e87 vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Wed Mar 16 12:56:43 2011 -0700 @@ -13,6 +13,9 @@ console.log("going to " + json.url); window.location.href = json.url; break; + case 'refresh': + window.location.reload(true); + break; } }); }); @@ -34,14 +37,15 @@ <h3>History</h3> <div id='group-history'> {% if all_harvest_round_data %} - <table> + <table class='debriefing'> <thead> - <tr><th>Round</th><th>Individual harvest</th><th>Group harvest</th><th>Original number of trees</th><th>Regrowth</th><th>Number of trees left</th></tr> + <tr><th>Round</th><th>Original number of trees</th><th>Your harvest decisions</th><th>Your group's total harvest decisions</th><th>Regrowth</th><th>Number of trees left</th></tr> </thead> <tbody> {% for harvest_round_data in all_harvest_round_data %} <tr> <td>{{harvest_round_data.round_configuration}}</td> + <td>{{harvest_round_data.original_number_of_trees}}</td> <td>{% if harvest_round_data.individual_harvest %} {{harvest_round_data.individual_harvest.value}} {% else %} @@ -49,7 +53,6 @@ {%endif%} </td> <td>{{harvest_round_data.group_harvest.value}}</td> - <td>{{harvest_round_data.original_number_of_trees}}</td> <td>{{harvest_round_data.regrowth.value}}</td> <td>{{harvest_round_data.final_number_of_trees}}</td> </tr> diff -r ae453f04d057 -r 584fe7694e87 vcweb/forestry/views.py --- a/vcweb/forestry/views.py Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/forestry/views.py Wed Mar 16 12:56:43 2011 -0700 @@ -64,6 +64,26 @@ class ParticipantHistory(object): pass +def generate_participant_history(participant_group_relationship): + group = participant_group_relationship.group + experiment = group.experiment + all_harvest_round_data = [] + for round_data in experiment.round_data.all(): + p = ParticipantHistory() + p.round_configuration = round_data.round_configuration + p.individual_harvest = get_harvest_decision(participant_group_relationship, round_data=round_data) + p.group_harvest = get_group_harvest(group, round_data=round_data) + p.regrowth = get_regrowth(group, round_data=round_data) + resource_level = get_resource_level(group, round_data=round_data) + try: + p.original_number_of_trees = resource_level.value + p.group_harvest.value - p.regrowth.value + except AttributeError: + pass + p.final_number_of_trees = resource_level.value + all_harvest_round_data.append(p) + logger.debug("all harvest round data: %s" % all_harvest_round_data) + return all_harvest_round_data + @participant_required def wait(request, experiment_id=None): try: @@ -71,25 +91,7 @@ participant = request.user.participant participant_experiment_relationship = participant.get_participant_experiment_relationship(experiment) participant_group_relationship = participant.get_participant_group_relationship(experiment) - logger.debug("participant group relationship is: %s" % participant_group_relationship) - all_harvest_round_data = [] - group = participant_group_relationship.group - for round_data in experiment.round_data.all(): - p = ParticipantHistory() - p.round_configuration = round_data.round_configuration - p.individual_harvest = get_harvest_decision(participant_group_relationship, round_data=round_data) - p.group_harvest = get_group_harvest(group, round_data=round_data) - p.regrowth = get_regrowth(group, round_data=round_data) - resource_level = get_resource_level(group, round_data=round_data) - try: - p.original_number_of_trees = resource_level.value + p.group_harvest.value - p.regrowth.value - except AttributeError: - pass - p.final_number_of_trees = resource_level.value - all_harvest_round_data.append(p) - - logger.debug("all harvest round data: %s" % all_harvest_round_data) - + all_harvest_round_data = generate_participant_history(participant_group_relationship) return render_to_response('forestry/wait.html', { 'participant_experiment_relationship': participant_experiment_relationship, 'participant_group_relationship':participant_group_relationship, @@ -165,13 +167,14 @@ def chat(request, experiment, participant): participant_group_rel = participant.get_participant_group_relationship(experiment) + participant_experiment_relationship = participant.get_participant_experiment_relationship(experiment) chat_messages = experiment.current_round_data.chat_messages.filter(participant_group_relationship__group=participant_group_rel.group) return render_to_response(experiment.current_round_template, { 'participant_group_relationship': participant_group_rel, + 'participant_experiment_relationship': participant_experiment_relationship, 'group': participant_group_rel.group, 'participant': participant, 'experiment': experiment, - 'SOCKET_IO_HOST': settings.SOCKET_IO_HOST, 'chat_messages': chat_messages, }, context_instance=RequestContext(request)) diff -r ae453f04d057 -r 584fe7694e87 vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Tue Mar 15 22:35:58 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Wed Mar 16 12:56:43 2011 -0700 @@ -80,7 +80,7 @@ del self.participant_to_connection[participant_tuple] del self.connection_to_participant[connection] except KeyError, k: - logger.warning( "caught key error %s while trying to remove connection %s" % (connection, k) ) + logger.warning("caught key error %s while trying to remove connection %s" % (connection, k) ) pass ''' |
From: <vir...@li...> - 2011-03-16 05:34:35
|
Subject: hg.virtualcommons 281 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/ae453f04d057 changeset: 281:ae453f04d057 user: Allen Lee <all...@as...> date: Tue Mar 15 22:35:58 2011 -0700 description: adding waiting stage debriefing, need to tie in realtime updating once all the decisions are in. diffstat: vcweb/core/models.py | 5 ++- vcweb/forestry/models.py | 39 +++++++++++++++++-- vcweb/forestry/templates/forestry/wait.html | 13 ++++-- vcweb/forestry/views.py | 9 +++- 4 files changed, 55 insertions(+), 11 deletions(-) diffs (170 lines): diff -r e96c5cca62ad -r ae453f04d057 vcweb/core/models.py --- a/vcweb/core/models.py Tue Mar 15 16:51:13 2011 -0700 +++ b/vcweb/core/models.py Tue Mar 15 22:35:58 2011 -0700 @@ -637,13 +637,15 @@ } GROUP_SCOPE = 'group' + GROUP_ROUND_SCOPE = 'group_round' PARTICIPANT_SCOPE = 'participant' ROUND_SCOPE = 'round' EXPERIMENT_SCOPE = 'experiment' SCOPE_CHOICES = ((ROUND_SCOPE, 'Parameter applies just for this round'), (EXPERIMENT_SCOPE, 'Parameter applies to this entire experiment'), - (GROUP_SCOPE, 'Parameter applies to the entire group'), + (GROUP_SCOPE, 'Parameter applies to the entire group for the duration of the experiment'), + (GROUP_ROUND_SCOPE, 'Parameter applies to the entire group for a given round'), (PARTICIPANT_SCOPE, 'Parameter is for a single participant')) scope = models.CharField(max_length=32, choices=SCOPE_CHOICES, default=ROUND_SCOPE) @@ -862,6 +864,7 @@ def get_data_value(self, parameter=None, parameter_name=None, round_data=None): criteria = self._data_parameter_criteria(parameter=parameter, parameter_name=parameter_name, round_data=round_data) + logger.debug("criteria: %s" % criteria) return self.data_values.get_or_create(**criteria)[0] def _data_parameter_criteria(self, parameter=None, parameter_name=None, round_data=None): diff -r e96c5cca62ad -r ae453f04d057 vcweb/forestry/models.py --- a/vcweb/forestry/models.py Tue Mar 15 16:51:13 2011 -0700 +++ b/vcweb/forestry/models.py Tue Mar 15 22:35:58 2011 -0700 @@ -10,22 +10,41 @@ check all forestry experiments. ''' -# returns a GroupRoundDataValue +# returns a GroupRoundDataValue. FIXME: duplication across get_group_harvest and get_regrowth def get_resource_level(group=None, round_data=None): - return group.get_data_value(parameter_name='resource_level', round_data=round_data) if group else None + return group.get_data_value(parameter=get_resource_level_parameter(), round_data=round_data) if group else None def has_resource_level(group=None): return group.has_data_parameter(parameter=get_resource_level_parameter()) +def get_group_harvest(group, round_data=None): + if round_data is None: + round_data = group.current_round_data + return group.get_data_value(parameter=get_group_harvest_parameter(), round_data=round_data) if group else None + +def get_regrowth(group, round_data=None): + if round_data is None: + round_data = group.current_round_data + return group.get_data_value(parameter=get_regrowth_parameter(), round_data=round_data) if group else None + def get_harvest_decision(participant_group_relationship, round_data=None): if round_data is None: round_data = participant_group_relationship.current_round_data - return ParticipantRoundDataValue.objects.get(participant_group_relationship=participant_group_relationship, - round_data=round_data, parameter__name='harvest_decision') + try: + return ParticipantRoundDataValue.objects.get(participant_group_relationship=participant_group_relationship, + round_data=round_data, parameter__name='harvest_decision') + except ParticipantRoundDataValue.DoesNotExist: + return None def get_harvest_decisions(group=None): return group.get_participant_data_values(parameter_name='harvest_decision') if group else [] +def set_regrowth(group, value): + group.set_data_value(parameter=get_regrowth_parameter(), value=value) + +def set_group_harvest(group, value): + group.set_data_value(parameter=get_group_harvest_parameter(), value=value) + def get_max_harvest_decision(resource_level): if resource_level >= 25: return 5 @@ -48,6 +67,16 @@ scope=Parameter.GROUP_SCOPE, experiment_metadata=get_forestry_experiment_metadata()) +def get_regrowth_parameter(): + return Parameter.objects.get(name='regrowth', + scope=Parameter.GROUP_SCOPE, + experiment_metadata=get_forestry_experiment_metadata()) + +def get_group_harvest_parameter(): + return Parameter.objects.get(name='group_harvest', + scope=Parameter.GROUP_SCOPE, + experiment_metadata=get_forestry_experiment_metadata()) + def get_harvest_decision_parameter(): return Parameter.objects.get( name='harvest_decision', @@ -109,6 +138,7 @@ total_harvest = sum( [ hd.value for hd in get_harvest_decisions(group).all() ]) if current_resource_level.value > 0 and total_harvest > 0: group.log("Harvest: removing %s from current resource level %s" % (total_harvest, current_resource_level.value)) + set_group_harvest(group, total_harvest) current_resource_level.value = max(current_resource_level.value - total_harvest, 0) #group.subtract(resource_level_parameter, total_harvest) ''' transfer resource levels across chat and quiz rounds if they exist ''' @@ -116,6 +146,7 @@ ''' set group round data resource_level for each group + regrowth ''' regrowth = current_resource_level.value / 10 group.log("Regrowth: adding %s to current resource level %s" % (regrowth, current_resource_level.value)) + set_regrowth(group, regrowth) current_resource_level.value = current_resource_level.value + regrowth current_resource_level.save() group.log("Transferring resource level %s to next round" % get_resource_level(group)) diff -r e96c5cca62ad -r ae453f04d057 vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Tue Mar 15 16:51:13 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Tue Mar 15 22:35:58 2011 -0700 @@ -33,7 +33,7 @@ <h3>History</h3> <div id='group-history'> - {% if participant_harvest_decisions %} + {% if all_harvest_round_data %} <table> <thead> <tr><th>Round</th><th>Individual harvest</th><th>Group harvest</th><th>Original number of trees</th><th>Regrowth</th><th>Number of trees left</th></tr> @@ -42,10 +42,15 @@ {% for harvest_round_data in all_harvest_round_data %} <tr> <td>{{harvest_round_data.round_configuration}}</td> - <td>{{harvest_round_data.individual_harvest}}</td> - <td>{{harvest_round_data.group_harvest}}</td> + <td>{% if harvest_round_data.individual_harvest %} + {{harvest_round_data.individual_harvest.value}} + {% else %} + 0 + {%endif%} + </td> + <td>{{harvest_round_data.group_harvest.value}}</td> <td>{{harvest_round_data.original_number_of_trees}}</td> - <td>{{harvest_round_data.regrowth}}</td> + <td>{{harvest_round_data.regrowth.value}}</td> <td>{{harvest_round_data.final_number_of_trees}}</td> </tr> {% endfor %} diff -r e96c5cca62ad -r ae453f04d057 vcweb/forestry/views.py --- a/vcweb/forestry/views.py Tue Mar 15 16:51:13 2011 -0700 +++ b/vcweb/forestry/views.py Tue Mar 15 22:35:58 2011 -0700 @@ -8,7 +8,7 @@ from vcweb.core.forms import QuizForm from vcweb.core.models import is_participant, is_experimenter, Experiment, ParticipantGroupRelationship, ParticipantExperimentRelationship from vcweb.core.decorators import participant_required, experimenter_required -from vcweb.forestry.models import get_resource_level, get_max_harvest_decision, get_forestry_experiment_metadata, set_harvest_decision, get_harvest_decision +from vcweb.forestry.models import get_resource_level, get_max_harvest_decision, get_forestry_experiment_metadata, set_harvest_decision, get_harvest_decision, get_group_harvest, get_regrowth from vcweb.forestry.forms import HarvestDecisionForm import logging @@ -81,10 +81,15 @@ p.group_harvest = get_group_harvest(group, round_data=round_data) p.regrowth = get_regrowth(group, round_data=round_data) resource_level = get_resource_level(group, round_data=round_data) - p.original_number_of_trees = resource_level.value + p.group_harvest - p.regrowth + try: + p.original_number_of_trees = resource_level.value + p.group_harvest.value - p.regrowth.value + except AttributeError: + pass p.final_number_of_trees = resource_level.value all_harvest_round_data.append(p) + logger.debug("all harvest round data: %s" % all_harvest_round_data) + return render_to_response('forestry/wait.html', { 'participant_experiment_relationship': participant_experiment_relationship, 'participant_group_relationship':participant_group_relationship, |
From: <vir...@li...> - 2011-03-15 23:49:52
|
Subject: hg.virtualcommons 280 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/e96c5cca62ad changeset: 280:e96c5cca62ad user: Allen Lee <all...@as...> date: Tue Mar 15 16:51:13 2011 -0700 description: going to add some more group-wide data parameters (regrowth and group harvest) to make participant history easier to compute. diffstat: vcweb/core/models.py | 10 +++++----- vcweb/forestry/models.py | 10 ++++++---- vcweb/forestry/templates/forestry/wait.html | 25 +++++++++++++++++++++++++ vcweb/forestry/views.py | 17 +++++++++++++++++ vcweb/vcweb-tornadio.py | 10 ++++++---- 5 files changed, 59 insertions(+), 13 deletions(-) diffs (145 lines): diff -r 03a97f70b471 -r e96c5cca62ad vcweb/core/models.py --- a/vcweb/core/models.py Tue Mar 15 16:23:21 2011 -0700 +++ b/vcweb/core/models.py Tue Mar 15 16:51:13 2011 -0700 @@ -860,13 +860,13 @@ def get_scalar_data_value(self, parameter=None, parameter_name=None): return self.get_data_value(parameter=parameter, parameter_name=parameter_name).value - def get_data_value(self, parameter=None, parameter_name=None): - criteria = self._data_parameter_criteria(parameter=parameter, parameter_name=parameter_name) + def get_data_value(self, parameter=None, parameter_name=None, round_data=None): + criteria = self._data_parameter_criteria(parameter=parameter, parameter_name=parameter_name, round_data=round_data) return self.data_values.get_or_create(**criteria)[0] - def _data_parameter_criteria(self, parameter=None, parameter_name=None): - return dict([('parameter', parameter) if parameter else ('parameter__name', parameter_name)], - round_data=self.current_round_data) + def _data_parameter_criteria(self, parameter=None, parameter_name=None, round_data=None): + return dict([('parameter', parameter) if parameter else ('parameter__name', parameter_name), + ('round_data', self.current_round_data if round_data is None else round_data)]) def get_group_data_values(self, name=None, *names): diff -r 03a97f70b471 -r e96c5cca62ad vcweb/forestry/models.py --- a/vcweb/forestry/models.py Tue Mar 15 16:23:21 2011 -0700 +++ b/vcweb/forestry/models.py Tue Mar 15 16:51:13 2011 -0700 @@ -11,15 +11,17 @@ ''' # returns a GroupRoundDataValue -def get_resource_level(group=None): - return group.get_data_value(parameter_name='resource_level') if group else None +def get_resource_level(group=None, round_data=None): + return group.get_data_value(parameter_name='resource_level', round_data=round_data) if group else None def has_resource_level(group=None): return group.has_data_parameter(parameter=get_resource_level_parameter()) -def get_harvest_decision(participant_group_relationship): +def get_harvest_decision(participant_group_relationship, round_data=None): + if round_data is None: + round_data = participant_group_relationship.current_round_data return ParticipantRoundDataValue.objects.get(participant_group_relationship=participant_group_relationship, - round_data=participant_group_relationship.current_round_data, parameter__name='harvest_decision') + round_data=round_data, parameter__name='harvest_decision') def get_harvest_decisions(group=None): return group.get_participant_data_values(parameter_name='harvest_decision') if group else [] diff -r 03a97f70b471 -r e96c5cca62ad vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Tue Mar 15 16:23:21 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Tue Mar 15 16:51:13 2011 -0700 @@ -24,11 +24,36 @@ {% block page %} <h3>Waiting for the next round to start</h3> +<p> The facilitator will start the next round when every participant is ready. <span class='ui-state-highlight ui-corner-all'> <small><a class='contactIcon' href="#">send a private message to the facilitator</a></small> </span> +</p> +<h3>History</h3> +<div id='group-history'> + {% if participant_harvest_decisions %} + <table> + <thead> + <tr><th>Round</th><th>Individual harvest</th><th>Group harvest</th><th>Original number of trees</th><th>Regrowth</th><th>Number of trees left</th></tr> + </thead> + <tbody> + {% for harvest_round_data in all_harvest_round_data %} + <tr> + <td>{{harvest_round_data.round_configuration}}</td> + <td>{{harvest_round_data.individual_harvest}}</td> + <td>{{harvest_round_data.group_harvest}}</td> + <td>{{harvest_round_data.original_number_of_trees}}</td> + <td>{{harvest_round_data.regrowth}}</td> + <td>{{harvest_round_data.final_number_of_trees}}</td> + </tr> + {% endfor %} + </tbody> + </table> + + {% endif %} +</div> <h3>Instructions</h3> <div class='info ui-corner-all'> Please wait until the next round begins. diff -r 03a97f70b471 -r e96c5cca62ad vcweb/forestry/views.py --- a/vcweb/forestry/views.py Tue Mar 15 16:23:21 2011 -0700 +++ b/vcweb/forestry/views.py Tue Mar 15 16:51:13 2011 -0700 @@ -61,6 +61,9 @@ logger.warning("No experiment available with id [%s]" % experiment_id) return redirect('core:experimenter_index') +class ParticipantHistory(object): + pass + @participant_required def wait(request, experiment_id=None): try: @@ -69,9 +72,23 @@ participant_experiment_relationship = participant.get_participant_experiment_relationship(experiment) participant_group_relationship = participant.get_participant_group_relationship(experiment) logger.debug("participant group relationship is: %s" % participant_group_relationship) + all_harvest_round_data = [] + group = participant_group_relationship.group + for round_data in experiment.round_data.all(): + p = ParticipantHistory() + p.round_configuration = round_data.round_configuration + p.individual_harvest = get_harvest_decision(participant_group_relationship, round_data=round_data) + p.group_harvest = get_group_harvest(group, round_data=round_data) + p.regrowth = get_regrowth(group, round_data=round_data) + resource_level = get_resource_level(group, round_data=round_data) + p.original_number_of_trees = resource_level.value + p.group_harvest - p.regrowth + p.final_number_of_trees = resource_level.value + all_harvest_round_data.append(p) + return render_to_response('forestry/wait.html', { 'participant_experiment_relationship': participant_experiment_relationship, 'participant_group_relationship':participant_group_relationship, + 'all_harvest_round_data': all_harvest_round_data, }, context_instance=RequestContext(request)) except Experiment.DoesNotExist: diff -r 03a97f70b471 -r e96c5cca62ad vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Tue Mar 15 16:23:21 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Tue Mar 15 16:51:13 2011 -0700 @@ -88,11 +88,13 @@ for the given group ''' def connections(self, group): - pgr_ids = [ pgr.pk for pgr in group.participant_group_relationships.all() ] - for pgr_id in pgr_ids: + experiment = group.experiment + for participant_group_relationship in group.participant_group_relationships.all(): ''' only return currently connected connections in this group ''' - if pgr_id in self.participant_to_connection: - yield (pgr_id, self.participant_to_connection[pgr_id]) + participant = participant_group_relationship.participant + participant_tuple = (participant.pk, experiment.pk) + if participant_tuple in self.participant_to_connection: + yield (participant_group_relationship.pk, self.participant_to_connection[participant_tuple]) pass def all_participants(self, connection, experiment): |
From: <vir...@li...> - 2011-03-15 23:22:00
|
Subject: hg.virtualcommons 279 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/03a97f70b471 changeset: 279:03a97f70b471 user: Allen Lee <all...@as...> date: Tue Mar 15 16:23:21 2011 -0700 description: changing experiment messages to activity log. diffstat: vcweb/core/models.py | 12 +++++++++--- vcweb/core/templates/monitor.html | 24 +++++++++++++----------- vcweb/static/css/style.css | 9 +++++---- vcweb/static/js/common.js | 3 +++ 4 files changed, 30 insertions(+), 18 deletions(-) diffs (145 lines): diff -r 21ce2d290121 -r 03a97f70b471 vcweb/core/models.py --- a/vcweb/core/models.py Tue Mar 15 15:15:29 2011 -0700 +++ b/vcweb/core/models.py Tue Mar 15 16:23:21 2011 -0700 @@ -798,6 +798,10 @@ def is_open(self): return self.size < self.max_size + @property + def current_round_activity_log(self): + return self.activity_log.filter(round_configuration=self.current_round) + def log(self, log_message): self.activity_log.create(round_configuration=self.current_round, log_message=log_message) @@ -811,7 +815,7 @@ round_data = self.current_round_data if round_data.group_data_values.filter(group=self).count() == 0: logger.debug("no group data values for the current round %s, creating new ones." % round_data) - self.log("Initializing data parameters for group %s in round %s" % (self, round_data)) + self.log("Initializing %s data parameters" % round_data) for group_data_parameter in self.data_parameters: self.data_values.create(round_data=round_data, parameter=group_data_parameter) @@ -1169,14 +1173,16 @@ class ActivityLog(models.Model): log_message = models.TextField() date_created = models.DateTimeField(auto_now_add=True) - def __unicode__(self): - return u"%s: %s" % (self.date_created, self.log_message) + return u"%s - %s" % (self.date_created.strftime("%m-%d-%Y %H:%M"), self.log_message) class GroupActivityLog(ActivityLog): group = models.ForeignKey(Group, related_name='activity_log') round_configuration = models.ForeignKey(RoundConfiguration) + def __unicode__(self): + return u"%s %s" % (self.group, super(GroupActivityLog, self).__unicode__()) + class ExperimentActivityLog(ActivityLog): experiment = models.ForeignKey(Experiment, related_name='activity_log') round_configuration = models.ForeignKey(RoundConfiguration) diff -r 21ce2d290121 -r 03a97f70b471 vcweb/core/templates/monitor.html --- a/vcweb/core/templates/monitor.html Tue Mar 15 15:15:29 2011 -0700 +++ b/vcweb/core/templates/monitor.html Tue Mar 15 16:23:21 2011 -0700 @@ -19,6 +19,7 @@ $('.confirm-experiment-action').click(function() { Dajaxice.vcweb.core.experiment_controller(update, {'experiment_id': {{experiment_id}}, 'action':this.name}); $('#statusDiv').hide('fast'); + $('#experimentData').hide('fast'); $('#statusSpinner').show('fast'); return false; }); @@ -34,6 +35,8 @@ }); $('#statusSpinner').hide('fast'); $('#statusDiv').show('fast'); + $('#experimentData').show('fast'); + if (round_data_count > 0) { $('#experimentData').accordion({ active: active_round_number - 1, @@ -57,7 +60,7 @@ break; default: } - experimentMessageDiv.scrollTop = experimentMessageDiv.scrollHeight; + scrollToBottom(experimentMessageDiv); }); $('.tooltip').qtip(qtipOptions); $('a[title]').not('.tooltip').qtip(qtipOptions); @@ -71,9 +74,7 @@ s.send(createGotoEvent()); return false; }); - $('#clear-experiment-messages').click(function() { - $('#experiment-messages').html(''); - }); + scrollToBottom(experimentMessageDiv); }); </script> </script> @@ -86,16 +87,16 @@ <h3>{{experiment}}</h3> <span>You are logged in as {{request.user.experimenter}}.</span> <hr/> -<!-- -<fieldset class='experimenter-sidebar-messages notice ui-corner-all'> - <legend>Experiment messages</legend> - <div id='experiment-messages' style='overflow:auto;'> - </div> -</fieldset> ---> <div id='experimenter-sidebar'> - <h5>Experiment messages <button id='clear-experiment-messages'>clear</button></h5> + <h5>Activity Log</h5> <div id='experiment-messages' class='experimenter-sidebar-messages notice ui-corner-all'> + {% for group in experiment.groups.all %} + {% for activity_log in group.current_round_activity_log %} + <div style='line-height: 0.9em;padding:3px;' class='ui-state-highlight'> + <small>{{activity_log}}</small> + </div> + {% endfor %} + {% endfor %} </div> </div> <fieldset class='small ui-corner-all'> diff -r 21ce2d290121 -r 03a97f70b471 vcweb/static/css/style.css --- a/vcweb/static/css/style.css Tue Mar 15 15:15:29 2011 -0700 +++ b/vcweb/static/css/style.css Tue Mar 15 16:23:21 2011 -0700 @@ -126,7 +126,7 @@ background-color: #efefef; padding: 2px; border: solid 1px #d3d3d3; - width: 500px; + width: 350px; } fieldset.small>legend { font-weight: bold; @@ -231,11 +231,12 @@ } #experimenter-sidebar h5 { padding: 0; - margin: -23px 0px 5px 0; + margin: -20px 0px 8px 0; } .experimenter-sidebar-messages { - height: 13em; - width: 22em; + display:block; + height: 14em; + width: 31em; overflow:auto; float:right; } diff -r 21ce2d290121 -r 03a97f70b471 vcweb/static/js/common.js --- a/vcweb/static/js/common.js Tue Mar 15 15:15:29 2011 -0700 +++ b/vcweb/static/js/common.js Tue Mar 15 16:23:21 2011 -0700 @@ -5,3 +5,6 @@ console.warn = console.warn || function(){}; console.error = console.error || function(){}; console.info = console.info || function(){}; +function scrollToBottom(element) { + element.scrollTop = element.scrollHeight; +} |
From: <vir...@li...> - 2011-03-15 22:14:10
|
Subject: hg.virtualcommons 278 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/21ce2d290121 changeset: 278:21ce2d290121 user: Allen Lee <all...@as...> date: Tue Mar 15 15:15:29 2011 -0700 description: adding log methods for convenience to create new activity_log messages in a group or experiment. adding regrowth rule in round teardown. diffstat: vcweb/core/models.py | 26 +++++++++++++++----------- vcweb/core/tests.py | 11 ++++++----- vcweb/forestry/models.py | 22 +++++++++++++++------- vcweb/forestry/templates/forestry/participate.html | 2 +- vcweb/forestry/tests.py | 6 +++++- vcweb/forestry/views.py | 15 ++++----------- vcweb/vcweb-tornadio.py | 24 ++++++++++-------------- 7 files changed, 56 insertions(+), 50 deletions(-) diffs (322 lines): diff -r 693243912dbb -r 21ce2d290121 vcweb/core/models.py --- a/vcweb/core/models.py Tue Mar 15 11:50:54 2011 -0700 +++ b/vcweb/core/models.py Tue Mar 15 15:15:29 2011 -0700 @@ -227,7 +227,7 @@ @property def is_data_round_in_progress(self): - return self.is_round_in_progress and self.current_round.has_data_parameters + return self.is_round_in_progress and self.current_round.is_playable_round @property def time_remaining(self): @@ -342,6 +342,9 @@ # return dynamic text based on current_round? return self.current_round.instructions + def log(self, log_message): + if log_message: + self.activity_log.create(round_configuration=self.current_round, log_message=log_message) def data_file_name(self, file_ext='csv'): return "%s_%s_%s.%s" % (slugify(self.experiment_metadata.title), self.pk, datetime.now().strftime("%d-%m-%y-%H%M"), file_ext) @@ -403,7 +406,7 @@ self.current_round_elapsed_time = 0 self.current_round_start_time = datetime.now() self.save() - self.activity_log.create(log_message='Starting round.', round_configuration=self.current_round) + self.log('Starting round') # FIXME: would prefer using self.namespace as a default but django's # managed unicode strings don't work as senders sender = self.experiment_metadata.pk if sender is None else sender @@ -416,7 +419,7 @@ self.status = 'ACTIVE' self.current_round_elapsed_time = max(self.current_round_elapsed_time, self.current_round.duration) self.save() - self.activity_log.create(log_message='Ending round with elapsed time %s.' % self.current_round_elapsed_time, round_configuration=self.current_round) + self.log('Ending round with elapsed time %s' % self.current_round_elapsed_time) sender = self.experiment_metadata.pk if sender is None else sender #sender = self.namespace.encode('utf-8') logger.debug("about to send round ended signal with sender %s" % sender) @@ -551,7 +554,7 @@ return self.round_type == RoundConfiguration.REGULAR @property - def has_data_parameters(self): + def is_playable_round(self): return self.round_type in (RoundConfiguration.PRACTICE, RoundConfiguration.REGULAR) def get_parameter(self, name): @@ -795,17 +798,20 @@ def is_open(self): return self.size < self.max_size + def log(self, log_message): + self.activity_log.create(round_configuration=self.current_round, + log_message=log_message) + ''' Initializes data parameters for all groups in this round, as necessary. If this round already has data parameters, is a no-op. ''' def initialize_data_parameters(self): - if self.current_round.has_data_parameters: + if self.current_round.is_playable_round: round_data = self.current_round_data if round_data.group_data_values.filter(group=self).count() == 0: logger.debug("no group data values for the current round %s, creating new ones." % round_data) - self.activity_log.create(round_configuration=self.current_round, - log_message="Initializing data parameters for group %s in round %s" % (self, round_data)) + self.log("Initializing data parameters for group %s in round %s" % (self, round_data)) for group_data_parameter in self.data_parameters: self.data_values.create(round_data=round_data, parameter=group_data_parameter) @@ -817,8 +823,7 @@ def set_data_value(self, parameter_name=None, parameter=None, value=None): data_value = self.get_data_value(parameter_name=parameter_name, parameter=parameter) data_value.value = value - self.activity_log.create(round_configuration=self.current_round, - log_message="setting parameter %s = %s" % (parameter, value)) + self.log("setting parameter %s = %s" % (parameter, value)) data_value.save() def subtract(self, parameter=None, amount=0): @@ -827,8 +832,7 @@ def add(self, parameter=None, amount=0): # could be a float or an int.. update_dict = { parameter.value_field_name : models.F(parameter.value_field_name) + amount } - self.activity_log.create(round_configuration=self.current_round, - log_message="adding %s to this group's %s parameter" % (amount, parameter)) + self.log("adding %s to this group's %s parameter" % (amount, parameter)) ''' vs GroupRoundDataValue.objects.filter(group_round_data=self.current_round_data, parameter=parameter).update(**update_dict) diff -r 693243912dbb -r 21ce2d290121 vcweb/core/tests.py --- a/vcweb/core/tests.py Tue Mar 15 11:50:54 2011 -0700 +++ b/vcweb/core/tests.py Tue Mar 15 15:15:29 2011 -0700 @@ -29,18 +29,18 @@ def advance_to_data_round(self): self.experiment.activate() while self.experiment.has_next_round: - if self.experiment.current_round.has_data_parameters: + if self.experiment.current_round.is_playable_round: return self.experiment self.experiment.advance_to_next_round() def all_data_rounds(self): self.experiment.activate() while self.experiment.has_next_round: - if self.experiment.current_round.has_data_parameters: + if self.experiment.current_round.is_playable_round: yield self.experiment self.experiment.advance_to_next_round() - def create_new_round_configuration(self, round_type='PLAY', template_name=None): + def create_new_round_configuration(self, round_type='REGULAR', template_name=None): return RoundConfiguration.objects.create(experiment_configuration=self.experiment_configuration, sequence_number=(self.experiment_configuration.last_round_sequence_number + 1), round_type=round_type, @@ -228,8 +228,9 @@ e.start_round() for g in e.groups.all(): g.initialize_data_parameters() - self.failUnlessEqual(e.current_round_data.group_data_values.count(), 0) - self.failUnlessEqual(e.current_round_data.participant_data_values.count(), 0) +# FIXME: (changed to practice round for demo purposes) + #self.failUnlessEqual(e.current_round_data.group_data_values.count(), 0) + #self.failUnlessEqual(e.current_round_data.participant_data_values.count(), 0) # first practice round e.advance_to_next_round() e.start_round() diff -r 693243912dbb -r 21ce2d290121 vcweb/forestry/models.py --- a/vcweb/forestry/models.py Tue Mar 15 11:50:54 2011 -0700 +++ b/vcweb/forestry/models.py Tue Mar 15 15:15:29 2011 -0700 @@ -10,6 +10,7 @@ check all forestry experiments. ''' +# returns a GroupRoundDataValue def get_resource_level(group=None): return group.get_data_value(parameter_name='resource_level') if group else None @@ -73,7 +74,7 @@ elif round_configuration.is_debriefing_round: logger.debug("set up debriefing round") - if round_configuration.has_data_parameters: + if round_configuration.is_playable_round: ''' practice or regular round, set up resource levels and participant harvest decision parameters @@ -99,17 +100,24 @@ resource_level_parameter = get_resource_level_parameter() current_round_configuration = experiment.current_round for group in experiment.groups.all(): +# implements regrowth function inline if has_resource_level(group): - if current_round_configuration.has_data_parameters: + current_resource_level = get_resource_level(group) + if current_round_configuration.is_playable_round: total_harvest = sum( [ hd.value for hd in get_harvest_decisions(group).all() ]) - if get_resource_level(group) > 0 and total_harvest > 0: - group.subtract(resource_level_parameter, total_harvest) + if current_resource_level.value > 0 and total_harvest > 0: + group.log("Harvest: removing %s from current resource level %s" % (total_harvest, current_resource_level.value)) + current_resource_level.value = max(current_resource_level.value - total_harvest, 0) + #group.subtract(resource_level_parameter, total_harvest) ''' transfer resource levels across chat and quiz rounds if they exist ''' if experiment.has_next_round: - ''' set group round data resource_level for each group ''' - logger.debug("Transferring resource level %s to next round" % get_resource_level(group)) + ''' set group round data resource_level for each group + regrowth ''' + regrowth = current_resource_level.value / 10 + group.log("Regrowth: adding %s to current resource level %s" % (regrowth, current_resource_level.value)) + current_resource_level.value = current_resource_level.value + regrowth + current_resource_level.save() + group.log("Transferring resource level %s to next round" % get_resource_level(group)) group.transfer_to_next_round(resource_level_parameter) - group.save() #@receiver(signals.round_started, sender='forestry') def round_started_handler(sender, experiment=None, **kwargs): diff -r 693243912dbb -r 21ce2d290121 vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Tue Mar 15 11:50:54 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Tue Mar 15 15:15:29 2011 -0700 @@ -42,7 +42,7 @@ {% block content %} <h3>Forestry round number {{ experiment.current_round.round_number }}</h3> {% for i in number_of_resource_divs %} -<div style="background: url('/static/images/forestry/pine-tree.png') repeat-x; width:600px; height: 79px;"> +<div style="background: url('/static/images/forestry/pine-tree.png') repeat-x; width:{{max_width}}px; height: 79px;"> </div> {% endfor %} diff -r 693243912dbb -r 21ce2d290121 vcweb/forestry/tests.py --- a/vcweb/forestry/tests.py Tue Mar 15 11:50:54 2011 -0700 +++ b/vcweb/forestry/tests.py Tue Mar 15 15:15:29 2011 -0700 @@ -54,7 +54,11 @@ at round end all harvest decisions are tallied and subtracted from the final resource_level ''' - expected_resource_level = lambda group: 100 - ((group.number % 5) * group.size) + def expected_resource_level(group): + after_harvests = 100 - ((group.number % 5) * group.size) + after_regrowth = after_harvests + (after_harvests / 10) + return after_regrowth + for group in e.groups.all(): self.failUnlessEqual(get_resource_level(group).value, expected_resource_level(group)) diff -r 693243912dbb -r 21ce2d290121 vcweb/forestry/views.py --- a/vcweb/forestry/views.py Tue Mar 15 11:50:54 2011 -0700 +++ b/vcweb/forestry/views.py Tue Mar 15 15:15:29 2011 -0700 @@ -76,6 +76,7 @@ context_instance=RequestContext(request)) except Experiment.DoesNotExist: logger.warning("No experiment found with id %s" % experiment_id) + return redirect('forestry:participant_index') # FIXME: refactor this ugliness @participant_required @@ -93,22 +94,13 @@ context_instance=RequestContext(request)) if experiment.is_round_in_progress: - if current_round.has_data_parameters: + if current_round.is_playable_round: return play(request, experiment, participant) elif current_round.is_chat_round: return chat(request, experiment, participant) elif current_round.is_quiz_round: return quiz(request, experiment, participant) - else: - # instructions or quiz round - participant_group_rel = participant.get_participant_group_relationship(experiment) - return render_to_response(experiment.current_round_template, { - 'participant_group_relationship': participant_group_rel, - 'experiment': experiment, - 'next_round_instructions': experiment.next_round_instructions - }, - context_instance=RequestContext(request)) - elif experiment.is_first_round: + else: # round is not currently active, redirect to waiting page. return redirect('forestry:wait', experiment_id=experiment.pk) except Experiment.DoesNotExist: @@ -182,6 +174,7 @@ max_harvest_decision = get_max_harvest_decision(resource_level.value) # FIXME: UI crap logic in view to determine how wide to make the tree div number_of_trees_per_row = 20 + max_width = number_of_trees_per_row * 30 number_of_resource_divs = range(0, resource_level.value / number_of_trees_per_row) resource_width = (resource_level.value % number_of_trees_per_row) * 30 return render_to_response(experiment.current_round_template, diff -r 693243912dbb -r 21ce2d290121 vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Tue Mar 15 11:50:54 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Tue Mar 15 15:15:29 2011 -0700 @@ -15,6 +15,12 @@ from vcweb.core.models import ParticipantExperimentRelationship, ParticipantGroupRelationship, ChatMessage, Experimenter, Experiment +def info_json(message): + return simplejson.dumps({'message_type': 'info', 'message': message}) + +def goto_json(url): + return simplejson.dumps({'message_type': 'goto', 'url': url}) + ''' Manages socket.io connections to tornadio. ''' @@ -102,25 +108,17 @@ else: logger.warning("No experimenter available for connection %s" % connection) - ''' experimenter functions ''' - @staticmethod - def info(message): - return simplejson.dumps({'message_type': 'info', 'message': message}) - def send_refresh(self, connection, experiment, experimenter_id=None): for (participant_group_pk, connection) in self.all_participants(connection, experiment): connection.send(ConnectionManager.refresh_json) def send_goto(self, connection, experiment, url): - goto_json = simplejson.dumps({ - 'message_type': 'goto', - 'url': url - }) + json = goto_json(url) for (participant_group_pk, connection) in self.all_participants(connection, experiment): - connection.send(goto_json) + connection.send(json) def send_to_experimenter(self, experimenter_tuple, json): (experimenter_pk, experiment_pk) = experimenter_tuple @@ -161,7 +159,6 @@ except Experimenter.DoesNotExist as e: logger.warning("Tried to establish connection but there isn't any experimenter with id %s" % experimenter_id) - def on_message(self, message): event = to_event(message) logger.debug("%s received message %s" % (self, message)) @@ -173,14 +170,13 @@ experiment = Experiment.objects.get(pk=experiment_id) connection_manager.send_refresh(self, experiment, experimenter_id) logger.debug("pinging back to experimenter") - self.send(ConnectionManager.info("Refreshed all participants")) + self.send(info_json("Refreshed all participants")) elif event.type == 'goto': experiment_id = event.experiment_id experiment = Experiment.objects.get(pk=experiment_id) url = event.url connection_manager.send_goto(self, experiment, url) - self.send(ConnectionManager.info("Sent goto:%s to all participants" % url)) - + self.send(info_json("Sent goto:%s to all participants" % url)) def on_close(self): connection_manager.remove_experimenter(self) |
From: <vir...@li...> - 2011-03-15 18:49:39
|
Subject: hg.virtualcommons 277 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/693243912dbb changeset: 277:693243912dbb user: Allen Lee <all...@as...> date: Tue Mar 15 11:50:54 2011 -0700 description: switching tornadio server to use participant_experiment_relationships instead of group relationships which may not be fully formed yet (depending on the experiment as well). adding new tree image and showing all trees in the resource. diffstat: vcweb/core/templates/includes/participant.events.html | 8 +- vcweb/core/templates/monitor.html | 2 +- vcweb/forestry/templates/forestry/chat.html | 7 +- vcweb/forestry/templates/forestry/instructions.html | 2 +- vcweb/forestry/templates/forestry/participate.html | 12 ++- vcweb/forestry/views.py | 26 ++++- vcweb/static/images/forestry/pine-tree.png | vcweb/vcweb-tornadio.py | 89 ++++++++++++--------- 8 files changed, 90 insertions(+), 56 deletions(-) diffs (335 lines): diff -r 17b3073eb3b0 -r 693243912dbb vcweb/core/templates/includes/participant.events.html --- a/vcweb/core/templates/includes/participant.events.html Mon Mar 14 10:57:22 2011 -0700 +++ b/vcweb/core/templates/includes/participant.events.html Tue Mar 15 11:50:54 2011 -0700 @@ -1,24 +1,24 @@ <script type="text/javascript"> - function createConnectionEvent() { return createMessageEvent("Initial connection", "connect"); } - function createReconnectionEvent() { return createMessageEvent("Reconnecting from disconnect", "reconnect"); } - function createMessageEvent(payload, event_type) { if (! event_type) { event_type = "chat"; } return { "type": event_type, +{% if participant_group_relationship %} "participant_group_relationship_id": {{participant_group_relationship.pk}}, +{% else %} + "participant_experiment_relationship_id": {{participant_experiment_relationship.pk}}, +{% endif %} "message": payload }; } - function createChatEvent(message) { return createMessageEvent(message); } diff -r 17b3073eb3b0 -r 693243912dbb vcweb/core/templates/monitor.html --- a/vcweb/core/templates/monitor.html Mon Mar 14 10:57:22 2011 -0700 +++ b/vcweb/core/templates/monitor.html Tue Mar 15 11:50:54 2011 -0700 @@ -104,7 +104,7 @@ <li><span id='refreshAllParticipants' title='Sends a page refresh to all connected participants.' class='clickable' > <span class='vcweb-icon ui-icon icon-left' style='background:url(/static/images/famfamfam/arrow_refresh.png);' alt=''></span>refresh all participants</a></li> <li><span id='gotoUrl' title='Moves all connected participants from waiting page to active page.' class='clickable' > - <span class='vcweb-icon ui-icon icon-left' style='background:url(/static/images/famfamfam/arrow_refresh.png);' alt=''></span>transition all participants to next round</a></li> + <span class='vcweb-icon ui-icon icon-left' style='background:url(/static/images/famfamfam/arrow_right.png);' alt=''></span>transition all participants to next round</a></li> <li> <a href='download/csv'><span class='vcweb-icon ui-icon icon-left' style='margin: 8px 0.15em 0px 0px; background:url(/static/images/download-icon.png);' alt=''></span>download data as <img src='/static/images/famfamfam/page_white_text.png' style='margin: 5px 0 0 0;' alt=''> csv</a> | <a href='download/xls'><img src='/static/images/famfamfam/page_white_excel.png' style='margin: 5px 0 0 0;' alt=''/> xls</a></li> diff -r 17b3073eb3b0 -r 693243912dbb vcweb/forestry/templates/forestry/chat.html --- a/vcweb/forestry/templates/forestry/chat.html Mon Mar 14 10:57:22 2011 -0700 +++ b/vcweb/forestry/templates/forestry/chat.html Tue Mar 15 11:50:54 2011 -0700 @@ -6,7 +6,7 @@ <script type="text/javascript"> $(function() { var chatDiv = document.getElementById('chat-div'); - var s = connect(window.location.hostname, 8888, 'participant/{{participant_group_relationship.pk}}'); + var s = connect(window.location.hostname, 8888, 'participant/{{participant_experiment_relationship.pk}}'); s.on('message', function(json_string) { var json = jQuery.parseJSON(json_string); switch (json.message_type) { @@ -18,6 +18,9 @@ case 'refresh': location.reload(true); break; + case 'goto': + location.href = json.url; + break; } }); //send the message when submit is clicked @@ -43,7 +46,7 @@ <div class='info ui-corner-all'> <span class='icon-left ui-icon ui-icon-info'></span> <b> - Welcome back {{participant.get_full_name}}. + Hello, {{participant.get_full_name}}. You are participant {{ participant_group_relationship.participant_number }} in {{participant_group_relationship.group}}. </b> </div> diff -r 17b3073eb3b0 -r 693243912dbb vcweb/forestry/templates/forestry/instructions.html --- a/vcweb/forestry/templates/forestry/instructions.html Mon Mar 14 10:57:22 2011 -0700 +++ b/vcweb/forestry/templates/forestry/instructions.html Tue Mar 15 11:50:54 2011 -0700 @@ -5,7 +5,7 @@ {% include "includes/socket.io.html" %} <script type="text/javascript"> $(function() { - var s = connect(window.location.hostname, 8888, 'participant/{{participant_group_relationship.pk}}'); + var s = connect(window.location.hostname, 8888, 'participant/{{participant_experiment_relationship.pk}}'); s.on('message', function(json_string) { var json = jQuery.parseJSON(json_string); switch (json.message_type) { diff -r 17b3073eb3b0 -r 693243912dbb vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Mon Mar 14 10:57:22 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Tue Mar 15 11:50:54 2011 -0700 @@ -41,13 +41,19 @@ {% endblock %} {% block content %} <h3>Forestry round number {{ experiment.current_round.round_number }}</h3> -<div style="background-image: url('/static/images/forestry/plain-tree.gif'); background-repeat: repeat-x; width:{{resource_width}}px; height: 35px;"> +{% for i in number_of_resource_divs %} +<div style="background: url('/static/images/forestry/pine-tree.png') repeat-x; width:600px; height: 79px;"> </div> +{% endfor %} +{% if resource_width > 0 %} +<div style="background: url('/static/images/forestry/pine-tree.png') repeat-x; width:{{resource_width}}px; height: 79px;"> + +</div> +{% endif %} <div class='ui-state-highlight'> <span class='icon-left ui-icon ui-icon-info'></span> - The resource size is <b>{{ resource_level.value }}</b>. - <span class='small-font'>(each tree image represents 10 trees)</span> + There are <b>{{ resource_level.value }}</b> trees left. </div> <div class='ui-state-error'> <span class='icon-left ui-icon ui-icon-info'></span> diff -r 17b3073eb3b0 -r 693243912dbb vcweb/forestry/views.py --- a/vcweb/forestry/views.py Mon Mar 14 10:57:22 2011 -0700 +++ b/vcweb/forestry/views.py Tue Mar 15 11:50:54 2011 -0700 @@ -6,7 +6,7 @@ from django.template.context import RequestContext from vcweb import settings from vcweb.core.forms import QuizForm -from vcweb.core.models import is_participant, is_experimenter, Experiment, ParticipantGroupRelationship +from vcweb.core.models import is_participant, is_experimenter, Experiment, ParticipantGroupRelationship, ParticipantExperimentRelationship from vcweb.core.decorators import participant_required, experimenter_required from vcweb.forestry.models import get_resource_level, get_max_harvest_decision, get_forestry_experiment_metadata, set_harvest_decision, get_harvest_decision from vcweb.forestry.forms import HarvestDecisionForm @@ -65,10 +65,12 @@ def wait(request, experiment_id=None): try: experiment = Experiment.objects.get(pk=experiment_id) - participant_group_relationship = request.user.participant.get_participant_group_relationship(experiment) + participant = request.user.participant + participant_experiment_relationship = participant.get_participant_experiment_relationship(experiment) + participant_group_relationship = participant.get_participant_group_relationship(experiment) logger.debug("participant group relationship is: %s" % participant_group_relationship) return render_to_response('forestry/wait.html', { - 'experiment': experiment, + 'participant_experiment_relationship': participant_experiment_relationship, 'participant_group_relationship':participant_group_relationship, }, context_instance=RequestContext(request)) @@ -81,8 +83,16 @@ participant = request.user.participant try: experiment = Experiment.objects.get(pk=experiment_id) + current_round = experiment.current_round + participant_experiment_relationship = participant.get_participant_experiment_relationship(experiment) + if current_round.is_instructions_round: + return render_to_response(experiment.current_round_template, { + 'participant_experiment_relationship': participant_experiment_relationship, + 'next_round_instructions': experiment.next_round_instructions + }, + context_instance=RequestContext(request)) + if experiment.is_round_in_progress: - current_round = experiment.current_round if current_round.has_data_parameters: return play(request, experiment, participant) elif current_round.is_chat_round: @@ -98,7 +108,7 @@ 'next_round_instructions': experiment.next_round_instructions }, context_instance=RequestContext(request)) - else: + elif experiment.is_first_round: # round is not currently active, redirect to waiting page. return redirect('forestry:wait', experiment_id=experiment.pk) except Experiment.DoesNotExist: @@ -170,8 +180,10 @@ group = participant_group_relationship.group resource_level = get_resource_level(group) max_harvest_decision = get_max_harvest_decision(resource_level.value) -# FIXME: UI crap logic in view to determine how wide to make the screen. - resource_width = (resource_level.value / 10) * 30 +# FIXME: UI crap logic in view to determine how wide to make the tree div + number_of_trees_per_row = 20 + number_of_resource_divs = range(0, resource_level.value / number_of_trees_per_row) + resource_width = (resource_level.value % number_of_trees_per_row) * 30 return render_to_response(experiment.current_round_template, locals(), context_instance=RequestContext(request)) diff -r 17b3073eb3b0 -r 693243912dbb vcweb/static/images/forestry/pine-tree.png Binary file vcweb/static/images/forestry/pine-tree.png has changed diff -r 17b3073eb3b0 -r 693243912dbb vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Mon Mar 14 10:57:22 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Tue Mar 15 11:50:54 2011 -0700 @@ -13,7 +13,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'vcweb.settings' -from vcweb.core.models import ParticipantGroupRelationship, ChatMessage, Experimenter, Experiment +from vcweb.core.models import ParticipantExperimentRelationship, ParticipantGroupRelationship, ChatMessage, Experimenter, Experiment ''' Manages socket.io connections to tornadio. @@ -24,11 +24,12 @@ # first started but groups haven't been allocated, socket.io won't work. Using # the ParticipantExperiment tuple would allow us to broadcast messages when we # want to from the experimenter.. + # (participant.pk, experiment.pk) -> connection connection_to_participant = {} participant_to_connection = {} connection_to_experimenter = {} -# (experimenter.pk, experiment.id) -> connection +# (experimenter.pk, experiment.pk) -> connection experimenter_to_connection = {} refresh_json = simplejson.dumps({ 'message_type': 'refresh' }) @@ -50,24 +51,27 @@ del self.connection_to_experimenter[connection] del self.experimenter_to_connection[(experimenter_pk, experiment_id)] - def get_participant(self, connection): - logger.debug("trying to retrieve participant group relationship for connection id %s" % connection) - logger.debug("maps are %s and %s" % (self.connection_to_participant, - self.participant_to_connection)) - return ParticipantGroupRelationship.objects.get(pk=self.connection_to_participant[connection]) + def get_participant_group_relationship(self, connection): + if connection in self.connection_to_participant: + (participant_pk, experiment_pk) = self.connection_to_participant[connection] + return ParticipantGroupRelationship.objects.get(participant__pk=participant_pk, group__experiment__pk = experiment_pk) + logger.debug("Didn't find connection %s in connection map %s." % (connection, self.connection_to_participant)) + return None - def add(self, auth_token, connection, participant_group_relationship): - if participant_group_relationship.pk in self.participant_to_connection: + def add_participant(self, auth_token, connection, participant_experiment_relationship): + participant_tuple = (participant_experiment_relationship.participant.pk, + participant_experiment_relationship.experiment.pk) + if participant_tuple in self.participant_to_connection: logger.debug("participant already has a connection, removing previous mappings.") - self.remove(self.participant_to_connection[participant_group_relationship.pk]) + self.remove(self.participant_to_connection[participant_tuple]) - self.connection_to_participant[connection] = participant_group_relationship.pk - self.participant_to_connection[participant_group_relationship.pk] = connection + self.connection_to_participant[connection] = participant_tuple + self.participant_to_connection[participant_tuple] = connection def remove(self, connection): try: - participant_group_pk = self.connection_to_participant[connection] - del self.participant_to_connection[participant_group_pk] + participant_tuple = self.connection_to_participant[connection] + del self.participant_to_connection[participant_tuple] del self.connection_to_participant[connection] except KeyError, k: logger.warning( "caught key error %s while trying to remove connection %s" % (connection, k) ) @@ -102,7 +106,8 @@ ''' experimenter functions ''' - def info(self, message): + @staticmethod + def info(message): return simplejson.dumps({'message_type': 'info', 'message': message}) def send_refresh(self, connection, experiment, experimenter_id=None): @@ -182,31 +187,39 @@ class ParticipantHandler(SocketConnection): def on_open(self, *args, **kwargs): + # FIXME: verify user auth tokens + extra = kwargs['extra'] + logger.debug('%s received extra: %s' % (self, extra)) + #(auth_token, dot, participant_group_relationship_id) = extra.partition('.') + #logger.debug("auth token: %s, id %s" % (auth_token, participant_group_relationship_id)) + relationship_id = extra try: - # FIXME: verify user auth tokens - extra = kwargs['extra'] - logger.debug('%s received extra: %s' % (self, extra)) - #(auth_token, dot, participant_group_relationship_id) = extra.partition('.') - #logger.debug("auth token: %s, id %s" % (auth_token, participant_group_relationship_id)) - participant_group_relationship_id = extra - participant_group_rel = ParticipantGroupRelationship.objects.get(pk=participant_group_relationship_id) - connection_manager.add(extra, self, participant_group_rel) - group = participant_group_rel.group - message = "Participant %s connected to group %s." % (participant_group_rel.participant_number, group) - connection_manager.send_to_group(group, - simplejson.dumps({ - 'message' : message, - 'message_type': 'info', - })) + participant_experiment_relationship = ParticipantExperimentRelationship.objects.get(pk=relationship_id) + connection_manager.add_participant(extra, self, participant_experiment_relationship) + participant_group_rel = connection_manager.get_participant_group_relationship(self) + if participant_group_rel is not None: + group = participant_group_rel.group + message = "Participant %s connected to group %s." % (participant_group_rel.participant_number, group) + connection_manager.send_to_group(group, + simplejson.dumps({ + 'message' : message, + 'message_type': 'info', + })) + else: + experimenter_tuple = (participant_experiment_relationship.experiment.experimenter.pk, + participant_experiment_relationship.experiment.pk) + connection_manager.send_to_experimenter(experimenter_tuple, + simplejson.dumps({ + 'message': "Participant %s connected to experiment." % participant_experiment_relationship, + 'message_type': 'info', + })) except KeyError, e: logger.debug("no participant group relationship id %s" % e) pass - except ParticipantGroupRelationship.DoesNotExist, e: + except ParticipantExperimentRelationship.DoesNotExist, e: logger.debug("no participant group relationship with id %s (%s)" % - (participant_group_relationship_id, e)) + (participant_experiment_relationship_id, e)) pass - logger.debug("args are: %s" % str(args)) - logger.debug("kwargs are: %s" % str(kwargs)) def on_message(self, message, *args, **kwargs): logger.debug("received message %s from handler %s" % (message, self)) @@ -214,13 +227,13 @@ if 'connect' in event.type: return # FIXME: add authentication - participant_group_rel = connection_manager.get_participant(self) - current_round_data = participant_group_rel.group.experiment.current_round_data - chat_message = ChatMessage.objects.create(participant_group_relationship=participant_group_rel, + participant_group_relationship = connection_manager.get_participant_group_relationship(self) + current_round_data = participant_group_relationship.group.experiment.current_round_data + chat_message = ChatMessage.objects.create(participant_group_relationship=participant_group_relationship, message=event.message, round_data=current_round_data ) - for participant_group_pk, connection in connection_manager.connections(participant_group_rel.group): + for participant_group_pk, connection in connection_manager.connections(participant_group_relationship.group): connection.send(simplejson.dumps({ "message" : chat_message.as_html, "message_type": 'chat', |
From: <vir...@li...> - 2011-03-14 17:56:10
|
Subject: hg.virtualcommons 276 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/17b3073eb3b0 changeset: 276:17b3073eb3b0 user: Allen Lee <all...@as...> date: Mon Mar 14 10:57:22 2011 -0700 description: adding first cut at goto url support diffstat: vcweb/core/templates/base.html | 6 +- vcweb/core/templates/includes/experimenter.events.html | 11 +++++ vcweb/core/templates/monitor.html | 8 +++- vcweb/forestry/fixtures/initial_data.json | 20 +++++++++- vcweb/forestry/templates/forestry/participate.html | 12 ++++++ vcweb/forestry/templates/forestry/wait.html | 6 --- vcweb/forestry/views.py | 1 + vcweb/vcweb-tornadio.py | 41 ++++++++++++++++---- 8 files changed, 86 insertions(+), 19 deletions(-) diffs (242 lines): diff -r adc83ffcaf7a -r 17b3073eb3b0 vcweb/core/templates/base.html --- a/vcweb/core/templates/base.html Fri Mar 11 17:56:44 2011 -0700 +++ b/vcweb/core/templates/base.html Mon Mar 14 10:57:22 2011 -0700 @@ -26,10 +26,10 @@ {% endblock %} </head> <body> - <div style='float:left; padding-top: 5px;'> - <img src='/static/images/vcweb-logo.png' alt='vcweb logo'/> - </div> <div id='logo'> + <div style='clear: none; position:relative;float:right; left:-930px; padding: 5px;'> + <img src='/static/images/vcweb-logo.png' alt='vcweb logo'/> + </div> <h1> {% block logo %} virtual commons web environment diff -r adc83ffcaf7a -r 17b3073eb3b0 vcweb/core/templates/includes/experimenter.events.html --- a/vcweb/core/templates/includes/experimenter.events.html Fri Mar 11 17:56:44 2011 -0700 +++ b/vcweb/core/templates/includes/experimenter.events.html Mon Mar 14 10:57:22 2011 -0700 @@ -3,6 +3,17 @@ function createRefreshEvent() { return createMessageEvent("Refresh all clients", "refresh"); } +function createGotoEvent(url) { + if (! url) { + url = "participate"; + } + return { + 'type': 'goto', + 'experimenter_id': {{ request.user.experimenter.pk }}, + 'experiment_id': {{ experiment.pk }}, + 'url': url + }; +} function createConnectionEvent() { return createMessageEvent("Initial connection", "connect"); } diff -r adc83ffcaf7a -r 17b3073eb3b0 vcweb/core/templates/monitor.html --- a/vcweb/core/templates/monitor.html Fri Mar 11 17:56:44 2011 -0700 +++ b/vcweb/core/templates/monitor.html Mon Mar 14 10:57:22 2011 -0700 @@ -66,12 +66,16 @@ s.send(createRefreshEvent()); return false; }); + $('#gotoUrl').click(function(evt) { + console.log("sending goto event"); + s.send(createGotoEvent()); + return false; + }); $('#clear-experiment-messages').click(function() { $('#experiment-messages').html(''); }); }); </script> - </script> {% endblock %} {% block title %} @@ -99,6 +103,8 @@ <ul class='actions'> <li><span id='refreshAllParticipants' title='Sends a page refresh to all connected participants.' class='clickable' > <span class='vcweb-icon ui-icon icon-left' style='background:url(/static/images/famfamfam/arrow_refresh.png);' alt=''></span>refresh all participants</a></li> + <li><span id='gotoUrl' title='Moves all connected participants from waiting page to active page.' class='clickable' > + <span class='vcweb-icon ui-icon icon-left' style='background:url(/static/images/famfamfam/arrow_refresh.png);' alt=''></span>transition all participants to next round</a></li> <li> <a href='download/csv'><span class='vcweb-icon ui-icon icon-left' style='margin: 8px 0.15em 0px 0px; background:url(/static/images/download-icon.png);' alt=''></span>download data as <img src='/static/images/famfamfam/page_white_text.png' style='margin: 5px 0 0 0;' alt=''> csv</a> | <a href='download/xls'><img src='/static/images/famfamfam/page_white_excel.png' style='margin: 5px 0 0 0;' alt=''/> xls</a></li> diff -r adc83ffcaf7a -r 17b3073eb3b0 vcweb/forestry/fixtures/initial_data.json --- a/vcweb/forestry/fixtures/initial_data.json Fri Mar 11 17:56:44 2011 -0700 +++ b/vcweb/forestry/fixtures/initial_data.json Mon Mar 14 10:57:22 2011 -0700 @@ -61,7 +61,7 @@ "experiment_configuration": 1, "instructions": "The following quiz is designed to ensure you understand the dynamics of this experiment.", "last_modified": "2010-09-07 15:13:03", - "round_type": "QUIZ", + "round_type": "PRACTICE", "sequence_number": 2 }, "model": "core.roundconfiguration", @@ -224,6 +224,24 @@ }, { "fields": { + "round_configuration": 2, + "parameter": [ "reset.resource_level" ], + "boolean_value": "True" + }, + "model": "core.roundparametervalue", + "pk": 8 + }, + { + "fields": { + "round_configuration": 2, + "parameter": [ "initial.resource_level" ], + "int_value": 100 + }, + "model": "core.roundparametervalue", + "pk": 9 + }, + { + "fields": { "round_configuration": 3, "parameter": [ "reset.resource_level" ], "boolean_value": "True" diff -r adc83ffcaf7a -r 17b3073eb3b0 vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Fri Mar 11 17:56:44 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Mon Mar 14 10:57:22 2011 -0700 @@ -1,6 +1,8 @@ {% extends "base-participant.html" %} {% block head %} {{ block.super }} +{% include "includes/participant.events.html" %} +{% include "includes/socket.io.html" %} <script type="text/javascript"> $(function() { $("#forestryForm").validate({ @@ -21,6 +23,16 @@ this.select(); }); $('#harvestDecisionId').focus(); + var s = connect(window.location.hostname, 8888, 'participant/{{participant_group_relationship.pk}}'); + s.on('message', function(json_string) { + var json = jQuery.parseJSON(json_string); + switch (json.message_type) { + case 'goto': + console.log("going to " + json.url); + window.location.href = json.url; + break; + } + }); }); </script> {% endblock %} diff -r adc83ffcaf7a -r 17b3073eb3b0 vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Fri Mar 11 17:56:44 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Mon Mar 14 10:57:22 2011 -0700 @@ -24,16 +24,10 @@ {% block page %} <h3>Waiting for the next round to start</h3> -{% if experiment.is_timed_round > 0%} -<div id='timeLeft' class='info infoIcon ui-corner-all'> - Time remaining: <span id='timeRemaining'>{{ experiment.time_remaining }}</span> -</div> -{% else %} The facilitator will start the next round when every participant is ready. <span class='ui-state-highlight ui-corner-all'> <small><a class='contactIcon' href="#">send a private message to the facilitator</a></small> </span> -{% endif %} <h3>Instructions</h3> <div class='info ui-corner-all'> diff -r adc83ffcaf7a -r 17b3073eb3b0 vcweb/forestry/views.py --- a/vcweb/forestry/views.py Fri Mar 11 17:56:44 2011 -0700 +++ b/vcweb/forestry/views.py Mon Mar 14 10:57:22 2011 -0700 @@ -66,6 +66,7 @@ try: experiment = Experiment.objects.get(pk=experiment_id) participant_group_relationship = request.user.participant.get_participant_group_relationship(experiment) + logger.debug("participant group relationship is: %s" % participant_group_relationship) return render_to_response('forestry/wait.html', { 'experiment': experiment, 'participant_group_relationship':participant_group_relationship, diff -r adc83ffcaf7a -r 17b3073eb3b0 vcweb/vcweb-tornadio.py --- a/vcweb/vcweb-tornadio.py Fri Mar 11 17:56:44 2011 -0700 +++ b/vcweb/vcweb-tornadio.py Mon Mar 14 10:57:22 2011 -0700 @@ -19,6 +19,11 @@ Manages socket.io connections to tornadio. ''' class ConnectionManager: + # FIXME: use (participant, experiment) tuples instead of + # ParticipantGroupRelationship? The problem is that when the experiment is + # first started but groups haven't been allocated, socket.io won't work. Using + # the ParticipantExperiment tuple would allow us to broadcast messages when we + # want to from the experimenter.. connection_to_participant = {} participant_to_connection = {} @@ -80,18 +85,13 @@ yield (pgr_id, self.participant_to_connection[pgr_id]) pass - ''' - experimenter functions - ''' - def send_refresh(self, connection, experiment, experimenter_id=None): + def all_participants(self, connection, experiment): if connection in self.connection_to_experimenter: (experimenter_pk, experiment_pk) = self.connection_to_experimenter[connection] if experiment.pk == experiment_pk: for group in experiment.groups.all(): for participant_group_pk, connection in self.connections(group): - logger.debug("sending refresh message %s to participant %s" % - (ConnectionManager.refresh_json, participant_group_pk)) - connection.send(ConnectionManager.refresh_json) + yield (participant_group_pk, connection) else: logger.warning("Experimenter %s tried to refresh experiment %s" % (experimenter_pk, experiment)) @@ -99,6 +99,24 @@ logger.warning("No experimenter available for connection %s" % connection) + ''' + experimenter functions + ''' + def info(self, message): + return simplejson.dumps({'message_type': 'info', 'message': message}) + + def send_refresh(self, connection, experiment, experimenter_id=None): + for (participant_group_pk, connection) in self.all_participants(connection, experiment): + connection.send(ConnectionManager.refresh_json) + + def send_goto(self, connection, experiment, url): + goto_json = simplejson.dumps({ + 'message_type': 'goto', + 'url': url + }) + for (participant_group_pk, connection) in self.all_participants(connection, experiment): + connection.send(goto_json) + def send_to_experimenter(self, experimenter_tuple, json): (experimenter_pk, experiment_pk) = experimenter_tuple logger.debug("sending %s to experimenter %s" % (json, experimenter_tuple)) @@ -150,7 +168,14 @@ experiment = Experiment.objects.get(pk=experiment_id) connection_manager.send_refresh(self, experiment, experimenter_id) logger.debug("pinging back to experimenter") - self.send(simplejson.dumps({'message':"Refreshed all participants", 'message_type':"info"})) + self.send(ConnectionManager.info("Refreshed all participants")) + elif event.type == 'goto': + experiment_id = event.experiment_id + experiment = Experiment.objects.get(pk=experiment_id) + url = event.url + connection_manager.send_goto(self, experiment, url) + self.send(ConnectionManager.info("Sent goto:%s to all participants" % url)) + def on_close(self): connection_manager.remove_experimenter(self) |
From: <vir...@li...> - 2011-03-12 00:55:50
|
Subject: hg.virtualcommons 275 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/adc83ffcaf7a changeset: 275:adc83ffcaf7a user: Allen Lee <all...@as...> date: Fri Mar 11 17:56:44 2011 -0700 description: changing requests to wait to always wait. diffstat: vcweb/core/models.py | 57 ++++++++++--------- vcweb/core/templates/participant-index.html | 4 +- vcweb/forestry/models.py | 6 +- vcweb/forestry/templates/forestry/participate.html | 11 ++- vcweb/forestry/templates/forestry/wait.html | 29 ++++----- vcweb/forestry/views.py | 27 +++++---- vcweb/static/css/style.css | 4 +- 7 files changed, 73 insertions(+), 65 deletions(-) diffs (294 lines): diff -r dec7aff7174b -r adc83ffcaf7a vcweb/core/models.py --- a/vcweb/core/models.py Fri Mar 11 14:11:22 2011 -0700 +++ b/vcweb/core/models.py Fri Mar 11 17:56:44 2011 -0700 @@ -775,8 +775,28 @@ def all_participants_str(self): return ', '.join([participant.email for participant in self.participants.all()]) + @property + def data_parameters(self): + return Parameter.objects.filter(experiment_metadata=self.experiment.experiment_metadata, scope=Parameter.GROUP_SCOPE) + + @property + def current_round_data(self): + return self.experiment.current_round_data + + @property + def current_round_data_values(self): + return self.current_round_data.group_data_values + + @property + def is_full(self): + return self.size >= self.max_size + + @property + def is_open(self): + return self.size < self.max_size + ''' - Initializes data parameters for all groups in this round, as necessary. + Initializes data parameters for all groups in this round, as necessary. If this round already has data parameters, is a no-op. ''' def initialize_data_parameters(self): @@ -881,26 +901,6 @@ def get_participant_data_values(self, parameter_name=None): return ParticipantRoundDataValue.objects.filter(round_data=self.current_round_data, participant_group_relationship__group=self, parameter__name=parameter_name) - @property - def data_parameters(self): - return Parameter.objects.filter(experiment_metadata=self.experiment.experiment_metadata, scope=Parameter.GROUP_SCOPE) - - - @property - def current_round_data(self): - return self.experiment.current_round_data - - @property - def current_round_data_values(self): - return self.current_round_data.group_data_values - - @property - def is_full(self): - return self.size >= self.max_size - - @property - def is_open(self): - return self.size < self.max_size def create_next_group(self): return Group.objects.create(number=self.number + 1, max_size=self.max_size, experiment=self.experiment) @@ -982,10 +982,9 @@ def completed_experiments(self): return self.experiments_with_status(Experiment.COMPLETED) - def set_data_value(self, experiment=None, parameter=None, value=None): if experiment and parameter and value is not None: - # FIXME: simplify-able? + # FIXME: shift to ParticipantGroupRelationship as data arbiter current_round_data = experiment.current_round_data participant_group_relationship = ParticipantGroupRelationship.objects.get(group__experiment=experiment, participant=self) participant_data_value, created = current_round_data.participant_data_values.get_or_create(parameter=parameter, @@ -1002,7 +1001,7 @@ return ParticipantGroupRelationship.objects.get_participant_number(experiment, self) def get_participant_group_relationship(self, experiment): - return ParticipantGroupRelationship.objects.get_participant_group(experiment, self) + return ParticipantGroupRelationship.objects.get_participant_group(self, experiment) def get_group(self, experiment): return ParticipantGroupRelationship.objects.get_group(experiment, self) @@ -1046,10 +1045,10 @@ class ParticipantGroupRelationshipManager(models.Manager): def get_group(self, experiment, participant): - participant_group = self.get_participant_group(experiment, participant) + participant_group = self.get_participant_group(participant, experiment) return participant_group.group if participant_group else None - def get_participant_group(self, experiment, participant): + def get_participant_group(self, participant, experiment): try: return self.get(group__experiment=experiment, participant=participant) except ParticipantGroupRelationship.DoesNotExist: @@ -1057,7 +1056,7 @@ return None def get_participant_number(self, experiment, participant): - participant_group = self.get_participant_group(experiment, participant) + participant_group = self.get_participant_group(participant, experiment) return participant_group.participant_number if participant_group else None """ @@ -1074,6 +1073,10 @@ objects = ParticipantGroupRelationshipManager() + @property + def current_round_data(self): + return self.group.current_round_data + def __unicode__(self): return u"{0}: #{1} (in {2})".format(self.participant, self.participant_number, self.group) diff -r dec7aff7174b -r adc83ffcaf7a vcweb/core/templates/participant-index.html --- a/vcweb/core/templates/participant-index.html Fri Mar 11 14:11:22 2011 -0700 +++ b/vcweb/core/templates/participant-index.html Fri Mar 11 17:56:44 2011 -0700 @@ -17,12 +17,12 @@ {% for experiment in experiments %} <div class='ui-state-highlight ui-corner-all'> <a href='{{ experiment.participant_url }}'> - <span class='ui-icon {{experiment_status|lower}}'></span> + <span class='icon-left ui-icon {{experiment_status|lower}}'></span> {{ experiment.status_line }}, created {{experiment.date_created|date:"SHORT_DATETIME_FORMAT"}} </a> </div> {% empty %} - <div class='ui-state-error ui-corner-all'><span class='ui-icon ui-icon-alert'></span>No <b>{{ experiment_status|lower }}</b> experiments</div> + <div class='ui-state-error ui-corner-all'><span class='icon-left ui-icon ui-icon-alert'></span>No <b>{{ experiment_status|lower }}</b> experiments</div> {% endfor %} {% endfor %} </div> diff -r dec7aff7174b -r adc83ffcaf7a vcweb/forestry/models.py --- a/vcweb/forestry/models.py Fri Mar 11 14:11:22 2011 -0700 +++ b/vcweb/forestry/models.py Fri Mar 11 17:56:44 2011 -0700 @@ -1,4 +1,4 @@ -from vcweb.core.models import ExperimentMetadata, Parameter, ParticipantGroupRelationship +from vcweb.core.models import ExperimentMetadata, Parameter, ParticipantGroupRelationship, ParticipantRoundDataValue from vcweb.core import signals from celery.decorators import task import logging @@ -16,6 +16,10 @@ def has_resource_level(group=None): return group.has_data_parameter(parameter=get_resource_level_parameter()) +def get_harvest_decision(participant_group_relationship): + return ParticipantRoundDataValue.objects.get(participant_group_relationship=participant_group_relationship, + round_data=participant_group_relationship.current_round_data, parameter__name='harvest_decision') + def get_harvest_decisions(group=None): return group.get_participant_data_values(parameter_name='harvest_decision') if group else [] diff -r dec7aff7174b -r adc83ffcaf7a vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Fri Mar 11 14:11:22 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Fri Mar 11 17:56:44 2011 -0700 @@ -32,12 +32,15 @@ <div style="background-image: url('/static/images/forestry/plain-tree.gif'); background-repeat: repeat-x; width:{{resource_width}}px; height: 35px;"> </div> -<div class='ui-state-highlight ui-corner-all'> - <span class='ui-icon ui-icon-info'></span> - The resource size is <b>{{ resource_level.value }}</b>. +<div class='ui-state-highlight'> + <span class='icon-left ui-icon ui-icon-info'></span> + The resource size is <b>{{ resource_level.value }}</b>. <span class='small-font'>(each tree image represents 10 trees)</span> - </div> + <div class='ui-state-error'> + <span class='icon-left ui-icon ui-icon-info'></span> + Your current harvest decision is <b>{{ harvest_decision.value }}</b> + </div> {% if max_harvest_decision > 0 %} <form id='forestryForm' action='' method='post'> <div class='field'> diff -r dec7aff7174b -r adc83ffcaf7a vcweb/forestry/templates/forestry/wait.html --- a/vcweb/forestry/templates/forestry/wait.html Fri Mar 11 14:11:22 2011 -0700 +++ b/vcweb/forestry/templates/forestry/wait.html Fri Mar 11 17:56:44 2011 -0700 @@ -1,25 +1,20 @@ {% extends "base-participant.html" %} - {% block head %} -<meta http-equiv='refresh' content='10' /> {{ block.super }} +{% include "includes/participant.events.html" %} +{% include "includes/socket.io.html" %} <script type="text/javascript"> - var intervalId = 0; - function checkTimeRemaining() { - var timeRemaining = $('#timeRemaining').html() - if (timeRemaining > 0) { - timeRemaining = timeRemaining - 1; - $('#timeRemaining').html(timeRemaining); - } - else { - window.clearInterval(intervalId); - location.reload(true); - } - - } - $(function() { - intervalId = setInterval( "checkTimeRemaining()", 1000 ); + var s = connect(window.location.hostname, 8888, 'participant/{{participant_group_relationship.pk}}'); + s.on('message', function(json_string) { + var json = jQuery.parseJSON(json_string); + switch (json.message_type) { + case 'goto': + console.log("going to " + json.url); + window.location.href = json.url; + break; + } + }); }); </script> {% endblock %} diff -r dec7aff7174b -r adc83ffcaf7a vcweb/forestry/views.py --- a/vcweb/forestry/views.py Fri Mar 11 14:11:22 2011 -0700 +++ b/vcweb/forestry/views.py Fri Mar 11 17:56:44 2011 -0700 @@ -6,9 +6,9 @@ from django.template.context import RequestContext from vcweb import settings from vcweb.core.forms import QuizForm -from vcweb.core.models import is_participant, is_experimenter, Experiment +from vcweb.core.models import is_participant, is_experimenter, Experiment, ParticipantGroupRelationship from vcweb.core.decorators import participant_required, experimenter_required -from vcweb.forestry.models import get_resource_level, get_max_harvest_decision, get_forestry_experiment_metadata, set_harvest_decision +from vcweb.forestry.models import get_resource_level, get_max_harvest_decision, get_forestry_experiment_metadata, set_harvest_decision, get_harvest_decision from vcweb.forestry.forms import HarvestDecisionForm import logging @@ -65,12 +65,12 @@ def wait(request, experiment_id=None): try: experiment = Experiment.objects.get(pk=experiment_id) - if experiment.is_round_in_progress: - return redirect('forestry:participate', experiment_id=experiment.pk) - else: - return render_to_response('forestry/wait.html', - {'experiment': experiment}, - context_instance=RequestContext(request)) + participant_group_relationship = request.user.participant.get_participant_group_relationship(experiment) + return render_to_response('forestry/wait.html', { + 'experiment': experiment, + 'participant_group_relationship':participant_group_relationship, + }, + context_instance=RequestContext(request)) except Experiment.DoesNotExist: logger.warning("No experiment found with id %s" % experiment_id) @@ -154,19 +154,22 @@ def play(request, experiment, participant): form = HarvestDecisionForm(request.POST or None) + participant_group_relationship = participant.get_participant_group_relationship(experiment) + harvest_decision = get_harvest_decision(participant_group_relationship) if form.is_valid(): - harvest_decision = form.cleaned_data['harvest_decision'] + resources_harvested = form.cleaned_data['harvest_decision'] resource_level = get_resource_level(participant.get_group(experiment)) max_harvest_decision = get_max_harvest_decision(resource_level.value) - if harvest_decision <= max_harvest_decision: - set_harvest_decision(participant=participant, experiment=experiment, value=harvest_decision) + if resources_harvested <= max_harvest_decision: + set_harvest_decision(participant=participant, experiment=experiment, value=resources_harvested) return redirect('forestry:wait', experiment_id=experiment.pk) else: raise forms.ValidationError("invalid harvest decision %s > max %s" % (harvest_decision, max_harvest_decision)) else: - group = participant.groups.get(experiment=experiment) + group = participant_group_relationship.group resource_level = get_resource_level(group) max_harvest_decision = get_max_harvest_decision(resource_level.value) +# FIXME: UI crap logic in view to determine how wide to make the screen. resource_width = (resource_level.value / 10) * 30 return render_to_response(experiment.current_round_template, locals(), diff -r dec7aff7174b -r adc83ffcaf7a vcweb/static/css/style.css --- a/vcweb/static/css/style.css Fri Mar 11 14:11:22 2011 -0700 +++ b/vcweb/static/css/style.css Fri Mar 11 17:56:44 2011 -0700 @@ -78,11 +78,11 @@ .icon-left { float:left; /* top right bottom left */ - margin: 0.25em; + margin: 0.32em; } .icon-right { float: right; - margin: 0.25em; + margin: 0.32em; } .float-left { float: left; |
From: <vir...@li...> - 2011-03-11 21:10:36
|
Subject: hg.virtualcommons 274 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/dec7aff7174b changeset: 274:dec7aff7174b user: Allen Lee <all...@as...> date: Fri Mar 11 14:11:22 2011 -0700 description: fixed css selector diffstat: vcweb/core/templates/monitor.html | 5 ++++- vcweb/static/css/style.css | 28 ++-------------------------- 2 files changed, 6 insertions(+), 27 deletions(-) diffs (152 lines): diff -r c5974aa28ec3 -r dec7aff7174b vcweb/core/templates/monitor.html --- a/vcweb/core/templates/monitor.html Thu Mar 10 14:18:33 2011 -0700 +++ b/vcweb/core/templates/monitor.html Fri Mar 11 14:11:22 2011 -0700 @@ -66,6 +66,9 @@ s.send(createRefreshEvent()); return false; }); + $('#clear-experiment-messages').click(function() { + $('#experiment-messages').html(''); + }); }); </script> @@ -87,7 +90,7 @@ </fieldset> --> <div id='experimenter-sidebar'> - <h5>Experiment messages</h5> + <h5>Experiment messages <button id='clear-experiment-messages'>clear</button></h5> <div id='experiment-messages' class='experimenter-sidebar-messages notice ui-corner-all'> </div> </div> diff -r c5974aa28ec3 -r dec7aff7174b vcweb/static/css/style.css --- a/vcweb/static/css/style.css Thu Mar 10 14:18:33 2011 -0700 +++ b/vcweb/static/css/style.css Fri Mar 11 14:11:22 2011 -0700 @@ -96,35 +96,27 @@ background-position: 3px center; margin: 0 0.15em 0 0; } - .errorIcon, .warningIcon, .alertIcon, .infoIcon, .smallInfoIcon, .contactIcon, .crossIcon { background-repeat: no-repeat; margin: 5px 0px; padding: 15px 10px 15px 35px; background-position: 3px center; } - .errorIcon, .warningIcon, .alertIcon { background-image: url('/static/images/warning.png') } - .crossIcon { background-image: url('/static/images/famfamfam/cross.png'); } - .contactIcon { background-image: url('/static/images/famfamfam/comment_add.png'); } - - .smallInfoIcon { background-image: url('/static/images/famfamfam/information.png'); } - .infoIcon { background-image: url('/static/images/info.png') } - .small-font { font-size: 0.8em; } @@ -144,78 +136,62 @@ #experimentData a { text-decoration: none; } - a.tooltip { background-color: #F9E275; } - #experiments a { text-decoration: none; color: #06C; } - #experiments a:hover { text-decoration: underline; color: #36241B; } - - #experiments ul { list-style: none; margin: 0 0 0 0; padding: 0 0 0 0; } - #experiments li { list-style-type: none; margin: 0; padding-left: 25px; } - #experiments span.inactive { background: url('/static/images/famfamfam/clock_stop.png') center left no-repeat; } - #experiments span.active { background: url('/static/images/famfamfam/accept.png') center left no-repeat; } - #experiments span.round_in_progress { background: url('/static/images/famfamfam/arrow_refresh.png') center left no-repeat; } - - #experiments .rightArrow { margin: 0; background: url('/static/images/famfamfam/bullet_go.png') center left no-repeat; padding-left: 16px; padding-right: 8px; } - ul.horizontal { list-style: none; display: block; text-decoration: none; font-size: 0.9em; } - #horizontal a { background: url("/static/images/separator.gif") bottom right no-repeat; padding-left: 8px; padding-right: 8px; text-decoration: none; } - #horizontal a:hover { text-decoration: underline; } - #horizontal li { float: left; margin: 6px 0px 0px 0px; padding: 0; } - #navmenu { background: #4A3226; float: left; @@ -253,9 +229,9 @@ #experimenter-sidebar { float: right; } -#experimenter-sidebar h2,h3,h4,h5 { +#experimenter-sidebar h5 { padding: 0; - margin: -14px 0px 5px 0; + margin: -23px 0px 5px 0; } .experimenter-sidebar-messages { height: 13em; |
From: <vir...@li...> - 2011-03-11 21:10:36
|
Subject: hg.virtualcommons 273 details: http://virtualcommons.hg.sourceforge.net:8000/hgroot/virtualcommons/virtualcommons/hgrepo/v/vi/virtualcommons/virtualcommons/rev/c5974aa28ec3 changeset: 273:c5974aa28ec3 user: Allen Lee <all...@as...> date: Thu Mar 10 14:18:33 2011 -0700 description: using jQuery.parseJSON instead of JSON.parse diffstat: vcweb/core/templates/monitor.html | 36 ++++++----- vcweb/forestry/templates/forestry/chat.html | 5 +- vcweb/forestry/templates/forestry/instructions.html | 12 ++-- vcweb/forestry/templates/forestry/participate.html | 14 +---- vcweb/forestry/views.py | 5 +- vcweb/static/css/style.css | 58 +++++------------- 6 files changed, 50 insertions(+), 80 deletions(-) diffs (381 lines): diff -r 567a7b05bf0d -r c5974aa28ec3 vcweb/core/templates/monitor.html --- a/vcweb/core/templates/monitor.html Thu Mar 10 12:35:19 2011 -0700 +++ b/vcweb/core/templates/monitor.html Thu Mar 10 14:18:33 2011 -0700 @@ -41,32 +41,26 @@ }); } } + var qtipOptions = {position: { corner: {target: 'topRight', tooltip: 'bottomLeft'}}, style: { name: 'dark', tip: 'bottomLeft'} }; $(function() { + var experimentMessageDiv = document.getElementById('experiment-messages'); registerCallbacks({{ experiment.round_data.count }}, {{ experiment.current_round.sequence_number }}); // socket.io connection // FIXME: add auth var s = connect(window.location.hostname, 8888, 'experimenter/{{request.user.experimenter.pk}}'); - s.on('message', function(json_message) { - console.log("Received message: " + json_message); - var json = JSON.parse(json_message); + s.on('message', function(json_string) { + console.log("Received message: " + json_string); + var json = jQuery.parseJSON(json_string); switch (json.message_type) { case 'info': $("#experiment-messages").append($("<div class='ui-state-highlight' />").append(json.message)); break; default: - console.log("WTH? " + json.message); - } - console.log("message type: " + json.message_type); - + experimentMessageDiv.scrollTop = experimentMessageDiv.scrollHeight; }); - $('.tooltip').qtip({position: { corner: {target: 'topRight', tooltip: 'bottomLeft'}}, style: { name: 'dark', tip: 'bottomLeft'} }); - $('a[title]').not('.tooltip').qtip({position: { corner: {target: 'topRight', tooltip: 'bottomLeft'}}, style: { name: 'dark', tip: 'bottomLeft'} }); - $('.collapsible').click(function() { - $(this).addClass('collapsed'); - var next = $(this).next(); - next.toggle('fast'); - }); + $('.tooltip').qtip(qtipOptions); + $('a[title]').not('.tooltip').qtip(qtipOptions); $('#refreshAllParticipants').click(function(evt) { console.log("sending refresh event"); s.send(createRefreshEvent()); @@ -83,9 +77,19 @@ {% block page %} {{block.super}} <h3>{{experiment}}</h3> -<p>You are logged in as {{request.user.experimenter}}.</p> -<div id='experiment-messages' class='experimenter-sidebar-messages notice ui-corner-all'> +<span>You are logged in as {{request.user.experimenter}}.</span> +<hr/> +<!-- +<fieldset class='experimenter-sidebar-messages notice ui-corner-all'> + <legend>Experiment messages</legend> + <div id='experiment-messages' style='overflow:auto;'> + </div> +</fieldset> +--> +<div id='experimenter-sidebar'> <h5>Experiment messages</h5> + <div id='experiment-messages' class='experimenter-sidebar-messages notice ui-corner-all'> + </div> </div> <fieldset class='small ui-corner-all'> <legend>Experiment management</legend> diff -r 567a7b05bf0d -r c5974aa28ec3 vcweb/forestry/templates/forestry/chat.html --- a/vcweb/forestry/templates/forestry/chat.html Thu Mar 10 12:35:19 2011 -0700 +++ b/vcweb/forestry/templates/forestry/chat.html Thu Mar 10 14:18:33 2011 -0700 @@ -1,5 +1,4 @@ {% extends "base-participant.html" %} - {% block head %} {{ block.super }} {% include "includes/participant.events.html" %} @@ -8,7 +7,8 @@ $(function() { var chatDiv = document.getElementById('chat-div'); var s = connect(window.location.hostname, 8888, 'participant/{{participant_group_relationship.pk}}'); - s.on('message', function(json) { + s.on('message', function(json_string) { + var json = jQuery.parseJSON(json_string); switch (json.message_type) { case 'chat': $("#chat-div").append($("<div class='ui-state-highlight' />").append(json.message)) @@ -34,7 +34,6 @@ }); </script> {% endblock %} - {% block title %} Forestry Chat Round {% endblock %} diff -r 567a7b05bf0d -r c5974aa28ec3 vcweb/forestry/templates/forestry/instructions.html --- a/vcweb/forestry/templates/forestry/instructions.html Thu Mar 10 12:35:19 2011 -0700 +++ b/vcweb/forestry/templates/forestry/instructions.html Thu Mar 10 14:18:33 2011 -0700 @@ -1,6 +1,4 @@ {% extends "base-participant.html" %} - - {% block head %} {{ block.super }} {% include "includes/participant.events.html" %} @@ -9,20 +7,22 @@ $(function() { var s = connect(window.location.hostname, 8888, 'participant/{{participant_group_relationship.pk}}'); s.on('message', function(json_string) { - var json = JSON.parse(json_string); + var json = jQuery.parseJSON(json_string); switch (json.message_type) { - case "refresh": + case 'refresh': console.log("refreshing.."); window.location.reload(true); break; + case 'goto': + console.log("going to " + json.url); + window.location.href = json.url; + break; } }); }); </script> {% endblock %} - {% block title %}Forestry Instructions{% endblock %} - {% block content %} <h3>Forestry</h3> <p> diff -r 567a7b05bf0d -r c5974aa28ec3 vcweb/forestry/templates/forestry/participate.html --- a/vcweb/forestry/templates/forestry/participate.html Thu Mar 10 12:35:19 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Thu Mar 10 14:18:33 2011 -0700 @@ -1,15 +1,7 @@ {% extends "base-participant.html" %} {% block head %} {{ block.super }} - <script type="text/javascript"> - function range(begin, end){ - var array = [] - for (var i = begin; i <= end; ++i) { - array.push(i); - } - return array; - } $(function() { $("#forestryForm").validate({ rules: { @@ -35,7 +27,6 @@ {% block title %} Participating in {{experiment.status_line}} {% endblock %} - {% block content %} <h3>Forestry round number {{ experiment.current_round.round_number }}</h3> <div style="background-image: url('/static/images/forestry/plain-tree.gif'); background-repeat: repeat-x; width:{{resource_width}}px; height: 35px;"> @@ -59,10 +50,9 @@ </div> </form> {% else %} -<div class='ui-state-highlight ui-corner-all'> +<div class='alert ui-corner-all'> <span class='ui-icon ui-icon-alert'></span> - The resource has been depleted to the point where no one can harvest from - it. + There aren't enough resources to harvest. </div> {% endif %} {% endblock content %} diff -r 567a7b05bf0d -r c5974aa28ec3 vcweb/forestry/views.py --- a/vcweb/forestry/views.py Thu Mar 10 12:35:19 2011 -0700 +++ b/vcweb/forestry/views.py Thu Mar 10 14:18:33 2011 -0700 @@ -10,8 +10,8 @@ from vcweb.core.decorators import participant_required, experimenter_required from vcweb.forestry.models import get_resource_level, get_max_harvest_decision, get_forestry_experiment_metadata, set_harvest_decision from vcweb.forestry.forms import HarvestDecisionForm +import logging -import logging logger = logging.getLogger(__name__) @login_required @@ -74,6 +74,7 @@ except Experiment.DoesNotExist: logger.warning("No experiment found with id %s" % experiment_id) +# FIXME: refactor this ugliness @participant_required def participate(request, experiment_id=None): participant = request.user.participant @@ -88,8 +89,8 @@ elif current_round.is_quiz_round: return quiz(request, experiment, participant) else: + # instructions or quiz round participant_group_rel = participant.get_participant_group_relationship(experiment) - # instructions or quiz round return render_to_response(experiment.current_round_template, { 'participant_group_relationship': participant_group_rel, 'experiment': experiment, diff -r 567a7b05bf0d -r c5974aa28ec3 vcweb/static/css/style.css --- a/vcweb/static/css/style.css Thu Mar 10 12:35:19 2011 -0700 +++ b/vcweb/static/css/style.css Thu Mar 10 14:18:33 2011 -0700 @@ -1,13 +1,11 @@ body { font-family: /*"Lucida Grande", "Trebuchet MS",*/ Arial, Helvetica, Tahoma, Verdana, sans-serif; font-size: 1.1em; - } a.external { background: url(/static/images/external.png) center right no-repeat; padding-right: 13px; } - h1, h2, h3, h4, h5 { margin: 0; font-weight: normal; @@ -18,31 +16,22 @@ margin-top:1em; margin-bottom:.7em; } - h2, h3, h4, h5 { border-bottom:1px solid #333; } - - h1 { font-size: 1.8em; } - h2 { font-size: 1.4em; } - h3 { font-size: 1.2em; } - h4 { font-size: 1.0em; } - - +h5 { font-size: 0.9em; } input[type=text], input[type=password] { width: 12em; } - input.error { padding: 0; margin: 0; border: solid red; } - label.error { background: url('/static/images/unchecked.gif') no-repeat left center #FBE3E4; line-height: normal; @@ -52,12 +41,10 @@ padding-left: 1.1em; margin-left: 0.3em; } - input.two-digits { width: 2em; text-align: right; } - span.label { float: left; text-align: right; @@ -68,43 +55,41 @@ display:inline; font-size: 0.8em; } - ul.messages { margin-left: 0; list-style: none; } - ul.actions { margin: 0; list-style: none; padding: 0; } - span.clickable { cursor: pointer; color: #961A06; text-decoration: underline; } - #actions li { padding: 3px; } - li.warning { font-size: 0.8em; } - .icon-left { float:left; /* top right bottom left */ margin: 0.25em; } - .icon-right { float: right; margin: 0.25em; } - +.float-left { + float: left; +} +.float-right { + float:right; +} .vcweb-icon { display:inline; background-repeat: no-repeat; @@ -143,7 +128,6 @@ .small-font { font-size: 0.8em; } - fieldset.small { font: 0.8em "Helvetica Neue", helvetica, arial, sans-serif; color: #666; @@ -152,13 +136,11 @@ border: solid 1px #d3d3d3; width: 500px; } - -legend { +fieldset.small>legend { font-weight: bold; text-transform: lowercase; padding: 2px 6px; } - #experimentData a { text-decoration: none; } @@ -263,34 +245,28 @@ color: #fff; padding-bottom: 8px; } - #timeRemaining span { background: url('/static/images/clock.png') bottom center no-repeat; margin-left: 8px; margin-right: 8px; } - +#experimenter-sidebar { + float: right; +} +#experimenter-sidebar h2,h3,h4,h5 { + padding: 0; + margin: -14px 0px 5px 0; +} .experimenter-sidebar-messages { - margin-top: 8px; - height: 13.1em; + height: 13em; width: 22em; - float: right; overflow:auto; + float:right; } - .chat { height: 20em; overflow: auto; } - #chatText { width: 100%; } - -.collapsible { - -} - -.collapsed { - -} |