from otree import settings from otree.api import * from .image_utils import encode_image from json import dumps as json_dumps, loads as json_loads from Levenshtein import distance as lev import random import itertools import time from django import template register = template.Library() import pandas as pd import numpy as np doc = """ Real-effort tasks. The different tasks are available in task_matrix.py, task_transcription.py, etc. You can delete the ones you don't need. """ def get_task_module(player): """ This function is only needed for demo mode, to demonstrate all the different versions. You can simplify it if you want. """ from . import task_transcription session = player.session task = session.config.get("task") # default return task_transcription class Constants(BaseConstants): name_in_url = "transcription" players_per_group = None num_rounds = 5 instructions_template = __name__ + "/instructions.html" captcha_length = 6 image_path1 = 'images/dragon.jpg' image_path2 = 'images/winged_lion.jpg' example = 'images/example.png' class Subsession(BaseSubsession): pass def creating_session(subsession: Subsession): session = subsession.session defaults = dict( retry_delay=1.0, puzzle_delay=1.0, attempts_per_puzzle=60, max_iterations=None ) session.params = {} for param in defaults: session.params[param] = session.config.get(param, defaults[param]) treatments = itertools.cycle([0, 1, 2]) for player in subsession.get_players(): player.participant.idcode = player.id_in_group player.idcode = player.participant.idcode for player in subsession.get_players(): player.treatment = next(treatments) player.participant.treatment = player.treatment player.treatment = player.participant.treatment class Group(BaseGroup): # json fields wait_for_ids = models.LongStringField(initial='[]') arrived_ids = models.LongStringField(initial='[]') wait_for_ids2 = models.LongStringField(initial='[]') arrived_ids2 = models.LongStringField(initial='[]') def unarrived_players(group: Group): return set(json_loads(group.wait_for_ids)) - set(json_loads(group.arrived_ids)) def unarrived_players2(group: Group): return set(json_loads(group.wait_for_ids2)) - set(json_loads(group.arrived_ids2)) class Player(BasePlayer): idcode = models.IntegerField() group_choice = models.IntegerField(choices=[ [1, 'Zöld sárkány'], [2, 'Szárnyas oroszlán'], ], label="Válaszd ki, hogy melyik csoport tagjaként szeretnél játszani") ###understood?### understand1 = models.BooleanField( choices=[ [False, 'Hamis'], [True, 'Igaz'], ], widget=widgets.RadioSelect, label="Ez egy másik kérdés" ) understand2 = models.BooleanField( choices=[ [False, 'Hamis'], [True, 'Igaz'], ], widget=widgets.RadioSelect, label="Ez egy másik kérdés" ) understand3 = models.BooleanField( choices=[ [False, 'Hamis'], [True, 'Igaz'], ], widget=widgets.RadioSelect, label="Ez egy másik kérdés" ) treatment = models.IntegerField() iteration = models.IntegerField(initial=0) num_trials = models.IntegerField(initial=0) num_correct = models.IntegerField(initial=0) num_notcorrect = models.IntegerField(initial=0) num_failed = models.IntegerField(initial=0) pct_correct = models.FloatField() weighted = models.FloatField() all_trials = models.IntegerField(initial=0) all_failed = models.IntegerField(initial=0) #### ##this is just what we show them## lev_dist_total = models.IntegerField() lev_dist_other_total = models.IntegerField() lev_dist_points_total = models.IntegerField() lev_dist_points_other_total = models.IntegerField() ################################## perceived_discr1 = models.IntegerField( choices=[ [0, 'A másik osztálytársamhoz képest igazságosan értékelték a megoldásaimat.'], [1, 'A másik osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.'] ], widget=widgets.RadioSelect, label="Az alábbi üzenetet küldöm:" ) perceived_discr2 = models.IntegerField( choices=[ [0, 'A Szárnyas oroszlán csoportba tartozó osztálytársamhoz képest igazságosan értékelték a megoldásaimat.'], [1, 'A Szárnyas oroszlán csoportba tartozó osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.'] ], widget=widgets.RadioSelect, label="Az alábbi üzenetet küldöm:" ) perceived_discr2b = models.IntegerField( choices=[ [0, 'A Zöld sárkány csoportba tartozó osztálytársamhoz képest igazságosan értékelték a megoldásaimat.'], [1, 'A Zöld sárkány csoportba tartozó osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.'] ], widget=widgets.RadioSelect, label="Az alábbi üzenetet küldöm:" ) mes_motivation = models.IntegerField( choices=[ [1, 'Nekem elment a kedvem, felesleges törni magunkat.'], [2, 'Csak így tovább!'], [3, 'Az utolsó kör jön, próbáljuk meg még jobban csinálni!'] ], widget=widgets.RadioSelect, label="Az alábbi üzenetet küldöm:" ) message_other_discr = models.IntegerField(initial=0) message_other_demot = models.IntegerField(initial=0) message_other_continue = models.IntegerField(initial=0) message_other_better = models.IntegerField(initial=0) mes1_timeout = models.BooleanField() mes2_timeout = models.BooleanField() emotion1 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, '1:Egyáltalán nem'], [2, '2'],[3, '3'],[4, '4'], [5, '5:Nagyon erősen'] ], label="Öröm") emotion2 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, '1:Egyáltalán nem'], [2, '2'],[3, '3'],[4, '4'], [5, '5:Nagyon erősen'] ], label="Meglepődés") emotion3 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, '1:Egyáltalán nem'], [2, '2'],[3, '3'],[4, '4'], [5, '5:Nagyon erősen'] ], label="Düh, harag") emotion4 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, '1:Egyáltalán nem'], [2, '2'],[3, '3'],[4, '4'], [5, '5:Nagyon erősen'] ], label="Félelem") emotion5 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, '1:Egyáltalán nem'], [2, '2'],[3, '3'],[4, '4'], [5, '5:Nagyon erősen'] ], label="Szomorúság") emotion6 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, '1:Egyáltalán nem'], [2, '2'],[3, '3'],[4, '4'], [5, '5:Nagyon erősen'] ], label="Undor") emotion7 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, '1:Egyáltalán nem'], [2, '2'],[3, '3'],[4, '4'], [5, '5:Nagyon erősen'] ], label="Unalom") quick = models.IntegerField( choices=[ [1, 'Tőlem telhetően mindent megtettem, a lehető leggyorsabban próbáltam a feladatokat megoldani.'], [2, 'Nem érdekelt a feladat, egyáltalán nem igyekeztem.'] ], widget=widgets.RadioSelect, label="Mennyire igyekeztél a lehető leggyorsabban a legtöbb feladatot pontosan megoldani a háték során?" ) effort_change = models.IntegerField( choices=[ [1, 'Nőtt'], [2, 'Csökket'], [2, 'Nem változott'] ], widget=widgets.RadioSelect, label="A játék során hogyan változott az igyekezeted?" ) feedback_effect = models.IntegerField( choices=[ [1, 'Még szorgalmasabban igyekeztem, hogy bebizonyítsam, hogy jó vagyok.'], [2, 'Elvették a kedvemet, kevésbé igyekeztem utána.'], [2, 'Nem voltak rám hatással, ugyanúgy igyekeztem továbbra is, mint korábban.'] ], widget=widgets.RadioSelect, label="Hogyan befolyásolták az igyekezetedet a feladatok után az értékelőtől kapott visszajelzések?" ) message_effect = models.IntegerField( choices=[ [1, 'Motiváltak, még jobban igyekeztem.'], [2, 'Elvették a kedvemet, kevésbé igyekeztem utána.'], [2, 'Nem voltak rám hatással, ugyanúgy igyekeztem továbbra is, mint korábban.'] ], widget=widgets.RadioSelect, label="Mennyiben befolyásoltak az igyekezetedben az osztálytársaidtól kapott üzenetek?" ) class WaitforResults(Page): timeout_seconds = 10 @staticmethod def is_displayed(player: Player): return (player.round_number <= Constants.num_rounds-1) @staticmethod def vars_for_template(player: Player): player_first = player.in_round(1) group_choice=player_first.group_choice image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict( image_path1=image_path1, image_path2=image_path2, group_choice=group_choice) class WaitforResults2(Page): timeout_seconds = 10 @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds-2) @staticmethod def vars_for_template(player: Player): player_first = player.in_round(1) group_choice=player_first.group_choice image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict( image_path1=image_path1, image_path2=image_path2, group_choice=group_choice) class Choose(Page): timeout_seconds = 60 @staticmethod def is_displayed(player: Player): return player.round_number == 1 form_model = 'player' form_fields = ['group_choice'] @staticmethod def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict( image_path1=image_path1, image_path2=image_path2) @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.group_choice = 1 # puzzle-specific stuff class Puzzle(ExtraModel): """A model to keep record of all generated puzzles""" player = models.Link(Player) iteration = models.IntegerField(initial=0) attempts = models.IntegerField(initial=0) timestamp = models.FloatField(initial=0) # can be either simple text, or a json-encoded definition of the puzzle, etc. text = models.LongStringField() # solution may be the same as text, if it's simply a transcription task solution = models.LongStringField() response = models.LongStringField() response_timestamp = models.FloatField() #is_correct = models.BooleanField() is_correct = models.IntegerField() is_invalid = models.BooleanField() pct_correct = models.FloatField() feedback = models.LongStringField() def generate_puzzle(player: Player) -> Puzzle: """Create new puzzle for a player""" task_module = get_task_module(player) fields = task_module.generate_puzzle_fields() player.iteration += 1 return Puzzle.create( player=player, iteration=player.iteration, timestamp=time.time(), **fields ) def get_current_puzzle(player): puzzles = Puzzle.filter(player=player, iteration=player.iteration) if puzzles: [puzzle] = puzzles return puzzle def encode_puzzle(puzzle: Puzzle): """Create data describing puzzle to send to client""" task_module = get_task_module(puzzle.player) # noqa # generate image for the puzzle image = task_module.render_image(puzzle) data = encode_image(image) return dict(image=data) def get_progress(player: Player): """Return current player progress""" return dict( num_trials=player.num_trials, num_correct=player.num_correct, num_incorrect=player.num_failed, num_notcorrect=player.num_notcorrect, iteration=player.iteration, feedback = "" ) def play_game(player: Player, message: dict): """Main game workflow Implemented as reactive scheme: receive message from vrowser, react, respond. Generic game workflow, from server point of view: - receive: {'type': 'load'} -- empty message means page loaded - check if it's game start or page refresh midgame - respond: {'type': 'status', 'progress': ...} - respond: {'type': 'status', 'progress': ..., 'puzzle': data} -- in case of midgame page reload - receive: {'type': 'next'} -- request for a next/first puzzle - generate new puzzle - respond: {'type': 'puzzle', 'puzzle': data} - receive: {'type': 'answer', 'answer': ...} -- user answered the puzzle - check if the answer is correct - respond: {'type': 'feedback', 'is_correct': true|false, 'retries_left': ...} -- feedback to the answer If allowed by config `attempts_pre_puzzle`, client can send more 'answer' messages When done solving, client should explicitely request next puzzle by sending 'next' message Field 'progress' is added to all server responses to indicate it on page. To indicate max_iteration exhausted in response to 'next' server returns 'status' message with iterations_left=0 """ session = player.session my_id = player.id_in_group params = session.params task_module = get_task_module(player) now = time.time() # the current puzzle or none current = get_current_puzzle(player) message_type = message['type'] # page loaded if message_type == 'load': p = get_progress(player) if current: return { my_id: dict(type='status', progress=p, puzzle=encode_puzzle(current)) } else: return {my_id: dict(type='status', progress=p)} if message_type == "cheat" and settings.DEBUG: return {my_id: dict(type='solution', solution=current.solution)} # client requested new puzzle if message_type == "next": if current is not None: #if current.response is None: #raise RuntimeError("trying to skip over unsolved puzzle") if now < current.timestamp + params["puzzle_delay"]: raise RuntimeError("retrying too fast") if current.iteration == params['max_iterations']: return { my_id: dict( type='status', progress=get_progress(player), iterations_left=0 ) } # generate new puzzle z = generate_puzzle(player) p = get_progress(player) return {my_id: dict(type='puzzle', puzzle=encode_puzzle(z), progress=p)} # client gives an answer to current puzzle if message_type == "answer": if current is None: raise RuntimeError("trying to answer no puzzle") if current.response is not None: # it's a retry if current.attempts >= params["attempts_per_puzzle"]: raise RuntimeError("Több próbálkozás nem megengedett.") #if now < current.response_timestamp + params["retry_delay"]: #raise RuntimeError("Várj egy kicsit, mindjárt újra próbálkozhatsz!") # undo last updation of player progress player.num_trials -= 1 if current.is_correct == 1: player.num_correct -= 0 else: player.num_failed -= 0 player.num_notcorrect = player.num_trials - player.num_correct # check answer answer = message["answer"] ##if answer == "" or answer is None or len(answer) != 6 or not answer.isalpha(): #or any((c in numno) for c in answer): ##current.invalid = True #raise ValueError("Érvénytelen megoldás") #player.num_trials -= 0 #player.num_correct -= 0 #player.num_failed -= 0 current.response = answer current.is_correct = task_module.is_correct(answer, current) current.is_invalid = task_module.is_invalid(answer) current.response_timestamp = now current.attempts += 1 current.feedback='' # update player progress # if current.is_correct: # player.num_correct += 1 # else: # player.num_failed += 1 #player.num_trials += 1 # update player progress if current.is_correct == 1: player.num_correct += 1 player.num_trials += 1 elif current.is_correct == 99: player.num_correct +=0 player.num_failed += 0 player.num_trials += 0 elif current.is_correct == 0: player.num_correct += 0 player.num_failed += 0 player.num_trials += 0 elif current.is_invalid == True: player.num_correct +=0 player.num_failed += 0 player.num_trials += 0 else: player.num_failed += current.is_correct * (-1) player.num_trials += 1 player.num_notcorrect = player.num_trials - player.num_correct retries_left = params["attempts_per_puzzle"] - current.attempts p = get_progress(player) return { my_id: dict( type='feedback', is_correct=current.is_correct, retries_left=retries_left, progress=p, feedback=current.feedback, is_invalid=current.is_invalid, ) } raise RuntimeError("unrecognized message from client") class Intro(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 class Game(Page): timeout_seconds = 60 live_method = play_game @staticmethod def js_vars(player: Player): return dict(params=player.session.params) @staticmethod def vars_for_template(player: Player): player_first = player.in_round(1) group_choice=player_first.group_choice task_module = get_task_module(player) image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict(DEBUG=settings.DEBUG, input_type=task_module.INPUT_TYPE, placeholder=task_module.INPUT_HINT, image_path1=image_path1, image_path2=image_path2, group_choice=group_choice) @staticmethod def before_next_page(player: Player, timeout_happened): if not timeout_happened and not player.session.params['max_iterations']: raise RuntimeError("malicious page submission") class Results_Overall(Page): @staticmethod def is_displayed(player: Player): return player.round_number <= Constants.num_rounds - 1 timeout_seconds = 60 #pass @staticmethod def vars_for_template(player: Player): iteration = [puzz.iteration for puzz in Puzzle.filter(player=player) if puzz.response is not None and puzz.is_correct != 99 and puzz.is_correct != 0] response = [puzz.response for puzz in Puzzle.filter(player=player) if puzz.response is not None and puzz.is_correct != 99 and puzz.is_correct != 0] solution = [puzz.solution for puzz in Puzzle.filter(player=player) if puzz.response is not None and puzz.is_correct != 99 and puzz.is_correct != 0] lev_dist = [puzz.is_correct * (-1) for puzz in Puzzle.filter(player=player) if puzz.response is not None and puzz.is_correct != 99 and puzz.is_correct != 0] lev_dist = [0 if l==-1 else l for l in lev_dist] treatment = player.treatment if treatment == 0: lev_dist_points = [] for l, s in zip(lev_dist, solution): ld = (1 - l / len(s)) lpo = len(s) - l lev_dist_points.append(lpo) ##Informally, the Levenshtein distance between two words is the minimum number of single-character edits # (insertions, deletions or substitutions) required to change one word into the other. # [1]- https://en.wikipedia.org/wiki/Levenshtein_distance # the other player should have the same amount of mistakes as the focal player # but the divergence from the original text would be random (swapping lower/uppercase letter from the original text) change_other = [random.sample(range(6), l) for l in lev_dist] response_other = [] # Multiple indices Replace in String # Using list comprehension + join() for ch, s in zip(change_other, solution): temp = list(s) res = [si.swapcase() if idx in ch else si for idx, si in enumerate(temp)] res = ''.join(res) response_other.append(res) lev_dist_other = [] lev_dist_points_other = [] for l, s in zip(response_other, solution): ldo = lev(l, s) ldop = (1 - ldo / len(s)) lpoo = len(s) - ldo lev_dist_other.append(ldo) lev_dist_points_other.append(lpoo) elif treatment == 1 or treatment == 2: lev_dist_points = [] for l, s in zip(lev_dist, solution): ld = (1 - l / len(s)) if l == 0: lpo = (len(s) - l)-1 lev_dist_points.append(lpo) elif l > 0: lpo = len(s) - l lev_dist_points.append(lpo) change_other = [random.sample(range(6), l) for l in lev_dist] ##Informally, the Levenshtein distance between two words is the minimum number of single-character edits # (insertions, deletions or substitutions) required to change one word into the other. # [1]- https://en.wikipedia.org/wiki/Levenshtein_distance # the other player should have the same amount of mistakes as the focal player # but the divergence from the original text would be random (swapping lower/uppercase letter from the original text) change_other = [random.sample(range(6), l) for l in lev_dist] response_other = [] # Multiple indices Replace in String # Using list comprehension + join() for ch, s in zip(change_other, solution): temp = list(s) res = [si.swapcase() if idx in ch else si for idx, si in enumerate(temp)] res = ''.join(res) response_other.append(res) lev_dist_other = [] lev_dist_points_other = [] for l, s in zip(response_other, solution): ldo = lev(l, s) lev_dist_other.append(ldo) if ldo == 0: lpoo = len(s) - ldo elif ldo > 0: lpoo = (len(s) - ldo) +1 lev_dist_points_other.append(lpoo) player.lev_dist_total = sum(lev_dist) player.lev_dist_other_total = sum(lev_dist_other) player.lev_dist_points_total = sum(lev_dist_points) player.lev_dist_points_other_total = sum(lev_dist_points_other) if (player.treatment == 1 or player.treatment == 2) and player.num_trials == 0: player.lev_dist_points_other_total = 1 else: player.lev_dist_points_other_total = player.lev_dist_points_other_total image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 player_first = player.in_round(1) group_choice=player_first.group_choice return dict(lev_dist_total= player.lev_dist_total, lev_dist_other_total= player.lev_dist_other_total, lev_dist_points_total= player.lev_dist_points_total, lev_dist_points_other_total= player.lev_dist_points_other_total, image_path1=image_path1, image_path2=image_path2, group_choice=group_choice ) class Results_Alternative(Page): @staticmethod def is_displayed(player: Player): return player.round_number <= Constants.num_rounds - 1 timeout_seconds = 120 @staticmethod def vars_for_template(player: Player): player_first = player.in_round(1) iteration = [puzz.iteration for puzz in Puzzle.filter(player=player) if puzz.response is not None and puzz.is_correct != 99 and puzz.is_correct != 0] response = [puzz.response for puzz in Puzzle.filter(player=player) if puzz.response is not None and puzz.is_correct != 99 and puzz.is_correct != 0] solution = [puzz.solution for puzz in Puzzle.filter(player=player) if puzz.response is not None and puzz.is_correct != 99 and puzz.is_correct != 0] lev_dist = [puzz.is_correct * (-1) for puzz in Puzzle.filter(player=player) if puzz.response is not None and puzz.is_correct != 99 and puzz.is_correct != 0] lev_dist = [0 if l == -1 else l for l in lev_dist] treatment =player.treatment change_other = [random.sample(range(6), l) for l in lev_dist] response_other = [] # Multiple indices Replace in String # Using list comprehension + join() for ch, s in zip(change_other, solution): temp = list(s) res = [si.swapcase() if idx in ch else si for idx, si in enumerate(temp)] res = ''.join(res) response_other.append(res) response_other_split = [] for r in response_other: temp = [] for rl in r: temp.append(rl) response_other_split.append(temp) response_split = [] for r in response: temp = [] for rl in r: temp.append(rl) response_split.append(temp) solution_split = [] for r in solution: temp = [] for rl in r: temp.append(rl) solution_split.append(temp) if treatment == 0: lev_dist_points = [] for l, s in zip(lev_dist, solution): lpo = len(s) - l lev_dist_points.append(lpo) lev_dist_points_other = [] for l, s in zip(response_other, solution): ldo = lev(l, s) lpoo = len(s) - ldo lev_dist_points_other.append(lpoo) elif treatment == 1 or treatment == 2: lev_dist_points = [] for l, s in zip(lev_dist, solution): if l == 0: lpo = (len(s) - l) - 1 lev_dist_points.append(lpo) elif l > 0: lpo = len(s) - l lev_dist_points.append(lpo) lev_dist_points_other = [] for l, s in zip(response_other, solution): ldo = lev(l, s) if ldo == 0: lpoo = len(s) - ldo elif ldo > 0: lpoo = (len(s) - ldo) + 1 lev_dist_points_other.append(lpoo) iterations = [*range(1, len(response_split) + 1)] solutions = [u'Helyes megoldás', u'A te megoldásod', u'A kiválasztott osztálytársad megoldása'] #solution_row = [[str(iterations[i])]+[solutions[0]] + j + ['-'] for i, j in enumerate(solution_split)] #response_row = [['']+[solutions[1]] + j + [lev_dist_points[i]] for i, j in enumerate(response_split)] #response_other_row = [['']+[solutions[2]] + j + [lev_dist_points_other[i]] for i, j in #enumerate(response_other_split)] solution_row = [j + [['-']] for i, j in enumerate(solution_split)] response_row = [j + [lev_dist_points[i]] for i, j in enumerate(response_split)] response_other_row = [j + [lev_dist_points_other[i]] for i, j in enumerate(response_other_split)] flatten = lambda *n: (e for a in n for e in (flatten(*a) if isinstance(a, (tuple, list)) else (a,))) solution_row_flat = [] for item in solution_row: solution_row_flat.append(list(flatten(item))) response_row_flat = [] for item in response_row: response_row_flat.append(list(flatten(item))) response_other_row_flat = [] for item in response_other_row: response_other_row_flat.append(list(flatten(item))) #headers = [u'Megoldás', u'Betű 1', u'Betű 2', u'Betű 3', u'Betű 4', u'Betű 5', u'Betű 6', # u'Pontszám'] headers = [u'betu1', u'betu2', u'betu3', u'betu4', u'betu5', u'betu6', 'pontszam'] solution_row_flat = [{headers[i]: x[i] for i in range(len(headers))} for x in solution_row_flat] response_row_flat = [{headers[i]: x[i] for i in range(len(headers))} for x in response_row_flat] response_other_row_flat = [{headers[i]: x[i] for i in range(len(headers))} for x in response_other_row_flat] puz_res = {} puz_res = {} for i, (a, b, c) in enumerate(list(zip(solution_row_flat, response_row_flat, response_other_row_flat))): puz_res[str(i + 1)] = (dict(solution=a, response=b, response_other=c)) #for i, j in enumerate(iterations): #puz_res[str(j)] = dict( #headers=headers, #solution=solution_row_flat[i], #response=response_row_flat[i], #response_other=response_other_row_flat[i], #) image_path1 =Constants.image_path1 image_path2 =Constants.image_path2 group_choice=player_first.group_choice return dict(puz_res=puz_res, image_path1=image_path1, image_path2=image_path2, group_choice=group_choice) class Perceived_discr1(Page): # #only in the last round @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds-2) and (player.treatment in [0,1]) form_model = 'player' form_fields = ['perceived_discr1'] timeout_seconds = 60 def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict(image_path1=image_path1, image_path2=image_path2) @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: # you may want to fill a default value for any form fields, # because otherwise they may be left null. player.perceived_discr1 = random.choice([0,1]) player.mes1_timeout = True class Perceived_discr2(Page): # #only in the last round @staticmethod def is_displayed(player: Player): player_first = player.in_round(1) return (player.round_number == Constants.num_rounds - 2) and (player.treatment == 2) and (player_first.group_choice == 1) form_model = 'player' form_fields = ['perceived_discr2' ] timeout_seconds = 60 def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 player_first = player.in_round(1) group_choice = player_first.group_choice return dict(image_path1=image_path1, image_path2=image_path2, group_choice=group_choice) @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: # you may want to fill a default value for any form fields, # because otherwise they may be left null. player.perceived_discr2 = random.choice([0,1]) player.mes1_timeout = True class Perceived_discr2b(Page): # #only in the last round @staticmethod def is_displayed(player: Player): player_first = player.in_round(1) return (player.round_number == Constants.num_rounds - 2) and (player.treatment == 2) and (player_first.group_choice == 2) form_model = 'player' form_fields = ['perceived_discr2b' ] timeout_seconds = 60 def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 player_first = player.in_round(1) group_choice = player_first.group_choice return dict(image_path1=image_path1, image_path2=image_path2, group_choice=group_choice) @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: # you may want to fill a default value for any form fields, # because otherwise they may be left null. player.perceived_discr2b = random.choice([0,1]) player.mes1_timeout = True class Perceived_discr_other(Page): timeout_seconds = 60 # #only in the last round @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds-2) @staticmethod def vars_for_template(player: Player): #group = player.group #players = group.get_players() player_first = player.in_round(1) #other_players = player.get_others_in_group() #random.shuffle(players) #if player.treatment == 0: # players = [p for p in players if p.treatment == 0] #elif player.treatment == 1: # players = [p for p in players if p.treatment == 1] #elif player.treatment == 2: # players = [p for p in players if p.treatment == 2] #others = [] #for i, p in enumerate(players): # if p == player.idcode: # if i <= len(players) - 4: # other = players[i + 1:i + 4] # if i == len(players) - 3: # other = players[i + 1:i + 3] + [players[0]] # if i == len(players) - 2: # other = players[i + 1:i + 2] + players[0:2] # if i == len(players) - 1: # other = players[0:3] # others.append(other) #others = list(itertools.chain(*others)) #target_len = 3 #k = target_len - len(others) if player.treatment == 0: message_other = ['A másik osztálytársamhoz képest igazságosan értékelték a megoldásaimat.', 'A másik osztálytársamhoz képest igazságosan értékelték a megoldásaimat.', 'A másik osztálytársamhoz képest igazságosan értékelték a megoldásaimat.'] elif player.treatment == 1: message_other = ['A másik osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.', 'A másik osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.', 'A másik osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.' ] #if len(others) < 3: # others = others # message_other1 = [other.perceived_discr1 for other in others] + random.choices([0,1],k=k) #else: # others = others # message_other1 = [other.perceived_discr1 for other in others] #player.message_other_discr = sum(message_other1) #message_other1 = ['A másik osztálytársamhoz képest igazságtalanabbul értékelték a megoldásaimat.' # if int(m) == 1 else 'A másik osztálytársamhoz képest igazságosan értékelték a megoldásaimat.' # if m==0 else '' for m in message_other1] #message_other = message_other1 elif player.treatment == 2 and player_first.group_choice == 1: message_other = ['A Szárnyas oroszlán csoportba tartozó osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.', 'A Szárnyas oroszlán csoportba tartozó osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.', 'A Szárnyas oroszlán csoportba tartozó osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.'] #if len(others) < 3: # others = others # message_other2 = [other.perceived_discr2 for other in others] + random.choices([0,1],k=k) #else: # others = others # message_other2 = [other.perceived_discr2 for other in others] #player.message_other_discr = sum(message_other2) #message_other2 = ['A Szárnyas oroszlán csoportba tartozó másik osztálytársamhoz képest igazságtalanabbul értékelték a megoldásaimat.' # if int(m) == 1 else 'A Szárnyas oroszlás csoportba tartozó másik osztálytársamhoz képest igazságosan értékelték a megoldásaimat.' #if m == 0 else '' for m in message_other2] #if 'A Szárnyas oroszlán csoportba tartozó másik osztálytársamhoz képest igazságtalanabbul értékelték a megoldásaimat.' in message_other2: # message_other2 = message_other2 #elif 'A Szárnyas oroszlán csoportba tartozó másik osztálytársamhoz képest igazságtalanabbul értékelték a megoldásaimat.' not in message_other2: # message_other2[random.choice([0,1,2])] = 'A Szárnyas oroszlán csoportba tartozó másik osztálytársamhoz képest igazságtalanabbul értékelték a megoldásaimat.' #message_other = message_other2 elif player.treatment == 2 and player_first.group_choice == 2: message_other = [ 'A Zöld sárkány csoportba tartozó osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.', 'A Zöld sárkány csoportba tartozó osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.', 'A Zöld sárkány csoportba tartozó osztálytársamhoz képest igazságtalanul értékelték a megoldásaimat.'] mes = ['Az első üzenet: ', 'A második üzenet: ', 'A harmadik üzenet: '] message_other = {mes[i]: message_other[i] for i in range(len(mes))} image_path1 =Constants.image_path1 image_path2 =Constants.image_path2 group_choice = player_first.group_choice return dict(message_other=message_other, image_path1=image_path1, image_path2=image_path2, group_choice=group_choice) class Message_motivation(Page): form_model = 'player' form_fields = ['mes_motivation'] # #only in the third round @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds-1) timeout_seconds = 60 def vars_for_template(player: Player): player_first = player.in_round(1) image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict(image_path1=image_path1, image_path2=image_path2, group_choice=player_first.group_choice) @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: # you may want to fill a default value for any form fields, # because otherwise they may be left null. player.perceived_discr2 = random.choice([0,1]) player.mes2_timeout = True class Message_mot_other(Page): timeout_seconds = 60 @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds - 1) @staticmethod def vars_for_template(player: Player): group = player.group players = group.get_players() other_players = player.get_others_in_group() player_first = player.in_round(1) random.shuffle(players) if player.treatment == 0: players = [p for p in players if p.treatment == 0] elif player.treatment == 1: players = [p for p in players if p.treatment == 1] elif player.treatment == 2: players = [p for p in players if p.treatment == 2] others = [] for i, p in enumerate(players): if p == player.idcode: if i <= len(players) - 4: other = players[i + 1:i + 4] if i == len(players) - 3: other = players[i + 1:i + 3] + [players[0]] if i == len(players) - 2: other = players[i + 1:i + 2] + players[0:2] if i == len(players) - 1: other = players[0:3] others.append(other) others = list(itertools.chain(*others)) target_len = 3 k = target_len - len(others) if len(others) < 3: others = others mes_motivation_other = [other.mes_motivation for other in others] + random.choices([1,2,3], k=k) else: others = others mes_motivation_other = [other.mes_motivation for other in others] player.message_other_demot = len([i for i in mes_motivation_other if i == 1]) player.message_other_continue = len([i for i in mes_motivation_other if i == 2]) player.message_other_better = len([i for i in mes_motivation_other if i == 3]) mes_motivation_other = ['Nekem elment a kedvem, felesleges törni magunkat.' if m == 1 else 'Csak így tovább!' if m == 2 else 'Az utolsó kör jön, próbáljuk meg még jobban csinálni!' if m == 3 else '' for m in mes_motivation_other] mes = ['Az első üzenet: ', 'A második üzenet: ', 'A harmadik üzenet: '] message_other = {mes[i]: mes_motivation_other[i] for i in range(len(mes))} image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict(message_other=message_other, image_path1 = image_path1, image_path2 = image_path2, group_choice=player_first.group_choice) class Intro2_afterchoice(Page): timeout_seconds = 30 @staticmethod def is_displayed(player: Player): return (player.round_number == 1) def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return {'image_path1': image_path1, 'image_path2': image_path2} @staticmethod def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 example = Constants.example return {'image_path1': image_path1, 'image_path2': image_path2, 'example': example} class ComputeRes(Page): timeout_seconds = 60 # #only in the last round @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds @staticmethod def vars_for_template(player: Player): all_players = player.in_all_rounds() all_trial =[] all_fail =[] for temp_player in all_players: all_trial.append(temp_player.num_trials) for temp_player in all_players: all_fail.append(temp_player.num_failed) all_trials = sum(all_trial) all_failed =sum(all_fail) all_possible_correct_characters = all_trials*Constants.captcha_length try: pct_correct = (1-(all_failed/all_possible_correct_characters))*100 weighted = pct_correct*all_trials except: pct_correct = 0 weighted = 0 player.pct_correct=pct_correct player.all_failed=all_failed player.all_trials=all_trials player.weighted=weighted return {'weighted': weighted, 'all_trials': all_trials, 'all_failed': all_failed, 'pct_correct': pct_correct} def wait_page_live_method(player: Player, data): group = player.group arrived_ids_set = set(json_loads(group.arrived_ids)) arrived_ids_set.add(player.id_in_subsession) group.arrived_ids = json_dumps(list(arrived_ids_set)) if not unarrived_players(group): return {0: dict(finished=True)} def wait_page_live_method2(player: Player, data): group = player.group arrived_ids_set2 = set(json_loads(group.arrived_ids2)) arrived_ids_set2.add(player.id_in_subsession) group.arrived_ids2 = json_dumps(list(arrived_ids_set2)) if not unarrived_players2(group): return {0: dict(finished=True)} class ScratchWaitPage(Page): @staticmethod def is_displayed(player: Player): group = player.group # first time if not json_loads(group.wait_for_ids): #wait_for_ids = [p.id_in_subsession for p in group.get_players()] wait_for_ids = [p.id_in_subsession for p in group.get_players() if p.participant.participate != 0] group.wait_for_ids = json_dumps(wait_for_ids) return unarrived_players(group) @staticmethod def live_method(player: Player, data): if data.get('type') == 'wait_page': return wait_page_live_method(player, data) @staticmethod def error_message(player: Player, values): group = player.group if unarrived_players(group): return "Még várunk néhány játékosra" class ScratchWaitPage2(Page): @staticmethod def is_displayed(player: Player): group = player.group # first time if not json_loads(group.wait_for_ids2): wait_for_ids2 = [p.id_in_subsession for p in group.get_players() if p.participant.participate != 0] group.wait_for_ids2 = json_dumps(wait_for_ids2) return (player.round_number == Constants.num_rounds - 1) and unarrived_players2(group) @staticmethod def live_method(player: Player, data): if data.get('type') == 'wait_page': return wait_page_live_method2(player, data) @staticmethod def error_message(player: Player, values): group = player.group if unarrived_players2(group): return "Még várunk néhány játékosra" class Intro2(Page): timeout_seconds = 30 @staticmethod def is_displayed(player: Player): return (player.round_number == 1) @staticmethod def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 example = Constants.example return {'image_path1': image_path1, 'image_path2': image_path2, 'example': example} class Intro2_details(Page): timeout_seconds = 90 @staticmethod def is_displayed(player: Player): return (player.round_number == 1) @staticmethod def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 example = Constants.example return {'image_path1': image_path1, 'image_path2': image_path2, 'example': example} class Check_if_understand(Page): timeout_seconds = 120 @staticmethod def is_displayed(player: Player): return (player.round_number == 1) form_model = 'player' form_fields = ['understand1', 'understand2', 'understand3'] @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: # you may want to fill a default value for any form fields, # because otherwise they may be left null. player.understand1 = True player.understand2 = True player.understand3 = True class Intro2_if_not_understand(Page): timeout_seconds = 60 @staticmethod def is_displayed(player: Player): return (player.round_number == 1 and (player.understand1 == True or player.understand2 == True or player.understand3 == True)) @staticmethod def vars_for_template(player: Player): image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 example = Constants.example return {'image_path1': image_path1, 'image_path2': image_path2, 'example': example} class Prebriefsurvey(Page): timeout_seconds = 120 @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds) form_model = 'player' form_fields = ['emotion1', 'emotion2', 'emotion3', 'emotion4', 'emotion5', 'emotion6', 'emotion7'] def vars_for_template(player: Player): player_first = player.in_round(1) image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict(image_path1=image_path1, image_path2=image_path2, group_choice=player_first.group_choice) class Prebriefsurvey2(Page): timeout_seconds = 120 @staticmethod def is_displayed(player: Player): return (player.round_number == Constants.num_rounds) form_model = 'player' form_fields = ['quick', 'effort_change', 'feedback_effect', 'message_effect'] def vars_for_template(player: Player): player_first = player.in_round(1) image_path1 = Constants.image_path1 image_path2 = Constants.image_path2 return dict(image_path1=image_path1, image_path2=image_path2, group_choice=player_first.group_choice) page_sequence = [Intro2, Intro2_details, Check_if_understand, Intro2_if_not_understand, Choose, Intro2_afterchoice, Game, ScratchWaitPage, WaitforResults, Results_Overall #,Results_Alternative ,Perceived_discr1, Perceived_discr2, Perceived_discr2b, WaitforResults2, Perceived_discr_other ,Message_motivation ,ScratchWaitPage2 #,MyWaitPage ,Message_mot_other ,Prebriefsurvey ,Prebriefsurvey2 ,ComputeRes ]