from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) author = 'Your name here' class Constants(BaseConstants): name_in_url = 'second_section' players_per_group = 20 num_rounds = 16 outside_option = 0 # ∅ school_type = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11', 's12', 's13', 's14', 's15', 's16', 's17', 's18', 's19', 's20'] student_type = ['i1', 'i2', 'i3', 'i4', 'i5', 'i6', 'i7', 'i8', 'i9', 'i10', 'i11', 'i12', 'i13', 'i14', 'i15', 'i16', 'i17', 'i18', 'i19', 'i20'] school_id_label = [[type, type] for type in school_type] + [['f', '∅']] student_preference1 = {'i1': ['s4', 's1', 's2', 's3', 's8', 's5', 's6', 's7', 's12', 's9', 's10', 's11', 's16', 's13', 's14', 's15', 's20', 's17', 's18', 's19'], 'i2': ['s4', 's2', 's3', 's1', 's8', 's6', 's7', 's5', 's12', 's10', 's11', 's9', 's16', 's14', 's15', 's13', 's20', 's18', 's19', 's17'], 'i3': ['s2', 's3', 's1', 's4', 's6', 's7', 's5', 's8', 's10', 's11', 's9', 's12', 's14', 's15', 's13', 's16', 's18', 's19', 's17', 's20'], 'i4': ['s2', 's4', 's3', 's1', 's6', 's8', 's7', 's5', 's10', 's12', 's11', 's9', 's14', 's16', 's15', 's13', 's18', 's20', 's19', 's17'], 'i5': ['s8', 's5', 's6', 's7', 's12', 's9', 's10', 's11', 's16', 's13', 's14', 's15', 's20', 's17', 's18', 's19', 's4', 's1', 's2', 's3'], 'i6': ['s8', 's6', 's7', 's5', 's12', 's10', 's11', 's9', 's16', 's14', 's15', 's13', 's20', 's18', 's19', 's17', 's4', 's2', 's3', 's1'], 'i7': ['s6', 's7', 's5', 's8', 's10', 's11', 's9', 's12', 's14', 's15', 's13', 's16', 's18', 's19', 's17', 's20', 's2', 's3', 's1', 's4'], 'i8': ['s6', 's8', 's7', 's5', 's10', 's12', 's11', 's9', 's14', 's16', 's15', 's13', 's18', 's20', 's19', 's17', 's2', 's4', 's3', 's1'], 'i9': ['s12', 's9', 's10', 's11', 's16', 's13', 's14', 's15', 's20', 's17', 's18', 's19', 's4', 's1', 's2', 's3', 's8', 's5', 's6', 's7'], 'i10': ['s12', 's10', 's11', 's9', 's16', 's14', 's15', 's13', 's20', 's18', 's19', 's17', 's4', 's2', 's3', 's1', 's8', 's6', 's7', 's5'], 'i11': ['s10', 's11', 's9', 's12', 's14', 's15', 's13', 's16', 's18', 's19', 's17', 's20', 's2', 's3', 's1', 's4', 's6', 's7', 's5', 's8'], 'i12': ['s10', 's12', 's11', 's9', 's14', 's16', 's15', 's13', 's18', 's20', 's19', 's17', 's2', 's4', 's3', 's1', 's6', 's8', 's7', 's5'], 'i13': ['s16', 's13', 's14', 's15', 's20', 's17', 's18', 's19', 's4', 's1', 's2', 's3', 's8', 's5', 's6', 's7', 's12', 's9', 's10', 's11'], 'i14': ['s16', 's14', 's15', 's13', 's20', 's18', 's19', 's17', 's4', 's2', 's3', 's1', 's8', 's6', 's7', 's5', 's12', 's10', 's11', 's9'], 'i15': ['s14', 's15', 's13', 's16', 's18', 's19', 's17', 's20', 's2', 's3', 's1', 's4', 's6', 's7', 's5', 's8', 's10', 's11', 's9', 's12'], 'i16': ['s14', 's16', 's15', 's13', 's18', 's20', 's19', 's17', 's2', 's4', 's3', 's1', 's6', 's8', 's7', 's5', 's10', 's12', 's11', 's9'], 'i17': ['s20', 's17', 's18', 's19', 's4', 's1', 's2', 's3', 's8', 's5', 's6', 's7', 's12', 's9', 's10', 's11', 's16', 's13', 's14', 's15'], 'i18': ['s20', 's18', 's19', 's17', 's4', 's2', 's3', 's1', 's8', 's6', 's7', 's5', 's12', 's10', 's11', 's9', 's16', 's14', 's15', 's13'], 'i19': ['s18', 's19', 's17', 's20', 's2', 's3', 's1', 's4', 's6', 's7', 's5', 's8', 's10', 's11', 's9', 's12', 's14', 's15', 's13', 's16'], 'i20': ['s18', 's20', 's19', 's17', 's2', 's4', 's3', 's1', 's6', 's8', 's7', 's5', 's10', 's12', 's11', 's9', 's14', 's16', 's15', 's13'], } school_priority1 = {'s1': ['i1', 'i2', 'i3', 'i4', 'i5', 'i6', 'i7', 'i8', 'i9', 'i10', 'i11', 'i12', 'i13', 'i14', 'i15', 'i16', 'i17', 'i18', 'i19', 'i20'], 's2': ['i2', 'i1', 'i3', 'i4', 'i6', 'i5', 'i7', 'i8', 'i10', 'i9', 'i11', 'i12', 'i14', 'i13', 'i15', 'i16', 'i18', 'i17', 'i19', 'i20'], 's3': ['i3', 'i1', 'i2', 'i4', 'i7', 'i5', 'i6', 'i8', 'i11', 'i9', 'i10', 'i12', 'i15', 'i13', 'i14', 'i16', 'i19', 'i17', 'i18', 'i20'], 's4': ['i4', 'i1', 'i2', 'i3', 'i8', 'i5', 'i6', 'i7', 'i12', 'i9', 'i10', 'i11', 'i16', 'i13', 'i14', 'i15', 'i20', 'i17', 'i18', 'i19'], 's5': ['i5', 'i6', 'i7', 'i8', 'i9', 'i10', 'i11', 'i12', 'i13', 'i14', 'i15', 'i16', 'i17', 'i18', 'i19', 'i20', 'i1', 'i2', 'i3', 'i4'], 's6': ['i6', 'i5', 'i7', 'i8', 'i10', 'i9', 'i11', 'i12', 'i14', 'i13', 'i15', 'i16', 'i18', 'i17', 'i19', 'i20', 'i2', 'i1', 'i3', 'i4'], 's7': ['i7', 'i5', 'i6', 'i8', 'i11', 'i9', 'i10', 'i12', 'i15', 'i13', 'i14', 'i16', 'i19', 'i17', 'i18', 'i20', 'i3', 'i1', 'i2', 'i4'], 's8': ['i8', 'i5', 'i6', 'i7', 'i12', 'i9', 'i10', 'i11', 'i16', 'i13', 'i14', 'i15', 'i20', 'i17', 'i18', 'i19', 'i4', 'i1', 'i2', 'i3'], 's9': ['i9', 'i10', 'i11', 'i12', 'i13', 'i14', 'i15', 'i16', 'i17', 'i18', 'i19', 'i20', 'i1', 'i2', 'i3', 'i4', 'i5', 'i6', 'i7', 'i8'], 's10': ['i10', 'i9', 'i11', 'i12', 'i14', 'i13', 'i15', 'i16', 'i18', 'i17', 'i19', 'i20', 'i2', 'i1', 'i3', 'i4', 'i6', 'i5', 'i7', 'i8'], 's11': ['i11', 'i9', 'i10', 'i12', 'i15', 'i13', 'i14', 'i16', 'i19', 'i17', 'i18', 'i20', 'i3', 'i1', 'i2', 'i4', 'i7', 'i5', 'i6', 'i8'], 's12': ['i12', 'i9', 'i10', 'i11', 'i16', 'i13', 'i14', 'i15', 'i20', 'i17', 'i18', 'i19', 'i4', 'i1', 'i2', 'i3', 'i8', 'i5', 'i6', 'i7'], 's13': ['i13', 'i14', 'i15', 'i16', 'i17', 'i18', 'i19', 'i20', 'i1', 'i2', 'i3', 'i4', 'i5', 'i6', 'i7', 'i8', 'i9', 'i10', 'i11', 'i12'], 's14': ['i14', 'i13', 'i15', 'i16', 'i18', 'i17', 'i19', 'i20', 'i2', 'i1', 'i3', 'i4', 'i6', 'i5', 'i7', 'i8', 'i10', 'i9', 'i11', 'i12'], 's15': ['i15', 'i13', 'i14', 'i16', 'i19', 'i17', 'i18', 'i20', 'i3', 'i1', 'i2', 'i4', 'i7', 'i5', 'i6', 'i8', 'i11', 'i9', 'i10', 'i12'], 's16': ['i16', 'i13', 'i14', 'i15', 'i20', 'i17', 'i18', 'i19', 'i4', 'i1', 'i2', 'i3', 'i8', 'i5', 'i6', 'i7', 'i12', 'i9', 'i10', 'i11'], 's17': ['i17', 'i18', 'i19', 'i20', 'i1', 'i2', 'i3', 'i4', 'i5', 'i6', 'i7', 'i8', 'i9', 'i10', 'i11', 'i12', 'i13', 'i14', 'i15', 'i16'], 's18': ['i18', 'i17', 'i19', 'i20', 'i2', 'i1', 'i3', 'i4', 'i6', 'i5', 'i7', 'i8', 'i10', 'i9', 'i11', 'i12', 'i14', 'i13', 'i15', 'i16'], 's19': ['i19', 'i17', 'i18', 'i20', 'i3', 'i1', 'i2', 'i4', 'i7', 'i5', 'i6', 'i8', 'i11', 'i9', 'i10', 'i12', 'i15', 'i13', 'i14', 'i16'], 's20': ['i20', 'i17', 'i18', 'i19', 'i4', 'i1', 'i2', 'i3', 'i8', 'i5', 'i6', 'i7', 'i12', 'i9', 'i10', 'i11', 'i16', 'i13', 'i14', 'i15'], } student_preference2 = {'i1': ['s2', 's10', 's9', 's8', 's7', 's16', 's15', 's14', 's13', 's1', 's3', 's4', 's5', 's20', 's12', 's11', 's6', 's17', 's18', 's19'], 'i2': ['s10', 's9', 's8', 's7', 's16', 's15', 's14', 's13', 's2', 's20', 's1', 's5', 's19', 's11', 's18', 's3', 's4', 's12', 's17', 's6'], 'i3': ['s10', 's9', 's8', 's7', 's16', 's15', 's14', 's13', 's2', 's3', 's1', 's17', 's4', 's19', 's18', 's6', 's5', 's11', 's20', 's12'], 'i4': ['s9', 's8', 's7', 's16', 's15', 's14', 's13', 's2', 's4', 's1', 's20', 's19', 's3', 's18', 's17', 's10', 's5', 's6', 's11', 's12'], 'i5': ['s8', 's7', 's16', 's15', 's14', 's13', 's2', 's5', 's6', 's10', 's11', 's20', 's19', 's12', 's3', 's4', 's9', 's1', 's17', 's18'], 'i6': ['s7', 's16', 's15', 's14', 's13', 's2', 's6', 's8', 's4', 's17', 's12', 's18', 's1', 's3', 's9', 's20', 's19', 's11', 's5', 's10'], 'i7': ['s16', 's15', 's14', 's13', 's2', 's7', 's1', 's3', 's4', 's5', 's20', 's12', 's11', 's6', 's17', 's18', 's19', 's8', 's9', 's10'], 'i8': ['s15', 's14', 's13', 's2', 's8', 's20', 's1', 's5', 's19', 's11', 's18', 's3', 's4', 's12', 's17', 's6', 's16', 's7', 's9', 's10'], 'i9': ['s14', 's13', 's2', 's9', 's15', 's5', 's6', 's10', 's11', 's20', 's19', 's12', 's3', 's4', 's7', 's1', 's17', 's18', 's16', 's8'], 'i10': ['s13', 's2', 's10', 's5', 's11', 's12', 's1', 's4', 's7', 's16', 's18', 's9', 's8', 's6', 's20', 's19', 's3', 's14', 's15', 's17'], 'i11': ['s12', 's20', 's19', 's18', 's17', 's5', 's4', 's3', 's1', 's11', 's13', 's6', 's16', 's8', 's9', 's2', 's15', 's7', 's14', 's10'], 'i12': ['s20', 's19', 's18', 's17', 's5', 's4', 's3', 's1', 's12', 's10', 's2', 's16', 's9', 's7', 's14', 's15', 's13', 's11', 's6', 's8'], 'i13': ['s20', 's19', 's18', 's17', 's5', 's4', 's3', 's1', 's12', 's13', 's8', 's10', 's6', 's7', 's11', 's15', 's14', 's16', 's9', 's2'], 'i14': ['s19', 's18', 's17', 's5', 's4', 's3', 's1', 's12', 's14', 's2', 's13', 's10', 's6', 's7', 's9', 's8', 's11', 's15', 's16', 's20'], 'i15': ['s18', 's17', 's5', 's4', 's3', 's1', 's12', 's15', 's2', 's20', 's11', 's16', 's6', 's9', 's10', 's13', 's14', 's7', 's8', 's19'], 'i16': ['s17', 's5', 's4', 's3', 's1', 's12', 's6', 's16', 's20', 's18', 's8', 's9', 's11', 's10', 's2', 's13', 's14', 's19', 's7', 's15'], 'i17': ['s5', 's4', 's3', 's1', 's12', 's17', 's18', 's6', 's2', 's9', 's20', 's19', 's11', 's10', 's7', 's8', 's13', 's14', 's15', 's16'], 'i18': ['s4', 's3', 's1', 's12', 's18', 's16', 's13', 's9', 's2', 's15', 's11', 's10', 's5', 's6', 's7', 's20', 's8', 's19', 's17', 's14'], 'i19': ['s3', 's1', 's12', 's19', 's4', 's20', 's11', 's2', 's15', 's16', 's7', 's10', 's9', 's5', 's6', 's18', 's17', 's13', 's14', 's8'], 'i20': ['s1', 's12', 's20', 's18', 's3', 's19', 's10', 's9', 's8', 's5', 's11', 's17', 's16', 's13', 's6', 's14', 's2', 's4', 's7', 's15'], } school_priority2 = {'s1': ['i1', 'i2', 'i3', 'i10', 'i11', 'i12', 'i9', 'i13', 'i6', 'i14', 'i15', 'i16', 'i17', 'i18', 'i19', 'i20', 'i7', 'i4', 'i5', 'i8'], 's2': ['i2', 'i17', 'i18', 'i3', 'i14', 'i4', 'i5', 'i12', 'i6', 'i7', 'i11', 'i8', 'i9', 'i10', 'i20', 'i15', 'i16', 'i1', 'i13', 'i19'], 's3': ['i3', 'i6', 'i9', 'i10', 'i11', 'i12', 'i1', 'i13', 'i14', 'i15', 'i16', 'i5', 'i8', 'i17', 'i18', 'i2', 'i19', 'i20', 'i7', 'i4'], 's4': ['i4', 'i11', 'i12', 'i7', 'i9', 'i13', 'i19', 'i14', 'i15', 'i3', 'i16', 'i17', 'i6', 'i18', 'i10', 'i5', 'i8', 'i1', 'i2', 'i20'], 's5': ['i5', 'i11', 'i12', 'i13', 'i14', 'i15', 'i16', 'i17', 'i1', 'i19', 'i8', 'i3', 'i20', 'i7', 'i10', 'i2', 'i4', 'i6', 'i18', 'i9'], 's6': ['i6', 'i16', 'i14', 'i18', 'i1', 'i2', 'i5', 'i20', 'i19', 'i4', 'i3', 'i8', 'i7', 'i11', 'i12', 'i13', 'i9', 'i10', 'i15', 'i17'], 's7': ['i7', 'i1', 'i2', 'i17', 'i18', 'i3', 'i19', 'i4', 'i5', 'i12', 'i6', 'i10', 'i20', 'i15', 'i16', 'i11', 'i13', 'i14', 'i8', 'i9'], 's8': ['i8', 'i9', 'i10', 'i1', 'i20', 'i2', 'i11', 'i3', 'i4', 'i15', 'i5', 'i14', 'i17', 'i16', 'i6', 'i13', 'i19', 'i7', 'i12', 'i18'], 's9': ['i9', 'i1', 'i7', 'i10', 'i2', 'i3', 'i16', 'i18', 'i4', 'i14', 'i11', 'i12', 'i6', 'i19', 'i13', 'i20', 'i17', 'i15', 'i5', 'i8'], 's10': ['i10', 'i1', 'i2', 'i15', 'i18', 'i3', 'i14', 'i17', 'i16', 'i6', 'i13', 'i19', 'i20', 'i7', 'i9', 'i4', 'i11', 'i12', 'i5', 'i8'], 's11': ['i11', 'i6', 'i16', 'i14', 'i18', 'i1', 'i2', 'i5', 'i20', 'i19', 'i4', 'i3', 'i8', 'i7', 'i12', 'i13', 'i9', 'i10', 'i15', 'i17'], 's12': ['i12', 'i6', 'i8', 'i13', 'i10', 'i14', 'i9', 'i2', 'i15', 'i16', 'i3', 'i17', 'i18', 'i5', 'i19', 'i20', 'i1', 'i4', 'i7', 'i11'], 's13': ['i13', 'i1', 'i19', 'i2', 'i3', 'i4', 'i5', 'i18', 'i6', 'i14', 'i7', 'i8', 'i11', 'i9', 'i10', 'i20', 'i15', 'i16', 'i17', 'i12'], 's14': ['i14', 'i1', 'i18', 'i2', 'i3', 'i11', 'i4', 'i17', 'i5', 'i6', 'i15', 'i7', 'i8', 'i20', 'i9', 'i16', 'i13', 'i19', 'i12', 'i10'], 's15': ['i15', 'i9', 'i14', 'i1', 'i20', 'i2', 'i3', 'i12', 'i4', 'i5', 'i18', 'i6', 'i7', 'i11', 'i8', 'i10', 'i19', 'i16', 'i13', 'i17'], 's16': ['i16', 'i17', 'i1', 'i19', 'i2', 'i9', 'i3', 'i4', 'i14', 'i12', 'i5', 'i6', 'i11', 'i7', 'i10', 'i13', 'i15', 'i18', 'i20', 'i8'], 's17': ['i17', 'i11', 'i7', 'i10', 'i12', 'i13', 'i18', 'i6', 'i14', 'i15', 'i8', 'i16', 'i4', 'i1', 'i5', 'i2', 'i20', 'i9', 'i3', 'i19'], 's18': ['i18', 'i11', 'i20', 'i2', 'i9', 'i12', 'i4', 'i16', 'i13', 'i3', 'i14', 'i17', 'i6', 'i5', 'i15', 'i19', 'i1', 'i7', 'i10', 'i8'], 's19': ['i19', 'i18', 'i6', 'i7', 'i9', 'i11', 'i12', 'i3', 'i8', 'i20', 'i13', 'i14', 'i10', 'i1', 'i2', 'i5', 'i16', 'i4', 'i15', 'i17'], 's20': ['i20', 'i10', 'i7', 'i11', 'i12', 'i8', 'i19', 'i13', 'i4', 'i1', 'i6', 'i16', 'i3', 'i5', 'i18', 'i9', 'i2', 'i15', 'i17', 'i14'], } doc = """ Your app description """ class Subsession(BaseSubsession): def creating_session(self): # print('creating session!') players = self.get_players() for p in players: p.set_type() class Group(BaseGroup): def boston(self): print('boston algorithm') #ここでpayoff tableを設定 if self.round_number < 9: School_priority = Constants.school_priority1 else: School_priority = Constants.school_priority2 preferences = [[0] * (Constants.players_per_group+1)] * Constants.players_per_group players_in_group = self.get_players() for p in players_in_group: preferences[p.id_in_group - 1] = [p.sub1, p.sub2, p.sub3, p.sub4, p.sub5, p.sub6, p.sub7, p.sub8, p.sub9, p.sub10, p.sub11, p.sub12, p.sub13, p.sub14, p.sub15, p.sub16, p.sub17, p.sub18, p.sub19, p.sub20, p.sub21] flag = False for i, sc_id in enumerate(preferences[p.id_in_group - 1]): if (sc_id == 'f') or (sc_id is None): flag = True if flag: preferences[p.id_in_group - 1][i] = 'f' print(preferences) school_matching_partner = dict(zip(Constants.school_type, [0]*20)) # {'s1':0, 's2':0,...,'s20':0} print(school_matching_partner) for step in range(Constants.players_per_group+1): # 0,1,2,3,4,...,20 print('step: ', step) for school_t in Constants.school_type: # ['s1','s2',...,'s20'] if school_matching_partner[school_t] is not 0: # 定員埋まっているので continue # まだ空いているので、同じstepでschool_idへapplyしている人たちで取り合い tmp_priority_ranking = 100 for student in players_in_group: student_id = student.id_in_group student_index = student_id-1 student_priority_ranking = School_priority[school_t].index(student.type) if (preferences[student_index][step] == school_t) \ and (student_priority_ranking < tmp_priority_ranking): school_matching_partner[school_t] = student_id tmp_priority_ranking = student_priority_ranking # print(preferences[student_index][step], school_t, tmp_priority_ranking, student_priority_ranking) # print(school_matching_partner) if tmp_priority_ranking is not 100: players_in_group.remove(self.get_player_by_id(school_matching_partner[school_t])) # matching が決定 print('matching was determind') print(school_matching_partner) for school_t, student_id in school_matching_partner.items(): if student_id == 0: continue student = self.get_player_by_id(student_id) student.matching_partner = school_t def da(self): print('DA algorithm') #ここでpayoff tableを設定 if self.round_number < 9: School_priority = Constants.school_priority1 else: School_priority = Constants.school_priority2 preferences = [[0] * (Constants.players_per_group+1)] * Constants.players_per_group players_in_group = self.get_players() for p in players_in_group: preferences[p.id_in_group - 1] = [p.sub1, p.sub2, p.sub3, p.sub4, p.sub5, p.sub6, p.sub7, p.sub8, p.sub9, p.sub10, p.sub11, p.sub12, p.sub13, p.sub14, p.sub15, p.sub16, p.sub17, p.sub18, p.sub19, p.sub20, p.sub21] flag = False for i, sc_id in enumerate(preferences[p.id_in_group - 1]): if (sc_id == 'f') or (sc_id is None): flag = True if flag: preferences[p.id_in_group - 1][i] = 'f' print(preferences) school_tmp_matching_partner = dict(zip(Constants.school_type, [0]*20)) # {'s1':0, 's2':0,...,'s20':0} print(school_tmp_matching_partner) while len(players_in_group) > 0: student = players_in_group.pop() for school_t in preferences[student.id_in_group - 1]: print('school_t', school_t) if school_t == 'f' or school_t is None: # outside option student.matching_partner = 'f' print('outside option') break rival_student_id = school_tmp_matching_partner[school_t] if rival_student_id != 0: student_rival = self.get_player_by_id(rival_student_id) if School_priority[school_t].index(student.type) \ < School_priority[school_t].index(student_rival.type): print(school_t, student.id_in_group, '新たな生徒のほうが好き') # 以下2行ただしいか? student.matching_partner = school_t student_rival.matching_partner = 'f' school_tmp_matching_partner[school_t] = student.id_in_group players_in_group.append(student_rival) break else: # 保持している生徒のほうが好き print('変更無しで次へ') else: print(school_t, student.id_in_group, 'マッチしている生徒がいないので、仮マッチさせて終了') school_tmp_matching_partner[school_t] = student.id_in_group student.matching_partner = school_t break def set_payoff(self): #ここでpayoff tableを設定 if self.round_number < 9: Student_preference = Constants.student_preference1 else: Student_preference = Constants.student_preference2 players = self.get_players() for p in players: if p.matching_partner == 'f': p.payoff = 0 else: p.payoff = c(21 - Student_preference[p.type].index(p.matching_partner)) class Player(BasePlayer): # 'i1','i2',...のいずれか type = models.StringField() # 's1','s2',...のいずれか matching_partner = models.StringField(initial='f') sub1 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第1志望', blank=True) # None sub2 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第2志望', blank=True) sub3 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第3志望', blank=True) sub4 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第4志望', blank=True) sub5 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第5志望', blank=True) sub6 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第6志望', blank=True) sub7 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第7志望', blank=True) sub8 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第8志望', blank=True) sub9 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第9志望', blank=True) sub10 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第10志望', blank=True) sub11 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第11志望', blank=True) sub12 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第12志望', blank=True) sub13 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第13志望', blank=True) sub14 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第14志望', blank=True) sub15 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第15志望', blank=True) sub16 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第16志望', blank=True) sub17 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第17志望', blank=True) sub18 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第18志望', blank=True) sub19 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第19志望', blank=True) sub20 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第20志望', blank=True) sub21 = models.StringField(choices=Constants.school_id_label, widget=widgets.RadioSelectHorizontal, label='第21志望', blank=True) def set_type(self): self.type = Constants.student_type[(self.id_in_group - self.round_number) % 20]