[virtualcommons-svn] commit/vcweb: alllee: renaming boundaries experiment app name for consistency,
Status: Beta
Brought to you by:
alllee
From: <com...@bi...> - 2013-04-22 08:54:25
|
1 new commit in vcweb: https://bitbucket.org/virtualcommons/vcweb/commits/0aa66ba02800/ Changeset: 0aa66ba02800 User: alllee Date: 2013-04-22 10:53:59 Summary: renaming boundaries experiment app name for consistency, fixes issue 103 Affected #: 33 files diff -r 5408d2dc620855130cbaed113ab17774ecd380bb -r 0aa66ba028003619ad69610ba68d54fc056e7a8c vcweb/bound/fixtures/bound_experiment_metadata.json --- /dev/null +++ b/vcweb/bound/fixtures/bound_experiment_metadata.json @@ -0,0 +1,16 @@ +[ + { + "pk": 6, + "model": "core.experimentmetadata", + "fields": { + "description": "The boundary effect experiment manipulates the resource flows and information connections between social groups and ecological resources.", + "short_name": null, + "title": "Boundary Effects Experiment", + "namespace": "bound", + "last_modified": "2012-10-29T16:42:20.880", + "date_created": "2012-10-29T16:42:20.874", + "logo_url": null, + "about_url": "http://commons.asu.edu" + } + } +] diff -r 5408d2dc620855130cbaed113ab17774ecd380bb -r 0aa66ba028003619ad69610ba68d54fc056e7a8c vcweb/bound/fixtures/bound_parameters.json --- /dev/null +++ b/vcweb/bound/fixtures/bound_parameters.json @@ -0,0 +1,67 @@ +[ + { + "fields": { + "name":"player_status", + "experiment_metadata": 1, + "creator": 1, + "type": "int", + "date_created": "2011-01-01 15:13:03", + "last_modified": "2011-01-01 15:13:05", + "scope": "participant" + }, + "model": "core.parameter", + "pk": 1111 + }, + { + "fields": { + "name":"regrowth_rate", + "experiment_metadata": 1, + "creator": 1, + "type": "float", + "date_created": "2011-01-01 15:13:03", + "last_modified": "2011-01-01 15:13:05", + "scope": "round" + }, + "model": "core.parameter", + "pk": 1112 + }, + { + "fields": { + "name":"cost_of_living", + "experiment_metadata": 1, + "creator": 1, + "type": "float", + "date_created": "2011-01-01 15:13:03", + "last_modified": "2011-01-01 15:13:05", + "scope": "round" + }, + "model": "core.parameter", + "pk": 1113 + }, + { + "fields": { + "name":"shared_resource", + "experiment_metadata": 1, + "creator": 1, + "type": "boolean", + "date_created": "2011-01-01 15:13:03", + "last_modified": "2011-01-01 15:13:05", + "scope": "round" + }, + "model": "core.parameter", + "pk": 1114 + }, + { + "fields": { + "name":"storage", + "experiment_metadata": 1, + "creator": 1, + "type": "int", + "date_created": "2011-01-01 15:13:07", + "last_modified": "2011-01-01 15:15:05", + "scope": "participant" + }, + "model": "core.parameter", + "pk": 1115 + } +] diff -r 5408d2dc620855130cbaed113ab17774ecd380bb -r 0aa66ba028003619ad69610ba68d54fc056e7a8c vcweb/bound/forms.py --- /dev/null +++ b/vcweb/bound/forms.py @@ -0,0 +1,8 @@ +from vcweb.core.forms import ParticipantGroupIdForm, SingleIntegerDecisionForm +from vcweb.forestry import forms + + +class HarvestDecisionForm(forms.HarvestDecisionForm): +# XXX: only used to export HarvestDecisionForm in its own namespace at the moment + pass + diff -r 5408d2dc620855130cbaed113ab17774ecd380bb -r 0aa66ba028003619ad69610ba68d54fc056e7a8c vcweb/bound/migrations/0001_initial.py --- /dev/null +++ b/vcweb/bound/migrations/0001_initial.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + from django.core.management import call_command + call_command("loaddata", "bound_experiment_metadata.json") + + def backwards(self, orm): + pass + + models = { + + } + + complete_apps = ['bound'] diff -r 5408d2dc620855130cbaed113ab17774ecd380bb -r 0aa66ba028003619ad69610ba68d54fc056e7a8c vcweb/bound/migrations/0002_max_harvest_decision.py --- /dev/null +++ b/vcweb/bound/migrations/0002_max_harvest_decision.py @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + def forwards(self, orm): + "Write your forwards methods here." + # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..." + Parameter = orm['core.Parameter'] + Experimenter = orm['core.Experimenter'] + Parameter.objects.create(name='max_harvest_decision', + creator=Experimenter.objects.get(pk=1), + type='int', + scope='experiment', + default_value_string='10', + description='Maximum harvest decision a player can make in a typical harvesting experiment') + + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'core.activitylog': { + 'Meta': {'object_name': 'ActivityLog'}, + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'log_message': ('django.db.models.fields.TextField', [], {}) + }, + u'core.address': { + 'Meta': {'object_name': 'Address'}, + 'city': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), + 'street1': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'street2': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'zipcode': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}) + }, + u'core.chatmessage': { + 'Meta': {'ordering': "['date_created']", 'object_name': 'ChatMessage', '_ormbases': [u'core.ParticipantRoundDataValue']}, + u'participantrounddatavalue_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['core.ParticipantRoundDataValue']", 'unique': 'True', 'primary_key': 'True'}), + 'target_participant': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'target_participant_chat_message_set'", 'null': 'True', 'to': u"orm['core.ParticipantGroupRelationship']"}) + }, + u'core.comment': { + 'Meta': {'ordering': "['date_created']", 'object_name': 'Comment', '_ormbases': [u'core.ParticipantRoundDataValue']}, + u'participantrounddatavalue_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['core.ParticipantRoundDataValue']", 'unique': 'True', 'primary_key': 'True'}) + }, + u'core.experiment': { + 'Meta': {'ordering': "['date_created', 'status']", 'object_name': 'Experiment'}, + 'amqp_exchange_name': ('django.db.models.fields.CharField', [], {'default': "'vcweb.default.exchange'", 'max_length': '64'}), + 'authentication_code': ('django.db.models.fields.CharField', [], {'default': "'vcweb.auth.code'", 'max_length': '32'}), + 'current_repeated_round_sequence_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'current_round_elapsed_time': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'current_round_sequence_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'current_round_start_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'duration': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + 'experiment_configuration': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.ExperimentConfiguration']"}), + 'experiment_metadata': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.ExperimentMetadata']"}), + 'experimenter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Experimenter']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'start_date_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'INACTIVE'", 'max_length': '32'}), + 'tick_duration': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + 'total_elapsed_time': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + u'core.experimentactivitylog': { + 'Meta': {'object_name': 'ExperimentActivityLog', '_ormbases': [u'core.ActivityLog']}, + u'activitylog_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['core.ActivityLog']", 'unique': 'True', 'primary_key': 'True'}), + 'experiment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_log_set'", 'to': u"orm['core.Experiment']"}), + 'round_configuration': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.RoundConfiguration']"}) + }, + u'core.experimentconfiguration': { + 'Meta': {'ordering': "['experiment_metadata', 'creator', 'date_created']", 'object_name': 'ExperimentConfiguration'}, + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'experiment_configuration_set'", 'to': u"orm['core.Experimenter']"}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'exchange_rate': ('django.db.models.fields.DecimalField', [], {'default': '0.2', 'null': 'True', 'max_digits': '6', 'decimal_places': '2', 'blank': 'True'}), + 'experiment_metadata': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'experiment_configuration_set'", 'to': u"orm['core.ExperimentMetadata']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'invitation_subject': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'invitation_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'is_experimenter_driven': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'max_group_size': ('django.db.models.fields.PositiveIntegerField', [], {'default': '5'}), + 'max_number_of_participants': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'treatment_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}) + }, + u'core.experimenter': { + 'Meta': {'ordering': "['user']", 'object_name': 'Experimenter'}, + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'authentication_token': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'failed_password_attempts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Institution']", 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'experimenter'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + u'core.experimenterrequest': { + 'Meta': {'object_name': 'ExperimenterRequest'}, + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'core.experimentmetadata': { + 'Meta': {'ordering': "['namespace', 'date_created']", 'object_name': 'ExperimentMetadata'}, + 'about_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'default_configuration': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.ExperimentConfiguration']", 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'logo_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'namespace': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'short_name': ('django.db.models.fields.SlugField', [], {'max_length': '32', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + u'core.experimentparametervalue': { + 'Meta': {'object_name': 'ExperimentParameterValue'}, + 'boolean_value': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}), + 'experiment_configuration': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parameter_value_set'", 'to': u"orm['core.ExperimentConfiguration']"}), + 'float_value': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'int_value': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'parameter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Parameter']"}), + 'string_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + u'core.experimentsession': { + 'Meta': {'object_name': 'ExperimentSession'}, + 'capacity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '20'}), + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'experiment_session_set'", 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'experiment_metadata': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'experiment_session_set'", 'to': u"orm['core.ExperimentMetadata']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'invitation_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'scheduled_date': ('django.db.models.fields.DateTimeField', [], {}), + 'scheduled_end_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + u'core.group': { + 'Meta': {'ordering': "['experiment', 'number']", 'object_name': 'Group'}, + 'experiment': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Experiment']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'max_size': ('django.db.models.fields.PositiveIntegerField', [], {'default': '5'}), + 'number': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'session_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) + }, + u'core.groupactivitylog': { + 'Meta': {'object_name': 'GroupActivityLog', '_ormbases': [u'core.ActivityLog']}, + u'activitylog_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['core.ActivityLog']", 'unique': 'True', 'primary_key': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_log_set'", 'to': u"orm['core.Group']"}), + 'round_configuration': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.RoundConfiguration']"}) + }, + u'core.groupcluster': { + 'Meta': {'ordering': "['date_created']", 'object_name': 'GroupCluster'}, + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'experiment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_cluster_set'", 'to': u"orm['core.Experiment']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'session_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) + }, + u'core.groupclusterdatavalue': { + 'Meta': {'object_name': 'GroupClusterDataValue'}, + 'boolean_value': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}), + 'float_value': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'group_cluster': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.GroupCluster']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'int_value': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'parameter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Parameter']"}), + 'round_data': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_cluster_data_value_set'", 'to': u"orm['core.RoundData']"}), + 'string_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + u'core.grouprelationship': { + 'Meta': {'ordering': "['date_created']", 'object_name': 'GroupRelationship'}, + 'cluster': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_relationship_set'", 'to': u"orm['core.GroupCluster']"}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'core.grouprounddatavalue': { + 'Meta': {'ordering': "['round_data', 'group', 'parameter']", 'object_name': 'GroupRoundDataValue'}, + 'boolean_value': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}), + 'float_value': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'data_value_set'", 'to': u"orm['core.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'int_value': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'parameter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Parameter']"}), + 'round_data': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_data_value_set'", 'to': u"orm['core.RoundData']"}), + 'string_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + u'core.institution': { + 'Meta': {'object_name': 'Institution'}, + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + }, + u'core.invitation': { + 'Meta': {'object_name': 'Invitation'}, + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'experiment_session': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.ExperimentSession']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'participant': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Participant']"}), + 'sender': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + u'core.like': { + 'Meta': {'ordering': "['-date_created', 'round_data', 'participant_group_relationship', 'parameter']", 'object_name': 'Like', '_ormbases': [u'core.ParticipantRoundDataValue']}, + u'participantrounddatavalue_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['core.ParticipantRoundDataValue']", 'unique': 'True', 'primary_key': 'True'}) + }, + u'core.parameter': { + 'Meta': {'ordering': "['name']", 'unique_together': "(('name', 'experiment_metadata', 'scope'),)", 'object_name': 'Parameter'}, + 'class_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Experimenter']"}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'default_value_string': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'enum_choices': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'experiment_metadata': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.ExperimentMetadata']", 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'scope': ('django.db.models.fields.CharField', [], {'default': "'round'", 'max_length': '32'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '32'}) + }, + u'core.participant': { + 'Meta': {'ordering': "['user']", 'object_name': 'Participant'}, + 'address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Address']", 'null': 'True', 'blank': 'True'}), + 'authentication_token': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'birthdate': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'can_receive_invitations': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'experiments': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'participant_set'", 'symmetrical': 'False', 'through': u"orm['core.ParticipantExperimentRelationship']", 'to': u"orm['core.Experiment']"}), + 'failed_password_attempts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'gender': ('django.db.models.fields.CharField', [], {'max_length': '1', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'participant_set'", 'symmetrical': 'False', 'through': u"orm['core.ParticipantGroupRelationship']", 'to': u"orm['core.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'institution': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Institution']", 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'participant'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + u'core.participantexperimentrelationship': { + 'Meta': {'object_name': 'ParticipantExperimentRelationship'}, + 'additional_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'current_location': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'experiment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'participant_relationship_set'", 'to': u"orm['core.Experiment']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_completed_round_sequence_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'participant': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'experiment_relationship_set'", 'to': u"orm['core.Participant']"}), + 'participant_identifier': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'sequential_participant_identifier': ('django.db.models.fields.PositiveIntegerField', [], {}) + }, + u'core.participantgrouprelationship': { + 'Meta': {'ordering': "['group', 'participant_number']", 'object_name': 'ParticipantGroupRelationship'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'first_visit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'participant_group_relationship_set'", 'to': u"orm['core.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notifications_since': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'blank': 'True'}), + 'participant': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'participant_group_relationship_set'", 'to': u"orm['core.Participant']"}), + 'participant_number': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'round_joined': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.RoundConfiguration']"}) + }, + u'core.participantrounddatavalue': { + 'Meta': {'ordering': "['-date_created', 'round_data', 'participant_group_relationship', 'parameter']", 'object_name': 'ParticipantRoundDataValue'}, + 'boolean_value': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}), + 'float_value': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'int_value': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'parameter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Parameter']"}), + 'participant_group_relationship': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'data_value_set'", 'to': u"orm['core.ParticipantGroupRelationship']"}), + 'round_data': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'participant_data_value_set'", 'to': u"orm['core.RoundData']"}), + 'string_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'submitted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'target_data_value': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'target_data_value_set'", 'null': 'True', 'to': u"orm['core.ParticipantRoundDataValue']"}) + }, + u'core.participantsignup': { + 'Meta': {'object_name': 'ParticipantSignup'}, + 'attendance': ('django.db.models.fields.PositiveIntegerField', [], {'max_length': '1', 'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'invitation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'signup_set'", 'to': u"orm['core.Invitation']"}), + 'participant': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'signup_set'", 'to': u"orm['core.Participant']"}) + }, + u'core.quizquestion': { + 'Meta': {'object_name': 'QuizQuestion'}, + 'answer': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'experiment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'default_quiz_question_set'", 'null': 'True', 'to': u"orm['core.Experiment']"}), + 'explanation': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'input_type': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'round_configuration': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'quiz_question_set'", 'to': u"orm['core.RoundConfiguration']"}) + }, + u'core.roundconfiguration': { + 'Meta': {'ordering': "['experiment_configuration', 'sequence_number', 'date_created']", 'object_name': 'RoundConfiguration'}, + 'chat_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'create_group_clusters': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'debriefing': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'display_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'duration': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'experiment_configuration': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'round_configuration_set'", 'to': u"orm['core.ExperimentConfiguration']"}), + 'group_cluster_size': ('django.db.models.fields.PositiveIntegerField', [], {'default': '2'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'instructions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'preserve_existing_groups': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'randomize_groups': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'repeat': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'round_type': ('django.db.models.fields.CharField', [], {'default': "'REGULAR'", 'max_length': '32'}), + 'sequence_number': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'session_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'survey_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'template_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) + }, + u'core.rounddata': { + 'Meta': {'ordering': "['round_configuration']", 'unique_together': "(('round_configuration', 'experiment'),)", 'object_name': 'RoundData'}, + 'elapsed_time': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'experiment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'round_data_set'", 'to': u"orm['core.Experiment']"}), + 'experimenter_notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'round_configuration': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'round_data_set'", 'to': u"orm['core.RoundConfiguration']"}) + }, + u'core.roundparametervalue': { + 'Meta': {'object_name': 'RoundParameterValue'}, + 'boolean_value': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}), + 'float_value': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'int_value': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'last_modified': ('vcweb.core.models.AutoDateTimeField', [], {'default': 'datetime.datetime.now'}), + 'parameter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.Parameter']"}), + 'round_configuration': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parameter_value_set'", 'to': u"orm['core.RoundConfiguration']"}), + 'string_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + u'core.spoolparticipantstatistics': { + 'Meta': {'object_name': 'SpoolParticipantStatistics'}, + 'absences': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'discharges': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'invitations': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'participant': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'spool_statistics_set'", 'to': u"orm['core.Participant']"}), + 'participations': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + } + } + + complete_apps = ['core', 'bound'] + symmetrical = True diff -r 5408d2dc620855130cbaed113ab17774ecd380bb -r 0aa66ba028003619ad69610ba68d54fc056e7a8c vcweb/bound/models.py --- /dev/null +++ b/vcweb/bound/models.py @@ -0,0 +1,426 @@ +from django.db.models import Sum +from django.dispatch import receiver +from vcweb.core import signals, simplecache +from vcweb.core.models import (ExperimentMetadata, Parameter, ParticipantRoundDataValue, GroupRelationship, + GroupCluster, GroupClusterDataValue, RoundData, RoundConfiguration) +from vcweb.forestry.models import (get_harvest_decision_parameter, get_harvest_decision, get_harvest_decision_dv, get_regrowth_rate_parameter, + get_group_harvest_parameter, get_reset_resource_level_parameter, get_resource_level as get_unshared_resource_level, + get_initial_resource_level as forestry_initial_resource_level, get_regrowth_parameter, set_resource_level, + get_resource_level_parameter, get_resource_level_dv as get_unshared_resource_level_dv, + set_group_harvest, set_regrowth, set_harvest_decision) + +import logging + +logger = logging.getLogger(__name__) + +# FIXME: hacky, should figure out a better way to bind this module with the ExperimentMetadata instance that it is +# dependent on +EXPERIMENT_METADATA_NAME = intern('bound') +# constants that should live in configuration as well +MAX_RESOURCE_LEVEL = 240 +MAX_SHARED_RESOURCE_LEVEL = 480 + +INITIAL_RESOURCES_PER_PARTICIPANT_PER_ROUND = 3 + +''' +Experiment Parameters and Metadata Accessors +''' + + +@simplecache +def get_experiment_metadata(): + return ExperimentMetadata.objects.get(namespace=EXPERIMENT_METADATA_NAME) + + +@simplecache +def get_player_status_parameter(): + return Parameter.objects.for_participant(name='player_status') + + +@simplecache +def get_storage_parameter(): + return Parameter.objects.for_participant(name='storage') + + +@simplecache +def get_survival_cost_parameter(): + return Parameter.objects.for_round(name='survival_cost') + + +@simplecache +def get_max_harvest_decision_parameter(): + return Parameter.objects.for_experiment(name='max_harvest_decision') + + +@simplecache +def get_cost_of_living_parameter(): + return Parameter.objects.for_round(name='cost_of_living') + + +@simplecache +def get_observe_other_group_parameter(): + return Parameter.objects.for_round(name='observe_other_group') + + +@simplecache +def get_shared_resource_enabled_parameter(): + return Parameter.objects.for_round(name='shared_resource') + + +''' value accessors ''' + +''' round and experiment configuration accessors ''' +def get_regrowth_rate(round_configuration): + return round_configuration.get_parameter_value(parameter=get_regrowth_rate_parameter(), default=0.40).float_value + + +def can_observe_other_group(round_configuration): + return round_configuration.get_parameter_value(parameter=get_observe_other_group_parameter(), + default=False).boolean_value + + +def is_shared_resource_enabled(round_configuration): + return round_configuration.get_parameter_value(parameter=get_shared_resource_enabled_parameter(), + default=False).boolean_value + +def get_max_resource_level(round_configuration): + ec = round_configuration.experiment_configuration +# FIXME: number of rounds currently hard coded to be 20 for regular rounds, 10 for practice rounds + number_of_rounds = 20 if round_configuration.is_regular_round else 10 + return INITIAL_RESOURCES_PER_PARTICIPANT_PER_ROUND * ec.max_group_size * number_of_rounds + +def get_initial_resource_level(round_configuration, default=None): + return get_max_resource_level(round_configuration) + +def should_reset_resource_level(round_configuration): + return round_configuration.get_parameter_value(parameter=get_reset_resource_level_parameter(), + default=False).boolean_value + +def get_cost_of_living(round_configuration): + return round_configuration.get_parameter_value(get_cost_of_living_parameter(), default=5).int_value + + +def get_max_harvest_decision(experiment_configuration): + return experiment_configuration.get_parameter_value(parameter=get_max_harvest_decision_parameter(), default=10).int_value + +def get_max_allowed_harvest_decision(participant_group_relationship, round_data=None, experiment_configuration=None): + return get_max_harvest_decision(experiment_configuration) + +def get_resource_level(group, round_data=None, round_configuration=None, cluster=None): + return get_resource_level_dv(group, round_data, round_configuration, cluster).int_value + +''' group data accessors ''' +def get_average_harvest(group, round_data): + return get_total_group_harvest(group, round_data) / float(group.size) + +def get_average_storage(group, round_data): + return get_total_storage(group, round_data) / float(group.size) + +def get_resource_level_dv(group, round_data=None, round_configuration=None, cluster=None): + ''' + Returns either the GroupClusterDataValue (shared resource condition) or the GroupRoundDataValue (standard + resource per group condition) for the given group + ''' + if round_data is None: + round_data = group.current_round_data + if round_configuration is None: + round_configuration = round_data.round_configuration + if is_shared_resource_enabled(round_configuration): + return get_shared_resource_level_dv(group, round_data, cluster) + else: + return get_unshared_resource_level_dv(group, round_data) + + +def get_shared_resource_level(group, round_data=None, cluster=None): + return get_shared_resource_level_dv(group, round_data, cluster).int_value + + +def get_shared_resource_level_dv(group=None, round_data=None, cluster=None): + if round_data is None: + round_data = group.current_round_data + if cluster is None: + group_relationship = GroupRelationship.objects.select_related('group_cluster').get(group=group) + cluster = group_relationship.cluster + return cluster.get_data_value(parameter=get_resource_level_parameter(), round_data=round_data) + +''' participant data value accessors ''' + +def get_storage_dv(participant_group_relationship, round_data=None, default=None): + return participant_group_relationship.get_data_value(parameter=get_storage_parameter(), round_data=round_data, default=default) + + +def get_storage(participant_group_relationship, round_data=None, default=0): + dv = get_storage_dv(participant_group_relationship, round_data, default) + return max(default if dv.int_value is None else dv.int_value, 0) + +def get_all_session_storages(experiment, participant_group_relationship): + debriefing_session_round_data = RoundData.objects.filter(experiment=experiment, + round_configuration__round_type=RoundConfiguration.RoundType.DEBRIEFING, + round_configuration__session_id__isnull=False) + return ParticipantRoundDataValue.objects.filter( + participant_group_relationship=participant_group_relationship, + parameter=get_storage_parameter(), + round_data__in=debriefing_session_round_data).order_by('date_created') + + +def _zero_if_none(value): + return 0 if value is None else value + +def get_total_group_harvest(group, round_data): + q = ParticipantRoundDataValue.objects.for_group(group=group, parameter=get_harvest_decision_parameter(), round_data=round_data).aggregate(total_harvest=Sum('int_value')) + return _zero_if_none(q['total_harvest']) + + +def get_total_harvest(participant_group_relationship, session_id): + q = ParticipantRoundDataValue.objects.for_participant(participant_group_relationship, parameter=get_harvest_decision_parameter(), + participant_group_relationship__group__session_id=session_id).aggregate(total_harvest=Sum('int_value')) + return _zero_if_none(q['total_harvest']) + +# returns the sum of all stored resources for each member in the group +def get_total_storage(group, round_data): + q = ParticipantRoundDataValue.objects.for_group(group=group, parameter=get_storage_parameter(), round_data=round_data).aggregate(total_storage=Sum('int_value')) + return _zero_if_none(q['total_storage']) + +def set_storage(participant_group_relationship, round_data, value): + storage_dv = get_storage_dv(participant_group_relationship, round_data) + storage_dv.int_value = value + storage_dv.save() + return storage_dv + +def get_player_status_dv(participant_group_relationship, round_data, default=True): + return participant_group_relationship.get_data_value(parameter=get_player_status_parameter(), + round_data=round_data, default=default) + +def get_player_status(participant_group_relationship, round_data, default=True): + return get_player_status_dv(participant_group_relationship, round_data, default).boolean_value + +def set_player_status(participant_group_relationship, round_data, value): + status_dv = get_player_status_dv(participant_group_relationship, round_data) + status_dv.boolean_value = value + status_dv.save() + return status_dv + +def get_last_harvest_decision(participant_group_relationship, round_data=None): + return participant_group_relationship.get_data_value(parameter=get_harvest_decision_parameter(), + round_data=round_data, default=0).int_value + + +@receiver(signals.round_started, sender=EXPERIMENT_METADATA_NAME) +def round_started_handler(sender, experiment=None, **kwargs): + if experiment is None: + logger.error("Received round started signal with no experiment: %s", sender) + raise ValueError("Received round started signal with no experiment") + round_configuration = experiment.current_round + round_data = experiment.get_round_data(round_configuration) + logger.debug("setting up round %s", round_configuration) + # initialize group and participant data values + if round_configuration.is_playable_round: + 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(),) + ) +# 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(), + round_data=round_data, boolean_value=False) + for prdv in deceased_participants: + pgr = prdv.participant_group_relationship + set_harvest_decision(pgr, 0, round_data, submitted=True) + ''' + during a practice or regular round, set up resource levels, participant harvest decision parameters, and group + formation + ''' + if should_reset_resource_level(round_configuration): + initial_resource_level = get_max_resource_level(round_configuration) + logger.debug("Resetting resource level for %s to %d", round_configuration, initial_resource_level) + for group in experiment.group_set.filter(session_id=round_configuration.session_id): + ''' set resource level to initial default ''' + existing_resource_level = get_resource_level_dv(group, round_data, round_configuration) + group.log( + "Setting resource level (%s) to initial value [%s]" % (existing_resource_level, initial_resource_level)) + existing_resource_level.int_value = initial_resource_level + existing_resource_level.save() + # FIXME: verify that this is expected behavior - if the resource level is reset, reset storage to 0 + ParticipantRoundDataValue.objects.for_group(group, parameter=get_storage_parameter(), + round_data=round_data).update(int_value=0) + # reset all player statuses to alive + ParticipantRoundDataValue.objects.for_group(group, parameter=get_player_status_parameter(), + round_data=round_data).update(boolean_value=True) + + + +def adjust_harvest_decisions(current_resource_level, group, round_data, total_harvest, group_size=0): + if group_size == 0: + group_size = group.size +# pass in the group size to handle group cluster case + average_harvest = current_resource_level / group_size + group.log("GROUP HARVEST ADJUSTMENT - original total harvest: %s, resource level: %s, average harvest: %s" % + (total_harvest, current_resource_level, average_harvest)) + hds = ParticipantRoundDataValue.objects.for_group(group=group, parameter=get_harvest_decision_parameter(), + round_data=round_data, int_value__gt=0).order_by('int_value') + total_adjusted_harvest = 0 +# FIXME: should be the same as group.size + total_number_of_decisions = hds.count() + logger.debug("total number of decisions: %s - group size: %s", total_number_of_decisions, group_size) + decisions_allocated = 0 + for hd in hds: + if hd.int_value <= average_harvest: + group.log("preserving %s < average harvest" % hd) + total_adjusted_harvest += hd.int_value + else: +# now to assign the overs, find out how much resource level is remaining + remaining_resource_level = current_resource_level - total_adjusted_harvest + remaining_decisions = total_number_of_decisions - decisions_allocated + average_harvest = remaining_resource_level / remaining_decisions + hd.is_active = False + hd.save() + logger.debug("Assigning %s to hd %s", average_harvest, hd) + ParticipantRoundDataValue.objects.create(participant_group_relationship=hd.participant_group_relationship, + parameter=get_harvest_decision_parameter(), round_data=round_data, int_value=average_harvest, + submitted=True) + total_adjusted_harvest += average_harvest + decisions_allocated += 1 + + logger.debug("harvested total %s", total_adjusted_harvest) + return total_adjusted_harvest + + +def update_resource_level(experiment, group, round_data, regrowth_rate, max_resource_level=None): + if max_resource_level is None: + max_resource_level = get_max_resource_level(round_data.round_configuration) + current_resource_level_dv = get_resource_level_dv(group, round_data) + current_resource_level = current_resource_level_dv.int_value +# FIXME: would be nicer to extend Group behavior and have group.get_total_harvest() instead of +# get_total_group_harvest(group, ...), see if we can enable this dynamically + total_harvest = get_total_group_harvest(group, round_data) + logger.debug("Harvest: total group harvest for playable round: %s", total_harvest) + if current_resource_level > 0: + if total_harvest > current_resource_level: + adjusted_harvest = adjust_harvest_decisions(current_resource_level, group, round_data, total_harvest) + total_harvest = adjusted_harvest + + group.log("Harvest: removing %s from current resource level %s" % (total_harvest, current_resource_level)) + set_group_harvest(group, total_harvest, round_data) + current_resource_level = current_resource_level - total_harvest + resource_regrowth = calculate_regrowth(current_resource_level, regrowth_rate, max_resource_level) + group.log("Regrowth: adding %s to current resource level %s" % (resource_regrowth, current_resource_level)) + set_regrowth(group, resource_regrowth, round_data) + # clamp resource + current_resource_level_dv.int_value = min(current_resource_level + resource_regrowth, max_resource_level) + current_resource_level_dv.save() + else: + group.log("current resource level is 0, no one can harvest") + set_group_harvest(group, 0, round_data) + ParticipantRoundDataValue.objects.for_group(group, parameter=get_harvest_decision_parameter(), + round_data=round_data).update(is_active=False) + for pgr in group.participant_group_relationship_set.all(): + # Create adjusted data values + ParticipantRoundDataValue.objects.create(participant_group_relationship=pgr, + round_data=round_data, parameter=get_harvest_decision_parameter(), + int_value=0) + + + ''' XXX: transfer resource levels across chat and quiz rounds if they exist ''' + if experiment.has_next_round: + ''' set group round data resource_level for each group + regrowth ''' + group.log("Transferring resource level %s to next round" % current_resource_level_dv.int_value) + group.copy_to_next_round(current_resource_level_dv) + + +# FIXME: reduce duplication between this and update_resource_level +def update_shared_resource_level(experiment, group_cluster, round_data, regrowth_rate, max_resource_level=None): + logger.debug("updating shared resource level") + if max_resource_level is None: + max_resource_level = get_max_resource_level(round_data.round_configuration) + max_resource_level = max_resource_level * group_cluster.size + shared_resource_level_dv = get_shared_resource_level_dv(cluster=group_cluster, round_data=round_data) + shared_resource_level = shared_resource_level_dv.int_value + shared_group_harvest = 0 + group_cluster_size = 0 + group_harvest_dict = {} + for group_relationship in group_cluster.group_relationship_set.all(): + group = group_relationship.group + group_cluster_size += group.size + group_harvest = get_total_group_harvest(group, round_data) + group_harvest_dict[group] = group_harvest + shared_group_harvest += group_harvest + group.log("total group harvest: %s" % group_harvest) + for group, group_harvest in group_harvest_dict.items(): + if shared_group_harvest > shared_resource_level: + # adjust each individual harvest for each group in this cluster + group_harvest = adjust_harvest_decisions(shared_resource_level, group, round_data, group_harvest, group_size=group_cluster_size) + set_group_harvest(group, group_harvest, round_data)... [truncated message content] |