async def __run_buy(self): user = User.get_by_discord_id(self.message.author.id) order_dict = { 'operation': "buy", 'season': app.config['SEASON'], 'week': current_round() } if user is None: await self.reply([ (f"User {self.message.author.mention} does not exist." "Use !newuser to create user first.") ]) return if len(self.args) not in [2, 3]: await self.reply([ "Incorrect number of arguments!!!", self.__class__.buy_help() ]) return try: stock = Stock.find_by_code(self.args[1]) except MultipleResultsFound as exc: await self.reply([ f"Stock code **{self.args[1]}** is not unique!!!", ]) return if not stock: await self.reply([f"Stock code **{self.args[1]}** not found!"]) return if len(self.args) == 3: if not represents_int(self.args[2]) or (represents_int( self.args[2]) and not int(self.args[2]) > 0): await self.reply( [f"**{self.args[2]}** must be whole positive number!"]) return else: if int(self.args[2]) <= app.config['MAX_SHARE_UNITS']: order_dict['buy_shares'] = self.args[2] else: order_dict['buy_funds'] = self.args[2] round_n = app.config['ROUNDS_COLLECT'][-1] match = MatchService.get_game(stock.name, round_n=round_n) if match and (match.homeTeamName.strip() in app.config['ADMIN_TEAMS'] or \ match.awayTeamName.strip() in app.config['ADMIN_TEAMS']): await self.reply( [f"You cannot buy stocks of a team going into BYE week!!!"]) return order = OrderService.create(user, stock, **order_dict) await self.reply([ f"Order **{order.id}** placed succesfully.", " ", f"**{order.desc()}**" ]) return
async def __run_gain(self): if len(self.args) not in [2]: await self.reply([ "Incorrect number of arguments!!!", self.__class__.gain_help() ]) return if not represents_int(self.args[1]) or int(self.args[1]) > 50 or int( self.args[1]) <= 0: await self.reply([ f"**{self.args[1]}** must be whole positive number and be less or equal 50!" ]) return sorted_users = UserService.order_by_current_gain(int(self.args[1])) msg = ["```asciidoc"] msg.append(" = Place = | = Gain = | = Investor =") for i, (position, value, user) in enumerate(sorted_users): msg.append("{:3d}. |{:9.2f} | {:s}".format( position, value, user.short_name())) msg.append("```") await self.reply(msg) return
def cracker_coach_cards(coach): history = request.args.get('history') if history and represents_int(history): cards = CrackerService.history_cards(coach,int(history)) else: cards = CrackerService.active_cards(coach) result = cracker_cards_schema.dump(cards) return jsonify(result.data)
async def __run_cancel(self): user = User.get_by_discord_id(self.message.author.id) if user is None: await self.reply([ (f"User {self.message.author.mention} does not exist." "Use !newuser to create user first.") ]) return if len(self.args) not in [2]: await self.reply([ "Incorrect number of arguments!!!", self.__class__.cancel_help() ]) return if not represents_int(self.args[1]) and self.args[1] != "all": await self.reply( [f"**{self.args[1]}** must be whole number or *all*!"]) return if self.args[1] == "all": mgs = [] for order in user.orders: if not order.processed: OrderService.cancel(order.id, user) mgs.append(f"Order ID {order.id} has been cancelled") await self.reply(mgs) return else: if OrderService.cancel(self.args[1], user): await self.reply( [f"Order ID {self.args[1]} has been cancelled"]) return else: await self.reply([ f"**Outstanding order with id {self.args[1]}** does not exist!" ]) return
async def comp(self, ctx, *args): """Manages in-game competitions for tournaments. Needs to be run in the tournament discord channel USAGE: !comp list list all competitions for tournament !comp create ladder creates ladder comp for tournament if it does not exists !comp create 1on1 <competition_name> creates 1 on 1 comp with <competition_name> for tournament if it does not exists !comp create knockout <team_number> <name> creates knockout comp with <name> for <team_number> teams !comp ticket <competition_name> sends ticket to the <competition_name> to the coach issuing the command in the tournament room !comp start <competition_name> starts comp with <competition_name> for tournament """ room = ctx.channel.name args_len = len(args) if args_len == 0 \ or (args_len > 0 and args[0] not in ["list","create", "ticket", "start"]) \ or (args[0] == "create" and \ (args_len < 2 or args[1] not in ["ladder", "1on1","knockout"] or (args[1] == "1on1" and args_len == 2) \ or (args[1] == "knockout" and args_len < 4 and not represents_int(args[2])))) \ or (args[0] in ["ticket", "start"] and args_len < 2): raise ValueError("Incorrect arguments") tourn = TournamentService.get_tournament_using_room(room) if tourn.status != "RUNNING": await ctx.send("Tournament is not running!") return if args[0] == "create": if args[1] == "ladder": comp_name = tourn.ladder_room_name() comp = CompetitionService.create_imperium_ladder(comp_name) if args[1] == "1on1": comp_name = " ".join(args[2:]) comp_name = comp_name[:25] if len( comp_name) > 25 else comp_name comp = CompetitionService.create_imperium_rr(comp_name) if args[1] == "knockout": comp_name = " ".join(args[3:]) comp_name = comp_name[:25] if len( comp_name) > 25 else comp_name comp = CompetitionService.create_imperium_knockout( comp_name, int(args[2])) tourn.competitions.append(comp) db.session.commit() await ctx.send( f"Competition **{comp.name}** created in **{comp.league_name}**" ) return if args[0] == "list": msg = [] msg.append('{:25s} | {:25} | {:25}'.format("League", "Name", "Type")) msg.append(78 * "-") for comp in tourn.competitions: msg.append('{:25s} | {:25} | {:25}'.format( comp.league_name, comp.name, comp.type_str())) await self.send_message(ctx.channel, msg, block=True) # await ctx.send("\n".join(msg)) return if args[0] == "ticket": comp_name = " ".join(args[1:]) # get coach coach = CoachService.discord_user_to_coach(ctx.author) result = CompetitionService.ticket_competition( comp_name, coach, tourn) team_name = result['ResponseCreateCompetitionTicket'][ 'TicketInfos']['RowTeam']['Name'] await ctx.send( f"Ticket sent to **{team_name}** for competition **{comp_name}**" ) return if args[0] == "start": comp_name = " ".join(args[1:]) comp = Competition.query.filter_by(name=comp_name).one_or_none() if not comp: raise CompetitionError( f"Competition **{comp_name}** does not exist") result = CompetitionService.start_competition(comp) await ctx.send(f"Started competition **{comp_name}**") return
async def complist(self, ctx, *args): """List all available tournaments""" if len(args) == 1 and not (represents_int(args[0]) or args[0] in ["all", "full", "free"]): raise ValueError( f"**{args[0]}** is not a number or 'all', 'full' or 'free'!!!") if len(args) > 1: if args[0] not in ["all", "full", "free"]: raise ValueError( f"**{args[0]}** is not 'all', 'full' or 'free'!!!") if args[1] not in ["bigo", "gman", "rel"]: raise ValueError( f"**{args[1]}** is not 'bigo', 'gman' or 'rel'!!!") #detail if len(args) == 1 and represents_int(args[0]): tourn = Tourn.query.filter_by( tournament_id=int(args[0])).one_or_none() if not tourn: raise ValueError(f"Tournament **id** does not exist") coaches = tourn.coaches.filter( TournamentSignups.mode == "active").all() count = len(coaches) msg = [ f"__**{tourn.name}**__ - **{tourn.status}**\n", f"**Type**: {tourn.region} - {tourn.type} - {tourn.mode}", f"**Dates**: Signup By/Start By/End By/Deadline - {tourn.signup_close_date}/{tourn.expected_start_date}/{tourn.expected_end_date}/{tourn.deadline_date}", f"**Entrance Fee**: {tourn.fee}", f"**Deck Size/Deck Target Value/Deck Max Value**: {tourn.deck_limit}/{tourn.deck_value_target}/{tourn.deck_value_limit}", f"**Conclave Ranges**:", f"\t**3 Blessing Points:**\t\t {tourn.conclave_ranges().blessing3.start}-{tourn.conclave_ranges().blessing3.stop}", f"\t**2 Blessing Points:**\t\t {tourn.conclave_ranges().blessing2.start}-{tourn.conclave_ranges().blessing2.stop}", f"\t**1 Blessing Point:** \t\t {tourn.conclave_ranges().blessing1.start}-{tourn.conclave_ranges().blessing1.stop}", f"\t**Conclave equilibrium:** {tourn.deck_value_target}", f"\t**1 Curse Point:**\t\t\t\t {tourn.conclave_ranges().curse1.start}-{tourn.conclave_ranges().curse1.stop}", f"\t**2 Curse Points:**\t\t\t {tourn.conclave_ranges().curse2.start}-{tourn.conclave_ranges().curse2.stop}", f"\t**3 Curse Points:**\t\t\t {tourn.conclave_ranges().curse3.start}-{tourn.conclave_ranges().curse3.stop}", f"**Sponsor**: {tourn.sponsor}", f"**Sponsor Description**: {tourn.sponsor_description}", f"**Special Rules**: {tourn.special_rules}", f"**Banned Cards**: {', '.join(tourn.banned_cards.split(';'))}", f"**Prizes**: {tourn.prizes}", f"**Unique Prize**: {tourn.unique_prize}", f"**Channel**: {tourn.discord_channel}", f"**Admin**: {tourn.admin}", ] if tourn.status == "RUNNING": msg.append( f"**Signups**: {count}/{tourn.coach_limit} {', '.join([coach.short_name() for coach in coaches])}" ) else: msg.append(f"**Signups**: {count}/{tourn.coach_limit}") if tourn.reserve_limit > 0: reserves = tourn.coaches.filter( TournamentSignups.mode == "reserve").all() count_res = len(reserves) if tourn.status == "RUNNING": msg.append( f"**Reserves**: {count_res}/{tourn.reserve_limit} {', '.join([coach.short_name() for coach in reserves])}" ) else: msg.append( f"**Reserves**: {count_res}/{tourn.reserve_limit}") await self.send_message(ctx.channel, msg) return #list else: if len(args) >= 1 and args[0] == "all": tourns = Tourn.query.all() tmsg = "All" elif len(args) >= 1 and args[0] == "full": tourns = Tourn.query.outerjoin( Tourn.tournament_signups).filter( Tourn.status == "OPEN").group_by(Tourn).having( func.count_(Tourn.tournament_signups) == Tourn.coach_limit + Tourn.reserve_limit).all() tmsg = "Full" elif len(args) >= 1 and args[0] == "free": tourns = Tourn.query.outerjoin( Tourn.tournament_signups).filter( Tourn.status == "OPEN").group_by(Tourn).having( func.count_(Tourn.tournament_signups) < Tourn.coach_limit + Tourn.reserve_limit).all() tmsg = "Free" else: tourns = Tourn.query.filter_by(status="OPEN").all() tmsg = "Open" if len(args) > 1: tourns = [ tourn for tourn in tourns if tourn.region.lower().replace(" ", "") == args[1] or tourn.region.lower() == "all" ] msg = [f"__**{tmsg} Tournaments:**__"] for tournament in tourns: coaches = tournament.coaches.filter( TournamentSignups.mode == "active").all() reserves = tournament.coaches.filter( TournamentSignups.mode == "reserve").all() count = len(coaches) count_res = len(reserves) reserve_message = f" ({count_res}/{tournament.reserve_limit}) " if tournament.reserve_limit != 0 else "" msg.append( f"**{tournament.tournament_id}.** {tournament.name}{' (Imperium)' if tournament.type == 'Imperium' else ''} - Signups: {count}/{tournament.coach_limit}{reserve_message}, Closes: {tournament.signup_close_date}" ) msg.append( " \nUse **!complist all|full|free <bigo|gman|rel>** to display tournaments" ) msg.append( "Use **!complist <id>** to display details of the tournament") msg.append("Use **!sign <id>** to register for tournament") msg.append("Use **!resign <id>** to resign from tournament") await self.send_message(ctx.channel, msg) return
async def __run_stock(self): if (self.args[0]) == "!stock": detail = False if len(self.args) < 2: await self.reply([ "Incorrect number of arguments!!!", self.__class__.stock_help() ]) else: limit = 24 if self.args[1] in [ "top", "bottom", "hot", "net", "gain", "loss", "gain%", "loss%" ] and len(self.args) == 3 and represents_int( self.args[2]) and int(self.args[2]) > 0 and int( self.args[2]) <= limit: if self.args[1] == "top": stocks = Stock.find_top(self.args[2]) elif self.args[1] == "bottom": stocks = Stock.find_bottom(self.args[2]) elif self.args[1] == "net": stocks = Stock.find_net(self.args[2]) elif self.args[1] == "gain": stocks = Stock.find_gain(self.args[2]) elif self.args[1] == "gain%": stocks = Stock.find_gain_pct(self.args[2]) elif self.args[1] == "loss": stocks = Stock.find_loss(self.args[2]) elif self.args[1] == "loss%": stocks = Stock.find_loss_pct(self.args[2]) else: stocks = Stock.find_hot(self.args[2]) elif self.args[1] == "detail" and len(self.args) == 3: detail = True try: stock = Stock.find_by_code(self.args[2]) if not stock: await self.reply( [f"{self.args[2]} is not unique stock code"]) return stocks = [stock] except MultipleResultsFound as exc: await self.reply( [f"{self.args[2]} is not unique stock code"]) return else: stocks = Stock.find_all_by_name(" ".join(self.args[1:])) msg = [] change_desc = "Change" if self.args[1] not in [ "gain%", "loss%" ] else "Change%" msg.append( '{:5s} - {:25} {:<8s} {:>7s}{:>9s}{:>8s}{:>11s}'.format( "Code", "Team Name", "Division", "Price", change_desc, "Shares", "Net Worth")) msg.append(78 * "-") round_n = current_round() for stock in stocks[0:limit]: match = MatchService.get_game(stock.name, round_n=round_n) played = "Y" if match and match.match_uuid else "N" changed_value = stock.unit_price_change if self.args[ 1] not in ["gain%", "loss%"] else 0 if int( stock.unit_price ) == 0 else 100 * stock.unit_price_change / ( stock.unit_price - stock.unit_price_change) msg.append( '{:5s} - {:25} {:<8s} {:>7.2f}{:>8.2f}{:1s}{:>8d}{:>11.2f}' .format(stock.code, stock.name, stock.division, stock.unit_price, changed_value, played, stock.share_count, stock.net_worth)) if detail: round_n = app.config['ROUNDS_COLLECT'][-1] match = MatchService.get_game(stocks[0].name, round_n=round_n) if match: homeStock = Stock.find_all_by_name( match.homeTeamName.strip()) awayStock = Stock.find_all_by_name( match.awayTeamName.strip()) homePrice = 0 if not homeStock else homeStock[ 0].unit_price awayPrice = 0 if not awayStock else awayStock[ 0].unit_price homeChange = 0 if not homeStock else homeStock[ 0].unit_price_change awayChange = 0 if not awayStock else awayStock[ 0].unit_price_change homeRace = "N/A" if not homeStock else homeStock[0].race awayRace = "N/A" if not awayStock else awayStock[0].race msg.append(" ") msg.append(f"[Round {round_n} Match]") msg.append('{:>37s} | {:<36s}'.format( "Home", "Away")) msg.append(78 * "-") msg.append('{:>37s} | {:<36s}'.format( match.homeCoachName, match.awayCoachName)) msg.append('{:>37s} | {:<36s}'.format( match.homeTeamName, match.awayTeamName)) msg.append('{:>37s} | {:<36s}'.format( homeRace, awayRace)) msg.append('{:>37.2f} | {:<36.2f}'.format( homePrice, awayPrice)) msg.append('{:>37.2f} | {:<36.2f}'.format( homeChange, awayChange)) # only 1 stock msg.append(" ") msg.append("[Owners]") msg.append(" ") msg.append('{:32s}: {:>8s}{:>11s}'.format( "Name", "Shares", "Net Worth")) msg.append(78 * "-") for share in stocks[0].shares: msg.append('{:32s}: {:8d}{:11.2f}'.format( share.user.short_name(), share.units, round(share.units * share.stock.unit_price, 2))) msg.append(" ") msg.append("[History]") msg.append(" ") msg.append('{:20s}: {:<12s}{:<8s}{:<8s}{:<11s}'.format( "Date", "Unit Price", "Change", "Shares", "Net Worth")) msg.append(78 * "-") for sh in stocks[0].histories: msg.append( '{:20s}: {:10.2f}{:8.2f}{:8d}{:11.2f}'.format( str(sh.date_created), sh.unit_price, sh.unit_price_change, sh.units, round(sh.units * sh.unit_price, 2))) if len(stocks) > 20: msg.append("...") msg.append("More stock follows, narrow your search!") await self.reply(msg, block=True)
async def __run_admin(self): # if not started from admin-channel if not self.__class__.is_admin_channel(self.message.channel): await self.reply([f"Insuficient rights"]) return if self.args[0] == "!adminstock": if len(self.args) != 2: await self.reply([f"Wrong number of parameters"]) return if self.args[1] not in ["update"]: await self.reply( [f"Wrong parameter - only *update* is allowed"]) return await self.short_reply("Updating...") StockService.update() await self.short_reply("Done") if self.args[0] == "!adminmarket": if len(self.args) != 2: await self.reply([f"Wrong number of parameters"]) return if self.args[1] not in ["close", "open", "status"]: await self.reply([ f"Wrong parameter - only *status*, *open* and *close* are allowed" ]) return if self.args[1] == "open": OrderService.open() msg = "Done" if self.args[1] == "close": OrderService.close() msg = "Done" if self.args[1] == "status": if OrderService.is_open(): msg = "Market is open" else: msg = "Market is closed" await self.short_reply(msg) if self.args[0] == "!adminlist": # require username argument if len(self.args) == 1: await self.reply(["Username missing"]) return users = User.find_all_by_name(self.args[1]) msg = [] if not users: msg.append("No users found") await self.reply(msg) for user in users: msg1, msg2, msg3, msg4 = self.list_messages(user) await self.reply(msg1) await self.reply(msg2, block=True) await self.reply(msg3) await self.reply(msg4, block=True) if self.args[0] == '!adminbank': # require username argument if len(self.args) < 4: await self.reply(["Not enough arguments!!!\n"]) await self.short_reply(self.__class__.adminbank_help()) return # amount must be int if not is_number(self.args[1]) or float(self.args[1]) > 100000000: await self.reply( ["<amount> is not number or is too high!!!\n"]) return user = await self.user_unique(self.args[2]) if user is None: return amount = float(self.args[1]) reason = ' '.join( str(x) for x in self.message.content.split(" ") [3:]) + " - updated by " + str(self.message.author.name) tran = Transaction(description=reason, price=-1 * amount) try: user.make_transaction(tran) except TransactionError as e: await self.transaction_error(e) return else: msg = [ f"Bank for {user.name} updated to **{round(user.account().amount,2)}** {app.config['CREDITS']}:\n", f"Note: {reason}\n", f"Change: {amount} {app.config['CREDITS']}" ] await self.reply(msg) await self.bank_notification( f"Your bank has been updated by **{amount}** {app.config['CREDITS']} - {reason}", user) return if self.args[0] == '!adminshare': # require username argument if len(self.args) < 5: await self.reply(["Not enough arguments!!!\n"]) await self.short_reply(self.__class__.adminshare_help()) return stocks = Stock.query.filter_by(code=self.args[1]).all() if not stocks: await self.short_reply( f"<stock> __{self.args[1]}__ not found!!!") return if len(stocks) > 1: emsg = f"<stock> __{name}__ is not **unique**!!!\n" emsg += "Select one: " for stock in stocks: emsg += stock.code emsg += " " await self.short_reply(emsg) return stock = stocks[0] # amount must be int if not represents_int(self.args[2]) or int( self.args[2]) > app.config['MAX_SHARE_UNITS']: await self.reply([ f"{self.args[2]} is not whole number or is higher than {app.config['MAX_SHARE_UNITS']}!!!\n" ]) return user = await self.user_unique(self.args[3]) if user is None: return amount = int(self.args[2]) reason = ' '.join( str(x) for x in self.message.content.split(" ") [4:]) + " - updated by " + str(self.message.author.name) tran = Transaction(description=reason, price=0) try: if amount > 0: done = StockService.add(user, stock, amount) else: done = StockService.remove(user, stock, -1 * amount) if not done: await self.short_reply( f"User {user.short_name()} does not own any shares of __{self.args[1].upper()}__!!!" ) return user.make_transaction(tran) except TransactionError as e: await self.transaction_error(e) return else: msg = [ f"{stock.code} shares for {user.name} has been updated.\n", f"Note: {reason}\n", f"Change: {amount} shares" ] await self.reply(msg) await self.bank_notification( f"Your {stock.code} shares has been updated by **{amount}** - {reason}", user) return if self.args[0] == '!adminpoints': # require username argument if len(self.args) < 4: await self.reply(["Not enough arguments!!!\n"]) await self.short_reply(self.__class__.adminpoints_help()) return # amount must be int if not represents_int(self.args[1]): await self.reply([f"{self.args[1]} is not whole number!!!\n"]) return user = await self.user_unique(self.args[2]) if user is None: return amount = int(self.args[1]) reason = ' '.join( str(x) for x in self.message.content.split(" ") [3:]) + " - updated by " + str(self.message.author.name) try: user.award_points(amount, reason) db.session.commit() except Exception as e: await self.transaction_error(e) return else: msg = [ f"Points for {user.name} has been updated.\n", f"Note: {reason}\n", f"Change: {amount} points" ] await self.reply(msg) await self.bank_notification( f"Your points has been updated by **{amount}** - {reason}", user) return
async def __run_sell(self): user = User.get_by_discord_id(self.message.author.id) order_dict = { 'operation': "sell", 'season': app.config['SEASON'], 'week': current_round() } if user is None: await self.reply([ (f"User {self.message.author.mention} does not exist." "Use !newuser to create user first.") ]) return if len(self.args) not in [2, 3]: await self.reply([ "Incorrect number of arguments!!!", self.__class__.sell_help() ]) return if self.args[1] == "all": if len(user.shares): for share in user.shares: order = OrderService.create(user, share.stock, **order_dict) await self.reply([ f"Order placed succesfully.", " ", f"**{order.desc()}**" ]) else: await self.reply([f"You do not own any shares"]) else: try: stock = Stock.find_by_code(self.args[1]) except MultipleResultsFound as exc: await self.reply([ f"Stock code **{self.args[1]}** is not unique!!!", ]) return if not stock: await self.reply([f"Stock code **{self.args[1]}** not found!"]) return if len(self.args) == 3: if not represents_int(self.args[2]) or (represents_int( self.args[2]) and not int(self.args[2]) > 0): await self.reply( [f"**{self.args[2]}** must be whole positive number!"]) return else: order_dict['sell_shares'] = int(self.args[2]) share = Share.query.join(Share.user, Share.stock).filter( User.id == user.id, Stock.id == stock.id).one_or_none() if not share: await self.reply([ f"You do not own any shares of **{self.args[1]}** stock!" ]) return order = OrderService.create(user, stock, **order_dict) await self.reply([ f"Order **{order.id}** placed succesfully.", " ", f"**{order.desc()}**" ]) return
def max_tournament_id(cls): tournaments = cls.tournaments() if tournaments and represents_int(tournaments[-1]["Tournament ID"]): return int(tournaments[-1]["Tournament ID"]) else: return 0