From 0a71b875723ce233e1f7018fde85b23e0b228edb Mon Sep 17 00:00:00 2001 From: Stephen George Date: Fri, 13 Oct 2023 09:48:06 -0500 Subject: [PATCH 1/6] Rivary messages --- backend/command_parser.py | 3 +- backend/commands/enter_score.py | 14 ++++++-- backend/commands/record.py | 61 +++++++++++++++++++++++++++++++++ backend/db.py | 9 +++++ backend/utility.py | 32 +++++++++++++---- start_bot.py | 4 +++ 6 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 backend/commands/record.py create mode 100644 start_bot.py diff --git a/backend/command_parser.py b/backend/command_parser.py index f948ad6..ce06b4b 100644 --- a/backend/command_parser.py +++ b/backend/command_parser.py @@ -1,5 +1,5 @@ from backend import configs -from backend.commands import enter_score, help, group, leaderboard, week_matches, user_stats, group_analysis, matchup_history +from backend.commands import enter_score, help, group, leaderboard, week_matches, user_stats, group_analysis, matchup_history, record from backend.commands.command_message import CommandMessage @@ -48,6 +48,7 @@ def determine_command(lctx, message_object): enter_score, leaderboard, week_matches, + record, user_stats, group_analysis, matchup_history diff --git a/backend/commands/enter_score.py b/backend/commands/enter_score.py index b1d54e8..5da5004 100644 --- a/backend/commands/enter_score.py +++ b/backend/commands/enter_score.py @@ -1,4 +1,4 @@ -from backend import slack_util, configs, db +from backend import slack_util, configs, db, utility from backend.commands import group BLOCK_NEW_SCORES_MSG = "Sorry, not accepting any scores at this time." @@ -83,7 +83,17 @@ def handle_message(lctx, command_object): slack_util.post_message(lctx, 'Entered into db', lctx.configs[configs.COMMISSIONER_SLACK_ID]) player = db.get_player_by_id(lctx.league_name, users['winner_id']) group_msg = group.build_message_for_group(lctx, player.grouping) - slack_util.post_message(lctx, group_msg, command_object.channel) + rivary_msg = build_message_for_rivary_record(lctx, users['winner_id'], users['loser_id']) + slack_util.post_message(lctx, '{}\n{}'.format(rivary_msg, group_msg), command_object.channel) + + +def build_message_for_rivary_record(lctx, p1_id, p2_id): + record = utility.get_players_record(lctx, p1_id, p2_id) + p1 = db.get_player_by_id(lctx.league_name, p1_id) + p2 = db.get_player_by_id(lctx.league_name, p2_id) + include_oof = True if abs(record['p1_wins'] - record['p2_wins']) > 5 else False + return '_{} is now {}-{} against {}._{}'.format( + p1.name, record['p1_wins'], record['p2_wins'], p2.name, ' :oof:' if include_oof else '') def parse_first_slack_id(message): diff --git a/backend/commands/record.py b/backend/commands/record.py new file mode 100644 index 0000000..bf53554 --- /dev/null +++ b/backend/commands/record.py @@ -0,0 +1,61 @@ +from backend import slack_util, configs, db, utility +NO_MATCH_MSG = "I couldn't find a match between you two." + +def handles_message(lctx, command_object): + is_admin = command_object.user == lctx.configs[configs.COMMISSIONER_SLACK_ID] and command_object.is_dm() + if not is_admin and command_object.channel != lctx.configs[configs.COMPETITION_CHANNEL_SLACK_ID]: + return False + if command_object.text.upper().startswith('RECORD') and not is_admin: + return True + return False + + +def get_format_message(lctx): + return 'aaaaaaaa' + + +def handle_message(lctx, command_object): + players = parse_users(command_object) + if players: + if players['first_id'] == players['second_id']: + slack_util.post_message(lctx, 'You are attempting to get the match record between yourself and yourself :bigbrain:', command_object.channel) + return + record = utility.get_players_record(lctx, players['first_id'], players['second_id']) + p1 = db.get_player_by_id(lctx.league_name, players['first_id']) + p2 = db.get_player_by_id(lctx.league_name, players['second_id']) + + if record['p1_wins'] + record['p2_wins'] == 0: + slack_util.post_message(lctx, '{} and {} never played a match together.'.format(p1.name, p2.name), command_object.channel) + return + + if record['p1_wins'] != record['p2_wins']: + better_player = [p1, record['p1_wins']] if record['p1_wins'] > record['p2_wins'] else [p2, record['p2_wins']] + worse_player = [p1, record['p1_wins']] if record['p1_wins'] < record['p2_wins'] else [p2, record['p2_wins']] + slack_util.post_message(lctx, '{} is {}-{} against {}.'.format(better_player[0].name, better_player[1], + worse_player[1], worse_player[0].name), command_object.channel) + else: + slack_util.post_message(lctx, '{} and {} are tied at {} win(s) each.'.format(p1.name, p2.name, record['p1_wins']), command_object.channel) + + + + +def parse_first_slack_id(message): + return message[message.index('<@') + 2: message.index('>')] + + +def parse_second_slack_id(message): + message = message[message.index('>') + 1:] + return parse_first_slack_id(message) + + +def parse_users(command_object): + command = command_object.text + try: + player1 = parse_first_slack_id(command) + player2 = parse_second_slack_id(command) + return { + 'first_id': player1, + 'second_id': player2 + } + except: + return diff --git a/backend/db.py b/backend/db.py index ff6044b..9c81b7b 100644 --- a/backend/db.py +++ b/backend/db.py @@ -285,6 +285,15 @@ def get_matches(league_name): return [Match.from_db(m) for m in rows] +def get_matches_between_players(league_name, p1_id, p2_id): + conn = get_connection(league_name) + c = conn.cursor() + c.execute('SELECT rowid, * FROM match WHERE (player_1,player_2) IN ((?, ?),(?, ?))', (p1_id, p2_id, p2_id, p1_id)) + rows = c.fetchall() + conn.close() + + return [Match.from_db(m) for m in rows] + def get_matches_for_season(league_name, season): conn = get_connection(league_name) diff --git a/backend/utility.py b/backend/utility.py index cbab6dc..b1c2489 100644 --- a/backend/utility.py +++ b/backend/utility.py @@ -52,7 +52,7 @@ def gather_scores(group_matches): return tie_breaker.order_players(players, group_matches) -def print_season_markup(lctx, season = None): +def print_season_markup(lctx, season=None): if season is None: season = db.get_current_season(lctx.league_name) all_matches = db.get_matches_for_season(lctx.league_name, season) @@ -95,7 +95,8 @@ def print_season_markup(lctx, season = None): players = [x for x in players if x['player_id'] is not None] if len(players) > i: p = players[i] - output += get_player_name(all_players, p['player_id']) + ' ' + str(p['m_w']) + '-' + str(p['m_l']) # + ' (' + str(p['s_w']) + '-' + str(p['s_l']) + ')' + output += get_player_name(all_players, p['player_id']) + ' ' + str(p['m_w']) + '-' + str( + p['m_l']) # + ' (' + str(p['s_w']) + '-' + str(p['s_l']) + ')' else: output += ' ' output += '|' @@ -103,10 +104,10 @@ def print_season_markup(lctx, season = None): for grouping in groupings: group_matches = [m for m in all_matches if m.grouping == grouping] - output += '\nh2. Group '+grouping+'\n' + output += '\nh2. Group ' + grouping + '\n' matches_by_week = {} for week in weeks: - output += '||'+str(week) + output += '||' + str(week) matches_by_week[week] = [m for m in group_matches if m.week == week] output += '||\n' @@ -115,7 +116,9 @@ def print_season_markup(lctx, season = None): if i >= len(matches_by_week[week]): break m = matches_by_week[week][i] - output += '|' + get_player_print(all_players, m.player_1_id, m) + '\\\\' + get_player_print(all_players, m.player_2_id, m) + output += '|' + get_player_print(all_players, m.player_1_id, m) + '\\\\' + get_player_print(all_players, + m.player_2_id, + m) output += '|\n' return output @@ -131,5 +134,22 @@ def get_players_dictionary(lctx): def replace_message_variables(lctx, message): message = message.replace('@bot_name', '<@{}>'.format(lctx.configs[configs.BOT_SLACK_USER_ID])) - message = message.replace('#competition_channel', '<#{}>'.format(lctx.configs[configs.COMPETITION_CHANNEL_SLACK_ID])) + message = message.replace('#competition_channel', + '<#{}>'.format(lctx.configs[configs.COMPETITION_CHANNEL_SLACK_ID])) return message + + +def get_players_record(lctx, p1_id, p2_id): + rivary_matches = db.get_matches_between_players(lctx.league_name, p1_id, p2_id) + p1_wins = 0 + p2_wins = 0 + if len(rivary_matches) == 0: + return {'p1_wins': 0, 'p2_wins': 0} + + for m in rivary_matches: + if m.winner_id == p1_id: + p1_wins += 1 + elif m.winner_id == p2_id: + p2_wins += 1 + return {'p1_wins': p1_wins, 'p2_wins': p2_wins} + diff --git a/start_bot.py b/start_bot.py new file mode 100644 index 0000000..0bbd76c --- /dev/null +++ b/start_bot.py @@ -0,0 +1,4 @@ +from backend.leaguebot import LeagueBot + +if __name__ == "__main__": + LeagueBot('StephenLeague').start_bot() \ No newline at end of file From 3ee59a0c4c9410e508774d5b10a81878baca5a27 Mon Sep 17 00:00:00 2001 From: Stephen George Date: Fri, 13 Oct 2023 09:50:37 -0500 Subject: [PATCH 2/6] Update bot --- backend/commands/help.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/commands/help.py b/backend/commands/help.py index 8b9d35e..eed7ed0 100644 --- a/backend/commands/help.py +++ b/backend/commands/help.py @@ -22,6 +22,7 @@ def channel_help(lctx): message = message + '\n`{} group [a, b, c, etc]` - see the current rankings of a group'.format(bot_name) message = message + '\n`{} analyze group [a, b, c, etc]` - see a summary of who can still get promoted and relegated'.format(bot_name) message = message + '\n`{} leaderboard [matches, sets] [won, played, winrate] [all]` - see the leaderboard, counting matches or sets, sorted by wins, # played, or winrate. 20 match minimum for winrate. This will only include active players by default. Add `all` to include all historical players.'.format(bot_name) + message = message + '\n`{} record @player1 @player2 - shows the win / loss ratio of player1 vs player2.'.format(bot_name) # message = message + '\n`{} loserboard` - see the loserboard, sorted by winrate'.format(bot_name) # message = message + '\n`{} matches for week` - see all matches occuring this week in all groups'.format(bot_name) return message From dbd6f7c7d3c36ffcb25f72437dda6e1549b9491a Mon Sep 17 00:00:00 2001 From: Stephen George Date: Fri, 13 Oct 2023 09:56:03 -0500 Subject: [PATCH 3/6] Add to help command --- backend/commands/help.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/commands/help.py b/backend/commands/help.py index eed7ed0..84e357a 100644 --- a/backend/commands/help.py +++ b/backend/commands/help.py @@ -22,7 +22,7 @@ def channel_help(lctx): message = message + '\n`{} group [a, b, c, etc]` - see the current rankings of a group'.format(bot_name) message = message + '\n`{} analyze group [a, b, c, etc]` - see a summary of who can still get promoted and relegated'.format(bot_name) message = message + '\n`{} leaderboard [matches, sets] [won, played, winrate] [all]` - see the leaderboard, counting matches or sets, sorted by wins, # played, or winrate. 20 match minimum for winrate. This will only include active players by default. Add `all` to include all historical players.'.format(bot_name) - message = message + '\n`{} record @player1 @player2 - shows the win / loss ratio of player1 vs player2.'.format(bot_name) + message = message + '\n`{} record @player1 @player2` - shows the win / loss ratio of player1 vs player2.'.format(bot_name) # message = message + '\n`{} loserboard` - see the loserboard, sorted by winrate'.format(bot_name) # message = message + '\n`{} matches for week` - see all matches occuring this week in all groups'.format(bot_name) return message From cb71ab8f1f3be43b299347613df222082b10124c Mon Sep 17 00:00:00 2001 From: Stephen George <130091513+stephengeorge8@users.noreply.github.com> Date: Fri, 13 Oct 2023 09:59:48 -0500 Subject: [PATCH 4/6] Delete start_bot.py --- start_bot.py | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 start_bot.py diff --git a/start_bot.py b/start_bot.py deleted file mode 100644 index 0bbd76c..0000000 --- a/start_bot.py +++ /dev/null @@ -1,4 +0,0 @@ -from backend.leaguebot import LeagueBot - -if __name__ == "__main__": - LeagueBot('StephenLeague').start_bot() \ No newline at end of file From dc620450e1151eb65243141043affb101d551e77 Mon Sep 17 00:00:00 2001 From: Stephen George Date: Fri, 13 Oct 2023 10:59:12 -0500 Subject: [PATCH 5/6] rivarly spelling fix --- backend/commands/enter_score.py | 6 +++--- backend/utility.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/commands/enter_score.py b/backend/commands/enter_score.py index e068319..abfca25 100644 --- a/backend/commands/enter_score.py +++ b/backend/commands/enter_score.py @@ -92,11 +92,11 @@ def handle_message(lctx, command_object): slack_util.post_message(lctx, 'Entered into db', lctx.configs[configs.COMMISSIONER_SLACK_ID]) player = db.get_player_by_id(lctx.league_name, users['winner_id']) group_msg = group.build_message_for_group(lctx, player.grouping) - rivary_msg = build_message_for_rivary_record(lctx, users['winner_id'], users['loser_id']) - slack_util.post_message(lctx, '{}\n{}'.format(rivary_msg, group_msg), command_object.channel) + rivalry_msg = build_message_for_rivalry_record(lctx, users['winner_id'], users['loser_id']) + slack_util.post_message(lctx, '{}\n{}'.format(rivalry_msg, group_msg), command_object.channel) -def build_message_for_rivary_record(lctx, p1_id, p2_id): +def build_message_for_rivalry_record(lctx, p1_id, p2_id): record = utility.get_players_record(lctx, p1_id, p2_id) p1 = db.get_player_by_id(lctx.league_name, p1_id) p2 = db.get_player_by_id(lctx.league_name, p2_id) diff --git a/backend/utility.py b/backend/utility.py index 090bc7a..48c037e 100644 --- a/backend/utility.py +++ b/backend/utility.py @@ -136,13 +136,13 @@ def replace_message_variables(lctx, message): def get_players_record(lctx, p1_id, p2_id): - rivary_matches = db.get_matches_between_players(lctx.league_name, p1_id, p2_id) + rivalry_matches = db.get_matches_between_players(lctx.league_name, p1_id, p2_id) p1_wins = 0 p2_wins = 0 - if len(rivary_matches) == 0: + if len(rivalry_matches) == 0: return {'p1_wins': 0, 'p2_wins': 0} - for m in rivary_matches: + for m in rivalry_matches: if m.winner_id == p1_id: p1_wins += 1 elif m.winner_id == p2_id: From 2bdd1806bf517ceba7902643b23212a65788f89d Mon Sep 17 00:00:00 2001 From: Stephen George Date: Wed, 14 Feb 2024 13:40:38 -0600 Subject: [PATCH 6/6] Fix enter score tests --- backend/commands/record.py | 2 +- start_bot.py | 4 ++++ tests/commands/test_enter_score.py | 12 ++++++++---- tests/commands/test_record.py | 0 4 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 start_bot.py create mode 100644 tests/commands/test_record.py diff --git a/backend/commands/record.py b/backend/commands/record.py index bf53554..930d811 100644 --- a/backend/commands/record.py +++ b/backend/commands/record.py @@ -11,7 +11,7 @@ def handles_message(lctx, command_object): def get_format_message(lctx): - return 'aaaaaaaa' + return 'NA' def handle_message(lctx, command_object): diff --git a/start_bot.py b/start_bot.py new file mode 100644 index 0000000..0bbd76c --- /dev/null +++ b/start_bot.py @@ -0,0 +1,4 @@ +from backend.leaguebot import LeagueBot + +if __name__ == "__main__": + LeagueBot('StephenLeague').start_bot() \ No newline at end of file diff --git a/tests/commands/test_enter_score.py b/tests/commands/test_enter_score.py index 4266ec7..e06ce09 100644 --- a/tests/commands/test_enter_score.py +++ b/tests/commands/test_enter_score.py @@ -1,10 +1,11 @@ from unittest import TestCase from unittest.mock import patch, call -import datetime, time +import datetime from backend import slack_util, configs, db, match_making from backend.commands import enter_score, group from backend.commands.command_message import CommandMessage +from backend.commands.enter_score import build_message_for_rivalry_record from backend.league_context import LeagueContext from tests import test_league_setup @@ -154,10 +155,11 @@ def test_handle_message_good_entry(self, mock_post_message, mock_add_reaction): self.assertEqual(4, tmp[0].sets) mock_add_reaction.assert_called_once_with(lctx, 'comp_channel', 'any_timestamp', enter_score.WORKED_REACTION) + rivary_msg = build_message_for_rivalry_record(lctx, 'playerA2', 'playerA1') group_msg = group.build_message_for_group(lctx, 'A') calls = [ call(lctx, 'Entered into db', 'commish'), - call(lctx, group_msg, 'comp_channel') + call(lctx, '{}\n{}'.format(rivary_msg, group_msg), 'comp_channel') ] mock_post_message.assert_has_calls(calls) @@ -189,10 +191,11 @@ def test_handle_message_no_sets(self, mock_post_message, mock_add_reaction): self.assertEqual(1, tmp[0].sets) mock_add_reaction.assert_called_once_with(lctx, 'comp_channel', 'any_timestamp', enter_score.WORKED_REACTION) + rivary_msg = build_message_for_rivalry_record(lctx, 'playerA2', 'playerA1') group_msg = group.build_message_for_group(lctx, 'A') calls = [ call(lctx, 'Entered into db', 'commish'), - call(lctx, group_msg, 'comp_channel') + call(lctx, '{}\n{}'.format(rivary_msg, group_msg), 'comp_channel') ] mock_post_message.assert_has_calls(calls) @@ -206,10 +209,11 @@ def test_handle_message_no_sets(self, mock_post_message, mock_add_reaction): self.assertEqual(1, tmp[0].sets) mock_add_reaction.assert_called_once_with(lctx, 'comp_channel', 'any_timestamp', enter_score.WORKED_REACTION) + rivary_msg = build_message_for_rivalry_record(lctx, 'playerA1', 'playerA2') group_msg = group.build_message_for_group(lctx, 'A') calls = [ call(lctx, 'Entered into db', 'commish'), - call(lctx, group_msg, 'comp_channel') + call(lctx, '{}\n{}'.format(rivary_msg, group_msg), 'comp_channel') ] mock_post_message.assert_has_calls(calls) diff --git a/tests/commands/test_record.py b/tests/commands/test_record.py new file mode 100644 index 0000000..e69de29