示例#1
0
    def from_arguments(args: Namespace, cube: Cube, parser: ArgumentParser) -> Optional["Label"]:
        if args.label_data is None:
            return None

        image, scale = args.label_data
        texture = Texture(image, GL_RGBA, flip=True, mipmap=True)
        if args.label_side is not None:
            side = args.label_side
        else:
            side = Side.TOP

        face = cube.get_side(Orientation.regular(side))
        if args.label_position is not None:
            i, j = args.label_position
            if i < 0 or i >= face.rows:
                parser.error(f"invalid label row: it must be between 0 and {face.rows - 1}")
                return None
            if j < 0 or j >= face.columns:
                parser.error(f"invalid label column: it must be between 0 and {face.columns - 1}")
                return None
        else:
            i = face.rows // 2
            j = face.columns // 2

        return Label(scale, texture, side, i, j)
示例#2
0
def test_runtime_globals():
    runtime = CubeRuntime(Cube((3, 3, 3)), Orientation(), lambda action: None,
                          lambda: None)
    existing = set(runtime.functions.global_values.keys())
    assert existing.issuperset(set(CubeRuntime.COLOR_NAMES.keys()))
    assert existing.issuperset(set(CubeRuntime.SIDE_NAMES.keys()))
    assert "push_orientation" in existing
示例#3
0
    def _get_colors(self, side: Side, i: int, j: int) -> List[Color]:
        orientation = Orientation.regular(side)
        front_side = self.cube.get_side(orientation)
        colors = [front_side.colors[i, j]]
        if i == 0 or i == front_side.rows - 1:
            if i == 0:
                top_side = self.cube.get_side(orientation.to_top)
                color = top_side.colors[top_side.rows - 1, j]
            else:
                bottom_side = self.cube.get_side(orientation.to_bottom)
                color = bottom_side.colors[0, j]
            colors.insert(0 if side in {Side.FRONT, Side.BACK} else 1, color)

        if j == 0 or j == front_side.columns - 1:
            if j == 0:
                left_side = self.cube.get_side(orientation.to_left)
                color = left_side.colors[i, left_side.columns - 1]
            else:
                right_side = self.cube.get_side(orientation.to_right)
                color = right_side.colors[i, 0]
            colors.insert(0, color)

        if len(colors) == 3:
            return [colors[2], colors[0], colors[1]]
        return colors
class TestApplySide:
    orientation = Orientation(Side.RIGHT, Side.BOTTOM)

    def test_apply_side(self):
        cube = Cube((2, 2, 2))
        colors = [[Color.WHITE, Color.RED], [Color.ORANGE, Color.GREEN]]

        apply_side(cube, self.orientation, colors)
        actual_colors = [[
            cube.get_side(self.orientation).colors[i, j] for j in [0, 1]
        ] for i in [0, 1]]
        assert colors == actual_colors

    def test_wrong_columns(self):
        cube = Cube((2, 2, 2))
        colors = [[Color.WHITE, Color.RED, Color.BLUE],
                  [Color.ORANGE, Color.GREEN, Color.BLUE]]
        with raises(argparse.ArgumentTypeError) as e:
            apply_side(cube, self.orientation, colors)
        assert str(e.value) == "Incorrect number of columns"

    def test_wrong_lines(self):
        cube = Cube((2, 2, 2))
        colors = [[Color.WHITE, Color.RED]]
        with raises(argparse.ArgumentTypeError) as e:
            apply_side(cube, self.orientation, colors)
        assert str(e.value) == "Incorrect number of lines"
示例#5
0
def test_flip_flops():
    code = """
        let count: int
        while top[1, 1] != top[2, 2] or count == 0 do 
            RUR'U'
            count = count + 1
        end
        out(count)
    """

    out_fn = MagicMock()

    stack = Stack()
    finish_function = MagicMock()
    cube_runtime = CubeRuntime(Cube((3, 3, 3)), Orientation(), lambda action: None, finish_function)
    cube_runtime.functions.initialize_stack(stack)
    stdlib.initialize_stack(stack)
    stack.add_global("out", Function(([Integer], Void)))

    globals = {"out": out_fn, **stdlib.exec_globals, **cube_runtime.functions.exec_globals}

    executor = ExecutionContext(globals)
    executor.compile(parser.parse(code, stack))
    executor.execute(MockTracebackWriter())
    cube_runtime.finished()

    out_fn.assert_called_once_with(6)
    finish_function.assert_called_once()
示例#6
0
def test_rotations(around: Side, front: Side, top: Side, twice: bool) -> None:
    orientation = Orientation(Side.FRONT, Side.TOP)
    action = Rotate(around, twice)
    # noinspection PyTypeChecker
    orientation = action.perform(None, orientation)

    assert orientation.front == front
    assert orientation.top == top
示例#7
0
def assert_cube(cube: Cube, front: str, right: str, back: str, left: str,
                top: str, bottom: str) -> None:
    orientation = Orientation()
    assert front == side_to_string(cube.get_side(orientation))
    assert right == side_to_string(cube.get_side(orientation.to_right))
    assert back == side_to_string(cube.get_side(orientation.to_right.to_right))
    assert left == side_to_string(cube.get_side(orientation.to_left))
    assert top == side_to_string(cube.get_side(orientation.to_top))
    assert bottom == side_to_string(cube.get_side(orientation.to_bottom))
示例#8
0
def test_get_side():
    orientation: Orientation = Orientation(Side.LEFT, Side.TOP)
    orientation.get_side_rotation = MagicMock()
    orientation.get_side_rotation.return_value = 0

    cube = Cube((3, 3, 3))
    side = cube.get_side(orientation)
    assert isinstance(side, CubeSide)
    assert side == cube.sides[Side.LEFT]
示例#9
0
def test_rotation_2(around: Side):
    action1 = Rotate(around, False)
    action2 = Rotate(around.opposite(), False)

    initial = Orientation(Side.LEFT, Side.BACK)
    orientation = action1.perform(None, initial)
    orientation = action2.perform(None, orientation)

    assert orientation == initial
示例#10
0
def test_action_callback():
    callback: Callable[[Action], None] = MagicMock()
    runtime = CubeRuntime(Cube((3, 3, 3)), Orientation(), callback,
                          lambda: None)
    runtime.perform_turn(Side.LEFT, 2, [1])

    callback: MagicMock
    action = callback.call_args_list[0][0][0]
    assert isinstance(action, Turn)
    assert action.type == TurningType.VERTICAL
示例#11
0
    def _generate(self) -> List[CubePart]:
        parts = []
        for side, i, j in self.cube.iterate_components():
            x, y, z = self.cube.get_absolute_coordinates(side, i, j)
            y = self.cube.shape[2] - 1 - y
            z = self.cube.shape[1] - 1 - z

            part = self._create_part(x, y, z, self._get_colors(side, i, j))
            parts.append(part)
            self.cube.set_data(Orientation.regular(side), i, j, part)
        return parts
示例#12
0
def test_data_set(sample_cube: Cube) -> None:
    orientation = Orientation(Side.RIGHT, Side.BACK)

    sample_cube.set_data(orientation, 1, 1, "a")
    sample_cube.set_data(orientation, 0, 0, "b")
    sample_cube.set_data(orientation, 1, 2, "c")
    sample_cube.set_data(orientation, 2, 1, "d")

    def get_side(orient: Orientation) -> str:
        return data_to_string(sample_cube.get_side(orient))

    orientation = Orientation(Side.FRONT, Side.TOP)
    assert get_side(orientation) == "None None None/None None d/None None None"
    assert get_side(
        orientation.to_top) == "None None b/None None None/None None None"
    assert get_side(orientation.to_right) == "None None b/d a None/None c None"
    assert get_side(orientation.to_right.to_right
                    ) == "b None None/None None None/None None None"
    assert get_side(
        orientation.to_bottom) == "None None None/None None c/None None None"
示例#13
0
def assert_solved(cube: Cube):
    for front in Side:
        face = cube.get_side(Orientation.regular(front))
        color = None
        for row in range(face.rows):
            for column in range(face.columns):
                c = face.colors[row, column]
                if color is None:
                    color = c
                else:
                    assert c == color
示例#14
0
    def test_scramble(self):
        result = []
        actions = [
            MockAction(result, string.ascii_uppercase[i]) for i in range(10)
        ]

        builder = CubeBuilder((2, 2, 2))
        builder.scramble(actions)
        _, orientation = builder.get()

        assert orientation == Orientation(Side.LEFT, Side.RIGHT)
        assert result == list("ABCDEFGHIJ")
示例#15
0
class TestBuilder:
    def test_create(self):
        builder = CubeBuilder((2, 2, 2))
        cube, orientation = builder.get()
        assert cube.shape == (2, 2, 2)
        assert orientation.top == Side.TOP
        assert orientation.front == Side.FRONT

    @mock.patch("cubelang.cli.cube_builder.apply_side")
    @pytest.mark.parametrize(
        "side, exp_orientation",
        [(Side.FRONT, Orientation(Side.FRONT, Side.TOP)),
         (Side.LEFT, Orientation(Side.LEFT, Side.TOP)),
         (Side.RIGHT, Orientation(Side.RIGHT, Side.TOP)),
         (Side.BACK, Orientation(Side.BACK, Side.TOP)),
         (Side.TOP, Orientation(Side.TOP, Side.BACK)),
         (Side.BOTTOM, Orientation(Side.BOTTOM, Side.FRONT))])
    def test_side(self, apply_side_fn, side, exp_orientation):
        builder = CubeBuilder((2, 2, 2))
        builder.side(side, [])
        apply_side_fn.assert_called_once_with(builder.cube, exp_orientation,
                                              [])

    def test_scramble(self):
        result = []
        actions = [
            MockAction(result, string.ascii_uppercase[i]) for i in range(10)
        ]

        builder = CubeBuilder((2, 2, 2))
        builder.scramble(actions)
        _, orientation = builder.get()

        assert orientation == Orientation(Side.LEFT, Side.RIGHT)
        assert result == list("ABCDEFGHIJ")
示例#16
0
def test_suspend_rotations():
    actions = []
    runtime = CubeRuntime(Cube((2, 2, 2)), Orientation(), actions.append,
                          lambda: None)
    runtime.perform_turn(Side.FRONT, 1, [1])
    runtime.perform_rotate(Side.TOP, False)
    runtime.suspend_rotations()
    for _ in range(3):
        runtime.perform_turn(Side.FRONT, 1, [1])
        runtime.perform_rotate(Side.TOP, False)
    runtime.resume_rotations()

    assert "FYFRBY'" == "".join(map(str, actions))
示例#17
0
def sample_cube() -> Cube:
    cube = Cube((3, 3, 3))
    orientation = Orientation()
    assert orientation.get_side_rotation() == 0

    red = cube.get_side(orientation)
    _set_side_colors(red, [[Color.ORANGE, Color.RED, Color.GREEN],
                           [Color.YELLOW, Color.RED, Color.GREEN],
                           [Color.BLUE, Color.WHITE, Color.GREEN]])

    green = cube.get_side(orientation.to_right)
    _set_side_colors(green, [[Color.RED, Color.ORANGE, Color.ORANGE],
                             [Color.RED, Color.GREEN, Color.WHITE],
                             [Color.RED, Color.GREEN, Color.WHITE]])

    orange = cube.get_side(orientation.to_left.to_left)
    _set_side_colors(orange, [[Color.YELLOW, Color.YELLOW, Color.RED],
                              [Color.ORANGE, Color.ORANGE, Color.WHITE],
                              [Color.ORANGE, Color.ORANGE, Color.GREEN]])

    blue = cube.get_side(orientation.to_left)
    _set_side_colors(blue, [[Color.YELLOW, Color.YELLOW, Color.YELLOW],
                            [Color.BLUE, Color.BLUE, Color.RED],
                            [Color.ORANGE, Color.WHITE, Color.WHITE]])

    yellow = cube.get_side(orientation.to_top)
    _set_side_colors(yellow, [[Color.BLUE, Color.GREEN, Color.GREEN],
                              [Color.BLUE, Color.YELLOW, Color.YELLOW],
                              [Color.BLUE, Color.BLUE, Color.WHITE]])

    white = cube.get_side(orientation.to_bottom)
    _set_side_colors(white, [[Color.RED, Color.GREEN, Color.YELLOW],
                             [Color.RED, Color.WHITE, Color.ORANGE],
                             [Color.WHITE, Color.BLUE, Color.BLUE]])

    assert_cube(cube, "ORG/YRG/BWG", "ROO/RGW/RGW", "YYR/OOW/OOG",
                "YYY/BBR/OWW", "BGG/BYY/BBW", "RGY/RWO/WBB")
    return cube
示例#18
0
def test_state_stack():
    actions = []
    runtime = CubeRuntime(Cube((2, 2, 2)), Orientation(), actions.append,
                          lambda: None)

    runtime.perform_turn(Side.FRONT, 1, [1])
    runtime.perform_rotate(Side.TOP, False)
    runtime.push_orientation()
    for _ in range(3):
        runtime.perform_turn(Side.FRONT, 1, [1])
        runtime.perform_rotate(Side.TOP, False)
    runtime.pop_orientation()

    assert "FYFYFYFYY" == "".join(map(str, actions))
示例#19
0
def test_get_color(side, orientation):
    class Colors:
        def __getitem__(self, item):
            pass

    class Side:
        def __init__(self):
            self.colors = Colors()

    with patch.object(Cube, 'get_side', return_value=Side()) as mock_method:
        runtime = CubeRuntime(Cube((3, 3, 3)), Orientation(),
                              lambda action: None, lambda: None)
        runtime.get_color(side, 0, 0)
        mock_method.assert_called_once_with(orientation)
示例#20
0
def test_orient_full():
    cube = Cube((3, 3, 3))
    for action in parse_actions("RUR'U'"):
        action.perform(cube, Orientation())

    match = cube.orient(Orientation(),
                        top=Pattern([[Color.WHITE, None, None],
                                     [None, "a", None], ["a", None, None]]),
                        front=Pattern([[None, None, None],
                                       [None, None, Color.ORANGE],
                                       [None, None, None]]),
                        right=Pattern([[None, None, None],
                                       [Color.YELLOW, None, None],
                                       ["a", None, None]]),
                        back=Pattern([[None, None, None], [None, None, None],
                                      [Color.BLUE, None, None]]),
                        left=Pattern([[None, Color.ORANGE, None],
                                      [None, None, None],
                                      [None, Color.GREEN, None]]),
                        bottom=Pattern([[Color.BLUE, None, Color.RED],
                                        [None, None, None], [None, None,
                                                             None]]))
    assert Orientation(Side.RIGHT, Side.BOTTOM) == match
示例#21
0
def test_data_rotation(sample_cube: Cube) -> None:
    orientation = Orientation(Side.FRONT, Side.TOP)
    sample_cube.set_data(orientation, 0, 2, "b")
    sample_cube.set_data(orientation, 1, 2, "a")
    sample_cube.turn_vertical(orientation, 3, 1)

    def get_side(orient: Orientation) -> str:
        return data_to_string(sample_cube.get_side(orient))

    assert get_side(
        orientation) == "None None None/None None None/None None None"
    assert get_side(
        orientation.to_right) == "None a b/None None None/None None None"
    assert get_side(
        orientation.to_top) == "None None b/None None a/None None None"
示例#22
0
def test_rotations(current: Tuple[Side, Side], left: Tuple[Side, Side],
                   top: Tuple[Side, Side], right: Tuple[Side, Side],
                   bottom: Tuple[Side, Side]) -> None:
    current_orientation = Orientation(*current)

    assert current_orientation.to_top.front == top[0]
    assert current_orientation.to_top.top == top[1]

    assert current_orientation.to_right.front == right[0]
    assert current_orientation.to_right.top == right[1]

    assert current_orientation.to_bottom.front == bottom[0]
    assert current_orientation.to_bottom.top == bottom[1]

    assert current_orientation.to_left.front == left[0]
    assert current_orientation.to_left.top == left[1]
示例#23
0
def test_turning_vertical(side: Side, func: str, out_sides: List[int],
                          out_amount: int) -> None:
    cube: Cube = CubeMock()
    mock = MagicMock()
    setattr(cube, func, mock)

    orientation = Orientation()
    action = Turn(side, [1, 2], 1)
    assert action.perform(cube, orientation) == orientation
    assert len(mock.call_args_list) == len(out_sides)
    print(mock.call_args_list[0])
    for args, side in zip(mock.call_args_list, out_sides):
        arg_orientation, arg_index, arg_turn = tuple(args)[0]
        assert arg_orientation == orientation
        assert arg_index == side
        assert arg_turn == out_amount
示例#24
0
    def _create_turn_animation(self, action: Turn) -> Animation:
        turns = action.turns
        if turns == 3:
            turns = -1
        if action.type == TurningType.HORIZONTAL:
            turns = -turns
        angle = math.radians(90 * turns)

        if action.type == TurningType.SLICE:
            axis = "z"
            side = Side.FRONT
        elif action.type == TurningType.VERTICAL:
            axis = "x"
            side = Side.LEFT
        else:
            axis = "y"
            side = Side.TOP

        orientation = Orientation.regular(side)
        width = self.cube.cube.get_side(orientation).columns
        components = set()
        for index in Turn.normalize_indices(action.indices, width):
            index -= 1
            if index == 0:
                components.update(self._get_parts_front(orientation))
            elif index == width - 1:
                components.update(
                    self._get_parts_front(orientation.to_right.to_right))
            components.update(
                self._get_parts_slice(orientation.to_right, index))

        def execution_callback(value: float) -> None:
            for component in components:
                component.set_temp_rotation(**{axis: value})

        def completion_callback() -> None:
            for component in components:
                component.apply_temp_rotation()
            self._run_animation()
            self.completed_count += 1

        return FloatAnimation(0.0,
                              angle,
                              execution_callback,
                              ease_in_out_quad,
                              completion_callback,
                              fraction_callback=self._fraction_callback)
示例#25
0
def run_test(seed, filename, dimension):
    scramble = subprocess.check_output(
        ["python", "-m", "cubelang.scrambler", "-d", str(dimension),
         "-s", str(seed)])

    scramble = scramble.decode(stdout.encoding).strip()

    cube = Cube((dimension, dimension, dimension))
    orientation = Orientation()
    for action in parse_actions(scramble):
        orientation = action.perform(cube, orientation)

    arguments = ["python", "-m", "cubelang", "-d", str(dimension), "-s", scramble,
                 str(Path(__file__).parents[1] / "examples" / filename)]
    solution = subprocess.check_output(arguments).decode("utf-8")

    for action in parse_actions(solution):
        orientation = action.perform(cube, orientation)
    assert_solved(cube)
示例#26
0
def test_orient():
    code = """
        orient top: {G--/---/---}, bottom: {--Y/---/---} then
            out(red)
        else-orient top: {-W-/---/---}, right: {---/---/-O-} then
            out(top[1, 1])
        end
    """

    out_fn = MagicMock()
    stack = Stack()
    cube_runtime = CubeRuntime(Cube((3, 3, 3)), Orientation(), lambda action: None, lambda: None)
    cube_runtime.functions.initialize_stack(stack)
    stdlib.initialize_stack(stack)
    stack.add_global("out", Function(([Color], Void)))

    globals = {"out": out_fn, **stdlib.exec_globals, **cube_runtime.functions.exec_globals}

    executor = ExecutionContext(globals)
    executor.compile(parser.parse(code, stack))
    executor.execute(MockTracebackWriter())
    cube_runtime.finished()
    out_fn.assert_called_once_with(orientation.Color.WHITE)
示例#27
0
    def __init__(self, cube: CubeModel[CubePart], label: Optional[Label],
                 color_theme: Dict[Color, Tuple[float, float, float]]):
        self.cube: CubeModel[CubePart] = cube
        self.label = label
        self.color_theme = color_theme

        self.shader = Program("object")
        self.shader.use()
        DirectionalLight.push_uniform_array(self.shader, "lights",
                                            CubePart.LIGHTS)

        models_path = Path(__file__).parents[1] / "models"
        self.vao_corner = load_obj(models_path / "corner.obj")
        self.vao_edge = load_obj(models_path / "edge.obj")
        self.vao_flat = load_obj(models_path / "flat.obj")
        self.stickers_texture = Texture.load("stickers",
                                             flip=True,
                                             mipmap=True)
        self.labels_texture = Texture.load("labels", flip=True, mipmap=True)

        self.parts: List[CubePart] = self._generate()

        if self.label is not None:
            orientation = Orientation.regular(self.label.side)
            side = self.cube.get_side(orientation)
            row, column = self.label.row, self.label.column

            rot_i = 0 if row == 0 else 2 if row == side.rows - 1 else 1
            rot_j = 0 if column == 0 else 2 if column == side.columns - 1 else 1
            part = side[row, column].data
            rotation, color = CubePart.LABEL_ROTATIONS[
                self.label.side][rot_i][rot_j]
            part.label_rotation = rotation
            part.label_visible = color

        self.rotation = IDENTITY
        self.temp_rotation = [0, 0, 0]
示例#28
0
def main():
    arg_parser = ArgumentParser()
    arg_parser.add_argument("-d",
                            dest="dimension",
                            help="dimensions of a cube",
                            default=3,
                            metavar="N",
                            type=integer_type(2))
    arg_parser.add_argument("-n",
                            dest="turns_num",
                            help="number of turns",
                            type=integer_type(1),
                            default=20)
    arg_parser.add_argument(
        "-a",
        dest="output_args",
        action="store_true",
        help=
        "display the state of the cube after the turns instead of the formula")
    arg_parser.add_argument(
        "-s",
        dest="seed",
        help="the seed for the pseudorandom number generator")
    args = arg_parser.parse_args()
    dim = args.dimension

    if args.seed is not None:
        random.seed(args.seed)

    actions: List[Turn] = []
    prev_side = None
    for i in range(args.turns_num):
        if prev_side is None:
            sides = SIDES
        else:
            sides = [x for x in SIDES if x != prev_side]

        prev_side = random.choice(sides)

        first_index = random.randint(1, dim // 2)
        last_index = random.randint(1, first_index)
        if first_index == last_index:
            indices = [first_index]
        else:
            indices = [last_index, ..., first_index]

        turn = Turn(prev_side, indices, random.randint(1, 3))
        actions.append(turn)

    if not args.output_args:
        for action in actions:
            print(str(action), end="")
        print()
    else:
        cube = Cube((dim, ) * 3)
        orientation = Orientation()
        for action in actions:
            action.perform(cube, orientation)

        print("--front", repr(cube.get_side(orientation).colors))
        print("--right", repr(cube.get_side(orientation.to_right).colors))
        print("--left", repr(cube.get_side(orientation.to_left).colors))
        print("--back",
              repr(cube.get_side(orientation.to_right.to_right).colors))
        print("--top", repr(cube.get_side(orientation.to_top).colors))
        print("--bottom", repr(cube.get_side(orientation.to_bottom).colors))
示例#29
0
    (Side.RIGHT, Side.TOP, TurningType.SLICE, 1, 1),
    (Side.FRONT, Side.TOP, TurningType.VERTICAL, 1, 3),
    (Side.FRONT, Side.RIGHT, TurningType.HORIZONTAL, 1, 3),
    (Side.TOP, Side.RIGHT, TurningType.SLICE, -1, 3),
])
def test_turning_transform(side: Side, turn: Side, res_side: TurningType,
                           res_sides: int, res_turns: int):
    action = Turn(side, [1], 1)
    transformed = action._transform(turn)
    assert transformed.type == res_side
    assert transformed.turns == res_turns
    assert transformed.indices[0] == res_sides


@pytest.mark.parametrize("orientation, action, type, indices",
                         [(Orientation(Side.BACK, Side.LEFT),
                           Turn(Side.RIGHT, 1, 3), TurningType.HORIZONTAL, -1),
                          (Orientation(Side.TOP, Side.BACK),
                           Turn(Side.TOP, 1, 1), TurningType.SLICE, -1),
                          (Orientation(Side.RIGHT, Side.BOTTOM),
                           Turn(Side.FRONT, 1, 1), TurningType.VERTICAL, -1)])
def test_orientation_changes(orientation: Side, action: Turn,
                             type: TurningType, indices: int):
    new_action = action.from_orientation(orientation)
    assert new_action.type == type
    assert new_action.indices[0] == indices


@pytest.mark.parametrize("indices, expected",
                         [([2], {2}), ([2, 4], {2, 4}),
                          ([2, ..., 4], {2, 3, 4}),
示例#30
0
def _iterate_orientations():
    for side in Side:
        orientation = Orientation.regular(side)
        for i in range(4):
            yield orientation
            orientation = orientation.rotate_clockwise()