node-mongo-demo

node.js and mongodb demo

git clone https://9o.is/git/node-mongo-demo.git

Lucky7.js

(4780B)


      1 import React from 'react';
      2 import * as api from '../api';
      3 
      4 const useSession = () => {
      5     const [session, setSession] = React.useState(undefined);
      6 
      7     React.useEffect(() => {
      8         const func = async () => {
      9             const response = await api.lucky7Session();
     10             setSession(response.data);
     11         };
     12         func();
     13     }, []);
     14 
     15     return {
     16         session,
     17     };
     18 };
     19 
     20 const useBetEvents = onEvent => {
     21     const [listening, setListening] = React.useState(false);
     22 
     23     React.useEffect(() => {
     24         const connect = async () => {
     25             const response = await api.lucky7BetEvents();
     26             const stream = response.data;
     27 
     28             const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
     29             setListening(true);
     30             while (true) {
     31                 const { value, done } = await reader.read();
     32                 if (done) {
     33                     setListening(false);
     34                     break;
     35                 }
     36                 const json = JSON.parse(value.slice(5));
     37                 onEvent(json);
     38             }
     39         };
     40         if (!listening) connect();
     41     }, [listening, onEvent]);
     42 };
     43 
     44 const getNextGameTime = (createdAt) => {
     45   const startDateTime = new Date(createdAt);
     46   const currentSeconds = Math.ceil(new Date() / 1000);
     47   const startSeconds = Math.floor(startDateTime.getTime() / 1000);
     48   const difference = currentSeconds - startSeconds;
     49 
     50   const nextChunk = Math.ceil(difference / 15) * 15;
     51   return new Date((startSeconds + nextChunk) * 1000);
     52 };
     53 
     54 const millisRemaining = date => date - Date.now();
     55 const secondsRemaining = date => Math.ceil((date - Date.now()) / 1000);
     56 
     57 const Timer = ({ createdAt }) => {
     58     const [nextGameTime, setNextGameTime] = React.useState(getNextGameTime(createdAt));
     59     const [seconds, setSeconds] = React.useState(secondsRemaining(nextGameTime));
     60 
     61     React.useEffect(() => {
     62         let timeout;
     63         let interval;
     64 
     65         const countdown = () => {
     66             setSeconds((prevSeconds) => prevSeconds === 0 ? 0 : prevSeconds - 1);
     67         };
     68 
     69         const resetTimer = () => {
     70             const nextGameTime = getNextGameTime(createdAt);
     71             setNextGameTime(nextGameTime);
     72             setSeconds(secondsRemaining(nextGameTime));
     73             clearInterval(interval);
     74 
     75             interval = setInterval(countdown, 1000);
     76             timeout = setTimeout(resetTimer, millisRemaining(nextGameTime));
     77         };
     78 
     79         resetTimer();
     80 
     81         return () => {
     82             clearTimeout(timeout);
     83             clearInterval(interval);
     84         };
     85     }, [createdAt, setSeconds, setNextGameTime]);
     86 
     87     return (
     88         <>
     89             Timer: {seconds}s<br/>
     90         </>
     91     );
     92 };
     93 
     94 const sortBets = bets =>
     95     Object.values(bets).sort((a, b) => a.rollAt < b.rollAt ? 1 : -1);
     96 
     97 const Lucky7 = user => {
     98     const { session } = useSession();
     99 
    100     const [bets, setBets] = React.useState({});
    101     const [error, setError] = React.useState(undefined);
    102 
    103     const eventHandler = React.useCallback(e => {
    104         const { bet } = e;
    105         setBets(bets => ({ ...bets, [bet.id]: { ...bets[bet.id], ...bet } }));
    106         setError(undefined);
    107     }, [setBets, setError]);
    108 
    109     useBetEvents(eventHandler);
    110 
    111     const handleBet = lucky => async () => {
    112         try {
    113             await api.lucky7Bet(lucky);
    114             setError(undefined);
    115         } catch (error) {
    116             if (error.status === 409 && error.response.data.code === 'SESSION_TIMER') {
    117                 setError(error.response.data.error);
    118             } else {
    119                 console.error(error)
    120             }
    121         }
    122     };
    123 
    124     return (
    125         <>
    126             {error ? <div>{error}</div> : <>&nbsp;</>}
    127             <div>
    128                 <button onClick={handleBet(true)}>Lucky</button>
    129                 <button onClick={handleBet(false)}>Unlucky</button>
    130                 {session ? <Timer createdAt={session.createdAt} /> : null}
    131             </div>
    132             <table>
    133                 <thead>
    134                     <tr>
    135                         <th>state</th>
    136                         <th>rollAt</th>
    137                         <th>lucky</th>
    138                         <th>roll</th>
    139                         <th>win</th>
    140                     </tr>
    141                 </thead>
    142                 <tbody>
    143                     {sortBets(bets).map(bet => (
    144                         <tr key={bet.id}>
    145                             <td>{bet.state}</td>
    146                             <td>{bet.rollAt}</td>
    147                             <td>{String(bet.lucky ?? '')}</td>
    148                             <td>{(bet.roll || []).join(',')}</td>
    149                             <td>{String(bet.win ?? '')}</td>
    150                         </tr>
    151                     ))}
    152                 </tbody>
    153             </table>
    154         </>
    155     );
    156 };
    157 
    158 export default Lucky7;
    159