from otree.api import Bot, Submission, SubmissionMustFail, expect from . import ( Privacy, Codice, CodiceNuovo, CodiceRitorno, Demografia, AILS, Test, CTAI, ATTARI, C, CODE_LETTERS, CODE_DIGITS, code_distance, hash_code, ) class PlayerBot(Bot): # case 'full': all test answers correct, submitted normally # case 'timeout': partial test answers, auto-submitted by the timer cases = ['full', 'timeout'] def play_round(self): yield Submission(Privacy, dict(privacy=True)) if C.CODE_MODE in ('hash', 'both'): yield from self.play_hash_code() if C.CODE_MODE in ('generated', 'both'): if self.player.wave == 'post': yield from self.play_code_return() else: yield from self.play_code_new() yield Demografia, dict( ruolo_tipo=2, ruolo_livello=1, ente_tipo=3, genere=99, eta_classe=2, titolo_studio=2, ) yield AILS, {r['var_name']: 4 for r in C.scales if r['scale'] == 'ails'} if self.case == 'full': yield Test, {r['var_name']: r['correct'] for r in C.test} expect(self.player.score_ea, 6) expect(self.player.score_ga, 9) expect(self.player.score_total, 15) else: # correct EA answers only, GA left blank -> scored as wrong answers = {r['var_name']: r['correct'] for r in C.test if r['subscale'] == 'ea'} yield Submission(Test, answers, timeout_happened=True) expect(self.player.score_ea, 6) expect(self.player.score_ga, 0) expect(self.player.score_total, 6) yield CTAI, {r['var_name']: 3 for r in C.scales if r['scale'] == 'ctai'} yield ATTARI, {r['var_name']: 5 for r in C.scales if r['scale'] == 'attari'} # Final page: one certificate token issued, not stored on the player tokens = self.session.vars.get('cert_tokens', []) if C.CERT_UNIQUE_TOKENS: expect(len(tokens) >= 1, True) expect(tokens, sorted(tokens)) def play_hash_code(self): yield SubmissionMustFail(Codice, dict(cod_madre='S1', cod_giorno='12', cod_padre='MA')) yield SubmissionMustFail(Codice, dict(cod_madre='SI', cod_giorno='32', cod_padre='MA')) yield SubmissionMustFail(Codice, dict(cod_madre='SI', cod_giorno='5', cod_padre='MA')) yield SubmissionMustFail(Codice, dict(cod_madre='SI', cod_giorno='00', cod_padre='M')) # lowercase / accents are normalized: 'sì' -> 'SI' yield Codice, dict(cod_madre='sì', cod_giorno='12', cod_padre='ma') expect(self.player.codice_hash, hash_code('SI12MA')) expect(self.player.field_maybe_none('cod_madre'), None) expect(self.player.field_maybe_none('cod_giorno'), None) expect(self.player.field_maybe_none('cod_padre'), None) def play_code_new(self): code = self.player.codice expect(len(code), 4) expect(all(ch in CODE_LETTERS for ch in code[:2]), True) expect(all(ch in CODE_DIGITS for ch in code[2:]), True) others = [p.codice for p in self.subsession.get_players() if p.id != self.player.id] expect(min(code_distance(code, o) for o in others) >= 2, True) expect(code in self.html, True) yield SubmissionMustFail(CodiceNuovo, {}) # checkbox not ticked yield CodiceNuovo, dict(codice_salvato=True) def play_code_return(self): yield SubmissionMustFail(CodiceRitorno, dict(codice='KT4')) yield SubmissionMustFail(CodiceRitorno, dict(codice='KO48')) # O never used yield SubmissionMustFail(CodiceRitorno, dict(codice='KT10')) # 0/1 never used if self.case == 'full': yield CodiceRitorno, dict(codice='kt 48') expect(self.player.codice, 'KT48') else: yield CodiceRitorno, dict(codice='', codice_perso=True) expect(self.player.codice, '')