def __init__(self, name, customer_id, wallet, dataCenter, crisp_sets=(0.3, 0.7), price_tolerance=0.5, quality_tolerance=0.5): """ :type dataCenter: DataCenter """ self.name, self.customer_id, self.wallet = name, customer_id, wallet self.price_tolerance, self.quality_tolerance = price_tolerance, quality_tolerance self.dataCenter = dataCenter # initialize crisp sets for fuzzy logic self.crisp_sets = crisp_sets # Register the user with google ads GoogleAds.register_user(self) self.dataCenter.register_data(self, register_type='customer') # ad space stores all the adverts consumed by this user self.ad_space = set() # stores all the bought products self.owned_products = set() # flag to stop thread self.STOP = False # regulate synchronisation self.lock = Lock() # start this user in separate thread self.thread = Thread(name=name, target=self.loop) self.thread.start()
def tick(self): self.lock.acquire() # append the sales record to the history self.sales_history.append(self.item_sold) # reset the sales counter self.item_sold = 0 self.lock.release() # Calculate the metrics for previous tick and add to tracker self.revenue_history.append(self.sales_history[-1] * self.product.price) self.profit_history.append(self.revenue_history[-1] - self.expense_history[-1]) self.sentiment_history.append(self.user_sentiment()) # add the profit to seller's wallet self.wallet += self.my_profit(True) # choose what to do for next timestep advert_type, scale = self.CEO() # ANSWER a. print data to show progress #test=', '.join(for x in self.sentiment_history) logging.info ('[Seller]: (%s,%d) Revenue in previous quarter:%d', self.name,self.tickcount,self.my_revenue(True)) logging.info ('[Seller]: (%s,%d) Expenses in previous quarter:%d', self.name,self.tickcount,self.my_expenses(True)) logging.info ('[Seller]: (%s,%d) Profit in previous quarter:%d', self.name,self.tickcount,self.my_profit(True)) logging.info ('[Seller]: (%s,%d) Sentiment in previous quarter:%d', self.name,self.tickcount,self.user_sentiment()) #logging.info ('[Seller]: (%s,%d) Sales in previous quarter:%d', self.name,self.tickcount,self.sales_history(True)) #logging.info ('[Seller]: (%s,%d)Strategy for next quarter \nAdvert Type: {}, scale: {}\n\n'.format(advert_type, scale)) # perform the actions and view the expense self.expense_history.append(GoogleAds.post_advertisement(self, self.product, advert_type, scale))
def analyze(self, product): # WRITE YOUR INTELLIGENT CODE HERE # You can use following functions to make decision # my_revenue # my_expenses # my_profit # user_sentiment # # You need to return the type of advert you want to publish and at what scale # GoogleAds.advert_price[advert_type] gives you the rate of an advert if GoogleAds.user_coverage(product) < 0.5: advert_type = GoogleAds.ADVERT_BASIC else: advert_type = GoogleAds.ADVERT_TARGETED logging.info('[CEO]: (%s,%d) CEO wallet %d ads price %d', self.seller.name, self.seller.tick_count, self.seller.wallet, GoogleAds.advert_price[advert_type]) scale = self.seller.wallet // GoogleAds.advert_price[ advert_type] // 10 # not spending everything # scale = 5 logging.info( '[CEO]: (%s,%d) CEO selected advert_type as %s with scale of %d for %s', self.seller.name, self.seller.tick_count, advert_type, scale, product.product_name) return advert_type, scale
def CEO(self): """ Choose advertisement types and scales for each product based on revenue and user_coverage. If user_coverage is less than target, choose basic ads, otherwise choose targeted ads. Set total advertisement budget less than a percentage of revenue or wallet money, to avoid bankrupt Scale (number of ads to put) equals to budget divided by advert price. :return: none """ # initilize empty variable advert_type = {} expense = {} ads_type = GoogleAds.ADVERT_BASIC # set advertising budget as a percentage of total revenue or total money in wallet ads_percent = 0.5 max_budget = self.wallet * 0.2 # decide individual advertising strategy for each product for product in self.products_list: # get the latest revenue to decide ads budget revenue = self.revenue_history[-1][product] #avoid bankrupt by setting advertisment budget ads_budget = max(ads_percent * revenue, max_budget) coverage = GoogleAds.user_coverage(product) # check if user_coverage is more than half of GoogleAds users if coverage > 0.5: ads_type = GoogleAds.ADVERT_TARGETED scale = min(int(ads_budget / GoogleAds.advert_price[ads_type]), 500) # perform the actions and view the expense advert_type.update({product: (ads_type, scale)}) # obtain expense from GoogleAds expense.update({product: GoogleAds.post_advertisement(self, product, ads_type, scale)}) # store advertisement types and scales, and expense history self.advert_history.append(advert_type) self.expense_history.append(expense) return
def buy(buyer, product): # get the seller for product from catalogue seller = Market.catalogue[product] # call seller's sold function seller.sold() logging.info("[Market]:Notify Seller %s about the sale of product %s ", seller.name, product.name) # deduct price from user's balance buyer.deduct(product.price) logging.info( "[Market]:Get the amount $ %s from buyer %s for product %s ", product.price, buyer.name, product.name) # track user GoogleAds.track_user_purchase(buyer, product) logging.info( "[Market]:Add buyer %s purchased the product %s to google Add track history", buyer.name, product.name)
def __init__(self, name, wallet, tolerance=0.5): self.name, self.wallet, self.tolerance = name, wallet, tolerance logging.info ("[Customer]:Customer %s Created",self.name) # Register the user with google ads GoogleAds.register_user(self) # ad space stores all the adverts consumed by this user self.ad_space = set() # stores all the bought products self.owned_products = set() # flag to stop thread self.STOP = False # regulate synchronisation self.lock = Lock() self.tickcount=0 # start this user in separate thread self.thread = Thread(name=name, target=self.loop) self.thread.start()
def buy(buyer, product_list): # give discount for more than 2 products if len(product_list) >= 2: discount_factor = 0.9 else: discount_factor = 1 for product in product_list: # get the seller for product from catalogue seller = Market.catalogue[product] # call seller's sold function which returns True if product is available; otherwise transaction fails if seller.sold(product): # deduct price from user's balance buyer.deduct(product.price*discount_factor) # track user GoogleAds.track_user_purchase(buyer, product) else: return False return True
def buy(buyer, product): Market.lock.acquire() # get the seller for product from catalogue storage_dict = Market.catalogue[product] seller_list = [seller for seller in storage_dict if storage_dict[seller] > 0] market_storage = sum([seller.product_storage[product] for seller in seller_list]) # call seller's sold function if len(seller_list) > 0: if market_storage > shortage: seller_index = 0 min_price = seller_list[0].price_history[product][-1] for seller in seller_list: index = 0 if seller.price_history[product][-1] < min_price: seller_index = index index += 1 seller = seller_list[seller_index] seller.sold(product) Market.catalogue[product][seller] -= 1 # deduct price from user's balance buyer.deduct(seller.price_history[product][-1]) # track user GoogleAds.track_user_purchase(buyer, product) Market.lock.release() return seller else: price = max([seller.price_history[product][-1]] for seller in seller_list) deal, seller, buyer = Auctioneer.bid_buy(buyer, product, market_storage, seller_list, price) if deal: Market.catalogue[product][seller] -= 1 GoogleAds.track_user_purchase(buyer, product) else: Market.lock.release() return 0
def __init__(self, name, wallet, products_list, tolerance=0.5): self.name, self.wallet, self.tolerance = name, wallet, tolerance # Register the user with google ads GoogleAds.register_user(self) # ad space stores all the adverts consumed by this user self.ad_space = [] # stores all the bought products self.owned_products = [] # the total product list, same as seller side self.products_list = products_list # product correlation factor matrix self.products_matrix = \ [[1, 0.7, 0.3, 0.6, 0.7, 0.5, 0.9, 0.7, 0.3], [0.7, 1, 0.4, 0.2, 0.5, 0.7, 0.9, 0.2, 0.1], [0.3, 0.4, 1, 0.8, 0.9, 0.1, 0.4, 0.5, 0.3], [0.6, 0.2, 0.8, 1, 0.9, 0.5, 0.4, 0.7, 0.4], [0.7, 0.2, 0.8, 1, 1, 0.5, 0.4, 0.7, 0.4], [0.5, 0.2, 0.8, 1, 0.9, 1, 0.4, 0.7, 0.4], [0.9, 0.2, 0.8, 1, 0.9, 0.5, 1, 0.7, 0.4], [0.7, 0.2, 0.8, 1, 0.9, 0.5, 0.4, 1, 0.4], [0.3, 0.2, 0.8, 1, 0.9, 0.5, 0.4, 0.7, 1] ] # flag to stop thread self.STOP = False # regulate synchronisation self.lock = Lock() # start this user in separate thread self.thread = Thread(name=name, target=self.loop) self.thread.start()
def CEO(self): # WRITE YOUR INTELLIGENT CODE HERE # You can use following functions to make decision # my_revenue # my_expenses # my_profit # user_sentiment # # You need to return the type of advert you want to publish and at what scale # GoogleAds.advert_price[advert_type] gives you the rate of an advert if (GoogleAds.user_coverage(self.product.name) < 0.5): advert_type = GoogleAds.ADVERT_BASIC else: advert_type=GoogleAds.ADVERT_TARGETED scale = self.wallet // GoogleAds.advert_price[advert_type] // 2 #not spending everything logging.info ('[Seller]: (%s,%d) CEO selected advert_type as %s with scale of %d for %s', self.name,self.tickcount,advert_type,scale,self.product.name) return advert_type, scale
def tick(self): """ in each tick, each product will be considered iteratively while in CEO decsion function, all products will be considered in each decsion""" self.dataCenter.seller_info_update(self.count) """ decide whether to buy cheating data sheets in each tick count > 20 """ self.data_cheating = False if self.count > 20 and random.random() > 0.7: self.data_cheating = True """obtain cheating data sheet """ self.dataCenter.send_data(self) # the price of a cheating package is related to package size self.wallet -= 20 * self.count self.cheating_package = self.dataCenter.send_data(self) for product in self.product_list: self.lock.acquire() # append the sales record to the history self.dataCenter.data_ranking(obj_data=[product, self], data_type='seller') self.sales_history[product].append(self.item_sold[product]) self.product_storage[product] -= self.item_sold[product] # reset the sales counter self.item_sold[product] = 0 # Calculate the metrics for previous tick and add to tracker self.revenue_history[product].append( self.sales_history[product][-1] * self.price_history[product][-1]) self.profit_history[product].append( self.revenue_history[product][-1] - self.expense_history[product][-1]) self.wallet += self.profit_history[product][-1] self.sentiment_history[product].append( self.user_sentiment(product)) self.price_history[product].append( self.price_history[product][-1] + self.CEO_price(product)) # add the profit to seller's wallet self.wallet += self.my_profit(product, True) self.lock.release() # choose what to do for next timestep advert_type, user_list, scale = self.CEO_advertisement(product) # ANSWER a. print data to show progress print('\nProduct in previous quarter: ' + product.name) print('Revenue in previous quarter:', self.my_revenue(product, True)) print('Expenses in previous quarter:', self.my_expenses(product, True)) print('Profit in previous quarter:', self.my_profit(product, True)) print( '\nStrategy for next quarter \nAdvert Type: {}, scale: {}\n\n'. format(advert_type, scale)) print('\n', self.count) # avoid bankrupt if self.count > 0 and self.revenue_history[product][-1] > 0: budget = ad_budget_ration * self.revenue_history[product][-1] elif self.count == 0: budget = ad_budget_ration * self.wallet / len( self.product_list) # perform the actions and view the expense else: budget = 0 if self.product_storage[product] > 0: self.expense_history[product].append( GoogleAds.post_advertisement(self, product, advert_type, user_list, scale, budget)) else: self.expense_history[product].append(0) print(self.name + ' wallet: ' + str(self.wallet))
def tick(self): self.lock.acquire() # append the sales record to the history self.sales_history.append(self.item_sold) # reset the sales counter self.item_sold = 0 self.lock.release() # Calculate the metrics for previous tick and add to tracker for product in self.products: # logging.info("[Seller]: (%s,%d) sold %d units of %s",self.name,self.tick_count,self.item_sold, product.product_name) self.revenue_history.append(self.sales_history[-1] * product.stock_price) self.profit_history.append(self.revenue_history[-1] - self.expense_history[-1]) self.sentiment_history.append(self.user_sentiment()) # add the profit to seller's wallet # self.wallet += self.my_profit(True) # choose what to do for next timestep ceo = CEO(self) # advert_type, scale = ceo.analyze() ceo.check_any_products_out_of_stock() ceo.purchase_stock() if self.wallet < 200: ceo.apply_discount_for_all_products() else: ceo.adjust_price() # ANSWER a. print data to show progress # print('Revenue in previous quarter:', self.my_revenue(True)) # print('Expenses in previous quarter:', self.my_expenses(True)) # print('Profit in previous quarter:', self.my_profit(True)) # print('\nStrategy for next quarter \nAdvert Type: {}, scale: {}\n\n'.format(advert_type, scale)) # logging.info('[Seller]: (%s,%d) Revenue in previous quarter:%d', self.name, self.tick_count, self.my_revenue(True)) # logging.info('[Seller]: (%s,%d) Expenses in previous quarter:%d', self.name, self.tick_count, self.my_expenses(True)) # logging.info('[Seller]: (%s,%d) Profit in previous quarter:%d', self.name, self.tick_count, self.my_profit(True)) # logging.info('[Seller]: (%s,%d) Sales in previous quarter:%s', self.name, self.tick_count, self.sales_history) # perform the actions and view the expense for product in self.products: # choose between ad type and scale advert_type, scale = ceo.analyze(product) # decide how much to spend on ads budget = ceo.decide_how_much_to_spend_on_ads() if GoogleAds.post_advertisement(self, product, advert_type, scale) > budget: logging.info( '[Seller,(%s,%d)]: The cost of product %s on ads exceeds the budget, do not spend.', self.name, self.tick_count, product.product_name) else: logging.info( '[Seller,(%s,%d)]: The cost of product %s on ads is less than the budget, then buy ads.', self.name, self.tick_count, product.product_name) self.expense_history.append( GoogleAds.post_advertisement(self, product, advert_type, scale))
def buy(buyer, products): # products: list of product of the same type, such as the iPhone XS product_id = products[0].product_id product_name = products[0].product_name product_price = products[0].stock_price seller_id = products[0].seller_id promotion_id = -1 # flag to check if a promotion applied most_valuable_customer_id = mysql.find_most_valuable_customer( seller_id) # get the seller for product from catalogue for product in products: # # random choose seller # seller_index = choice(Market.catalogue[product.product_name]) # index = Market.catalogue[product.product_name].index(seller_index) # seller = Market.catalogue[product.product_name][index] # find seller in the market catalogue for x in Market.catalogue.get(product.product_name): if x.id == seller_id: seller = x # find the buyer who has spent the most in the same seller and offer promotion with id 1 if most_valuable_customer_id == buyer.id: product_price = product.stock_price * 0.95 promotion_id = 1 # call seller's sold function seller.sold(product) # deduct price from user's balance buyer.deduct(product.stock_price) # track user GoogleAds.track_user_purchase(buyer, product) # update the stock of product products[0].stock_quantity = products[0].stock_quantity - len(products) if products[0].stock_quantity < 0: # print("stock < 0") pass else: logging.info( "[Market]: Update the stock quantity to %d of product %s of seller %s %d", products[0].stock_quantity, product_name, seller.name, seller_id) # update the stock of product in database mysql.update_stock(product_id, seller_id, products[0].stock_quantity, products[0].stock_cost, seller.wallet) dt = datetime.datetime.now() transaction = Transaction(datetime=dt, seller_id=seller.id, customer_id=buyer.id, product_id=product_id, quantity=len(products), total_amount=product_price * len(products)) logging.info( "[Market]:Transaction between Seller %s and Customer %s with the product %s at %s " "in year %s and quarter %s", seller.name, buyer.name, product_name, transaction.timestamp, transaction.year, transaction.quarter) # add the profit to seller's wallet seller.wallet += product_price * len(products) # if a promotion has been applied in calculating, then update the transaction promotion id property if promotion_id != -1: transaction.set_promotion_id(promotion_id) # if a customer makes a single transaction > $2000, offer a $50 off if transaction.total_amount >= 2000: transaction.total_amount -= 50 # if no promotion has been applied to this customer, then update the transaction promotion to id 5 if promotion_id == -1: transaction.set_promotion_id(5) # write to database mysql.save_txn(transaction)