def test_generate_argument_list_with_transition(): color_repeats_level = DerivedLevel( "yes", Transition(lambda colors: colors[0] == colors[1], [color])) x_product = color_repeats_level.get_dependent_cross_product() assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[0]) == [['red', 'red']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[1]) == [['red', 'blue']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[2]) == [['blue', 'red']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[3]) == [['blue', 'blue']] double_repeat_level = DerivedLevel( "name", Transition(lambda colors, texts: True, [color, text])) x_product = double_repeat_level.get_dependent_cross_product() assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[0]) == [['red', 'red'], ['red', 'red']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[1]) == [['red', 'red'], ['red', 'blue']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[2]) == [['red', 'red'], ['blue', 'red']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[3]) == [['red', 'red'], ['blue', 'blue']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[15]) == [['blue', 'blue'], ['blue', 'blue']]
def extract_simplelevel(self, block: Block, level: DerivedLevel) -> List[Dict[Factor, SimpleLevel]]: """Recursively deciphers the excluded level to a list of combinations basic levels.""" excluded_levels = [] excluded: List[Tuple[Level, ...]] = [cross for cross in level.get_dependent_cross_product() if level.window.predicate(*[level.name for level in cross])] for excluded_level_tuple in excluded: combos: List[Dict[Factor, SimpleLevel]] = [{}] for excluded_level in excluded_level_tuple: if isinstance(excluded_level, DerivedLevel): result = self.extract_simplelevel(block, excluded_level) newcombos = [] valid = True for r in result: for c in combos: for f in c: if f in r: if c[f] != r[f]: valid = False if valid: newcombos.append({**r, **c}) combos = newcombos else: if not isinstance(excluded_level, SimpleLevel): raise ValueError(f"Unexpected level type in exclusion: level {level.name} of type " f"{type(level).__name__}.") for c in combos: if block.factor_in_crossing(excluded_level.factor) and block.require_complete_crossing: block.errors.add("WARNING: Some combinations have been excluded, this crossing may not be complete!") c[excluded_level.factor] = excluded_level excluded_levels.extend(combos) return excluded_levels
def test_derived_level_get_dependent_cross_product(): assert [((tup[0][0].factor_name, tup[0][1].external_name), (tup[1][0].factor_name, tup[1][1].external_name)) for tup in con_level.get_dependent_cross_product() ] == [(('color', 'red'), ('text', 'red')), (('color', 'red'), ('text', 'blue')), (('color', 'blue'), ('text', 'red')), (('color', 'blue'), ('text', 'blue'))] integer = Factor("integer", ["1", "2"]) numeral = Factor("numeral", ["I", "II"]) text = Factor("text", ["one", "two"]) two_con_level = DerivedLevel( "twoCon", WithinTrial(lambda x: x, [integer, numeral, text])) assert [((tup[0][0].factor_name, tup[0][1].external_name), (tup[1][0].factor_name, tup[1][1].external_name), (tup[2][0].factor_name, tup[2][1].external_name)) for tup in two_con_level.get_dependent_cross_product() ] == [(('integer', '1'), ('numeral', 'I'), ('text', 'one')), (('integer', '1'), ('numeral', 'I'), ('text', 'two')), (('integer', '1'), ('numeral', 'II'), ('text', 'one')), (('integer', '1'), ('numeral', 'II'), ('text', 'two')), (('integer', '2'), ('numeral', 'I'), ('text', 'one')), (('integer', '2'), ('numeral', 'I'), ('text', 'two')), (('integer', '2'), ('numeral', 'II'), ('text', 'one')), (('integer', '2'), ('numeral', 'II'), ('text', 'two'))] mixed_level = DerivedLevel( "mixed", WithinTrial(lambda x: x, [ Factor("color", ["red", "blue", "green"]), Factor("boolean", ["true", "false"]) ])) assert [((tup[0][0].factor_name, tup[0][1].external_name), (tup[1][0].factor_name, tup[1][1].external_name)) for tup in mixed_level.get_dependent_cross_product() ] == [(('color', 'red'), ('boolean', 'true')), (('color', 'red'), ('boolean', 'false')), (('color', 'blue'), ('boolean', 'true')), (('color', 'blue'), ('boolean', 'false')), (('color', 'green'), ('boolean', 'true')), (('color', 'green'), ('boolean', 'false'))]
def extract_simplelevel(self, block: Block, level: DerivedLevel) -> List[Dict[Factor, SimpleLevel]]: excluded_levels = [] excluded = list(filter(lambda c: level.window.fn(*list(map(lambda f: get_external_level_name(f[1]), c))), level.get_dependent_cross_product())) for i in excluded: combos = cast(List[Dict[Factor, SimpleLevel]], [dict()]) for j in i: if type(j[1]) is DerivedLevel: result = self.extract_simplelevel(block, j[1]) newcombos = [] valid = True for r in result: for c in combos: for f in c: if f in r: if c[f] != r[f]: valid = False if valid: newcombos.append({**r, **c}) combos = newcombos else: for c in combos: if block.factor_in_crossing(j[0]) and block.require_complete_crossing: block.errors.add("WARNING: Some combinations have been excluded, this crossing may not be complete!") c[j[0]] = j[1] excluded_levels.extend(combos) return excluded_levels