def test_static(self): """ Test we properly generate the PMF for static values """ for i in range(100): pmf = PMF.static(i) self.assertEqual(pmf.get(i), 1) self.assertEqual(sum(pmf.values), 1)
def test_flatten(self): """ test that flattening two dists into one sums to one """ for pmf_1 in self.pmf_examples: for pmf_2 in self.pmf_examples: for i in range(100): flattened = PMF.flatten( [pmf_1 * (i / 100), pmf_2 * ((100 - i) / 100)]) self.assertRoundEqual(sum(flattened.values), 1)
def test_convolve_many(self): """ test convolving two PMFs """ for pmf_1 in self.pmf_examples: for pmf_2 in self.pmf_examples: pmf_convolved = PMF.convolve_many([pmf_1, pmf_2]) self.assertEqual(len(pmf_convolved.values), len(pmf_1.values) + len(pmf_2.values) - 1) self.assertRoundEqual(pmf_convolved.mean(), pmf_1.mean() + pmf_2.mean())
def test_dn(self): """ Check that we propery generate d(n) PMFs """ for i in range(1, 100): pmf = PMF.dn(i) # You should never be able roll a 0 on a dice self.assertEqual(pmf.get(0), 0) # Check the probability is uniform self.assertTrue(all([x == 1 / i for x in pmf.values[1:]]))
def setUp(self): self.pmf_examples = [ PMF.dn(6), PMF.dn(5), PMF.dn(1), PMF.static(0), PMF.static(5), PMF.dn(6).convert_binomial(5), PMF.dn(6).re_roll_value(1), ]
def parse_rsn(self, value): try: return PMFCollection([PMF.static(int(value or 1))]) except ValueError: match = re.match(r'(?P<number>\d+)?d(?P<faces>\d+)', value.lower()) if match: number, faces = re.match(r'(?P<number>\d+)?d(?P<faces>\d+)', value.lower()).groups() return PMFCollection.mdn( int(number) if number else 1, int(faces)) else: return PMFCollection.empty()
def get_damage_plot(self, tab_data, tab_results): damage_pmfs = [x.total_wounds_dist for x in tab_results] damage_values = PMF.convolve_many(damage_pmfs).cumulative().trim_tail( thresh=10**(-4)).values if len(damage_values) > 1: return { 'x': [i for i, x in enumerate(damage_values)], 'y': [100 * x for i, x in enumerate(damage_values)], 'name': tab_data['inputs'].get('tabname'), } else: return {}
def get_damage_plot(self, tab_data, tab_results, colour): damage_pmfs = [x.total_wounds_dist for x in tab_results] damage_values = PMF.convolve_many(damage_pmfs).cumulative().trim_tail( thresh=10**(-4)).values pts = int(tab_data.get('points', 1)) if len(damage_values) > 1: return { 'x': [i / pts for i, x in enumerate(damage_values)], 'y': [100 * x for i, x in enumerate(damage_values)], 'name': tab_data.get('tabname'), 'line': { 'color': colour }, 'legendgroup': tab_data.get('tabname') } else: return {}
def _tab_graph_data(self, tab_id, callback): tab_results = [] tab_inputs = callback.tab_inputs[tab_id] weapon_metadata = {} tab_enabled = tab_inputs.get('enabled') == 'enabled' for weapon_id in range(self.weapon_count): weapon_inputs = tab_inputs['weapons'].get(weapon_id) if tab_enabled and weapon_inputs and weapon_inputs.get( 'weaponenabled') == 'enabled': results = self.compute_controller.compute( **tab_inputs, **weapon_inputs) tab_results.append(results) weapon_metadata[weapon_id] = { 'mean': results.total_wounds_dist.mean(), 'std': results.total_wounds_dist.std(), } else: weapon_metadata[weapon_id] = { 'mean': -1, 'std': -1, } tab_pmf = PMF.convolve_many([x.total_wounds_dist for x in tab_results]) colour = TAB_COLOURS[tab_id] return { 'graphs': { 'damage': self.get_damage_plot(tab_inputs, tab_results, colour), 'drones': self.get_drone_plot(tab_inputs, tab_results, colour), 'self': self.get_self_damage_plot(tab_inputs, tab_results, colour), }, 'metadata': { 'mean': tab_pmf.mean(), 'std': tab_pmf.std(), 'weapon_metadata': weapon_metadata, }, }
def test_convolution_pmfs(self): """ test that pmfs from convolution have list type values """ self.assertTrue( isinstance(PMF.convolve_many(self.pmf_examples).values, list))