-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmodels.py
More file actions
234 lines (188 loc) · 8.61 KB
/
models.py
File metadata and controls
234 lines (188 loc) · 8.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
from otree.api import (
models, BaseConstants, BaseSubsession, BasePlayer
)
from django.contrib.contenttypes.models import ContentType
from otree_redwood.models import Event, DecisionGroup
from otree_redwood.models import Group as RedwoodGroup
import csv
import random
import math
import otree.common
from profanity_filter import ProfanityFilter
pf = ProfanityFilter()
doc = """
This is a Lines Queueing project
"""
class Constants(BaseConstants):
name_in_url = 'queuing_experiment'
players_per_group = None
num_rounds = 50
base_points = 0
def parse_config(config_file):
with open('queuing_experiment/configs/' + config_file) as f:
rows = list(csv.DictReader(f))
rounds = []
for row in rows:
rounds.append({
'round_number': int(row['round_number']),
'group_id': int(row['group_id']),
'duration': int(row['duration']),
'shuffle_role': True if row['shuffle_role'] == 'TRUE' else False,
'players_per_group': int(row['players_per_group']),
'swap_method': str(row['swap_method']),
'messaging': True if row['messaging'] == 'TRUE' else False,
'value': str(row['value']),
'endowment': int(row['endowment']),
'practice': True if row['practice'] == 'TRUE' else False,
})
return rounds
class Subsession(BaseSubsession):
def num_rounds(self):
return len(parse_config(self.session.config['config_file']))
def creating_session(self):
config = self.config
if not config:
return
#Random rounds picked for payment
self.session.vars['payment_round1'] = 0
self.session.vars['payment_round2'] = 0
while self.session.vars['payment_round1'] == 0:
rnd = random.randint(1, self.num_rounds())
if parse_config(self.session.config['config_file'])[rnd-1]['practice']:
pass
else:
self.session.vars['payment_round1'] = rnd
while self.session.vars['payment_round2'] == 0:
rnd = random.randint(1, self.num_rounds())
if parse_config(self.session.config['config_file'])[rnd-1]['practice'] or rnd == self.session.vars['payment_round1']:
pass
else:
self.session.vars['payment_round2'] = rnd
num_silos = self.session.config['num_silos']
fixed_id_in_group = not config['shuffle_role']
players = self.get_players()
num_players = len(players)
silos = [[] for _ in range(num_silos)]
for i, player in enumerate(players):
if self.round_number == 1:
player.silo_num = math.floor(num_silos * i/num_players)
else:
player.silo_num = player.in_round(1).silo_num
silos[player.silo_num].append(player)
group_matrix = []
for silo in silos:
silo_matrix = []
ppg = self.config['players_per_group']
for i in range(0, len(silo), ppg):
silo_matrix.append(silo[i:i+ppg])
group_matrix.extend(otree.common._group_randomly(silo_matrix, fixed_id_in_group))
self.set_group_matrix(group_matrix)
def set_initial_positions(self):
for g in self.get_groups():
players = g.get_players()
positions = [i for i in range(len(players))]
random.shuffle(positions)
for i in range(len(positions)):
players[i]._initial_position = positions[i]
players[i]._final_position = positions[i]
players[i]._initial_decision = 0
def set_initial_decisions(self):
for player in self.get_players():
player._initial_decision = 0
def set_payoffs(self):
for g in self.get_groups():
g.set_payoffs()
@property
def config(self):
try:
return parse_config(self.session.config['config_file'])[self.round_number-1]
except IndexError:
return None
class Group(RedwoodGroup):
def period_length(self):
return parse_config(self.session.config['config_file'])[self.round_number-1]['duration']
def swap_method(self):
return parse_config(self.session.config['config_file'])[self.round_number-1]['swap_method']
def value(self):
return parse_config(self.session.config['config_file'])[self.round_number-1]['value']
def value_list(self):
valueList = [int(i) for i in parse_config(self.session.config['config_file'])[self.round_number-1]['value'].strip('][').split(',')]
print("valueList: ",valueList)
return valueList
def endowment(self):
return parse_config(self.session.config['config_file'])[self.round_number-1]['endowment']
def messaging(self):
return parse_config(self.session.config['config_file'])[self.round_number-1]['messaging']
def practice(self):
return parse_config(self.session.config['config_file'])[self.round_number-1]['practice']
# returns a list of the queue where index is position and value is player id
def queue_list(self):
ppg = parse_config(self.session.config['config_file'])[self.round_number-1]['players_per_group']
queue_list = [0 for i in range(ppg)]
for p in self.get_players():
queue_list[p._initial_position] = p.id_in_group
print("queue_list: ", queue_list)
return queue_list
def set_payoffs(self):
for p in self.get_players():
events = list(self.events.filter(channel='swap'))
p.set_payoff(events)
def _on_swap_event(self, event=None, **kwargs):
type = event.value['type']
# updates states of all players involved in the most recent event that triggered this
# method call
print(event.value)
event.value['channel'] = 'outgoing'
if event.value['type'] == 'request':
if 'message' in event.value:
pf.censor(event.value['message'])
event.value['message'] = pf.censor(event.value['message'])
# broadcast the updated data out to all subjects
self.send('swap', event.value)
self.save()
def _on_report_event(self, event=None, **kwargs):
print(event.value['message'])
self.save()
class Player(BasePlayer):
silo_num = models.IntegerField()
_initial_position = models.IntegerField()
_initial_decision = models.IntegerField()
_final_position = models.IntegerField()
final_payoff = models.CurrencyField()
def initial_position(self):
return self._initial_position
def final_position(self):
return self._final_position
def initial_decision(self):
return self._initial_decision
def num_players(self):
return parse_config(self.session.config['config_file'])[self.round_number-1]['players_per_group']
def set_payoff(self,events):
final_position = self._initial_position
payoff = self.group.endowment()
for event in events:
if event.value['type'] == 'accept' and event.value['channel'] == 'incoming':
amount = event.value['offer']
if self.group.swap_method() == 'Double' and event.value['transfer'] == 0:
pass
else:
if self.group.swap_method() == 'Double':
amount = event.value['transfer']
if self.id_in_group == event.value['senderID']:
final_position = event.value['receiverPosition']
if self.group.swap_method() != 'swap':
payoff += amount
elif self.id_in_group == event.value['receiverID']:
final_position = event.value['senderPosition']
if self.group.swap_method() != 'swap':
payoff -= amount
val_list = self.group.value_list()
payoff += ((self.num_players() + 1 - (final_position + 1)) * val_list[self._initial_position])
self._final_position = final_position
self.payoff += payoff
print('Final Position of', self.id_in_group, ': ', final_position, ' Service Value: ', ((self.num_players() + 1 - (final_position + 1)) * self.group.value()))
#practice round does not count
if self.group.practice():
self.participant.payoff -= self.payoff
if self.round_number == self.subsession.num_rounds():
self.final_payoff = self.in_round(self.session.vars['payment_round1']).payoff + self.in_round(self.session.vars['payment_round2']).payoff