def test_go_new(self): go = GameObject(mode=GameMode(mode="Normal", priority=5)) test_dict = go.dump() key = test_dict["key"] go.new(mode=GameMode(mode="Normal", priority=5)) self.assertNotEqual(go.key, key)
def test_gc_new_game_modes(self): mode_list = [ GameMode( mode="test1", priority=5, ), GameMode( mode="test2", priority=6, ) ] g = GameController(game_modes=mode_list) modes = g.game_mode_names self.assertTrue("test1" in modes) self.assertTrue("test2" in modes) self.assertFalse("test3" in modes)
def test_gc_load_game_modes(self): mode_list = [ GameMode( mode="test1", priority=5, ), GameMode( mode="test2", priority=6, ) ] g = GameController() g.load_modes(input_modes=mode_list) modes = g.game_mode_names self.assertTrue("test1" in modes) self.assertTrue("test2" in modes)
def load(self, source=None): """ Load the representation of a GameObject from a Python <dict> representing the game object. :param source: a Python <dict> as detailed above. :return: """ if not source: raise ValueError( "A valid dictionary must be passed as the source_dict") if not isinstance(source, dict): raise TypeError( "A valid dictionary must be passed as the source_dict. {} given." .format(type(source))) required_keys = ("key", "status", "ttl", "answer", "mode", "guesses_made") if not all(key in source for key in required_keys): raise ValueError( "The dictionary passed is malformed: {}".format(source)) _mode = GameMode(**source["mode"]) self._key = source["key"] self._status = source["status"] self._ttl = source["ttl"] self._answer = DigitWord(*source["answer"], wordtype=_mode.digit_type) self._mode = _mode self._guesses_made = source["guesses_made"]
def test_go_dump(self): go = GameObject(mode=GameMode(mode="Normal", priority=5)) test_dict = go.dump() self.assertIsInstance(test_dict, dict) required_keys = { "key", "status", "ttl", "answer", "mode", "guesses_made" } keys_from_dump = set([key for key in go.dump().keys()]) self.assertTrue(required_keys <= keys_from_dump)
def test_gc_load_game_modes_nolist(self): mode_list = \ GameMode( mode="test1", priority=5, ) g = GameController() with self.assertRaises(TypeError): g.load_modes(input_modes=mode_list)
def _load_game(self, game_json): self.handler.log(message="JSON provided") if not isinstance(game_json, self.STRINGY): raise TypeError("Game must be passed as a serialized JSON string.") self.handler.log(message="Attempting to execute_load") game_dict = json.loads(game_json) self.handler.log(message="Validating mode exists in JSON") if not 'mode' in game_dict: raise ValueError( "Mode is not provided in JSON; game_json cannot be loaded!") _mode = GameMode(**game_dict["mode"]) if len(game_dict["answer"]) != game_dict["mode"]["digits"]: raise ValueError( "JSON provided answer does not match the JSON game mode") _game_object = GameObject(mode=_mode, source_game=game_dict) return _game_object
def test_gm_property_helptext(self): gm = GameMode(mode="test", priority=3, help_text="Help") self.assertEqual(gm.help_text, "Help") gm.help_text = "This is some help" self.assertEqual(gm.help_text, "This is some help")
def test_gm_new(self): gm = GameMode(mode="test", priority=1) self.assertIsInstance(gm, GameMode)
def test_gm_property_guesses_allowed_bad(self): gm = GameMode(mode="test", priority=3) with self.assertRaises(TypeError): gm.guesses_allowed = "X"
def test_gm_property_instructions(self): gm = GameMode(mode="test", priority=3, instruction_text="Test") self.assertEqual(gm.instruction_text, "Test") gm.instruction_text = "This is some test text" self.assertEqual(gm.instruction_text, "This is some test text")
def test_go_load_bad(self): go = GameObject(mode=GameMode(mode="Normal", priority=5)) with self.assertRaises(ValueError): go.load(source={"key": "fred"})
def test_gm_property_guesses_allowed(self): gm = GameMode(mode="test", priority=3, guesses_allowed=5) self.assertEqual(gm.guesses_allowed, 5) gm.guesses_allowed = 7 self.assertEqual(gm.guesses_allowed, 7)
def test_go_answer(self): go = GameObject(mode=GameMode(mode="test", priority=5)) self.assertIsInstance(go.answer, DigitWord) self.assertIsInstance(go.answer.word, list)
def load_modes(self, input_modes=None): """ Loads modes (GameMode objects) to be supported by the game object. Four default modes are provided (normal, easy, hard, and hex) but others could be provided either by calling load_modes directly or passing a list of GameMode objects to the instantiation call. :param input_modes: A list of GameMode objects; nb: even if only one new GameMode object is provided, it MUST be passed as a list - for example, passing GameMode gm1 would require passing [gm1] NOT gm1. :return: A list of GameMode objects (both defaults and any added). """ # Set default game modes self.handler.method = "load_modes" self.handler.log(message="Loading default modes") _modes = [ GameMode( mode="Normal", priority=20, digits=4, digit_type=DigitWord.DIGIT, guesses_allowed=10, help_text= "This is the normal (default) game. You need to guess 4 digits " "in the right place and each digit must be a whole number " "between 0 and 9. There are 10 tries to guess the " "correct answer.", instruction_text="Enter 4 digits, each digit between 0 and 9 " "(0, 1, 2, 3, 4, 5, 6, 7, 8, and 9)."), GameMode( mode="Easy", priority=10, digits=3, digit_type=DigitWord.DIGIT, guesses_allowed=6, help_text= "Easy. You need to guess 3 digits in the right place and each " "digit must be a whole number between 0 and 9. There are " "6 tries to guess the correct answer.", instruction_text="Enter 3 digits, each digit between 0 and 9 " "(0, 1, 2, 3, 4, 5, 6, 7, 8, and 9)."), GameMode( mode="Hard", priority=30, digits=6, digit_type=DigitWord.DIGIT, guesses_allowed=6, help_text= "Hard. You need to guess 6 digits in the right place and each " "digit must be a whole number between 0 and 9. There are " "only 6 tries to guess the correct answer.", instruction_text="Enter 6 digits, each digit between 0 and 9 " "(0, 1, 2, 3, 4, 5, 6, 7, 8, and 9)."), GameMode( mode="Hex", priority=40, digits=4, digit_type=DigitWord.HEXDIGIT, guesses_allowed=10, help_text= "Hex. You need to guess 4 digits in the right place and each " "digit must be a hexidecimal number between 0 and F. There are " "10 tries to guess the correct answer.", instruction_text="Enter 4 digits, each digit between 0 and F " "(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, " "E, and F).") ] self.handler.log(message="Loaded modes: {}".format(_modes)) if input_modes is not None: if not isinstance(input_modes, list): raise TypeError("Expected list of input_modes") for mode in input_modes: if not isinstance(mode, GameMode): _mode = GameMode(**mode) else: _mode = mode self.handler.log(message="Appending mode: {}".format(mode)) _modes.append(_mode) self.handler.log(message="Deep copying modes") self._game_modes = copy.deepcopy(_modes) self.default_mode = "Normal"
def test_gm_new_extra_params(self): with self.assertRaises(TypeError): GameMode(mode="test", priority=3, super_digits="*")
def test_go_guesses_made_update(self): go = GameObject(mode=GameMode(mode="test", priority=5)) go.guesses_made += 1 self.assertEqual(go.guesses_made, 1)
def test_gm_new_no_mode(self): with self.assertRaises(KeyError): GameMode()
def test_gm_new_bad_priority(self): with self.assertRaises(KeyError): GameMode(mode="test")
def test_go_guesses_made_updatebad(self): go = GameObject(mode=GameMode(mode="test", priority=5)) with self.assertRaises(TypeError): go.guesses_made = "W1"
def test_go_ttl(self): go = GameObject(mode=GameMode(mode="test", priority=5)) self.assertIsInstance(go.ttl, int)
def test_go_status(self): go = GameObject(mode=GameMode(mode="test", priority=5)) go.status = "TestStatus" self.assertEqual(go.status, "TestStatus")
def load(self, game_json=None, mode=None): """ Load a game from a serialized JSON representation. The game expects a well defined structure as follows (Note JSON string format): '{ "guesses_made": int, "key": "str:a 4 word", "status": "str: one of playing, won, lost", "mode": { "digits": int, "digit_type": DigitWord.DIGIT | DigitWord.HEXDIGIT, "mode": GameMode(), "priority": int, "help_text": str, "instruction_text": str, "guesses_allowed": int }, "ttl": int, "answer": [int|str0, int|str1, ..., int|strN] }' * "mode" will be cast to a GameMode object * "answer" will be cast to a DigitWord object :param game_json: The source JSON - MUST be a string :param mode: A mode (str or GameMode) for the game being loaded :return: A game object """ self.handler.method = "execute_load" self.handler.log(message="Validating mode value") self.handler.log(message="Mode: Value {} Type {}".format(mode, type(mode))) _mode = mode or 'Normal' # Default mode to normal if not provided self.handler.log(message="Validating (any) JSON provided") if game_json is None: # New game_json self.handler.log(message="No JSON, so start new game.") self.handler.log(message="Validating (any) mode provided") if mode is not None: self.handler.log(message="mode provided, checking if string or GameMode") if isinstance(mode, self.STRINGY): self.handler.log(message="Mode is a string; matching name {}".format(mode)) _game_object = GameObject(mode=self._match_mode(mode=mode)) elif isinstance(mode, GameMode): self.handler.log(message="Mode is a GameMode object") _game_object = GameObject(mode=mode) else: self.handler.log(message="Mode is invalid") raise TypeError("Game mode must be a GameMode or string") else: self.handler.log(message="Game mode is None, so default mode used.") _game_object = GameObject(mode=self._game_modes[0]) _game_object.status = self.GAME_PLAYING else: self.handler.log(message="JSON provided") if not isinstance(game_json, self.STRINGY): raise TypeError("Game must be passed as a serialized JSON string.") self.handler.log(message="Attempting to execute_load") game_dict = json.loads(game_json) self.handler.log(message="Validating mode exists in JSON") if not 'mode' in game_dict: raise ValueError("Mode is not provided in JSON; game_json cannot be loaded!") _mode = GameMode(**game_dict["mode"]) if len(game_dict["answer"]) != game_dict["mode"]["digits"]: raise ValueError("JSON provided answer does not match the JSON game mode") _game_object = GameObject(mode=_mode, source_game=game_dict) self.handler.log(message="Deep copy loaded (or new) object") self.game = copy.deepcopy(_game_object)
def test_gm_property_digit_type_bad(self): gm = GameMode(mode="test", priority=3) with self.assertRaises(TypeError): gm.digit_type = "X"
def test_gm_new_bad_mode(self): with self.assertRaises(TypeError): GameMode(mode="test", priority=3, digits="S")
def test_go_guesses_remaining(self): go = GameObject(mode=GameMode(mode="Normal", priority=5)) self.assertEqual(go.guesses_remaining, 10)
def test_gc_new_game_direct(self): g = GameController() g._new_game(GameMode( mode="test1", priority=5, ))
def test_gm_property_priority(self): gm = GameMode(mode="test", priority=3) gm.priority = 5 self.assertEqual(gm.priority, 5)
def test_gm_property_digit_type(self): gm = GameMode(mode="test", priority=3) gm.digit_type = 5 self.assertEqual(gm.digit_type, 5)
def test_go_mode(self): go = GameObject(mode=GameMode(mode="test", priority=5)) self.assertIsInstance(go.mode, GameMode)