export default function Stats()

in pinball-frontend/app/events/page.tsx [20:194]


export default function Stats() {
  const [gameEvents, setGameEvents] = useState<GameEvent[]>([]);
  const [gameStartEvent, setGameStartEvent] = useState<GameEvent | null>(null);
  const gameStartTimestamp = gameStartEvent?.utcTimestamp || getNowTimestamp();
  const [timeElapsedMillis, setTimeElapsedMillis] = useState(0);
  const [machineId, setMachineId] = useState('');
  const [gameId, setGameId] = useState('');
  const lastPrEvent = gameEvents.find((gameEvent) => gameEvent?.data?.BacklogName === 'PR');
  const prCount = lastPrEvent ? lastPrEvent.data.BacklogCount : gameStartEvent ? gameStartEvent.data.InitialPRCount : 0;
  const lastBugEvent = gameEvents.find((gameEvent) => gameEvent?.data?.BacklogName === 'Bug');
  const bugCount = lastBugEvent ? lastBugEvent.data.BacklogCount : gameStartEvent ? gameStartEvent.data.InitialBugCount : 0;
  const lastBallDrainEvent = gameEvents.find((gameEvent) => gameEvent.pinballEventType === 'BallDrained');
  const ballDrainCount = lastBallDrainEvent ? lastBallDrainEvent.data.TotalDrains : 0;
  const lastBallLaunchEvent = gameEvents.find((gameEvent) => gameEvent.pinballEventType === 'BallLaunched');
  const ballLaunchCount = lastBallLaunchEvent ? lastBallLaunchEvent.data.LaunchedBallCount : 0;
  const lastLoopHitEvent = gameEvents.find((gameEvent) => gameEvent.pinballEventType === 'LoopHit');
  const loopHitCount = lastLoopHitEvent ? lastLoopHitEvent.data.TotalLoops : 0;
  const [currentGame, setCurrentGame] = useState({
    gameId: 'CURRENT_GAME',
    playerName: '',
    avatar: '',
  });

  useEffect(() => {
    const interval = setInterval(() => {
      const gameEndEvent = gameEvents.find((gameEvent) => (gameEvent.pinballEventType === 'GameEnded'));
      if (gameEndEvent) {
        setTimeElapsedMillis(gameEndEvent.gameLengthMilliseconds);
      } else if (gameStartTimestamp) {
        const now = getNowTimestamp();
        setTimeElapsedMillis(now - gameStartTimestamp);
      } else {
        setTimeElapsedMillis(0);
      }
    }, 1000);

    //Clearing the interval
    return () => clearInterval(interval);
  }, [gameEvents, gameStartTimestamp, timeElapsedMillis]);

  useEffect(() => {
    const liveEventsQuery = query(liveGameEventsRef, orderBy('publishTime', 'desc'), limit(1000));
    const unsubscribe = onSnapshot(liveEventsQuery, (querySnapshot) => {
      const gameEvents = querySnapshot.docs.map((doc) => {
        const { GameId, ...data } = doc.data().data; // remove GameId from data
        // sorts the keys so they are always printed in the same order
        const dataString = JSON.stringify(data, Object.keys(data).sort(), 2);
        const pinballEventType = doc.data().PinballEventType;
        const utcTimestamp = doc.data().utcTimestamp;
        if (doc.data().MachineId) {
          setMachineId(doc.data().MachineId);
        }
        if (doc.data().GameId) {
          setGameId(doc.data().GameId);
        }
        const gameEvent = {
          messageId: doc.data().messageId,
          publishTime: doc.data().publishTime,
          pinballEventType,
          utcTimestamp,
          gameLengthMilliseconds: data.GameLengthMilliseconds,
          dataString,
          data,
        };
        if (pinballEventType === 'GameStarted') {
          console.log({ docData: doc.data() })
          setGameStartEvent(gameEvent)
          setCurrentGame({
            ...currentGame,
            playerName: data.PlayerName,
            avatar: data.Avatar,
          });
        }
        return gameEvent;
      });
      setGameEvents(gameEvents);
    });
    return unsubscribe;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);


const twoDigitPad = (number: number) => {
  return ('0' + number).slice(-2);
}

  return (
    <main className="flex min-h-screen flex-col justify-between overflow-x-hidden m-4">
      <QRCodeLink url="https://pinball-frontend-404073014646.us-west3.run.app/events" />
      <div className="flex">
        <div className="w-full">
          <div className="pb-2 sm:flex">
            <div className="font-bold pr-4 text-xl">Machine ID:</div>
            <div className="font-mono text-xs sm:text-lg">{machineId}</div>
          </div>
          <div className="pb-2 sm:flex">
            <div className="font-bold pr-4 text-xl">Game ID:</div>
            <div className="font-mono text-xs sm:text-lg">{gameId}</div>
          </div>
          <div className="grid grid-cols-2 md:grid-cols-3 p-2" style={{ borderWidth: '2px', borderColor: '#FBBC04' }}>
            <MetricsTile
              title="Game Events"
              value={gameEvents.length}
            />
            <MetricsTile
              title="Ball Drains"
              value={ballDrainCount}
            />
            <MetricsTile
              title="Launched Balls"
              value={ballLaunchCount}
            />
            <MetricsTile
              title="Loops Hit"
              value={loopHitCount}
            />
          </div>
          <table className="text-left font-thin mt-12">
            <thead>
              <tr>
                <th scope="col" className="hidden sm:block px-6 py-3 w-[10ch]">
                  Metadata
                </th>
                <th scope="col" className="px-6 py-3">
                  Event Data
                </th>
              </tr>
            </thead>
            <tbody>
              {gameEvents.map((gameEvent) => (
                <tr key={gameEvent.messageId} className="border border-t-1 border-b-0 border-l-0 border-r-0" >
                  <td className="hidden sm:block px-6 py-4 font-mono">
                    <div className="text-xl whitespace-nowrap">
                      Event Type:
                      <br />
                      {gameEvent.pinballEventType}
                    </div>
                    <div className="text-xs whitespace-nowrap py-4">
                      Message Id:
                      <br />
                      {gameEvent.messageId}
                    </div>
                  </td>
                  <td scope="row" className="px-6 py-4 whitespace-nowrap font-mono">
                    <div className="sm:hidden text-xs whitespace-nowrap">
                      <div className="text-xl whitespace-nowrap">
                        Event Type: {gameEvent.pinballEventType}
                      </div>
                      <div className="text-xs whitespace-nowrap py-4">
                        Message Id: {gameEvent.messageId}
                      </div>
                    </div>
                    <pre className="text-sm md:text-xl">
                      {gameEvent.dataString}
                    </pre>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <ActiveRankingCard
          title="Game Length Leader Board"
          field="GameLengthMilliseconds"
          mapper={(milliseconds: number) => Math.floor(milliseconds / 1000)}
          units="seconds"
          currentGame={{
            ...currentGame,
            value: timeElapsedMillis,
          }}
        />
      </div>
    </main >
  );
}