Skip to content

Commit

Permalink
Refactored to introduce operation result and allow ui improvement and… (
Browse files Browse the repository at this point in the history
#17)

* Refactored to introduce operation results and allow ui improvement and web output formatter.

* linting

* linting and extract function for removing prefix

* fix import issue.
  • Loading branch information
DavidWylie authored Jan 8, 2024
1 parent 10b4464 commit 67bed45
Show file tree
Hide file tree
Showing 28 changed files with 440 additions and 220 deletions.
5 changes: 4 additions & 1 deletion roll_witch/dice_bot/event_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ async def on_message(self, message):
roll_string=roll_string,
user=message.author.display_name,
)
await message.channel.send(response)
message_to_send = command.format_output(
roll_result=response, user=message.author.display_name
)
await message.channel.send(message_to_send)
except ValueError:
await message.channel.send(
f" {message.author.display_name}: Invalid Command"
Expand Down
7 changes: 6 additions & 1 deletion roll_witch/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from roll_witch.dice_bot import bot
from roll_witch.web_app import router
import asyncio
Expand All @@ -6,7 +8,10 @@
loop = asyncio.get_event_loop()

loop.run_until_complete(router.start_app())
loop.run_until_complete(bot.start_bot())
if os.getenv("DISABLE_BOT") == "true":
print("Bot is disabled")
else:
loop.run_until_complete(bot.start_bot())
try:
loop.run_forever()
finally:
Expand Down
27 changes: 18 additions & 9 deletions roll_witch/rolling/command/__init__.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
from . import basic, token, regex, shadow_run
from .basic import BasicOperation
from .regex import RegexOperation
from .shadow_run import ShadowRunOperation
from .token import TokenOperation

operations = {
"!r-t": token,
"!r-r": regex,
"!rb": basic,
"!r-b": basic,
"!roll": token,
"!r": token,
"!sr": shadow_run,
"!r-t": TokenOperation(),
"!r-r": RegexOperation(),
"!rb": BasicOperation(),
"!r-b": BasicOperation(),
"!roll": TokenOperation(),
"!r": TokenOperation(),
"!sr": ShadowRunOperation(),
}


def clean_command(command_string):
return command_string.lower().replace("! ", "!").lstrip()


def remove_prefix(command_string, prefix):
if command_string.startswith(prefix):
return command_string[len(prefix):]
return command_string.lstrip()


def get_command(message_content: str):
clean_command_string = clean_command(message_content)
for prefix, op_getter in operations.items():
if clean_command_string.startswith(prefix):
operation_input = clean_command_string[len(prefix):].lstrip()
operation_input = remove_prefix(clean_command_string, prefix)
return op_getter, operation_input
return None, message_content
55 changes: 35 additions & 20 deletions roll_witch/rolling/command/basic.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from roll_witch.rolling.input import get_basic_rpg_parser
from roll_witch.rolling.output import TargetedOutputWriter
from roll_witch.rolling.roller import TargetedRoller
from roll_witch.rolling.roller import TargetedRoller, OperationRollResults
from math import ceil, floor
from roll_witch.rolling.protocols import Result
from roll_witch.rolling.protocols import Operation, OperationResult


class BasicOutputWriter(TargetedOutputWriter):
def build_success_string(self, roll_result: Result):
def build_success_string(self, roll_result: OperationResult):
target_number = abs(roll_result.spec.target_number)

if roll_result.total <= ceil(target_number * 0.05):
Expand All @@ -27,20 +27,35 @@ def build_success_string(self, roll_result: Result):
return "Failed"


def execute(roll_string: str, user: str):
try:
spec = get_spec(roll_string)
roll_result = TargetedRoller().roll(spec)
output = BasicOutputWriter().write_output(roll_result, user)
if len(output) > 2000:
raise ValueError()
return output
except ValueError:
raise Exception("Your answer is just too big to give you")
except Exception as e:
raise Exception(f"{e}")


def get_spec(roll_string):
parser = get_basic_rpg_parser()
return parser.parse(roll_string)
class BasicOperation(Operation):
def __init__(self):
super().__init__()
self.roller = TargetedRoller()
self.output_writer = BasicOutputWriter()
self.parser = get_basic_rpg_parser()

def execute(self, roll_string: str, user: str) -> OperationResult:
try:
spec = self.get_spec(roll_string)
result = OperationRollResults(spec)
roll_result = self.roller.roll(spec)
result.append_roll_result(roll_result)
return result
except ValueError:
raise Exception("Your answer is just too big to give you")
except Exception as e:
raise Exception(f"{e}")

def format_output(self, result: OperationResult, user):
try:
output = self.output_writer.write_output(result, user)
if len(output) > 2000:
raise ValueError()
return output
except ValueError:
raise Exception("Your answer is just too big to give you")
except Exception as e:
raise Exception(f"{e}")

def get_spec(self, roll_string):
return self.parser.parse(roll_string)
80 changes: 36 additions & 44 deletions roll_witch/rolling/command/regex.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,39 @@
from roll_witch.rolling.input import get_regex_parser
from roll_witch.rolling.output import TargetedOutputWriter, StandardOutputWriter
from roll_witch.rolling.roller import TargetedRoller, StandardRoller


def execute(roll_string: str, user: str):
roll_spec = get_spec(roll_string)
if roll_spec.has_target():
return do_targeted_roll(roll_spec, user)
else:
return do_standard_roll(roll_spec, user)


def get_spec(roll_string):
parser = get_regex_parser()
roll_spec = parser.parse(roll_string)
return roll_spec


def do_targeted_roll(spec, user):
try:
roller = TargetedRoller()
output = TargetedOutputWriter()
roll_result = roller.roll(spec)
output = output.write_output(roll_result, user)
if len(output) > 2000:
raise ValueError()
return output
except ValueError:
raise Exception("Your answer is just too big to give you")
except Exception as e:
raise Exception(f"{e}")


def do_standard_roll(spec, user):
try:
roller = StandardRoller()
output = StandardOutputWriter()
roll_result = roller.roll(spec)
output = output.write_output(roll_result, user)
if len(output) > 2000:
raise ValueError()
return output
except ValueError:
raise Exception("Your answer is just too big to give you")
except Exception as e:
raise Exception(f"{e}")
from roll_witch.rolling.protocols import Operation, OperationResult
from roll_witch.rolling.roller import OperationRollResults


class RegexOperation(Operation):
def __init__(self):
self.name = "Regular Expression Roll"
self.targeted_roller = TargetedRoller()
self.standard_roller = StandardRoller()
self.targeted_output_writer = TargetedOutputWriter()
self.standard_output_writer = StandardOutputWriter()
self.parser = get_regex_parser()

def execute(self, roll_string: str, user: str) -> OperationResult:
try:
roll_spec = self.parser.parse(roll_string)
result = OperationRollResults(roll_spec)
if roll_spec.has_target():
result.append_roll_result(self.targeted_roller.roll(roll_spec))
result.met_target = self.targeted_roller.met_target(roll_spec, result.total)
else:
result.append_roll_result(self.standard_roller.roll(roll_spec))
return result
except Exception as e:
raise Exception(f"{e}")

def format_output(self, result: OperationResult, user):
try:
if result.had_target():
return self.targeted_output_writer.write_output(result, user)
else:
return self.standard_output_writer.write_output(result, user)
except ValueError:
raise Exception("Your answer is just too big to give you")
except Exception as e:
raise Exception(f"{e}")
42 changes: 25 additions & 17 deletions roll_witch/rolling/command/shadow_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
from roll_witch.rolling.output import OperationOutputWriter
from roll_witch.rolling.roller import RollResult, RollSpec
from roll_witch.rolling.roller import StandardRoller
from roll_witch.rolling.roller.operation_result import OperationResult
from roll_witch.rolling.roller.operation_result import OperationRollResults
from roll_witch.rolling.protocols import Operation, OperationResult


class ShadowRunResult(OperationResult):
class ShadowRunRollResults(OperationRollResults):
def had_target(self) -> bool:
return False

Expand All @@ -16,21 +17,28 @@ def _apply_roll_to_total(self, result: RollResult):
self.roll_total += result.roll_total


def execute(roll_string: str, user: str):
spec = get_spec(roll_string)
roller = StandardRoller()
output_parser = OperationOutputWriter()
result = ShadowRunResult(spec)
for part in spec.parts:
part.target_number = spec.target_number
result.append_roll_result(roller.roll(part))
class ShadowRunOperation(Operation):
def __init__(self):
super().__init__()
self.name = "Shadow Run Roll"
self.parser = get_token_parser()
self.roller = StandardRoller()
self.output_parser = OperationOutputWriter()

return output_parser.write_output(result, user)
def execute(self, roll_string: str, user: str):
spec = self.get_spec(roll_string)
result = ShadowRunRollResults(spec)
for part in spec.parts:
part.target_number = spec.target_number
result.append_roll_result(self.roller.roll(part))

return result

def get_spec(roll_string):
parser = get_token_parser()
roll_spec = parser.parse(roll_string)
if not roll_spec.target_number:
roll_spec.add_part(RollSpec(target_number=5, operation=None))
return roll_spec
def format_output(self, result: OperationResult, user) -> str:
return self.output_parser.write_output(result, user)

def get_spec(self, roll_string):
roll_spec = self.parser.parse(roll_string)
if not roll_spec.target_number:
roll_spec.add_part(RollSpec(target_number=5, operation=None))
return roll_spec
36 changes: 20 additions & 16 deletions roll_witch/rolling/command/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,29 @@
StandardRoller,
TargetedRoller,
)
from roll_witch.rolling.roller.operation_result import OperationResult
from roll_witch.rolling.roller.operation_result import OperationRollResults
from roll_witch.rolling.protocols import Operation


def execute(roll_string: str, user: str):
spec = get_spec(roll_string)
roller = StandardRoller()
target_roller = TargetedRoller()
output_parser = OperationOutputWriter()
result = OperationResult(spec)
for part in spec.parts:
result.append_roll_result(roller.roll(part))
class TokenOperation(Operation):
def __init__(self):
super().__init__()
self.name = "Standard Dice Roll"
self.parser = get_token_parser()
self.roller = StandardRoller()
self.target_roller = TargetedRoller()
self.output_parser = OperationOutputWriter()

if spec.has_target():
result.met_target = target_roller.met_target(spec, result.total)
def execute(self, roll_string: str, user: str):
spec = self.parser.parse(roll_string)
result = OperationRollResults(spec)
for part in spec.parts:
result.append_roll_result(self.roller.roll(part))

return output_parser.write_output(result, user)
if spec.has_target():
result.met_target = self.target_roller.met_target(spec, result.total)

return result

def get_spec(roll_string):
parser = get_token_parser()
roll_spec = parser.parse(roll_string)
return roll_spec
def format_output(self, roll_result, user) -> str:
return self.output_parser.write_output(roll_result, user)
2 changes: 0 additions & 2 deletions roll_witch/rolling/output/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from .standard import StandardOutputWriter
from .target import TargetedOutputWriter
from .operation import OperationOutputWriter
from .base import OutputParser

__all__ = [
"StandardOutputWriter",
"TargetedOutputWriter",
"OperationOutputWriter",
"OutputParser",
]
27 changes: 9 additions & 18 deletions roll_witch/rolling/output/base.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
from roll_witch.rolling.roller import RollResult
from roll_witch.rolling.protocols import Result
from abc import ABC, abstractmethod
from typing import Protocol


class OutputParser(Protocol):
def write_output(self, roll_result: Result, user: str):
return "Unknown"
from ..protocols.result import OperationResult


class BaseOutputWriter(ABC):
def write_output(self, roll_result: Result, user):
total_string = self.build_total_string(roll_result)
return self.build_result_string(roll_result, total_string, user)
def write_output(self, result: OperationResult, user):
total_string = self.build_total_string(result)
return self.build_result_string(result, total_string, user)

def build_total_string(self, roll_result: Result):
if isinstance(roll_result, RollResult):
modifier_string = roll_result.formatted_modifier()
return f"{roll_result.rolls} = {roll_result.roll_total}{modifier_string}"
else:
raise Exception("Invalid Output parser for given data")
def build_total_string(self, result: OperationResult):
roll_result = result.rolls[0]
modifier_string = roll_result.formatted_modifier()
return f"{roll_result.rolls} = {roll_result.roll_total}{modifier_string}"

@abstractmethod
def build_result_string(self, roll_result: Result, total_string, user):
def build_result_string(self, roll_result: OperationResult, total_string, user):
return "Unsupported"
Loading

0 comments on commit 67bed45

Please sign in to comment.