def test_populate_base_items(self):
        """
        Build item collection of base items and ensure
        that they are populated accordingly
        """
        item_collection = ItemCollection()
        item_types = ("rock", "paper", "scissors", "lizard", "spock")
        unit_type_id = 2
        level = 13

        for item_type in item_types:
            item = self._make_item(item_type=item_type,
                                   unit_type_id=unit_type_id,
                                   is_permanent=True,
                                   min_level=level)
            item_collection.add(item)

        base_items = item_collection.items
        unit_bravo = self._make_unit(base_items=base_items,
                                     unit_type_id=unit_type_id,
                                     level=level)

        self.assertEqual(unit_bravo.level, level)
        self.assertEqual(unit_bravo.unit_type_id, unit_type_id)

        for base_item in base_items:
            self.assertEqual(base_item.min_level, level)
            self.assertEqual(base_item.unit_type_id, unit_type_id)

        self.assertEqual(unit_bravo.items, base_items)
    def test_equip_random_weapon(self):
        """
        Build item collection of base items and ensure
        that they are populated accordingly
        """
        item_collection = ItemCollection()
        item_types = ("rock", "paper", "scissors", "lizard", "spock")
        unit_type_id = 1
        level = 13

        for item_type in item_types:
            item = self._make_item(item_type=item_type,
                                   unit_type_id=unit_type_id,
                                   is_permanent=True,
                                   min_level=level)
            item_collection.add(item)

        base_items = item_collection.items
        unit_bravo = self._make_unit(base_items=base_items,
                                     unit_type_id=unit_type_id,
                                     level=level)

        for item_type in item_types:
            unit_bravo.equip_random_weapon(avoid_weapon_type=item_type)
            equipped_weapon = unit_bravo.equipped_weapon

            self.assertNotEqual(equipped_weapon.item_type, item_type)
    def test_get_item_by_item_name(self):
        item = self._get_item()
        collection = ItemCollection()
        collection.add(item)

        expected = item

        # Typical use case
        actual = collection.get_item_by_item_name(item.name)

        self.assertEqual(len(collection.items), 1)
        self.assertEqual(expected, actual)

        # Test that we don't get the wrong thing
        expected = None
        actual = collection.get_item_by_item_name("hello world")
        self.assertEqual(expected, actual)
    def _build_items(self, **kwargs):
        """
        This requires a populated EffectCollection in order
        to build the items due to the fact that items can have
        associated effects.
        """
        self.log.info("Building items")

        effect_collection = kwargs["effect_collection"]

        item_builder = ItemBuilder()
        item_model = ItemModel(db=self.db)
        item_models = item_model.get_items()
        item_effects_model = ItemEffects(db=self.db)
        item_effects_map = item_effects_model.get_item_effects()
        item_collection = ItemCollection()
        items = item_builder.build_items(item_models=item_models,
                                         item_effects_map=item_effects_map,
                                         effect_collection=effect_collection)

        for item in items:
            item_collection.add(item)

        return item_collection
    def test_add_item(self):
        item = self._get_item()
        collection = ItemCollection()
        collection.add(item)

        expected = item
        actual = collection.get_item_by_item_name(item.name)

        self.assertEqual(len(collection.items), 1)
        self.assertEqual(expected, actual)

        # Test that we can't add duplicate items
        collection.add(item)
        self.assertEqual(len(collection.items), 1)
    def test_get_base_items(self):
        base_item = self._get_item(is_permanent=True)

        collection = ItemCollection()
        collection.add(base_item)

        # Typical use case
        actual = collection.get_base_items()

        self.assertEqual(len(actual), 1)

        # Add non-base item
        item = self._get_item()

        collection.add(item)

        actual = collection.get_base_items()

        # Make sure the item was added
        self.assertEqual(len(collection.items), 2)

        # Make sure the result is still correct
        self.assertEqual(len(actual), 1)
    def get_combatants(self):
        """
        Create units, with an item of each type
        """
        item_collection = ItemCollection()
        unit_models = []
        unit_items_list = []
        expected_units = []

        item_types = ("rock", "paper", "scissors", "lizard", "spock")
        for item_type in item_types:
            item = self._make_item(item_type=item_type)
            item_collection.add(item)

        for j in range(0, 2):
            unit_model = self._get_unit_model()
            unit_id = unit_model["id"]

            for c_item in item_collection.items:
                unit_items_list.append({"item_id": c_item.id,
                                        "unit_id": unit_id})
                unit_model["items"].append(c_item)

            with LogCapture():
                logger = logging.getLogger()
                unit = Unit(unit=unit_model, log=logger)

            expected_units.append(unit)
            unit_models.append(unit_model)

        """
        Although we added more items, the collection should
        never add duplicates
        """
        total_items = len(item_types)
        self.assertEqual(len(item_collection.items), total_items)

        """
        There two units with five items each, so unit_items_map
        should have ten items total
        """
        unit_items_list_length = len(unit_items_list)
        self.assertEqual(unit_items_list_length, 10)

        builder = UnitBuilder()
        unit_items_model = UnitItems(db="quux")
        unit_items_map = unit_items_model._get_unit_items_map(unit_items_list)

        with LogCapture():
            logger = logging.getLogger()
            actual_units = builder.build_units(unit_models=unit_models,
                                               unit_items_map=unit_items_map,
                                               item_collection=item_collection,
                                               effect_collection="quux",
                                               dialogue_collection="quux",
                                               unit_effects_map={},
                                               unit_dialogue_map={},
                                               log=logger)

        self.assertEqual(len(expected_units), len(actual_units))

        """
        Ensure that each unit has the expected item set
        """
        unit_items = [uitem for uitem in item_collection.items]

        for unit in actual_units:
            # Ensure that each of the new units have full HP
            self.assertEqual(unit.get_hp(), unit.calculate_hp())
            self.assertEqual(unit.items, unit_items)

        return actual_units
    def test_create_units(self):
        """
        The item collection is populated by models
        """
        item_collection = ItemCollection()
        effect_collection = EffectCollection()
        dialogue_collection = UnitDialogueCollection()

        """
        Prepare unit model collection
        """
        unit_models = []
        expected_units = []
        unit_items = []
        unit_effects = []
        unit_dialogue = []
        unit_items_model = UnitItems(db="quux")
        unit_effects_model = UnitEffects(db="quux")
        unit_dialogue_model = UnitDialogueModel(db="quux")

        total_units = 25
        item_types = ("rock", "paper", "scissors", "paper", "spock")
        total_items_per_unit = len(item_types)
        total_effects_per_unit = 5
        total_dialogue_per_unit = 5

        for j in range(0, total_units):
            """
            Add items for each unit
            """
            items = []
            effects = []
            dialogue = []
            unit_model = self._get_unit_model()
            unit_id = unit_model["id"]
            unit_type_id = unit_model["unit_type_id"]

            for it in item_types:
                item = self._make_item(item_type=it,
                                       unit_type_id=unit_type_id)
                items.append(item)
                item_collection.add(item)
                unit_items.append({"item_id": item.id, "unit_id": unit_id})

            unit_model["items"] = items

            """
            Base items
            """
            unit_model["base_items"] = \
                item_collection.get_base_items_by_unit_type_id(unit_type_id)

            """
            Add effects
            """
            for k in range(0, total_effects_per_unit):
                effect = self._make_effect()
                effects.append(effect)
                effect_collection.add(effect)
                unit_effects.append(
                    {"effect_id": effect.id, "unit_id": unit_id})

            unit_model["effects"] = effects

            """
            Add dialogue
            """
            for q in range(0, total_dialogue_per_unit):
                a_dialogue = self._make_dialogue()
                dialogue.append(a_dialogue)
                dialogue_collection.add(a_dialogue)
                unit_dialogue.append(
                    {"dialogue_id": a_dialogue.id, "unit_id": unit_id})

            unit_model["dialogue"] = dialogue

            """
            Add completed unit to expected
            """
            unit_models.append(unit_model)

            with LogCapture():
                logger = logging.getLogger()
                unit = Unit(unit=unit_model, log=logger)

            expected_units.append(unit)

        unit_items_map = unit_items_model._get_unit_items_map(unit_items)
        unit_effects_map = unit_effects_model._get_unit_effects_map(
            unit_effects)
        unit_dialogue_map = unit_dialogue_model._get_unit_dialogue_map(
            unit_dialogue)

        builder = UnitBuilder()
        with LogCapture():
            logger = logging.getLogger()
            actual_units = builder.build_units(unit_models=unit_models,
                                               unit_items_map=unit_items_map,
                                               item_collection=item_collection,
                                               effect_collection=effect_collection,
                                               unit_effects_map=unit_effects_map,
                                               dialogue_collection=dialogue_collection,
                                               unit_dialogue_map=unit_dialogue_map,
                                               log=logger)

        expected_unit_ids = [unit.id for e_unit in expected_units]
        actual_unit_ids = [unit.id for a_unit in actual_units]

        self.assertEqual(expected_unit_ids, actual_unit_ids)

        """
        Test that the actual units contain the expected items
        and effects
        """
        self.assertEqual(len(actual_units), len(expected_units))

        for e_unit in expected_units:
            self.assertEqual(len(e_unit.items), total_items_per_unit)
            self.assertEqual(len(e_unit.effects), total_effects_per_unit)
            self.assertEqual(len(e_unit.dialogue), total_dialogue_per_unit)

        for a_unit in actual_units:
            self.assertEqual(len(a_unit.items), total_items_per_unit)
            self.assertEqual(len(a_unit.effects), total_effects_per_unit)
            self.assertEqual(len(a_unit.dialogue), total_dialogue_per_unit)

            """
            Ensure each item either has no unit type requirement (0)
            or it matches the unit in question
            """
            for a_item in a_unit.items:
                self.assertIn(a_item.unit_type_id, (0, a_unit.unit_type_id))
    def test_build_world(self):
        """
        Utilize models to build the world.

        1. Get dungeons
        2. Get effects
        3. Get item effects
        4. Get items
        5. Get unit items
        6. Get units
        """

        """ Dungeons """
        dungeon_model = DungeonModel(db=self.db)
        dungeon_models = dungeon_model.get_dungeons()

        self.assertIsInstance(dungeon_models, list)
        self.assertTrue(dungeon_models)

        """ Effects """
        effects_model = EffectModel(db=self.db)
        effects_models = effects_model.get_effects()

        self.assertIsInstance(effects_models, list)
        self.assertTrue(effects_models)

        """ Unit effects map """
        unit_effects_model = UnitEffects(db=self.db)
        unit_effects = unit_effects_model.get_unit_effects()
        unit_effects_map = unit_effects_model._get_unit_effects_map(unit_effects)

        self.assertIsInstance(unit_effects_map, dict)
        self.assertTrue(unit_effects_map)

        """ Unit dialogue map """
        unit_dialogue_model = UnitDialogueModel(db=self.db)
        unit_dialogue = unit_dialogue_model.get_unit_dialogue()
        unit_dialogue_map = unit_dialogue_model._get_unit_dialogue_map(unit_dialogue)

        self.assertIsInstance(unit_dialogue, list)
        self.assertIsInstance(unit_dialogue_map, dict)
        self.assertTrue(unit_dialogue_map)

        """ Item effects map """
        item_effects_model = ItemEffects(db=self.db)
        item_effects = item_effects_model.get_item_effects()
        item_effects_map = item_effects_model._get_item_effects_map(item_effects)

        self.assertIsInstance(item_effects, list)
        self.assertIsInstance(item_effects_map, dict)
        self.assertTrue(item_effects_map)
        self.assertTrue(item_effects)

        """ Items """
        item_model = ItemModel(db=self.db)
        item_models = item_model.get_items()

        self.assertIsInstance(item_models, list)
        self.assertTrue(item_models)

        """ Unit items map """
        unit_items_model = UnitItems(db=self.db)
        unit_item_models = unit_items_model.get_unit_items()
        unit_items_map = unit_items_model._get_unit_items_map(unit_item_models)

        self.assertIsInstance(unit_item_models, list)
        self.assertIsInstance(unit_items_map, dict)
        self.assertTrue(unit_items_map)
        self.assertTrue(unit_item_models)

        """ Units """
        unit_model = UnitModel(db=self.db)
        unit_models = unit_model.get_units()

        self.assertIsInstance(unit_models, list)
        self.assertTrue(unit_models)

        """ Assemble collections using models """
        item_collection = ItemCollection()
        effect_collection = EffectCollection()
        dialogue_collection = UnitDialogueCollection()

        for effect_model in effects_models:
            effect = Effect(effect=effect_model)
            effect_collection.add(effect)

        self.assertTrue(effect_collection.effects)

        item_builder = ItemBuilder()
        items = item_builder.build_items(item_models=item_models,
                                         item_effects_map=item_effects_map,
                                         effect_collection=effect_collection)
        self.assertIsInstance(items, list)
        self.assertTrue(items)

        for item in items:
            item_collection.add(item)

        self.assertTrue(item_collection.items)

        for ud in unit_dialogue:
            dialogue = UnitDialogue(dialogue=ud)
            dialogue_collection.add(dialogue)

        """ Build units using assembled collections """
        unit_builder = UnitBuilder()

        with LogCapture() as l:
            logger = logging.getLogger()
            units = unit_builder.build_units(unit_models=unit_models,
                                             effect_collection=effect_collection,
                                             item_collection=item_collection,
                                             dialogue_collection=dialogue_collection,
                                             unit_items_map=unit_items_map,
                                             unit_effects_map=unit_effects_map,
                                             unit_dialogue_map=unit_dialogue_map,
                                             log=logger)

        self.assertIsInstance(units, list)
        self.assertTrue(units)

        num_players = 0

        for unit in units:
            self.assertIsInstance(unit, Unit)

            if unit.is_player:
                num_players += 1

        self.assertTrue(num_players > 0)

        """
        Populate collections
        """
        unit_collection = UnitCollection()

        for unit in units:
            unit_collection.add(unit)

        self.assertEqual(len(unit_collection.units), len(unit_models))