Compare commits

..

4 Commits

Author SHA1 Message Date
Zed
3525ea42e1 Jack's Changes (#1)
First merge after adding branch

Co-authored-by: c0de <c0de@c0de.dev>
Reviewed-on: #1
Co-authored-by: Zed <benolken5@gmail.com>
Co-committed-by: Zed <benolken5@gmail.com>
2024-04-23 22:19:20 +00:00
f1db0f62fc Await discord user interaction with name get 2022-12-10 17:57:53 -06:00
fd5f5a7e7a I Completely disagree with this decision.
Remove the table for the original output
2022-12-10 12:36:36 -06:00
fc2fe0a396 update help 2022-12-10 12:31:56 -06:00
11 changed files with 124 additions and 100 deletions

View File

@@ -6,7 +6,7 @@
FROM python:3.10-alpine3.16 AS build
RUN pip install --no-cache-dir discord peewee beautifultable
RUN pip install --no-cache-dir discord peewee
WORKDIR /app
COPY . .
@@ -15,4 +15,4 @@ FROM build AS run
ENV discord_token ""
ENV database_path "/tmp/baseball.db"
CMD ["python", "/app/main.py"]
CMD ["python", "-u", "/app/main.py"]

View File

@@ -8,7 +8,6 @@ discord = "*"
peewee = "*"
pylint = "*"
black = "*"
beautifultable = "*"
[dev-packages]

33
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "171e06b48e5905ea64caab54728c14bd65292a2957b33964c688f2172e677b62"
"sha256": "b6fb0d9cfe588eab84db4024e6b319681e9e70d00c74282b6722fe283ac3e348"
},
"pipfile-spec": 6,
"requires": {
@@ -106,7 +106,7 @@
"sha256:f973157ffeab5459eefe7b97a804987876dd0a55570b8fa56b4e1954bf11329b",
"sha256:ff25f48fc8e623d95eca0670b8cc1469a83783c924a602e0fbd47363bb54aaca"
],
"markers": "python_version >= '3.6'",
"markers": "python_full_version >= '3.6.0'",
"version": "==3.8.3"
},
"aiosignal": {
@@ -130,7 +130,7 @@
"sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15",
"sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"
],
"markers": "python_version >= '3.6'",
"markers": "python_full_version >= '3.6.0'",
"version": "==4.0.2"
},
"attrs": {
@@ -141,14 +141,6 @@
"markers": "python_version >= '3.5'",
"version": "==22.1.0"
},
"beautifultable": {
"hashes": [
"sha256:040bc987444965678f4ffdfa2f17ac357f1a13e5875b161c9a1899b375319d17",
"sha256:b34053a581976c4c23064bb0e918a7f6f22273cf196c787946db323a6a2b7d84"
],
"index": "pypi",
"version": "==1.1.0"
},
"black": {
"hashes": [
"sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320",
@@ -172,7 +164,7 @@
"sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845",
"sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"
],
"markers": "python_version >= '3.6'",
"markers": "python_full_version >= '3.6.0'",
"version": "==2.1.1"
},
"click": {
@@ -333,7 +325,7 @@
"sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325",
"sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"
],
"markers": "python_version >= '3.6'",
"markers": "python_full_version >= '3.6.0'",
"version": "==0.7.0"
},
"multidict": {
@@ -425,11 +417,11 @@
},
"pathspec": {
"hashes": [
"sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5",
"sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"
"sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6",
"sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"
],
"markers": "python_version >= '3.7'",
"version": "==0.10.2"
"version": "==0.10.3"
},
"peewee": {
"hashes": [
@@ -467,16 +459,9 @@
"sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b",
"sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"
],
"markers": "python_version >= '3.6'",
"markers": "python_full_version >= '3.6.0'",
"version": "==0.11.6"
},
"wcwidth": {
"hashes": [
"sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",
"sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"
],
"version": "==0.2.5"
},
"wrapt": {
"hashes": [
"sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3",

View File

@@ -4,6 +4,8 @@
# pylint: disable=missing-module-docstring
import logging
from database.models import database, GameModel as Game
@@ -24,6 +26,18 @@ class BaseGameManager:
# Discord client instance
self.discord = None
logger = logging.getLogger()
console = logging.StreamHandler()
format_str = '%(asctime)s\t%(levelname)s -- %(processName)s %(filename)s:%(lineno)s -- %(message)s'
console.setFormatter(logging.Formatter(format_str))
logger.addHandler(console)
logger.setLevel(logging.DEBUG)
self.logger = logger
def __enter__(self):
"""
Allows use of `with Game() as game` for try/except statements

30
game/clear.py Normal file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python3
# Copyright 2022 - c0de <c0de@c0de.dev>
# Licensed under the MIT License (https://opensource.org/licenses/MIT)
# pylint: disable=missing-module-docstring,too-few-public-methods
from database.models import PlayerModel as Player
from game.base import BaseGameManager
class ClearManager(BaseGameManager):
"""Commands that run when a player clears the session leaderboard"""
def __init__(self):
super().__init__()
self.commands.append(("clear", self.clear))
async def clear(self):
"""Clear command - Clears the session scoreboard"""
players = Player.select(Player.player_id, Player.total_points)
for player in players:
player.total_points = 0
Player.bulk_update(players, fields=[Player.total_points])
clear_message = "The score has been cleared!"
await self.message.channel.send(clear_message)

View File

@@ -6,49 +6,26 @@
import datetime
from beautifultable import BeautifulTable
from database.models import GameModel as Game, GuessModel as Guess
from game.base import BaseGameManager
from game.process_guess import ProcessGuess
class EndGameManager(BaseGameManager):
"""Commands that run at the end of a game"""
"""Commands that run at the end of a play"""
def __init__(self):
super().__init__()
self.commands.append(("resolve", self.stop))
def __stop_args__(self):
pieces = self.message.content.split()
if len(pieces) == 2:
return pieces[1], False, None, None
if len(pieces) == 4:
return pieces[1], True, pieces[2], pieces[3]
return None, False, None, None
async def update_pitch_value(self):
"""Update game state database for closing arguments"""
# Determine arguments
pitch_value, has_batter, batter_id, batter_guess = self.__stop_args__()
pitch_value = self.message.content.split()[1]
if not pitch_value:
return await self.message.channel.send(
f"Invalid command <@{ str(self.message.author.id) }>!"
)
if has_batter:
player_id = batter_id[3:]
Guess.create(
game_id=self.game.game_id,
player_id=player_id,
player_name=self.discord.get_user(int(player_id).name),
guess=int(batter_guess),
).save()
# Save the pitch value
Game.update(
{
@@ -77,40 +54,33 @@ class EndGameManager(BaseGameManager):
)
# Discard the game if there weren't enough players
if guess_count < 3:
if guess_count < 2:
self.game = None
self.is_running = False
return await self.message.channel.send(
("Play closed!\n" + "However, there were not enough participants.")
)
message = "Closed this play! Here are the results:"
message += "\n```\n"
table = BeautifulTable()
table.column_headers = [
"PLAYER",
"GUESS",
"DIFFERENCE",
"POINTS GAINED",
"TOTAL POINTS",
]
message = (
"Closed this play! Here are the results\n"
+ "__PLAYER | GUESS | DIFFERENCE | POINTS GAINED | TOTAL POINTS__\n"
)
pitch_value = await self.update_pitch_value()
guess_processor = ProcessGuess(
game=self, pitch_value=pitch_value, message=table
game=self, pitch_value=pitch_value, message=message
)
(
table,
message,
closest_player_id,
furthest_player_id,
) = guess_processor.process_guesses()
message += str(table)
message += "\n```\n"
message += f"Congrats <@{closest_player_id}>! You were the closest!\n"
message += f"Sorry <@{furthest_player_id}>, you were way off\n"
message += (
f"\nCongrats <@{closest_player_id}>! You were the closest!\n"
+ f"Sorry <@{furthest_player_id}>, you were way off"
)
await self.message.channel.send(message)

View File

@@ -24,10 +24,9 @@ class HelpManager(BaseGameManager):
+ "!guess - While a game is running, add a guess"
+ " (or update an existing one) from 1-1000\n"
+ "!resolve <value> - 1-1000 to resolve the game\n"
+ " You can also add a batter's guess with: "
+ "!resolve <value> <discord id #> <guess>\n"
+ "!clear - Clear the session scoreboard\n"
+ "!points - Shows a table of the most recent players, and their scores\n"
+ "!reset - Removes all the guesses"
+ "!reset - Removes all players and total points\n"
+ "!help - Shows this message"
)

View File

@@ -16,10 +16,11 @@ from game.guess import GuessManager
from game.points import PointsManager
from game.reset import ResetManager
from game.help import HelpManager
from game.clear import ClearManager
class GameManager(
NewGameManager, EndGameManager, GuessManager, PointsManager, ResetManager, HelpManager
NewGameManager, EndGameManager, GuessManager, PointsManager, ResetManager, HelpManager, ClearManager
):
"""
Represents what this bot is able to do on a channel (or DMs)

View File

@@ -13,7 +13,7 @@ class NewGameManager(BaseGameManager):
def __init__(self):
super().__init__()
self.commands.append(("braveball", self.start))
self.commands.append(("bb", self.start))
async def start(self):
"""

View File

@@ -4,14 +4,12 @@
# pylint: disable=not-an-iterable,missing-module-docstring,too-few-public-methods
from beautifultable import BeautifulTable
from database.models import PlayerModel as Player
from game.base import BaseGameManager
class PointsManager(BaseGameManager):
"""Commands that run when a player makes a guess"""
"""Commands that run when a player wants to view the session leaderboard"""
def __init__(self):
super().__init__()
@@ -25,23 +23,22 @@ class PointsManager(BaseGameManager):
message = (
"\nPlayers, who played recently, with their points highest to lowest\n\n"
)
message += "```\n"
table = BeautifulTable()
table.column_headers = ["Player", "Total Points", "Last Played"]
message += "Player | Total Points | Last Played\n"
players = Player.select(
Player.player_name, Player.total_points, Player.last_update
).order_by(Player.last_update.desc(), Player.total_points.desc())
).order_by(Player.total_points.desc())
for player in players:
table.rows.append([
message += (
" | ".join(
[
player.player_name,
str(player.total_points),
str(player.last_update)[:-10],
])
message += str(table)
message += "\n```\n"
]
)
+ "\n"
)
return await self.message.channel.send(message)

View File

@@ -40,6 +40,7 @@ class ProcessGuess:
Player.player_id,
Player.player_name,
Player.total_points,
Guess.difference
)
.join(Player)
.where(
@@ -71,14 +72,25 @@ class ProcessGuess:
def get_difference(self, guess=None):
"""Difference calculation, includes "loop over" effect"""
self.game_manager.logger.debug("get_difference")
self.game_manager.logger.debug(guess if guess else "")
if not guess:
guess = self.guess.guess
self.game_manager.logger.debug(f"guess: {guess}")
difference = abs(guess - self.pitch_value)
self.game_manager.logger.debug(f"Difference:{difference}")
if difference > 500:
difference = 1000 - difference
self.game_manager.logger.debug("Diff loop over 500")
self.game_manager.logger.debug(f"{difference}")
self.difference = difference
return self.difference
@@ -88,32 +100,51 @@ class ProcessGuess:
they are (within range of 0-500) to the pitch_value
"""
self.game_manager.logger.debug("> get_difference_score")
self.game_manager.logger.debug(self.difference)
if self.difference == 0:
self.difference_score = 15
self.game_manager.logger.debug("0 Diff")
elif self.difference > 0 and self.difference < 21:
self.difference_score = 8
self.game_manager.logger.debug("0 to 20 diff")
elif self.difference > 20 and self.difference < 51:
self.difference_score = 5
self.game_manager.logger.debug("21 to 50 Diff")
elif self.difference > 50 and self.difference < 101:
self.difference_score = 3
self.game_manager.logger.debug("51 to 100 Diff")
elif self.difference > 100 and self.difference < 151:
self.difference_score = 2
self.game_manager.logger.debug("101 to 150 Diff")
elif self.difference > 150 and self.difference < 201:
self.difference_score = 1
self.game_manager.logger.debug("151 to 200 Diff")
elif self.difference > 200 and self.difference < 495:
self.difference_score = 0
self.game_manager.logger.debug("Diff too big")
else:
self.difference_score = -5
self.game_manager.logger.debug("Big succ")
return self.difference_score
def get_winner_loser(self):
"""Determine which guesses are closest and furthest from the pitch_value"""
self.game_manager.logger.debug("> get_winner_loser")
guess_values = [record.guess for record in self.get_guesses()]
self.game_manager.logger.debug(", ".join([str(guess) for guess in guess_values]))
# Closest to the pitch_value
winner = min(guess_values, key=lambda guess: self.get_difference(guess))
self.game_manager.logger.debug(f"winner: {winner}")
# Furthest from the pitch_value
loser = max(guess_values, key=lambda guess: self.get_difference(guess))
self.game_manager.logger.debug(f"loser: {loser}")
return winner, loser
@@ -129,20 +160,17 @@ class ProcessGuess:
for guess in self.get_guesses():
self.guess = guess
self.game_manager.logger.debug(f"Current guess: {guess}")
difference = self.get_difference()
difference_score = self.get_difference_score()
self.update_difference_value()
self.update_player_total_points()
self.message.rows.append(
[
guess.player.player_name,
guess.guess,
difference,
difference_score,
guess.player.total_points + difference_score,
]
)
self.message += f"{guess.player.player_name} | {guess.guess} | {difference} | {difference_score} | {(guess.player.total_points + difference_score)}\n"
self.game_manager.logger.debug(f"new total: {(guess.player.total_points + difference_score)}")
if guess.guess == winner:
closest_player_id = guess.player.player_id
@@ -150,4 +178,5 @@ class ProcessGuess:
if guess.guess == loser:
furthest_player_id = guess.player.player_id
self.game_manager.logger.debug(self.message)
return self.message, closest_player_id, furthest_player_id