def trigger(self): count_a, count_b = 0, 0 pos_a, pos_b = 0, 0 for p in Universe.instance().permutations: if not any(i.isnumeric() for i in p): continue if not (self.a in p or self.b in p): continue p1, p2 = list(p) position = p1 if p1.isnumeric() else p2 if self.a in p: count_a += 1 pos_a = position else: count_b += 1 pos_b = position for count, position, other, factor in ((count_a, pos_a, self.b, -1), (count_b, pos_b, self.a, 1)): if int(count) != 1: continue for i in Universe.instance().dic['positions']: is_before = int(i) * factor < int(position) if is_before: continue UnlinkCondition("{} {}".format(i, other))
def test_nomatchexception(self): self.fake_dic = { 'colors': ['yellow', 'blue'], 'pets': ['cats', 'dogs'] } Universe.instance().permutations.remove({'yellow', 'dogs'}) Universe.instance().permutations.remove({'yellow', 'cats'}) with self.assertRaises(NoMatchLeftException): Condition.linked_to('yellow')
def trigger(self): count_a, count_b = 0, 0 pos_a, pos_b = 0, 0 permutations = Universe.instance().permutations for p in permutations: if not any(i.isnumeric() for i in p): continue if not (self.a in p or self.b in p): continue p1, p2 = list(p) position = p1 if p1.isnumeric() else p2 if self.a in p: if ({self.b, str(int(position) + 1)} in permutations or {self.b, str(int(position) - 1)} in permutations): count_a += 1 pos_a = position else: UnlinkCondition('{} {}'.format(self.a, position)) else: if ({self.a, str(int(position) + 1)} in permutations or {self.a, str(int(position) - 1)} in permutations): count_b += 1 pos_b = position else: UnlinkCondition('{} {}'.format(self.b, position)) for count, position, other in ( (count_a, pos_a, self.b), (count_b, pos_b, self.a)): if int(count) != 1: continue possible_pos = [] for i in Universe.instance().dic['positions']: if int(i) + 1 == int(position): possible_pos.append(i) continue if int(i) - 1 == int(position): possible_pos.append(i) continue UnlinkCondition("{} {}".format(i, other)) if len(possible_pos) == 1: LinkCondition('{} {}'.format(possible_pos[0], other))
def check_orphans(): vals = list(Universe.instance().dic.values()) for i in range(len(vals)): for j in range(len(vals)): if i == j: continue for element in vals[i]: LinkCondition.check_orphaned_element(element, vals[j])
def check_orphaned_element(element, group): universe = Universe.instance().permutations opts_left = list(filter(lambda i: {element, i} in universe, group)) links = LinkCondition.link_conditions if len(opts_left) == 1 and (opts_left[0], element) not in links: LinkCondition("{0} {1}".format(opts_left[0], element))
def link(self): """Linking two elements means removing the alternatives from the universe's permutations list.""" universe = Universe.instance() should_invoke = False for element in self.group_a: if element == self.a: continue for sub_a in Condition.linked_to(element) | {element}: if {sub_a, self.b} not in universe.permutations: continue universe.permutations.remove({sub_a, self.b}) should_invoke = True for element in self.group_b: if element == self.b: continue for sub_b in Condition.linked_to(element) | {element}: if {sub_b, self.a} not in universe.permutations: continue universe.permutations.remove({sub_b, self.a}) should_invoke = True for linked in Condition.linked_to(self.a): if linked == self.b: continue if (linked, self.b) in LinkCondition.link_conditions: continue LinkCondition('{} {}'.format(self.b, linked)) for linked in Condition.linked_to(self.b): if linked == self.a: continue if (linked, self.a) in LinkCondition.link_conditions: continue LinkCondition('{} {}'.format(self.a, linked)) return should_invoke
def linked_to(element): linked_elements = set() for group in Universe.instance().dic.values(): if element in group: continue possible_combinations = [] candidate = None for item in group: if {item, element} in Universe.instance().permutations: candidate = item possible_combinations.append({item, element}) if len(possible_combinations) == 0: raise NoMatchLeftException(element, group) elif len(possible_combinations) == 1: linked_elements |= {candidate} return linked_elements
def check_valid(self): super().check_valid() universe = Universe.instance() vals = list(i for v in universe.dic.values() for i in v) keys = universe.dic.keys() for key, group in universe.dic.items(): if self.a in group and self.b in group: raise InvalidMember(self.b)
def __init__(self, expression): super().__init__(expression) if self not in BeforeCondition.before_conditions: BeforeCondition.before_conditions.append(self) UnlinkCondition(expression) UnlinkCondition('1 {}'.format(self.b)) UnlinkCondition('{} {}'.format( Universe.instance().dic['positions'][-1], self.a, )) self.trigger()
def test_link(self): self.fake_dic = { 'colors': ['yellow', 'blue'], 'pets': ['cats', 'dogs'] } self.assertTrue(LinkCondition('dogs yellow')) self.assertTrue(LinkCondition('dogs 1')) self.assertEqual( Universe.instance().permutations, [{'yellow', 'dogs'}, {'blue', 'cats'}, {'1', 'yellow'}, {'blue', '2'}, {'cats', '2'}, {'1', 'dogs'}])
def trigger(self): super().trigger() count_a, count_b = 0, 0 pos_a, pos_b = 0, 0 permutations = Universe.instance().permutations for p in permutations: if not any(i.isnumeric() for i in p): continue if not (self.a in p or self.b in p): continue p1, p2 = list(p) position = p1 if p1.isnumeric() else p2 if self.a in p: if {self.b, str(int(position) + 1)} in permutations: count_a += 1 pos_a = position else: UnlinkCondition('{} {}'.format(self.a, position)) else: if {self.a, str(int(position) - 1)} in permutations: count_b += 1 pos_b = position else: UnlinkCondition('{} {}'.format(self.b, position)) for count, position, other, factor in ((count_a, pos_a, self.b, -1), (count_b, pos_b, self.a, 1)): if int(count) != 1: continue for i in Universe.instance().dic['positions']: is_neighbor = int(i) + (1 * factor) == int(position) if is_neighbor: continue UnlinkCondition("{} {}".format(i, other))
def __init__(self, expression): super().__init__(expression) if self not in LeftCondition.left_conditions: LeftCondition.left_conditions.append(self) UnlinkCondition(expression) UnlinkCondition('1 {}'.format(self.b)) UnlinkCondition('{} {}'.format( Universe.instance().dic['positions'][-1], self.a, )) self.trigger() if self.has_changed(): self.invoke_boundaries() LinkCondition.check_orphans()
def check_valid(self): universe = Universe.instance() vals = list(i for v in universe.dic.values() for i in v) keys = universe.dic.keys() for m in (self.a, self.b): if m not in vals: raise InvalidMember(m) for key, group in universe.dic.items(): if self.a in group: self.key_a = key self.group_a = group elif self.b in group: self.key_b = key self.group_b = group
def unlink(self): """Linking two elements means removing the alternatives from the universe's permutations list.""" universe = Universe.instance() should_invoke = False if {self.a, self.b} in universe.permutations: universe.permutations.remove({self.a, self.b}) should_invoke = True for el_a in Condition.linked_to(self.a) | {self.a}: for el_b in Condition.linked_to(self.b) | {self.b}: if (el_a, el_b) in UnlinkCondition.unlink_conditions: continue if {el_a, el_b} not in universe.permutations: continue UnlinkCondition("{} {}".format(el_a, el_b)) return should_invoke
def test_unlink(self): self.fake_dic = { 'colors': ['yellow', 'blue'], 'pets': ['cats', 'dogs'], 'cars': ['Toyota', 'Ford']} self.assertTrue(UnlinkCondition('dogs yellow')) self.assertTrue(UnlinkCondition('Ford cats')) self.assertTrue(UnlinkCondition('dogs 2')) self.assertEqual(Universe.instance().permutations, [ {'yellow', 'cats'}, {'blue', 'dogs'}, {'yellow', 'Toyota'}, {'blue', 'Ford'}, {'yellow', '2'}, {'blue', '1'}, {'cats', 'Toyota'}, {'dogs', 'Ford'}, {'cats', '2'}, {'dogs', '1'}, {'2', 'Toyota'}, {'1', 'Ford'}])
def __init__(self, expression): self.set_members(expression) self.check_valid() Condition.conditions.append(self) self.before_perms = len(list(Universe.instance().permutations))
def trigger(self): """Trigger method. Should be implemented by boundary type conditions.""" self.before_perms = len(list(Universe.instance().permutations))
def has_changed(self): return len(list(Universe.instance().permutations)) != self.before_perms
def test_next(self): self.fake_dic = { 'colors': ['yellow', 'blue', 'purple', 'green'], 'pets': ['cats', 'dogs', 'horses', 'capybaras'] } self.assertTrue(UnlinkCondition('dogs 2')) self.assertTrue(UnlinkCondition('dogs 3')) self.assertTrue(UnlinkCondition('dogs 4')) self.assertTrue(NextCondition('dogs blue')) self.assertTrue(NextCondition('capybaras yellow')) self.assertTrue({'1', 'dogs'} in Universe.instance().permutations) self.assertFalse({'2', 'dogs'} in Universe.instance().permutations) self.assertFalse({'3', 'dogs'} in Universe.instance().permutations) self.assertFalse({'4', 'dogs'} in Universe.instance().permutations) self.assertFalse({'1', 'blue'} in Universe.instance().permutations) self.assertTrue({'2', 'blue'} in Universe.instance().permutations) self.assertFalse({'3', 'blue'} in Universe.instance().permutations) self.assertFalse({'4', 'blue'} in Universe.instance().permutations) self.assertTrue(NextCondition('blue capybaras')) self.assertFalse( {'1', 'capybaras'} in Universe.instance().permutations) self.assertFalse( {'2', 'capybaras'} in Universe.instance().permutations) self.assertTrue({'3', 'capybaras'} in Universe.instance().permutations) self.assertFalse( {'4', 'capybaras'} in Universe.instance().permutations) self.assertFalse({'1', 'yellow'} in Universe.instance().permutations) self.assertFalse({'2', 'yellow'} in Universe.instance().permutations) self.assertFalse({'3', 'yellow'} in Universe.instance().permutations) self.assertTrue({'4', 'yellow'} in Universe.instance().permutations)