Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
โ€ฆo-with-me into 138-๋Œ€ํšŒ-์„ธ๋ถ€์ •๋ณด-ํŽ˜์ด์ง€-์ƒ์„ฑ
  • Loading branch information
dmdmdkdkr committed Nov 29, 2023
2 parents 82231ee + 51ba82e commit 80981df
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
import { css } from '@style/css';

import { useEffect } from 'react';

import Loading from '@/components/Common/Loading';
import useTimer from '@/hooks/timer/useTimer';
import useSocketTimer from '@/hooks/timer/useSocketTimer';
import { formatMilliSecond } from '@/utils/date';
import type { Socket } from '@/utils/socket';

interface Props {
socket: Socket;
isConnected: boolean;
endsAt: Date;
isConnected?: boolean;
onTimeout?: () => void;
}

export default function Timer(props: Props) {
let { socket, endsAt, isConnected } = props;
export default function SocketTimer(props: Props) {
let { socket, endsAt, isConnected, onTimeout } = props;
// api ์—ฐ๊ฒฐ์ด X endsAt ๋Œ€์‹  ์ž„์‹œ๋กœ ๋งŒ๋“ค์–ด๋†“์€ ๊ฒƒ.
endsAt = new Date('2023-11-29T13:10:10.000Z');
const { remainMiliSeconds } = useTimer({ socket, endsAt });
// min 1 => 60์ดˆ ๋™์•ˆ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ๋ณ€๊ฒฝํ•ด์„œ ์“ฐ์„ธ์š” ์ผ๋‹จ์€..
const min = 120;
endsAt = new Date(new Date().getTime() + min * 60 * 1000);

const { remainMiliSeconds, isTimeout } = useSocketTimer({
socket,
endsAt,
socketEvent: 'ping',
});

useEffect(() => {
if (isTimeout && typeof onTimeout === 'function') onTimeout();
}, [isTimeout]);

if (isConnected && remainMiliSeconds !== -1) {
// ์—ฐ๊ฒฐ๋„ ๋˜์–ด์žˆ๊ณ , ์„œ๋ฒ„ ์‹œ๊ฐ„๋„ ๋„์ฐฉํ•ด์„œ count down์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/Submission/Connecting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface Props {
}

export default function Connecting(props: Props) {
if (!props.isConnected) return null;
if (props.isConnected) return null;

return (
<div className={rowStyle}>
Expand All @@ -16,6 +16,7 @@ export default function Connecting(props: Props) {
</div>
);
}

const rowStyle = css({
display: 'flex',
gap: '0.5rem',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,36 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { Socket } from '@/utils/socket';

interface UseTimer {
interface Props {
socket: Socket;
endsAt: Date;
onTimeoutHandler?: () => void;
socketEvent: string;
}

export default function useTimer({ socket, endsAt, onTimeoutHandler }: UseTimer) {
export default function useSocketTimer({ socket, endsAt, socketEvent }: Props) {
const timerIntervalId = useRef<NodeJS.Timeout | null>(null);
const endTime = useMemo(() => endsAt.getTime(), [endsAt]);
const [isTimeout, setIsTimeout] = useState(false);
const [remainMiliSeconds, setRemainMiliSeconds] = useState<number>(-1);

useEffect(() => {
console.log('ํƒ€์ด๋จธ ์‹คํ–‰');
// ์›น ์†Œ์ผ“ ๋Œ€์‹  ์‚ฌ์šฉ.
mockWebSocket();
if (!socket.hasListeners('ping')) {
socket.on('ping', handlePingMessage);
socket.emit(socketEvent);
if (socket.hasListeners(socketEvent)) {
socket.on(socketEvent, handlePingMessage);
}
}, [socket]);

const handlePingMessage = useCallback((time: Date | string) => {
console.log(time);
if (timerIntervalId.current) clearInterval(timerIntervalId.current);

time = typeof time === 'string' ? new Date(time) : time;
const remainMiliSec = endTime - time.getTime();
setRemainMiliSeconds(remainMiliSec);
timerIntervalId.current = setInterval(() => {
console.log('1์ดˆ๋งˆ๋‹ค ์‹คํ–‰');
setRemainMiliSeconds((prev) => prev - 1000);
}, 1000);
}, []);
Expand All @@ -37,20 +40,20 @@ export default function useTimer({ socket, endsAt, onTimeoutHandler }: UseTimer)
// ์›น ์†Œ์ผ“ ์—ฐ๊ฒฐ ํ›„ ์‚ญ์ œ ์˜ˆ์ •
const mockWebSocket = useCallback(() => {
const delayFactor = 2000;
const serverTime = new Date();
handlePingMessage(serverTime);
setInterval(() => {
console.log('ping 5์ดˆ( + ๋„คํŠธ์›Œํฌ ์ง€์—ฐ) ๋งˆ๋‹ค ์‹คํ–‰');
const serverTime = new Date();
handlePingMessage(serverTime);
}, 5000 + Math.random() * delayFactor);
}, []);

useEffect(() => {
// TODO time 0์ด๋ฉด ๋Œ€์‹œ๋ณด๋“œ๋กœ ์ด๋™ํ•˜๋Š” ๋กœ์ง
// ํ•ด๋‹น PR์—์„œ ํ•ด๊ฒฐํ•  ๋ฌธ์ œ๋Š” ์•„๋‹ˆ๋ผ PASS
// ์ดˆ๊ธฐ ๊ฐ’์ธ -1 => ์„œ๋ฒ„์—์„œ ์‹œ๊ฐ„์ด ์˜ค์ง€ ์•Š์•˜๋‹ค.
if (remainMiliSeconds === -1) return;
if (Math.floor(remainMiliSeconds / 1000) <= 0) {
if (typeof onTimeoutHandler === 'function') onTimeoutHandler();
// ๋‚˜๊ฐ€๋Š” ๋กœ์ง
setIsTimeout(true);
}
}, [remainMiliSeconds]);
return { remainMiliSeconds };
return { remainMiliSeconds, isTimeout };
}
24 changes: 21 additions & 3 deletions frontend/src/pages/ContestPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { css } from '@style/css';

import { useContext, useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';

import { ModalContext } from '@/components/Common/Modal/ModalContext';
import CompetitionHeader from '@/components/Contest/CompetitionHeader';
Expand All @@ -10,8 +11,8 @@ import Editor from '@/components/Editor/Editor';
import ProblemViewer from '@/components/Problem/ProblemViewer';
import { SimulationInputModal } from '@/components/Simulation/SimulationInputModal';
import { SimulationResultList } from '@/components/Simulation/SimulationResultList';
import SocketTimer from '@/components/SocketTimer';
import { SubmissionResult } from '@/components/Submission';
import Timer from '@/components/Timer';
import { SITE } from '@/constants';
import type { SubmissionForm } from '@/hooks/competition';
import { useCompetition } from '@/hooks/competition';
Expand All @@ -22,13 +23,16 @@ import { isNil } from '@/utils/type';

const RUN_SIMULATION = 'ํ…Œ์ŠคํŠธ ์‹คํ–‰';
const CANCEL_SIMULATION = '์‹คํ–‰ ์ทจ์†Œ';
const DASHBOARD_URL = '/contest/dashboard';

export default function ContestPage() {
const { id } = useParams<{ id: string }>();
const competitionId: number = id ? parseInt(id, 10) : -1;
const [currentProblemIndex, setCurrentProblemIndex] = useState(0);
const modal = useContext(ModalContext);

const navigate = useNavigate();

const simulation = useSimulation();

const { socket, competition, submitSolution, isConnected } = useCompetition(competitionId);
Expand Down Expand Up @@ -88,14 +92,23 @@ export default function ContestPage() {
modal.open();
}

function handleTimeout() {
navigate(`${DASHBOARD_URL}/${competitionId}`);
}

const problems = problemList.map((problem) => problem.id);

return (
<main className={style}>
<CompetitionHeader crumbs={crumbs} id={competitionId} />
<section>
<section className={rowStyle}>
<span className={problemTitleStyle}>{problem.title}</span>
<Timer socket={socket.current} isConnected={isConnected} endsAt={new Date(endsAt)} />
<SocketTimer
socket={socket.current}
isConnected={isConnected}
endsAt={new Date(endsAt)}
onTimeout={handleTimeout}
/>
</section>
<section className={rowListStyle}>
<ContestProblemSelector
Expand Down Expand Up @@ -158,3 +171,8 @@ const problemTitleStyle = css({
const execButtonStyle = css({
color: 'black',
});

const rowStyle = css({
display: 'flex',
justifyContent: 'space-between',
});

0 comments on commit 80981df

Please sign in to comment.