couple cleanups and unit tests for acro
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
This commit is contained in:
+32
-37
@@ -3,7 +3,6 @@
|
||||
SPDX-FileCopyrightText: © 2026 Brian S. Stephan <bss@incorporeal.org>
|
||||
SPDX-License-Identifier: GPL-3.0
|
||||
"""
|
||||
|
||||
import logging
|
||||
import random
|
||||
import threading
|
||||
@@ -47,41 +46,16 @@ class AcroGame(object):
|
||||
"""Provide access to the current round of the game."""
|
||||
return self.rounds[-1]
|
||||
|
||||
def end_current_round(self):
|
||||
"""Clean up and output for ending the current round."""
|
||||
self.state = AcroGameState.round_results
|
||||
self.bot.reply(None, "voting's over! here are the scores for the round:", explicit_target=self.channel)
|
||||
self._print_round_scores()
|
||||
self._add_round_scores_to_game_scores()
|
||||
|
||||
# delay a bit
|
||||
time.sleep(self.current_round.seconds_to_pause)
|
||||
self._continue_or_quit()
|
||||
|
||||
def start_new_game(self, channel):
|
||||
def start_new_game(self):
|
||||
"""Begin a new game, which will have multiple rounds."""
|
||||
if self.state != AcroGameState.stopped:
|
||||
return "the game is already running."
|
||||
|
||||
self.state = AcroGameState.game_start
|
||||
self.channel = channel
|
||||
self.bot.reply(None, "starting a new game of acro. it will run until you tell it to quit.",
|
||||
explicit_target=self.channel)
|
||||
|
||||
self.start_new_round()
|
||||
|
||||
def start_new_round(self):
|
||||
"""Start a new round for play."""
|
||||
self.state = AcroGameState.round_submission
|
||||
self.rounds.append(AcroRound())
|
||||
acro = self._generate_acro()
|
||||
self.current_round.acro = acro
|
||||
sleep_time = self.current_round.seconds_to_submit + (self.current_round.seconds_to_submit_step * (len(acro)-3))
|
||||
|
||||
self.bot.reply(None, "the round has started! your acronym is '{0:s}'. "
|
||||
"submit within {1:d} seconds via !acro submit [meaning]".format(acro, sleep_time),
|
||||
explicit_target=self.channel)
|
||||
|
||||
t = threading.Thread(target=self.thread_do_process_submissions, args=(sleep_time,))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
self._start_new_round()
|
||||
|
||||
def start_voting(self):
|
||||
"""Begin the voting period."""
|
||||
@@ -130,7 +104,7 @@ class AcroGame(object):
|
||||
def thread_do_process_votes(self):
|
||||
"""Wait for players to provide votes, and then continue or quit."""
|
||||
time.sleep(self.current_round.seconds_to_vote)
|
||||
self.end_current_round()
|
||||
self._end_current_round()
|
||||
|
||||
def _add_round_scores_to_game_scores(self):
|
||||
"""Apply the final round scores to the total scores for the game."""
|
||||
@@ -147,7 +121,15 @@ class AcroGame(object):
|
||||
if self.should_quit:
|
||||
self._end_game()
|
||||
else:
|
||||
self.start_new_round()
|
||||
self._start_new_round()
|
||||
|
||||
def _end_current_round(self):
|
||||
"""Clean up and output for ending the current round."""
|
||||
self.state = AcroGameState.round_results
|
||||
self.bot.reply(None, "voting's over! here are the scores for the round:", explicit_target=self.channel)
|
||||
self._print_round_scores()
|
||||
self._add_round_scores_to_game_scores()
|
||||
self._continue_or_quit()
|
||||
|
||||
def _end_game(self):
|
||||
"""Clean up the entire game."""
|
||||
@@ -245,6 +227,22 @@ class AcroGame(object):
|
||||
explicit_target=self.channel)
|
||||
i += 1
|
||||
|
||||
def _start_new_round(self):
|
||||
"""Start a new round for play."""
|
||||
self.state = AcroGameState.round_submission
|
||||
self.rounds.append(AcroRound())
|
||||
acro = self._generate_acro()
|
||||
self.current_round.acro = acro
|
||||
sleep_time = self.current_round.seconds_to_submit + (self.current_round.seconds_to_submit_step * (len(acro)-3))
|
||||
|
||||
self.bot.reply(None, "the round has started! your acronym is '{0:s}'. "
|
||||
"submit within {1:d} seconds via !acro submit [meaning]".format(acro, sleep_time),
|
||||
explicit_target=self.channel)
|
||||
|
||||
t = threading.Thread(target=self.thread_do_process_submissions, args=(sleep_time,))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
@staticmethod
|
||||
def _turn_text_into_acro(text):
|
||||
"""Turn text into an acronym."""
|
||||
@@ -325,10 +323,7 @@ class Acro(Plugin):
|
||||
except KeyError:
|
||||
game = AcroGame(self.bot, event.target)
|
||||
self.games[event.target] = game
|
||||
|
||||
if game.state != AcroGameState.stopped:
|
||||
return self.bot.reply(event, "the game is already running.")
|
||||
game.start_new_game(event.target)
|
||||
return self.bot.reply(event, game.start_new_game())
|
||||
else:
|
||||
return self.bot.reply(event, "you must start the game from a channel.")
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
"""Tests for the acromania game module.
|
||||
|
||||
SPDX-FileCopyrightText: © 2026 Brian S. Stephan <bss@incorporeal.org>
|
||||
SPDX-License-Identifier: GPL-3.0
|
||||
"""
|
||||
from unittest import mock
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from acro.ircplugin import AcroGame, AcroGameState, AcroRound
|
||||
|
||||
|
||||
class AcroGameTestCase(TestCase):
|
||||
"""Test game state transition stuff."""
|
||||
|
||||
def test_game_creation(self):
|
||||
"""Test the initial state of a created game."""
|
||||
game = self._create_game()
|
||||
assert game.state == AcroGameState.stopped
|
||||
assert game.should_quit is False
|
||||
assert game.channel == '#test'
|
||||
|
||||
def test_game_start(self):
|
||||
"""Start the game."""
|
||||
game = self._create_game()
|
||||
with mock.patch('acro.ircplugin.AcroGame._start_new_round') as round_mock:
|
||||
resp = game.start_new_game()
|
||||
assert game.state == AcroGameState.game_start
|
||||
assert round_mock.called_exactly_once()
|
||||
assert resp is None
|
||||
|
||||
def test_game_start_double_start_error(self):
|
||||
"""Start the game."""
|
||||
game = self._create_game()
|
||||
with mock.patch('acro.ircplugin.AcroGame._start_new_round') as round_mock:
|
||||
resp = game.start_new_game()
|
||||
resp = game.start_new_game()
|
||||
assert round_mock.called_exactly_once()
|
||||
assert resp == "the game is already running."
|
||||
|
||||
def _create_game(self):
|
||||
"""Create a game, either for a direct test or for subsequent tests.
|
||||
|
||||
The bot is mocked out and can be used for validation.
|
||||
"""
|
||||
return AcroGame(mock.MagicMock(), '#test')
|
||||
Reference in New Issue
Block a user