示例#1
0
    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()
示例#2
0
    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))
示例#3
0
 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
示例#4
0
    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
示例#5
0
    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)
示例#6
0
    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()
示例#7
0
    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
示例#8
0
    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
示例#9
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()
示例#10
0
    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
示例#11
0
    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))
示例#12
0
    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))
示例#13
0
    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)