File size: 4,442 Bytes
6fd9719
 
af71f44
 
 
 
4c67d79
6fd9719
6bb08c4
 
 
c6ef322
4c67d79
6bb08c4
6fd9719
4c67d79
b715c89
ba7c9fe
 
 
 
 
 
 
 
 
 
6bb08c4
 
 
 
 
 
5c4a167
7994c21
5c4a167
 
4eee6c0
7d70895
 
4eee6c0
 
5c4a167
 
 
 
 
 
 
 
6fd9719
 
 
b715c89
 
 
 
 
 
6fd9719
b715c89
 
 
 
 
 
 
 
 
ba7c9fe
 
 
 
b715c89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6fd9719
b715c89
 
4eee6c0
 
 
 
 
 
 
 
 
 
b715c89
 
 
 
ba7c9fe
b715c89
5c4a167
6fd9719
 
 
4c67d79
 
6fd9719
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
'use client';

import { Button, ButtonGroup } from '@heroui/button';
import { Card, CardBody } from '@heroui/card';
import { Checkbox } from '@heroui/checkbox';
import { Slider } from '@heroui/slider';
import { useRef, useState } from 'react';

import { useControlContext } from '@/contexts/control-context';

import { Actions } from './consts';
import { rotationController } from './rotation-controller';
import { StateModal, StateModalRef } from './state-modal';

export const UIControls = () => {
  const stateModalRef = useRef<StateModalRef | null>(null);
  const [isControlsOpen, setIsControlsOpen] = useState(true);
  const {
    rubiksCubeRef,
    showRotationIndicators,
    setShowRotationIndicators,
    setBackground,
    cubeRoughness,
    setCubeRoughness,
    cubeSpeed,
    setCubeSpeed,
  } = useControlContext();

  const scramble = () => {
    const scrambleSteps = Array.from({ length: 20 }, () => Actions[Math.floor(Math.random() * Actions.length)]);
    rubiksCubeRef?.current?.rotate(scrambleSteps);
  };

  const reset = () => {
    rubiksCubeRef?.current?.reset();
  };

  const showState = () => {
    const state = rotationController.getState();
    stateModalRef.current?.open(state);
  };

  const solve = () => {
    alert('Working on it!');
  };

  const train = () => {
    alert('Working on it!');
  };

  return (
    <div className="z-10 pointer-events-none">
      <Card className="max-w-sm bg-white/30 border border-white/80 backdrop-blur-xl pointer-events-auto">
        <CardBody className="flex flex-col">
          <div className="flex justify-between items-center">
            <div className="text-2xl font-bold">Controls</div>
            <Button variant="light" size="sm" onPress={() => setIsControlsOpen(!isControlsOpen)}>
              {isControlsOpen ? 'Hide' : 'Show'}
            </Button>
          </div>
          <div
            className={`
              flex flex-col gap-6 transition-all duration-500 ease-in-out
              ${isControlsOpen ? 'max-h-[1000px] opacity-100' : 'max-h-0 opacity-0 pointer-events-none'}
              overflow-hidden
            `}
            style={{ willChange: 'max-height, opacity' }}
          >
            <div className="flex flex-col gap-2 mt-6">
              <div className="flex items-center justify-between">
                <div className="text-sm">Rotation Indicators</div>
                <Checkbox isSelected={showRotationIndicators} onValueChange={setShowRotationIndicators} />
              </div>
              <div className="flex items-center justify-between">
                <div className="text-sm">Background</div>
                <ButtonGroup size="sm">
                  <Button onPress={() => setBackground('sunset')}>Sunset</Button>
                  <Button onPress={() => setBackground('dawn')}>Dawn</Button>
                  <Button onPress={() => setBackground('forest')}>Forest</Button>
                </ButtonGroup>
              </div>
              <Slider
                size="sm"
                label="Cube Roughness"
                value={cubeRoughness}
                onChange={(value) => setCubeRoughness(value as number)}
                minValue={0.2}
                maxValue={1}
                step={0.01}
              />
              <Slider
                size="sm"
                label="Cube Speed"
                value={cubeSpeed}
                onChange={(value) => setCubeSpeed(value as number)}
                minValue={1}
                maxValue={10}
                step={1}
              />
            </div>
            <div className="flex flex-col gap-2">
              <div className="flex gap-2">
                <ButtonGroup size="sm">
                  <Button onPress={scramble}>Scramble</Button>
                  <Button onPress={reset}>Reset</Button>
                </ButtonGroup>

                <Button size="sm" variant="light" onPress={showState}>
                  Show State
                </Button>

                <Button size="sm" className="ms-auto" color="success" onPress={solve}>
                  Solve
                </Button>
              </div>
              <div className="text-sm italic font-bold underline text-primary cursor-pointer" onClick={train}>
                Train your own model!
              </div>
            </div>
          </div>
        </CardBody>
      </Card>

      <StateModal ref={stateModalRef} />
    </div>
  );
};