Skip to content

Commit

Permalink
Copy scramble and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
simonkellly committed May 21, 2024
1 parent 141372d commit 9cfcd0b
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import cubeImage from '/cube-colors.png';
import { experimentalSolve3x3x3IgnoringCenters } from 'cubing/search';
import { GanCubeMove } from 'gan-web-bluetooth';

export default function Twisty({ className }: { className: string }) {
export default function BTCubeDisplay({ className }: { className: string }) {
const containerRef = useRef<HTMLDivElement>(null);
const [player, setPlayer] = useState<TwistyPlayer | null>(null);

Expand All @@ -24,7 +24,7 @@ export default function Twisty({ className }: { className: string }) {
controlPanel: 'none',
cameraLatitude: 25,
cameraLongitude: 25,
tempoScale: 2,
tempoScale: 4,
experimentalStickering: 'picture',
experimentalSprite: cubeImage,
});
Expand Down
27 changes: 13 additions & 14 deletions src/components/timer/timerStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const TimerStore = new Store({
solutionMoves: [],
});

async function setScrambleFromCubeState(originalScramble: Alg | string) {
async function updateScrambleFromCubeState(originalScramble: Alg | string) {
const ogScrambleStr = originalScramble.toString();
if (!CubeStore.state.kpattern) {
TimerStore.setState(state => ({
Expand Down Expand Up @@ -60,16 +60,16 @@ async function setScrambleFromCubeState(originalScramble: Alg | string) {
}));
}

async function processScrambleMove(ev: GanCubeMove) {
async function processScramblingMove(ev: GanCubeMove) {
const ogScramble = TimerStore.state.originalScramble;
const scrambleMoves = TimerStore.state.scramble.split(' ');
if (scrambleMoves.length === 0) {
if (ogScramble.length > 0) await setScrambleFromCubeState(ogScramble);
if (ogScramble.length > 0) await updateScrambleFromCubeState(ogScramble);
return;
}

if (scrambleMoves.length === TimerStore.state.scrambleIdx) {
await setScrambleFromCubeState(ogScramble);
await updateScrambleFromCubeState(ogScramble);
return;
}

Expand Down Expand Up @@ -99,7 +99,7 @@ async function processScrambleMove(ev: GanCubeMove) {
return;
}

await setScrambleFromCubeState(ogScramble);
await updateScrambleFromCubeState(ogScramble);
}

const newScramble = async () => {
Expand All @@ -109,24 +109,23 @@ const newScramble = async () => {
...state,
originalScramble: scramble.toString(),
}));
await setScrambleFromCubeState(scramble.toString());
await updateScrambleFromCubeState(scramble.toString());
};

export const useCubeTimer = () => {
const cube = useStore(CubeStore, state => state.cube);

const stopwatch = useStopwatch();

useEffect(() => {
const subscription = cube?.events$.subscribe((event: GanCubeEvent) => {
if (event.type !== 'MOVE') return;

if (stopwatch.isRunning()) return;
processScrambleMove(event);
processScramblingMove(event);
});

if (TimerStore.state.originalScramble)
setScrambleFromCubeState(TimerStore.state.originalScramble);
updateScrambleFromCubeState(TimerStore.state.originalScramble);

return () => {
subscription?.unsubscribe();
Expand Down Expand Up @@ -168,7 +167,7 @@ export const useCubeTimer = () => {
const algs = await extractAlgs(solution);

console.log('Scramble:', TimerStore.state.originalScramble);
let last = times[0].cubeTimestamp;
let last = times.length > 0 ? times[0].cubeTimestamp : 0;
console.table(algs.map(([alg, idx]) => {
const ms = times[idx].cubeTimestamp - last;
const time = (ms / 1000).toFixed(2);
Expand All @@ -179,7 +178,7 @@ export const useCubeTimer = () => {
newScramble();
};

const pressSpaceBar = (up: boolean) => {
const updateStateFromSpaceBar = (up: boolean) => {
const currentState = state.current;
if (currentState === TimerState.Inactive) {
if (!up) {
Expand All @@ -205,11 +204,11 @@ export const useCubeTimer = () => {
}
};

useHotkeys(' ', () => pressSpaceBar(false), { keyup: false });
useHotkeys(' ', () => pressSpaceBar(true), { keyup: true });
useHotkeys(' ', () => updateStateFromSpaceBar(false), { keyup: false });
useHotkeys(' ', () => updateStateFromSpaceBar(true), { keyup: true });

return {
stopwatch,
pressSpaceBar,
pressSpaceBar: updateStateFromSpaceBar,
};
};
60 changes: 40 additions & 20 deletions src/routes/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import { createFileRoute } from '@tanstack/react-router';
import { useStore } from '@tanstack/react-store';
import { useHotkeysContext } from 'react-hotkeys-hook';
import { Timer, TimerRenderer } from 'react-use-precision-timer';
import Twisty from '@/components/cubing/twisty';
import BTCubeDisplay from '@/components/cubing/btCubeDisplay';
import DrawScramble from '@/components/timer/drawScramble';
import { TimerStore, useCubeTimer } from '@/components/timer/timerStore';
import { CubeStore } from '@/lib/smartCube';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Copy } from 'lucide-react';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';

export const Route = createFileRoute('/dashboard')({
component: Dashboard,
Expand All @@ -21,27 +24,44 @@ function ScrambleDisplay() {
const scramble = useStore(TimerStore, state => state.scramble);
const scrambleIndex = useStore(TimerStore, state => state.scrambleIdx);

const copyScramble = () => {
window.navigator.clipboard.writeText(TimerStore.state.originalScramble);
}

// TODO: Make this not affect timer positioning
return (
<h2 className="text-3xl font-semibold text-center p-4 flex-none select-none">
{scramble.length > 0 ? (
scramble.split(' ').map((move, i) => {
const className = cn(
'inline-block px-2 mx-1 py-1 text-white rounded-lg',
{
'bg-muted': i === scrambleIndex,
'text-muted': i < scrambleIndex,
}
);
return (
<div
key={scramble.length + move + 'Move' + i}
className={className}
>
{move}
</div>
);
})
<>
{scramble.split(' ').map((move, i) => {
const className = cn(
'inline-block px-2 mx-1 py-1 text-white rounded-lg',
{
'bg-muted': i === scrambleIndex,
'text-muted': i < scrambleIndex,
}
);
return (
<div
key={scramble.length + move + 'Move' + i}
className={className}
>
{move}
</div>
);
})}
{' '}
<Tooltip>
<TooltipTrigger asChild>
<Button size="icon" variant="outline" onClick={copyScramble}>
<Copy />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Copy scramble</p>
</TooltipContent>
</Tooltip>
</>
) : (
<></>
)}
Expand Down Expand Up @@ -79,7 +99,7 @@ function Dashboard() {
>
<ScrambleDisplay />
<div className="flex grow h-full items-center">
<h1 className="text-9xl font-extrabold text-white text-center m-auto font-mono py-8">
<h1 className="text-9xl font-extrabold text-white text-center m-auto font-mono py-8 select-none">
<TimerRenderer
timer={cubeTimer.stopwatch}
renderRate={30}
Expand All @@ -92,7 +112,7 @@ function Dashboard() {
<legend className="-ml-1 px-1 text-sm font-medium">
<CubeName />
</legend>
<Twisty className="w-full h-64 m-auto" />
<BTCubeDisplay className="w-full h-64 m-auto" />
</fieldset>
<fieldset className="rounded-lg border px-4 hover:bg-muted col-span-2">
<legend className="-ml-1 px-1 text-sm font-medium">Results</legend>
Expand Down
4 changes: 2 additions & 2 deletions src/routes/twisty.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { createFileRoute } from '@tanstack/react-router';
import Twisty from '@/components/cubing/twisty';
import BTCubeDisplay from '@/components/cubing/btCubeDisplay';

export const Route = createFileRoute('/twisty')({
component: TwistyExample,
});

function TwistyExample() {
return <Twisty className="w-64 h-64" />;
return <BTCubeDisplay className="w-64 h-64" />;
}

0 comments on commit 9cfcd0b

Please sign in to comment.