import os import json from json import JSONDecodeError from otree.api import * import random import numpy as np from otree import settings #from sklearn.metrics.pairwise import cosine_similarity max_player = 64 ## hoch ansetzen , damit es nicht überläuft im worst case, nimm global id um zu bestimmen welcher eintrag jeder einzelne ist ### TODO: Test this ### Todo: Change/Add fields, do it here too field_labels = { 0: 'hobbies_politik', 1: 'hobbies_kultur', 2: 'hobbies_technik', 3: 'hobbies_sport', 4: 'hobbies_familie', 5: 'hobbies_wellness', 6: 'hobbies_philosophie', 7: 'hobbies_tiere', # Sport 8: 'sport_ballsport', 9: 'sport_wintersport', 10: 'sport_wassersport', 11: 'sport_kraftsport', 12: 'sport_yoga', 13: 'sport_reiten', 14: 'sport_klettern', 15: 'sport_leichtathletik', 16: 'sport_kampfsport', 17: 'sport_motorsport', 18: 'sport_tanzsport', 19: 'sport_nosport', # Music 20: 'music_klassik', 21: 'music_deutsche', 22: 'music_pop', 23: 'music_rap', 24: 'music_rock', 25: 'music_reggae', 26: 'music_jazz', 27: 'music_electronic', # Film 28: 'film_krimi', 29: 'film_horror', 30: 'film_romantik', 31: 'film_action', 32: 'film_komoedie', 33: 'film_scifi', 34: 'film_dokus', 35: 'film_animation', # Urlaub 36: 'urlaub_meer', 37: 'urlaub_bergen', 38: 'urlaub_stadt', 39: 'urlaub_party', 40: 'urlaub_abenteuerlich', 41: 'urlaub_all_incl', 42: 'urlaub_fernweh', 43: 'urlaub_haus', # Eigenschaften 44: 'eigenschaft_karrierebewusst', 45: 'eigenschaft_kinderlieb', 46: 'eigenschaft_sportlich', 47: 'eigenschaft_zuruckhaltend', 48: 'eigenschaft_sparsam', 49: 'eigenschaft_warmherzig', 50: 'eigenschaft_zuverlassig', 51: 'eigenschaft_humorvoll', # Denken 52: 'denken_spass', 53: 'denken_gute_laune', 54: 'denken_ernsthaft', 55: 'denken_vertraeumt', 56: 'denken_sachlich', 57: 'denken_loesungsorientiert', 58: 'denken_ruhe', 59: 'denken_lebhaft', # Wichtigsten 60: 'wichtig_freundschaft', 61: 'wichtig_liebe', 62: 'wichtig_ruhe', 63: 'wichtig_erfolg', 64: 'wichtig_menschen', 65: 'wichtig_soziale', 66: 'wichtig_selbstverwirklichung', 67: 'wichtig_partner', # Add more entries for other fields 68: 'Religion', # Assuming this is the 52nd field 69: 'Diskussion', 70: 'Vertrauen', 71: 'Privat', 72: 'Widerspruch', 73: 'Impuls', 74: 'Kraenkung', 75: 'UeberVerhaeltnisse', 76: 'Rache', 77: 'Banane', 78: 'Wohnhaus', 79: 'Geschlecht', 80: 'Geburtsjahr', 81: 'Studiengang', 82: 'Studienfeld', 83: 'Herkunftsland', 84: 'Wohnort', ## Geburtstjahr .... } #label = field_labels.get(index, "Unknown") customer_vector = np.zeros(shape=(len(field_labels),1)) #np.array() seller_vector = np.zeros(shape=(len(field_labels),1)) #np.array() ### Idee 2 personality_matrix = np.zeros(shape=(len(field_labels), max_player )) ## Helper def make_boolean(blank = True, initial=False): return models.BooleanField( blank=blank, initial=initial ) def make_int(label, choices, widget=widgets.RadioSelect, initial=None): return models.IntegerField( widget=widget, label=label, choices=choices, initial=initial ) ### EXTRA MODEL ### class NumberSequence(ExtraModel): question = models.StringField() solution = models.StringField() type = models.BooleanField() class Analogy(ExtraModel): question = models.StringField() optionA = models.StringField() optionB = models.StringField() optionC = models.StringField() optionD = models.StringField() optionE = models.StringField() solution = models.StringField() def create_group_seller_order(group): ### Todo: für kleinere Gruppen evtl nicht gut seller = [] for p in group.get_players(): if not p.customer: seller.append(p) random.shuffle(seller) first, second, third = seller return first.id_in_group,second.id_in_group,third.id_in_group def calc_average_rating(rating, avg, amount_ratings): return (rating + avg*(amount_ratings-1)) / (amount_ratings) def calc_average_amounts(rating_this_round, average_rating_before, amount_rated): if amount_rated == 0: return amount_rated return (rating_this_round + average_rating_before * (amount_rated-1)) / amount_rated def calc_points_total_till_round(player): not_counted = sum(int(p.round_number > 2 and not p.play_together) for p in player.in_previous_rounds()) ## überspringe die nicht gematchten Runden points_total = sum(p.points_total for p in player.in_previous_rounds()) return points_total/(player.round_number - 1 - not_counted) ### todo: überlegen wie man calc_average_amount ausnutzen kann für die neue verteilugn def get_market_interaction_data(group, round = 1): ### für 5er gruppen sollte es so jetzt auch funktionieren first, second, third = group.get_player_by_id(group.seller_first), group.get_player_by_id( group.seller_second), group.get_player_by_id(group.seller_third) first.avg_rating = first.in_round(round-1).avg_rating second.avg_rating = second.in_round(round-1).avg_rating third.avg_rating = third.in_round(round-1).avg_rating ## performance = Punkte aus den Vorrunden in den Tasks performance = (calc_points_total_till_round(first) + calc_points_total_till_round(second) + calc_points_total_till_round(third))/3 return (first,second,third), performance def get_one_to_one_data(group): points = 0 count_seller = 0 # should be 3 , but maybe in next version you have a different seller/cusomer distribution for player in group.get_players(): if player.type > 0: points += player.points_total count_seller += 1 return points / count_seller def get_form_fields(cat): return [x['name'] for x in cat] def error_message(cat, values, min=1, max=3 ): num_selected = 0 min_answers = "eine Antwort" if min == 1 else f"{min} Antworten" max_answers = "eine Antwort" if max == 1 else f"{max} Antworten" for x in cat: if values[x['name']]: num_selected += 1 if num_selected < min: return f"Bitte wählen Sie mindestens {min_answers} aus" if num_selected >3: return f"Bitte wählen Sie höchstens {max_answers} aus" def role_assignment(subsession, SELLER, CUSTOMER): player_list = subsession.get_players() player_points = [(player.id, player.participant.total_points_test, player) for player in player_list] # Sort the list based on total_points_test sorted_player_points = sorted(player_points, key=lambda x: x[1]) middle = len(sorted_player_points)//2 customer_list = [] seller_list = [] for i, (id, points, player) in enumerate(sorted_player_points): player.tag = SELLER player.customer = False if 4 <= i+1 < 8: ## 4 <= <7 player.type = 1 elif middle - 2 <= i+1 < middle + 2: ## middle - 3<= middle+3 player.type = 2 elif len(player_list)-7 <= i+1 < len(player_list)-3: ## -7 <= <4 player.type = 3 else: player.type = 0 player.tag = CUSTOMER player.customer = True if not player.type: customer_list.append(player) else: seller_list.append(player) return customer_list, seller_list def role_assignment_small(subsession,SELLER, CUSTOMER): player_list = subsession.get_players() player_points = [(player.id, player.participant.total_points_test ,player) for player in player_list] customer_list, seller_list = [],[] # Sort the list based on total_points_test sorted_player_points = sorted(player_points, key=lambda x: x[1]) for i, (id, points, player) in enumerate(sorted_player_points): if i < len(player_list)//2: player.tag = CUSTOMER #player.role = CUSTOMER player.type = 0 player.customer = True customer_list.append(player) else: player.tag = SELLER #player.role = SELLER player.type = 1 player.customer = False seller_list.append(player) return customer_list, seller_list def sort_sellers(sellers, order): n = len(order) sorted_sellers = [] for i in range(0, len(sellers), n): chunk = sellers[i:i+n] if len(chunk) == n: # Ensure the chunk is complete as per the order length sorted_chunk = [chunk[j] for j in order] else: # If the chunk is incomplete, just add it as is sorted_chunk = chunk sorted_sellers.extend(sorted_chunk) return sorted_sellers def matching(customer, seller, seller_order, small): if small: sorted_sellers = [None] * len(seller) random.shuffle(customer) sorted_customer = customer ### EVTL NUR FÜR DIE SMALL VARIANTE; NOCHMAL DURCHSCHAUEN MIT 24 for new_index, seller_index in enumerate(seller_order): sorted_sellers[new_index] = seller[seller_index] #sorted_customer[new_index] = customer[] match_count = len(seller)//3 matching_array = [] for i in range(match_count): match = sorted_customer[i * 3: (i + 1) * 3] + sorted_sellers[i * 3: (i + 1) * 3] matching_array.append(match) return matching_array # Todo: Falls leute nichtauftauchen (weniger Customer) hier die logikanpassen else: # für 24 # matching_array = [] # match_count = len(seller)//3 # wv 3er Gruppen Seller haben wir # # ## customer: # missing_customer = match_count*3 - len(customer) # full_groups = match_count - missing_customer # # ## einfach 6er Gruppen bauen # for i in range(full_groups): # group_sellers = seller[i*3: (i+1)*3] # group_customers = customer[i*3: (i+1)*3] # gleiche Logik und größe wie die Seller # matching_array.append(group_sellers+group_customers) # # ### die 5er Gruppen bauen # for i in range(missing_customer): # group_sellers = seller[(full_groups + i) * 3: (full_groups + i + 1) * 3] # group_customers = customer[(full_groups + i) * 2: (full_groups + i + 1) * 2] # matching_array.append(group_sellers + group_customers) # return matching_array # ''' # ### todo: Behnud Zum widerherstellen löschen wenn das obere Passt # #für 24 random.shuffle(customer) sorted_customer = customer #sorted_sellers = sort_sellers(seller, seller_order) sorted_sellers = [seller[i] for i in seller_order] ## muss die Reihenfolge haben match_count = len(seller) // 3 matching_array = [] ### Seller so lassen, Kunden anpassen aufgrundlage der 3teilbarkeit # sorted_seller_group = sorted_sellers[0 * 3: (0 + 1) * 3] ## sorted_customer_group = [0,2,4,2,424,24] ## Window für Customer verschieben for i in range(match_count): match = sorted_customer[i * 3: (i + 1) * 3] + sorted_sellers[i * 3: (i + 1) * 3] matching_array.append(match) return matching_array # ''' def seller_order_swap(): mix_bottom = [0,1,2,3] mix_top = [8,9,10,11] order_mid = [7,6,5,4] random.shuffle(mix_bottom) random.shuffle(mix_top) matching_array=[] for i in range(len(mix_bottom)//2): match = [ mix_bottom[i*2], mix_bottom[i*2+1], order_mid[i] ] match_top = [ mix_top[i*2], mix_top[i*2+1], order_mid[2+i] ] matching_array.extend(match) matching_array.extend(match_top) return matching_array def generate_order_for_tasks(player, analogy_length, num_sequence_length): maximum_length = min(analogy_length, num_sequence_length) indices_seller = list(range(0, maximum_length)) ## only 37 in the num_sequence file indices_customer = list(range(0, maximum_length)) random.shuffle(indices_customer) random.shuffle(indices_seller) player.participant.social_proximity_order_customer = indices_customer player.participant.social_proximity_order_seller = indices_seller def get_cities(): with open(os.path.join(os.path.dirname(__file__), 'files/', 'staedte.txt'), 'r', encoding='utf-8') as file: cities = [line.strip() for line in file] return [(city, city) for city in cities] def get_countries(): with open(os.path.join(os.path.dirname(__file__), 'files/', 'laender.txt'), 'r', encoding='utf-8') as file: countries = [line.strip() for line in file] return [(country, country) for country in countries] def convert_to_binary(elem): if elem in ['0', 'False', 0, '']: return 0 return 1 def count_similarities(player,opposite, binary_question = 68, stringquestions = 6): arr = show_similarity(player,opposite,binary_question,stringquestions) arr = np.array([convert_to_binary(elem) for elem in arr]) similarity_count = np.count_nonzero(arr) return similarity_count def calc_string_responses(p1,p2, string_questions = 3): string_similarity_count = 0 for i in range(-string_questions, 0): if p1[i].strip().lower() == p2[i].strip().lower(): string_similarity_count+=1 return string_similarity_count def show_similarity(player,opposite, binary_question = 68,stringquestions = 6): p1 = player.participant.social_proximity_list p2 = opposite.participant.social_proximity_list p1_binary = np.array(p1[:binary_question] == 'True', dtype=int) p2_binary = np.array(p2[:binary_question] == 'True', dtype=int) same_ones_binary = np.bitwise_and(p1_binary, p2_binary) p1_multiples = p1[binary_question:len(p1) - stringquestions] p2_multiples = p2[binary_question:len(p2) - stringquestions] same_ones_multiple = np.where(p1_multiples == p2_multiples, p1_multiples, 0) same_one_string = [""] * stringquestions # np.zeros(stringquestions, dtype=int) for i in range(stringquestions): p1_str = p1[-stringquestions + i].strip().lower() p2_str = p2[-stringquestions + i].strip().lower() same_one_string[i] = p1[-stringquestions + i] if p1_str == p2_str else "" # same_ones_multiple = np.where(p1 == p2, p1,0) combined = [same_ones_binary, same_ones_multiple, same_one_string] return np.concatenate(combined) def avg_similarities(player, opp_group): similarities = [count_similarities(player,p) for p in opp_group] avg = sum(similarities)/len(opp_group) return avg def get_seller_subgroup(group, seller = "SELLER"): seller = [] for player in group: if player.type != 0: seller.append(player) return seller ### OLD UNPERFORMANT 7ER def seven_old_generator(): i = 1 solution = 0 counts_7 = [0] * 15 LINE_LENGTH = 15 numbers = [0] * 15 # // Fill all 16 lines with numbers while (i <= 15): # // Initialize variables j = 1 # val_t = 0 counts_7[i - 1] = 0 innerlist = [0] * 15 # // Fill a line up to LINE_LENGTH while (j <= LINE_LENGTH): val_t = 0 val = random.randint(0, 9) # // val_t = val_t * MULTI; val_t = val_t + val # // Repeat under certain condition, prevent leading 0 if (val_t == 0 and j == 1): j = 0 # // Add solution if value is a 7 if (val == 7): counts_7[i - 1] = counts_7[i - 1] + 1 innerlist[j - 1] = str(val_t) j = j + 1 numbers[i - 1] = ''.join(innerlist) solution = solution + counts_7[i - 1] i = i + 1 return numbers, solution def load_logic_tasks(type="analogy"): path = __name__[:-7] + "/files/" + type + ".csv" typemodel = Analogy ## todo: type ändern oder analogy boolsch machen if type=='nums': typemodel = NumberSequence rows = read_csv(path, typemodel) for i, row in enumerate(rows): row['number'] = i+1 return rows def get_number_for_player(player,stage): number = player.round_number*2 - 3 + stage ## stage sollte 1 oder 2 sein if player.type: return player.participant.social_proximity_order_customer[number] return player.participant.social_proximity_order_seller[number] def check_for_correct_answer(player, game_object, response_games): try: resp = json.loads(str(response_games)) if resp == 0: return False return resp['answer'] == game_object['solution'] except JSONDecodeError: return False def customer_seller_divider(players): customer, seller, customer_subsession, seller_subsession= [],[],[],[] for p in players: if p.customer: customer_subsession.append(p.id_in_subsession) customer.append(p.id_in_group) else: seller_subsession.append(p.id_in_subsession) seller.append(p.id_in_group) return customer,seller, customer_subsession, seller_subsession def one_to_one_matching(players, second_time = False): ### Trennen Customer und Seller _,_, customer,seller = customer_seller_divider(players) random.shuffle(customer) if len(customer) != len(seller) and second_time: ## customer umsortieren das die unverbrauchten der Vorrunde vorne stehen seller = seller[::-1] ## umdrehen ## Variante zum testen mit 24-21 seller_overhead = len(seller) - len(customer) if seller_overhead > 0: seller_matching = seller[:-seller_overhead] else: seller_matching = seller matching_array = [ [s, c] for s, c in zip(seller_matching, customer) ] if seller_overhead>0: for s in seller[-seller_overhead:]: matching_array.append([s]) for p in players: if seller_overhead>0 and p.id_in_subsession in seller[-seller_overhead:]: p.play_together = False ### Frag nach ob ich einen Partner habe , sonst -1 . playtogether -1 else: p.match = 1 if p.customer else 2 return matching_array def one_to_one_matching_after_vote(subsession): for group in subsession.get_groups(): players = group.get_players() group_size = len(players) ## hier die seller und customer mal testen seller_ids = [group.seller_first, group.seller_second, group.seller_third] #seller_ids = [4,5,6] ## todo: wieder rausnehmen seller = [group.get_player_by_id(group.seller_first), group.get_player_by_id(group.seller_second), group.get_player_by_id(group.seller_third),] counts = dict(X=0, Y=0, Z=0) seller_list_letter = ['X', 'Y', 'Z'] for p in players: if p in seller: continue ## überspringe seller choices = [p.market_interaction_choice_1, p.market_interaction_choice_2, p.market_interaction_choice_3] ## choices haben ID 1,2,3 für X,Y,Z for i, choice in enumerate(choices): counts[seller_list_letter[choice-1]]+= 7 / (2**i) # Set Match if not chosen yet selected_seller_id = seller_ids[choice - 1] selected_seller = seller[choice-1] sel_seller = group.get_player_by_id(selected_seller_id) if selected_seller.match == -1 and p.match == -1: selected_seller.match = p.id_in_group p.match = selected_seller.id_in_group#choice p.matched_pref = i+1 p.match_letter = seller_list_letter[choice - 1] p.matched_index = choice - 1 if settings.DEBUG: pass break most_chosen_letter = max(counts, key=counts.get) most_chosen_index = seller_list_letter.index(most_chosen_letter) group.get_player_by_id(seller_ids[most_chosen_index]).top = True for p in players: if p.match==-1: p.play_together = False def calc_points_round(player): count7_nums = player.points_count_seven_1 + player.points_count_seven_2 + player.points_count_seven_3 + player.points_count_seven_4 analogy = player.points_analogy_2 + player.points_analogy_1 sequence = player.points_num_seq_1 + player.points_num_seq_2 logic = analogy+sequence return count7_nums+logic, logic, analogy, sequence def delta_number_count(count_7, solution, points=4): ret = max(points - abs(count_7-solution),0) return ret def build_global_vectors(player_list, CUSTOMER, SELLER): global customer_vector global seller_vector (cust_count, seller_count) = (0,0) for player in player_list: x = generate_subject_vector(player) ### Todo: Speichern wir den so in die Participant variable if player.role == CUSTOMER: customer_vector+=x cust_count+=1 else: seller_vector+=x seller_count+=1 cust_avg = customer_vector/cust_count sell_avg = seller_vector/seller_count def generate_subject_vector(subject_data): # Convert the subject's data into a numpy array ## get religion return np.array([ subject_data.hobbies_politik, subject_data.hobbies_kultur, subject_data.hobbies_technik, subject_data.hobbies_sport, subject_data.hobbies_familie, subject_data.hobbies_wellness, subject_data.hobbies_philosophie, subject_data.hobbies_tiere, subject_data.sport_ballsport, subject_data.sport_wintersport, subject_data.sport_wassersport, subject_data.sport_kraftsport, subject_data.sport_yoga, subject_data.sport_reiten, subject_data.sport_klettern, subject_data.sport_leichtathletik, subject_data.sport_kampfsport, subject_data.sport_motorsport, subject_data.sport_tanzsport, subject_data.sport_nosport, subject_data.music_klassik, subject_data.music_deutsche, subject_data.music_pop, subject_data.music_rap, subject_data.music_rock, subject_data.music_reggae, subject_data.music_jazz, subject_data.music_electronic, subject_data.film_krimi, subject_data.film_horror, subject_data.film_romantik, subject_data.film_action, subject_data.film_komoedie, subject_data.film_scifi, subject_data.film_dokus, subject_data.film_animation, subject_data.urlaub_meer, subject_data.urlaub_bergen, subject_data.urlaub_stadt, subject_data.urlaub_party, subject_data.urlaub_abenteuerlich, subject_data.urlaub_all_incl, subject_data.urlaub_fernweh, subject_data.urlaub_haus, subject_data.eigenschaft_karrierebewusst, subject_data.eigenschaft_kinderlieb, subject_data.eigenschaft_sportlich, subject_data.eigenschaft_zuruckhaltend, subject_data.eigenschaft_sparsam, subject_data.eigenschaft_warmherzig, subject_data.eigenschaft_zuverlassig, subject_data.eigenschaft_humorvoll, subject_data.denken_spass, subject_data.denken_gute_laune, subject_data.denken_ernsthaft, subject_data.denken_vertraeumt, subject_data.denken_sachlich, subject_data.denken_loesungsorientiert, subject_data.denken_ruhe, subject_data.denken_lebhaft, subject_data.wichtig_freundschaft, subject_data.wichtig_liebe, subject_data.wichtig_ruhe, subject_data.wichtig_erfolg, subject_data.wichtig_menschen, subject_data.wichtig_soziale, subject_data.wichtig_selbstverwirklichung, subject_data.wichtig_partner, subject_data.Religion, subject_data.Diskussion, subject_data.Vertrauen, subject_data.Privat, subject_data.Widerspruch, subject_data.Impuls, subject_data.Kraenkung, subject_data.UeberVerhaeltnisse, subject_data.Rache, subject_data.Banane, subject_data.Wohnhaus, subject_data.Geschlecht, subject_data.Geburtsjahr, subject_data.Studienfeld, subject_data.Studiengang, subject_data.Herkunftsland, subject_data.Wohnort, ]) def calc_similarity(player1,player2): p1_vec = generate_subject_vector(player1) p2_vec = generate_subject_vector(player2) return calc_similarity_vector(p1_vec,p2_vec) def calc_similarity_vector(vec1,vec2): diff = np.abs(vec1 - vec2) sim = vec1 == vec2 return sim, diff def set_random_answers(player_list): bool_fields = [v for v in field_labels.values()][:68] rest = [v for v in field_labels.values()][68:-6] rest_string = [v for v in field_labels.values()][-6:] rest_answers_type1 = ["weiblich","1990","Angewandte Sportwissenschaft", "Naturwissenschaft" , "Albanien", "Aasen" ] rest_answers_type2 = ["männlich","1989","Sport BK", "Sport" , "Deutschland", "Paderborn" ] for player in player_list: type_1 = random.random() < 0.5 for field in bool_fields: setattr(player,field,random.choice([True,False])) for field in rest: setattr(player,field,2) for i,field in enumerate(rest_string): val = rest_answers_type1[i] if type_1 else rest_answers_type2[i] setattr(player, field, val) def get_boolean_for_tasks(customer, stage, round, type_of_task, play_together, test_round = 2): ## NUR SELLER if round <= test_round: return True if not customer: return play_together if type_of_task == 1: return False # [1,2,3,4,5,6,7,8] - 1 = countseven , 2,4 logikaufgaben if type_of_task == 2 and stage == 1: return True if type_of_task == 3 and stage in (2,4): return True return False def get_group_before(players ): matching_array = [[],[],[],[]] ### händisch gemacht for p in players: p_before = p.in_round(3) matching_array[p_before.group_before_one_to_one_matching - 1].append(p.id_in_group) p.group_before_one_to_one_matching = p_before.group_before_one_to_one_matching return matching_array def calc_payoff_round(player, round , exchange_rate_anbieter = 1.25, exch_rate_kunde_anbieter = 2.4, exch_rate_kunde_owntask = 1.5 , exch_rate_util = 1, cost_util_fail_kunde = -0.5, no_transact_payoff = 8, bonus_pref_anbieter = 3, bonus_util_correct_interaction= 3, bound_estimation = 1, max_points_kunde_owntasks = 4, start_market = 5 ): customer = player.customer if round <= 2: #Testrunde player.payoff = player.points_total else: ## ab runde 3 if not player.play_together or player.match == -1 : ## heißt einer zu wenig & ich habe kein gegenüber player.payoff = no_transact_payoff player.payoff_show_float = no_transact_payoff else: opposite = player.group.get_player_by_id(player.match) ### gegenüber if not customer: ### ANBIETER player.payoff = player.points_total * exchange_rate_anbieter ## Grundlage Anbieter Verdienst player.payoff_show_float = player.points_total * exchange_rate_anbieter player.payment_toseller = player.payoff_show_float if opposite.type_of_task > 1: ## hat gespielt mein Freund util_customer = (max_points_kunde_owntasks - opposite.points_total)*cost_util_fail_kunde customer_correct = opposite.points_total == max_points_kunde_owntasks if customer_correct: util_customer = (max_points_kunde_owntasks)*exch_rate_kunde_owntask player.utility_customer_forseller = util_customer*exch_rate_util ## evtl die umrechnung hier erweitern player.payoff += player.utility_customer_forseller player.payoff_show_float += player.utility_customer_forseller if round >= start_market: ## mostvotedanbieter bonus player.bonus_most_preferred = bonus_pref_anbieter * player.top player.payoff += player.bonus_most_preferred player.payoff_show_float += player.bonus_most_preferred else: ### KUNDE util_customer = opposite.points_total * exch_rate_kunde_anbieter player.util_seller = util_customer correct = player.points_total == max_points_kunde_owntasks if correct: player.util_customer = max_points_kunde_owntasks*exch_rate_kunde_owntask util_customer += player.util_customer if abs(opposite.points_total - player.estimated_points) <= bound_estimation: util_customer += bonus_util_correct_interaction player.estimation_customer = bonus_util_correct_interaction player.payoff_show_float = util_customer * exch_rate_util player.payoff = cu(player.payoff_show_float) ## bezahl den Anbieter player.payment_toseller = opposite.points_total * exchange_rate_anbieter player.payoff_show_float -= player.payment_toseller player.payoff -= player.payment_toseller def generate_performance_info_group(group): _ , seller, _, _ = customer_seller_divider(group.get_players()) first, second, third = group.get_player_by_id(seller[0]), group.get_player_by_id(seller[1]), group.get_player_by_id(seller[2]) performance = (calc_points_total_till_round(first) + calc_points_total_till_round(second) + calc_points_total_till_round(third)) / 3 return performance def generate_misc_data(integer_fields): int_field_data = dict() for field in integer_fields: int_field_data[field.name] = dict( label = field.label, choices = field.choices ) return int_field_data def generate_answer_text(labels, prefixs, answers, no_match = 'Keine Übereinstimmung'): ## [list of list][list of strings] page_dict = dict() if len(labels) != len(prefixs): raise ValueError('Länge labels und Prefixs müssen identisch sein') for label,prefix in zip(labels,prefixs): page_dict[prefix] = dict( label=label, answers=None ) for key, (antwort,label) in zip(page_dict.keys(), enumerate(answers)): label_info = page_dict[key] label_info['answers'] = label if antwort != 0 else no_match return page_dict ### Ganzen Similarity Page extra def find_choice_in_dict(singular_data_choices, name, choice): for item in singular_data_choices: if item['name'] == name: break res = get_name_by_index(item['choices'], choice) return res def get_name_by_index(choices, index): for entry in choices: if entry[0] == index: return entry[1] return None def prepare_similarity_data_for_js(similarity_results, question_groups, header_labels, besondere, player , singular_data_choices, KEINE_UEBEREINSTIMMUNG, EXTRA_STRING_ANSWERS = ['Studiengang', 'Geburtsjahr', 'Geschlecht', 'Wohnort', 'Herkunftsland', 'Studienfeld']): tabs_data = {} ## durch die kategorien mit den jweiligen fragen durch iterieren for category , questions in question_groups.items(): ## Das baut uns die tabs in der Form - {'Interessen': {'header': 'Interessen', 'questions': []}, tabs_data[category] = dict( header=category, ### evtl hier die label gedöns hinmachen !!! DAS HIER IST DER TAB HEADER questions = [] ) multiple_questions = [] multiple_questions_not_used = set() for question in questions: idx = next((i for i, label in enumerate(field_labels.values()) if label == question['name']), None) if idx is not None: is_similar = str(similarity_results[idx]) not in ['', '0', 'False'] ## Similar mit TExt multi_answer_question = question['name'].islower() if is_similar: if question['name'] in EXTRA_STRING_ANSWERS: player_answer = getattr(player.in_round(1), question['name'], KEINE_UEBEREINSTIMMUNG) tabs_data[category]['questions'].append(dict(name=question['label'], answers=[player_answer])) elif multi_answer_question: ## multiple choices ## liste der antworten multiple_questions.append(dict(question=question['name'].split('_')[0],answer = question['label'])) else: player_answer = getattr(player.in_round(1), question['name'], KEINE_UEBEREINSTIMMUNG) answer = find_choice_in_dict(singular_data_choices,question['name'],player_answer) tabs_data[category]['questions'].append(dict(name=question['label'], answers=[answer])) else: ### Fallunterscheidung, bei single data - direkt mit hinzufügen, bei multipledata den anderen füllen if multi_answer_question: multiple_questions_not_used.add(question['name'].split('_')[0]) else: tabs_data[category]['questions'].append( dict(name=question['label'], answers=[KEINE_UEBEREINSTIMMUNG])) ### für die multiantwortmöglichkeiten if multiple_questions: unique_questions = {entry['question'] for entry in multiple_questions} for question_header in unique_questions: ## anstatt den ersten zu nehmen, bau mir eine Menge von Headern und geh nur für diesen prefix durch question_header_label = header_labels.get(question_header,'nicht gefunden') quest_dict = dict( name=question_header_label, answers=[] ) for label in multiple_questions: if label['question'] == question_header: quest_dict['answers'].append(label['answer']) ## update tab-dataheaderlabel, if not there tabs_data[category]['questions'].append(quest_dict) if not multiple_questions and multiple_questions_not_used: ####Hier die Multiple dinger als Frage hinzufügen for name in multiple_questions_not_used: tabs_data[category]['questions'].append(dict(name=header_labels.get(name, 'nicht gefunden'), answers=[KEINE_UEBEREINSTIMMUNG])) ### Namen zurück übersetzen for entry,fulltext in besondere.items(): tabs_data[entry]['header'] = fulltext return json.dumps(tabs_data)