from otree.api import * doc = """ Shopping app (online grocery store) """ def read_csv(): import csv with open (__name__ + '/catalog_new.csv', encoding='utf-8-sig') as f: rows = [row for row in csv.DictReader(f)] for row in rows: # all values in CSV are string unless you convert them row['unit_price'] = float(row['unit_price']) row['image_path'] = 'dishes/{}.jpeg'.format(row['image_jpeg']) # print(rows) return rows def read_csv_2(): import csv with open (__name__ + '/catalog_new_2.csv', encoding='utf-8-sig') as f: rows2 = [row for row in csv.DictReader(f)] for row2 in rows2: # all values in CSV are string unless you convert them row2['unit_price_2'] = float(row2['unit_price_2']) row2['image_path_2'] = 'dishes_2/{}.jpeg'.format(row2['image_jpeg_2']) # print(rows) return rows2 class C(BaseConstants): NAME_IN_URL = 'shop_takeout' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 PRODUCTS = read_csv() # SKU = 'stock keeping unit' = product ID PRODUCTS_DICT = {row['sku']: row for row in PRODUCTS} PRODUCTS_2 = read_csv_2() PRODUCTS_DICT_2 = {row2['sku2']: row2 for row2 in PRODUCTS_2} class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): total_price = models.CurrencyField(initial=0) restaurant = models.StringField(initial="0") class Item(ExtraModel): player = models.Link(Player) sku = models.StringField() name = models.StringField() quantity = models.IntegerField() unit_price = models.CurrencyField() def total_price(item: Item): return item.quantity * item.unit_price def to_dict(item: Item): return dict( sku=item.sku, name=item.name, quantity=item.quantity, total_price=total_price(item), ) def live_method(player: Player, data): if 'sku' in data: sku = data['sku'] delta = data['delta'] product = C.PRODUCTS_DICT[sku] matches = Item.filter(player=player, sku=sku) if matches: [item] = matches item.quantity += delta if item.quantity <= 0: item.delete() else: if delta > 0: Item.create( player=player, quantity=delta, sku=sku, name=product['name'], unit_price=product['unit_price'], ) items = Item.filter(player=player) item_dicts = [to_dict(item) for item in items] player.total_price = sum([total_price(item) for item in items]) return {player.id_in_group: dict(items=item_dicts, total_price=player.total_price)} def live_method_2(player: Player, data): if 'sku' in data: sku = data['sku'] delta = data['delta'] product = C.PRODUCTS_DICT_2[sku] matches = Item.filter(player=player, sku=sku) if matches: [item] = matches item.quantity += delta if item.quantity <= 0: item.delete() else: if delta > 0: Item.create( player=player, quantity=delta, sku=sku, name=product['name_2'], unit_price=product['unit_price_2'], ) items = Item.filter(player=player) item_dicts = [to_dict(item) for item in items] player.total_price = sum([total_price(item) for item in items]) return {player.id_in_group: dict(items=item_dicts, total_price=player.total_price)} #PAGES class SelectRestaurant(Page): form_fields = ["restaurant"] form_model = "player" @staticmethod def vars_for_template(player: Player): # print(dict(items=Item.filter(player=player))) return dict(items=Item.filter(player=player)) # @staticmethod # def before_next_page(player: Player, timeout_happened): # print(player.restaurant) class ShopPage_1(Page): @staticmethod def is_displayed(player: Player): return player.restaurant == str(1) live_method = live_method # def vars_for_template(player: Player): # print(player.raw_responses) class ShopPage_2(Page): @staticmethod def is_displayed(player: Player): return player.restaurant == str(2) live_method = live_method_2 class Confirm(Page): # def before_next_page(self): # if 'back' in self.request.POST: # self._is_back = True @staticmethod def vars_for_template(player: Player): return dict(items=Item.filter(player=player)) class Results(Page): @staticmethod def vars_for_template(player: Player): return dict(items=Item.filter(player=player)) page_sequence = [ SelectRestaurant, ShopPage_1, ShopPage_2, Results ]