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())
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})
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)