virtualcommons-svn Mailing List for Virtual Commons Experiment Software (Page 30)
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: Bitbucket <com...@bi...> - 2011-07-07 20:40:50
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/5116b3dc5612/ changeset: 5116b3dc5612 user: alllee date: 2011-07-07 22:40:52 summary: adding icon ImageField to Activity (adds PIL dependency, you'll need to run pip install PIP for syncdb to work properly) and configuring MEDIA_ROOT/MEDIA_URL affected #: 3 files (91 bytes) --- a/vcweb/lighterprints/models.py Thu Jul 07 02:03:36 2011 -0700 +++ b/vcweb/lighterprints/models.py Thu Jul 07 13:40:52 2011 -0700 @@ -16,7 +16,8 @@ # FIXME: allow for experiment-configurable levels? level = models.PositiveIntegerField(default=1) group_activity = models.BooleanField(default=False, help_text='Whether or not this activity has beneficial group effect multipliers, e.g., ride sharing') - cooldown = models.PositiveIntegerField(default=1, help_text='How much time, in hours, must elapse before this activity can become available again') + cooldown = models.PositiveIntegerField(default=1, null=True, blank=True, help_text='How much time, in hours, must elapse before this activity can become available again') + icon = models.ImageField(upload_to='lighterprints/activity-icons/') @property def label(self): @@ -28,8 +29,7 @@ @property def icon_url(self): - # FIXME: implement as return "/activity/id/icon" - pass + return self.icon.url def __unicode__(self): return u'%s (+%s)' % (self.label, self.savings) --- a/vcweb/requirements.pip Thu Jul 07 02:03:36 2011 -0700 +++ b/vcweb/requirements.pip Thu Jul 07 13:40:52 2011 -0700 @@ -8,6 +8,7 @@ django-kombu django-dajaxice django-autocomplete +PIL #django-unittest-depth #redis #beanstalkc --- a/vcweb/settings.py Thu Jul 07 02:03:36 2011 -0700 +++ b/vcweb/settings.py Thu Jul 07 13:40:52 2011 -0700 @@ -33,16 +33,7 @@ # If you set this to False, Django will make some optimizations so as not # to load the internationalization machinery. -USE_I18N = False - -# Absolute path to the directory that holds media. -# Example: "/home/media/media.lawrence.com/" -#MEDIA_ROOT = '' - -# URL that handles the media served from MEDIA_ROOT. Make sure to use a -# trailing slash if there is a path component (optional in other cases). -# Examples: "http://media.lawrence.com", "http://example.com/media/" -#MEDIA_URL = '/static/' +USE_I18N = True # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. Default is '/static/admin/' @@ -135,6 +126,15 @@ path.join(path.abspath(path.dirname(__file__)), 'static').replace('\\', '/'), ) +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = path.join(STATIC_ROOT, 'media') + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '/static/media/' + # set up jquery-ui css classes for django messages MESSAGE_TAGS = { Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <iss...@bi...> - 2011-07-07 19:39:39
|
--- you can reply above this line --- New issue 27: add icon file field to Activity https://bitbucket.org/virtualcommons/vcweb/issue/27/add-icon-file-field-to-activity A Lee / alllee on Thu, 7 Jul 2011 21:39:33 +0200: Description: Use https://docs.djangoproject.com/en/dev/ref/models/fields/#imagefield Responsible: alllee -- This is an issue notification from bitbucket.org. You are receiving this either because you are the owner of the issue, or you are following the issue. |
From: Bitbucket <com...@bi...> - 2011-07-07 09:03:35
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/c35ff5f35a27/ changeset: c35ff5f35a27 user: alllee date: 2011-07-07 11:03:36 summary: updating tornadio script affected #: 1 file (33 bytes) --- a/vcweb/vcwebio.py Thu Jul 07 01:03:20 2011 -0700 +++ b/vcweb/vcwebio.py Thu Jul 07 02:03:36 2011 -0700 @@ -95,7 +95,7 @@ ''' def connections(self, group): experiment = group.experiment - for participant_group_relationship in group.participant_group_relationships.all(): + for participant_group_relationship in group.participant_group_relationship_set.select_related(depth=1).all(): ''' only return currently connected connections in this group ''' participant = participant_group_relationship.participant participant_tuple = (participant.pk, experiment.pk) @@ -106,7 +106,7 @@ 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 group in experiment.group_set.all(): for participant_group_pk, connection in self.connections(group): yield (participant_group_pk, connection) else: @@ -230,7 +230,7 @@ event.participant_pk = participant_pk pgr_pk = event.participant_group_relationship_id participant_group_relationship = ParticipantGroupRelationship.objects.get(pk=pgr_pk) - prdv = experiment.current_round_data.participant_data_values.get(participant_group_relationship__pk=pgr_pk) + prdv = experiment.current_round_data.participant_data_value_set.get(participant_group_relationship__pk=pgr_pk) event.participant_data_value_pk = prdv.pk event.participant_number = participant_group_relationship.participant_number event.participant_group = participant_group_relationship.group_number Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-07-07 08:05:02
|
5 new changesets in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/9db1221cfc7c/ changeset: 9db1221cfc7c user: alllee date: 2011-07-07 07:03:24 summary: fixes issue 24 affected #: 8 files (327 bytes) --- a/vcweb/core/models.py Wed Jul 06 12:16:47 2011 -0700 +++ b/vcweb/core/models.py Wed Jul 06 22:03:24 2011 -0700 @@ -124,8 +124,8 @@ The configuration for a given Experiment instance. One ExperimentConfiguration can be applied to many Experiment instances but can only be associated to a single ExperimentMetadata record. """ - experiment_metadata = models.ForeignKey(ExperimentMetadata, related_name='experiment_configurations') - creator = models.ForeignKey(Experimenter, related_name='experiment_configurations') + experiment_metadata = models.ForeignKey(ExperimentMetadata, related_name='experiment_configuration_set') + creator = models.ForeignKey(Experimenter, related_name='experiment_configuration_set') name = models.CharField(max_length=255) max_number_of_participants = models.PositiveIntegerField(default=0) date_created = models.DateField(auto_now_add=True) @@ -136,11 +136,11 @@ @property def final_sequence_number(self): # FIXME: or max round_configurations.sequence_number (degenerate data) - return self.round_configurations.count() + return self.round_configuration_set.count() @property def last_round_sequence_number(self): - return self.round_configurations.aggregate(sequence_number=Max('sequence_number'))['sequence_number'] + return self.round_configuration_set.aggregate(sequence_number=Max('sequence_number'))['sequence_number'] @property def namespace(self): @@ -186,11 +186,11 @@ current_round_sequence_number = models.PositiveIntegerField(default=1) """ Each round is assigned a sequential sequence number, ranging from 1 to N. Used to identify which round the experiment is currently running. """ - experimenter = models.ForeignKey(Experimenter, related_name='experiments') + experimenter = models.ForeignKey(Experimenter) """ the user running this experiment """ experiment_metadata = models.ForeignKey(ExperimentMetadata) """ the experiment metadata object that this experiment instance represents """ - experiment_configuration = models.ForeignKey(ExperimentConfiguration, related_name='experiments') + experiment_configuration = models.ForeignKey(ExperimentConfiguration) """ the configuration parameters in use for this experiment run. """ status = models.CharField(max_length=32, choices=STATUS_CHOICES, default='INACTIVE') @@ -265,8 +265,8 @@ @property def participant_group_relationships(self): - for group in self.groups.all(): - for pgr in group.participant_group_relationships.all(): + for group in self.group_set .all(): + for pgr in group.participant_group_relationship_set.all(): yield pgr @property @@ -316,7 +316,7 @@ @property def current_round_data(self): - round_data, created = self.round_data.get_or_create(round_configuration=self.current_round) + round_data, created = self.round_data_set.get_or_create(round_configuration=self.current_round) return round_data @property @@ -375,12 +375,12 @@ @property def all_participants_have_submitted(self): - pdvs = self.current_round_data.participant_data_values + pdvs = self.current_round_data.participant_data_value_set return pdvs.filter(submitted=False).count() == 0 def register_participants(self, users=None, emails=None, institution=None, password=None): - if self.participants.count() > 0: - logger.warning("This experiment %s already has %d participants - aborting", self, self.participants.count()) + if self.participant_set.count() > 0: + logger.warning("This experiment %s already has %d participants - aborting", self, self.participant_set.count()) return if users is None: users = [] @@ -406,8 +406,8 @@ ''' hardcoded defaults for the slovakia pretest ''' def setup_test_participants(self, count=20, institution=None, email_suffix='sav.sk', password='test'): - if self.participants.count() > 0: - logger.warning("This experiment %s already has %d participants - aborting", self, self.participants.count()) + if self.participant_set.count() > 0: + logger.warning("This experiment %s already has %d participants - aborting", self, self.participant_set.count()) return users = [] for i in xrange(1, count+1): @@ -431,25 +431,25 @@ if participant_parameters is None: participant_parameters = self.parameters(scope=Parameter.PARTICIPANT_SCOPE) current_round_data = self.current_round_data - for group in self.groups.select_related(depth=1).all(): + for group in self.group_set.select_related(depth=1).all(): for parameter in group_parameters: - group_data_value, created = current_round_data.group_data_values.get_or_create(group=group, parameter=parameter) + group_data_value, created = current_round_data.group_data_value_set.get_or_create(group=group, parameter=parameter) logger.debug("%s (%s)", group_data_value, created) - for pgr in group.participant_group_relationships.all(): + for pgr in group.participant_group_relationship_set.all(): for parameter in participant_parameters: - participant_data_value, created = current_round_data.participant_data_values.get_or_create(participant_group_relationship=pgr, parameter=parameter) + participant_data_value, created = current_round_data.participant_data_value_set.get_or_create(participant_group_relationship=pgr, parameter=parameter) logger.debug("%s (%s)", participant_data_value, created) def log(self, log_message): if log_message: logger.debug("%s: %s", self, log_message) - self.activity_log.create(round_configuration=self.current_round, log_message=log_message) + self.activity_log_set.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) def parameters(self, scope=None): - ps = self.experiment_metadata.parameters + ps = self.experiment_metadata.parameter_set return ps.filter(scope=scope) if scope else ps def activate(self): @@ -462,10 +462,10 @@ def allocate_groups(self, randomize=True): # clear out all existing groups # FIXME: record previous mappings in activity log. - self.groups.all().delete() + self.group_set.all().delete() # seed the initial group. - current_group = self.groups.create(number=1, max_size=self.experiment_configuration.max_group_size) - participants = list(self.participants.all()) + current_group = self.group_set.create(number=1, max_size=self.experiment_configuration.max_group_size) + participants = list(self.participant_set.all()) if randomize: random.shuffle(participants) @@ -476,10 +476,10 @@ # XXX: if there a performance hit here, should probably do a void return instead # or collect the groups as they are added - return self.groups + return self.group_set def get_round_configuration(self, sequence_number): - return self.experiment_configuration.round_configurations.get(sequence_number=sequence_number) + return self.experiment_configuration.round_configuration_set.get(sequence_number=sequence_number) def get_template_path(self, name): return "%s/%s" % (self.namespace, name) @@ -560,12 +560,12 @@ ) def transfer_participants(self, experiment): - if experiment.participants.count() == 0: - for participant in self.participants.all(): + if experiment.participant_set.count() == 0: + for participant in self.participant_set.all(): ParticipantExperimentRelationship.objects.create(participant=participant, experiment=experiment, created_by=self.experimenter.user) else: - logger.warning("Tried to transfer participants to an experiment %s that already had participants %s", experiment, experiment.participants.all()) + logger.warning("Tried to transfer participants to an experiment %s that already had participants %s", experiment, experiment.participant_set.all()) def __unicode__(self): return u"%s #%s | %s" % (self.experiment_metadata.title, self.pk, self.experimenter) @@ -586,7 +586,7 @@ 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') + experiment_configuration = models.ForeignKey(ExperimentConfiguration, related_name='round_configuration_set') sequence_number = models.PositiveIntegerField(help_text='Used internally to determine the ordering of the rounds in an experiment in ascending order, e.g., 1,2,3,4,5') display_number = models.PositiveIntegerField(default=0, help_text='The round number to be displayed with this round. If set to zero, defaults to the internally used sequence_number.') @@ -661,20 +661,20 @@ def get_parameter(self, name): parameter = Parameter.objects.get(name=name, scope=Parameter.ROUND_SCOPE) - round_parameter, created = self.round_parameter_values.get_or_create(parameter=parameter) + round_parameter, created = self.round_parameter_value_set.get_or_create(parameter=parameter) if created: logger.debug("created new parameter %s for %s", parameter, self) return round_parameter def set_parameter(self, name=None, value=None): parameter = Parameter.objects.get(name=name, scope=Parameter.ROUND_SCOPE) - parameter_value, created = self.round_parameter_values.get_or_create(parameter=parameter) + parameter_value, created = self.round_parameter_value_set.get_or_create(parameter=parameter) parameter_value.value = value parameter_value.save() def get_parameter_value(self, name, default=None): try: - return self.round_parameter_values.get(parameter__name=name).value + return self.round_parameter_value_set.get(parameter__name=name).value except RoundParameterValue.DoesNotExist: return default @@ -707,8 +707,8 @@ answer = models.CharField(max_length=64) input_type = models.CharField(max_length=32) explanation = models.CharField(max_length=512) - round_configuration = models.ForeignKey(RoundConfiguration, related_name='quiz_questions') - experiment = models.ForeignKey(Experiment, related_name='default_quiz_questions', null=True, blank=True) + round_configuration = models.ForeignKey(RoundConfiguration, related_name='quiz_question_set') + experiment = models.ForeignKey(Experiment, related_name='default_quiz_question_set', null=True, blank=True) def is_correct(self, candidate): return self.answer == candidate @@ -764,7 +764,7 @@ date_created = models.DateTimeField(auto_now_add=True) last_modified = models.DateTimeField(auto_now=True) creator = models.ForeignKey(Experimenter) - experiment_metadata = models.ForeignKey(ExperimentMetadata, related_name='parameters') + experiment_metadata = models.ForeignKey(ExperimentMetadata) enum_choices = models.TextField(null=True, blank=True) is_required = models.BooleanField(default=False) @@ -817,6 +817,7 @@ class Meta: ordering = ['name'] + unique_together = ['name', 'experiment_metadata', 'scope'] class ParameterizedValue(models.Model): parameter = models.ForeignKey(Parameter) @@ -845,7 +846,7 @@ """ Represents a specific piece of round configuration data. """ - round_configuration = models.ForeignKey(RoundConfiguration, related_name='round_parameter_values') + round_configuration = models.ForeignKey(RoundConfiguration, related_name='round_parameter_value_set') def __unicode__(self): return u"{0} -> [{1}: {2}]".format(self.round_configuration, self.parameter, self.value) @@ -871,7 +872,7 @@ how many members can this group hold at a maximum? Could be specified as a RoundParameterValue / ExperimentConfiguration value """ - experiment = models.ForeignKey(Experiment, related_name='groups') + experiment = models.ForeignKey(Experiment) """ The experiment that contains this Group. """ @@ -887,7 +888,7 @@ @property def size(self): - return self.participants.count() + return self.participant_set.count() @property def current_round(self): @@ -895,7 +896,7 @@ @property def all_participants_str(self): - return ', '.join([participant.email for participant in self.participants.all()]) + return ', '.join([participant.email for participant in self.participant_set.all()]) @property def data_parameters(self): @@ -919,12 +920,12 @@ @property def current_round_activity_log(self): - return self.activity_log.filter(round_configuration=self.current_round) + return self.activity_log_set.filter(round_configuration=self.current_round) def log(self, log_message): if log_message: logger.debug(log_message) - self.activity_log.create(round_configuration=self.current_round, log_message=log_message) + self.activity_log_set.create(round_configuration=self.current_round, log_message=log_message) def subtract(self, parameter=None, amount=0): self.add(parameter, -amount) @@ -961,7 +962,7 @@ round_data = self.current_round_data criteria = self._data_parameter_criteria(parameter=parameter, parameter_name=parameter_name, round_data=round_data) try: - return self.data_values.get(**criteria) + return self.data_value_set.get(**criteria) except GroupRoundDataValue.DoesNotExist as e: logger.warning("No data value found for criteria %s", criteria) if default is None: @@ -1067,8 +1068,8 @@ (GroupRoundDataValue), participant_data (ParticipantRoundDataValue), and chat_messages (ChatMessage) """ - experiment = models.ForeignKey(Experiment, related_name='round_data') - round_configuration = models.ForeignKey(RoundConfiguration) + experiment = models.ForeignKey(Experiment, related_name='round_data_set') + round_configuration = models.ForeignKey(RoundConfiguration, related_name='round_data_set') elapsed_time = models.PositiveIntegerField(default=0) def __unicode__(self): @@ -1078,8 +1079,8 @@ ordering = [ 'round_configuration' ] class GroupRoundDataValue(DataValue): - group = models.ForeignKey(Group, related_name='data_values') - round_data = models.ForeignKey(RoundData, related_name='group_data_values') + group = models.ForeignKey(Group, related_name='data_value_set') + round_data = models.ForeignKey(RoundData, related_name='group_data_value_set') def __init__(self, *args, **kwargs): super(GroupRoundDataValue, self).__init__(*args, **kwargs) @@ -1100,8 +1101,8 @@ class Participant(CommonsUser): can_receive_invitations = models.BooleanField(default=False) - groups = models.ManyToManyField(Group, through='ParticipantGroupRelationship', related_name='participants') - experiments = models.ManyToManyField(Experiment, through='ParticipantExperimentRelationship', related_name='participants') + groups = models.ManyToManyField(Group, through='ParticipantGroupRelationship', related_name='participant_set') + experiments = models.ManyToManyField(Experiment, through='ParticipantExperimentRelationship', related_name='participant_set') @property def active_experiments(self): @@ -1131,10 +1132,10 @@ """ Many-to-many relationship entity storing a participant and the experiment they are participating in. """ - participant = models.ForeignKey(Participant, related_name='experiment_relationships') + participant = models.ForeignKey(Participant, related_name='experiment_relationship_set') participant_identifier = models.CharField(max_length=32) sequential_participant_identifier = models.PositiveIntegerField() - experiment = models.ForeignKey(Experiment, related_name='participant_relationships') + experiment = models.ForeignKey(Experiment, related_name='participant_relationship_set') date_created = models.DateTimeField(auto_now_add=True) created_by = models.ForeignKey(User) last_completed_round_sequence_number = models.PositiveIntegerField(default=0) @@ -1179,8 +1180,8 @@ round in which they joined the group, and the datetime that they joined the group. """ participant_number = models.PositiveIntegerField() - participant = models.ForeignKey(Participant, related_name='participant_group_relationships') - group = models.ForeignKey(Group, related_name = 'participant_group_relationships') + participant = models.ForeignKey(Participant, related_name='participant_group_relationship_set') + group = models.ForeignKey(Group, related_name = 'participant_group_relationship_set') round_joined = models.ForeignKey(RoundConfiguration) date_created = models.DateTimeField(auto_now_add=True) active = models.BooleanField(default=True) @@ -1200,7 +1201,7 @@ if parameter is not None and value is not None: # FIXME: make sure this is concurrent-safe or better yet that all participant data values are created at the # start of a round. - participant_data_value, created = current_round_data.participant_data_values.get_or_create(parameter=parameter, participant_group_relationship=self) + participant_data_value, created = current_round_data.participant_data_value_set.get_or_create(parameter=parameter, participant_group_relationship=self) participant_data_value.value = value # FIXME: parameterize / make explicit? participant_data_value.submitted = True @@ -1218,7 +1219,7 @@ class ChatMessageManager(models.Manager): def message(self, experiment, message): current_round_data = experiment.current_round_data - for participant in experiment.participants.all(): + for participant in experiment.participant_set.all(): yield ChatMessage.objects.create(participant_group_relationship=participant.get_participant_group_relationship(experiment), message=message, round_data=current_round_data) @@ -1228,19 +1229,19 @@ A chat message sent by a participant in a group to the rest of the members of the group or a target participant if target_participant is set. """ - participant_group_relationship = models.ForeignKey(ParticipantGroupRelationship, related_name='chat_messages') + participant_group_relationship = models.ForeignKey(ParticipantGroupRelationship, related_name='participant_chat_message_set') """ the combination of participant and group that generated this chat message """ message = models.CharField(max_length=512) """ the chat message """ - target_participant = models.ForeignKey(ParticipantGroupRelationship, null=True, blank=True, related_name='targets') + target_participant = models.ForeignKey(ParticipantGroupRelationship, null=True, blank=True, related_name='target_participant_chat_message_set') """ if set, this is a targeted message to the other participant in this group. If null, this is a broadcast message to the entire group """ date_created = models.DateTimeField(auto_now_add=True) """ the creation datetime of this chat message """ - round_data = models.ForeignKey(RoundData, related_name='chat_messages') + round_data = models.ForeignKey(RoundData, related_name='chat_message_set') """ the round data associated with this chat message """ objects = ChatMessageManager() @@ -1277,8 +1278,8 @@ (from DataValue), the round in which the data value was associated. """ class ParticipantRoundDataValue(DataValue): - round_data = models.ForeignKey(RoundData, related_name='participant_data_values') - participant_group_relationship = models.ForeignKey(ParticipantGroupRelationship, related_name='participant_data_values') + round_data = models.ForeignKey(RoundData, related_name='participant_data_value_set') + participant_group_relationship = models.ForeignKey(ParticipantGroupRelationship, related_name='participant_data_value_set') submitted = models.BooleanField(default=False) def __init__(self, *args, **kwargs): @@ -1318,14 +1319,14 @@ 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') + group = models.ForeignKey(Group, related_name='activity_log_set') 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') + experiment = models.ForeignKey(Experiment, related_name='activity_log_set') round_configuration = models.ForeignKey(RoundConfiguration) def is_experimenter(user, experimenter=None): --- a/vcweb/core/templates/experimenter/monitor.html Wed Jul 06 12:16:47 2011 -0700 +++ b/vcweb/core/templates/experimenter/monitor.html Wed Jul 06 22:03:24 2011 -0700 @@ -149,7 +149,7 @@ </div><div id='statusDiv'> {% block status %} - {% with participant_count=experiment.participants.count %} + {% with participant_count=experiment.participant_set.count %} <fieldset class='small ui-corner-all'><legend>round status</legend><ul id='actions' class='actions'> @@ -186,7 +186,7 @@ <li>Type: {{ experiment.current_round.get_round_type_display }}</li><li>Round started on {{ experiment.current_round_start_time }}</li><li>Time remaining: {{ experiment.time_remaining }}</li> - <li title='{{experiment.participants.all|join:" "}}'>Registered participants: <b>{{participant_count}}</b> + <li title='{{experiment.participant_set.all|join:" "}}'>Registered participants: <b>{{participant_count}}</b></li></ul></fieldset> --- a/vcweb/core/templates/experimenter/register-participants.html Wed Jul 06 12:16:47 2011 -0700 +++ b/vcweb/core/templates/experimenter/register-participants.html Wed Jul 06 22:03:24 2011 -0700 @@ -26,7 +26,7 @@ <p>Registering participants for <span style='padding:1px;' class='info'>{{experiment}}</span>. </p><p> - <span style='padding: 3px;' class='ui-state-highlight'><b>There are currently {{experiment.participants.count}} registered participants.</b></span> + <span style='padding: 3px;' class='ui-state-highlight'><b>There are currently {{experiment.participant_set.count}} registered participants.</b></span> {% include "includes/form-as-div.html" %} <div><button class='submit' type='submit'>Register</button> --- a/vcweb/core/tests.py Wed Jul 06 12:16:47 2011 -0700 +++ b/vcweb/core/tests.py Wed Jul 06 22:03:24 2011 -0700 @@ -22,7 +22,7 @@ experiment = Experiment.objects.get(pk=1).clone() else: experiment = self.create_new_experiment(experiment_metadata, **kwargs) - if experiment.participants.count() == 0: + if experiment.participant_set.count() == 0: experiment.setup_test_participants(email_suffix='asu.edu') logger.debug("loaded %s", experiment) self.experiment = experiment @@ -46,7 +46,7 @@ experiment_configuration = ExperimentConfiguration.objects.create(experiment_metadata=experiment_metadata, name='Test Experiment Configuration', creator=experimenter) for index in xrange(1, 10): - experiment_configuration.round_configurations.create(sequence_number=index) + experiment_configuration.round_configuration_set.create(sequence_number=index) return Experiment.objects.create(experimenter=self.experimenter, experiment_metadata=experiment_metadata, experiment_configuration=experiment_configuration) @@ -77,8 +77,7 @@ ) def create_new_parameter(self, name='vcweb.test.parameter', scope='EXPERIMENT_SCOPE', parameter_type='string'): - return self.experiment_metadata.parameters.create(creator=self.experimenter, - name=name, scope=scope, type=parameter_type) + return self.experiment_metadata.parameter_set.create(creator=self.experimenter, name=name, scope=scope, type=parameter_type) def create_new_group(self, max_size=10, experiment=None): @@ -158,8 +157,8 @@ def test_group_allocation(self): experiment = self.experiment experiment.allocate_groups(randomize=False) - self.assertEqual(experiment.groups.count(), 2, "there should be 2 groups after non-randomized allocation") - self.assertEqual(sum(map(lambda group:group.participants.count(), experiment.groups.all())), 10) + self.assertEqual(experiment.group_set.count(), 2, "there should be 2 groups after non-randomized allocation") + self.assertEqual( 10, sum([group.participant_set.count() for group in experiment.group_set]) ) def test_participant_numbering(self): experiment = self.experiment @@ -200,21 +199,21 @@ e.start_round() # instructions round current_round_data = e.current_round_data - self.assertEqual(current_round_data.group_data_values.count(), 0) - self.assertEqual(current_round_data.participant_data_values.count(), 0) + self.assertEqual(current_round_data.group_data_value_set.count(), 0) + self.assertEqual(current_round_data.participant_data_value_set.count(), 0) def test_playable_round(self): e = self.advance_to_data_round() e.start_round() current_round_data = e.current_round_data - for group in e.groups.all(): + for group in e.group_set.all(): for parameter in group.data_parameters.all(): - group_data_value, created = current_round_data.group_data_values.get_or_create(group=group, + group_data_value, created = current_round_data.group_data_value_set.get_or_create(group=group, parameter=parameter) self.assertFalse(created) - for pgr in group.participant_group_relationships.all(): + for pgr in group.participant_group_relationship_set.all(): for parameter in e.parameters(scope=Parameter.PARTICIPANT_SCOPE): - participant_data_value, created = current_round_data.participant_data_values.get_or_create(participant_group_relationship=pgr, + participant_data_value, created = current_round_data.participant_data_value_set.get_or_create(participant_group_relationship=pgr, parameter=parameter) self.assertFalse(created) @@ -222,9 +221,9 @@ def test_set_data_value_activity_log(self): e = self.advance_to_data_round() test_data_value = 10 - for g in e.groups.all(): + for g in e.group_set.all(): activity_log_counter = GroupActivityLog.objects.filter(group=g).count() - for data_value in g.data_values.all(): + for data_value in g.data_value_set.all(): # XXX: pathological use of set_data_value, no point in doing it # this way since typical usage would do a lookup by name. g.set_data_value(parameter=data_value.parameter, value=test_data_value) @@ -239,14 +238,14 @@ first_pass = True while e.has_next_round: if first_pass: - for g in e.groups.all(): + for g in e.group_set.all(): g.set_data_value(parameter=parameter, value=test_data_value) self.assertEqual(g.get_data_value(parameter=parameter).value, test_data_value) self.assertEqual(g.get_scalar_data_value(parameter=parameter), test_data_value) g.transfer_to_next_round(parameter) first_pass = False else: - for g in e.groups.all(): + for g in e.group_set.all(): self.assertEqual(g.get_data_value(parameter=parameter).value, test_data_value) self.assertEqual(g.get_scalar_data_value(parameter=parameter), test_data_value) g.transfer_to_next_round(parameter) @@ -263,8 +262,8 @@ for p in self.participants: g.add_participant(p) count += 1 - self.assertTrue(g.participants) - self.assertEqual(g.participants.count(), count, "group.participants size should be %i" % count) + self.assertTrue(g.participant_set) + self.assertEqual(g.participant_set.count(), count, "group.participants size should be %i" % count) self.assertEqual(g.size, count, "group size should be %i" % count) @@ -281,7 +280,7 @@ self.assertTrue(per.participant_identifier) self.assertTrue(per.sequential_participant_identifier > 0) - self.assertEqual(e.participants.count(), self.participants.count()) + self.assertEqual(e.participant_set.count(), self.participants.count()) class RoundConfigurationTest(BaseVcwebTest): --- a/vcweb/core/views.py Wed Jul 06 12:16:47 2011 -0700 +++ b/vcweb/core/views.py Wed Jul 06 22:03:24 2011 -0700 @@ -218,7 +218,7 @@ class ParticipantSingleExperimentMixin(SingleExperimentMixin, ParticipantMixin): def check_user(self, user, experiment): - # FIXME: should we do a user.participant in experiment.participants.all() check? + # FIXME: should we do a user.participant in experiment.participant_set.all() check? return experiment class ExperimenterSingleExperimentMixin(SingleExperimentMixin, ExperimenterMixin): @@ -275,7 +275,7 @@ class ClearParticipantsExperimentView(ExperimenterSingleExperimentView): def process_experiment(self, experiment): - experiment.participants.all().delete() + experiment.participant_set.all().delete() return experiment def render_to_response(self, context): return redirect('core:dashboard') --- a/vcweb/forestry/models.py Wed Jul 06 12:16:47 2011 -0700 +++ b/vcweb/forestry/models.py Wed Jul 06 22:03:24 2011 -0700 @@ -119,7 +119,7 @@ if should_reset_resource_level(round_configuration): initial_resource_level = get_initial_resource_level(round_configuration) logger.debug("Resetting resource level for %s to %d", round_configuration, initial_resource_level) - for group in experiment.groups.all(): + for group in experiment.group_set.all(): ''' set resource level to initial default ''' group.log("Setting resource level to initial value [%s]" % initial_resource_level) set_resource_level(group, initial_resource_level) @@ -136,7 +136,7 @@ current_round_configuration = experiment.current_round logger.debug("current round: %s", current_round_configuration) max_resource_level = 100 - for group in experiment.groups.all(): + for group in experiment.group_set.all(): # FIXME: simplify logic if has_resource_level(group): current_resource_level = get_resource_level(group) --- a/vcweb/forestry/tests.py Wed Jul 06 12:16:47 2011 -0700 +++ b/vcweb/forestry/tests.py Wed Jul 06 22:03:24 2011 -0700 @@ -17,7 +17,7 @@ def test_round_started_signal(self): e = self.advance_to_data_round() e.start_round(sender=forestry_sender) - for group in e.groups.all(): + for group in e.group_set.all(): self.verify_resource_level(group) return e @@ -26,18 +26,18 @@ # manually invoke round_setup, otherwise start_round should work as # well (but that's tested in the signal tests) round_setup(e) - for group in e.groups.all(): + for group in e.group_set.all(): self.verify_resource_level(group) return e def verify_round_ended(self, e, end_round_func): current_round_data = e.current_round_data harvest_decision_parameter = get_harvest_decision_parameter() - for group in e.groups.all(): + for group in e.group_set.all(): ds = get_harvest_decisions(group) self.verify_resource_level(group) - self.assertEqual(len(ds), group.participants.count()) - for pgr in group.participant_group_relationships.all(): + self.assertEqual(len(ds), group.participant_set.count()) + for pgr in group.participant_group_relationship_set.all(): pdv = ParticipantRoundDataValue.objects.get( parameter=harvest_decision_parameter, participant_group_relationship=pgr, @@ -90,7 +90,7 @@ if current_round_configuration.is_playable_round: expected_resource_level = calculate_expected_resource_level(expected_resource_level, max_harvest_decision * 5) - for group in e.groups.all(): + for group in e.group_set.all(): self.assertEquals(get_resource_level(pgr.group).value, expected_resource_level) if e.has_next_round: @@ -107,14 +107,14 @@ e.start_round() current_round_data = e.current_round_data group_parameters = (get_regrowth_parameter(), get_group_harvest_parameter(), get_resource_level_parameter()) - for group in e.groups.select_related(depth=1).all(): + for group in e.group_set.select_related(depth=1).all(): for parameter in group_parameters: - group_data_value = group.data_values.get(round_data=current_round_data, parameter=parameter) + group_data_value = group.data_value_set.get(round_data=current_round_data, parameter=parameter) self.assertTrue(group_data_value.parameter in group_parameters) self.assertTrue(group_data_value) # single participant data parameter, harvest decisions - for pgr in group.participant_group_relationships.all(): - prdv = pgr.participant_data_values.get(round_data=current_round_data, + for pgr in group.participant_group_relationship_set.all(): + prdv = pgr.participant_data_value_set.get(round_data=current_round_data, parameter=get_harvest_decision_parameter()) self.assertTrue(prdv) self.assertEquals(prdv.parameter, get_harvest_decision_parameter()) @@ -124,12 +124,12 @@ # generate harvest decisions current_round_data = e.current_round_data harvest_decision_parameter = get_harvest_decision_parameter() - for group in e.groups.all(): + for group in e.group_set.all(): ds = get_harvest_decisions(group) - self.assertEquals(len(ds), group.participants.count()) - for p in group.participants.all(): + self.assertEquals(len(ds), group.participant_set.count()) + for p in group.participant_set.all(): pgr = ParticipantGroupRelationship.objects.get(participant=p, group=group) - pdv, created = current_round_data.participant_data_values.get_or_create( + pdv, created = current_round_data.participant_data_value_set.get_or_create( participant_group_relationship=pgr, parameter=harvest_decision_parameter) self.assertFalse(created) @@ -176,22 +176,22 @@ def test_get_set_resource_level(self): e = self.advance_to_data_round() e.start_round() - for group in e.groups.all(): + for group in e.group_set.all(): resource_level = get_resource_level(group) self.assertTrue(resource_level.pk > 0) self.assertEqual(resource_level.value, 100) resource_level.value = 3 resource_level.save() - for group in e.groups.all(): + for group in e.group_set.all(): resource_level = get_resource_level(group) self.assertEqual(resource_level.value, 3) - for group in e.groups.all(): + for group in e.group_set.all(): set_resource_level(group, 100) self.assertEqual(get_resource_level(group).value, 100) - for group in e.groups.all(): + for group in e.group_set.all(): resource_level = get_resource_level(group) self.assertEqual(resource_level.value, 100) @@ -201,7 +201,7 @@ for e in self.all_data_rounds(): self.assertNotEqual(current_round_data, e.current_round_data) current_round_data = e.current_round_data - for data_value in current_round_data.group_data_values.filter(parameter__name='resource_level'): + for data_value in current_round_data.group_data_value_set.filter(parameter__name='resource_level'): self.assertTrue(data_value.pk > 0) self.assertEqual('resource_level', data_value.parameter.name) data_value.value = 50 @@ -210,7 +210,7 @@ data_value.value = 100 data_value.save() self.assertEqual(100, data_value.value) - self.assertEqual(e.current_round_data.group_data_values.count(), GroupRoundDataValue.objects.filter(experiment=e, round_data=current_round_data).count()) + self.assertEqual(e.current_round_data.group_data_value_set.count(), GroupRoundDataValue.objects.filter(experiment=e, round_data=current_round_data).count()) self.assertEqual(e.parameters(scope=Parameter.GROUP_SCOPE).count(), 3) data_round_number += 1 @@ -231,7 +231,7 @@ for p in self.participants: pexpr = ParticipantExperimentRelationship.objects.get(participant=p, experiment=e) pgroupr = ParticipantGroupRelationship.objects.get(group__experiment=e, participant=p) - current_round_data.participant_data_values.create(participant_group_relationship=pgroupr, parameter=data_param, value=pexpr.sequential_participant_identifier * 2) + current_round_data.participant_data_value_set.create(participant_group_relationship=pgroupr, parameter=data_param, value=pexpr.sequential_participant_identifier * 2) return e def test_data_values(self): @@ -244,7 +244,7 @@ e = self.create_participant_data_values() current_round_data = e.current_round_data for p in self.participants: - participant_data_values = current_round_data.participant_data_values.filter(participant_group_relationship__participant=p) + participant_data_values = current_round_data.participant_data_value_set.filter(participant_group_relationship__participant=p) self.assertEqual(participant_data_values.count(), 1) pexpr = p.get_participant_experiment_relationship(e) logger.debug("relationship %s" % pexpr) --- a/vcweb/lighterprints/tests.py Wed Jul 06 12:16:47 2011 -0700 +++ b/vcweb/lighterprints/tests.py Wed Jul 06 22:03:24 2011 -0700 @@ -34,7 +34,7 @@ # initialize participant carbon savings for participant_group_relationship in ParticipantGroupRelationship.objects.filter(group__experiment=e): for activity in Activity.objects.all(): - activity_performed, created = participant_group_relationship.participant_data_values.get_or_create(round_data=current_round_data, parameter=parameter) + activity_performed, created = participant_group_relationship.participant_data_value_set.get_or_create(round_data=current_round_data, parameter=parameter) activity_performed.value = activity.pk logger.debug("activity performed %s (%s)", activity_performed, created) http://bitbucket.org/virtualcommons/vcweb/changeset/a24cd2f26036/ changeset: a24cd2f26036 user: alllee date: 2011-07-07 08:20:03 summary: fixing core tests affected #: 2 files (289 bytes) --- a/vcweb/core/models.py Wed Jul 06 22:03:24 2011 -0700 +++ b/vcweb/core/models.py Wed Jul 06 23:20:03 2011 -0700 @@ -158,7 +158,7 @@ return self.filter(status='ACTIVE') def increment_elapsed_time(self, status='ROUND_IN_PROGRESS', amount=60): - if status: + if status is not None: es = self.filter(status=status) es.update(current_round_elapsed_time=models.F('current_round_elapsed_time') + amount, total_elapsed_time=models.F('total_elapsed_time') + amount) @@ -449,8 +449,8 @@ return "%s_%s_%s.%s" % (slugify(self.experiment_metadata.title), self.pk, datetime.now().strftime("%d-%m-%y-%H%M"), file_ext) def parameters(self, scope=None): - ps = self.experiment_metadata.parameter_set - return ps.filter(scope=scope) if scope else ps + parameter_set = self.experiment_metadata.parameter_set + return parameter_set.filter(scope=scope) if scope else parameter_set def activate(self): if not self.is_active: --- a/vcweb/core/tests.py Wed Jul 06 22:03:24 2011 -0700 +++ b/vcweb/core/tests.py Wed Jul 06 23:20:03 2011 -0700 @@ -23,7 +23,7 @@ else: experiment = self.create_new_experiment(experiment_metadata, **kwargs) if experiment.participant_set.count() == 0: - experiment.setup_test_participants(email_suffix='asu.edu') + experiment.setup_test_participants(email_suffix='asu.edu', count=10) logger.debug("loaded %s", experiment) self.experiment = experiment return experiment @@ -157,8 +157,9 @@ def test_group_allocation(self): experiment = self.experiment experiment.allocate_groups(randomize=False) + logger.debug("experiment participants is %s", experiment.participant_set.all()) self.assertEqual(experiment.group_set.count(), 2, "there should be 2 groups after non-randomized allocation") - self.assertEqual( 10, sum([group.participant_set.count() for group in experiment.group_set]) ) + self.assertEqual( 10, sum([group.participant_set.count() for group in experiment.group_set.all()]) ) def test_participant_numbering(self): experiment = self.experiment @@ -189,7 +190,7 @@ self.assertTrue(total_elapsed_time == 0) delta = 120 Experiment.objects.increment_elapsed_time(status=experiment.status, amount=delta) - experiment = self.load_experiment() + experiment = Experiment.objects.get(pk=self.experiment.pk) self.assertEqual(experiment.current_round_elapsed_time, current_round_elapsed_time + delta) self.assertEqual(experiment.total_elapsed_time, total_elapsed_time + delta) @@ -259,11 +260,13 @@ """ g = self.create_new_group(max_size=10, experiment=self.experiment) count = 0; + logger.debug("self participants: %s (%s)", self.participants, len(self.participants)) for p in self.participants: - g.add_participant(p) + g = g.add_participant(p) count += 1 - self.assertTrue(g.participant_set) - self.assertEqual(g.participant_set.count(), count, "group.participants size should be %i" % count) + if count > 10: + count = count % 10 + self.assertEqual(g.participant_set.count(), count, "group.participant_set count should be %i" % count) self.assertEqual(g.size, count, "group size should be %i" % count) http://bitbucket.org/virtualcommons/vcweb/changeset/726d04f3f6f8/ changeset: 726d04f3f6f8 user: alllee date: 2011-07-07 08:53:36 summary: fixing more tests affected #: 3 files (46 bytes) --- a/vcweb/core/models.py Wed Jul 06 23:20:03 2011 -0700 +++ b/vcweb/core/models.py Wed Jul 06 23:53:36 2011 -0700 @@ -817,7 +817,7 @@ class Meta: ordering = ['name'] - unique_together = ['name', 'experiment_metadata', 'scope'] + unique_together = ('name', 'experiment_metadata', 'scope') class ParameterizedValue(models.Model): parameter = models.ForeignKey(Parameter) --- a/vcweb/core/tests.py Wed Jul 06 23:20:03 2011 -0700 +++ b/vcweb/core/tests.py Wed Jul 06 23:53:36 2011 -0700 @@ -40,6 +40,10 @@ def experimenter(self): return self.experiment.experimenter + @property + def participants(self): + return self.experiment.participant_set.all() + def create_new_experiment(self, experiment_metadata, experimenter=None): if experimenter is None: experimenter = Experimenter.objects.get(pk=1) @@ -52,7 +56,6 @@ def setUp(self): - self.participants = Participant.objects.all() self.load_experiment() def advance_to_data_round(self): --- a/vcweb/forestry/tests.py Wed Jul 06 23:20:03 2011 -0700 +++ b/vcweb/forestry/tests.py Wed Jul 06 23:53:36 2011 -0700 @@ -237,8 +237,8 @@ def test_data_values(self): e = self.create_participant_data_values() num_participant_parameters = e.parameters(scope=Parameter.PARTICIPANT_SCOPE).count() - self.assertEqual(e.participants.count() * num_participant_parameters, ParticipantRoundDataValue.objects.filter(experiment=e).count(), - 'There should be %s participants * %s total data parameters = %s' % (e.participants.count(), num_participant_parameters, e.participants.count() * num_participant_parameters)) + self.assertEqual(e.participant_set.count() * num_participant_parameters, ParticipantRoundDataValue.objects.filter(experiment=e).count(), + 'There should be %s participants * %s total data parameters = %s' % (e.participant_set.count(), num_participant_parameters, e.participant_set.count() * num_participant_parameters)) def test_data_value_conversion(self): e = self.create_participant_data_values() http://bitbucket.org/virtualcommons/vcweb/changeset/25be79f35772/ changeset: 25be79f35772 user: alllee date: 2011-07-07 09:46:37 summary: more test fixes, need to check views as well affected #: 3 files (231 bytes) --- a/vcweb/core/models.py Wed Jul 06 23:53:36 2011 -0700 +++ b/vcweb/core/models.py Thu Jul 07 00:46:37 2011 -0700 @@ -265,7 +265,7 @@ @property def participant_group_relationships(self): - for group in self.group_set .all(): + for group in self.group_set.all(): for pgr in group.participant_group_relationship_set.all(): yield pgr @@ -938,7 +938,7 @@ vs GroupRoundDataValue.objects.filter(group_round_data=self.current_round_data, parameter=parameter).update(**update_dict) ''' - updated_rows = self.data_values.filter(round_data=self.current_round_data, parameter=parameter).update(**update_dict) + updated_rows = self.data_value_set.filter(round_data=self.current_round_data, parameter=parameter).update(**update_dict) if updated_rows != 1: logger.error("Updated %s rows, should have been only one.", updated_rows) ''' @@ -949,7 +949,7 @@ def has_data_parameter(self, **kwargs): criteria = self._data_parameter_criteria(**kwargs) try: - self.data_values.get(**criteria) + self.data_value_set.get(**criteria) return True except: return False @@ -992,9 +992,9 @@ round_data = self.current_round_data if names: if name: names.append(name) - return self.data_values.filter(round_data=round_data, parameter__name__in=names) + return self.data_value_set.filter(round_data=round_data, parameter__name__in=names) elif name: - return self.data_values.get(round_data=round_data, parameter__name=name) + return self.data_value_set.get(round_data=round_data, parameter__name=name) else: logger.warning("Trying to retrieve data value by name with no args") return None @@ -1021,9 +1021,9 @@ logger.error("Trying to transfer parameter (%s: %s) past the last round of the experiment", parameter, value) return None - next_round_data, created = self.experiment.round_data.get_or_create(round_configuration=self.experiment.next_round) + next_round_data, created = self.experiment.round_data_set.get_or_create(round_configuration=self.experiment.next_round) logger.debug("next round data: %s (%s)", next_round_data, created) - group_data_value, created = next_round_data.group_data_values.get_or_create(group=self, parameter=parameter, defaults={'value': value}) + group_data_value, created = next_round_data.group_data_value_set.get_or_create(group=self, parameter=parameter, defaults={'value': value}) logger.debug("group data value: %s (%s)", group_data_value, created) if not created: group_data_value.value = value --- a/vcweb/forestry/models.py Wed Jul 06 23:53:36 2011 -0700 +++ b/vcweb/forestry/models.py Thu Jul 07 00:46:37 2011 -0700 @@ -138,10 +138,12 @@ max_resource_level = 100 for group in experiment.group_set.all(): # FIXME: simplify logic + logger.debug("group %s has resource level", group) if has_resource_level(group): 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() ]) + logger.debug("total harvest for playable round: %d", 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)) set_group_harvest(group, total_harvest) --- a/vcweb/forestry/tests.py Wed Jul 06 23:53:36 2011 -0700 +++ b/vcweb/forestry/tests.py Thu Jul 07 00:46:37 2011 -0700 @@ -81,17 +81,18 @@ e.current_round_sequence_number) expected_resource_level = get_initial_resource_level(current_round_configuration) - max_harvest_decision = get_max_harvest_decision(expected_resource_level) - for pgr in e.participant_group_relationships: - self.assertEquals(get_resource_level(pgr.group).value, expected_resource_level) - set_harvest_decision(pgr, max_harvest_decision) - e.end_round() + if current_round_configuration.is_playable_round: + max_harvest_decision = get_max_harvest_decision(expected_resource_level) + for pgr in e.participant_group_relationships: + self.assertEquals(get_resource_level(pgr.group).value, expected_resource_level) + set_harvest_decision(pgr, max_harvest_decision) - if current_round_configuration.is_playable_round: expected_resource_level = calculate_expected_resource_level(expected_resource_level, max_harvest_decision * 5) + e.end_round() for group in e.group_set.all(): - self.assertEquals(get_resource_level(pgr.group).value, expected_resource_level) + logger.debug("checking group: %s", group) + self.assertEquals(get_resource_level(group).value, expected_resource_level) if e.has_next_round: e.advance_to_next_round() http://bitbucket.org/virtualcommons/vcweb/changeset/38515f4d9f88/ changeset: 38515f4d9f88 user: alllee date: 2011-07-07 10:03:20 summary: view fixes for related_name / x_set convention refactoring affected #: 7 files (132 bytes) --- a/vcweb/core/ajax.py Thu Jul 07 00:46:37 2011 -0700 +++ b/vcweb/core/ajax.py Thu Jul 07 01:03:20 2011 -0700 @@ -112,6 +112,6 @@ 'status': status_block, 'experimentData': data_block, 'active_round_number': experiment.current_round_sequence_number, - 'round_data_count': experiment.round_data.count(), + 'round_data_count': experiment.round_data_set.count(), 'error_message': error_message, }) --- a/vcweb/core/models.py Thu Jul 07 00:46:37 2011 -0700 +++ b/vcweb/core/models.py Thu Jul 07 01:03:20 2011 -0700 @@ -321,7 +321,7 @@ @property def playable_round_data(self): - return self.round_data.select_related(depth=1).filter(round_configuration__round_type__in=RoundConfiguration.PLAYABLE_ROUND_CONFIGURATIONS, + return self.round_data_set.select_related(depth=1).filter(round_configuration__round_type__in=RoundConfiguration.PLAYABLE_ROUND_CONFIGURATIONS, round_configuration__sequence_number__lte=self.current_round_sequence_number) @property @@ -908,7 +908,7 @@ @property def current_round_data_values(self): - return self.current_round_data.group_data_values + return self.current_round_data.group_data_value_set @property def is_full(self): --- a/vcweb/core/templates/experimenter/dashboard.html Thu Jul 07 00:46:37 2011 -0700 +++ b/vcweb/core/templates/experimenter/dashboard.html Thu Jul 07 01:03:20 2011 -0700 @@ -45,20 +45,18 @@ {% for e in experiments %} <div class='notice ui-corner-all'> {{e.status_line}} + <span style='float:right; padding: 3px;' class='ui-state-highlight'><b>{{e.participant_set.count}} registered participants</b></span><ul class='horizontal experiment-menu'> - <li><span style='padding: 3px;' class='ui-state-highlight'><b>{{e.participants.count}} registered participants</b></span></li><li><a title='Monitor and control this experiment' href='{{e.monitor_url}}'><img src='{{STATIC_URL}}images/famfamfam/zoom.png' alt='General experiment monitoring interface'/> monitor</a></li><li><a class='confirm-experiment-action' title='Creates a new copy of this experiment with the exact same configuration but no registered participants.' href='{{e.clone_url}}'><img src='{{STATIC_URL}}images/famfamfam/page_copy.png' alt='Clone experiment'/> clone</a></li> - {% if e.participants.count == 0 %} - {% comment %} + {% if e.participant_set.count == 0 %} <li><a title='Register participants for this experiment with actual email addresses' href='{{e.controller_url}}/register-email-list'><img src='{{STATIC_URL}}images/famfamfam/group_add.png' alt='register'/> register participants by email</a></li> - {% endcomment %} <li><a title='Register participants for this experiment with fake email addresses by providing an email suffix and the number of participants.' href='{{e.controller_url}}/register-simple'> --- a/vcweb/core/templates/experimenter/monitor.html Thu Jul 07 00:46:37 2011 -0700 +++ b/vcweb/core/templates/experimenter/monitor.html Thu Jul 07 01:03:20 2011 -0700 @@ -63,7 +63,7 @@ } $(function() { var experimentMessageDiv = document.getElementById('experiment-messages'); - registerCallbacks({{ experiment.round_data.count }}, {{ experiment.current_round.sequence_number }}); + registerCallbacks({{ experiment.round_data_set.count }}, {{ experiment.current_round.sequence_number }}); // socket.io connection // FIXME: add auth var s = connect('experimenter/{{request.user.experimenter.pk}}'); @@ -196,7 +196,7 @@ </div><div id='experimentData'> {% block data %} - {% for round_data in experiment.round_data.all reversed %} + {% for round_data in experiment.round_data_set.all reversed %} <h3><a href='#'>{{ round_data }}</a></h3><div id='round_data_{{forloop.counter}}'> {% if round_data.group_data_values.count > 0 %} --- a/vcweb/core/views.py Thu Jul 07 00:46:37 2011 -0700 +++ b/vcweb/core/views.py Thu Jul 07 01:03:20 2011 -0700 @@ -300,7 +300,7 @@ writer = unicodecsv.UnicodeWriter(response) writer.writerow(['Group', 'Members']) for group in experiment.groups.all(): - writer.writerow(itertools.chain.from_iterable([[group], group.participants.all()])) + writer.writerow(itertools.chain.from_iterable([[group], group.participant_set.all()])) for round_data in experiment.round_data.all(): round_configuration = round_data.round_configuration # write out group-wide data values @@ -338,8 +338,8 @@ current_row = 0 group_sheet.write(0, 0, 'Group') group_sheet.write(0, 1, 'Participant') - for group in experiment.groups.all(): - for participant in group.participants.all(): + for group in experiment.group_set.all(): + for participant in group.participant_set.all(): group_sheet.write(current_row, 0, group) group_sheet.write(current_row, 1, participant) current_row += 1 --- a/vcweb/forestry/templates/forestry/manage-experiment.html Thu Jul 07 00:46:37 2011 -0700 +++ b/vcweb/forestry/templates/forestry/manage-experiment.html Thu Jul 07 01:03:20 2011 -0700 @@ -14,8 +14,7 @@ <a href='#'>view data</a> | <a href='#'>download data</a></div> - {% if experiment.groups.count > 0 %} - {% for group in experiment.groups.all %} + {% for group in experiment.group_set.all %} <h3> {{ group }} </h3><div class='participants'><table> @@ -23,7 +22,7 @@ <th>Participant</th><th>Round</th><th>Parameter</th><th>Value</th></thead><tbody> - {% for participant in group.participants.all %} + {% for participant in group.participant_set.all %} {% endfor %} </tbody> @@ -37,10 +36,9 @@ {% endfor %} </ul></div> + {% empty %} + <div class='info'>Groups have not been allocated yet.</div> {% endfor %} - {% else %} - <div class='info'>Groups have not been allocated yet.</div> - {% endif %} </fieldset></p> --- a/vcweb/sanitation/templates/sanitation/configure.html Thu Jul 07 00:46:37 2011 -0700 +++ b/vcweb/sanitation/templates/sanitation/configure.html Thu Jul 07 01:03:20 2011 -0700 @@ -74,7 +74,7 @@ <th>Participant</th><th>Round</th><th>Parameter</th><th>Value</th></thead><tbody> - {% for participant in group.participants.all %} + {% for participant in group.participant_set.all %} {% endfor %} </tbody></table> Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <iss...@bi...> - 2011-07-06 20:43:08
|
--- you can reply above this line --- New issue 26: internationalization / localization https://bitbucket.org/virtualcommons/vcweb/issue/26/internationalization-localization A Lee / alllee on Wed, 6 Jul 2011 22:43:02 +0200: Description: Provide veronika with english text to be translated to slovak and work out internationalization in django Responsible: alllee -- This is an issue notification from bitbucket.org. You are receiving this either because you are the owner of the issue, or you are following the issue. |
From: Bitbucket <iss...@bi...> - 2011-07-06 20:05:59
|
--- you can reply above this line --- New issue 25: implement server endpoints for lighter footprints https://bitbucket.org/virtualcommons/vcweb/issue/25/implement-server-endpoints-for-lighter A Lee / alllee on Wed, 6 Jul 2011 22:05:53 +0200: Description: # available activities for participant X in experiment Y (or, more cleanly, participant_experiment_relationship.pk) # group discussion board / activity stream # post endpoints for adding to discussion board + performing an activity Responsible: alllee -- This is an issue notification from bitbucket.org. You are receiving this either because you are the owner of the issue, or you are following the issue. |
From: Bitbucket <iss...@bi...> - 2011-07-06 20:00:43
|
--- you can reply above this line --- New issue 24: follow django conventions for related_name https://bitbucket.org/virtualcommons/vcweb/issue/24/follow-django-conventions-for-related_name A Lee / alllee on Wed, 6 Jul 2011 22:00:37 +0200: Description: See http://stackoverflow.com/questions/6601626/django-many-to-many-relationships-prevailing-naming-convention Responsible: alllee -- This is an issue notification from bitbucket.org. You are receiving this either because you are the owner of the issue, or you are following the issue. |
From: Bitbucket <com...@bi...> - 2011-07-06 19:16:46
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/e738a1174e1a/ changeset: e738a1174e1a user: alllee date: 2011-07-06 21:16:47 summary: adding ActivityAvailability to admin site affected #: 2 files (173 bytes) --- a/vcweb/lighterprints/admin.py Sat Jul 02 20:24:09 2011 -0700 +++ b/vcweb/lighterprints/admin.py Wed Jul 06 12:16:47 2011 -0700 @@ -2,6 +2,7 @@ registering django models with django admin ''' from django.contrib import admin -from vcweb.lighterprints.models import Activity +from vcweb.lighterprints.models import Activity, ActivityAvailability admin.site.register(Activity) +admin.site.register(ActivityAvailability) --- a/vcweb/lighterprints/models.py Sat Jul 02 20:24:09 2011 -0700 +++ b/vcweb/lighterprints/models.py Wed Jul 06 12:16:47 2011 -0700 @@ -26,6 +26,11 @@ def icon_name(self): return self.name + @property + def icon_url(self): + # FIXME: implement as return "/activity/id/icon" + pass + def __unicode__(self): return u'%s (+%s)' % (self.label, self.savings) Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-07-03 03:24:13
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/e244563c9e25/ changeset: e244563c9e25 user: alllee date: 2011-07-03 05:24:09 summary: updating and refactoring test harness a bit, getting rid of hard-coded Forestry experiment details in BaseVcwebTest affected #: 4 files (1.9 KB) --- a/vcweb/core/models.py Sat Jul 02 12:01:24 2011 -0700 +++ b/vcweb/core/models.py Sat Jul 02 20:24:09 2011 -0700 @@ -398,10 +398,10 @@ for user in users: (p, created) = Participant.objects.get_or_create(user=user) # FIXME: instead of asking for the email suffix, perhaps we just append the institution URL to keep it simpler? - p.institution = institution - p.save() - ParticipantExperimentRelationship.objects.create(participant=p, experiment=self, - created_by=self.experimenter.user) + if institution and p.institution != institution: + p.institution = institution + p.save() + ParticipantExperimentRelationship.objects.create(participant=p, experiment=self, created_by=self.experimenter.user) ''' hardcoded defaults for the slovakia pretest ''' @@ -586,8 +586,7 @@ 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') + experiment_configuration = models.ForeignKey(ExperimentConfiguration, related_name='round_configurations') sequence_number = models.PositiveIntegerField(help_text='Used internally to determine the ordering of the rounds in an experiment in ascending order, e.g., 1,2,3,4,5') display_number = models.PositiveIntegerField(default=0, help_text='The round number to be displayed with this round. If set to zero, defaults to the internally used sequence_number.') @@ -721,21 +720,6 @@ def get_by_natural_key(self, key): return self.get(name=key) - ''' - name_cache = {} - def get(self, *args, **kwargs): - if 'name' in kwargs: - # check cache - name = kwargs['name'] - if name in self.name_cache: - return self.name_cache[name] - parameter = super(ParameterManager, self).get(*args, **kwargs) - self.name_cache[name] = parameter - return parameter - else: - return super(ParameterManager, self).get(*args, **kwargs) - ''' - class Parameter(models.Model): PARAMETER_TYPES = (('int', 'Integer value'), ('string', 'String value'), --- a/vcweb/core/tests.py Sat Jul 02 12:01:24 2011 -0700 +++ b/vcweb/core/tests.py Sat Jul 02 20:24:09 2011 -0700 @@ -16,16 +16,44 @@ """ fixtures = ['test_users_participants', 'forestry_test_data'] - def load_experiment(self): - self.experiment = Experiment.objects.get(pk=1) - return self.experiment + def load_experiment(self, experiment_metadata=None, **kwargs): + if experiment_metadata is None: +# default to the Forestry experiment if no metadata is passed in + experiment = Experiment.objects.get(pk=1).clone() + else: + experiment = self.create_new_experiment(experiment_metadata, **kwargs) + if experiment.participants.count() == 0: + experiment.setup_test_participants(email_suffix='asu.edu') + logger.debug("loaded %s", experiment) + self.experiment = experiment + return experiment + + @property + def experiment_metadata(self): + return self.experiment.experiment_metadata + + @property + def experiment_configuration(self): + return self.experiment.experiment_configuration + + @property + def experimenter(self): + return self.experiment.experimenter + + def create_new_experiment(self, experiment_metadata, experimenter=None): + if experimenter is None: + experimenter = Experimenter.objects.get(pk=1) + experiment_configuration = ExperimentConfiguration.objects.create(experiment_metadata=experiment_metadata, + name='Test Experiment Configuration', creator=experimenter) + for index in xrange(1, 10): + experiment_configuration.round_configurations.create(sequence_number=index) + return Experiment.objects.create(experimenter=self.experimenter, + experiment_metadata=experiment_metadata, experiment_configuration=experiment_configuration) + def setUp(self): self.participants = Participant.objects.all() self.load_experiment() - self.experimenter = Experimenter.objects.get(pk=1) - self.experiment_metadata = ExperimentMetadata.objects.get(pk=1) - self.experiment_configuration = ExperimentConfiguration.objects.get(pk=1) def advance_to_data_round(self): self.experiment.activate() @@ -48,11 +76,6 @@ template_name=template_name ) - def create_new_experiment(self): - return Experiment.objects.create(experimenter=self.experimenter, - experiment_configuration=self.experiment_configuration, - experiment_metadata=self.experiment_metadata) - def create_new_parameter(self, name='vcweb.test.parameter', scope='EXPERIMENT_SCOPE', parameter_type='string'): return self.experiment_metadata.parameters.create(creator=self.experimenter, name=name, scope=scope, type=parameter_type) @@ -249,7 +272,7 @@ def test_participant_identifier(self): """ exercises the generation of participant_identifier """ - e = self.create_new_experiment() + e = self.experiment.clone() for p in self.participants: per = ParticipantExperimentRelationship.objects.create(participant=p, experiment=e, created_by=self.experimenter.user) --- a/vcweb/lighterprints/models.py Sat Jul 02 12:01:24 2011 -0700 +++ b/vcweb/lighterprints/models.py Sat Jul 02 20:24:09 2011 -0700 @@ -1,7 +1,7 @@ from django.db import models from django.db.models import Sum from vcweb.core import signals, simplecache -from vcweb.core.models import Experiment, ExperimentMetadata, GroupRoundDataValue +from vcweb.core.models import Experiment, ExperimentMetadata, Experimenter, GroupRoundDataValue, Parameter from django.dispatch import receiver import datetime @@ -41,6 +41,18 @@ def get_lighterprints_experiment_metadata(): return ExperimentMetadata.objects.get(namespace='lighterprints') +@simplecache +def create_activity_performed_parameter(experimenter=None): + if experimenter is None: + experimenter = Experimenter.objects.get(pk=1) + parameter, created = Parameter.objects.get_or_create(name='activity_performed', scope=Parameter.PARTICIPANT_SCOPE, type='int', + creator=experimenter, experiment_metadata=get_lighterprints_experiment_metadata()) + return parameter + +@simplecache +def get_activity_performed_parameter(): + return Parameter.objects.get(name='activity_performed') + def get_active_experiments(): return Experiment.objects.filter(experiment_metadata=get_lighterprints_experiment_metadata(), status__in=('ACTIVE', 'ROUND_IN_PROGRESS')) --- a/vcweb/lighterprints/tests.py Sat Jul 02 12:01:24 2011 -0700 +++ b/vcweb/lighterprints/tests.py Sat Jul 02 20:24:09 2011 -0700 @@ -1,20 +1,20 @@ -from django.test import TestCase from django.test.client import RequestFactory, Client -from vcweb.core.models import Experiment, Experimenter +from vcweb.core.tests import BaseVcwebTest +from vcweb.core.models import ParticipantGroupRelationship from vcweb.lighterprints.views import * from vcweb.lighterprints.models import * import logging logger = logging.getLogger(__name__) -class BaseTest(TestCase): +class BaseTest(BaseVcwebTest): def setUp(self): + super(BaseTest, self).setUp() self.client = Client() self.factory = RequestFactory() - self.experimenter = Experimenter.objects.get(pk=1) - self.experiment = Experiment.objects.create(experimenter=self.experimenter, - experiment_metadata=get_lighterprints_experiment_metadata()) + experiment_metadata = get_lighterprints_experiment_metadata() + self.load_experiment(experiment_metadata=experiment_metadata) class ActivityViewTest(BaseTest): @@ -30,11 +30,11 @@ e.activate() e.start_round() current_round_data = e.current_round_data - parameter = get_activity_performed_parameter() + parameter = create_activity_performed_parameter() # initialize participant carbon savings for participant_group_relationship in ParticipantGroupRelationship.objects.filter(group__experiment=e): for activity in Activity.objects.all(): - activity_performed, created = participant_group_relationship.participant_data_values.get_or_create(round_data=current_round_data, - parameter=parameter, value=activity.pk) + activity_performed, created = participant_group_relationship.participant_data_values.get_or_create(round_data=current_round_data, parameter=parameter) + activity_performed.value = activity.pk logger.debug("activity performed %s (%s)", activity_performed, created) Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-07-02 19:01:36
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/3378ce24bbd8/ changeset: 3378ce24bbd8 user: alllee date: 2011-07-02 21:01:24 summary: removing broken tests in forestry caused by Experiment.advance_to_next_round changes (invokes start_round automatically, transferring parameters, etc.). Should revisit / reimplement later. affected #: 6 files (2.2 KB) --- a/vcweb/core/models.py Fri Jul 01 15:34:13 2011 -0700 +++ b/vcweb/core/models.py Sat Jul 02 12:01:24 2011 -0700 @@ -25,10 +25,7 @@ @receiver(signals.minute_tick, sender=None) def minute_tick_handler(sender, time=None, **kwargs): """ - tick handlers. handles each minute tick. Might rethink this and use timed / - delayed tasks in celery execute at the end of each round for controlled - experiments and for longer-scale experiments use 1 minute granularity for - performance sake. + handles each minute tick """ logger.debug("handling minute tick signal at %s with kwargs %s", time, kwargs) # inspect all active experiments and update their time left @@ -1297,12 +1294,15 @@ """ class ParticipantRoundDataValue(DataValue): round_data = models.ForeignKey(RoundData, related_name='participant_data_values') - participant_group_relationship = models.ForeignKey(ParticipantGroupRelationship, related_name='round_data_values') + participant_group_relationship = models.ForeignKey(ParticipantGroupRelationship, related_name='participant_data_values') submitted = models.BooleanField(default=False) def __init__(self, *args, **kwargs): super(ParticipantRoundDataValue, self).__init__(*args, **kwargs) - if not hasattr(self, 'experiment'): + if 'experiment' in kwargs and not hasattr(self, 'round_data'): + self.experiment = kwargs['experiment'] + self.round_data = self.experiment.current_round_data + elif not hasattr(self, 'experiment'): self.experiment = self.round_data.experiment @property --- a/vcweb/core/tests.py Fri Jul 01 15:34:13 2011 -0700 +++ b/vcweb/core/tests.py Sat Jul 02 12:01:24 2011 -0700 @@ -8,12 +8,12 @@ logger = logging.getLogger(__name__) -""" -base class for vcweb.core tests, sets up test fixtures for participants, -forestry_test_data, and a number of participants, experiments, etc., -based on the forestry experiment -""" class BaseVcwebTest(TestCase): + """ + base class for vcweb.core tests, sets up test fixtures for participants, + forestry_test_data, and a number of participants, experiments, etc., + based on the forestry experiment + """ fixtures = ['test_users_participants', 'forestry_test_data'] def load_experiment(self): @@ -165,10 +165,11 @@ self.assertTrue(current_round_elapsed_time == 0) total_elapsed_time = experiment.total_elapsed_time self.assertTrue(total_elapsed_time == 0) - Experiment.objects.increment_elapsed_time(status=experiment.status) + delta = 120 + Experiment.objects.increment_elapsed_time(status=experiment.status, amount=delta) experiment = self.load_experiment() - self.assertEqual(experiment.current_round_elapsed_time, current_round_elapsed_time + 1) - self.assertEqual(experiment.total_elapsed_time, total_elapsed_time + 1) + self.assertEqual(experiment.current_round_elapsed_time, current_round_elapsed_time + delta) + self.assertEqual(experiment.total_elapsed_time, total_elapsed_time + delta) def test_instructions_round_parameters(self): e = self.experiment --- a/vcweb/forestry/tests.py Fri Jul 01 15:34:13 2011 -0700 +++ b/vcweb/forestry/tests.py Sat Jul 02 12:01:24 2011 -0700 @@ -37,8 +37,7 @@ ds = get_harvest_decisions(group) self.verify_resource_level(group) self.assertEqual(len(ds), group.participants.count()) - for p in group.participants.all(): - pgr = ParticipantGroupRelationship.objects.get(group=group, participant=p) + for pgr in group.participant_group_relationships.all(): pdv = ParticipantRoundDataValue.objects.get( parameter=harvest_decision_parameter, participant_group_relationship=pgr, @@ -46,27 +45,9 @@ ) self.assertTrue(pdv.pk > 0) self.assertFalse(pdv.value) - pdv.value = group.number % 5 + pdv.value = 5 pdv.save() - end_round_func(e) - ''' - at round end all harvest decisions are tallied and subtracted from - the final resource_level - ''' - def expected_resource_level(group): - after_harvests = 100 - ((group.number % 5) * group.size) - after_regrowth = min(after_harvests + (after_harvests / 10), 100) - return after_regrowth - - for group in e.groups.all(): - self.assertEqual(get_resource_level(group).value, - expected_resource_level(group)) - - e.advance_to_next_round() - for group in e.groups.all(): - resource_level = get_resource_level(group) - self.assertEqual(resource_level.value, expected_resource_level(group)) def test_round_ended(self): e = self.test_round_setup() @@ -133,7 +114,7 @@ self.assertTrue(group_data_value) # single participant data parameter, harvest decisions for pgr in group.participant_group_relationships.all(): - prdv = pgr.round_data_values.get(round_data=current_round_data, + prdv = pgr.participant_data_values.get(round_data=current_round_data, parameter=get_harvest_decision_parameter()) self.assertTrue(prdv) self.assertEquals(prdv.parameter, get_harvest_decision_parameter()) @@ -145,12 +126,13 @@ harvest_decision_parameter = get_harvest_decision_parameter() for group in e.groups.all(): ds = get_harvest_decisions(group) - self.assertFalse(ds, 'there should not be any harvest decisions.') + self.assertEquals(len(ds), group.participants.count()) for p in group.participants.all(): pgr = ParticipantGroupRelationship.objects.get(participant=p, group=group) - pdv = current_round_data.participant_data_values.create( + pdv, created = current_round_data.participant_data_values.get_or_create( participant_group_relationship=pgr, parameter=harvest_decision_parameter) + self.assertFalse(created) self.assertTrue(pdv.pk > 0) self.assertFalse(pdv.value) pdv.value = 3 @@ -220,18 +202,14 @@ self.assertNotEqual(current_round_data, e.current_round_data) current_round_data = e.current_round_data 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.assertTrue(data_value.pk > 0) - self.assertFalse(data_value.value) - data_value.value = 100 - data_value.save() - self.assertEqual(100, data_value.value) self.assertEqual('resource_level', data_value.parameter.name) data_value.value = 50 data_value.save() self.assertEqual(50, data_value.value) - + data_value.value = 100 + data_value.save() + self.assertEqual(100, data_value.value) self.assertEqual(e.current_round_data.group_data_values.count(), GroupRoundDataValue.objects.filter(experiment=e, round_data=current_round_data).count()) self.assertEqual(e.parameters(scope=Parameter.GROUP_SCOPE).count(), 3) data_round_number += 1 @@ -280,4 +258,4 @@ self.assertFalse(dv.float_value) e.advance_to_next_round() current_round_data = e.current_round_data - self.assertEqual(0, ParticipantRoundDataValue.objects.filter(round_data=current_round_data).count()) + self.assertEqual(10, ParticipantRoundDataValue.objects.filter(round_data=current_round_data).count()) --- a/vcweb/lighterprints/management.py Fri Jul 01 15:34:13 2011 -0700 +++ b/vcweb/lighterprints/management.py Sat Jul 02 12:01:24 2011 -0700 @@ -7,7 +7,7 @@ import logging logger = logging.getLogger(__name__) -@receiver(post_syncdb, sender=vcweb.core.models, dispatch_uid='sanitation_metadata_creator') +@receiver(post_syncdb, sender=vcweb.core.models, dispatch_uid='lighterprints_metadata_creator') def post_syncdb_handler(sender, **kwargs): ''' creates the forestry ExperimentMetadata record if not already created. --- a/vcweb/lighterprints/models.py Fri Jul 01 15:34:13 2011 -0700 +++ b/vcweb/lighterprints/models.py Sat Jul 02 12:01:24 2011 -0700 @@ -1,6 +1,6 @@ from django.db import models from django.db.models import Sum -from vcweb.core import signals +from vcweb.core import signals, simplecache from vcweb.core.models import Experiment, ExperimentMetadata, GroupRoundDataValue from django.dispatch import receiver import datetime @@ -37,8 +37,12 @@ available_start_time = models.TimeField(null=True, blank=True) available_end_time = models.TimeField(null=True, blank=True) +@simplecache +def get_lighterprints_experiment_metadata(): + return ExperimentMetadata.objects.get(namespace='lighterprints') + def get_active_experiments(): - return Experiment.objects.filter(experiment_metadata=ExperimentMetadata.objects.get(name='lighterprints'), + return Experiment.objects.filter(experiment_metadata=get_lighterprints_experiment_metadata(), status__in=('ACTIVE', 'ROUND_IN_PROGRESS')) @receiver(signals.midnight_tick) --- a/vcweb/lighterprints/tests.py Fri Jul 01 15:34:13 2011 -0700 +++ b/vcweb/lighterprints/tests.py Sat Jul 02 12:01:24 2011 -0700 @@ -1,15 +1,20 @@ +from django.test import TestCase from django.test.client import RequestFactory, Client -from vcweb.core.tests import BaseVcwebTest +from vcweb.core.models import Experiment, Experimenter from vcweb.lighterprints.views import * +from vcweb.lighterprints.models import * import logging logger = logging.getLogger(__name__) -class BaseTest(BaseVcwebTest): +class BaseTest(TestCase): def setUp(self): self.client = Client() self.factory = RequestFactory() + self.experimenter = Experimenter.objects.get(pk=1) + self.experiment = Experiment.objects.create(experimenter=self.experimenter, + experiment_metadata=get_lighterprints_experiment_metadata()) class ActivityViewTest(BaseTest): @@ -18,3 +23,18 @@ logger.debug("response is: %s", response) self.assertEqual(response.status_code, 200) + +class UpdateLevelTest(BaseTest): + def test_daily_carbon_savings(self): + e = self.experiment + e.activate() + e.start_round() + current_round_data = e.current_round_data + parameter = get_activity_performed_parameter() +# initialize participant carbon savings + for participant_group_relationship in ParticipantGroupRelationship.objects.filter(group__experiment=e): + for activity in Activity.objects.all(): + activity_performed, created = participant_group_relationship.participant_data_values.get_or_create(round_data=current_round_data, + parameter=parameter, value=activity.pk) + logger.debug("activity performed %s (%s)", activity_performed, created) + Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-07-01 22:34:21
|
2 new changesets in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/3372fa4da8a0/ changeset: 3372fa4da8a0 user: alllee date: 2011-06-30 23:14:36 summary: pushing djcelery loading to the end of settings.py so that settings_local.py configuration can be modify it affected #: 4 files (406 bytes) --- a/vcweb/README Thu Jun 30 11:31:53 2011 -0700 +++ b/vcweb/README Thu Jun 30 14:14:36 2011 -0700 @@ -25,7 +25,6 @@ To start up celeryd and celerybeat -./manage.py celeryd -./manage.py celerybeat +./manage.py celeryd -B -(or fab celeryd / celerybeat) +(or fab celeryd) --- a/vcweb/core/signals.py Thu Jun 30 11:31:53 2011 -0700 +++ b/vcweb/core/signals.py Thu Jun 30 14:14:36 2011 -0700 @@ -6,6 +6,7 @@ round_ended = Signal(providing_args=['experiment', 'time', 'round_configuration']) minute_tick = Signal(providing_args=['time']) hour_tick = Signal(providing_args=['time']) +midnight_tick = Signal(providing_args=['time']) post_login = Signal(providing_args=['user']) post_logout = Signal(providing_args=['user']) --- a/vcweb/core/tasks.py Thu Jun 30 11:31:53 2011 -0700 +++ b/vcweb/core/tasks.py Thu Jun 30 14:14:36 2011 -0700 @@ -1,4 +1,5 @@ from celery.decorators import periodic_task +from celery.schedules import crontab from datetime import datetime, timedelta from vcweb.core import signals @@ -10,6 +11,11 @@ # use signal or just update experiment instance models directly here? signals.minute_tick.send(sender=None, time=datetime.now()) -@periodic_task(run_every=timedelta(seconds=3600), ignore_result=True) +@periodic_task(run_every=crontab(hour="*", minute="0", day_of_week="*")) def every_hour(): signals.hour_tick.send(sender=None, time=datetime.now()) + +@periodic_task(run_every=crontab(hour="0", minute="0", day_of_week="*")) +def at_midnight(): + signals.midnight_tick.send(sender=None, time=datetime.now()) + --- a/vcweb/settings.py Thu Jun 30 11:31:53 2011 -0700 +++ b/vcweb/settings.py Thu Jun 30 14:14:36 2011 -0700 @@ -1,4 +1,4 @@ -# Django settings for vcweb project. +from django.contrib import messages from os import path, makedirs import sys @@ -8,7 +8,6 @@ ADMINS = ( ('Allen Lee', 'all...@as...') - # ('Your Name', 'you...@do...'), ) MANAGERS = ADMINS @@ -113,21 +112,15 @@ # socket.io configuration SOCKET_IO_PORT = 8882; -# celery configuration -BROKER_BACKEND = "djkombu.transport.DatabaseTransport" -# rabbitmq/amqp celery config -BROKER_HOST = "localhost" -BROKER_PORT = 5672 -BROKER_USER = "vcweb" -BROKER_PASSWORD = 'override this in settings_local.py' -BROKER_VHOST = "vcweb.vhost" - # celerybeat configuration CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' CELERYBEAT_MAX_LOOP_INTERVAL = 5 CELERYBEAT_LOG_FILE = 'celerybeat.log' CELERYBEAT_LOG_LEVEL = 'ERROR' +# simplest celery transport that uses Django database (djkombu_messages) +BROKER_BACKEND = "djkombu.transport.DatabaseTransport" + # activation window ACCOUNT_ACTIVATION_DAYS = 30 @@ -142,11 +135,8 @@ path.join(path.abspath(path.dirname(__file__)), 'static').replace('\\', '/'), ) -import djcelery -djcelery.setup_loader() # set up jquery-ui css classes for django messages -from django.contrib import messages MESSAGE_TAGS = { messages.constants.INFO : 'ui-state-highlight ui-corner-all', messages.constants.WARNING: 'ui-state-error ui-corner-all', @@ -166,7 +156,6 @@ # logging configuration VCWEB_LOG_FILENAME = 'vcweb.log' TORNADIO_LOG_FILENAME = 'tornadio.log' - LOGGING = { 'version': 1, 'disable_existing_loggers': True, @@ -235,3 +224,8 @@ } } +# this is the last thing to happen so we can override django-celery configuration +# settings +import djcelery +djcelery.setup_loader() + http://bitbucket.org/virtualcommons/vcweb/changeset/5ff788ffd730/ changeset: 5ff788ffd730 user: alllee date: 2011-07-02 00:34:13 summary: first cut at lighter prints group update logic, still needs a lot of work affected #: 4 files (2.7 KB) --- a/vcweb/core/models.py Thu Jun 30 14:14:36 2011 -0700 +++ b/vcweb/core/models.py Fri Jul 01 15:34:13 2011 -0700 @@ -870,10 +870,10 @@ return u"{0} -> [{1}: {2}]".format(self.round_configuration, self.parameter, self.value) -""" -A DataValue is used by Groups and Participants. GroupRoundData -""" class DataValue(ParameterizedValue): + """ + Supertype for GroupRoundDataValue and ParticipantRoundDataValue + """ experiment = models.ForeignKey(Experiment) def __unicode__(self): @@ -886,7 +886,7 @@ number = models.PositiveIntegerField() ''' internal numbering unique to the given experiment ''' max_size = models.PositiveIntegerField(default=5) - """ + """ how many members can this group hold at a maximum? Could be specified as a RoundParameterValue / ExperimentConfiguration value """ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vcweb/lighterprints/management.py Fri Jul 01 15:34:13 2011 -0700 @@ -0,0 +1,30 @@ +from django.dispatch import receiver +from django.db.models.signals import post_syncdb +from vcweb.core.models import ExperimentMetadata +import vcweb +from datetime import datetime + +import logging +logger = logging.getLogger(__name__) + +@receiver(post_syncdb, sender=vcweb.core.models, dispatch_uid='sanitation_metadata_creator') +def post_syncdb_handler(sender, **kwargs): + ''' + creates the forestry ExperimentMetadata record if not already created. + FIXME: what are pros/cons for doing it this way vs adding it to initial_data.json + pros: + 1. don't have to hard-code pks and pk references.. + cons: + 1. have to invoke syncdb in order to get this to run + ''' + experiment_metadata_dict = { + "about_url": "http://commons.asu.edu", + "description": "A mobile-ready HTML5 experiment / game that educates and examines how groups of people coordinate to reach carbon emission targets.", + "namespace": "lighterprints", + "title": "Lighter Footprints", + "date_created": datetime.now() + } + experiment_metadata, created = ExperimentMetadata.objects.get_or_create(**experiment_metadata_dict) + logger.debug("experiment metadata: %s (%s)", experiment_metadata, created) + + --- a/vcweb/lighterprints/models.py Thu Jun 30 14:14:36 2011 -0700 +++ b/vcweb/lighterprints/models.py Fri Jul 01 15:34:13 2011 -0700 @@ -1,4 +1,9 @@ from django.db import models +from django.db.models import Sum +from vcweb.core import signals +from vcweb.core.models import Experiment, ExperimentMetadata, GroupRoundDataValue +from django.dispatch import receiver +import datetime class Activity(models.Model): name = models.CharField(max_length=32, unique=True) @@ -31,3 +36,35 @@ activity = models.ForeignKey(Activity) available_start_time = models.TimeField(null=True, blank=True) available_end_time = models.TimeField(null=True, blank=True) + +def get_active_experiments(): + return Experiment.objects.filter(experiment_metadata=ExperimentMetadata.objects.get(name='lighterprints'), + status__in=('ACTIVE', 'ROUND_IN_PROGRESS')) + +@receiver(signals.midnight_tick) +def update_active_experiments(sender, time=None, **kwargs): + for experiment in get_active_experiments(): + # calculate total carbon savings and decide if they move on to the next level + for group in experiment.groups.all(): + grdv = GroupRoundDataValue.objects.get(group=group, name='carbon_footprint_level') + if should_advance_level(group, grdv.value): +# advance group level + grdv.value = min(grdv.value + 1, 3) + grdv.save() + + +def get_daily_carbon_savings(group): +# grab all of yesterday's participant data values + today = datetime.date.today() + yesterday = today - datetime.timedelta(1) + participant_data_values = group.get_participant_data_values().filter(date_created__gte=yesterday) + participant_data_values.aggregate(total=Sum('value')) + return participant_data_values['total'] + + +def should_advance_level(group, level): + if level < 3: + daily_carbon_savings = get_daily_carbon_savings(group) + return daily_carbon_savings > level * 10 + return False + Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-30 18:31:57
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/b0acb3ca37c5/ changeset: b0acb3ca37c5 user: alllee date: 2011-06-30 20:31:53 summary: adding simple celery configuration using the default django database instead of a rabbitmq broker affected #: 4 files (293 bytes) --- a/vcweb/core/signals.py Wed Jun 29 15:38:03 2011 -0700 +++ b/vcweb/core/signals.py Thu Jun 30 11:31:53 2011 -0700 @@ -5,6 +5,7 @@ round_started = Signal(providing_args=["experiment", 'time', 'round_configuration']) round_ended = Signal(providing_args=['experiment', 'time', 'round_configuration']) minute_tick = Signal(providing_args=['time']) +hour_tick = Signal(providing_args=['time']) post_login = Signal(providing_args=['user']) post_logout = Signal(providing_args=['user']) --- a/vcweb/core/tasks.py Wed Jun 29 15:38:03 2011 -0700 +++ b/vcweb/core/tasks.py Thu Jun 30 11:31:53 2011 -0700 @@ -2,17 +2,14 @@ from datetime import datetime, timedelta from vcweb.core import signals -''' -The updater module is invoked periodically from an external process to set up the -signaling and timing / processing of experiments in progress. - -@author: alllee -''' - @periodic_task(run_every=timedelta(seconds=60), ignore_result=True) def every_minute(): + ''' + Celery task invoked periodically from celerybeat. + ''' # use signal or just update experiment instance models directly here? signals.minute_tick.send(sender=None, time=datetime.now()) - - +@periodic_task(run_every=timedelta(seconds=3600), ignore_result=True) +def every_hour(): + signals.hour_tick.send(sender=None, time=datetime.now()) --- a/vcweb/fabfile.py Wed Jun 29 15:38:03 2011 -0700 +++ b/vcweb/fabfile.py Thu Jun 30 11:31:53 2011 -0700 @@ -102,10 +102,7 @@ local("{python} manage.py runserver {ip}:{port}".format(python=env.python, **locals()), capture=False) def celeryd(): - local("%(python)s manage.py celeryd" % env) - -def celerybeat(): - local("%(python)s manage.py celerybeat" % env) + local("%(python)s manage.py celeryd -B" % env) def push(): local('hg push ssh://hg...@bi.../virtualcommons/vcweb') --- a/vcweb/settings.py Wed Jun 29 15:38:03 2011 -0700 +++ b/vcweb/settings.py Thu Jun 30 11:31:53 2011 -0700 @@ -113,7 +113,9 @@ # socket.io configuration SOCKET_IO_PORT = 8882; -# celery rabbitmq/amqp configuration +# celery configuration +BROKER_BACKEND = "djkombu.transport.DatabaseTransport" +# rabbitmq/amqp celery config BROKER_HOST = "localhost" BROKER_PORT = 5672 BROKER_USER = "vcweb" @@ -121,6 +123,7 @@ BROKER_VHOST = "vcweb.vhost" # celerybeat configuration +CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' CELERYBEAT_MAX_LOOP_INTERVAL = 5 CELERYBEAT_LOG_FILE = 'celerybeat.log' CELERYBEAT_LOG_LEVEL = 'ERROR' Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-29 23:12:53
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/553037a68117/ changeset: 553037a68117 user: alllee date: 2011-06-30 00:38:03 summary: minor updates to templating, moving on to scheduling affected #: 5 files (546 bytes) --- a/vcweb/core/templates/mobile/base.html Tue Jun 28 12:17:53 2011 -0700 +++ b/vcweb/core/templates/mobile/base.html Wed Jun 29 15:38:03 2011 -0700 @@ -33,7 +33,7 @@ <div data-role='page' id='{% block page_id %}home{% endblock %}'> {% block header %} <div data-role='header' data-position='inline'> - <h1>vcmobile</h1> + <h1>{{experiment|default:"vcweb mobile"}}</h1></div> {% endblock header %} {% block content %} --- a/vcweb/core/templates/mobile/divpage.html Tue Jun 28 12:17:53 2011 -0700 +++ b/vcweb/core/templates/mobile/divpage.html Wed Jun 29 15:38:03 2011 -0700 @@ -1,10 +1,16 @@ <div data-role='page' id='{% block page_id %}home{% endblock %}'> {% block header %} - {% include "lighterprints/mobile/header.html" %} + <div data-role='header' data-position='inline'> + <h1>{{experiment.title|default:"vcweb experiment"}}</h1> + </div> {% endblock header %} {% block content %} {% endblock content %} {% block footer %} - {% include "lighterprints/mobile/footer.html" %} + <div data-role='footer'> + <h4> + This project is funded by the <a href='http://nsf.gov'>National Science Foundation</a> and <a href='http://www.asu.edu'>Arizona State University</a>. + </h4> + </div> {% endblock footer %} </div> --- a/vcweb/lighterprints/models.py Tue Jun 28 12:17:53 2011 -0700 +++ b/vcweb/lighterprints/models.py Wed Jun 29 15:38:03 2011 -0700 @@ -17,6 +17,10 @@ def label(self): return self.display_name if self.display_name else self.name + @property + def icon_name(self): + return self.name + def __unicode__(self): return u'%s (+%s)' % (self.label, self.savings) --- a/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Tue Jun 28 12:17:53 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Wed Jun 29 15:38:03 2011 -0700 @@ -13,10 +13,15 @@ <h3>Level {{level}} Activities</h3><div class='ui-grid-d'> {% for activity, grid_letter in activities %} - <div class='ui-block-{{grid_letter}}'><button data-theme='e'>{{ activity }}</button></div> + <div class='ui-block-{{grid_letter}}'><button data-icon='{{activity.icon_name}}' data-iconpos='top' data-theme='e'>{{ activity }}</button></div> {% endfor %} </div></div> {% endfor %} </div> {% endblock %} + +{% block footer %} +{% include "lighterprints/mobile/footer.html" %} +{% endblock footer %} + --- a/vcweb/lighterprints/templates/lighterprints/mobile/index.html Tue Jun 28 12:17:53 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/index.html Wed Jun 29 15:38:03 2011 -0700 @@ -17,7 +17,7 @@ <div data-role='content' data-theme='e'><div class='ui-grid-{{grid_letter}}'> {% for activity, grid_letter in available_activities %} - <div class='ui-block-{{grid_letter}}'><button data-theme='b'>{{activity}}</button></div> + <div class='ui-block-{{grid_letter}}'><button data-icon='{{activity.icon_name}}' data-iconpos='top' data-theme='b'>{{activity}}</button></div> {% endfor %} </div></div> Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <iss...@bi...> - 2011-06-28 22:05:08
|
--- you can reply above this line --- New issue 23: migrate socket.io code to v7 https://bitbucket.org/virtualcommons/vcweb/issue/23/migrate-socketio-code-to-v7 virtualcommons on Wed, 29 Jun 2011 00:05:02 +0200: Description: Need to migrate and test new socket.io release version https://github.com/LearnBoost/Socket.IO-node/wiki/Migrating-0.6-to-0.7 Responsible: alllee -- This is an issue notification from bitbucket.org. You are receiving this either because you are the owner of the issue, or you are following the issue. |
From: Bitbucket <com...@bi...> - 2011-06-28 19:17:58
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/54dd750d33c9/ changeset: 54dd750d33c9 user: alllee date: 2011-06-28 21:17:53 summary: adding jsonp callback validator from https://github.com/tav/scripts/blob/master/validate_jsonp.py and basic jsonp support to JSONResponseMixin that expects a callback parameter. affected #: 6 files (6.7 KB) --- a/vcweb/core/auth.py Mon Jun 27 23:59:03 2011 -0700 +++ b/vcweb/core/auth.py Tue Jun 28 12:17:53 2011 -0700 @@ -1,23 +1,16 @@ -''' - -General VCWEB authentication backend to allow users to login with their email -as their username. - -code adapted from http://djangosnippets.org/snippets/74/ -and http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/ - -''' - - from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User from django.core.validators import email_re import logging logger = logging.getLogger(__name__) - # FIXME: check for and handle Participant experiment auth codes. class AuthenticationBackend(ModelBackend): + ''' + General VCWEB authentication backend to allow users to login with their email as their username. + Code adapted from http://djangosnippets.org/snippets/74/ and + http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/ + ''' def authenticate(self, username=None, password=None): if email_re.search(username): try: @@ -25,6 +18,8 @@ if user.check_password(password): return user # check for and handle participants logging in with an auth code? - except User.DoesNotExist: - return None + except User.DoesNotExist as e: + logger.debug("no user found with username %s: %s", username, e) + else: + logger.debug("username failed the email regex: %s", username) return None --- a/vcweb/core/models.py Mon Jun 27 23:59:03 2011 -0700 +++ b/vcweb/core/models.py Tue Jun 28 12:17:53 2011 -0700 @@ -22,16 +22,15 @@ FIXME: getting a bit monolithically unwieldy. Consider splitting into models subdirectory """ -@receiver(signals.second_tick, sender=None) -def second_tick_handler(sender, time=None, **kwargs): +@receiver(signals.minute_tick, sender=None) +def minute_tick_handler(sender, time=None, **kwargs): """ - tick handlers. handles each second tick. Might rethink this and use timed / + tick handlers. handles each minute tick. Might rethink this and use timed / delayed tasks in celery execute at the end of each round for controlled experiments and for longer-scale experiments use 1 minute granularity for performance sake. """ - logger.debug("handling second tick signal at %s", time) - logger.debug("kwargs: %s", kwargs) + logger.debug("handling minute tick signal at %s with kwargs %s", time, kwargs) # inspect all active experiments and update their time left Experiment.objects.increment_elapsed_time(status='ROUND_IN_PROGRESS') @@ -161,11 +160,11 @@ def get_all_active(self): return self.filter(status='ACTIVE') - def increment_elapsed_time(self, status='ROUND_IN_PROGRESS'): + def increment_elapsed_time(self, status='ROUND_IN_PROGRESS', amount=60): if status: es = self.filter(status=status) - es.update(current_round_elapsed_time=models.F('current_round_elapsed_time') + 1, - total_elapsed_time=models.F('total_elapsed_time') + 1) + es.update(current_round_elapsed_time=models.F('current_round_elapsed_time') + amount, + total_elapsed_time=models.F('total_elapsed_time') + amount) # check each experiment's total_elapsed_time against the total allotted time and # issue round_stopped signals to experiments that need to be stopped. for experiment in es.all(): --- a/vcweb/core/signals.py Mon Jun 27 23:59:03 2011 -0700 +++ b/vcweb/core/signals.py Tue Jun 28 12:17:53 2011 -0700 @@ -4,7 +4,7 @@ experiment_started = Signal(providing_args=["experiment", "time", "experimenter"]) round_started = Signal(providing_args=["experiment", 'time', 'round_configuration']) round_ended = Signal(providing_args=['experiment', 'time', 'round_configuration']) -second_tick = Signal(providing_args=['time']) +minute_tick = Signal(providing_args=['time']) post_login = Signal(providing_args=['user']) post_logout = Signal(providing_args=['user']) --- a/vcweb/core/tasks.py Mon Jun 27 23:59:03 2011 -0700 +++ b/vcweb/core/tasks.py Tue Jun 28 12:17:53 2011 -0700 @@ -1,19 +1,18 @@ +from celery.decorators import periodic_task +from datetime import datetime, timedelta +from vcweb.core import signals + ''' -The updater module is invoked periodically from an external process to set up the signaling and timing / processing -of experiments in progress. +The updater module is invoked periodically from an external process to set up the +signaling and timing / processing of experiments in progress. @author: alllee ''' -from celery.decorators import periodic_task -from datetime import datetime, timedelta -from vcweb.core import signals +@periodic_task(run_every=timedelta(seconds=60), ignore_result=True) +def every_minute(): + # use signal or just update experiment instance models directly here? + signals.minute_tick.send(sender=None, time=datetime.now()) -@periodic_task(run_every=timedelta(seconds=1), ignore_result=True) -def every_second(): - # use signal or just update experiment instance models directly here? - signals.second_tick.send(sender=None, time=datetime.now()) - - --- a/vcweb/core/views.py Mon Jun 27 23:59:03 2011 -0700 +++ b/vcweb/core/views.py Tue Jun 28 12:17:53 2011 -0700 @@ -22,6 +22,7 @@ from vcweb.core.models import (Participant, Experimenter, Experiment, Institution, is_participant, is_experimenter) from vcweb.core.decorators import anonymous_required, experimenter_required, participant_required from vcweb.core import unicodecsv +from vcweb.core.validate_jsonp import is_valid_jsonp_callback_value import itertools import logging logger = logging.getLogger(__name__) @@ -44,13 +45,21 @@ def get_json_response(self, content, **httpresponse_kwargs): "Construct an `HttpResponse` object." + callback = self.request.GET.get('callback', '') + if is_valid_jsonp_callback_value(callback): + content = '%s(%s)' % (callback, content) + logger.debug("returning json content %s", content) return HttpResponse(content, content_type='application/json', **httpresponse_kwargs) def convert_context_to_json(self, context, context_key='object_list', **kwargs): - "Convert the context dictionary into a JSON object" - return dumps(context[context_key]) + """ + Converts the data object associated with context_key in the context dict + into a JSON object and returns it. If context_key is None, converts the + entire context dict. + """ + return dumps( context if context_key is None else context[context_key] ) class AnonymousMixin(object): """ provides the anonymous_required decorator """ Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-28 06:59:07
|
2 new changesets in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/1c4b3230f35a/ changeset: 1c4b3230f35a user: alllee date: 2011-06-28 08:41:56 summary: refactoring view logic, adjusting emitted json next affected #: 2 files (180 bytes) --- a/vcweb/core/views.py Mon Jun 27 16:28:54 2011 -0700 +++ b/vcweb/core/views.py Mon Jun 27 23:41:56 2011 -0700 @@ -44,14 +44,12 @@ def get_json_response(self, content, **httpresponse_kwargs): "Construct an `HttpResponse` object." - logger.debug("return json response %s", content) return HttpResponse(content, content_type='application/json', **httpresponse_kwargs) def convert_context_to_json(self, context, context_key='object_list', **kwargs): "Convert the context dictionary into a JSON object" - logger.debug("serializing context %s with context_key %s", context, context_key) return dumps(context[context_key]) class AnonymousMixin(object): --- a/vcweb/lighterprints/views.py Mon Jun 27 16:28:54 2011 -0700 +++ b/vcweb/lighterprints/views.py Mon Jun 27 23:41:56 2011 -0700 @@ -14,20 +14,19 @@ # FIXME: replace with dynamic set model = Activity - def get_activity_by_level(self): - activity_by_level = collections.defaultdict(list) - for activity in Activity.objects.all(): - activity_by_level[activity.level].append(activity) - return dict(activity_by_level) - def get_context_data(self, **kwargs): context = super(BaseListView, self).get_context_data(**kwargs) - context['activity_by_level'] = self.get_activity_by_level() + all_activities = Activity.objects.all() + activity_by_level = collections.defaultdict(list) + for activity in all_activities: + activity_by_level[activity.level].append(activity) + context['activity_by_level'] = dict(activity_by_level) + context['flattened_activities'] = all_activities return context def render_to_response(self, context, **response_kwargs): if self.request.GET.get('format', 'html') == 'json': - return JSONResponseMixin.render_to_response(self, context, context_key='activity_by_level') + return JSONResponseMixin.render_to_response(self, context, context_key='flattened_activities') else: return MultipleObjectTemplateResponseMixin.render_to_response(self, context) @@ -37,14 +36,14 @@ class MobileView(ActivityListView): jqm_grid_columns = tuple("abcde") - def get_activity_by_level(self): - activity_by_level = collections.defaultdict(list) - for index, activity in enumerate(Activity.objects.all()): - activity_by_level[activity.level].append((activity, MobileView.jqm_grid_columns[index])) - return dict(activity_by_level) - def get_context_data(self, **kwargs): context = super(MobileView, self).get_context_data(**kwargs) + activity_by_level = collections.defaultdict(list) + for index, activity in enumerate(context['flattened_activities']): + activity_by_level[activity.level].append((activity, + MobileView.jqm_grid_columns[index % 5])) + context['activity_by_level'] = dict(activity_by_level) + available_activities = get_available_activities(self.request) context['grid_letter'] = MobileView.jqm_grid_columns[max(len(available_activities) - 2, 0)] context['available_activities'] = available_activities http://bitbucket.org/virtualcommons/vcweb/changeset/1442870b22ab/ changeset: 1442870b22ab user: alllee date: 2011-06-28 08:59:03 summary: crude flattened json serialization. affected #: 1 file (426 bytes) --- a/vcweb/lighterprints/views.py Mon Jun 27 23:41:56 2011 -0700 +++ b/vcweb/lighterprints/views.py Mon Jun 27 23:59:03 2011 -0700 @@ -16,12 +16,19 @@ def get_context_data(self, **kwargs): context = super(BaseListView, self).get_context_data(**kwargs) - all_activities = Activity.objects.all() + all_activities = context['activity_list'] activity_by_level = collections.defaultdict(list) + flattened_activities = [] for activity in all_activities: activity_by_level[activity.level].append(activity) + #activity_as_dict = collections.OrderedDict() + activity_as_dict = {} + for attr_name in ('pk', 'name', 'summary', 'display_name', 'description', 'savings', 'url', 'available_all_day', 'level', 'group_activity', 'cooldown'): + activity_as_dict[attr_name] = getattr(activity, attr_name) + flattened_activities.append(activity_as_dict) + context['activity_by_level'] = dict(activity_by_level) - context['flattened_activities'] = all_activities + context['flattened_activities'] = flattened_activities return context def render_to_response(self, context, **response_kwargs): @@ -39,7 +46,7 @@ def get_context_data(self, **kwargs): context = super(MobileView, self).get_context_data(**kwargs) activity_by_level = collections.defaultdict(list) - for index, activity in enumerate(context['flattened_activities']): + for index, activity in enumerate(context['activity_list']): activity_by_level[activity.level].append((activity, MobileView.jqm_grid_columns[index % 5])) context['activity_by_level'] = dict(activity_by_level) Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-27 23:29:07
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/22bd927bc912/ changeset: 22bd927bc912 user: alllee date: 2011-06-28 01:28:54 summary: still some template issues, getting rid of delegate code as it's causing flash-of-unstyled-content badness affected #: 6 files (237 bytes) --- a/vcweb/core/templates/mobile/base.html Sat Jun 25 17:53:05 2011 -0700 +++ b/vcweb/core/templates/mobile/base.html Mon Jun 27 16:28:54 2011 -0700 @@ -10,7 +10,8 @@ <!-- vcweb common js --><script type='text/javascript'> // maintain active button state - $(document).delegate("div:jqmData(role='page')", 'pageshow', function() { + /* + $("body").delegate("div:jqmData(role='page')", 'pageshow', function() { console.debug("window location hash is " + window.location.hash); if (window.location.hash) { $(this).find("div:jqmData(role='navbar') a").each(function() { @@ -23,6 +24,7 @@ }); } }); + */ </script> {% endblock %} </head> --- a/vcweb/lighterprints/templates/lighterprints/mobile/footer.html Sat Jun 25 17:53:05 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/footer.html Mon Jun 27 16:28:54 2011 -0700 @@ -1,3 +1,3 @@ -<div data-role='footer'> +<div data-role='footer' data-theme='a'> {% include "lighterprints/mobile/navbar.html" %} </div> --- a/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Sat Jun 25 17:53:05 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Mon Jun 27 16:28:54 2011 -0700 @@ -1,4 +1,9 @@ {% extends "mobile/divpage.html" %} +{% block header %} +<div data-role='header'> + <h1>All Activities</h1> +</div> +{% endblock header %} {% block page_id %}full-activity-list{% endblock page_id %} {% block content %} --- a/vcweb/lighterprints/templates/lighterprints/mobile/header.html Sat Jun 25 17:53:05 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/header.html Mon Jun 27 16:28:54 2011 -0700 @@ -1,4 +1,4 @@ -<div data-role='header' data-position='inline'> +<div data-role='header' data-theme='d'><h1>Lighter Footprints</h1></div> --- a/vcweb/lighterprints/templates/lighterprints/mobile/index.html Sat Jun 25 17:53:05 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/index.html Mon Jun 27 16:28:54 2011 -0700 @@ -8,12 +8,13 @@ {% endblock %} {% block header %} -{% include "lighterprints/mobile/header.html" %} +<div data-role='header'> + <h1>Available Activities</h1> +</div> {% endblock header %} {% block content %} <div data-role='content' data-theme='e'> - <h3>Available activities</h3><div class='ui-grid-{{grid_letter}}'> {% for activity, grid_letter in available_activities %} <div class='ui-block-{{grid_letter}}'><button data-theme='b'>{{activity}}</button></div> --- a/vcweb/lighterprints/templates/lighterprints/mobile/navbar.html Sat Jun 25 17:53:05 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/navbar.html Mon Jun 27 16:28:54 2011 -0700 @@ -1,8 +1,8 @@ <div data-role='navbar'><ul> - <li><a href='#home-screen' data-role='button' data-icon='home' data-transition='fade'>Home</a></li> - <li><a href='#full-activity-list' data-role='button' data-icon='grid' data-transition='fade'>All activities</a></li> - <li><a href='#group-performance' data-role='button' data-icon='group' data-transition='fade'>Group performance</a></li> + <li><a href='#home-screen' data-role='button' class='ui-state-persist' data-icon='home' data-transition='fade'>Home</a></li> + <li><a href='#full-activity-list' data-role='button' class='ui-state-persist' data-icon='grid' data-transition='fade'>All activities</a></li> + <li><a href='#group-performance' data-role='button' class='ui-state-persist' data-icon='info' data-transition='fade'>Group performance</a></li></ul></div> Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-26 00:53:12
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/96e769becc27/ changeset: 96e769becc27 user: alllee date: 2011-06-26 02:53:05 summary: pushing navbar javascript up to mobile/base and trying out .delegate instead of .live, renamed lpbase.html to divpage.html and moved to core/templates/mobile affected #: 7 files (1.5 KB) --- a/.hgignore Sat Jun 25 13:06:22 2011 -0700 +++ b/.hgignore Sat Jun 25 17:53:05 2011 -0700 @@ -11,4 +11,4 @@ build logs tmp -.orig +*.orig --- a/vcweb/core/templates/mobile/base.html Sat Jun 25 13:06:22 2011 -0700 +++ b/vcweb/core/templates/mobile/base.html Sat Jun 25 17:53:05 2011 -0700 @@ -8,6 +8,22 @@ <script type="text/javascript" src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script><link href="{{STATIC_URL}}css/mobile.css" rel="stylesheet" type="text/css" media="screen" /><!-- vcweb common js --> + <script type='text/javascript'> + // maintain active button state + $(document).delegate("div:jqmData(role='page')", 'pageshow', function() { + console.debug("window location hash is " + window.location.hash); + if (window.location.hash) { + $(this).find("div:jqmData(role='navbar') a").each(function() { + if ($(this).attr('href') == window.location.hash) { + $(this).addClass('ui-btn-active ui-state-persist'); + } + else { + $(this).removeClass('ui-btn-active ui-state-persist'); + } + }); + } + }); + </script> {% endblock %} </head><body> --- a/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Sat Jun 25 13:06:22 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Sat Jun 25 17:53:05 2011 -0700 @@ -1,4 +1,4 @@ -{% extends "lighterprints/mobile/lpbase.html" %} +{% extends "mobile/divpage.html" %} {% block page_id %}full-activity-list{% endblock page_id %} {% block content %} --- a/vcweb/lighterprints/templates/lighterprints/mobile/index.html Sat Jun 25 13:06:22 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/index.html Sat Jun 25 17:53:05 2011 -0700 @@ -1,16 +1,6 @@ {% extends "mobile/base.html" %} {% block head %} {{ block.super }} -<script type='text/javascript'> - // maintain active button state - $("div:jqmData(role='page')").live('pageshow', function (event) { - console.debug("window location hash is " + window.location.hash); - if (window.location.hash) { - $('#navbar a').removeClass('ui-btn-active'); - $('#navbar a[href="' + window.location.hash + '"]').addClass('ui-btn-active'); - } - }); -</script> {% endblock head %} {% block title %} --- a/vcweb/lighterprints/templates/lighterprints/mobile/lpbase.html Sat Jun 25 13:06:22 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -<div data-role='page' id='{% block page_id %}home{% endblock %}'> - {% block header %} - {% include "lighterprints/mobile/header.html" %} - {% endblock header %} - {% block content %} - {% endblock content %} - {% block footer %} - {% include "lighterprints/mobile/footer.html" %} - {% endblock footer %} -</div> --- a/vcweb/lighterprints/templates/lighterprints/mobile/navbar.html Sat Jun 25 13:06:22 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/navbar.html Sat Jun 25 17:53:05 2011 -0700 @@ -1,8 +1,8 @@ -<div data-role='navbar' id='navbar'> +<div data-role='navbar'><ul> - <li><a href='#home-screen' data-role='button' data-icon='home' class='ui-btn-active' data-transition='fade'>Home</a></li> - <li><a href='#full-activity-list' data-role='button' data-icon='grid' data-transition='slide'>All activities</a></li> - <li><a href='#group-performance' data-role='button' data-icon='group' data-transition='pop'>Group performance</a></li> + <li><a href='#home-screen' data-role='button' data-icon='home' data-transition='fade'>Home</a></li> + <li><a href='#full-activity-list' data-role='button' data-icon='grid' data-transition='fade'>All activities</a></li> + <li><a href='#group-performance' data-role='button' data-icon='group' data-transition='fade'>Group performance</a></li></ul></div> Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-25 20:06:31
|
2 new changesets in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/4e7478038125/ changeset: 4e7478038125 user: alllee date: 2011-06-25 21:39:11 summary: moving nav menu to the bottom of the screen and fixing some html / template issues. current scheme is to load all mobile content at once (i.e., include divs for all secondary and below pages). affected #: 5 files (1.4 KB) --- a/vcweb/core/templates/mobile/base.html Fri Jun 24 21:41:42 2011 -0700 +++ b/vcweb/core/templates/mobile/base.html Sat Jun 25 12:39:11 2011 -0700 @@ -11,7 +11,25 @@ {% endblock %} </head><body> - {% block content %} - {% endblock content %} + {% block page %} + <div data-role='page' id='home'> + {% block header %} + <div data-role='header' data-position='inline'> + <h1>vcmobile</h1> + </div> + {% endblock header %} + {% block content %} + {% endblock content %} + {% block footer %} + <div data-role='footer'> + <h4> + This project is funded by the <a href='http://nsf.gov'>National Science Foundation</a> and <a href='http://www.asu.edu'>Arizona State University</a>. + </h4> + </div> + {% endblock footer %} + </div> + {% block extrapages %} + {% endblock extrapages %} + {% endblock page %} </body></html> --- a/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Fri Jun 24 21:41:42 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Sat Jun 25 12:39:11 2011 -0700 @@ -12,4 +12,5 @@ </div> {% endfor %} </div> + {% include "lighterprints/mobile/footer.html" %} </div> --- a/vcweb/lighterprints/templates/lighterprints/mobile/header.html Fri Jun 24 21:41:42 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/header.html Sat Jun 25 12:39:11 2011 -0700 @@ -1,11 +1,5 @@ <div data-role='header' data-position='inline'><h1>Lighter Footprints</h1> - <div data-role='navbar'> - <ul> - <li><a href='#home-screen' data-role='button' data-icon='home'>Home</a></li> - <li><a href='#full-activity-list' data-role='button' data-icon='grid'>All activities</a></li> - <li><a href='#group-performance' data-role='button' data-icon='group'>Group performance</a></li> - </ul> - </div></div> + --- a/vcweb/lighterprints/templates/lighterprints/mobile/index.html Fri Jun 24 21:41:42 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/index.html Sat Jun 25 12:39:11 2011 -0700 @@ -9,18 +9,25 @@ Lighter Footprints {% endblock %} +{% block header %} +{% include "lighterprints/mobile/header.html" %} +{% endblock header %} + {% block content %} -<div data-role='page' id='home-screen'> - {% include "lighterprints/mobile/header.html" %} - <div data-role='content' data-theme='e'> - <h3>Available activities</h3> - <div class='ui-grid-{{grid_letter}}'> - {% for activity, grid_letter in available_activities %} - <div class='ui-block-{{grid_letter}}'><button data-theme='b'>{{activity}}</button></div> - {% endfor %} - </div> - +<div data-role='content' data-theme='e'> + <h3>Available activities</h3> + <div class='ui-grid-{{grid_letter}}'> + {% for activity, grid_letter in available_activities %} + <div class='ui-block-{{grid_letter}}'><button data-theme='b'>{{activity}}</button></div> + {% endfor %} </div></div> +{% endblock content %} + +{% block extrapages %} {% include "lighterprints/mobile/full-activity-list.html" %} -{% endblock content %} +{% endblock extrapages %} + +{% block footer %} +{% include "lighterprints/mobile/footer.html" %} +{% endblock footer %} --- a/vcweb/lighterprints/views.py Fri Jun 24 21:41:42 2011 -0700 +++ b/vcweb/lighterprints/views.py Sat Jun 25 12:39:11 2011 -0700 @@ -22,7 +22,6 @@ def get_context_data(self, **kwargs): context = super(BaseListView, self).get_context_data(**kwargs) - logger.debug("ActivityListView.get_context_data: %s", context) context['activity_by_level'] = self.get_activity_by_level() return context @@ -36,19 +35,18 @@ template_name = 'lighterprints/activity_detail.html' class MobileView(ActivityListView): - jquery_grid_list = list("abcde") + jqm_grid_columns = tuple("abcde") def get_activity_by_level(self): activity_by_level = collections.defaultdict(list) for index, activity in enumerate(Activity.objects.all()): - activity_by_level[activity.level].append((activity, MobileView.jquery_grid_list[index])) + activity_by_level[activity.level].append((activity, MobileView.jqm_grid_columns[index])) return dict(activity_by_level) def get_context_data(self, **kwargs): context = super(MobileView, self).get_context_data(**kwargs) - logger.debug("super context: %s", context) available_activities = get_available_activities(self.request) - context['grid_letter'] = 'a' if len(available_activities) < 2 else MobileView.jquery_grid_list[len(available_activities) - 2] + context['grid_letter'] = MobileView.jqm_grid_columns[max(len(available_activities) - 2, 0)] context['available_activities'] = available_activities return context @@ -61,6 +59,6 @@ def get_available_activities(request): # FIXME: currently stubbed out to return all activities. should move this to # models.py and have it take a Participant? - return zip(Activity.objects.all(), MobileView.jquery_grid_list) + return zip(Activity.objects.all(), MobileView.jqm_grid_columns) http://bitbucket.org/virtualcommons/vcweb/changeset/1f0bce8a4551/ changeset: 1f0bce8a4551 user: alllee date: 2011-06-25 22:06:22 summary: setting active state on navbar properly and some template cleanup affected #: 6 files (1.3 KB) --- a/vcweb/core/templates/mobile/base.html Sat Jun 25 12:39:11 2011 -0700 +++ b/vcweb/core/templates/mobile/base.html Sat Jun 25 13:06:22 2011 -0700 @@ -12,7 +12,7 @@ </head><body> {% block page %} - <div data-role='page' id='home'> + <div data-role='page' id='{% block page_id %}home{% endblock %}'> {% block header %} <div data-role='header' data-position='inline'><h1>vcmobile</h1> --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/footer.html Sat Jun 25 13:06:22 2011 -0700 @@ -0,0 +1,3 @@ +<div data-role='footer'> + {% include "lighterprints/mobile/navbar.html" %} +</div> --- a/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Sat Jun 25 12:39:11 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/full-activity-list.html Sat Jun 25 13:06:22 2011 -0700 @@ -1,16 +1,17 @@ -<div data-role='page' id='full-activity-list'> - {% include "lighterprints/mobile/header.html" %} - <div data-role='content'> - {% for level, activities in activity_by_level.iteritems %} - <div data-role='collapsible' data-theme='b'> - <h3>Level {{level}} Activities</h3> - <div class='ui-grid-d'> - {% for activity, grid_letter in activities %} - <div class='ui-block-{{grid_letter}}'><button data-theme='e'>{{ activity }}</button></div> - {% endfor %} - </div> +{% extends "lighterprints/mobile/lpbase.html" %} + +{% block page_id %}full-activity-list{% endblock page_id %} +{% block content %} +<div data-role='content'> + {% for level, activities in activity_by_level.iteritems %} + <div data-role='collapsible' data-theme='b'> + <h3>Level {{level}} Activities</h3> + <div class='ui-grid-d'> + {% for activity, grid_letter in activities %} + <div class='ui-block-{{grid_letter}}'><button data-theme='e'>{{ activity }}</button></div> + {% endfor %} </div> - {% endfor %} </div> - {% include "lighterprints/mobile/footer.html" %} + {% endfor %} </div> +{% endblock %} --- a/vcweb/lighterprints/templates/lighterprints/mobile/index.html Sat Jun 25 12:39:11 2011 -0700 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/index.html Sat Jun 25 13:06:22 2011 -0700 @@ -2,6 +2,14 @@ {% block head %} {{ block.super }} <script type='text/javascript'> + // maintain active button state + $("div:jqmData(role='page')").live('pageshow', function (event) { + console.debug("window location hash is " + window.location.hash); + if (window.location.hash) { + $('#navbar a').removeClass('ui-btn-active'); + $('#navbar a[href="' + window.location.hash + '"]').addClass('ui-btn-active'); + } + }); </script> {% endblock head %} --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/lpbase.html Sat Jun 25 13:06:22 2011 -0700 @@ -0,0 +1,10 @@ +<div data-role='page' id='{% block page_id %}home{% endblock %}'> + {% block header %} + {% include "lighterprints/mobile/header.html" %} + {% endblock header %} + {% block content %} + {% endblock content %} + {% block footer %} + {% include "lighterprints/mobile/footer.html" %} + {% endblock footer %} +</div> --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vcweb/lighterprints/templates/lighterprints/mobile/navbar.html Sat Jun 25 13:06:22 2011 -0700 @@ -0,0 +1,8 @@ +<div data-role='navbar' id='navbar'> + <ul> + <li><a href='#home-screen' data-role='button' data-icon='home' class='ui-btn-active' data-transition='fade'>Home</a></li> + <li><a href='#full-activity-list' data-role='button' data-icon='grid' data-transition='slide'>All activities</a></li> + <li><a href='#group-performance' data-role='button' data-icon='group' data-transition='pop'>Group performance</a></li> + </ul> +</div> + Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-25 04:42:05
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/c6787d0d463c/ changeset: c6787d0d463c user: alllee date: 2011-06-25 06:41:42 summary: first cut at a jquery mobile view with navbar / activities / performance affected #: 4 files (2.3 KB) --- a/vcweb/lighterprints/views.py Fri Jun 24 18:27:00 2011 -0700 +++ b/vcweb/lighterprints/views.py Fri Jun 24 21:41:42 2011 -0700 @@ -22,7 +22,7 @@ def get_context_data(self, **kwargs): context = super(BaseListView, self).get_context_data(**kwargs) - logger.debug("context is %s", context) + logger.debug("ActivityListView.get_context_data: %s", context) context['activity_by_level'] = self.get_activity_by_level() return context @@ -35,20 +35,32 @@ class ActivityDetailView(JSONResponseMixin, BaseDetailView): template_name = 'lighterprints/activity_detail.html' +class MobileView(ActivityListView): + jquery_grid_list = list("abcde") + + def get_activity_by_level(self): + activity_by_level = collections.defaultdict(list) + for index, activity in enumerate(Activity.objects.all()): + activity_by_level[activity.level].append((activity, MobileView.jquery_grid_list[index])) + return dict(activity_by_level) + + def get_context_data(self, **kwargs): + context = super(MobileView, self).get_context_data(**kwargs) + logger.debug("super context: %s", context) + available_activities = get_available_activities(self.request) + context['grid_letter'] = 'a' if len(available_activities) < 2 else MobileView.jquery_grid_list[len(available_activities) - 2] + context['available_activities'] = available_activities + return context + + def get_template_names(self): + return ['lighterprints/mobile/index.html'] + class DoActivityView(FormView): pass -class MobileView(ActivityListView): +def get_available_activities(request): + # FIXME: currently stubbed out to return all activities. should move this to + # models.py and have it take a Participant? + return zip(Activity.objects.all(), MobileView.jquery_grid_list) - def get_context_data(self, **kwargs): - context = super(ActivityListView, self).get_context_data(**kwargs) - activity_by_level = collections.defaultdict(list) - jquery_grid_list = list("abcde") - for index, activity in enumerate(Activity.objects.all()): - activity_by_level[activity.level].append((activity, jquery_grid_list[index])) - context['activity_by_level'] = dict(activity_by_level) - logger.debug("activity by level %s", activity_by_level) - return context - def get_template_names(self): - return ['lighterprints/mobile.html'] Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-25 01:27:06
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/0a84bd347d6c/ changeset: 0a84bd347d6c user: alllee date: 2011-06-25 03:27:00 summary: adding simple mobile view proof of concept affected #: 3 files (567 bytes) --- a/vcweb/core/templates/mobile/base.html Thu Jun 23 18:15:42 2011 -0700 +++ b/vcweb/core/templates/mobile/base.html Fri Jun 24 18:27:00 2011 -0700 @@ -3,7 +3,7 @@ <head> {% block head %} <title>{% block title %}Virtual Commons Web Environment{% endblock %}</title> - <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b.1/jquery.mobile-1.0b.1.min.css" /> + <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.css" /><script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'></script><script type="text/javascript" src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script><link href="{{STATIC_URL}}css/mobile.css" rel="stylesheet" type="text/css" media="screen" /> --- a/vcweb/lighterprints/urls.py Thu Jun 23 18:15:42 2011 -0700 +++ b/vcweb/lighterprints/urls.py Fri Jun 24 18:27:00 2011 -0700 @@ -1,9 +1,9 @@ from django.conf.urls.defaults import url, patterns -from vcweb.lighterprints.views import ActivityDetailView, ActivityListView, DoActivityView +from vcweb.lighterprints.views import (ActivityDetailView, ActivityListView, DoActivityView, MobileView) urlpatterns = patterns('vcweb.lighterprints.views', - url(r'^$', 'index', name='index'), + url(r'^mobile$', MobileView.as_view(), name='mobile'), url(r'^(?P<experiment_id>\d+)/configure$', 'configure', name='configure'), url(r'^activity/list/?$', ActivityListView.as_view()), url(r'^activity/(?P<activity_id>\d+)$', ActivityDetailView.as_view()), --- a/vcweb/lighterprints/views.py Thu Jun 23 18:15:42 2011 -0700 +++ b/vcweb/lighterprints/views.py Fri Jun 24 18:27:00 2011 -0700 @@ -10,7 +10,7 @@ logger = logging.getLogger(__name__) -class ActivityListView(JSONResponseMixin, BaseListView, MultipleObjectTemplateResponseMixin): +class ActivityListView(JSONResponseMixin, MultipleObjectTemplateResponseMixin, BaseListView): # FIXME: replace with dynamic set model = Activity @@ -30,7 +30,6 @@ if self.request.GET.get('format', 'html') == 'json': return JSONResponseMixin.render_to_response(self, context, context_key='activity_by_level') else: - logger.debug("returning MOTRM render_to_response with context %s", context['activity_by_level']) return MultipleObjectTemplateResponseMixin.render_to_response(self, context) class ActivityDetailView(JSONResponseMixin, BaseDetailView): @@ -38,3 +37,18 @@ class DoActivityView(FormView): pass + +class MobileView(ActivityListView): + + def get_context_data(self, **kwargs): + context = super(ActivityListView, self).get_context_data(**kwargs) + activity_by_level = collections.defaultdict(list) + jquery_grid_list = list("abcde") + for index, activity in enumerate(Activity.objects.all()): + activity_by_level[activity.level].append((activity, jquery_grid_list[index])) + context['activity_by_level'] = dict(activity_by_level) + logger.debug("activity by level %s", activity_by_level) + return context + + def get_template_names(self): + return ['lighterprints/mobile.html'] Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-06-24 01:15:57
|
2 new changesets in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/07eb1c2a5015/ changeset: 07eb1c2a5015 user: alllee date: 2011-06-24 03:13:59 summary: creating base mobile template and adding cookie ajax csrf support affected #: 3 files (1.5 KB) --- a/vcweb/core/templates/base.html Wed Jun 22 09:22:27 2011 -0700 +++ b/vcweb/core/templates/base.html Thu Jun 23 18:13:59 2011 -0700 @@ -13,6 +13,7 @@ <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'></script><script type='text/javascript' src='{{STATIC_URL}}js/common.js'></script><script type='text/javascript' src='{{STATIC_URL}}js/jquery.qtip-1.0.0-rc3.min.js'></script> + <script type='text/javascript' src='{{STATIC_URL}}js/jquery.cookies.2.2.0.min.js'></script> {% include "includes/jquery.ui.html" %} {% if debug_mode %} {% load dajaxice_templatetags %} --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vcweb/core/templates/mobile/base.html Thu Jun 23 18:13:59 2011 -0700 @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> + <head> + {% block head %} + <title>{% block title %}Virtual Commons Web Environment{% endblock %}</title> + <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b.1/jquery.mobile-1.0b.1.min.css" /> + <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'></script> + <script type="text/javascript" src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script> + <link href="{{STATIC_URL}}css/mobile.css" rel="stylesheet" type="text/css" media="screen" /> + <!-- vcweb common js --> + {% endblock %} + </head> + <body> + {% block content %} + {% endblock content %} + </body> +</html> --- a/vcweb/static/js/common.js Wed Jun 22 09:22:27 2011 -0700 +++ b/vcweb/static/js/common.js Thu Jun 23 18:13:59 2011 -0700 @@ -28,21 +28,6 @@ } $(document).ajaxSend(function(event, xhr, settings) { - function getCookie(name) { - var cookieValue = null; - if (document.cookie && document.cookie != '') { - var cookies = document.cookie.split(';'); - for (var i = 0; i < cookies.length; i++) { - var cookie = jQuery.trim(cookies[i]); - // Does this cookie string begin with the name we want? - if (cookie.substring(0, name.length + 1) == (name + '=')) { - cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; - } - } - } - return cookieValue; - } function sameOrigin(url) { // url could be relative or scheme relative or absolute var host = document.location.host; // host + port @@ -58,8 +43,7 @@ function safeMethod(method) { return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } - if (!safeMethod(settings.type) && sameOrigin(settings.url)) { - xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); + xhr.setRequestHeader("X-CSRFToken", $.cookies.get('csrftoken')); } }); http://bitbucket.org/virtualcommons/vcweb/changeset/17ad2eb9169e/ changeset: 17ad2eb9169e user: alllee date: 2011-06-24 03:15:42 summary: pushing cookies to base-vcweb-form dependency affected #: 2 files (193 bytes) --- a/vcweb/core/templates/base.html Thu Jun 23 18:13:59 2011 -0700 +++ b/vcweb/core/templates/base.html Thu Jun 23 18:15:42 2011 -0700 @@ -11,9 +11,8 @@ <link href="{{STATIC_URL}}css/style.css" rel="stylesheet" type="text/css" media="screen" /><!-- vcweb common js --><script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'></script> + <script type='text/javascript' src='{{STATIC_URL}}js/jquery.qtip-1.0.0-rc3.min.js'></script><script type='text/javascript' src='{{STATIC_URL}}js/common.js'></script> - <script type='text/javascript' src='{{STATIC_URL}}js/jquery.qtip-1.0.0-rc3.min.js'></script> - <script type='text/javascript' src='{{STATIC_URL}}js/jquery.cookies.2.2.0.min.js'></script> {% include "includes/jquery.ui.html" %} {% if debug_mode %} {% load dajaxice_templatetags %} --- a/vcweb/core/templates/includes/jquery.forms.html Thu Jun 23 18:13:59 2011 -0700 +++ b/vcweb/core/templates/includes/jquery.forms.html Thu Jun 23 18:15:42 2011 -0700 @@ -1,1 +1,2 @@ <script type='text/javascript' src='{{STATIC_URL}}js/jquery.validate.min.js'></script> +<script type='text/javascript' src='{{STATIC_URL}}js/jquery.cookies.2.2.0.min.js'></script> Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <iss...@bi...> - 2011-06-22 16:30:25
|
--- you can reply above this line --- New issue 22: look closely at pretest round 2 of chat (16) https://bitbucket.org/virtualcommons/vcweb/issue/22/look-closely-at-pretest-round-2-of-chat-16 virtualcommons on Wed, 22 Jun 2011 18:30:15 +0200: Description: Students report their individual / group harvests disappeared for this round. Could be related to the other bug that popped up with chat escaping and double login of the experimenter. Responsible: alllee -- This is an issue notification from bitbucket.org. You are receiving this either because you are the owner of the issue, or you are following the issue. |
From: Bitbucket <com...@bi...> - 2011-06-22 16:22:34
|
1 new changeset in vcweb: http://bitbucket.org/virtualcommons/vcweb/changeset/00024d63ebf0/ changeset: 00024d63ebf0 user: alllee date: 2011-06-22 18:22:27 summary: patches from this morning's pretest: fixing issue 21 - using tornado.xhtml_escape to untaint incoming chat messages when max_harvest_decision is 0, display the deforested picture. affected #: 3 files (371 bytes) --- a/vcweb/forestry/templates/forestry/participate.html Wed Jun 22 01:50:58 2011 -0700 +++ b/vcweb/forestry/templates/forestry/participate.html Wed Jun 22 09:22:27 2011 -0700 @@ -62,6 +62,7 @@ {% endblock %} {% block content %} <h3>Forestry round number {{ experiment.current_round.round_number }}</h3> +{% if max_harvest_decision > 0 %} <div style="background: url('{{STATIC_URL}}images/forestry/{{tree.name}}.png'); width:{{max_width}}px; height: {{max_height}}px;"> </div> @@ -71,11 +72,12 @@ </div> {% endif %} -{% if resource_level.value == 0 %} +{% else %} <div style='padding: 8px; margin: auto; border: solid 1px; background: #E8E8E8 url({{STATIC_URL}}images/forestry/deforestation.jpg) no-repeat center; height: 282px; width:425px;'> </div> {% endif %} + <div style='padding: 5px; margin: 8px 0px;' class='ui-state-highlight'><span class='icon-left ui-icon ui-icon-info'> </span> There are <b>{{ resource_level.value }}</b> trees left. --- a/vcweb/forestry/views.py Wed Jun 22 01:50:58 2011 -0700 +++ b/vcweb/forestry/views.py Wed Jun 22 09:22:27 2011 -0700 @@ -70,7 +70,8 @@ experiment = group.experiment participant_history = deque() for round_data in experiment.playable_round_data: - logger.debug("generating participant history for %s", round_data) + logger.debug("generating participant history for %s, current round %s", + participant_group_relationship.participant, round_data) data = ParticipantRoundData() # FIXME: this kind of binding is a bit laborious and error-prone, refactor if possible data.round_configuration = round_data.round_configuration --- a/vcweb/vcwebio.py Wed Jun 22 01:50:58 2011 -0700 +++ b/vcweb/vcwebio.py Wed Jun 22 09:22:27 2011 -0700 @@ -1,6 +1,7 @@ #!/usr/bin/env python import tornado.web from tornadio import SocketConnection, get_router, server +from tornado.escape import xhtml_escape import os import sys import logging @@ -18,17 +19,6 @@ def info_json(message): return simplejson.dumps({'message_type': 'info', 'message': message}) -def goto_json(url): - return simplejson.dumps({'message_type': 'goto', 'url': url}) - -def chat_json(chat_message): - return simplejson.dumps({ - "pk": chat_message.pk, - "date_created": chat_message.date_created.strftime("%H:%M:%S"), - "message" : unicode(chat_message), - "message_type": 'chat', - }) - class ConnectionManager: ''' Manages socket.io connections to tornadio. @@ -259,7 +249,7 @@ 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, + message=xhtml_escape(event.message), round_data=current_round_data ) chat_json = simplejson.dumps({ Repository URL: https://bitbucket.org/virtualcommons/vcweb/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <iss...@bi...> - 2011-06-22 15:40:30
|
--- you can reply above this line --- New issue 21: socket.io tornadio issues when logging in twice https://bitbucket.org/virtualcommons/vcweb/issue/21/socketio-tornadio-issues-when-logging-in virtualcommons on Wed, 22 Jun 2011 17:40:23 +0200: Description: Few issues: # Somehow weird HTML is getting inserted as the message # Need to make sure we are untainting the chat messages {{{ #!python DEBUG 2011-06-22 08:25:26,310 [tornadio.vcweb|send_to_experimenter:148] sending to connection <__main__.ExperimenterHandler object at 0x133f8210> DEBUG 2011-06-22 08:25:30,089 [tornadio.vcweb|on_message:227] received message {u'participant_group_relationship_id': 3, u'message': u'<img src="http://c.sme.sk/imgs/pager/ico1.gif" class="ico"/><a href="#" id="smepager_menu1" onMouseOver="smepager_showTime(\'smepager_drop1\');" onMouseOut="smepager_hideTime(\'smepager_drop1\');">Spr\xe1vy</a><img src="http://c.sme.sk/imgs/pager/sipka.gif" alt="+"/>', u'message_type': u'chat', u'participant_experiment_relationship_id': 11} from handler <__main__.ParticipantHandler object at 0x1390c3d0> DEBUG 2011-06-22 08:25:30,090 [tornadio.vcweb|get_participant_group_relationship:76] Looking for ParticipantGroupRelationship with tuple (11, 2) DEBUG 2011-06-22 08:25:30,109 [tornadio.vcweb|send_to_experimenter:145] sending {"participant": "Student 1 (s1...@as...)", "message_type": "chat", "date_created": "08:25:30", "pk": 91, "message": "3: <img src=\"http://c.sme.sk/imgs/pager/ico1.gif\" class=\"ico\"/><a href=\"#\" id=\"smepager_menu1\" onMouseOver=\"smepager_showTime('smepager_drop1');\" onMouseOut=\"smepager_hideTime('smepager_drop1');\">Spr\u00e1vy</a><img src=\"http://c.sme.sk/imgs/pager/sipka.gif\" alt=\"+\"/>", "round_data_pk": 14} to experimenter (3, 2) sending to connection <__main__.ExperimenterHandler object at 0x133f8210> DEBUG 2011-06-22 08:26:22,270 [tornadio.vcweb|on_message:227] received message {u'participant_group_relationship_id': 2, u'message': u'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Virtual Commons Web Login</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="/static/css/blueprint/screen.css" type="text/css" media="screen, projection" /> <link rel="stylesheet" href="/static/css/blueprint/print.css" type="text/css" media="print" /> <!--[if lt IE 8]><link rel="stylesheet" href="/static/media/css/blueprint/ie.css" type="text/css" media="screen, projection" /><![endif]--> <link href="/static/css/guarantee/style.css" rel="stylesheet" type="text/css" media="screen" /> <link href="/static/css/style.css" rel="stylesheet" type="text/css" media="screen" /> <!-- vcweb common js --> <script type=\'text/javascript\' src=\'https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js\'></script> <script type=\'text/javascript\' src=\'/static/js/common.js\'></script> <script type=\'text/javascript\' src=\'/static/js/jquery.qtip-1.0.0-rc3.min.js\'></script> <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/pepper-grinder/jquery-ui.css" rel="stylesheet" type="text/css" media="screen" /> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js"></script> <script type=\'text/javascript\' src=\'/static/js/dajaxice.core.js\' charset=\'utf-8\'></script> <script type=\'text/javascript\'> <!-- sets all external links to open up in new windows and jquery-ui buttonifies all buttons--> $(function() { $(\'a.external\').attr({ target: "_blank" }); $(\'button\').button(); }); </script> <script type=\'text/javascript\' src=\'/static/js/jquery.validate.min.js\'></script> <script type=\'text/javascript\'> $(function() { $(\':input\').addClass(\'required\'); $(\'#vcweb-form\').validate(); $(\'#id_email\').focus(); }); </script> </head> <body> <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> virtual commons web environment </h1> </div> <div id=\'header\'> <div id=\'menu\'> <ul> \t<li class=\'inactive\' ><a href=\'/\' class=\'first\'>Home</a></li> \t \t<li class=\'inactive\'><a href=\'/about/\'>About</a></li> \t<li class=\'inactive\'><a href=\'/contact/\'>Contact us</a></li> \t<li class=\'active inactive\'><a href=\'/accounts/login/\'>Login/Register</a></li> \t </ul> </div> </div> <div id=\'page\'> <noscript> <div class=\'alert alertIcon ui-corner-all\'> Please <b>enable JavaScript</b> before using this site. <br/>Our experiments are highly interactive and <b>will not function properly</b> without JavaScript. </div> </noscript> <form id=\'vcweb-form\' action=\'\' method=\'post\'> <h3>Returning User</h3> <p> Don't have an account or a first-time user? Please <a href=\'/accounts/register/\'>register first</a>. </p> <div class=\'field\'> <span class=\'label\' ><label for="id_email">Email</label>:</span> <input id="id_email" type="text" class="required email" name="email" /> </div> <div class=\'field\'> <span class=\'label\' ><label for="id_password">Password</label>:</span> <input id="id_password" type="password" class="required" name="password" /> </div> <div><button type=\'submit\' class=\'submit\'>Login</button></div> </form> <div style=\'clear: both;\'> </div> <!-- end #page --> </div> <div id="footer"> <p> <a href=\'http://shesc.asu.edu\'>School of Human Evolution and Social Change</a> <br /> <a href=\'http://csid.asu.edu\'>Center for the Study of Institutional Diversity</a> </p> <p class=\'legal\'> Copyright (c) 2010 Arizona Board of Regents. Design adapted from <a href="http://www.freecsstemplates.org/">Free CSS Templates</a>.<br/> This project is funded by the <a href=\'http://nsf.gov\'>National Science Foundation</a> and <a href=\'http://www.asu.edu\'>Arizona State University</a>. <br /> </p> </div> </body> </html> ', u'message_type': u'chat', u'participant_experiment_relationship_id': 15} from handler <__main__.ParticipantHandler object at 0x13b34350> }}} Responsible: alllee -- This is an issue notification from bitbucket.org. You are receiving this either because you are the owner of the issue, or you are following the issue. |