def get_set_brand(self, name):
        """
            Step 1: Check if name is None or not.
            Step 2: Set name to lower(name), for ease of caching.
            Step 3: If name is in correction, set name to lower(correct name).
            Step 4: If name brands is in cache, get the cached Brand object.
            Step 5: Else, create a Brand object with title = original name
                    (correct but not lower cased). Then store it into the
                    cache it with name (correct and lower cased) as the key.
            Step 6: Return the Brand object.
        """
        if not name:
            return None

        name_original = name
        name = name_original.lower()
        if name in self.brand_corrections:
            name_original = self.brand_corrections[name]
            name = name_original.lower()

        if name in Pipeline.brands:
            return Pipeline.brands[name]

        brand = models.Brand(title=name_original)

        Pipeline.brands[name] = brand
        Pipeline.db.add(brand)

        return brand
Esempio n. 2
0
def resolve_acquisition():
    game_id = request.json['game_id']
    id_token = request.json['id_token']
    sell_count = int(request.json['sell_count'])
    trade_count = int(request.json['trade_count'])

    user_id = firebase_admin.auth.verify_id_token(id_token)['uid']
    state = persistance.get_game_state(game_id)

    if state.current_action_player != user_id:
        raise models.RuleViolation(
            "Stop trying to take other player's turns! You cheat!")

    if state.current_action_type != models.ActionType.RESOLVE_ACQUISITION:
        raise models.RuleViolation(
            'It is your turn, but it is not time to resolve an acquisition!')

    if not state.is_started:
        raise models.RuleViolation('Cannot take turn until game has begun!')

    acquiree = models.Brand(state.current_action_details['acquiree'])
    player_acquiree_stock_count = state.stock_by_player[user_id][acquiree]

    if sell_count + trade_count > player_acquiree_stock_count:
        raise models.RuleViolation(
            'Cannot trade and sell more stock than you current have!')

    acquirer = models.Brand(state.current_action_details['acquirer'])
    cost_at_acquisition_time = state.current_action_details[
        'acquiree_cost_at_acquisition_time']

    stock.sell_stock(state, user_id, acquiree, cost_at_acquisition_time,
                     sell_count)
    stock.trade_stock(state, user_id, acquiree, acquirer, trade_count)

    turns.transition_from_resolve(state, game_id)

    persistance.update_game_state(game_id, state.to_dict())

    return 'OK'
Esempio n. 3
0
def place_tile():
    game_id = request.json['game_id']
    id_token = request.json['id_token']
    x = int(request.json['x'])
    y = int(request.json['y'])
    raw_brand = request.json['brand']
    brand = None if raw_brand == '' else models.Brand(raw_brand)

    player_id = firebase_admin.auth.verify_id_token(id_token)['uid']
    state = persistance.get_game_state(game_id)

    if state.current_action_player != player_id:
        raise models.RuleViolation(
            "Stop trying to take other player's turns! You cheat!")

    if state.current_action_type != models.ActionType.PLACE_TILE:
        raise models.RuleViolation(
            'It is your turn, but it is not time to place a tile!')

    player_tiles = persistance.get_player_tiles(game_id, player_id)

    if not any(tile.x == x and tile.y == y for tile in player_tiles):
        raise models.RuleViolation(
            'You do not have that tile! Stop trying to cheat!')

    if not state.is_started:
        raise models.RuleViolation('Cannot take turn until game has begun!')

    tile = models.Tile(x, y)
    place_tile_result = grid.place_tile(state, tile, brand)
    stock.apply_majority_bonuses(state, place_tile_result.acquired_chains)
    stock.award_founder_share(state, player_id, place_tile_result.new_brand)
    grid.set_brand_lists(state)
    stock.set_price_table(state)
    turns.transition_from_place(state, place_tile_result, game_id)

    persistance.delete_player_tile(game_id, player_id, models.Tile(x, y))
    # this should all happen atomically, but as a stopgap make sure this happens last
    persistance.update_game_state(game_id, state.to_dict())

    return 'OK'
Esempio n. 4
0
def add_brand():
    form = Add_Brand()
    # form submitted to the server by a user
    if form.validate_on_submit():
        new_brand = models.Brand()
        # set brand name and description from form data
        new_brand.name = form.name.data
        new_brand.desc = form.desc.data
        if form.photo.data:
            photo_file = save_photo(form.photo.data)
            new_brand.photo = photo_file
        new_brand.deletable = True
        # flash message to let user know that the brand has been created
        flash('{} brand successfully created.'.format(new_brand.name))
        db.session.add(new_brand)
        db.session.commit()
        return redirect(url_for('brand', id=new_brand.id))
    # request to see the page
    return render_template('add_edit_brand.html',
                           form=form,
                           title="Add Brand",
                           legend="Add")
Esempio n. 5
0
def buy_stock():
    max_purchase_amount = int(os.environ['MAX_STOCK_PURCHASE_AMOUNT'])

    game_id = request.json['game_id']
    id_token = request.json['id_token']
    purchase_order = request.json['purchase_order']

    user_id = firebase_admin.auth.verify_id_token(id_token)['uid']
    state = persistance.get_game_state(game_id)

    if state.current_action_player != user_id:
        raise models.RuleViolation(
            "Stop trying to take other player's turns! You cheat!")

    if state.current_action_type != models.ActionType.BUY_STOCK:
        raise models.RuleViolation(
            'It is your turn, but it is not time to buy stock!')

    if not state.is_started:
        raise models.RuleViolation('Cannot take turn until game has begun!')

    total_stock_purchased = 0

    for raw_brand, raw_amount in purchase_order.items():
        parsed_amount = int(raw_amount)
        total_stock_purchased += parsed_amount
        brand = models.Brand(raw_brand)
        stock.buy_stock(state, user_id, brand, parsed_amount)

    if total_stock_purchased > max_purchase_amount:
        raise models.RuleViolation('Too many stock in purchase order!')

    turn_transitioned_state = turns.transition_from_buy(state, game_id)

    persistance.update_game_state(game_id, turn_transitioned_state.to_dict())

    return 'OK'
Esempio n. 6
0
def process_entry(entry, website_pk):
    """Process entry data.

    params:
        - entry: parsed dataset line
        - website_pk: website Mongo <ObjectId> reference

    The function will process the entry data based on the "page type: product_detail or product_listing".

    A boolean value will be returned to mark the process ended successful or failed.

    The process can also raise exception for unrecoverable failures.

    """
    if not entry['extract_ok']:
        return False

    extracted_data = entry['extracted_data']

    if entry['page_type'] == 'product_detail':
        item = extracted_data['item']
        brand = item['brand_name']
        if brand:
            try:
                brand = models.Brand(brand=brand).ensure()
            except:
                raise

        props = {
            "brand": brand,
            "crawled_at": parse_datetime(entry['crawled_at']),
            "discount_percentage": item['discount_percentage'],
            "name": item['article_name'],
            "on_sale": item['on_sale'],
            "price": item['sale_price'],
            "product_type": item['article_type'],
            "properties": item['extra_props'],
            "sku": item['sku'],
            "url": entry['page_url'],
            "website": website_pk,
            # path=None,
            # listings=[],
        }
        # print(props)
        ## Clean None values
        props = utils.removeNoneValuesFromDict(props)
        # print(props)
        p = models.Product(**props)
        try:
            # p.save()
            p.ensure()
        except models.DuplicateKeyError as error:
            logger.debug("Item already exists: %s - %s - %s [%s]" % (
                props.get("sku"),
                props.get("name"),
                props.get("url"),
                props.get("crawled_at"),
            ))
            return False
        except Exception as e:
            writeErrorFile('detail-%s' % (website_pk), entry['body'])
            raise e

    elif entry['page_type'] == 'product_listing':
        status = True

        number_of_items = extracted_data['number_of_items']
        # number_of_items = len(extracted_data['items'])

        props = {
            "page_number": entry['page_number'],
            "page_listing_size": number_of_items,
            "category": entry['product_category'],
            "sorted_by": entry['ordering'],
            "url": entry['page_url'],
            "crawled_at": parse_datetime(entry['crawled_at']),
            "website": website_pk,
        }

        props = utils.removeNoneValuesFromDict(props)

        pl = models.ProductListingPage(**props)
        try:
            pl.ensure()
            pl_pk = pl.pk
        except models.DuplicateKeyError as error:
            pl = models.ProductListingPage.objects.get(
                dict([(k, v) for k, v in props.items()
                      if k in ('url', 'crawled_at')]))
            pl_pk = pl.pk
        except:
            raise

        # -------------------------------------------------------------------------
        # Assign Items
        # -------------------------------------------------------------------------
        total_items = 0
        not_found_products = 0
        listing_added_total = 0
        insufficent_data = 0
        for i, item in enumerate(extracted_data['items']):
            # -------------------------------------------------------------------------
            # Find Item first
            # -------------------------------------------------------------------------
            detail_page_url = item.get('detail_page_url')
            if not detail_page_url:
                continue

            total_items = total_items + 1
            # -------------------------------------------------------------------------
            # Find matching Product based on detail_page_url
            # -------------------------------------------------------------------------
            try:
                product = models.Product.objects.get({'path': detail_page_url})
            except models.Product.DoesNotExist:
                logger.debug("No Product match found for %s" %
                             (detail_page_url))
                not_found_products = not_found_products + 1
                continue

            try:
                li_props = {
                    "position": i + 1,
                    "price": item['sale_price'],
                    "on_sale": item['on_sale'],
                    "discount_percentage": item['discount_percentage'],
                    "listing_props": item['listing_props'],
                    "listing": pl_pk,
                }
                # -------------------------------------------------------------------------
                # Create Listing Item
                # -------------------------------------------------------------------------
                li = models.ProductListingItem(**li_props)
            except Exception as e:
                writeErrorFile('listing-%s' % (pl_pk), entry['body'])
                logger.error(e)
                insufficent_data = insufficent_data + 1
                continue

            if any([True for l in product.listings if l.listing._id == pl_pk]):
                # print("Listing already added to product")
                listing_added_total = listing_added_total + 1
                continue

            # -------------------------------------------------------------------------
            # Add New Listing ot Product listings
            # -------------------------------------------------------------------------
            product.listings.append(li)

            try:
                product.save()
                listing_added_total = listing_added_total + 1
            except Exception as e:
                logger.error(e)

                writeErrorFile('listing-%s-%s' % (pl_pk, i), entry['body'])

        # -------------------------------------------------------------------------
        # Debug stats
        # -------------------------------------------------------------------------
        logger.debug("""%s: stats (ok:%s/missing:%s/nodata:%s/total:%s)""" % (
            utils.get_url_path(entry['page_url']),
            listing_added_total,
            not_found_products,
            insufficent_data,
            total_items,
        ))

        return True
    else:
        logger.error("Unknown page_type")
        return False

    return True