forked from c0de/BaseballBot
Working base version
This commit is contained in:
commit
e22f67ab17
12
.idea/ghostballBot.iml
generated
Normal file
12
.idea/ghostballBot.iml
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
<component name="TestRunnerService">
|
||||||
|
<option name="projectConfiguration" value="Nosetests" />
|
||||||
|
<option name="PROJECT_TEST_RUNNER" value="Nosetests" />
|
||||||
|
</component>
|
||||||
|
</module>
|
4
.idea/misc.xml
generated
Normal file
4
.idea/misc.xml
generated
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/ghostballBot.iml" filepath="$PROJECT_DIR$/.idea/ghostballBot.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
91
.idea/workspace.xml
generated
Normal file
91
.idea/workspace.xml
generated
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="60bff1c9-5425-4855-bbbe-90297c1dfe49" name="Default Changelist" comment="" />
|
||||||
|
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="FileTemplateManagerImpl">
|
||||||
|
<option name="RECENT_TEMPLATES">
|
||||||
|
<list>
|
||||||
|
<option value="Python Script" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectId" id="1Ol6SCamPcPPraK1ZGhiktLdkWv" />
|
||||||
|
<component name="PropertiesComponent">
|
||||||
|
<property name="settings.editor.selected.configurable" value="preferences.lookFeel" />
|
||||||
|
</component>
|
||||||
|
<component name="RecentsManager">
|
||||||
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$/src/main/database_module/database_classes" />
|
||||||
|
</key>
|
||||||
|
</component>
|
||||||
|
<component name="RunDashboard">
|
||||||
|
<option name="ruleStates">
|
||||||
|
<list>
|
||||||
|
<RuleState>
|
||||||
|
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||||
|
</RuleState>
|
||||||
|
<RuleState>
|
||||||
|
<option name="name" value="StatusDashboardGroupingRule" />
|
||||||
|
</RuleState>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="RunManager">
|
||||||
|
<configuration name="bot_runner" type="PythonConfigurationType" factoryName="Python" temporary="true">
|
||||||
|
<module name="ghostballBot" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<envs>
|
||||||
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
|
</envs>
|
||||||
|
<option name="SDK_HOME" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/src/main/discord_module" />
|
||||||
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/src/main/discord_module/bot_runner.py" />
|
||||||
|
<option name="PARAMETERS" value="NjEyODQwNDg5ODI1MzM3Mzc0.XVoPyQ.g8d_P-EV1p8OytraEWmYnsCBB7w /mln/ghostbot.cfg" />
|
||||||
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
|
<option name="MODULE_MODE" value="false" />
|
||||||
|
<option name="REDIRECT_INPUT" value="false" />
|
||||||
|
<option name="INPUT_FILE" value="" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<recent_temporary>
|
||||||
|
<list>
|
||||||
|
<item itemvalue="Python.bot_runner" />
|
||||||
|
</list>
|
||||||
|
</recent_temporary>
|
||||||
|
</component>
|
||||||
|
<component name="SvnConfiguration">
|
||||||
|
<configuration />
|
||||||
|
</component>
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="60bff1c9-5425-4855-bbbe-90297c1dfe49" name="Default Changelist" comment="" />
|
||||||
|
<created>1564362047285</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1564362047285</updated>
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="XDebuggerManager">
|
||||||
|
<breakpoint-manager>
|
||||||
|
<default-breakpoints>
|
||||||
|
<breakpoint type="python-exception">
|
||||||
|
<properties notifyOnTerminate="true" exception="BaseException">
|
||||||
|
<option name="notifyOnTerminate" value="true" />
|
||||||
|
</properties>
|
||||||
|
</breakpoint>
|
||||||
|
</default-breakpoints>
|
||||||
|
</breakpoint-manager>
|
||||||
|
</component>
|
||||||
|
</project>
|
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
0
src/main/__init__.py
Normal file
0
src/main/__init__.py
Normal file
51
src/main/configs.py
Normal file
51
src/main/configs.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Names of Configurations
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
|
DATABASE_USERNAME = 'database_username'
|
||||||
|
DATABASE_PASSWORD = 'database_password'
|
||||||
|
DATABASE_HOST = 'database_host'
|
||||||
|
DATABASE_PORT = 'database_port'
|
||||||
|
DATABASE_NAME = 'database_name'
|
||||||
|
SEASON_1_SPREADSHEET_ID = 's1_spreadsheet_id'
|
||||||
|
SEASON_2_SPREADSHEET_ID = 's2_spreadsheet_id'
|
||||||
|
PLAYER_SPREADSHEET = 'player_spreadsheet'
|
||||||
|
|
||||||
|
'''
|
||||||
|
Main source for configurations fetched from a startup configuration file. Includes the ability to fetch all, or fetch
|
||||||
|
one configuration once the file is loaded.
|
||||||
|
|
||||||
|
You'll find the names of these configs above as constants that can be used throughout the rest of this repository
|
||||||
|
'''
|
||||||
|
class Configs():
|
||||||
|
configs = {}
|
||||||
|
|
||||||
|
def __init__(self, config_file_path):
|
||||||
|
self.config_file_path = config_file_path
|
||||||
|
self.__load_configs__()
|
||||||
|
|
||||||
|
'''
|
||||||
|
Fetches a single configuration by the name of that configuration.
|
||||||
|
Returns None if that configuration does not exist
|
||||||
|
'''
|
||||||
|
def get_config_by_name(self, name):
|
||||||
|
try:
|
||||||
|
return Configs.configs[name]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
'''
|
||||||
|
Fetches all configurations and returns them as a dictionary of config_key -> config_value
|
||||||
|
'''
|
||||||
|
def get_all_configs(self):
|
||||||
|
return Configs.configs
|
||||||
|
|
||||||
|
'''
|
||||||
|
Performs the initial load of configurations from a startup configuration file
|
||||||
|
'''
|
||||||
|
def __load_configs__(self):
|
||||||
|
Configs.configs = {}
|
||||||
|
config_file = open(self.config_file_path, 'r')
|
||||||
|
for line in config_file:
|
||||||
|
split_line = line.split('=')
|
||||||
|
Configs.configs[split_line[0]] = split_line[1].strip('\n')
|
0
src/main/database_module/__init__.py
Normal file
0
src/main/database_module/__init__.py
Normal file
31
src/main/database_module/database_classes/db_classes.py
Normal file
31
src/main/database_module/database_classes/db_classes.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from sqlalchemy import Column, String, Integer, ForeignKey, Date
|
||||||
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
from sqlalchemy.ext.hybrid import hybrid_property
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
|
from src.main.db_session import DatabaseSession
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
|
||||||
|
class Play(Base):
|
||||||
|
__tablename__ = 'play'
|
||||||
|
|
||||||
|
play_id = Column(String, nullable=False, primary_key=True)
|
||||||
|
pitch_value = Column(Integer, nullable=True)
|
||||||
|
swing_value = Column(Integer, nullable=False)
|
||||||
|
creation_date = Column(Date, nullable=False)
|
||||||
|
|
||||||
|
guesses = relationship(lambda : Guess)
|
||||||
|
|
||||||
|
class Guess(Base):
|
||||||
|
__FAKE_VALUE__ = -5000
|
||||||
|
|
||||||
|
__tablename__ = 'guess'
|
||||||
|
member_id = Column(String, nullable=False, primary_key=True)
|
||||||
|
play_id = Column(UUID, ForeignKey(Play.play_id), nullable=False, primary_key=True)
|
||||||
|
guessed_number = Column(Integer, nullable=False)
|
||||||
|
member_name = Column(String, nullable=False)
|
||||||
|
difference = Column(Integer)
|
||||||
|
|
||||||
|
play = relationship("Play", back_populates="guesses")
|
85
src/main/database_module/guess_dao.py
Normal file
85
src/main/database_module/guess_dao.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
from src.main.database_module.database_classes.db_classes import Guess
|
||||||
|
from src.main.db_session import DatabaseSession
|
||||||
|
|
||||||
|
MEMBER_ID = 'member_id'
|
||||||
|
PLAY_ID = 'play_id'
|
||||||
|
GUESSED_NUMBER = 'guessed_number'
|
||||||
|
DIFFERENCE = 'difference'
|
||||||
|
MEMBER_NAME = 'member_name'
|
||||||
|
|
||||||
|
class GuessDAO():
|
||||||
|
db_string = None
|
||||||
|
session = None
|
||||||
|
Session = None
|
||||||
|
engine = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def insert(self, guess_info):
|
||||||
|
session = DatabaseSession.session
|
||||||
|
|
||||||
|
guess = Guess(
|
||||||
|
member_id=guess_info[MEMBER_ID],
|
||||||
|
play_id = guess_info[PLAY_ID],
|
||||||
|
guessed_number = guess_info[GUESSED_NUMBER],
|
||||||
|
member_name = guess_info[MEMBER_NAME]
|
||||||
|
)
|
||||||
|
|
||||||
|
existing_guess = self.__convert_all__(session\
|
||||||
|
.query(Guess)\
|
||||||
|
.filter(Guess.member_id == guess_info[MEMBER_ID], Guess.play_id == guess_info[PLAY_ID]))
|
||||||
|
|
||||||
|
if len(existing_guess) == 0:
|
||||||
|
session.add(guess)
|
||||||
|
session.commit()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
'''
|
||||||
|
Converts the database object into a Dictionary, so that the database object is not passed out of the
|
||||||
|
datastore layer.
|
||||||
|
'''
|
||||||
|
def __convert_all__(self, games):
|
||||||
|
converted_games = []
|
||||||
|
for game in games:
|
||||||
|
game_dict = {}
|
||||||
|
for column in game.__dict__:
|
||||||
|
game_dict[column] = str(getattr(game, column))
|
||||||
|
|
||||||
|
converted_games.append(deepcopy(game_dict))
|
||||||
|
|
||||||
|
return converted_games
|
||||||
|
|
||||||
|
def set_differences(self, pitch_value, play_id):
|
||||||
|
session = DatabaseSession.session
|
||||||
|
games_to_update = self.__convert_all__(session.query(Guess).filter(Guess.play_id == play_id))
|
||||||
|
|
||||||
|
for game in games_to_update:
|
||||||
|
difference = self.calculate_difference(pitch_value, game[GUESSED_NUMBER])
|
||||||
|
session.query(Guess).filter(Guess.member_id == game[MEMBER_ID], Guess.play_id == game[PLAY_ID]).update({Guess.difference: difference})
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
def calculate_difference(self, pitch_value, guess_value):
|
||||||
|
pitched_number = int(pitch_value)
|
||||||
|
possible_value = abs(int(guess_value) - pitched_number)
|
||||||
|
|
||||||
|
if possible_value > 500:
|
||||||
|
return 1000 - possible_value
|
||||||
|
else:
|
||||||
|
return possible_value
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_closest(self, num_to_fetch):
|
||||||
|
session = DatabaseSession.session
|
||||||
|
|
||||||
|
return self.__convert_all__(
|
||||||
|
session\
|
||||||
|
.query(Guess)\
|
||||||
|
.order_by(Guess.difference)\
|
||||||
|
.limit(num_to_fetch)
|
||||||
|
)
|
79
src/main/database_module/play_dao.py
Normal file
79
src/main/database_module/play_dao.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
from src.main.db_session import DatabaseSession
|
||||||
|
from src.main.database_module.database_classes.db_classes import Play
|
||||||
|
|
||||||
|
PLAY_ID = 'play_id'
|
||||||
|
PITCH_VALUE = 'pitch_value'
|
||||||
|
SWING_VALUE = 'swing_value'
|
||||||
|
CREATION_DATE = 'creation_date'
|
||||||
|
|
||||||
|
class PlayDAO():
|
||||||
|
db_string = None
|
||||||
|
session = None
|
||||||
|
Session = None
|
||||||
|
engine = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def insert(self, play_info):
|
||||||
|
session = DatabaseSession.session
|
||||||
|
|
||||||
|
play = Play(
|
||||||
|
play_id = play_info[PLAY_ID],
|
||||||
|
pitch_value = play_info[PITCH_VALUE] if PITCH_VALUE in play_info else None,
|
||||||
|
swing_value = play_info[SWING_VALUE] if SWING_VALUE in play_info else None,
|
||||||
|
creation_date = play_info[CREATION_DATE]
|
||||||
|
)
|
||||||
|
|
||||||
|
session.add(play)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
def get_play_by_id(self, input_id):
|
||||||
|
session = DatabaseSession.session
|
||||||
|
return self.__convert_all__(session.query(Play).filter(Play.play_id == input_id))
|
||||||
|
|
||||||
|
'''
|
||||||
|
Checks to see if there is a play that is currently active or not
|
||||||
|
'''
|
||||||
|
def is_active_play(self):
|
||||||
|
return self.get_active_play() != None
|
||||||
|
|
||||||
|
def get_active_play(self):
|
||||||
|
session = DatabaseSession.session
|
||||||
|
plays = self.__convert_all__(session.query(Play).filter(Play.pitch_value == None))
|
||||||
|
|
||||||
|
if len(plays) > 1:
|
||||||
|
raise AssertionError("More than one active play! Can't continue!")
|
||||||
|
elif len(plays) == 0:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return plays[0]
|
||||||
|
|
||||||
|
def resolve_play(self, input_pitch, input_swing):
|
||||||
|
session = DatabaseSession.session
|
||||||
|
active_id = self.get_active_play()
|
||||||
|
|
||||||
|
session\
|
||||||
|
.query(Play)\
|
||||||
|
.filter(Play.pitch_value == None)\
|
||||||
|
.update({Play.pitch_value: input_pitch, Play.swing_value: input_swing})
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return active_id
|
||||||
|
|
||||||
|
'''
|
||||||
|
Converts the database object into a Dictionary, so that the database object is not passed out of the
|
||||||
|
datastore layer.
|
||||||
|
'''
|
||||||
|
def __convert_all__(self, plays):
|
||||||
|
converted_plays = []
|
||||||
|
for play in plays:
|
||||||
|
play_dict = {}
|
||||||
|
for column in play.__dict__:
|
||||||
|
play_dict[column] = str(getattr(play, column))
|
||||||
|
|
||||||
|
converted_plays.append(deepcopy(play_dict))
|
||||||
|
|
||||||
|
return converted_plays
|
26
src/main/db_session.py
Normal file
26
src/main/db_session.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append('../../../../../src')
|
||||||
|
|
||||||
|
from src.main.configs import Configs, DATABASE_USERNAME, DATABASE_PASSWORD, DATABASE_HOST, DATABASE_NAME
|
||||||
|
|
||||||
|
'''
|
||||||
|
Stores a database session for use throughout the application. Must be initialized at startup before any database calls
|
||||||
|
are made and AFTER the Configurations are setup.
|
||||||
|
|
||||||
|
This shouldn't need to be touched after startup. To use, see the sqlalchemy docs...or just start by calling Session()
|
||||||
|
and then use it to handle the necessary CRUD operations.
|
||||||
|
|
||||||
|
You should NOT instantiate this in any method except the main application runner
|
||||||
|
'''
|
||||||
|
class DatabaseSession():
|
||||||
|
session = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
config_map = Configs.configs
|
||||||
|
db_string = 'postgresql://%s:%s@%s/%s' % \
|
||||||
|
(config_map[DATABASE_USERNAME], config_map[DATABASE_PASSWORD], config_map[DATABASE_HOST], config_map[DATABASE_NAME])
|
||||||
|
Session = sessionmaker(create_engine(db_string))
|
||||||
|
DatabaseSession.session = Session()
|
0
src/main/discord_module/__init__.py
Normal file
0
src/main/discord_module/__init__.py
Normal file
146
src/main/discord_module/bot_runner.py
Normal file
146
src/main/discord_module/bot_runner.py
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
import discord
|
||||||
|
import uuid
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from src.main.configs import Configs
|
||||||
|
from src.main.database_module.guess_dao import GuessDAO, GUESSED_NUMBER, MEMBER_ID, MEMBER_NAME
|
||||||
|
from src.main.database_module.play_dao import PlayDAO, PLAY_ID, CREATION_DATE
|
||||||
|
from src.main.db_session import DatabaseSession
|
||||||
|
from src.main.discord_module.leaderboard_config import LeaderboardConfig
|
||||||
|
|
||||||
|
play_dao = None
|
||||||
|
guess_dao = None
|
||||||
|
bot = discord.Client()
|
||||||
|
|
||||||
|
@bot.event
|
||||||
|
async def on_ready():
|
||||||
|
print('Logged in as')
|
||||||
|
print(bot.user.name)
|
||||||
|
print(bot.user.id)
|
||||||
|
print('------')
|
||||||
|
|
||||||
|
@bot.event
|
||||||
|
async def on_message(message):
|
||||||
|
if message.author == bot.user:
|
||||||
|
return
|
||||||
|
|
||||||
|
content = message.content
|
||||||
|
|
||||||
|
'''
|
||||||
|
Sets up the next set of guesses.
|
||||||
|
'''
|
||||||
|
if content.startswith('!ghostball'):
|
||||||
|
if play_dao.is_active_play():
|
||||||
|
await bot.send_message(message.channel, "Um, I think there's already an active play. Could you close that one first, please?")
|
||||||
|
else:
|
||||||
|
play_object = {PLAY_ID : uuid.uuid4(), CREATION_DATE : datetime.datetime.now()}
|
||||||
|
play_dao.insert(play_object)
|
||||||
|
|
||||||
|
await bot.send_message(message.channel, "@everyone, pitch is in! Send me your guesses with a !guess command.")
|
||||||
|
|
||||||
|
if content.startswith("!guess"):
|
||||||
|
guess_value = __parse_guess__(content)
|
||||||
|
|
||||||
|
if not play_dao.is_active_play():
|
||||||
|
await bot.send_message(message.channel, "Hey, there's no active play! Start one up first with !ghostball.")
|
||||||
|
else:
|
||||||
|
play = play_dao.get_active_play()
|
||||||
|
guess_object = {PLAY_ID: play['play_id'],
|
||||||
|
MEMBER_ID: str(message.author.id),
|
||||||
|
GUESSED_NUMBER: guess_value,
|
||||||
|
MEMBER_NAME: str(message.author.name)}
|
||||||
|
|
||||||
|
if guess_dao.insert(guess_object):
|
||||||
|
await bot.add_reaction(message, emoji="\N{THUMBS UP SIGN}")
|
||||||
|
|
||||||
|
# Closes off the active play to be ready for the next set
|
||||||
|
if content.startswith('!resolve'):
|
||||||
|
# try:
|
||||||
|
pitch_value, swing_value = __parse_resolve_play__(content)
|
||||||
|
if pitch_value is None or swing_value is None:
|
||||||
|
await bot.send_message(message.channel, "Hey " + "<@" + str(message.author.id) + ">, I'm not sure what you meant. "
|
||||||
|
"You need real, numeric, values for this command to work. "
|
||||||
|
"Use !resolve <pitch number> <swing_number> and try again.")
|
||||||
|
|
||||||
|
# Check if we have an active play
|
||||||
|
if not play_dao.is_active_play():
|
||||||
|
await bot.send_message(message.channel, "You confused me. There's no active play so I have nothing to close!")
|
||||||
|
else:
|
||||||
|
play = play_dao.resolve_play(pitch_value, swing_value)
|
||||||
|
guess_dao.set_diff erences(pitch_value, play['play_id'])
|
||||||
|
|
||||||
|
await bot.send_message(message.channel,
|
||||||
|
"You got it boss. Closed this play, no further guesses allowed!")
|
||||||
|
|
||||||
|
# Likely due to too few parameters but could be any number of things
|
||||||
|
# except :
|
||||||
|
# await bot.send_message(message.channel, "Hey " + "<@" + str(message.author.id) + ">, you confused me with that message. "
|
||||||
|
# "To close an active pitch, the proper command is !resolve <pitch number> <swing_number>. "
|
||||||
|
# "Use that format and try again, ok?")
|
||||||
|
|
||||||
|
if content.startswith('!leaderboard'):
|
||||||
|
leaderboard_config = __parse_leaderboard_message__(content)
|
||||||
|
|
||||||
|
if leaderboard_config.should_sort_by_pure_closest():
|
||||||
|
values = guess_dao.fetch_closest(10)
|
||||||
|
|
||||||
|
string_to_send = ''
|
||||||
|
for i, value in enumerate(values):
|
||||||
|
string_to_send += str(i + 1) + ': ' + value['member_name'] + ', ' + value['difference'] + '\n'
|
||||||
|
|
||||||
|
await bot.send_message(message.channel, string_to_send)
|
||||||
|
|
||||||
|
elif leaderboard_config.should_sort_by_best_average():
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
await bot.send_message(message.channel, "I don't understand that leaderboard command, sorry! I know it's a little confusing, so send me"
|
||||||
|
" a !help message if you want the full rundown for how to make this work!")
|
||||||
|
|
||||||
|
if content.startswith('!help'):
|
||||||
|
help_message = __get_help_message__()
|
||||||
|
recipient = await bot.get_user_info(message.author.id)
|
||||||
|
await bot.send_message(recipient, help_message)
|
||||||
|
|
||||||
|
def __get_help_message__():
|
||||||
|
# Start message with person who asked for help
|
||||||
|
help_message = "Hey! I can be instructed to do any number of things! Use the following commands: \n" \
|
||||||
|
"!guess <NUMBER> --- This will add your guess to the currently active play. " \
|
||||||
|
"I will give you a thumbs up if everything worked!\n" \
|
||||||
|
"!ghostball --- Starts a new play. I'll let you know if this didn't work for some reason!\n" \
|
||||||
|
"!help --- You just asked for this. If you ask for it again, I'll repeat myself.\n" \
|
||||||
|
"!resolve <PITCH_NUMBER> <SWING NUMBER>--- Uses the pitch number and real swing number " \
|
||||||
|
"to figure out who was closest and ends the active play.\n" \
|
||||||
|
"<HELP MESSAGE NEEDS DOCUMENTATION FOR LEADERBOARD COMMAND>\n"
|
||||||
|
|
||||||
|
return help_message
|
||||||
|
|
||||||
|
|
||||||
|
def __parse_leaderboard_message__(message_content):
|
||||||
|
return LeaderboardConfig(message_content)
|
||||||
|
|
||||||
|
def __parse_guess__(message_content):
|
||||||
|
pieces = message_content.split(' ')
|
||||||
|
try:
|
||||||
|
return pieces[1]
|
||||||
|
except TypeError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __parse_resolve_play__(message_content):
|
||||||
|
pieces = message_content.split(' ')
|
||||||
|
try:
|
||||||
|
return pieces[1], pieces[2]
|
||||||
|
except TypeError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
args = sys.argv
|
||||||
|
token = args[1]
|
||||||
|
file_path = args[2]
|
||||||
|
|
||||||
|
configs = Configs(file_path)
|
||||||
|
databaseSession = DatabaseSession()
|
||||||
|
play_dao = PlayDAO()
|
||||||
|
guess_dao = GuessDAO()
|
||||||
|
bot.run(token)
|
15
src/main/discord_module/leaderboard_config.py
Normal file
15
src/main/discord_module/leaderboard_config.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class LeaderboardConfig():
|
||||||
|
closest = True
|
||||||
|
def __init__(self, message_content):
|
||||||
|
pieces = message_content.split(' ')
|
||||||
|
if len(pieces) == 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
if pieces[1] == 'average':
|
||||||
|
self.closest = False
|
||||||
|
|
||||||
|
def should_sort_by_pure_closest(self):
|
||||||
|
return self.closest
|
||||||
|
|
||||||
|
def should_sort_by_best_average(self):
|
||||||
|
return not self.closest
|
0
src/test/__init__.py
Normal file
0
src/test/__init__.py
Normal file
Loading…
Reference in New Issue
Block a user