feat:
This commit is contained in:
commit
db9c2829fd
5 changed files with 17021 additions and 75 deletions
16933
frontend/casino/package-lock.json
generated
Normal file
16933
frontend/casino/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,67 +2,76 @@ import { useState, useEffect, useRef, useLayoutEffect } from "react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import symbols2 from "../../../pages/SlotGamePage/symbols2";
|
import symbols2 from "../../../pages/SlotGamePage/symbols2";
|
||||||
|
|
||||||
function Reel({ isHorizontal, rng, rngReverse, cellCount }) {
|
|
||||||
const carousel = useRef(null);
|
|
||||||
const refs = useRef([]);
|
|
||||||
const cells = refs.current.map((value) => value);
|
|
||||||
const [selectedIndex, setSelectedIndex] = useState(null);
|
|
||||||
const [width, setWidth] = useState(0);
|
|
||||||
const [height, setHeight] = useState(0);
|
|
||||||
let rotateFn = isHorizontal ? "rotateY" : "rotateX";
|
|
||||||
let radius;
|
|
||||||
let theta;
|
|
||||||
let cellAngle;
|
|
||||||
|
|
||||||
function randomNumberInRange(min, max) {
|
interface ReelProps {
|
||||||
|
isHorizontal: boolean;
|
||||||
|
cellCount: string | number;
|
||||||
|
rng: boolean;
|
||||||
|
rngReverse: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Reel({ isHorizontal, rng, rngReverse, cellCount }: ReelProps) {
|
||||||
|
const carousel = useRef<HTMLDivElement | null>(null);
|
||||||
|
const refs = useRef<(HTMLDivElement | null)[]>([]);
|
||||||
|
const cells = refs.current.map((value) => value);
|
||||||
|
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
||||||
|
const [width, setWidth] = useState<number>(0);
|
||||||
|
const [height, setHeight] = useState<number>(0);
|
||||||
|
let rotateFn = isHorizontal ? "rotateY" : "rotateX";
|
||||||
|
let radius: number;
|
||||||
|
let theta: number;
|
||||||
|
let cellAngle: number;
|
||||||
|
|
||||||
|
function randomNumberInRange(min: number, max: number): number {
|
||||||
// 👇️ get number between min (inclusive) and max (inclusive)
|
// 👇️ get number between min (inclusive) and max (inclusive)
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return cellCount < 7
|
return Number(cellCount) < 7
|
||||||
? setSelectedIndex(selectedIndex + randomNumberInRange(3, 6))
|
? setSelectedIndex(selectedIndex! + randomNumberInRange(3, 6))
|
||||||
: setSelectedIndex(selectedIndex + randomNumberInRange(6, 14));
|
: setSelectedIndex(selectedIndex! + randomNumberInRange(6, 14));
|
||||||
}, [rng]);
|
}, [rng]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return cellCount < 7
|
return Number(cellCount) < 7
|
||||||
? setSelectedIndex(selectedIndex + randomNumberInRange(-3, -6))
|
? setSelectedIndex(selectedIndex! + randomNumberInRange(-3, -6))
|
||||||
: setSelectedIndex(selectedIndex + randomNumberInRange(-6, -14));
|
: setSelectedIndex(selectedIndex! + randomNumberInRange(-6, -14));
|
||||||
}, [rngReverse]);
|
}, [rngReverse]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setWidth(carousel.current.offsetWidth);
|
setWidth(carousel.current!.offsetWidth);
|
||||||
setHeight(carousel.current.offsetHeight);
|
setHeight(carousel.current!.offsetHeight);
|
||||||
setSelectedIndex(0);
|
setSelectedIndex(0);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
theta = 360 / cellCount;
|
theta = 360 / Number(cellCount);
|
||||||
rotateFn = isHorizontal ? "rotateY" : "rotateX";
|
rotateFn = isHorizontal ? "rotateY" : "rotateX";
|
||||||
const angle = theta * selectedIndex * -1;
|
const angle = theta * selectedIndex! * -1;
|
||||||
carousel.current.style.transform = `translateZ(${-radius}px) ${rotateFn}(${angle}deg)`;
|
carousel.current!.style.transform = `translateZ(${-radius}px) ${rotateFn}(${angle}deg)`;
|
||||||
}, [selectedIndex]);
|
}, [selectedIndex]);
|
||||||
|
|
||||||
function rotateCarousel() {
|
function rotateCarousel() {
|
||||||
const angles = theta * selectedIndex * -1;
|
const angles = theta * selectedIndex! * -1;
|
||||||
carousel.current.style.transform = `translateZ(${-radius}px) ${rotateFn}(${angles}deg)`;
|
carousel.current!.style.transform = `translateZ(${-radius}px) ${rotateFn}(${angles}deg)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeCarousel() {
|
function changeCarousel() {
|
||||||
theta = 360 / cellCount;
|
theta = 360 / Number(cellCount);
|
||||||
const cellSize = isHorizontal ? width : height;
|
const cellSize = isHorizontal ? width : height;
|
||||||
radius = Math.round(cellSize / 2 / Math.tan(Math.PI / cellCount));
|
radius = Math.round(cellSize / 2 / Math.tan(Math.PI / Number(cellCount)));
|
||||||
// eslint-disable-next-line no-plusplus
|
// eslint-disable-next-line no-plusplus
|
||||||
for (let i = 0; i < cells.length; i++) {
|
for (let i = 0; i < cells.length; i++) {
|
||||||
const cell = cells[i];
|
const cell = cells[i];
|
||||||
if (i < cellCount) {
|
if (i < Number(cellCount)) {
|
||||||
cell.style.opacity = 1;
|
cell!.style.opacity = "1";
|
||||||
cellAngle = theta * i;
|
cellAngle = theta * i;
|
||||||
cell.style.transform = `${rotateFn}(${cellAngle}deg) translateZ(${radius}px)`;
|
cell!.style.transform = `${rotateFn}(${cellAngle}deg) translateZ(${radius}px)`;
|
||||||
rotateCarousel();
|
rotateCarousel();
|
||||||
} else {
|
} else {
|
||||||
cell.style.opacity = 0;
|
cell!.style.opacity = "0";
|
||||||
cell.style.transform = "none";
|
cell!.style.transform = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +80,7 @@ function Reel({ isHorizontal, rng, rngReverse, cellCount }) {
|
||||||
rotateFn = isHorizontal ? "rotateY" : "rotateX";
|
rotateFn = isHorizontal ? "rotateY" : "rotateX";
|
||||||
changeCarousel();
|
changeCarousel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// set initials
|
// set initials
|
||||||
onOrientationChange();
|
onOrientationChange();
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
import {useSlotMachine} from "../../web3/functions/SlotMachine/useSlotMachine.ts";
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
export const SlotPlayButton = () => {
|
interface SlotPlayButtonProps {
|
||||||
|
onClick: () => void;
|
||||||
const { playSlot } = useSlotMachine()
|
}
|
||||||
|
|
||||||
|
const SlotPlayButton: React.FC<SlotPlayButtonProps> = ({ onClick }) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
onClick={() => { playSlot() }}
|
className="bg-rose-700 rounded-[100px] shadow text-white text-2xl font-bold py-5 px-10 hover:bg-rose-600 max-w-[200px]"
|
||||||
className="bg-rose-700 rounded-[100px] shadow text-white text-2xl font-bold py-5 px-10 hover:bg-rose-600">
|
onClick={onClick}
|
||||||
|
>
|
||||||
Крутить
|
Крутить
|
||||||
</button>
|
</button>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
SlotPlayButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SlotPlayButton;
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import ContainerLayout from "../../utils/ContainerLayout"
|
import ContainerLayout from "../../utils/ContainerLayout"
|
||||||
import { RPSPlayButton } from "../../components/web3/RPSPlayButton"
|
import { RPSPlayButton } from "../../components/web3/RPSPlayButton"
|
||||||
|
|
||||||
|
|
|
@ -1,68 +1,63 @@
|
||||||
import ContainerLayout from "../../utils/ContainerLayout"
|
import {useEffect, useState} from "react";
|
||||||
import PropTypes from 'prop-types';
|
import ContainerLayout from "../../utils/ContainerLayout.tsx";
|
||||||
import Reel from '../../components/App/Slot/Reel';
|
import Reel from "../../components/App/Slot/Reel.tsx";
|
||||||
import { useEffect, useState } from 'react';
|
import SlotPlayButton from "../../components/web3/SlotPlayButton.tsx";
|
||||||
import { RPSPlayButton } from '../../components/web3/RPSPlayButton';
|
|
||||||
import {SlotPlayButton} from "../../components/web3/SlotPlayButton.tsx";
|
|
||||||
|
|
||||||
export const SlotGamePage = () => {
|
export const SlotGamePage = () => {
|
||||||
const [isHorizontal, setIsHorizontal] = useState(false)
|
const [isHorizontal, setIsHorizontal] = useState(false);
|
||||||
const [cellCount, setCellCount] = useState(7)
|
const [rng, setRng] = useState(false);
|
||||||
const [rng, setRng] = useState(false)
|
const [rngReverse, setRngReverse] = useState(false);
|
||||||
const [rngReverse, setRngReverse] = useState(false)
|
|
||||||
|
|
||||||
const mql = window.matchMedia('(orientation: portrait)')
|
const mql = window.matchMedia("(orientation: portrait)");
|
||||||
|
|
||||||
mql.onchange = (e) => {
|
mql.onchange = (e) => {
|
||||||
if (e.matches) {
|
if (e.matches) {
|
||||||
setIsHorizontal(true)
|
setIsHorizontal(true);
|
||||||
} else {
|
} else {
|
||||||
setIsHorizontal(false)
|
setIsHorizontal(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleRng = () => {
|
const spinReels = () => {
|
||||||
setRng(!rng)
|
// Trigger the spinning effect in each reel
|
||||||
}
|
setRng(!rng);
|
||||||
const handleRngReverse = () => {
|
setRngReverse(!rngReverse);
|
||||||
setRngReverse(!rngReverse)
|
};
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mql.matches) {
|
if (mql.matches) {
|
||||||
setIsHorizontal(true)
|
setIsHorizontal(true);
|
||||||
} else {
|
} else {
|
||||||
setIsHorizontal(false)
|
setIsHorizontal(false);
|
||||||
}
|
}
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContainerLayout>
|
<ContainerLayout>
|
||||||
<div className="flex flex-row gap-4">
|
<div className="flex flex-row gap-4">
|
||||||
<div className="max-h-[180px] bg-green-700 flex flex-col justify-between shadow text-white text-2xl font-bold py-4 px-6 rounded-xl">
|
<div className="max-h-[180px] bg-green-700 flex flex-col justify-between shadow text-white text-2xl font-bold py-4 px-6 rounded-xl">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<p>выигрыш:</p><span className="text-yellow-400">5000</span>
|
<p>выигрыш:</p>
|
||||||
|
<span className="text-yellow-400">5000</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<p>ставка:</p><span className="text-yellow-400">10 000</span>
|
<p>ставка:</p>
|
||||||
|
<span className="text-yellow-400">10 000</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="min-h-[800px] w-full bg-fuchsia-600 flex items-center justify-center">
|
<div className="min-h-[800px] w-full flex items-center justify-center">
|
||||||
<div className="flex flex-row portrait:flex-col justify-center items-center my-auto">
|
<div className="flex flex-row portrait:flex-col justify-center items-center my-auto">
|
||||||
<Reel rng={rng} rngReverse={rngReverse} cellCount={cellCount} isHorizontal={isHorizontal} />
|
<Reel rng={rng} rngReverse={rngReverse} cellCount={7} isHorizontal={isHorizontal} />
|
||||||
<Reel rng={rng} rngReverse={rngReverse} cellCount={cellCount} isHorizontal={isHorizontal} />
|
<Reel rng={rng} rngReverse={rngReverse} cellCount={7} isHorizontal={isHorizontal} />
|
||||||
<Reel rng={rng} rngReverse={rngReverse} cellCount={cellCount} isHorizontal={isHorizontal} />
|
<Reel rng={rng} rngReverse={rngReverse} cellCount={7} isHorizontal={isHorizontal} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="max-w-[100px]">
|
<div className="max-w-[100px]">
|
||||||
<SlotPlayButton />
|
<SlotPlayButton onClick={spinReels} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ContainerLayout>
|
</ContainerLayout>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
SlotGamePage.propTypes = {
|
|
||||||
cellCount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
|
|
||||||
};
|
};
|
Loading…
Reference in a new issue