[virtualcommons-svn] commit/vcweb: alllee: fixing issues related to the updated harvest decision su
Status: Beta
Brought to you by:
alllee
|
From: <com...@bi...> - 2013-04-10 00:33:22
|
1 new commit in vcweb: https://bitbucket.org/virtualcommons/vcweb/commits/68867218d8e4/ Changeset: 68867218d8e4 User: alllee Date: 2013-04-10 02:33:12 Summary: fixing issues related to the updated harvest decision submission: - no longer create harvest decision participant data values at the start of the round - at the end of the round this means we can't assume that all harvest decisions have already been made - improving signal handling error messaging a bit and adding a trick for cloning django object instances Affected #: 4 files diff -r bca65c1a5c5073b4dbbeefb3a3fbf553cbce1763 -r 68867218d8e4a370488d378f3f1d1c4baacbd7b7 vcweb/boundaries/models.py --- a/vcweb/boundaries/models.py +++ b/vcweb/boundaries/models.py @@ -208,8 +208,7 @@ experiment.initialize_data_values( group_cluster_parameters=(get_regrowth_parameter(), get_resource_level_parameter(),), group_parameters=(get_regrowth_parameter(), get_group_harvest_parameter(), get_resource_level_parameter(),), - participant_parameters=(get_storage_parameter(), - get_player_status_parameter(),) + participant_parameters=(get_storage_parameter(), get_player_status_parameter(),) ) # check for dead participants and set their ready and harvest decision flags deceased_participants = ParticipantRoundDataValue.objects.select_related('participant_group_relationship').filter(parameter=get_player_status_parameter(), @@ -354,9 +353,10 @@ group.log("Transferring shared resource level %s to next round" % shared_resource_level_dv.int_value) group_cluster.copy_to_next_round(shared_resource_level_dv) -def update_participants(experiment, round_data): +def update_participants(experiment, round_data, round_configuration): logger.debug("updating participants") - cost_of_living = get_cost_of_living(round_data.round_configuration) + cost_of_living = get_cost_of_living(round_configuration) + next_round_data = experiment.round_data_set.get_or_create(round_configuration=experiment.next_round) for pgr in experiment.participant_group_relationships: player_status_dv = get_player_status_dv(pgr, round_data) storage_dv = get_storage_dv(pgr, round_data) @@ -372,7 +372,7 @@ storage_dv.save() logger.debug("updating participant %s (storage: %s, harvest: %s, status: %s)", pgr, storage_dv.int_value, harvest_decision, player_status_dv.boolean_value) - pgr.copy_to_next_round(player_status_dv, storage_dv) + pgr.copy_to_next_round(player_status_dv, storage_dv, next_round_data=next_round_data) @receiver(signals.round_ended, sender=EXPERIMENT_METADATA_NAME) def round_ended_handler(sender, experiment=None, **kwargs): @@ -385,9 +385,20 @@ logger.debug("ending boundaries round: %s", round_configuration) if round_configuration.is_playable_round: regrowth_rate = get_regrowth_rate(round_configuration) + harvest_decision_parameter = get_harvest_decision_parameter() # zero out unsubmitted harvest decisions - ParticipantRoundDataValue.objects.filter(round_data=round_data, parameter=get_harvest_decision_parameter(), - submitted=False).update(int_value=0) + for pgr in experiment.participant_group_relationships: + # FIXME: not thread-safe but this *should* only be invoked once per experiment. If we start getting + # spurious data values, revisit this section + prdv, created = ParticipantRoundDataValue.objects.get_or_create( + round_data=round_data, + participant_group_relationship=pgr, + parameter=harvest_decision_parameter, + is_active=True, + defaults={ 'int_value': 0 }) + if created: + logger.debug("created new harvest decision prdv %s for participant %s", prdv, pgr) + # FIXME: generify and merge update_shared_resource_level and update_resource_level to operate on "group-like" objects if possible if is_shared_resource_enabled(round_configuration): for group_cluster in GroupCluster.objects.for_experiment(experiment, session_id=round_configuration.session_id): @@ -395,7 +406,7 @@ else: for group in experiment.group_set.filter(session_id=round_configuration.session_id): update_resource_level(experiment, group, round_data, regrowth_rate) - update_participants(experiment, round_data) + update_participants(experiment, round_data, round_configuration) def calculate_regrowth(resource_level, regrowth_rate, max_resource_level): diff -r bca65c1a5c5073b4dbbeefb3a3fbf553cbce1763 -r 68867218d8e4a370488d378f3f1d1c4baacbd7b7 vcweb/boundaries/static/css/boundaries/style.css --- a/vcweb/boundaries/static/css/boundaries/style.css +++ b/vcweb/boundaries/static/css/boundaries/style.css @@ -29,4 +29,7 @@ .harvest-decision-resources td { cursor: pointer; } +.harvest-decision-tree:hover { + background-color: yellow; +} diff -r bca65c1a5c5073b4dbbeefb3a3fbf553cbce1763 -r 68867218d8e4a370488d378f3f1d1c4baacbd7b7 vcweb/boundaries/templates/boundaries/participate.html --- a/vcweb/boundaries/templates/boundaries/participate.html +++ b/vcweb/boundaries/templates/boundaries/participate.html @@ -459,7 +459,7 @@ <input id='participantGroupId' type='hidden' name='participant_group_id' data-bind='value: $root.participantGroupId'/><input id='harvestDecisionTextInput' type='hidden' name='integer_decision' data-bind='value: $data'><div class='harvest-decision-tree' data-bind='click: $root.submitDecision.bind($data, "#multi-select-decision-form" + $data)'> - <img data-bind='attr: { src: $root.resourceImageUrl(), alt: "Harvest " + $data + " tree(s)." }'><br> + <img width="40" height="40" data-bind='attr: { src: $root.resourceImageUrl(), alt: "Harvest " + $data + " tree(s)." }'><br><span style='margin-left: 2px;' class='badge badge-success' data-bind='text: $data'></span></div></form> @@ -568,7 +568,7 @@ } return 0; }); - model.resourceImageUrl = ko.observable("{{STATIC_URL}}images/forestry/pine-tree.png"); + model.resourceImageUrl = ko.observable("{{STATIC_URL}}images/boundaries/deciduous-tree.png"); model.resourceImageBackgroundUrl = ko.observable("url('{{STATIC_URL}}images/forestry/pine-tree.png')"); model.resourceImageWidth = ko.computed(function() { return model.resourcesToDisplay() * 30 + "px"; @@ -609,6 +609,7 @@ console.debug("number of trees: " + numberOfTrees); var formData = $(formId).serialize(); model.submitted(true); + model.harvestDecision(numberOfTrees); console.debug(formData); $.post('submit-harvest-decision', formData, function(response) { console.log(response); diff -r bca65c1a5c5073b4dbbeefb3a3fbf553cbce1763 -r 68867218d8e4a370488d378f3f1d1c4baacbd7b7 vcweb/core/models.py --- a/vcweb/core/models.py +++ b/vcweb/core/models.py @@ -886,9 +886,15 @@ if sender is None: sender = intern(self.experiment_metadata.namespace.encode('utf8')) signal_tuple = signals.round_started.send_robust(sender, experiment=self, time=datetime.now(), round_configuration=current_round_configuration) - logger.debug("round started signal returned %s", signal_tuple) + self._check_signal_result(signal_tuple) return signal_tuple + def _check_signal_result(self, signal_tuple_list): + logger.debug("checking signal tuple list: %s", signal_tuple_list) + for signal_tuple in signal_tuple_list: + if signal_tuple[1] is not None: + logger.error("%s resulted in an error condition: %s", signal_tuple[0], signal_tuple[1]) + def stop_round(self, sender=None, **kwargs): return self.end_round() @@ -900,7 +906,7 @@ #sender = self.namespace.encode('utf-8') logger.debug("about to send round ended signal with sender %s", sender) signal_tuple = signals.round_ended.send_robust(sender, experiment=self, round_configuration=self.current_round) - logger.debug("signal tuple: %s", signal_tuple) + self._check_signal_result(signal_tuple) return signal_tuple def activate(self): @@ -1697,13 +1703,14 @@ gcdv.value = value gcdv.save() - def copy_to_next_round(self, *data_values): + def copy_to_next_round(self, next_round_data=None, *data_values): e = self.experiment if e.is_last_round: logger.error("Trying to transfer data values %s past the last round of the experiment, aborting", data_values) else: - next_round_data, created = RoundData.objects.get_or_create(experiment=e, round_configuration=e.next_round) + if not next_round_data: + next_round_data, created = RoundData.objects.get_or_create(experiment=e, round_configuration=e.next_round) for data_value in data_values: parameter = data_value.parameter gcdv, created = GroupClusterDataValue.objects.get_or_create(group_cluster=self, round_data=next_round_data, parameter=parameter) @@ -1952,15 +1959,16 @@ else: logger.warning("Unable to set data value %s on round data %s for %s", value, round_data, parameter) - def copy_to_next_round(self, *data_values): + def copy_to_next_round(self, next_round_data=None, *data_values): e = self.experiment - next_round_data, created = RoundData.objects.get_or_create(experiment=e, round_configuration=e.next_round) + if not next_round_data: + next_round_data, created = RoundData.objects.get_or_create(experiment=e, round_configuration=e.next_round) for existing_dv in data_values: - parameter = existing_dv.parameter - new_dv, created = ParticipantRoundDataValue.objects.get_or_create(participant_group_relationship=self, - round_data=next_round_data, parameter=parameter) - new_dv.value = existing_dv.value - new_dv.save() + # Taking advantage of a trick from here: + # http://stackoverflow.com/questions/12182657/copy-or-clone-an-object-instance-in-django-python + existing_dv.pk = None + existing_dv.round_data = next_round_data + existing_dv.save() def __unicode__(self): return u"{0}: #{1} (in {2})".format(self.participant, self.participant_number, self.group) 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. |