Ejemplo n.º 1
0
def act(actor, target, action, narration):
    acting_on_self = target.key().name() == actor.key().name()
    a = Thespian(actor)
    if acting_on_self:
        t = a
    else:
        t = Thespian(target)
    action_types[action].run_script(a, t)
    now = datetime.now()
    db.run_in_transaction(a.run_effects_at, now)
    if not acting_on_self:
        db.run_in_transaction(t.run_effects_at, now)
    Action.create(actor, target, now, action, narration, a.effect_summary(), t.effect_summary())
Ejemplo n.º 2
0
def action(table_name):
    table = Table.query.filter_by(name=table_name).first()
    hand = table.active_hand
    if not hand:
        # TODO - Handle no current hand state
        return jsonify({"success": False, "msg": "No current hand"})

    data = request.get_json()
    user = User.query.get(get_jwt_identity())
    if not user:
        return jsonify({"success": False, "msg": "No user found"}), 401

    player = user.active_player
    if EMULATOR_ENABLED:
        player = hand.next_to_act
    if not player:
        return jsonify({"success": False, "msg": "No player found"})
    elif player not in table.active_players:
        return jsonify({
            "success": False,
            "msg": "Can't act while sitting at a different table"
        })
    elif player not in table.ready_players:
        return jsonify({
            "success": False,
            "msg": "Can't act while sitting out"
        })

    if player != hand.next_to_act:
        # TODO - Handle action by wrong user state
        return jsonify({"success": False, "msg": "Player acting out of turn"})

    try:
        action_type = ActionType[data.get("actionType")]
    except KeyError:
        return jsonify({"success": False, "msg": "Invalid action type"})

    current_bet = data.get("betAmt", 0)
    prev_bet = hand.active_betting_round.sum_player_bets(player)
    total_bet = prev_bet + current_bet

    if hand.antes_owed:
        if action_type != ActionType.BLIND:  # TODO - Create ANTE type?
            return jsonify({"success": False, "msg": "Expected ante"})
        elif current_bet != hand.stakes.ante and current_bet != player.balance:
            return jsonify({"success": False, "msg": "Incorrect ante amount"})
    elif hand.blinds_owed:
        if action_type != ActionType.BLIND:
            return jsonify({"success": False, "msg": "Expected blind"})

        expected_blind = hand.stakes.small if hand.active_betting_round.sum == 0 else hand.stakes.big
        if current_bet != expected_blind and current_bet != player.balance:
            # TODO - Solve for all-in on big blind
            #  This should allow players to bet amounts other than SB or BB
            #  but it will fail to set the expected bet to the BB if the player
            #  who should have paid the full BB went all-in for less.
            return jsonify({"success": False, "msg": "Incorrect blind amount"})
    else:
        if not hand.dealt:
            return jsonify({
                "success": False,
                "msg": "Can't take action before hand dealt"
            })
        if action_type == ActionType.BLIND:
            return jsonify({
                "success": False,
                "msg": "Cannot post blind after hand dealt"
            })
        elif action_type == ActionType.CHECK:
            current_bet = 0
            if hand.active_betting_round.bet and not prev_bet == hand.active_betting_round.bet:
                return jsonify({
                    "success": False,
                    "msg": "Cannot check if bet > 0"
                })
        elif action_type == ActionType.BET:
            if current_bet > player.balance:
                return jsonify({"success": False, "msg": "Bet > balance"})
            elif hand.active_betting_round.bet and total_bet < hand.active_betting_round.bet and total_bet != player.balance:
                return jsonify({"success": False, "msg": "Bet < current bet"})
            elif total_bet < determine_min_raise(
                    hand.stakes.big, hand.active_betting_round.bet, prev_bet,
                    hand.active_betting_round.raise_amt, player.balance
            ) and total_bet != hand.active_betting_round.bet:
                return jsonify({"success": False, "msg": "Bet < minimum bet"})

    prev_num_rounds = len(hand.betting_rounds)

    try:
        act = Action.create(holding_id=player.active_holding.id,
                            type=data.get("actionType"))
        resolution = hand.resolve_action(act, current_bet, total_bet)
    except IntegrityError:
        return jsonify({"success": False, "msg": "Database error"})
    except Exception as e:
        return jsonify({
            "success": False,
            "msg": "Unknown error",
            "error": str(e)
        })

    # TODO - This is such a hack. Fix it.
    # Number of cards showing at each round num
    try:
        num_up_cards = [0, 3, 4, 5]
        num_up_cards_round = num_up_cards[hand.active_betting_round.round_num]
        up_cards = [card.name
                    for card in hand.board.cards][:num_up_cards_round]
    except AttributeError:
        # Hand has ended, so hand.active_betting_round is None
        up_cards = []

    sse_data = {
        "id":
        act.id,
        "handId":
        hand.id,
        "playerId":
        act.player.id,
        "playerBalance":
        act.player.balance,
        "actionType":
        act.type,
        "pot":
        hand.active_pot.amount,
        "next":
        hand.next_to_act.id,
        "bet":
        current_bet,
        "roundBet":
        hand.active_betting_round.bet if hand.active_betting_round else 0,
        "roundRaise":
        hand.active_betting_round.raise_amt
        if hand.active_betting_round else 0,
        "playerRoundBet":
        total_bet,  # Sum of player's bets for this betting round (THIS WILL FAIL ON ALL-IN SIDE POTS)
        "roundComplete":
        resolution.get("round_complete", False)
    }

    if resolution.get("new_round"):
        sse_data["newRound"] = True
        sse_data["board"] = up_cards

    if resolution.get("hand_complete"):
        sse_data["handComplete"] = True
        sse_data["winners"] = [{
            "id": pot.winner.id,
            "amount": pot.amount,
            "balance": pot.winner.balance
        } for pot in hand.pots_paid]

        # Include holding data for showdown if necessary
        if len(hand.live_holdings) > 1:
            sse_data["showdown"] = [{
                "playerId":
                holding.player_id,
                "holdings": [card.name for card in holding.cards],
            } for holding in hand.live_holdings]

    sse.publish(sse_data, type="action", channel=table.name)

    return jsonify({"success": True})
Ejemplo n.º 3
0
def parse_actions_of_brand(brand_id, brand_link):
    """
    Получение и запись списка акций бренда в таблицу actions
    :param brand_id: id бренда в таблице brands
    :param brand_link: ссылка на акции бренда
    :return:
    """
    logging.info(f'Парсинг акций бренда {brand_link}')
    soup_page = get_soup_page_by_link(brand_link)

    # определяем количество страниц с акциями
    ul_paging = soup_page.find('ul', class_='paging')
    if ul_paging:
        page_count = ul_paging.find_all('li')[-2]
        page_count = re.search('<li>.+?</li>', str(page_count))
        page_count = re.sub('<li><a.+?>', '', str(page_count.group()))
        page_count = int(re.sub('</a></li>', '', page_count))
    else:
        page_count = 1

    # проходимся по каждой странице с акциями
    page_start = 1
    for page_number in range(page_start, page_count + 1):
        soup_page = get_soup_page_by_link(brand_link + '?page=' +
                                          str(page_number))
        stuff = soup_page.find('div', class_='post-container')

        # проходимся по каждому блоку с акцией
        for item in stuff:
            title = re.search('a href=".+?\.html">.+?</a>', str(item))
            if not title:
                continue

            # проверяем, что дата акции позднее 2019 года
            dates = re.search('<span class="time-of">.+?</span>', str(item))
            dates = re.sub('<span class="time-of">', '', str(dates.group()))
            dates = re.sub('</span>', '', dates)
            if int(dates.split(' ')[-1]) < 2019:
                continue

            # заходим на страницу акции и парсим её
            action_link = 'https://proactions.ru' + item.find(
                'a', class_='button-01')['href']
            soup_action_page = get_soup_page_by_link(action_link)
            logging.info(f'Парсинг страницы акции {action_link}')
            result = get_action_page(soup_action_page)

            try:
                action = Action.get((Action.title == result['title']) & (
                    Action.description == result['description'])
                                    & (Action.benefits == result['benefits'])
                                    & (Action.date == result['date']))
            except Action.DoesNotExist:
                action = Action.create(title=result['title'],
                                       link=action_link,
                                       description=result['description'],
                                       benefits=result['benefits'],
                                       date=result['date'],
                                       img=result['img'],
                                       url_official=result['url_official'],
                                       participation=result['participation'],
                                       timing=result['timing'],
                                       other_text=result['other_text'],
                                       organizers=result['organizers'],
                                       operators=result['operators'],
                                       rules_link=result['rules_link'],
                                       tags=result['tags'],
                                       comments_num=int(
                                           result['comments_num']),
                                       view_num=int(result['view_num']),
                                       rating=result['rating'])
                logging.info(f'Запись акции, action.id = {action}')

                if action.comments_num > 0:
                    comments = parse_comments(action_link)
                    for comment in comments:
                        Comment.create(action_id=action.id,
                                       username=comment['username'],
                                       login=comment['login'],
                                       date=comment['date'],
                                       link=comment['link'],
                                       rating=comment['rating'],
                                       text=comment['text'],
                                       img=comment['img'])
                    logging.info(f'Запись {len(comments)} комментарий')

            #print('ACTION: ', action)
            try:
                BrandAction.get((BrandAction.brand_id == brand_id)
                                & (BrandAction.action_id == action.id))
            except BrandAction.DoesNotExist:
                BrandAction.create(brand_id=brand_id, action_id=action.id)