async def betting_start_command(self, ctx: commands.Context, *argv): if len(argv) != 1 or not argv[0].isdigit(): await ctx.channel.send('參數錯誤: 請使用`!betitng start 賭局id`') return game_id = int(argv[0]) game: GamblingGame = GamblingUtil.get_game(game_id) if game == None: await ctx.channel.send( '參數錯誤: 無法找到id 為:{} 的賭盤。請使用`!betitng list`查詢。'.format(game_id)) return if game.creater_id != ctx.author.id: await ctx.channel.send('權限錯誤: 這個賭盤不是你創建的!') return if game.guild_id != ctx.guild.id: await ctx.channel.send('權限錯誤: 這個賭盤不是在這裡創建的,創建的伺服為: {}'.format( self.bot.get_guild(game.guild_id).name)) return if game.status != Util.GamblingStatus.init: await ctx.channel.send('權限錯誤: 這個賭盤的狀態為: {},無法開始。'.format( Util.GamblingStatus(game.status).name)) return embed = GamblingEmbed.get_betting_embed(game) msg = await ctx.channel.send(embed=embed) await msg.pin() GamblingUtil.update_game_status(game, Util.GamblingStatus.ready, ctx.channel.id, msg.id)
def test_addGamePoolAmount(self): original: GamblingGame = GamblingUtil.create_game( 123, "new_game", 5, ["hello", "hi"], 123) GamblingUtil.add_game_pool_amount(original, 300) original = GamblingUtil.get_game(original.id) assert original.pool == 300
def test_updateGameStatus(self): game: GamblingGame = GamblingUtil.create_game(123, "new_game", 5, ["hello", "hi"], 123) GamblingUtil.update_game_status(game, Util.GamblingStatus.ready, 123, 456) result_game = GamblingUtil.get_game(game.id) assert game == result_game
def test_getBets(self): original: GamblingGame = GamblingUtil.create_game( 123, "new_game", 5, ["hello", "hi"], 123) GamblingUtil.update_game_status(original, Util.GamblingStatus.ready, 123, 456) assert GamblingUtil.add_bet(original, 123, 10, 1) bets = GamblingUtil.get_bets(original) assert len(bets) == 1
async def betting_exchange_command(self, ctx: commands.Context, *argv): exchange_rate = GamblingUtil.get_token_rate() if len(argv) != 1: await ctx.channel.send('參數錯誤: 請使用`!betitng exchange 🍗數量`') return if not argv[0].isdigit(): await ctx.channel.send('參數錯誤: 🍗數量必須為數字') return desired_token = int(argv[0]) if desired_token < 1: await ctx.channel.send('參數錯誤: 🍗數量不能低於1') return member: Member = self.database.get_member(ctx.author.id) if member == None: member = self.database.add_member(ctx.author.id) required_coin = exchange_rate * desired_token if member.coin < required_coin: await ctx.channel.send( f'參數錯誤: 您目前手持硬幣數量不夠 目前 {exchange_rate}硬幣兌換1🍗\n目前您擁有硬幣{member.coin}, 小於交換所需量 {required_coin}' ) return self.database.add_coin(member.member_id, -1 * required_coin) self.database.add_token(member.member_id, desired_token) member: Member = self.database.get_member(ctx.author.id) msg = "```兌換完成! 兌換明細如下:\n" msg += f"本次兌換匯率: {exchange_rate}\n" msg += f"本次兌換消耗硬幣: {required_coin}\n" msg += f"本次兌換獲得🍗: {desired_token}根\n" msg += f"目前持有硬幣: {member.coin}\n" msg += f"目前持有🍗: {member.token}根\n" msg += "```" await ctx.channel.send(msg)
async def refresh_betting_message(self): for guild in self.bot.guilds: games = GamblingUtil.get_active_games(guild.id) game: GamblingGame for game in games: channel = game.guild_id massage = await channel.fetch_message(game.message_id) embed = self.get_betting_embed(game) await massage.edit(embed=embed)
def test_gameCreation(self): game: GamblingGame = GamblingUtil.create_game(123, "new_game", 5, ["hello", "hi"], 123) assert game.guild_id == 123 assert game.name == "new_game" assert game.base == 5 assert game.pool == 0 assert game.item_list == ["hello", "hi"] assert game.creater_id == 123 assert game.status == Util.GamblingStatus.init
def test_getActiveGameInChannel(self): original: GamblingGame = GamblingUtil.create_game( 123, "new_game", 5, ["hello", "hi"], 123) GamblingUtil.update_game_status(original, Util.GamblingStatus.ready, 123, 456) game = GamblingUtil.get_active_game_in_channel(123, 456) assert len(game) == 0 game = GamblingUtil.get_active_game_in_channel(123, 123) assert game == [original] another = GamblingUtil.create_game(123, "new_game", 5, ["hello", "hi"], 123) GamblingUtil.update_game_status(another, Util.GamblingStatus.ready, 123, 456) game = GamblingUtil.get_active_game_in_channel(123, 123) assert len(game) == 2
def test_getActiveGameList(self): game1: GamblingGame = GamblingUtil.create_game(123, "new_game1", 5, ["hello", "hi"], 123) game2: GamblingGame = GamblingUtil.create_game(123, "new_game2", 5, ["hello", "hi"], 123) gameList = GamblingUtil.get_active_games(123) assert len(gameList) == 0 GamblingUtil.update_game_status(game1, Util.GamblingStatus.ready, 123, 321) gameList = GamblingUtil.get_active_games(123) assert len(gameList) == 1 GamblingUtil.update_game_status(game2, Util.GamblingStatus.ready, 123, 321) gameList = GamblingUtil.get_active_games(123) assert len(gameList) == 2 assert gameList == [game1, game2]
async def exchange_token(self, ctx: commands.Command, need_token: int): member = MemberUtil.get_or_add_member(ctx.author.id) if member is None: await ctx.send("沒硬幣還想換雞腿,趕快去店外雜談區聊天賺硬幣!") else: coinspertoken = GamblingUtil.get_token_rate() spend = need_token * coinspertoken if member.coin > spend: MemberUtil.add_coin(member_id=member.id, amount=-spend) MemberUtil.add_token(member_id=member.id, amount=need_token) await ctx.send(f"成功兌換{need_token}個雞腿,目前剩下{member.coin}個硬幣") else: msg = f"兌換失敗!不足{spend - member.coin}個硬幣\n" msg += f"目前匯率為 一隻雞腿{coinspertoken}個硬幣" await ctx.send(msg)
async def betting_lock_command(self, ctx: commands.Context, *argv): send_target = None if ctx.channel == None: send_target = ctx.author else: send_target = ctx.channel if len(argv) != 1 or not argv[0].isdigit(): await send_target.send('參數錯誤: `!betting lock 賭盤id`') return game_id = int(argv[0]) game: GamblingGame = GamblingUtil.get_game(game_id) if game == None: await send_target.send('參數錯誤: 沒有ID為{}的賭盤'.format(game_id)) return if game.creater_id != ctx.author.id: await send_target.send('權限錯誤: 你不是創建這個賭盤的人') return if game.status != Util.GamblingStatus.ready: await send_target.send('權限錯誤: 這個賭盤的狀態為:{}'.format(game.status.name) ) return GamblingUtil.update_game_status(game, Util.GamblingStatus.wait) await send_target.send('更新賭盤狀態為: {}'.format( Util.GamblingStatus.wait.name))
def test_tokenRateCorrect(self): self.database.add_member(123) # token: 100, coin: 0, rate: NAN assert GamblingUtil.DEFAULT_RATE == GamblingUtil.get_token_rate() self.database.add_coin(123, 10) # token: 100, coin: 10, rate: 0.1 assert GamblingUtil.DEFAULT_RATE == GamblingUtil.get_token_rate() self.database.add_coin(123, 90) # token: 100, coin: 100, rate: 1 assert GamblingUtil.get_token_rate() == GamblingUtil.get_token_rate() self.database.add_coin(123, 500) # token: 100, coin: 600, rate: 6 assert GamblingUtil.get_token_rate() == 6 self.database.add_member(321) # token: 200, coin: 600, rate: 3 assert GamblingUtil.get_token_rate() == GamblingUtil.get_token_rate() self.database.add_coin(321, 600) # token: 200, coin: 1200, rate: 6 assert GamblingUtil.get_token_rate() == 6
async def betting_list_command(self, ctx: commands.Context, *argv): guild = ctx.guild game_list = GamblingUtil.get_active_games(guild.id) if len(game_list) == 0: return embed = Embed() embed.title = '賭盤列表' game: GamblingGame for game in game_list: channel = ctx.channel embed.add_field( name=game.name, value='每注: {}, 獎金池: {}, 狀態: {}\n頻道: <#{}>, 伺服器:{}'.format( game.base, game.pool, game.status.name, channel.id, guild.name), inline=False) await ctx.channel.send(embed=embed)
def test_addBetSuccess(self): original: GamblingGame = GamblingUtil.create_game( 123, "new_game", 5, ["hello", "hi"], 123) GamblingUtil.update_game_status(original, Util.GamblingStatus.ready, 123, 456) assert GamblingUtil.add_bet(original, 123, 10, 1) original: GamblingGame = GamblingUtil.get_game(original.id) assert original.pool == 10 assert GamblingUtil.add_bet(original, 123, 10, 1) assert original.pool == 20
async def betting_exchange_rate_command(self, ctx: commands.Context, *argv): exchange_rate = GamblingUtil.get_token_rate() await ctx.channel.send(f"目前🍗兌換率為 {exchange_rate} 硬幣:1隻🍗")
async def betting_end_command(self, ctx: commands.Context, *argv): if len(argv) != 2: await ctx.channel.send('參數錯誤: `!betting lock 勝利編號 賭盤id`') return if not argv[1].isdigit() or not argv[0].isdigit(): await ctx.channel.send('參數錯誤: `!betting lock 勝利編號 賭盤id`') return game_id = int(argv[1]) option_index = int(argv[0]) game: GamblingGame = GamblingUtil.get_game(int(argv[1])) if not game: await ctx.channel.send('參數錯誤: 找不到id 為{}的賭盤'.format(game_id)) return if game.creater_id != ctx.author.id: await ctx.channel.send('權限錯誤: 你不是創建這個賭盤的人') return if game.status != Util.GamblingStatus.wait: await ctx.channel.send('權限錯誤: 這個賭盤的狀態為:{}'.format(game.status.name) ) return betting_items = json.loads(game.item_list) if option_index < 0 or option_index > len(betting_items): await ctx.channel.send(f'參數錯誤: `勝利編號 {option_index} 為無效編號`') return #[第一項總注,第n項總注...,總項總注] member_charge_sum = [0] * len(betting_items) member_bet = {} winning_item = betting_items[option_index] bets = GamblingUtil.get_bets(game) bet: GamblingBet for bet in bets: member_charge_sum[bet.item_index] += bet.charge member_bet[bet.member_id] = member_bet.get(bet.member_id, 0) + bet.charge for member_id in member_bet: member: Member = self.database.get_member(member_id) if member == None: continue token_spent = 0 if member_bet[member_id].get(winning_item, 0) != 0: token_spent = member_bet[member_id][winning_item] coin_won = 0 winning_sum = member_charge_sum[option_index] if winning_sum != 0: coin_won = int(token_spent / winning_sum * game.base * game.pool) user = await self.bot.fetch_user(member_id) if user == None: await ctx.channel.send('無法找到該id的用戶: {},跳過!') continue self.database.add_token(member_id, coin_won) member = self.database.get_member(member_id) await user.send('恭喜獲得{}點🍗, ...結餘:{}'.format(coin_won, member.coin)) GamblingUtil.update_game_status(game, Util.GamblingStatus.end, winning_index=option_index) channel = await self.bot.fetch_channel(game.channel_id) if channel != None: msg = await channel.fetch_message(game.message_id) await msg.edit(embed=GamblingEmbed.get_betting_embed( self.bot, self.database, game)) if msg.pinned: await msg.unpin() await ctx.channel.send('結算成功')
async def betting_create_command(self, ctx: commands.Context, *argv): descript_base = '請<@{}>跟著指示完成創建\n'.format(ctx.author.id) embed = Embed() embed.title = '創建賭盤: 創建者<@!{}>'.format(ctx.author.id) embed.description = descript_base embed.add_field(name='設定賭盤名稱', value='請直接回覆賭局名稱', inline=False) embed.add_field(name='設定賭注單位', value='請先回覆賭局名稱', inline=False) main_message = await ctx.channel.send(embed=embed) def reaction_check(reaction, user): if user == ctx.author and reaction.message == main_message: return str(reaction.emoji) == '⭕' or '❌' else: return False betting_count = 0 bet_item_offset = 2 if not await GamblingUtil.create_loop(embed, main_message, ctx, type(str()), '賭盤名稱', 0): return embed.set_field_at(1, name='設定賭注單位', value='請直接回覆每注單位', inline=False) await main_message.edit(embed=embed) if not await GamblingUtil.create_loop(embed, main_message, ctx, type(int()), '賭注單位', 1): return add_flag = True while add_flag or betting_count < 2: embed.add_field(name='設定賭注項目-第{}項'.format(betting_count), value='請先回覆賭注項目-第{}項'.format(betting_count), inline=False) await main_message.edit(embed=embed) if not await GamblingUtil.create_loop( embed, main_message, ctx, type( str()), '賭品-第{}項'.format(betting_count), betting_count + bet_item_offset): return if betting_count > 0: embed.add_field(name='完成設定?', value='完成設定⭕️繼續設定❌', inline=False) await main_message.edit(embed=embed) await main_message.add_reaction('⭕') await main_message.add_reaction('❌') try: get_reaction = await self.bot.wait_for( 'reaction_add', timeout=30.0, check=reaction_check) except asyncio.TimeoutError: embed.set_field_at(betting_count + bet_item_offset + 1, name='完成設定?-等待反應超時', value='error') await main_message.clear_reactions() await main_message.edit(embed=embed) return False else: if get_reaction[0].emoji == '⭕': tem_list = [] for i in embed.fields[2:-1]: tem_list.append(i.value) game: GamblingGame = GamblingUtil.create_game( ctx.guild.id, embed.fields[0].value, int(embed.fields[1].value), tem_list, ctx.author.id) embed.set_field_at( betting_count + bet_item_offset + 1, name='完成設定!!!', value= '設定完成!!!\n請<@{}> 到想要的頻道輸入\n`!betting start {}`\n開啟賭局!' .format(ctx.author.id, game.id), inline=False) add_flag = False else: embed.remove_field(betting_count + bet_item_offset + 1) await main_message.clear_reactions() await main_message.edit(embed=embed) betting_count += 1
async def betting_bte_command(self, ctx: commands.Context, *argv): guild = ctx.guild channel = ctx.channel ## if channel == None: await ctx.author.send('請到開啟賭牌的頻道下注!!') return if guild == None: await ctx.author.send('無法處理的伺服器!') return if not self.database.has_channel(guild.id, channel.id, Util.ChannelType.AUTO_DELETE): await ctx.message.delete() flag = False if len(argv) < 2: flag = True elif not argv[0].isdigit() or not argv[1].isdigit(): flag = True if flag: await ctx.author.send('參數錯誤: `!bet 加注數量 下注編號 [賭局ID]`') return bet_amount = int(argv[0]) # 加注數量 choice_id = int(argv[1]) # 下注編號 _bettings = GamblingUtil.get_active_game_in_channel( guild.id, ctx.channel.id) ready_games = [] game: GamblingGame for game in _bettings: if game.status == Util.GamblingStatus.ready: ready_games.append(game) if len(ready_games) == 0: await ctx.author.send('參數錯誤: 這個頻道沒有開啟的賭局!') return if len(ready_games) > 1: if len(argv) <= 2: tem_betting_list = '' for game in ready_games: tem_betting_list += '\n賭局名:{}, id: {}'.format( game.name, game.id) await ctx.author.send('這個頻道有複數賭局開啟中\n請指定賭局`!bet 下注數 賭局ID`' + tem_betting_list) return if not argv[2].isdigit(): await ctx.author.send('參數錯誤: 賭局ID必須是數字') betting_id = int(argv[2]) flag = True for game in ready_games: if betting_id == game.id: flag = False break if flag: ctx.author.send('參數錯誤: 這個<#{}>沒有ID為: {}的賭局'.format( ctx.channel.id, betting_id)) ready_games = game elif len(ready_games) == 1: ready_games = ready_games[0] else: await ctx.channel.send('未預期的錯誤: <@!326752816238428164>快修阿!') return game: GamblingGame = ready_games if game.status != Util.GamblingStatus.ready: await ctx.author.send('權限錯誤: 現在的賭局狀態為: {}不能下注'.format( Util.GamblingStatus(game.status).name)) return if bet_amount < 1: await ctx.author.send('參數錯誤: 下注🍗不能為此數: {}'.format(bet_amount)) return # 所有可下注選項 betting_item_list = json.load(game.item_list) if not choice_id < len(betting_item_list): await ctx.author.send('參數錯誤: 不存在編號: {}'.format(choice_id)) return member = self.database.get_member(ctx.author.id) if member == None: member = self.database.add_member(ctx.author.id) require_amount = bet_amount * game.base if member.coin < require_amount: await ctx.author.send('道德錯誤: 你的🍗不夠啦! ...剩餘{},下注{}'.format( member.coin, require_amount)) return self.database.add_coin(member, -1 * require_amount) GamblingUtil.add_bet(game=game, user_id=member.member_id, amount=require_amount, item_index=choice_id) await ctx.author.send('你成功對{} 下注了{}點🍗。...餘額為: {}。'.format( betting_item_list[choice_id], require_amount, member.coin))
def get_betting_embed(bot: commands.Bot, database: KfpDb, game: GamblingGame): guild: Guild = bot.get_guild(game.guild_id) if guild == None: return Embed(title='錯誤', description='無法處理的伺服id: {}'.format(game.guild_id)) embed = Embed() embed.colour = Color(randint(0, 0xffffff)) embed.title = game.name _description = '' if game.status == Util.GamblingStatus.ready: _description += '請各位輸入`!bet 下注數 下注編號 {}` 開始下注!。\n'.format(game.id) if game.status == Util.GamblingStatus.wait: _description += '停止下注!' _description += '#目前所有選項的期望賠率都是一樣的,有人有想法可以聯絡<@326752816238428164>\n' if game.status == Util.GamblingStatus.ready: _description += '<@{}>可以輸入`!betting lock {}`來停止下注。'.format( game.creater_id, game.id) if game.status == Util.GamblingStatus.wait: _description += '<@{}>可以輸入`!betting end 勝利編號 {}`來結算賭盤。'.format( game.creater_id, game.id) embed.description = _description betting_items = json.loads(game.item_list) #[第一項總注,第n項總注...,總項總注] member_charge_sum = [0] * len(betting_items) member_bet = {} bets = GamblingUtil.get_bets(game) bet: GamblingBet for bet in bets: member_charge_sum[bet.item_index] += bet.charge member_bet[bet.member_id] = member_bet.get(bet.member_id, 0) + bet.charge for i, target_name in enumerate(betting_items): if member_charge_sum[i] > 0: embed.add_field(name='編號: {} #'.format(i) + target_name, value='賠率: {:.3f}'.format( float((game.pool / member_charge_sum[i]))), inline=False) else: embed.add_field(name='編號: {} #'.format(i) + target_name, value='賠率: ?', inline=False) embed.add_field(name='賭局id', value=str(game.id)) embed.add_field(name='獎金池', value=str(game.pool * game.base)) embed.add_field(name='每注單位', value=str('{}🍗'.format(game.base))) embed.add_field(name='刷新速度', value='5s') embed.add_field(name='狀態', value=Util.GamblingStatus(game.status).name) embed.add_field(name='====我是分隔線====', value='#', inline=False) inline_flasg = False for member_id in member_bet: member = guild.get_member(int(member_id)) if member == None: continue value = '' for bet_item in member_bet[member_id]: if game.status == Util.GamblingStatus.end.value: if bet_item == betting_items[game.winning_index]: value += '{}:得到{}點🍗\n'.format( bet_item, member_bet[member_id][bet_item] / member_charge_sum[game.winning_index] * member_charge_sum[-1] * game.base) else: value += '{}:輸掉{}點🍗拉\n'.format( bet_item, member_bet[member_id][bet_item] * game.base) else: value += '{}:{}注\n'.format(bet_item, member_bet[member_id][bet_item]) embed.add_field(name=member.display_name, value=value[:-1], inline=inline_flasg) if not inline_flasg: inline_flasg = True return embed
def test_tokenRateDefault(self): assert GamblingUtil.DEFAULT_RATE == GamblingUtil.get_token_rate()
def test_addBetFailedNotReady(self): original: GamblingGame = GamblingUtil.create_game( 123, "new_game", 5, ["hello", "hi"], 123) assert not GamblingUtil.add_bet(original, 123, 2, 1)