def test_fit_charge_to_fully_bound_charge(self): fit = Fit() fit_other = Fit() module = ModuleHigh(self.mktype().id, state=State.active, charge=None) charge = Charge(self.mktype().id) module_other = ModuleHigh(self.mktype().id, state=State.active, charge=None) charge_other = Charge(self.mktype().id) fit.modules.high.append(module) fit_other.modules.high.append(module_other) module.charge = charge module_other.charge = charge_other # Action with self.assertRaises(ValueError): module.charge = charge_other # Verification self.assertIs(module.charge, charge) self.assertIs(module_other.charge, charge_other) # Cleanup self.assert_item_buffers_empty(module) self.assert_item_buffers_empty(charge) self.assert_item_buffers_empty(module_other) self.assert_item_buffers_empty(charge_other) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_solsys_buffers_empty(fit_other.solar_system) self.assert_log_entries(0)
def test_non_uniform(self): fit = Fit() item = Ship( self.mktype( attrs={ AttrId.hp: 10, AttrId.em_dmg_resonance: 0.9, AttrId.therm_dmg_resonance: 0.8, AttrId.kin_dmg_resonance: 0.7, AttrId.expl_dmg_resonance: 0.6, AttrId.armor_hp: 50, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.6, AttrId.armor_kin_dmg_resonance: 0.8, AttrId.armor_expl_dmg_resonance: 0.9, AttrId.shield_capacity: 600, AttrId.shield_em_dmg_resonance: 1.0, AttrId.shield_therm_dmg_resonance: 0.8, AttrId.shield_kin_dmg_resonance: 0.6, AttrId.shield_expl_dmg_resonance: 0.5 }).id) fit.ship = item # Verification results = item.get_ehp(DmgProfile(25, 6, 8.333, 1)) self.assertAlmostEqual(results.hull, 11.957, places=3) self.assertAlmostEqual(results.armor, 95.276, places=3) self.assertAlmostEqual(results.shield, 685.551, places=3) self.assertAlmostEqual(results.total, 792.783, places=3) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_worst_em(self): fit = Fit() item = Ship( self.mktype( attrs={ AttrId.hp: 1, AttrId.em_dmg_resonance: 0.8, AttrId.therm_dmg_resonance: 0.7, AttrId.kin_dmg_resonance: 0.7, AttrId.expl_dmg_resonance: 0.7, AttrId.armor_hp: 10, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.3, AttrId.armor_kin_dmg_resonance: 0.3, AttrId.armor_expl_dmg_resonance: 0.3, AttrId.shield_capacity: 100, AttrId.shield_em_dmg_resonance: 0.2, AttrId.shield_therm_dmg_resonance: 0.1, AttrId.shield_kin_dmg_resonance: 0.1, AttrId.shield_expl_dmg_resonance: 0.1 }).id) fit.ship = item # Verification self.assertAlmostEqual(item.worst_case_ehp.hull, 1.25) self.assertAlmostEqual(item.worst_case_ehp.armor, 25) self.assertAlmostEqual(item.worst_case_ehp.shield, 500) self.assertAlmostEqual(item.worst_case_ehp.total, 526.25) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_inside_value_failure(self): fit = Fit() fit_other = Fit() item1 = ModuleHigh(self.mktype().id) item2 = ModuleHigh(self.mktype().id) item3 = ModuleHigh(self.mktype().id) fit.modules.high.append(item1) fit.modules.high.append(item2) fit_other.modules.high.append(item3) # Action with self.assertRaises(ValueError): fit.modules.high.insert(1, item3) # Verification self.assertIs(len(fit.modules.high), 2) self.assertIs(fit.modules.high[0], item1) self.assertIs(fit.modules.high[1], item2) self.assertIs(len(fit_other.modules.high), 1) self.assertIs(fit_other.modules.high[0], item3) # Cleanup self.assert_item_buffers_empty(item1) self.assert_item_buffers_empty(item2) self.assert_item_buffers_empty(item3) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_solsys_buffers_empty(fit_other.solar_system) self.assert_log_entries(0)
def test_uniform(self): fit = Fit() item = Ship( self.mktype( attrs={ AttrId.hp: 1, AttrId.em_dmg_resonance: 0.8, AttrId.therm_dmg_resonance: 0.8, AttrId.kin_dmg_resonance: 0.8, AttrId.expl_dmg_resonance: 0.8, AttrId.armor_hp: 10, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.4, AttrId.armor_kin_dmg_resonance: 0.4, AttrId.armor_expl_dmg_resonance: 0.4, AttrId.shield_capacity: 100, AttrId.shield_em_dmg_resonance: 0.2, AttrId.shield_therm_dmg_resonance: 0.2, AttrId.shield_kin_dmg_resonance: 0.2, AttrId.shield_expl_dmg_resonance: 0.2 }).id) fit.ship = item # Verification results = item.get_ehp(DmgProfile(1, 1, 1, 1)) self.assertAlmostEqual(results.hull, 1.25) self.assertAlmostEqual(results.armor, 25) self.assertAlmostEqual(results.shield, 500) self.assertAlmostEqual(results.total, 526.25) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_non_uniform(self): fit = Fit() item = Ship(self.mktype(attrs={ AttrId.hp: 10, AttrId.em_dmg_resonance: 0.9, AttrId.therm_dmg_resonance: 0.8, AttrId.kin_dmg_resonance: 0.7, AttrId.expl_dmg_resonance: 0.6, AttrId.armor_hp: 50, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.6, AttrId.armor_kin_dmg_resonance: 0.8, AttrId.armor_expl_dmg_resonance: 0.9, AttrId.shield_capacity: 600, AttrId.shield_em_dmg_resonance: 1.0, AttrId.shield_therm_dmg_resonance: 0.8, AttrId.shield_kin_dmg_resonance: 0.6, AttrId.shield_expl_dmg_resonance: 0.5}).id) fit.ship = item # Verification results = item.get_ehp(DmgProfile(25, 6, 8.333, 1)) self.assertAlmostEqual(results.hull, 11.957, places=3) self.assertAlmostEqual(results.armor, 95.276, places=3) self.assertAlmostEqual(results.shield, 685.551, places=3) self.assertAlmostEqual(results.total, 792.783, places=3) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_attr_hp_all_absent(self): fit = Fit() item = Ship( self.mktype( attrs={ AttrId.em_dmg_resonance: 0.9, AttrId.therm_dmg_resonance: 0.8, AttrId.kin_dmg_resonance: 0.7, AttrId.expl_dmg_resonance: 0.6, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.6, AttrId.armor_kin_dmg_resonance: 0.8, AttrId.armor_expl_dmg_resonance: 0.9, AttrId.shield_em_dmg_resonance: 1.0, AttrId.shield_therm_dmg_resonance: 0.8, AttrId.shield_kin_dmg_resonance: 0.6, AttrId.shield_expl_dmg_resonance: 0.5 }).id) fit.ship = item # Verification results = item.get_ehp(DmgProfile(25, 6, 8.333, 1)) self.assertAlmostEqual(results.hull, 0) self.assertAlmostEqual(results.armor, 0) self.assertAlmostEqual(results.shield, 0) self.assertAlmostEqual(results.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_uniform(self): fit = Fit() item = Ship(self.mktype(attrs={ AttrId.hp: 1, AttrId.em_dmg_resonance: 0.8, AttrId.therm_dmg_resonance: 0.8, AttrId.kin_dmg_resonance: 0.8, AttrId.expl_dmg_resonance: 0.8, AttrId.armor_hp: 10, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.4, AttrId.armor_kin_dmg_resonance: 0.4, AttrId.armor_expl_dmg_resonance: 0.4, AttrId.shield_capacity: 100, AttrId.shield_em_dmg_resonance: 0.2, AttrId.shield_therm_dmg_resonance: 0.2, AttrId.shield_kin_dmg_resonance: 0.2, AttrId.shield_expl_dmg_resonance: 0.2}).id) fit.ship = item # Verification results = item.get_ehp(DmgProfile(1, 1, 1, 1)) self.assertAlmostEqual(results.hull, 1.25) self.assertAlmostEqual(results.armor, 25) self.assertAlmostEqual(results.shield, 500) self.assertAlmostEqual(results.total, 526.25) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_generic(self): fit = Fit() item = Ship(self.mktype(attrs={ AttrId.em_dmg_resonance: 0.01, AttrId.therm_dmg_resonance: 0.02, AttrId.kin_dmg_resonance: 0.03, AttrId.expl_dmg_resonance: 0.04, AttrId.armor_em_dmg_resonance: 0.05, AttrId.armor_therm_dmg_resonance: 0.06, AttrId.armor_kin_dmg_resonance: 0.07, AttrId.armor_expl_dmg_resonance: 0.08, AttrId.shield_em_dmg_resonance: 0.09, AttrId.shield_therm_dmg_resonance: 0.1, AttrId.shield_kin_dmg_resonance: 0.11, AttrId.shield_expl_dmg_resonance: 0.12}).id) fit.ship = item # Verification self.assertAlmostEqual(item.resists.hull.em, 0.99) self.assertAlmostEqual(item.resists.hull.thermal, 0.98) self.assertAlmostEqual(item.resists.hull.kinetic, 0.97) self.assertAlmostEqual(item.resists.hull.explosive, 0.96) self.assertAlmostEqual(item.resists.armor.em, 0.95) self.assertAlmostEqual(item.resists.armor.thermal, 0.94) self.assertAlmostEqual(item.resists.armor.kinetic, 0.93) self.assertAlmostEqual(item.resists.armor.explosive, 0.92) self.assertAlmostEqual(item.resists.shield.em, 0.91) self.assertAlmostEqual(item.resists.shield.thermal, 0.9) self.assertAlmostEqual(item.resists.shield.kinetic, 0.89) self.assertAlmostEqual(item.resists.shield.explosive, 0.88) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_attr_hp_all_absent(self): fit = Fit() item = Ship(self.mktype(attrs={ AttrId.em_dmg_resonance: 0.9, AttrId.therm_dmg_resonance: 0.8, AttrId.kin_dmg_resonance: 0.7, AttrId.expl_dmg_resonance: 0.6, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.6, AttrId.armor_kin_dmg_resonance: 0.8, AttrId.armor_expl_dmg_resonance: 0.9, AttrId.shield_em_dmg_resonance: 1.0, AttrId.shield_therm_dmg_resonance: 0.8, AttrId.shield_kin_dmg_resonance: 0.6, AttrId.shield_expl_dmg_resonance: 0.5}).id) fit.ship = item # Verification results = item.get_ehp(DmgProfile(25, 6, 8.333, 1)) self.assertAlmostEqual(results.hull, 0) self.assertAlmostEqual(results.armor, 0) self.assertAlmostEqual(results.shield, 0) self.assertAlmostEqual(results.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_attr_hp_all_absent(self): fit = Fit() item = Ship( self.mktype( attrs={ AttrId.em_dmg_resonance: 0.8, AttrId.therm_dmg_resonance: 0.8, AttrId.kin_dmg_resonance: 0.8, AttrId.expl_dmg_resonance: 0.8, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.4, AttrId.armor_kin_dmg_resonance: 0.4, AttrId.armor_expl_dmg_resonance: 0.4, AttrId.shield_em_dmg_resonance: 0.2, AttrId.shield_therm_dmg_resonance: 0.2, AttrId.shield_kin_dmg_resonance: 0.2, AttrId.shield_expl_dmg_resonance: 0.2 }).id) fit.ship = item # Verification self.assertAlmostEqual(item.worst_case_ehp.hull, 0) self.assertAlmostEqual(item.worst_case_ehp.armor, 0) self.assertAlmostEqual(item.worst_case_ehp.shield, 0) self.assertAlmostEqual(item.worst_case_ehp.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_worst_em(self): fit = Fit() item = Ship(self.mktype(attrs={ AttrId.hp: 1, AttrId.em_dmg_resonance: 0.8, AttrId.therm_dmg_resonance: 0.7, AttrId.kin_dmg_resonance: 0.7, AttrId.expl_dmg_resonance: 0.7, AttrId.armor_hp: 10, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.3, AttrId.armor_kin_dmg_resonance: 0.3, AttrId.armor_expl_dmg_resonance: 0.3, AttrId.shield_capacity: 100, AttrId.shield_em_dmg_resonance: 0.2, AttrId.shield_therm_dmg_resonance: 0.1, AttrId.shield_kin_dmg_resonance: 0.1, AttrId.shield_expl_dmg_resonance: 0.1}).id) fit.ship = item # Verification self.assertAlmostEqual(item.worst_case_ehp.hull, 1.25) self.assertAlmostEqual(item.worst_case_ehp.armor, 25) self.assertAlmostEqual(item.worst_case_ehp.shield, 500) self.assertAlmostEqual(item.worst_case_ehp.total, 526.25) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_switch_item(self): # Here we create 2 separate fits with ships; each ship affects module # with different strength. When we pass module from one fit to another, # its internal attribute storage should be cleared. If it wasn't # cleared, we wouldn't be able to get refreshed value of attribute # Setup src_attr_id = self.allocate_attr_id('src1', 'src2') self.mkattr(src='src1', attr_id=src_attr_id) self.mkattr(src='src2', attr_id=src_attr_id) tgt_attr_id = self.allocate_attr_id('src1', 'src2') self.mkattr(src='src1', attr_id=tgt_attr_id) self.mkattr(src='src2', attr_id=tgt_attr_id) modifier = self.mkmod( affectee_filter=ModAffecteeFilter.domain, affectee_domain=ModDomain.ship, affectee_attr_id=tgt_attr_id, operator=ModOperator.post_percent, affector_attr_id=src_attr_id) effect_id = self.allocate_effect_id('src1', 'src2') effect_src1 = self.mkeffect( src='src1', effect_id=effect_id, category_id=EffectCategoryId.passive, modifiers=[modifier]) effect_src2 = self.mkeffect( src='src2', effect_id=effect_id, category_id=EffectCategoryId.passive, modifiers=[modifier]) ship_type_id = self.allocate_type_id('src1', 'src2') ship1 = Ship(self.mktype( src='src1', type_id=ship_type_id, attrs={src_attr_id: 10}, effects=[effect_src1]).id) ship2 = Ship(self.mktype( src='src2', type_id=ship_type_id, attrs={src_attr_id: 20}, effects=[effect_src2]).id) item_type_id = self.allocate_type_id('src1', 'src2') self.mktype(src='src1', type_id=item_type_id, attrs={tgt_attr_id: 50}) self.mktype(src='src2', type_id=item_type_id, attrs={tgt_attr_id: 50}) item = Rig(item_type_id) fit1 = Fit(SolarSystem('src1')) fit1.ship = ship1 fit2 = Fit(SolarSystem('src2')) fit2.ship = ship2 fit1.rigs.add(item) self.assertAlmostEqual(item.attrs.get(tgt_attr_id), 55) # Action fit1.rigs.remove(item) fit2.rigs.add(item) # Verification self.assertAlmostEqual(item.attrs.get(tgt_attr_id), 60) # Cleanup self.assert_solsys_buffers_empty(fit1.solar_system) self.assert_solsys_buffers_empty(fit2.solar_system) self.assert_log_entries(0)
def test_switch_fit(self): # Here we check if attributes are updated if fit gets new source # instance # Setup src_attr_id = self.allocate_attr_id('src1', 'src2') self.mkattr(src='src1', attr_id=src_attr_id) self.mkattr(src='src2', attr_id=src_attr_id) tgt_attr_id = self.allocate_attr_id('src1', 'src2') max_attr_id = self.allocate_attr_id('src1', 'src2') self.mkattr(src='src1', attr_id=tgt_attr_id, max_attr_id=max_attr_id) self.mkattr(src='src2', attr_id=tgt_attr_id, max_attr_id=max_attr_id) self.mkattr(src='src1', attr_id=max_attr_id, default_value=54.5) self.mkattr(src='src2', attr_id=max_attr_id, default_value=88) modifier = self.mkmod( affectee_filter=ModAffecteeFilter.domain, affectee_domain=ModDomain.ship, affectee_attr_id=tgt_attr_id, operator=ModOperator.post_percent, affector_attr_id=src_attr_id) effect_id = self.allocate_effect_id('src1', 'src2') effect_src1 = self.mkeffect( src='src1', effect_id=effect_id, category_id=EffectCategoryId.passive, modifiers=[modifier]) effect_src2 = self.mkeffect( src='src2', effect_id=effect_id, category_id=EffectCategoryId.passive, modifiers=[modifier]) ship_type_id = self.allocate_type_id('src1', 'src2') self.mktype( src='src1', type_id=ship_type_id, attrs={src_attr_id: 10}, effects=[effect_src1]) self.mktype( src='src2', type_id=ship_type_id, attrs={src_attr_id: 20}, effects=[effect_src2]) item_type_id = self.allocate_type_id('src1', 'src2') self.mktype(src='src1', type_id=item_type_id, attrs={tgt_attr_id: 50}) self.mktype(src='src2', type_id=item_type_id, attrs={tgt_attr_id: 75}) fit = Fit() ship = Ship(ship_type_id) item = Rig(item_type_id) fit.ship = ship fit.rigs.add(item) # 50 * 1.1, but capped at 54.5 self.assertAlmostEqual(item.attrs.get(tgt_attr_id), 54.5) # Action fit.solar_system.source = 'src2' # Verification # 75 * 1.2, but capped at 88 self.assertAlmostEqual(item.attrs.get(tgt_attr_id), 88) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_none_to_none(self): fit = Fit() # Action fit.ship = None # Verification self.assertIsNone(fit.ship) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_none_to_item(self): fit = Fit() item = Ship(self.mktype().id) # Action fit.ship = item # Verification self.assertIs(fit.ship, item) # Cleanup self.assert_item_buffers_empty(item) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_switch_fit(self): # Here we check if attributes are updated if fit gets new source # instance # Setup src_attr_id = self.allocate_attr_id('src1', 'src2') self.mkattr(src='src1', attr_id=src_attr_id) self.mkattr(src='src2', attr_id=src_attr_id) tgt_attr_id = self.allocate_attr_id('src1', 'src2') max_attr_id = self.allocate_attr_id('src1', 'src2') self.mkattr(src='src1', attr_id=tgt_attr_id, max_attr_id=max_attr_id) self.mkattr(src='src2', attr_id=tgt_attr_id, max_attr_id=max_attr_id) self.mkattr(src='src1', attr_id=max_attr_id, default_value=54.5) self.mkattr(src='src2', attr_id=max_attr_id, default_value=88) modifier = self.mkmod(affectee_filter=ModAffecteeFilter.domain, affectee_domain=ModDomain.ship, affectee_attr_id=tgt_attr_id, operator=ModOperator.post_percent, affector_attr_id=src_attr_id) effect_id = self.allocate_effect_id('src1', 'src2') effect_src1 = self.mkeffect(src='src1', effect_id=effect_id, category_id=EffectCategoryId.passive, modifiers=[modifier]) effect_src2 = self.mkeffect(src='src2', effect_id=effect_id, category_id=EffectCategoryId.passive, modifiers=[modifier]) ship_type_id = self.allocate_type_id('src1', 'src2') self.mktype(src='src1', type_id=ship_type_id, attrs={src_attr_id: 10}, effects=[effect_src1]) self.mktype(src='src2', type_id=ship_type_id, attrs={src_attr_id: 20}, effects=[effect_src2]) item_type_id = self.allocate_type_id('src1', 'src2') self.mktype(src='src1', type_id=item_type_id, attrs={tgt_attr_id: 50}) self.mktype(src='src2', type_id=item_type_id, attrs={tgt_attr_id: 75}) fit = Fit() ship = Ship(ship_type_id) item = Rig(item_type_id) fit.ship = ship fit.rigs.add(item) # 50 * 1.1, but capped at 54.5 self.assertAlmostEqual(item.attrs.get(tgt_attr_id), 54.5) # Action fit.solar_system.source = 'src2' # Verification # 75 * 1.2, but capped at 88 self.assertAlmostEqual(item.attrs.get(tgt_attr_id), 88) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_attr_all_absent(self): fit = Fit() item = Ship(self.mktype().id) fit.ship = item # Verification self.assertAlmostEqual(item.hp.hull, 0) self.assertAlmostEqual(item.hp.armor, 0) self.assertAlmostEqual(item.hp.shield, 0) self.assertAlmostEqual(item.hp.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_not_loaded(self): fit = Fit() item = Ship(self.allocate_type_id()) fit.ship = item # Verification self.assertAlmostEqual(item.hp.hull, 0) self.assertAlmostEqual(item.hp.armor, 0) self.assertAlmostEqual(item.hp.shield, 0) self.assertAlmostEqual(item.hp.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_not_loaded(self): fit = Fit() item = Ship(self.allocate_type_id()) fit.ship = item # Verification self.assertAlmostEqual(item.worst_case_ehp.hull, 0) self.assertAlmostEqual(item.worst_case_ehp.armor, 0) self.assertAlmostEqual(item.worst_case_ehp.shield, 0) self.assertAlmostEqual(item.worst_case_ehp.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_not_loaded(self): fit = Fit() item = Ship(self.allocate_type_id()) fit.ship = item # Verification results = item.get_ehp(DmgProfile(1, 1, 1, 1)) self.assertAlmostEqual(results.hull, 0) self.assertAlmostEqual(results.armor, 0) self.assertAlmostEqual(results.shield, 0) self.assertAlmostEqual(results.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_none_to_item_type_failure(self): fit = Fit() item = Stance(self.mktype().id) # Action with self.assertRaises(TypeError): fit.ship = item # Verification self.assertIsNone(fit.ship) # Check that item which failed to be added can be assigned to other # field fit.stance = item # Cleanup self.assert_item_buffers_empty(item) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_to_item(self): fit = Fit() ship_type = self.mktype() item1 = Ship(ship_type.id) item2 = Ship(ship_type.id) fit.ship = item1 # Action fit.ship = item2 # Verification self.assertIs(fit.ship, item2) # Cleanup self.assert_item_buffers_empty(item1) self.assert_item_buffers_empty(item2) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_generic(self): fit = Fit() item = Ship(self.mktype(attrs={ AttrId.hp: 8, AttrId.armor_hp: 10, AttrId.shield_capacity: 12}).id) fit.ship = item # Verification self.assertAlmostEqual(item.hp.hull, 8) self.assertAlmostEqual(item.hp.armor, 10) self.assertAlmostEqual(item.hp.shield, 12) self.assertAlmostEqual(item.hp.total, 30) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_to_item_type_failure(self): fit = Fit() item1 = Ship(self.mktype().id) item2 = Stance(self.mktype().id) fit.ship = item1 # Action with self.assertRaises(TypeError): fit.ship = item2 # Verification self.assertIs(fit.ship, item1) fit.stance = item2 # Cleanup self.assert_item_buffers_empty(item1) self.assert_item_buffers_empty(item2) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_fit_none_to_non_charge(self): fit = Fit() module = ModuleHigh(self.mktype().id, state=State.active, charge=None) non_charge = Stance(self.mktype().id) fit.modules.high.append(module) # Action with self.assertRaises(TypeError): module.charge = non_charge # Verification self.assertIsNone(module.charge) fit.stance = non_charge # Cleanup self.assert_item_buffers_empty(module) self.assert_item_buffers_empty(non_charge) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_none_to_item_value_failure(self): fit = Fit() fit_other = Fit() item = Ship(self.mktype().id) fit_other.ship = item # Action with self.assertRaises(ValueError): fit.ship = item # Verification self.assertIsNone(fit.ship) self.assertIs(fit_other.ship, item) # Cleanup self.assert_item_buffers_empty(item) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_solsys_buffers_empty(fit_other.solar_system) self.assert_log_entries(0)
def test_charge_attr_em_absent(self): fit = Fit() item = ModuleHigh( self.mktype( attrs={ AttrId.dmg_mult: 2.5, AttrId.capacity: 2.0, self.cycle_attr.id: 500, AttrId.charge_rate: 1.0, AttrId.reload_time: 5000}, effects=[self.effect], default_effect=self.effect).id, state=State.active) item.charge = Charge(self.mktype(attrs={ AttrId.volume: 0.2, AttrId.therm_dmg: 6.3, AttrId.kin_dmg: 7.4, AttrId.expl_dmg: 8.5}).id) fit.modules.high.append(item) # Verification volley = item.get_volley() self.assertAlmostEqual(volley.em, 0) self.assertAlmostEqual(volley.thermal, 15.75) self.assertAlmostEqual(volley.kinetic, 18.5) self.assertAlmostEqual(volley.explosive, 21.25) self.assertAlmostEqual(volley.total, 55.5) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_contains(self): fit = Fit() item1 = ModuleHigh(self.mktype().id) item2 = ModuleHigh(self.mktype().id) self.assertFalse(item1 in fit.modules.high) self.assertFalse(None in fit.modules.high) self.assertFalse(item2 in fit.modules.high) fit.modules.high.append(item1) self.assertTrue(item1 in fit.modules.high) self.assertFalse(None in fit.modules.high) self.assertFalse(item2 in fit.modules.high) fit.modules.high.place(3, item2) self.assertTrue(item1 in fit.modules.high) self.assertTrue(None in fit.modules.high) self.assertTrue(item2 in fit.modules.high) fit.modules.high.remove(item1) self.assertFalse(item1 in fit.modules.high) self.assertTrue(None in fit.modules.high) self.assertTrue(item2 in fit.modules.high) fit.modules.high.remove(item2) self.assertFalse(item1 in fit.modules.high) self.assertFalse(None in fit.modules.high) self.assertFalse(item2 in fit.modules.high) # Cleanup self.assert_item_buffers_empty(item1) self.assert_item_buffers_empty(item2) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_enabling(self): # Setup chance_attr = self.mkattr() src_attr = self.mkattr() tgt_attr = self.mkattr() modifier = self.mkmod(affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.self, affectee_attr_id=tgt_attr.id, operator=ModOperator.post_mul, affector_attr_id=src_attr.id) effect = self.mkeffect(category_id=EffectCategoryId.passive, fitting_usage_chance_attr_id=chance_attr.id, modifiers=[modifier]) fit = Fit() item = Booster( self.mktype(attrs={ chance_attr.id: 0.5, tgt_attr.id: 100, src_attr.id: 1.2 }, effects=[effect]).id) fit.boosters.add(item) self.assertAlmostEqual(item.attrs[tgt_attr.id], 100) # Action item.set_side_effect_status(effect.id, True) # Verification self.assertIs(item.side_effects[effect.id].status, True) self.assertAlmostEqual(item.attrs[tgt_attr.id], 120) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_disabling_not_side_effect(self): # Setup src_attr = self.mkattr() tgt_attr = self.mkattr() modifier = self.mkmod(affectee_filter=ModAffecteeFilter.item, affectee_domain=ModDomain.self, affectee_attr_id=tgt_attr.id, operator=ModOperator.post_mul, affector_attr_id=src_attr.id) effect = self.mkeffect(category_id=EffectCategoryId.passive, modifiers=[modifier]) fit = Fit() item = Booster( self.mktype(attrs={ tgt_attr.id: 100, src_attr.id: 1.2 }, effects=[effect]).id) fit.boosters.add(item) self.assertAlmostEqual(item.attrs[tgt_attr.id], 120) # Verification with self.assertRaises(NoSuchSideEffectError): item.set_side_effect_status(effect.id, False) self.assertNotIn(effect.id, item.side_effects) self.assertAlmostEqual(item.attrs[tgt_attr.id], 120) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_none(self): fit = Fit() item1 = ModuleHigh(self.mktype().id) item2 = ModuleHigh(self.mktype().id) fit.modules.high.append(item1) fit.modules.high.append(item2) # Action with self.assertRaises(ValueError): fit.modules.high.free(None) # Verification self.assertIs(len(fit.modules.high), 2) self.assertIs(fit.modules.high[0], item1) self.assertIs(fit.modules.high[1], item2) # Cleanup fit.modules.high.free(item1) # Action fit.modules.high.free(None) # Verification self.assertIs(len(fit.modules.high), 2) self.assertIsNone(fit.modules.high[0]) self.assertIs(fit.modules.high[1], item2) # Cleanup self.assert_item_buffers_empty(item1) self.assert_item_buffers_empty(item2) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_effect_disabled(self): fit = Fit() item = Drone(self.mktype(attrs={ AttrId.dmg_mult: 2.5, AttrId.em_dmg: 52, AttrId.therm_dmg: 63, AttrId.kin_dmg: 74, AttrId.expl_dmg: 85, self.cycle_attr.id: 4000 }, effects=[self.effect], default_effect=self.effect).id, state=State.active) item.set_effect_mode(self.effect.id, EffectMode.force_stop) fit.drones.add(item) # Verification volley = item.get_volley() self.assertAlmostEqual(volley.em, 0) self.assertAlmostEqual(volley.thermal, 0) self.assertAlmostEqual(volley.kinetic, 0) self.assertAlmostEqual(volley.explosive, 0) self.assertAlmostEqual(volley.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_charge_attr_em_absent(self): fit = Fit() item = ModuleHigh(self.mktype(attrs={ AttrId.capacity: 60.0, self.cycle_attr.id: 5000, AttrId.charge_rate: 1.0, AttrId.reload_time: 10000, AttrId.module_reactivation_delay: 120000 }, effects=[self.effect_item], default_effect=self.effect_item).id, state=State.active) item.charge = Charge( self.mktype(attrs={ AttrId.volume: 30.0, AttrId.therm_dmg: 6300, AttrId.kin_dmg: 7400, AttrId.expl_dmg: 8500 }, effects=[self.effect_charge], default_effect=self.effect_charge).id) fit.modules.high.append(item) # Verification volley = item.get_volley() self.assertAlmostEqual(volley.em, 0) self.assertAlmostEqual(volley.thermal, 6300) self.assertAlmostEqual(volley.kinetic, 7400) self.assertAlmostEqual(volley.explosive, 8500) self.assertAlmostEqual(volley.total, 22200) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_reload(self): fit = Fit() bomb_type = self.make_charge_type({ AttrId.em_dmg: 52, AttrId.therm_dmg: 63, AttrId.kin_dmg: 74, AttrId.expl_dmg: 85 }) item = self.make_item({ AttrId.fighter_ability_launch_bomb_type: bomb_type.id, AttrId.fighter_squadron_max_size: 9, self.cycle_attr.id: 60000 }) fit.fighters.add(item) # Verification dps = item.get_dps(reload=True) self.assertAlmostEqual(dps.em, 7.8) self.assertAlmostEqual(dps.thermal, 9.45) self.assertAlmostEqual(dps.kinetic, 11.1) self.assertAlmostEqual(dps.explosive, 12.75) self.assertAlmostEqual(dps.total, 41.1) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_charge_not_loaded(self): fit = Fit() item = ModuleHigh( self.mktype( attrs={ AttrId.dmg_mult: 2.5, AttrId.capacity: 2.0, self.cycle_attr.id: 500, AttrId.charge_rate: 1.0, AttrId.reload_time: 5000}, effects=[self.effect], default_effect=self.effect).id, state=State.active) item.charge = Charge(self.allocate_type_id()) fit.modules.high.append(item) # Verification volley = item.get_volley() self.assertAlmostEqual(volley.em, 0) self.assertAlmostEqual(volley.thermal, 0) self.assertAlmostEqual(volley.kinetic, 0) self.assertAlmostEqual(volley.explosive, 0) self.assertAlmostEqual(volley.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_reload(self): fit = Fit() item = ModuleHigh( self.mktype( attrs={ AttrId.capacity: 2.0, self.cycle_attr.id: 2000, AttrId.charge_rate: 1.0, AttrId.reload_time: 10000}, effects=[self.effect_item], default_effect=self.effect_item).id, state=State.active) item.charge = Charge(self.mktype( attrs={ AttrId.volume: 0.1, AttrId.em_dmg: 5.2, AttrId.therm_dmg: 6.3, AttrId.kin_dmg: 7.4, AttrId.expl_dmg: 8.5}, effects=[self.effect_charge], default_effect=self.effect_charge).id) fit.modules.high.append(item) # Verification dps = item.get_dps(reload=True) self.assertAlmostEqual(dps.em, 2.08) self.assertAlmostEqual(dps.thermal, 2.52) self.assertAlmostEqual(dps.kinetic, 2.96) self.assertAlmostEqual(dps.explosive, 3.4) self.assertAlmostEqual(dps.total, 10.96) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_reactivation_shorter_than_reload(self): fit = Fit() item = ModuleHigh(self.mktype(attrs={ AttrId.dmg_mult: 2.5, AttrId.capacity: 2.0, self.cycle_attr.id: 500, AttrId.charge_rate: 1.0, AttrId.reload_time: 6500, AttrId.module_reactivation_delay: 1500 }, effects=[self.effect], default_effect=self.effect).id, state=State.active) item.charge = Charge( self.mktype( attrs={ AttrId.volume: 0.2, AttrId.em_dmg: 5.2, AttrId.therm_dmg: 6.3, AttrId.kin_dmg: 7.4, AttrId.expl_dmg: 8.5 }).id) fit.modules.high.append(item) # Verification dps = item.get_dps(reload=True) self.assertAlmostEqual(dps.em, 5.2) self.assertAlmostEqual(dps.thermal, 6.3) self.assertAlmostEqual(dps.kinetic, 7.4) self.assertAlmostEqual(dps.explosive, 8.5) self.assertAlmostEqual(dps.total, 27.4) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_effective(self): fit = Fit() item = ModuleHigh(self.mktype(attrs={ AttrId.dmg_mult: 2.5, AttrId.capacity: 2.0, self.cycle_attr.id: 500, AttrId.charge_rate: 1.0, AttrId.reload_time: 5000 }, effects=[self.effect], default_effect=self.effect).id, state=State.active) item.charge = Charge( self.mktype( attrs={ AttrId.volume: 0.2, AttrId.em_dmg: 5.2, AttrId.therm_dmg: 6.3, AttrId.kin_dmg: 7.4, AttrId.expl_dmg: 8.5 }).id) fit.modules.high.append(item) # Verification profile = ResistProfile(0.2, 0.2, 0.8, 1) dps = item.get_dps(tgt_resists=profile) self.assertAlmostEqual(dps.em, 20.8) self.assertAlmostEqual(dps.thermal, 25.2) self.assertAlmostEqual(dps.kinetic, 7.4) self.assertAlmostEqual(dps.explosive, 0) self.assertAlmostEqual(dps.total, 53.4) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_slice(self): fit = Fit() item1 = ModuleHigh(self.mktype().id) item2 = ModuleHigh(self.mktype().id) fit.modules.high.append(item1) fit.modules.high.place(3, item2) slice_full = fit.modules.high[:] self.assertEqual(len(slice_full), 4) self.assertIs(slice_full[0], item1) self.assertIsNone(slice_full[1]) self.assertIsNone(slice_full[2]) self.assertIs(slice_full[3], item2) slice_positive = fit.modules.high[0:2] self.assertEqual(len(slice_positive), 2) self.assertIs(slice_positive[0], item1) self.assertIsNone(slice_positive[1]) slice_negative = fit.modules.high[-2:] self.assertEqual(len(slice_negative), 2) self.assertIsNone(slice_negative[0]) self.assertIs(slice_negative[1], item2) slice_step = fit.modules.high[::2] self.assertEqual(len(slice_step), 2) self.assertIs(slice_step[0], item1) self.assertIsNone(slice_step[1]) # Cleanup self.assert_item_buffers_empty(item1) self.assert_item_buffers_empty(item2) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_item_after_nones(self): fit = Fit() item1 = ModuleHigh(self.mktype().id) item2 = ModuleHigh(self.mktype().id) item3 = ModuleHigh(self.mktype().id) fit.modules.high.append(item1) fit.modules.high.place(3, item2) fit.modules.high.place(6, item3) # Action fit.modules.high.free(item2) # Verification self.assertEqual(len(fit.modules.high), 7) self.assertIs(fit.modules.high[0], item1) self.assertIsNone(fit.modules.high[1]) self.assertIsNone(fit.modules.high[2]) self.assertIsNone(fit.modules.high[3]) self.assertIsNone(fit.modules.high[4]) self.assertIsNone(fit.modules.high[5]) self.assertIs(fit.modules.high[6], item3) # Action fit.modules.high.free(item3) # Verification self.assertEqual(len(fit.modules.high), 1) self.assertIs(fit.modules.high[0], item1) # Cleanup self.assert_item_buffers_empty(item1) self.assert_item_buffers_empty(item2) self.assert_item_buffers_empty(item3) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
def test_detached_module_charge_to_non_charge(self): fit_other = Fit() module = ModuleHigh(self.mktype().id, state=State.active, charge=None) charge = Charge(self.mktype().id) non_charge = Stance(self.mktype().id) module.charge = charge # Action with self.assertRaises(TypeError): module.charge = non_charge # Verification self.assertIs(module.charge, charge) fit_other.stance = non_charge # Cleanup self.assert_item_buffers_empty(module) self.assert_item_buffers_empty(charge) self.assert_item_buffers_empty(non_charge) self.assert_solsys_buffers_empty(fit_other.solar_system) self.assert_log_entries(0)
def __generic_init(self): char_type_id = Type.character_static EveItemWrapper.__init__(self, char_type_id) # Attributes which store objects hidden behind properties self.__source = None # Set with fits which are loaded and use this character self.__loaded_proxies = WeakSet() self.skills = SkillCoreSet(self) self._eos_fit = EosFit()
def test_item_to_item_value_failure(self): fit = Fit() fit_other = Fit() ship_type = self.mktype() item1 = Ship(ship_type.id) item2 = Ship(ship_type.id) fit.ship = item1 fit_other.ship = item2 # Action with self.assertRaises(ValueError): fit.ship = item2 # Verification self.assertIs(fit.ship, item1) self.assertIs(fit_other.ship, item2) # Cleanup self.assert_item_buffers_empty(item1) self.assert_item_buffers_empty(item2) self.assert_solsys_buffers_empty(fit.solar_system) self.assert_solsys_buffers_empty(fit_other.solar_system) self.assert_log_entries(0)
class RestrictionTestCase(IntegrationTestCase): """Class which should be used by restriction service tests. Attributes: fit: Pre-created fit. """ def setUp(self): IntegrationTestCase.setUp(self) self.fit = Fit() def get_error(self, item, restriction): """Get restriction error for passed item of passed restriction type. Args: item: Item which should be validated. restriction: Restriction type which we're interested in. Errors of any other restriction types will be ignored. Returns: If specified error occurred with specified item, returns error data; if it didn't, returns None. """ skip_checks = set(Restriction).difference([restriction]) try: self.fit.validate(skip_checks) except ValidationError as e: error_data = e.args[0] if item not in error_data: return None item_error = error_data[item] if restriction not in item_error: return None return item_error[restriction] else: return None def get_log(self, name='eos.restriction*'): return IntegrationTestCase.get_log(self, name=name)
def __generic_init(self): # Attributes which store objects hidden behind properties self.__source = None self.__ship = None self.__character_proxy = None self.__character_core = None # Eos fit will be primary point of using Eos calculation engine for # fit-specific data self._eos_fit = EosFit() # Manages fit-specific data needed for undo/redo self._cmd_mgr = CommandManager(100) # There's little sense in changing proxy character, thus we assign # it here and it stays with fit forever self.__set_character_proxy(CharacterProxy())
def test_item_attr_hp_all_absent(self): fit = Fit() item = Ship(self.mktype(attrs={ AttrId.em_dmg_resonance: 0.8, AttrId.therm_dmg_resonance: 0.8, AttrId.kin_dmg_resonance: 0.8, AttrId.expl_dmg_resonance: 0.8, AttrId.armor_em_dmg_resonance: 0.4, AttrId.armor_therm_dmg_resonance: 0.4, AttrId.armor_kin_dmg_resonance: 0.4, AttrId.armor_expl_dmg_resonance: 0.4, AttrId.shield_em_dmg_resonance: 0.2, AttrId.shield_therm_dmg_resonance: 0.2, AttrId.shield_kin_dmg_resonance: 0.2, AttrId.shield_expl_dmg_resonance: 0.2}).id) fit.ship = item # Verification self.assertAlmostEqual(item.worst_case_ehp.hull, 0) self.assertAlmostEqual(item.worst_case_ehp.armor, 0) self.assertAlmostEqual(item.worst_case_ehp.shield, 0) self.assertAlmostEqual(item.worst_case_ehp.total, 0) # Cleanup self.assert_solsys_buffers_empty(fit.solar_system) self.assert_log_entries(0)
class Character(PyfaBase, EveItemWrapper): """ "Core" character class. It should be used for managing characters (e.g. in character editor). Fits will use proxy twin of the character. We cannot use core because different fits carry different attributes on character and all child entities (like skills, on-character implants, and so on). Pyfa model children: .RestrictedSet(skills) """ __tablename__ = 'characters' id = Column('character_id', Integer, primary_key=True) alias = Column(String) def __init__(self, alias='', source=None): self.__generic_init() # Use default source, unless specified otherwise if source is None: source = SourceManager.default self.source = source self.alias = alias @reconstructor def _dbinit(self): self.__generic_init() # Use default source for all reconstructed characters self.source = SourceManager.default # Restore entities which are stored on character for skill in self._skills: self.skill.add(skill) def __generic_init(self): char_type_id = Type.character_static EveItemWrapper.__init__(self, char_type_id) # Attributes which store objects hidden behind properties self.__source = None # Set with fits which are loaded and use this character self.__loaded_proxies = WeakSet() self.skills = SkillCoreSet(self) self._eos_fit = EosFit() # EVE item wrapper methods @property def _source(self): return self.source @property def _eos_item(self): return self._eos_fit.character @property def _src_children(self): return get_src_children(chain( self.skills, )) # Miscellanea public stuff @property def source(self): return self.__source @source.setter def source(self, new_source): # Attempt to fetch source from source manager if passed object # is not instance of source class if not isinstance(new_source, Source) and new_source is not None: new_source = SourceManager.get(new_source) old_source = self.source # Do not update anything if sources are the same if new_source is old_source: return self.__source = new_source # Update eos model with new data self._eos_fit.source = getattr(new_source, 'eos', None) # Update pyfa model with new data # Unlike fit, character represents EVE item, thus we need # to update it too self._update_source() for src_child in self._src_children: src_child._update_source() persist = pyfa_persist abandon = pyfa_abandon def validate(self): self._eos_fit.validate() # Auxiliary methods def _proxy_iter(self): """ Safe iterator over related character proxies, avoids issues with set size getting changed by GC during iteration. """ for char_proxy in tuple(self.__loaded_proxies): yield char_proxy def _link_proxy(self, char_proxy): """Create connection between character core and proxy""" self.__loaded_proxies.add(char_proxy) def _unlink_proxy(self, char_proxy): """Remove connection between character core and proxy""" self.__loaded_proxies.discard(char_proxy) def __repr__(self): spec = ['id'] return make_repr_str(self, spec)
class Fit(PyfaBase): """ Full pyfa model of fit: .fit .character_core (read-write fit-agnostic) .RestrictedSet(skills) .character_proxy (read-only fit-specific) .RestrictedSet(skills) .ship .stance .{subsystems} .modules.[high]/[med]/[low] """ __tablename__ = 'fits' id = Column('fit_id', Integer, primary_key=True) name = Column('fit_name', String, nullable=False) _db_ship_type_id = Column('ship_type_id', Integer) _db_stance_type_id = Column('stance_type_id', Integer) _db_character_id = Column('character_id', Integer, ForeignKey('characters.character_id')) _db_character = relationship('Character') def __init__(self, name='', source=None, ship=None): self.__generic_init() # Use default source, unless specified otherwise if source is None: source = SourceManager.default self._set_source(source) self._set_ship(ship) self.name = name @reconstructor def _dbinit(self): self.__generic_init() # Use default source for all reconstructed fits self._set_source(SourceManager.default) # Restore entities which are stored on fit in DB if self._db_ship_type_id is not None: self._set_ship(Ship(self._db_ship_type_id)) if self._db_stance_type_id is not None: self.ship._set_stance(Stance(self._db_stance_type_id)) # TODO: find appropriate way to reconstruct modules for module in self._db_modules: pass for subsystem in self._db_subsystems: self.ship.subsystems._add_to_set(subsystem) self.character_core = self._db_character def __generic_init(self): # Attributes which store objects hidden behind properties self.__source = None self.__ship = None self.__character_proxy = None self.__character_core = None # Eos fit will be primary point of using Eos calculation engine for # fit-specific data self._eos_fit = EosFit() # Manages fit-specific data needed for undo/redo self._cmd_mgr = CommandManager(100) # There's little sense in changing proxy character, thus we assign # it here and it stays with fit forever self.__set_character_proxy(CharacterProxy()) # Define list of source-dependent child objects, it's necessary # to update fit source @property def _src_children(self): return get_src_children(chain( (self.ship,), # Just proxy, character core is completely separate entity with # its own source management (self.character_proxy,), )) # Read-only info @property def stats(self): return self._eos_fit.stats # Children getters/setters @property def character_core(self): return self.__character_core @character_core.setter def character_core(self, new_char_core): old_char_core = self.__character_core if new_char_core is old_char_core: return # Update child reference self.__character_core = new_char_core # Update DB self._db_character = new_char_core # Handle all interactions between new character core and # character proxy (which is attached to this fit) on proxy # side self.character_proxy._parent_char_core = new_char_core @property def character_proxy(self): """ For character proxy we're not providing setter because it's supposed to stay with fit all the time. """ return self.__character_proxy def __set_character_proxy(self, new_char_proxy): old_char_proxy = self.__character_proxy if new_char_proxy is old_char_proxy: return if old_char_proxy is not None: if old_char_proxy._parent_fit is not self: raise ItemRemovalConsistencyError(old_char_proxy) # Handle all character proxy children removal on proxy itself old_char_proxy._parent_fit = None # Update child reference self.__character_proxy = new_char_proxy if new_char_proxy is not None: if new_char_proxy._parent_fit is not None: raise ItemAlreadyUsedError(new_char_proxy) # Handle all character proxy children addition on proxy itself new_char_proxy._parent_fit = self @property def ship(self): return self.__ship @ship.setter def ship(self, new_ship): command = ShipChangeCommand(self, new_ship) self._cmd_mgr.do(command) def _set_ship(self, new_ship): old_ship = self.__ship if new_ship is old_ship: return if old_ship is not None: if old_ship._parent_fit is not self: raise ItemRemovalConsistencyError(old_ship) old_ship._parent_fit = None self.__ship = new_ship if new_ship is not None: if new_ship._parent_fit is not None: raise ItemAlreadyUsedError(new_ship) new_ship._parent_fit = self # Undo/redo proxies @property def has_undo(self): return self._cmd_mgr.has_undo @property def has_redo(self): return self._cmd_mgr.has_redo def undo(self): self._cmd_mgr.undo() def redo(self): self._cmd_mgr.redo() def purge_commands(self): """ Purge all undos/redos fit currently has. Useful when you want to do some initial setup on the fit, and then purge commands to present fit without undo queue. """ self._cmd_mgr.purge() # Miscellanea public stuff @property def source(self): return self.__source @source.setter def source(self, new_source): command = SourceChangeCommand(self, new_source) self._cmd_mgr.do(command) def _set_source(self, new_source): """ Set fit's source. Source represents EVE data to be used. Required arguments: new_source -- source to use, can be None """ # Attempt to fetch source from source manager if passed object # is not instance of source class if not isinstance(new_source, Source) and new_source is not None: new_source = SourceManager.get(new_source) old_source = self.source # Do not update anything if sources are the same if new_source is old_source: return self.__source = new_source # Update eos model with new data self._eos_fit.source = getattr(new_source, 'eos', None) # Update pyfa model with new data for src_child in self._src_children: src_child._update_source() persist = pyfa_persist abandon = pyfa_abandon def validate(self): self._eos_fit.validate() # Auxiliary methods def __repr__(self): spec = ['id'] return make_repr_str(self, spec)
def setUp(self): IntegrationTestCase.setUp(self) self.fit = Fit()