def test_create_item(self):
        """
        1. Create Item
        2. Create effects for each item
        3. Instantiate Item using augmented model
        4. Compare to actual result from ItemBuilder
        """
        item_models = []
        item_effects_list = []
        total_items = 10
        total_effects_per_item = 2
        expected_items = []

        item_collection = ItemCollection()
        effect_collection = EffectCollection()

        for i in range(0, total_items):
            effects = []
            item_model = self._get_item_model()
            item_id = item_model["id"]

            for j in range(0, total_effects_per_item):
                effect = self._make_effect()
                effect_id = effect.id
                effects.append(effect)
                effect_collection.add(effect)
                item_effects_list.append(
                    {"item_id": item_id, "effect_id": effect_id})

            item_model["effects"] = effects

            item_models.append(item_model)

            item = Item(item=item_model)
            expected_items.append(item)

        item_effects_model = ItemEffects(db="quux")
        item_effects_map = item_effects_model._get_item_effects_map(
            item_effects_list)

        builder = ItemBuilder()
        actual_items = builder.build_items(item_collection=item_collection,
                                           effect_collection=effect_collection,
                                           item_models=item_models,
                                           item_effects_map=item_effects_map)

        self.assertEqual(len(actual_items), total_items)

        for a_item in actual_items:
            self.assertEqual(len(a_item.effects), total_effects_per_item)
    def _build_effects(self):
        """
        Returns a populated EffectCollection
        """
        self.log.info("Building effects")

        effects_collection = EffectCollection()
        effects_model = EffectModel(db=self.db)
        effects_models = effects_model.get_effects()

        for effect_model in effects_models:
            effect = Effect(effect=effect_model)

            effects_collection.add(effect)

        return effects_collection
    def test_make_effect_by_effect_name(self):
        effect_name = "Realm King"
        effect = self._make_effect(effect_name=effect_name)

        collection = EffectCollection()
        collection.add(effect)

        expected = effect

        # Typical use case
        actual = collection.get_effect_by_effect_name(effect_name=effect_name)

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

        # Test that we don't get the wrong thing
        expected = None
        actual = collection.get_effect_by_effect_name(
            effect_name="hello world")
        self.assertEqual(expected, actual)
    def test_get_effect_undead(self):
        effect_name = "Undead"
        undead_effect = self._make_effect(effect_name=effect_name)

        collection = EffectCollection()

        """
        Test that it doesn't return something
        when the collection is empty
        """
        actual = collection.get_effect_undead()

        self.assertEqual(len(collection.effects), 0)
        self.assertEqual(None, actual)

        # Add undead
        collection.add(undead_effect)

        # Typical use case
        actual = collection.get_effect_undead()

        self.assertEqual(len(collection.effects), 1)
        self.assertEqual(undead_effect, actual)

        """
        Add something other than undead and make sure
        it doesn't return the wrong thing
        """
        effect_name = "Realm King"
        realm_king_effect = self._make_effect(effect_name=effect_name)

        collection.add(realm_king_effect)

        actual = collection.get_effect_undead()

        self.assertEqual(len(collection.effects), 2)
        self.assertEqual(undead_effect, actual)
    def test_add_effect(self):
        effect_name = "Test Effect"
        effect_type = "rock"
        effect = self._make_effect(effect_name=effect_name)

        collection = EffectCollection()
        collection.add(effect)

        expected = effect
        actual = collection.get_effect_by_effect_name(effect_name=effect_name)

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

        # Test that we can't add duplicate effects
        collection.add(effect)
        self.assertEqual(len(collection.effects), 1)
    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))