Merge pull request #114 from Sakimori/leagues
implements tournaments and a foundation for leagues
This commit is contained in:
commit
6e69117e62
6
games.py
6
games.py
|
@ -190,11 +190,10 @@ class team(object):
|
||||||
for this_player in self.rotation:
|
for this_player in self.rotation:
|
||||||
for stat in this_player.game_stats.keys():
|
for stat in this_player.game_stats.keys():
|
||||||
this_player.game_stats[stat] = 0
|
this_player.game_stats[stat] = 0
|
||||||
return True
|
return self
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
if self.is_ready():
|
if self.is_ready():
|
||||||
if self.pitcher is None:
|
|
||||||
self.set_pitcher()
|
self.set_pitcher()
|
||||||
while len(self.lineup) <= 4:
|
while len(self.lineup) <= 4:
|
||||||
self.lineup.append(random.choice(self.lineup))
|
self.lineup.append(random.choice(self.lineup))
|
||||||
|
@ -205,8 +204,7 @@ class team(object):
|
||||||
|
|
||||||
class game(object):
|
class game(object):
|
||||||
|
|
||||||
def __init__(self, name, team1, team2, length=None):
|
def __init__(self, team1, team2, length=None):
|
||||||
self.name = name
|
|
||||||
self.over = False
|
self.over = False
|
||||||
self.teams = {"away" : team1, "home" : team2}
|
self.teams = {"away" : team1, "home" : team2}
|
||||||
self.inning = 1
|
self.inning = 1
|
||||||
|
|
127
leagues.py
Normal file
127
leagues.py
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
import time, asyncio, jsonpickle, random, math
|
||||||
|
from games import team, game
|
||||||
|
from discord import Embed, Color
|
||||||
|
import database as db
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class league(object):
|
||||||
|
def __init__(self, name, subleagues_dic):
|
||||||
|
self.subleagues = {} #key: name, value: [divisions]
|
||||||
|
self.max_days
|
||||||
|
self.day = 1
|
||||||
|
self.name = name
|
||||||
|
self.subleagues = subleagues_dic
|
||||||
|
|
||||||
|
class division(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.teams = {} #key: team object, value: {wins; rd (run diff)}
|
||||||
|
|
||||||
|
class tournament(object):
|
||||||
|
def __init__(self, name, team_dic, series_length = 5, finals_series_length = 7, max_innings = 9, id = None, secs_between_games = 300, secs_between_rounds = 600):
|
||||||
|
self.name = name
|
||||||
|
self.teams = team_dic #same format as division, wins/losses will be used for seeding later
|
||||||
|
self.bracket = None
|
||||||
|
self.results = None
|
||||||
|
self.series_length = series_length
|
||||||
|
self.finals_length = finals_series_length
|
||||||
|
self.game_length = max_innings
|
||||||
|
self.active = False
|
||||||
|
self.delay = secs_between_games
|
||||||
|
self.round_delay = secs_between_rounds
|
||||||
|
self.finals = False
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
if id is None:
|
||||||
|
self.id = random.randint(1111,9999)
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
|
||||||
|
def build_bracket(self, random_sort = False, by_wins = False):
|
||||||
|
teams_list = list(self.teams.keys()).copy()
|
||||||
|
|
||||||
|
if random_sort:
|
||||||
|
def sorter(team_in_list):
|
||||||
|
return random.random()
|
||||||
|
|
||||||
|
elif by_wins:
|
||||||
|
def sorter(team_in_list):
|
||||||
|
return self.teams[team_in_list]["wins"] #sorts by wins
|
||||||
|
|
||||||
|
else: #sort by average stars
|
||||||
|
def sorter(team_in_list):
|
||||||
|
return team_in_list.average_stars()
|
||||||
|
|
||||||
|
teams_list.sort(key=sorter, reverse=True)
|
||||||
|
|
||||||
|
|
||||||
|
bracket_layers = int(math.ceil(math.log(len(teams_list), 2)))
|
||||||
|
empty_slots = int(math.pow(2, bracket_layers) - len(teams_list))
|
||||||
|
|
||||||
|
for i in range(0, empty_slots):
|
||||||
|
teams_list.append(None)
|
||||||
|
|
||||||
|
previous_bracket_layer = teams_list.copy()
|
||||||
|
for i in range(0, bracket_layers - 1):
|
||||||
|
this_layer = []
|
||||||
|
for pair in range(0, int(len(previous_bracket_layer)/2)):
|
||||||
|
if pair % 2 == 0: #if even number
|
||||||
|
this_layer.insert(0+int(pair/2), [previous_bracket_layer.pop(0), previous_bracket_layer.pop(-1)]) #every other pair goes at front of list, moving forward
|
||||||
|
else:
|
||||||
|
this_layer.insert(0-int((1+pair)/2), [previous_bracket_layer.pop(int(len(previous_bracket_layer)/2)-1), previous_bracket_layer.pop(int(len(previous_bracket_layer)/2))]) #every other pair goes at end of list, moving backward
|
||||||
|
previous_bracket_layer = this_layer
|
||||||
|
self.bracket = bracket(previous_bracket_layer, bracket_layers)
|
||||||
|
|
||||||
|
def round_check(self):
|
||||||
|
if self.bracket.depth == 1:
|
||||||
|
self.finals = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
class bracket(object):
|
||||||
|
this_bracket = []
|
||||||
|
|
||||||
|
def __init__(self, bracket_list, depth):
|
||||||
|
self.this_bracket = bracket_list
|
||||||
|
self.depth = depth
|
||||||
|
self.bottom_row = []
|
||||||
|
|
||||||
|
def get_bottom_row(self):
|
||||||
|
self.depth = 1
|
||||||
|
self.bottom_row = []
|
||||||
|
self.dive(self.this_bracket)
|
||||||
|
return self.bottom_row
|
||||||
|
|
||||||
|
def dive(self, branch):
|
||||||
|
if not isinstance(branch[0], list): #if it's a pair of games
|
||||||
|
self.bottom_row.append(branch)
|
||||||
|
else:
|
||||||
|
self.depth += 1
|
||||||
|
return self.dive(branch[0]), self.dive(branch[1])
|
||||||
|
|
||||||
|
#def set_winners(self, branch, winners_list):
|
||||||
|
#new_bracket =
|
||||||
|
|
||||||
|
def set_winners_dive(self, winners_list, index = 0, branch = None, parent = None):
|
||||||
|
if branch is None:
|
||||||
|
branch = self.this_bracket.copy()
|
||||||
|
if not isinstance(branch[0], list): #if it's a pair of games
|
||||||
|
if branch[0].name in winners_list or branch[1] is None:
|
||||||
|
winner = branch[0]
|
||||||
|
if parent is not None:
|
||||||
|
parent[index] = winner
|
||||||
|
elif branch[1].name in winners_list:
|
||||||
|
winner = branch[1]
|
||||||
|
if parent is not None:
|
||||||
|
parent[index] = winner
|
||||||
|
else:
|
||||||
|
self.set_winners_dive(winners_list, index = 0, branch = branch[0], parent = branch)
|
||||||
|
self.set_winners_dive(winners_list, index = 1, branch = branch[1], parent = branch)
|
||||||
|
|
||||||
|
if parent is None:
|
||||||
|
self.this_bracket = branch
|
||||||
|
return branch
|
|
@ -1,4 +1,4 @@
|
||||||
import asyncio, time, datetime, games, json, threading, jinja2
|
import asyncio, time, datetime, games, json, threading, jinja2, leagues
|
||||||
from flask import Flask, url_for, Response, render_template, request, jsonify
|
from flask import Flask, url_for, Response, render_template, request, jsonify
|
||||||
from flask_socketio import SocketIO, emit
|
from flask_socketio import SocketIO, emit
|
||||||
|
|
||||||
|
@ -153,4 +153,4 @@ def update_loop():
|
||||||
})
|
})
|
||||||
|
|
||||||
socketio.emit("states_update", data_to_send)
|
socketio.emit("states_update", data_to_send)
|
||||||
time.sleep(6)
|
time.sleep(8)
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
<Compile Include="debug storage.py">
|
<Compile Include="debug storage.py">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="leagues.py">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="main_controller.py">
|
<Compile Include="main_controller.py">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -57,28 +60,12 @@
|
||||||
<Content Include="games_config.json" />
|
<Content Include="games_config.json" />
|
||||||
<Content Include="ids" />
|
<Content Include="ids" />
|
||||||
<Content Include="matteo.db" />
|
<Content Include="matteo.db" />
|
||||||
<Content Include="static\css\common.css" />
|
|
||||||
<Content Include="static\css\game.css" />
|
|
||||||
<Content Include="static\css\games_page.css" />
|
|
||||||
<Content Include="static\css\game_page.css" />
|
|
||||||
<Content Include="static\css\prism.png" />
|
|
||||||
<Content Include="static\discord.png" />
|
<Content Include="static\discord.png" />
|
||||||
<Content Include="static\img\base_empty.png" />
|
|
||||||
<Content Include="static\img\base_filled.png" />
|
|
||||||
<Content Include="static\img\out_in.png" />
|
|
||||||
<Content Include="static\img\out_out.png" />
|
|
||||||
<Content Include="static\js\game_loader.js" />
|
|
||||||
<Content Include="static\js\grid_loader.js" />
|
|
||||||
<Content Include="templates\base.html" />
|
|
||||||
<Content Include="templates\game.html" />
|
<Content Include="templates\game.html" />
|
||||||
<Content Include="templates\game_box.html" />
|
|
||||||
<Content Include="templates\index.html" />
|
<Content Include="templates\index.html" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="static\" />
|
<Folder Include="static\" />
|
||||||
<Folder Include="static\css\" />
|
|
||||||
<Folder Include="static\img\" />
|
|
||||||
<Folder Include="static\js\" />
|
|
||||||
<Folder Include="templates\" />
|
<Folder Include="templates\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
|
||||||
|
|
358
the_prestige.py
358
the_prestige.py
|
@ -1,4 +1,4 @@
|
||||||
import discord, json, math, os, roman, games, asyncio, random, main_controller, threading, time, urllib
|
import discord, json, math, os, roman, games, asyncio, random, main_controller, threading, time, urllib, leagues
|
||||||
import database as db
|
import database as db
|
||||||
import onomancer as ono
|
import onomancer as ono
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
@ -127,32 +127,19 @@ class StartGameCommand(Command):
|
||||||
innings = None
|
innings = None
|
||||||
try:
|
try:
|
||||||
team_name1 = command.split("\n")[1].strip()
|
team_name1 = command.split("\n")[1].strip()
|
||||||
team1 = games.get_team(team_name1)
|
team1 = get_team_fuzzy_search(team_name1)
|
||||||
if team1 is None:
|
|
||||||
teams = games.search_team(team_name1.lower())
|
|
||||||
if len(teams) == 1:
|
|
||||||
team1 = teams[0]
|
|
||||||
team_name2 = command.split("\n")[2].strip()
|
team_name2 = command.split("\n")[2].strip()
|
||||||
team2 = games.get_team(team_name2)
|
team2 = get_team_fuzzy_search(team_name2)
|
||||||
if team2 is None:
|
|
||||||
teams = games.search_team(team_name2.lower())
|
|
||||||
if len(teams) == 1:
|
|
||||||
team2 = teams[0]
|
|
||||||
innings = int(command.split("\n")[3])
|
innings = int(command.split("\n")[3])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
try:
|
try:
|
||||||
team_name1 = command.split("\n")[1].strip()
|
team_name1 = command.split("\n")[1].strip()
|
||||||
team1 = games.get_team(team_name1)
|
team1 = get_team_fuzzy_search(team_name1)
|
||||||
if team1 is None:
|
|
||||||
teams = games.search_team(team_name1.lower())
|
|
||||||
if len(teams) == 1:
|
|
||||||
team1 = teams[0]
|
|
||||||
team_name2 = command.split("\n")[2].strip()
|
team_name2 = command.split("\n")[2].strip()
|
||||||
team2 = games.get_team(team_name2)
|
team2 = get_team_fuzzy_search(team_name2)
|
||||||
if team2 is None:
|
|
||||||
teams = games.search_team(team_name2.lower())
|
|
||||||
if len(teams) == 1:
|
|
||||||
team2 = teams[0]
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
await msg.channel.send("We need at least three lines: startgame, away team, and home team are required. Optionally, the number of innings can go at the end, if you want a change of pace.")
|
await msg.channel.send("We need at least three lines: startgame, away team, and home team are required. Optionally, the number of innings can go at the end, if you want a change of pace.")
|
||||||
return
|
return
|
||||||
|
@ -164,12 +151,12 @@ class StartGameCommand(Command):
|
||||||
await msg.channel.send("Anything less than 2 innings isn't even an outing. Try again.")
|
await msg.channel.send("Anything less than 2 innings isn't even an outing. Try again.")
|
||||||
return
|
return
|
||||||
|
|
||||||
elif innings is not None and innings > 30 and msg.author.id not in config()["owners"]:
|
elif innings is not None and innings > 200 and msg.author.id not in config()["owners"]:
|
||||||
await msg.channel.send("Y'all can't behave, so we've limited games to 30 innings. Ask xvi to start it with more if you really want to.")
|
await msg.channel.send("Y'all can behave, so we've upped the limit on game length to 200 innings.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if team1 is not None and team2 is not None:
|
if team1 is not None and team2 is not None:
|
||||||
game = games.game(msg.author.name, team1.finalize(), team2.finalize(), length=innings)
|
game = games.game(team1.finalize(), team2.finalize(), length=innings)
|
||||||
channel = msg.channel
|
channel = msg.channel
|
||||||
await msg.delete()
|
await msg.delete()
|
||||||
|
|
||||||
|
@ -270,14 +257,10 @@ class ShowTeamCommand(Command):
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
team_name = command.strip()
|
team_name = command.strip()
|
||||||
team = games.get_team(team_name)
|
team = get_team_fuzzy_search(team_name)
|
||||||
if team is not None:
|
if team is not None:
|
||||||
await msg.channel.send(embed=build_team_embed(team))
|
await msg.channel.send(embed=build_team_embed(team))
|
||||||
else:
|
return
|
||||||
teams = games.search_team(team_name.lower())
|
|
||||||
if len(teams) == 1:
|
|
||||||
await msg.channel.send(embed=build_team_embed(teams[0]))
|
|
||||||
else:
|
|
||||||
await msg.channel.send("Can't find that team, boss. Typo?")
|
await msg.channel.send("Can't find that team, boss. Typo?")
|
||||||
|
|
||||||
class ShowAllTeamsCommand(Command):
|
class ShowAllTeamsCommand(Command):
|
||||||
|
@ -315,7 +298,7 @@ class SwapPlayerCommand(Command):
|
||||||
template = """m;swapsection
|
template = """m;swapsection
|
||||||
[team name]
|
[team name]
|
||||||
[player name]"""
|
[player name]"""
|
||||||
description = "Swaps a player from lineup to rotation, or from rotation to lineup. Requires team ownership."
|
description = "Swaps a player from lineup to rotation, or from rotation to lineup. Requires team ownership and exact spelling of team name."
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
try:
|
try:
|
||||||
|
@ -344,7 +327,7 @@ class MovePlayerCommand(Command):
|
||||||
[team name]
|
[team name]
|
||||||
[player name]
|
[player name]
|
||||||
[new lineup/rotation position number] (indexed with 1 being the top)"""
|
[new lineup/rotation position number] (indexed with 1 being the top)"""
|
||||||
description = "Moves a player in your lineup or rotation. Requires team ownership."
|
description = "Moves a player in your lineup or rotation. Requires team ownership and exact spelling of team name."
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
try:
|
try:
|
||||||
|
@ -374,7 +357,7 @@ class AddPlayerCommand(Command):
|
||||||
template = """m;addplayer pitcher (or m;addplayer batter)
|
template = """m;addplayer pitcher (or m;addplayer batter)
|
||||||
[team name]
|
[team name]
|
||||||
[player name]"""
|
[player name]"""
|
||||||
description = "Recruits a new player to your team, as either a pitcher or a batter. Requires team ownership."
|
description = "Recruits a new player to your team, as either a pitcher or a batter. Requires team ownership and exact spelling of team name."
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
try:
|
try:
|
||||||
|
@ -407,6 +390,7 @@ class RemovePlayerCommand(Command):
|
||||||
template = """m;removeplayer
|
template = """m;removeplayer
|
||||||
[team name]
|
[team name]
|
||||||
[player name]"""
|
[player name]"""
|
||||||
|
description = "Removes a player from your team. Requires team ownership and exact spelling of team name."
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
try:
|
try:
|
||||||
|
@ -452,7 +436,7 @@ class HelpCommand(Command):
|
||||||
class DeleteTeamCommand(Command):
|
class DeleteTeamCommand(Command):
|
||||||
name = "deleteteam"
|
name = "deleteteam"
|
||||||
template = "m;deleteteam [name]"
|
template = "m;deleteteam [name]"
|
||||||
description = "Allows you to delete the team with the provided name if you are the owner of it, Gives a confirmation first to prevent accidental deletions. If it isn't letting you delete your team, you probably created it before teams having owners was a thing, contact xvi and xie can assign you as the owner."
|
description = "Allows you to delete the team with the provided name. Requires team ownership. If you are the owner and the bot is telling you it's not yours, contact xvi and xie can assist."
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
team_name = command.strip()
|
team_name = command.strip()
|
||||||
|
@ -473,7 +457,6 @@ class AssignOwnerCommand(Command):
|
||||||
return user.id in config()["owners"]
|
return user.id in config()["owners"]
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
#try:
|
|
||||||
new_owner = msg.mentions[0]
|
new_owner = msg.mentions[0]
|
||||||
team_name = command.strip().split(new_owner.mention+" ")[1]
|
team_name = command.strip().split(new_owner.mention+" ")[1]
|
||||||
print(team_name)
|
print(team_name)
|
||||||
|
@ -481,8 +464,43 @@ class AssignOwnerCommand(Command):
|
||||||
await msg.channel.send(f"{team_name} is now owned by {new_owner.display_name}. Don't break it.")
|
await msg.channel.send(f"{team_name} is now owned by {new_owner.display_name}. Don't break it.")
|
||||||
else:
|
else:
|
||||||
await msg.channel.send("We couldn't find that team. Typo?")
|
await msg.channel.send("We couldn't find that team. Typo?")
|
||||||
#except:
|
|
||||||
#await msg.channel.send("We hit a snag. Tell xvi.")
|
class StartTournamentCommand(Command):
|
||||||
|
name = "starttournament"
|
||||||
|
template = """m;starttournament
|
||||||
|
[tournament name]
|
||||||
|
[list of teams, each on a new line]"""
|
||||||
|
description = "Starts a tournament with the teams given. Byes will be given to teams to allow for numbers other than powers of two. The current tournament format is:\nBest of 5 until the finals, which are Best of 7"
|
||||||
|
|
||||||
|
async def execute(self, msg, command):
|
||||||
|
to_parse = command.split("\n")[0]
|
||||||
|
if "--rounddelay " in to_parse:
|
||||||
|
try:
|
||||||
|
round_delay = int(to_parse.split("--rounddelay ")[1].split(" ")[0])
|
||||||
|
except ValueError:
|
||||||
|
await msg.channel.send("The delay between rounds should be a whole number.")
|
||||||
|
return
|
||||||
|
if round_delay < 1 or round_delay > 120:
|
||||||
|
await msg.channel.send("The delay between rounds has to be between 1 and 120 minutes.")
|
||||||
|
else:
|
||||||
|
round_delay = 10
|
||||||
|
|
||||||
|
tourney_name = command.split("\n")[1]
|
||||||
|
list_of_team_names = command.split("\n")[2:]
|
||||||
|
team_dic = {}
|
||||||
|
for name in list_of_team_names:
|
||||||
|
team = get_team_fuzzy_search(name.strip())
|
||||||
|
if team == None:
|
||||||
|
await msg.channel.send(f"We couldn't find {name}. Try again?")
|
||||||
|
return
|
||||||
|
team_dic[team] = {"wins": 0}
|
||||||
|
|
||||||
|
id = random.randint(1111,9999)
|
||||||
|
|
||||||
|
tourney = leagues.tournament(tourney_name, team_dic, id=id, secs_between_rounds = round_delay * 60)
|
||||||
|
tourney.build_bracket(random_sort = True)
|
||||||
|
|
||||||
|
await start_tournament_round(msg.channel, tourney)
|
||||||
|
|
||||||
|
|
||||||
commands = [
|
commands = [
|
||||||
|
@ -504,6 +522,7 @@ commands = [
|
||||||
ShowAllTeamsCommand(),
|
ShowAllTeamsCommand(),
|
||||||
SearchTeamsCommand(),
|
SearchTeamsCommand(),
|
||||||
StartGameCommand(),
|
StartGameCommand(),
|
||||||
|
StartTournamentCommand(),
|
||||||
StartRandomGameCommand(),
|
StartRandomGameCommand(),
|
||||||
CreditCommand(),
|
CreditCommand(),
|
||||||
RomanCommand(),
|
RomanCommand(),
|
||||||
|
@ -512,7 +531,7 @@ commands = [
|
||||||
|
|
||||||
client = discord.Client()
|
client = discord.Client()
|
||||||
gamesarray = []
|
gamesarray = []
|
||||||
gamesqueue = []
|
active_tournaments = []
|
||||||
setupmessages = {}
|
setupmessages = {}
|
||||||
|
|
||||||
thread1 = threading.Thread(target=main_controller.update_loop)
|
thread1 = threading.Thread(target=main_controller.update_loop)
|
||||||
|
@ -587,19 +606,6 @@ async def on_message(msg):
|
||||||
except CommandError as ce:
|
except CommandError as ce:
|
||||||
await msg.channel.send(str(ce))
|
await msg.channel.send(str(ce))
|
||||||
|
|
||||||
async def start_game(channel):
|
|
||||||
msg = await channel.send("Play ball!")
|
|
||||||
await asyncio.sleep(4)
|
|
||||||
newgame = games.debug_game()
|
|
||||||
gamesarray.append(newgame)
|
|
||||||
while not newgame.over:
|
|
||||||
state = newgame.gamestate_update_full()
|
|
||||||
if not state.startswith("Game over"):
|
|
||||||
await msg.edit(content=state)
|
|
||||||
await asyncio.sleep(3)
|
|
||||||
await channel.send(state)
|
|
||||||
gamesarray.pop()
|
|
||||||
|
|
||||||
|
|
||||||
async def setup_game(channel, owner, newgame):
|
async def setup_game(channel, owner, newgame):
|
||||||
newgame.owner = owner
|
newgame.owner = owner
|
||||||
|
@ -726,32 +732,7 @@ Creator, type `{newgame.name} done` to finalize lineups.""")
|
||||||
await game_task
|
await game_task
|
||||||
|
|
||||||
async def watch_game(channel, newgame, user = None, league = None):
|
async def watch_game(channel, newgame, user = None, league = None):
|
||||||
blank_emoji = discord.utils.get(client.emojis, id = 790899850295509053)
|
newgame, state_init = prepare_game(newgame)
|
||||||
empty_base = discord.utils.get(client.emojis, id = 790899850395779074)
|
|
||||||
occupied_base = discord.utils.get(client.emojis, id = 790899850320543745)
|
|
||||||
out_emoji = discord.utils.get(client.emojis, id = 791578957241778226)
|
|
||||||
in_emoji = discord.utils.get(client.emojis, id = 791578957244792832)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
|
||||||
weathers = games.all_weathers()
|
|
||||||
newgame.weather = weathers[random.choice(list(weathers.keys()))]
|
|
||||||
state_init = {
|
|
||||||
"away_name" : newgame.teams['away'].name,
|
|
||||||
"home_name" : newgame.teams['home'].name,
|
|
||||||
"max_innings" : newgame.max_innings,
|
|
||||||
"update_pause" : 0,
|
|
||||||
"top_of_inning" : True,
|
|
||||||
"victory_lap" : False,
|
|
||||||
"weather_emoji" : newgame.weather.emoji,
|
|
||||||
"weather_text" : newgame.weather.name,
|
|
||||||
"start_delay" : 5,
|
|
||||||
"end_delay" : 10
|
|
||||||
}
|
|
||||||
if newgame.weather.name == "Heavy Snow":
|
|
||||||
newgame.weather.counter_away = random.randint(0,len(newgame.teams['away'].lineup)-1)
|
|
||||||
newgame.weather.counter_home = random.randint(0,len(newgame.teams['home'].lineup)-1)
|
|
||||||
|
|
||||||
if league is not None:
|
if league is not None:
|
||||||
discrim_string = league
|
discrim_string = league
|
||||||
|
@ -775,14 +756,155 @@ async def watch_game(channel, newgame, user = None, league = None):
|
||||||
await channel.send(f"{newgame.teams['away'].name} vs. {newgame.teams['home'].name}, starting at {config()['simmadome_url']+ext}")
|
await channel.send(f"{newgame.teams['away'].name} vs. {newgame.teams['home'].name}, starting at {config()['simmadome_url']+ext}")
|
||||||
gamesarray.append((newgame, channel, user, timestamp))
|
gamesarray.append((newgame, channel, user, timestamp))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main_controller.master_games_dic[timestamp] = (newgame, state_init, discrim_string)
|
main_controller.master_games_dic[timestamp] = (newgame, state_init, discrim_string)
|
||||||
|
|
||||||
async def play_from_queue(channel, game, user_mention):
|
def prepare_game(newgame, league = None, weather_name = None):
|
||||||
await channel.send(f"{user_mention}, your game's ready.")
|
if weather_name is None:
|
||||||
game_task = asyncio.create_task(watch_game(channel, game))
|
weathers = games.all_weathers()
|
||||||
await game_task
|
newgame.weather = weathers[random.choice(list(weathers.keys()))]
|
||||||
|
|
||||||
|
state_init = {
|
||||||
|
"away_name" : newgame.teams['away'].name,
|
||||||
|
"home_name" : newgame.teams['home'].name,
|
||||||
|
"max_innings" : newgame.max_innings,
|
||||||
|
"update_pause" : 0,
|
||||||
|
"top_of_inning" : True,
|
||||||
|
"victory_lap" : False,
|
||||||
|
"weather_emoji" : newgame.weather.emoji,
|
||||||
|
"weather_text" : newgame.weather.name,
|
||||||
|
"start_delay" : 5,
|
||||||
|
"end_delay" : 10
|
||||||
|
}
|
||||||
|
|
||||||
|
if league is None:
|
||||||
|
state_init["is_league"] = False
|
||||||
|
else:
|
||||||
|
state_init["is_league"] = True
|
||||||
|
|
||||||
|
if newgame.weather.name == "Heavy Snow":
|
||||||
|
newgame.weather.counter_away = random.randint(0,len(newgame.teams['away'].lineup)-1)
|
||||||
|
newgame.weather.counter_home = random.randint(0,len(newgame.teams['home'].lineup)-1)
|
||||||
|
return newgame, state_init
|
||||||
|
|
||||||
|
async def start_tournament_round(channel, tourney, seeding = None):
|
||||||
|
current_games = []
|
||||||
|
if tourney.bracket is None:
|
||||||
|
if seeding is None:
|
||||||
|
tourney.build_bracket(random_sort=True)
|
||||||
|
|
||||||
|
games_to_start = tourney.bracket.get_bottom_row()
|
||||||
|
|
||||||
|
for pair in games_to_start:
|
||||||
|
if pair[0] is not None and pair[1] is not None:
|
||||||
|
this_game = games.game(pair[0].prepare_for_save().finalize(), pair[1].prepare_for_save().finalize(), length = tourney.game_length)
|
||||||
|
this_game, state_init = prepare_game(this_game)
|
||||||
|
|
||||||
|
state_init["is_league"] = True
|
||||||
|
state_init["title"] = f"0 - 0"
|
||||||
|
discrim_string = tourney.name
|
||||||
|
|
||||||
|
timestamp = str(time.time() * 1000.0 + random.randint(0,3000))
|
||||||
|
current_games.append((this_game, timestamp))
|
||||||
|
main_controller.master_games_dic[timestamp] = (this_game, state_init, discrim_string)
|
||||||
|
|
||||||
|
ext = "?league=" + urllib.parse.quote_plus(tourney.name)
|
||||||
|
|
||||||
|
if tourney.round_check(): #if finals
|
||||||
|
await channel.send(f"The {tourney.name} finals are starting now, at {config()['simmadome_url']+ext}")
|
||||||
|
finals = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
await channel.send(f"{len(current_games)} games started for the {tourney.name} tournament, at {config()['simmadome_url']+ext}")
|
||||||
|
finals = False
|
||||||
|
await tourney_round_watcher(channel, tourney, current_games, config()['simmadome_url']+ext, finals)
|
||||||
|
|
||||||
|
async def continue_tournament_series(tourney, queue, games_list, wins_in_series):
|
||||||
|
for oldgame in queue:
|
||||||
|
away_team = games.get_team(oldgame.teams["away"].name)
|
||||||
|
home_team = games.get_team(oldgame.teams["home"].name)
|
||||||
|
this_game = games.game(away_team.finalize(), home_team.finalize(), length = tourney.game_length)
|
||||||
|
this_game, state_init = prepare_game(this_game)
|
||||||
|
|
||||||
|
state_init["is_league"] = True
|
||||||
|
|
||||||
|
state_init["title"] = f"{wins_in_series[oldgame.teams['away'].name]} - {wins_in_series[oldgame.teams['home'].name]}"
|
||||||
|
|
||||||
|
discrim_string = tourney.name
|
||||||
|
|
||||||
|
timestamp = str(time.time() * 1000.0 + random.randint(0,3000))
|
||||||
|
games_list.append((this_game, timestamp))
|
||||||
|
main_controller.master_games_dic[timestamp] = (this_game, state_init, discrim_string)
|
||||||
|
|
||||||
|
return games_list
|
||||||
|
|
||||||
|
async def tourney_round_watcher(channel, tourney, games_list, filter_url, finals = False):
|
||||||
|
tourney.active = True
|
||||||
|
active_tournaments.append(tourney)
|
||||||
|
wins_in_series = {}
|
||||||
|
winner_list = []
|
||||||
|
while tourney.active:
|
||||||
|
queued_games = []
|
||||||
|
while len(games_list) > 0:
|
||||||
|
try:
|
||||||
|
for i in range(0, len(games_list)):
|
||||||
|
game, key = games_list[i]
|
||||||
|
if game.over and main_controller.master_games_dic[key][1]["end_delay"] <= 9:
|
||||||
|
if game.teams['home'].name not in wins_in_series.keys():
|
||||||
|
wins_in_series[game.teams["home"].name] = 0
|
||||||
|
if game.teams['away'].name not in wins_in_series.keys():
|
||||||
|
wins_in_series[game.teams["away"].name] = 0
|
||||||
|
|
||||||
|
winner_name = game.teams['home'].name if game.teams['home'].score > game.teams['away'].score else game.teams['away'].name
|
||||||
|
|
||||||
|
if winner_name in wins_in_series.keys():
|
||||||
|
wins_in_series[winner_name] += 1
|
||||||
|
else:
|
||||||
|
wins_in_series[winner_name] = 1
|
||||||
|
|
||||||
|
final_embed = game_over_embed(game)
|
||||||
|
await channel.send(f"A {tourney.name} game just ended!")
|
||||||
|
await channel.send(embed=final_embed)
|
||||||
|
if wins_in_series[winner_name] >= int((tourney.series_length+1)/2) and not finals:
|
||||||
|
winner_list.append(winner_name)
|
||||||
|
elif wins_in_series[winner_name] >= int((tourney.finals_length+1)/2):
|
||||||
|
winner_list.append(winner_name)
|
||||||
|
else:
|
||||||
|
queued_games.append(game)
|
||||||
|
|
||||||
|
games_list.pop(i)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
print("something went wrong in tourney_watcher")
|
||||||
|
await asyncio.sleep(4)
|
||||||
|
|
||||||
|
|
||||||
|
if len(queued_games) > 0:
|
||||||
|
await channel.send(f"The next batch of games for {tourney.name} will start in {int(tourney.delay/60)} minutes.")
|
||||||
|
await asyncio.sleep(tourney.delay)
|
||||||
|
await channel.send(f"{len(queued_games)} games for {tourney.name}, starting at {filter_url}")
|
||||||
|
games_list = await continue_tournament_series(tourney, queued_games, games_list, wins_in_series)
|
||||||
|
else:
|
||||||
|
tourney.active = False
|
||||||
|
|
||||||
|
if finals: #if this last round was finals
|
||||||
|
embed = discord.Embed(color = discord.Color.dark_purple(), title = f"{winner_list[0]} win the {tourney.name} finals!")
|
||||||
|
await channel.send(embed=embed)
|
||||||
|
active_tournaments.pop(active_tournaments.index(tourney))
|
||||||
|
return
|
||||||
|
|
||||||
|
tourney.bracket.set_winners_dive(winner_list)
|
||||||
|
|
||||||
|
winners_string = ""
|
||||||
|
for game in tourney.bracket.get_bottom_row():
|
||||||
|
winners_string += f"{game[0].name}\n{game[1].name}\n"
|
||||||
|
await channel.send(f"""
|
||||||
|
This round of games for {tourney.name} is now complete! The next round will be starting in {int(tourney.round_delay/60)} minutes.
|
||||||
|
Advancing teams:
|
||||||
|
{winners_string}""")
|
||||||
|
await asyncio.sleep(tourney.round_delay)
|
||||||
|
await start_tournament_round(channel, tourney)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def team_delete_confirm(channel, team, owner):
|
async def team_delete_confirm(channel, team, owner):
|
||||||
team_msg = await channel.send(embed=build_team_embed(team))
|
team_msg = await channel.send(embed=build_team_embed(team))
|
||||||
|
@ -850,8 +972,8 @@ def team_from_collection(newteam_json):
|
||||||
raise CommandError("We've given you 100 characters for the slogan. Discord puts limits on us and thus, we put limits on you. C'est la vie.")
|
raise CommandError("We've given you 100 characters for the slogan. Discord puts limits on us and thus, we put limits on you. C'est la vie.")
|
||||||
if len(newteam_json["lineup"]) > 20:
|
if len(newteam_json["lineup"]) > 20:
|
||||||
raise CommandError("20 players in the lineup, maximum. We're being really generous here.")
|
raise CommandError("20 players in the lineup, maximum. We're being really generous here.")
|
||||||
if not len(newteam_json["rotation"]) == 1:
|
if not len(newteam_json["rotation"]) > 8:
|
||||||
raise CommandError("One and only one pitcher per team, thanks.")
|
raise CommandError("8 pitchers on the rotation, max. That's a *lot* of pitchers.")
|
||||||
for player in newteam_json["lineup"] + newteam_json["rotation"]:
|
for player in newteam_json["lineup"] + newteam_json["rotation"]:
|
||||||
if len(player["name"]) > 70:
|
if len(player["name"]) > 70:
|
||||||
raise CommandError(f"{player['name']} is too long, chief. 70 or less.")
|
raise CommandError(f"{player['name']} is too long, chief. 70 or less.")
|
||||||
|
@ -931,7 +1053,10 @@ async def team_pages(msg, all_teams, search_term=None):
|
||||||
embed.set_footer(text = f"Page {page+1} of {page_max}")
|
embed.set_footer(text = f"Page {page+1} of {page_max}")
|
||||||
for i in range(0,25):
|
for i in range(0,25):
|
||||||
try:
|
try:
|
||||||
|
if all_teams[i+25*page].slogan.strip() != "":
|
||||||
embed.add_field(name=all_teams[i+25*page].name, value=all_teams[i+25*page].slogan)
|
embed.add_field(name=all_teams[i+25*page].name, value=all_teams[i+25*page].slogan)
|
||||||
|
else:
|
||||||
|
embed.add_field(name=all_teams[i+25*page].name, value="404: Slogan not found")
|
||||||
except:
|
except:
|
||||||
break
|
break
|
||||||
pages.append(embed)
|
pages.append(embed)
|
||||||
|
@ -961,16 +1086,30 @@ async def team_pages(msg, all_teams, search_term=None):
|
||||||
|
|
||||||
async def game_watcher():
|
async def game_watcher():
|
||||||
while True:
|
while True:
|
||||||
#try:
|
try:
|
||||||
this_array = gamesarray.copy()
|
this_array = gamesarray.copy()
|
||||||
for i in range(0,len(this_array)):
|
for i in range(0,len(this_array)):
|
||||||
game, channel, user, key = this_array[i]
|
game, channel, user, key = this_array[i]
|
||||||
if game.over and main_controller.master_games_dic[key][1]["end_delay"] <= 9:
|
if game.over and main_controller.master_games_dic[key][1]["end_delay"] <= 9:
|
||||||
|
final_embed = game_over_embed(game)
|
||||||
|
if user is not None:
|
||||||
|
await channel.send(f"{user.mention}'s game just ended.")
|
||||||
|
else:
|
||||||
|
await channel.send("A game started from this channel just ended.")
|
||||||
|
await channel.send(embed=final_embed)
|
||||||
|
gamesarray.pop(i)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
print("something broke in game_watcher")
|
||||||
|
await asyncio.sleep(4)
|
||||||
|
|
||||||
|
def game_over_embed(game):
|
||||||
title_string = f"{game.teams['away'].name} at {game.teams['home'].name} ended after {game.inning-1} innings"
|
title_string = f"{game.teams['away'].name} at {game.teams['home'].name} ended after {game.inning-1} innings"
|
||||||
if (game.inning - 1) > game.max_innings: #if extra innings
|
if (game.inning - 1) > game.max_innings: #if extra innings
|
||||||
title_string += f" with {game.inning - (game.max_innings+1)} extra innings."
|
title_string += f" with {game.inning - (game.max_innings+1)} extra innings.\n"
|
||||||
else:
|
else:
|
||||||
title_string += "."
|
title_string += ".\n"
|
||||||
|
title_string += game.weather.emoji + game.weather.name
|
||||||
|
|
||||||
winning_team = game.teams['home'].name if game.teams['home'].score > game.teams['away'].score else game.teams['away'].name
|
winning_team = game.teams['home'].name if game.teams['home'].score > game.teams['away'].score else game.teams['away'].name
|
||||||
winstring = f"{game.teams['away'].score} to {game.teams['home'].score}\n"
|
winstring = f"{game.teams['away'].score} to {game.teams['home'].score}\n"
|
||||||
|
@ -981,24 +1120,35 @@ async def game_watcher():
|
||||||
else:
|
else:
|
||||||
winstring += f"{winning_team} wins!"
|
winstring += f"{winning_team} wins!"
|
||||||
|
|
||||||
if user is not None:
|
embed = discord.Embed(color=discord.Color.dark_purple(), title=title_string)
|
||||||
if isinstance(user, str):
|
embed.add_field(name="Final score:", value=winstring)
|
||||||
await channel.send(f"A game from {user} just ended.")
|
return embed
|
||||||
else:
|
|
||||||
await channel.send(f"{user.mention}'s game just ended.")
|
|
||||||
else:
|
|
||||||
await channel.send("A game started from this channel just ended.")
|
|
||||||
|
|
||||||
final_embed = discord.Embed(color=discord.Color.dark_purple(), title=title_string)
|
def get_team_fuzzy_search(team_name):
|
||||||
final_embed.add_field(name="Final score:", value=winstring)
|
team = games.get_team(team_name)
|
||||||
await channel.send(embed=final_embed)
|
if team is None:
|
||||||
gamesarray.pop(i)
|
teams = games.search_team(team_name.lower())
|
||||||
break
|
if len(teams) == 1:
|
||||||
#except:
|
team = teams[0]
|
||||||
#print("something broke in game_watcher")
|
return team
|
||||||
|
|
||||||
await asyncio.sleep(6)
|
|
||||||
|
|
||||||
|
|
||||||
|
#test_bracket = {
|
||||||
|
# "Milwaukee Lockpicks" : {"wins": 4, "rd": 0},
|
||||||
|
# "Madagascar Penguins" : {"wins": 2, "rd": 0},
|
||||||
|
# "Twin Cities Evening" : {"wins": 1, "rd": 0},
|
||||||
|
# "Washington State Houses" : {"wins": 9, "rd": 0},
|
||||||
|
# "Appalachian Underground" : {"wins": 8, "rd": 0},
|
||||||
|
# "Pacific2 Rams" : {"wins": 3, "rd": 0},
|
||||||
|
# "New Jersey Radio" : {"wins": 11, "rd": 0},
|
||||||
|
# "Moline Jolenes" : {"wins": 6, "rd": 0},
|
||||||
|
# "California Commissioners" : {"wins": 10, "rd": 0},
|
||||||
|
# "Pigeon’s Reckoning" : {"wins": 7, "rd": 0},
|
||||||
|
# "Kernow Technologists" : {"wins": 5, "rd": 0}
|
||||||
|
# }
|
||||||
|
#tourney = leagues.tournament("Test Tourney", test_bracket, max_innings=3)
|
||||||
|
#tourney.build_bracket(by_wins=True)
|
||||||
|
#tourney.bracket.set_winners_dive(['Twin Cities Evening','Madagascar Penguins', 'Pacific2 Rams'])
|
||||||
|
#print(tourney.bracket.this_bracket)
|
||||||
|
|
||||||
client.run(config()["token"])
|
client.run(config()["token"])
|
Loading…
Reference in New Issue
Block a user