From 75f4846ebb11984d40273fc23e49d88bc4538a36 Mon Sep 17 00:00:00 2001 From: kowoohyuk Date: Mon, 10 May 2021 15:55:16 +0900 Subject: [PATCH 01/22] =?UTF-8?q?[#29]=20refactor:=20:hammer:=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EA=B8=B0=EB=B0=98=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/App.js | 4 +-- fe/src/components/game-list/GameList.jsx | 18 ++++++------ fe/src/components/game-list/GameListItem.jsx | 13 ++++----- fe/src/components/game-play/GamePlay.jsx | 12 ++++---- .../components/game-play/board/BallCount.jsx | 14 ++++----- fe/src/components/game-play/board/Board.jsx | 6 ++-- fe/src/components/game-play/board/Inning.jsx | 4 +-- fe/src/components/game-play/board/Screen.jsx | 16 +++++----- fe/src/components/game-play/log/Log.jsx | 6 ++-- fe/src/components/game-play/player/Player.jsx | 29 +++++++------------ .../game-play/popup/roster/Roster.jsx | 6 ++-- .../game-play/popup/roster/RosterPlayer.jsx | 17 +++++++++++ .../game-play/popup/roster/TeamRoster.jsx | 25 +++++----------- .../game-play/popup/score/Score.jsx | 6 ++-- .../game-play/popup/score/ScoreList.jsx | 20 ++++++------- fe/src/components/game-play/score/Score.jsx | 6 ++-- fe/src/components/ui/PopUp.jsx | 15 +++++----- fe/src/index.css | 5 ---- 18 files changed, 109 insertions(+), 113 deletions(-) create mode 100644 fe/src/components/game-play/popup/roster/RosterPlayer.jsx diff --git a/fe/src/App.js b/fe/src/App.js index 9bf3775bb..bf5532a11 100644 --- a/fe/src/App.js +++ b/fe/src/App.js @@ -6,14 +6,14 @@ import background from './images/background.png'; function App() { return ( <> - + {/* */} ); } -const StyleBackground = styled.div` +const StyledBackground = styled.div` background-image: url(${(props) => props.src}); background-size: cover; position: absolute; diff --git a/fe/src/components/game-list/GameList.jsx b/fe/src/components/game-list/GameList.jsx index 57e0552e9..5590a446f 100644 --- a/fe/src/components/game-list/GameList.jsx +++ b/fe/src/components/game-list/GameList.jsx @@ -10,20 +10,20 @@ const GameList = (props) => { )); return ( - - {TITLE} - {DESCRIPTION} - {gameList} - + + {TITLE} + {DESCRIPTION} + {gameList} + ); }; -const StyleGameList = styled.div` +const StyledGameList = styled.div` padding: 0 15vw; margin-top: 2.5rem; `; -const StyleTitle = styled.div` +const StyledTitle = styled.div` margin-bottom: 5rem; font-size: 3rem; font-weight: 600; @@ -31,14 +31,14 @@ const StyleTitle = styled.div` text-align: center; `; -const StyleDescription = styled.div` +const StyledDescription = styled.div` margin-bottom: 2rem; font-size: 2rem; color: #fff; text-align: center; `; -const StyleList = styled.div` +const StyledList = styled.div` max-width: 50rem; margin: 0 auto; padding-left: 1.0625rem; diff --git a/fe/src/components/game-list/GameListItem.jsx b/fe/src/components/game-list/GameListItem.jsx index bfc6f812b..dacaec5d1 100644 --- a/fe/src/components/game-list/GameListItem.jsx +++ b/fe/src/components/game-list/GameListItem.jsx @@ -2,24 +2,23 @@ import React from 'react'; import styled from 'styled-components'; const GameListItem = ({ home, away, game_id, idx }) => { return ( - +
GAME {idx + 1}
{home}
vs
{away}
-
+ ); }; -const StyleGameItem = styled.div` +const StyledGameItem = styled.div` margin: 0 auto; margin-bottom: 1.5rem; padding: 1rem 0; border-radius: 1rem; - opacity: 0.95; - background-color: #d2d2d2; + background-color: rgba(210, 210, 210, 0.95); .title { color: #ff4545; text-align: center; @@ -32,7 +31,7 @@ const StyleGameItem = styled.div` text-align: center; align-items: center; padding: 1rem 0; - .teams-name { + &-name { font-size: 2rem; font-weight: 600; cursor: pointer; @@ -40,7 +39,7 @@ const StyleGameItem = styled.div` color: #ff4545; } } - .teams-vs { + &-vs { padding-bottom: 0.5rem; font-size: 2.5rem; font-weight: 600; diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index 1fcb145c0..473632857 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -45,24 +45,24 @@ const GamePlay = ({ home, away, game_id }) => { const memberList = { home: data.home.member_list, away: data.home.member_list }; const pitchers = { home: data.home.pitcher, away: data.home.pitcher }; return ( - + - + {/* {/* */} {/* */} - - + + ); }; -const StyleGamePlay = styled.div``; +const StyledGamePlay = styled.div``; -const StyleGamePlayGrid = styled.div` +const StyledGamePlayGrid = styled.div` display: grid; grid-template-columns: 3fr minmax(19.5rem, 1fr); grid-template-rows: minmax(14.5rem, 25vh) 75vh; diff --git a/fe/src/components/game-play/board/BallCount.jsx b/fe/src/components/game-play/board/BallCount.jsx index e15f89dda..ac9ca9b8c 100644 --- a/fe/src/components/game-play/board/BallCount.jsx +++ b/fe/src/components/game-play/board/BallCount.jsx @@ -3,20 +3,20 @@ import styled from 'styled-components'; const BallCount = ({ ballCount: { strike, ball, out } }) => { return ( - -
+ +
S
{createBallCountTag(strike)}
-
+
B
{createBallCountTag(ball)}
-
+
O
{createBallCountTag(out)}
- + ) } @@ -28,10 +28,10 @@ function createBallCountTag(count) { return result; } -const StyleBallCount = styled.div` +const StyledBallCount = styled.div` color:#fff; font-weight:600; - .couters { + .counters { display: flex; margin-bottom:0.5rem; & > div { diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 72764c3c5..1b1672f6e 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -4,14 +4,14 @@ import Inning from './Inning'; import Screen from './Screen'; const Board = (props) => ( - + - + ); -const StyledBoard = styled.div` +const StyleddBoard = styled.div` display: grid; grid-template-columns: 10rem 1fr 10rem; `; diff --git a/fe/src/components/game-play/board/Inning.jsx b/fe/src/components/game-play/board/Inning.jsx index bba297793..f08bc62cf 100644 --- a/fe/src/components/game-play/board/Inning.jsx +++ b/fe/src/components/game-play/board/Inning.jsx @@ -1,10 +1,10 @@ import React from 'react'; import styled from 'styled-components'; const Inning = ({ inning: { turn, round }, isHome }) => { - return {round}회{turn ? '초' : '말'} {(isHome && turn) || (!isHome && !turn) ? '공격' : '수비'} + return {round}회{turn ? '초' : '말'} {(isHome && turn) || (!isHome && !turn) ? '공격' : '수비'} } -const StyleInning = styled.div` +const StyledInning = styled.div` font-size: 1.5rem; font-weight: 600; color: #fff; diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index c84f1476c..57159b303 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -4,24 +4,24 @@ import styled from 'styled-components'; const Screen = (props) => { return ( - - PITCH - + + PITCH +
-
-
+ + ); } -const StyleScreen = styled.div` +const StyledScreen = styled.div` position:relative; align-self: center; `; -const StylePitch = styled.button` +const StyledPitch = styled.button` position: absolute; top: calc(50% - 1.5rem); left: calc(50% - 5rem); @@ -43,7 +43,7 @@ const StylePitch = styled.button` } ` -const StyleGround = styled.div` +const StyledGround = styled.div` border: 3px solid #fff; width: 20rem; height: 20rem; diff --git a/fe/src/components/game-play/log/Log.jsx b/fe/src/components/game-play/log/Log.jsx index 925f417f5..e2391dcc8 100644 --- a/fe/src/components/game-play/log/Log.jsx +++ b/fe/src/components/game-play/log/Log.jsx @@ -31,15 +31,15 @@ const Log = (props) => {
)); return ( - +
{log_list}
-
+ ); }; -const StyleLog = styled.div` +const StyledLog = styled.div` .logs { display: flex; flex-flow: column-reverse; diff --git a/fe/src/components/game-play/player/Player.jsx b/fe/src/components/game-play/player/Player.jsx index 4e5a2a663..ca4a517a2 100644 --- a/fe/src/components/game-play/player/Player.jsx +++ b/fe/src/components/game-play/player/Player.jsx @@ -4,28 +4,21 @@ const Player = ({ memberList, turn, pitchers }) => { const HOME = 'home'; const AWAY = 'away'; - const getMember = (id, members) => { + const getPlayer = (members, id) => { + const result = {}; for (const member of members) { - if (member.id === id) return member; + if (member.id === id) result.pitcher = member; + if (member.state) result.batter = member; } - return null; + return result; }; - const getBatter = (members) => { - for (const member of members) { - if (member.state) return member; - } - return null; - }; - - const pitcher = turn - ? getMember(pitchers[HOME], memberList[HOME]) - : getMember(pitchers[AWAY], memberList[AWAY]); - - const batter = turn ? getBatter(memberList[HOME]) : getBatter(memberList[AWAY]); + const { pitcher, batter } = turn + ? getPlayer(memberList[HOME], pitchers[HOME]) + : getPlayer(memberList[AWAY], pitchers[AWAY]); return ( - +
투수
@@ -42,11 +35,11 @@ const Player = ({ memberList, turn, pitchers }) => {
- + ); }; -const StylePlayer = styled.div` +const StyledPlayer = styled.div` height: 100%; padding-bottom: 1.5rem; display: flex; diff --git a/fe/src/components/game-play/popup/roster/Roster.jsx b/fe/src/components/game-play/popup/roster/Roster.jsx index 7d8315458..f7c47e72a 100644 --- a/fe/src/components/game-play/popup/roster/Roster.jsx +++ b/fe/src/components/game-play/popup/roster/Roster.jsx @@ -3,15 +3,15 @@ import TeamRoster from './TeamRoster'; const Roster = () => { // team_name 필요 return ( - + - + ); } // 90vw는 돼야하는데 그러면 이상함...; -const StyleRoster = styled.div` +const StyledRoster = styled.div` margin: 0 auto; max-width: 60vw; margin-top: 5rem; diff --git a/fe/src/components/game-play/popup/roster/RosterPlayer.jsx b/fe/src/components/game-play/popup/roster/RosterPlayer.jsx new file mode 100644 index 000000000..532ba7f85 --- /dev/null +++ b/fe/src/components/game-play/popup/roster/RosterPlayer.jsx @@ -0,0 +1,17 @@ +import React from 'react'; + +const RosterPlayer = ({ name, at_bat, safety, out, player_name }) => { + const getAverage = (at_bat, safety) => (safety / at_bat).toFixed(3); + const class_name = 'roster--member' + (name === player_name ? ' active' : ''); + return ( +
  • +
    {name}
    +
    {at_bat}
    +
    {safety}
    +
    {out}
    +
    {getAverage(at_bat, safety)}
    +
  • + ); +}; + +export default RosterPlayer; \ No newline at end of file diff --git a/fe/src/components/game-play/popup/roster/TeamRoster.jsx b/fe/src/components/game-play/popup/roster/TeamRoster.jsx index 30cf3ec1d..b5dc3f419 100644 --- a/fe/src/components/game-play/popup/roster/TeamRoster.jsx +++ b/fe/src/components/game-play/popup/roster/TeamRoster.jsx @@ -1,31 +1,22 @@ import styled from 'styled-components'; +import RosterPlayer from './RosterPlayer'; const TeamRoster = ({ member_list, player_name, team_name = '베리베리 스트로베리', player = false }) => { const HEADS = ['타자', '타석', '안타', '아웃', '평균']; const TOTALTEXT = 'Totals'; const heads = HEADS.map((head, idx) =>
    {head}
    ); - const getAverage = (at_bat, safety) => (safety / at_bat).toFixed(3); let [totalAtBat, totalSafety, totalOut] = [0, 0, 0]; - const members = member_list.map(({ name, at_bat, safety, out }, idx) => { + const members = member_list.map((member, idx) => { + const { at_bat, safety, out } = member; totalAtBat += at_bat; totalSafety += safety; totalOut += out; - const class_name = 'roster--member' + (name === player_name ? ' active' : ''); - return ( -
  • -
    {name}
    -
    {at_bat}
    -
    {safety}
    -
    {out}
    -
    {getAverage(at_bat, safety)}
    -
  • - ); - } - ); + return + }); return ( - +
    {team_name} {player &&
    Player
    }
    • @@ -40,11 +31,11 @@ const TeamRoster = ({ member_list, player_name, team_name = '베리베리 스트
    -
    + ); } -const StyleTeamRoster = styled.div` +const StyledTeamRoster = styled.div` .title { font-size: 1.5rem; font-weight: 600; diff --git a/fe/src/components/game-play/popup/score/Score.jsx b/fe/src/components/game-play/popup/score/Score.jsx index 0d4e6267d..bee530063 100644 --- a/fe/src/components/game-play/popup/score/Score.jsx +++ b/fe/src/components/game-play/popup/score/Score.jsx @@ -7,15 +7,15 @@ const Score = (props) => { const ROUND = new Array(12).fill().map((_, idx) => idx + 1); return ( - + - + ); }; -const StyleScore = styled.div` +const StyledScore = styled.div` width: 70rem; min-width: 63rem; display: flex; diff --git a/fe/src/components/game-play/popup/score/ScoreList.jsx b/fe/src/components/game-play/popup/score/ScoreList.jsx index 679762fd3..c7105bc2e 100644 --- a/fe/src/components/game-play/popup/score/ScoreList.jsx +++ b/fe/src/components/game-play/popup/score/ScoreList.jsx @@ -3,37 +3,37 @@ import styled from 'styled-components'; import { IoBaseballOutline } from 'react-icons/io5'; const ScoreList = ({ team, dataType, data, isPlayer }) => { - const isRound = dataType === 'round'; + const isInRound = dataType === 'round'; const scoreList = new Array(12).fill(''); data.forEach((v, idx) => (scoreList[idx] = v)); - isRound ? scoreList.push('R') : scoreList.push(data.reduce((acc, cur) => acc + cur)); + isInRound ? scoreList.push('R') : scoreList.push(data.reduce((acc, cur) => acc + cur)); const scoreDivList = scoreList.map((score, idx, arr) => (
    {score}
    )); return ( - +
    {isPlayer && } -
    {team ? team : ''}
    +
    {team || ''}
    {isPlayer &&
    player
    }
    {scoreDivList}
    -
    + ); }; -const StyleScoreList = styled.div` +const StyledScoreList = styled.div` display: flex; .team-wrapper { @@ -61,8 +61,8 @@ const StyleScoreList = styled.div` } .score-list { - border-bottom: ${({ isRound }) => isRound && '3px solid #fff'}; - margin-bottom: ${({ isRound }) => (isRound ? '1rem' : '0.3rem')}; + border-bottom: ${({ isInRound }) => isInRound && '3px solid #fff'}; + margin-bottom: ${({ isInRound }) => (isInRound ? '1rem' : '0.3rem')}; } .score { display: flex; @@ -70,7 +70,7 @@ const StyleScoreList = styled.div` font-size: 1.5rem; font-weight: 700; width: 3rem; - height: ${({ isRound }) => (isRound ? '2.7rem' : '3rem')}; + height: ${({ isInRound }) => (isInRound ? '2.7rem' : '3rem')}; margin-right: 1rem; } .last-score { diff --git a/fe/src/components/game-play/score/Score.jsx b/fe/src/components/game-play/score/Score.jsx index d3043fc5b..453f200e6 100644 --- a/fe/src/components/game-play/score/Score.jsx +++ b/fe/src/components/game-play/score/Score.jsx @@ -4,7 +4,7 @@ const Score = ({ teamName, score, turn }) => { const TITLE = 'BASEBALL GAME ONLINE'; const TURN = 'Player'; return ( - +
    {TITLE}
    @@ -24,11 +24,11 @@ const Score = ({ teamName, score, turn }) => {
    - + ); }; -const StyleScore = styled.div` +const StyledScore = styled.div` .title { font-size: 3rem; font-weight: 600; diff --git a/fe/src/components/ui/PopUp.jsx b/fe/src/components/ui/PopUp.jsx index bbee37ffa..299a6f75b 100644 --- a/fe/src/components/ui/PopUp.jsx +++ b/fe/src/components/ui/PopUp.jsx @@ -3,12 +3,12 @@ import styled, { keyframes } from 'styled-components'; const PopUp = ({ children, position }) => { const [active, setActive] = useState(false); - const handleClick = ({target}) => !target.closest('.childrenWrapper') && setActive(false); - return active ? + const handleClick = ({target}) => (target.className === 'childrenWrapper' || !target.closest('.childrenWrapper')) && setActive(false); + return active ?
    {children}
    -
    : setActive(true)} />; + : setActive(true)} />; }; const toBottom = keyframes` @@ -29,12 +29,13 @@ const toTop = keyframes` } `; -const StylePopUp = styled.div` +const StyledPopUp = styled.div` position: absolute; top: 0; width: 100vw; height: 100vh; z-index: 2; + text-align: center; &:before { background-color: rgba(0, 0, 0, 0.9); content: ''; @@ -50,7 +51,7 @@ const StylePopUp = styled.div` } `; -const StyleEmpty = styled.div` +const StyledEmpty = styled.div` width:100vw; height:5rem; position: absolute; @@ -62,10 +63,10 @@ const StyleEmpty = styled.div` export default PopUp; // const PopUp = ({ children }) => { -// return {children}; +// return {children}; // }; -// const StylePopUp = styled.div` +// const StyledPopUp = styled.div` // position: fixed; // width: 100vw; // height: 100vh; diff --git a/fe/src/index.css b/fe/src/index.css index 740956d38..e2f8999a1 100644 --- a/fe/src/index.css +++ b/fe/src/index.css @@ -11,8 +11,3 @@ body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} From 903cece47b7b3f08dcddacc808f21a84f0937dc6 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Mon, 10 May 2021 18:04:15 +0900 Subject: [PATCH 02/22] =?UTF-8?q?[#31]feat::sparkles:=20pitch=20=ED=81=B4?= =?UTF-8?q?=EB=A6=AD=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/board/Board.jsx | 90 ++++++++++++++++---- fe/src/components/game-play/board/Screen.jsx | 63 ++++++++++---- 2 files changed, 120 insertions(+), 33 deletions(-) diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 1b1672f6e..bd24a2f1b 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -1,17 +1,82 @@ import styled from 'styled-components'; +import { useReducer, useEffect } from 'react'; import BallCount from './BallCount'; import Inning from './Inning'; import Screen from './Screen'; -const Board = (props) => ( - - - - - -); +const ballCountReducer = (state, action) => { + let newState = { ...state }; + switch (action.type) { + case 'strike': + newState.strike++; + break; + case 'ball': + newState.ball++; + break; + case 'safety': + newState = { strike: 0, ball: 0, out: newState.out }; + break; + case 'clear': + newState = { strike: 0, ball: 0, out: 0 }; + break; + case 'out': + newState.strike = 0; + newState.out++; + break; + default: + throw Error('잘못된 ball-count reducer'); + } + return newState; +}; + +const Board = (props) => { + const [ballCount, ballCountDispatch] = useReducer(ballCountReducer, { + strike: 0, + ball: 0, + out: 0, + }); + const handleStrike = () => { + if (ballCount.strike === 2) { + handleOut(); + //필요한 것들 + } else { + ballCountDispatch({ type: 'strike' }); + } + }; + const handleBall = () => { + if (ballCount.ball === 3) { + ballCountDispatch({ type: 'safety' }); + } else { + ballCountDispatch({ type: 'ball' }); + } + }; + const handleOut = () => { + if (ballCount.out === 2) { + ballCountDispatch({ type: 'clear' }); + // 공수교대 + // if(turn) + // setTurn(false); + // else + // setRound(round + 1); + // setTurn(true); + } else { + ballCountDispatch({ type: 'out' }); + } + }; + const handleSafety = () => { + ballCountDispatch({ type: 'safety' }); + }; + + return ( + + + + + + ); +}; -const StyleddBoard = styled.div` +const StyledBoard = styled.div` display: grid; grid-template-columns: 10rem 1fr 10rem; `; @@ -22,12 +87,5 @@ const isHome = true; const inning = { turn: true, - round: 4 -} - -const ballCount = { - strike: 2, - ball: 3, - out: 2 + round: 4, }; - diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index 57159b303..8834f8b52 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -1,24 +1,53 @@ -import React from 'react'; +import React, { useState } from 'react'; import styled from 'styled-components'; +const Screen = ({ handleStrike, handleBall, handleSafety }) => { + const [baseData, setBaseData] = useState({ + 1: false, + 2: false, + 3: false, + }); + + const handlePitchClick = () => { + const randomNum = Math.ceil(Math.random() * 100); + if (randomNum <= 50) { + //스트라이크 + handleStrike(); + // ballCountDispatch({ type: 'strike' }); + } else if (randomNum <= 80) { + //볼 + handleBall(); + } else { + handleSafety(); + //안타 + //멤버변경 + if (randomNum <= 90) { + //1루타 + } else if (randomNum <= 96) { + //2루타 + } else if (randomNum <= 99) { + //3루타 + } else { + //홈런 + } + } + }; -const Screen = (props) => { return ( - PITCH + PITCH -
    -
    -
    -
    -
    +
    +
    +
    +
    ); -} +}; const StyledScreen = styled.div` - position:relative; + position: relative; align-self: center; `; const StyledPitch = styled.button` @@ -39,9 +68,9 @@ const StyledPitch = styled.button` z-index: 1; &:hover { background-color: #fff; - color:#000; + color: #000; } -` +`; const StyledGround = styled.div` border: 3px solid #fff; @@ -59,7 +88,7 @@ const StyledGround = styled.div` bottom: -1rem; left: -1rem; &:before { - content: ""; + content: ''; background-color: #fff; width: 2.8284712rem; height: 4rem; @@ -78,10 +107,10 @@ const StyledGround = styled.div` right: -1rem; } &:nth-child(4) { - top:-1rem;; - left:-1rem; + top: -1rem; + left: -1rem; } } -` +`; -export default Screen; \ No newline at end of file +export default Screen; From ace4b9fe7b0c493a4edc8841738c0da19e39548a Mon Sep 17 00:00:00 2001 From: kowoohyuk Date: Tue, 11 May 2021 16:11:55 +0900 Subject: [PATCH 03/22] =?UTF-8?q?[#33]=20feat:=20:sparkles:=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B4=EB=93=9C=20=EB=B0=8F=20=ED=84=B4=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?,=20=EB=A9=A4=EB=B2=84=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9D=BC=EB=B6=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/GamePlay.jsx | 42 +++--- .../components/game-play/board/BallCount.jsx | 2 +- fe/src/components/game-play/board/Board.jsx | 26 ++-- .../game-play/popup/roster/Roster.jsx | 129 +----------------- .../game-play/popup/roster/RosterPlayer.jsx | 2 +- .../game-play/popup/roster/TeamRoster.jsx | 6 +- fe/src/util/api.js | 15 ++ 7 files changed, 60 insertions(+), 162 deletions(-) create mode 100644 fe/src/util/api.js diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index 473632857..d79b2122d 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -7,6 +7,7 @@ import Log from './log/Log'; import PopUpScore from './popup/score/Score'; import PopUpRoster from './popup/roster/Roster'; import PopUp from '../ui/PopUp'; +import { fetchPUT } from '../../util/api.js'; const ScoreContext = createContext(); const MemberListContext = createContext(); @@ -14,46 +15,49 @@ const LogContext = createContext(); const memberListReducer = (state, action) => { let next = 0; - const newState = state.map((member, idx) => { + const team = action.turn ? 'home' : 'away'; + const newTeam = state[team].map((member, idx, arr) => { let { safety, at_bat, out, state } = member; - if(action.type === 'out') out++ - else safety++ - at_bat++ - if(action.id === member.id) { - next = idx + 1 === member.length ? 0 : idx + 1; + if(member.state) { + if(action.type === 'out') out++ + else safety++ + at_bat++ + next = idx + 1 === arr.length ? 0 : idx + 1; return {...member, safety, at_bat, out, state: !state}; + } else { + return member; } }); - newState[next].state = true; - return newState; + newTeam[next].state = true; + return { ...state, [team]: newTeam }; } const GamePlay = ({ home, away, game_id }) => { const [turn, round, member_list] = [null, null, null]; const [inning, setInning] = useState({ - turn, - round + turn: true, + round: 1 }); // const [score, setScore] = useState(null); - // const [memberList, memberListDispatch] = useReducer(memberListReducer, member_list); //member_list fetch해서 받아올아이 + const [memberList, memberListDispatch] = useReducer(memberListReducer, { home: data.home.member_list, away: data.away.member_list }); //member_list fetch해서 받아올아이 /* data, */ const score = { home: data.home.score, away: data.away.score }; - const memberList = { home: data.home.member_list, away: data.home.member_list }; - const pitchers = { home: data.home.pitcher, away: data.home.pitcher }; + // const memberList = ; + const pitchers = { home: data.home.pitcher, away: data.away.pitcher }; return ( - + {/* {/* */} - + {/* */} - - + + @@ -106,7 +110,7 @@ const teamName = { }; const data = { - round: 4, // 게임 시작시는 round,turn X + round: 1, // 게임 시작시는 round,turn X turn: true, //(false : 말) home: { member_list: [ @@ -191,7 +195,7 @@ const data = { state: false, }, ], - pitcher: 3, + pitcher: 5, score: 0, // 재접속 시에도 유지할 수 있도록 팀 별 점수를 받을 수 있어야 합니다! }, away: { diff --git a/fe/src/components/game-play/board/BallCount.jsx b/fe/src/components/game-play/board/BallCount.jsx index ac9ca9b8c..2c31fce8f 100644 --- a/fe/src/components/game-play/board/BallCount.jsx +++ b/fe/src/components/game-play/board/BallCount.jsx @@ -23,7 +23,7 @@ const BallCount = ({ ballCount: { strike, ball, out } }) => { function createBallCountTag(count) { const result = []; for(let i = 0; i < count; i++) { - result.push(
    ); + result.push(
    ); } return result; } diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index bd24a2f1b..8e8d32b49 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -1,8 +1,9 @@ import styled from 'styled-components'; -import { useReducer, useEffect } from 'react'; +import { useReducer, useEffect, useState } from 'react'; import BallCount from './BallCount'; import Inning from './Inning'; import Screen from './Screen'; +import { fetchPUT } from '../../../util/api.js'; const ballCountReducer = (state, action) => { let newState = { ...state }; @@ -29,7 +30,7 @@ const ballCountReducer = (state, action) => { return newState; }; -const Board = (props) => { +const Board = ({ memberListDispatch, inning, setInning }) => { const [ballCount, ballCountDispatch] = useReducer(ballCountReducer, { strike: 0, ball: 0, @@ -53,20 +54,24 @@ const Board = (props) => { const handleOut = () => { if (ballCount.out === 2) { ballCountDispatch({ type: 'clear' }); - // 공수교대 - // if(turn) - // setTurn(false); - // else - // setRound(round + 1); - // setTurn(true); + if(inning.turn) setInning({...inning, turn: !inning.turn}); + else setInning({...inning, round: inning.round + 1, turn: !inning.turn}); } else { ballCountDispatch({ type: 'out' }); } + // 멤버 아웃 1, 타석 1 증가 + memberListDispatch({ type: 'out', turn: inning.turn }); }; const handleSafety = () => { ballCountDispatch({ type: 'safety' }); + memberListDispatch({ type: 'safety', turn: inning.turn }); + // 멤버 안타 1, 타석 1 증가 }; + useEffect(() => { + return () => fetchPUT(inning); + }, [inning]); + return ( @@ -84,8 +89,3 @@ const StyledBoard = styled.div` export default Board; const isHome = true; - -const inning = { - turn: true, - round: 4, -}; diff --git a/fe/src/components/game-play/popup/roster/Roster.jsx b/fe/src/components/game-play/popup/roster/Roster.jsx index f7c47e72a..5ab0e0433 100644 --- a/fe/src/components/game-play/popup/roster/Roster.jsx +++ b/fe/src/components/game-play/popup/roster/Roster.jsx @@ -1,11 +1,11 @@ import styled from 'styled-components'; import TeamRoster from './TeamRoster'; -const Roster = () => { +const Roster = ({ memberList }) => { // team_name 필요 return ( - - + + ); } @@ -27,127 +27,4 @@ const StyledRoster = styled.div` } `; -const game_roster = { - // 평균은 fe에서 - 'home': { - 'member_list' : [ - { - 'name': '김광진', - 'at_bat': 7, // 타석 - 'safety': 3, // 안타 - 'out': 4, // 아웃 - }, - { - 'name': '추신수', - 'at_bat': 7, // 타석 - 'safety': 5, // 안타 - 'out': 2, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 11, // 타석 - 'safety': 4, // 안타 - 'out': 7, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 10, // 타석 - 'safety': 2, // 안타 - 'out': 8, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 3, // 타석 - 'safety': 2, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 4, // 타석 - 'safety': 1, // 안타 - 'out': 3, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 6, // 타석 - 'safety': 2, // 안타 - 'out': 4, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 5, // 타석 - 'safety': 4, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 7, // 타석 - 'safety': 7, // 안타 - 'out': 0, // 아웃 - }, - ], - 'player_name' : '추신수' - }, - 'away':{ - 'member_list' : [ - { - 'name': '김광진', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '이대호', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - { - 'name': '김광진', - 'at_bat': 2, // 타석 - 'safety': 1, // 안타 - 'out': 1, // 아웃 - }, - ], - 'player_name' : '이대호' - } -} - - export default Roster; diff --git a/fe/src/components/game-play/popup/roster/RosterPlayer.jsx b/fe/src/components/game-play/popup/roster/RosterPlayer.jsx index 532ba7f85..6e37095aa 100644 --- a/fe/src/components/game-play/popup/roster/RosterPlayer.jsx +++ b/fe/src/components/game-play/popup/roster/RosterPlayer.jsx @@ -1,7 +1,7 @@ import React from 'react'; const RosterPlayer = ({ name, at_bat, safety, out, player_name }) => { - const getAverage = (at_bat, safety) => (safety / at_bat).toFixed(3); + const getAverage = (at_bat, safety) => (safety / at_bat) ? (safety / at_bat).toFixed(3) : 0; const class_name = 'roster--member' + (name === player_name ? ' active' : ''); return (
  • diff --git a/fe/src/components/game-play/popup/roster/TeamRoster.jsx b/fe/src/components/game-play/popup/roster/TeamRoster.jsx index b5dc3f419..316e6fe15 100644 --- a/fe/src/components/game-play/popup/roster/TeamRoster.jsx +++ b/fe/src/components/game-play/popup/roster/TeamRoster.jsx @@ -1,13 +1,15 @@ import styled from 'styled-components'; import RosterPlayer from './RosterPlayer'; -const TeamRoster = ({ member_list, player_name, team_name = '베리베리 스트로베리', player = false }) => { +const TeamRoster = ({ memberList, player = false }) => { + const player_name = 'abc'; + const team_name = '베리베리 스트로베리'; const HEADS = ['타자', '타석', '안타', '아웃', '평균']; const TOTALTEXT = 'Totals'; const heads = HEADS.map((head, idx) =>
    {head}
    ); let [totalAtBat, totalSafety, totalOut] = [0, 0, 0]; - const members = member_list.map((member, idx) => { + const members = memberList.map((member, idx) => { const { at_bat, safety, out } = member; totalAtBat += at_bat; totalSafety += safety; diff --git a/fe/src/util/api.js b/fe/src/util/api.js new file mode 100644 index 000000000..360c5adee --- /dev/null +++ b/fe/src/util/api.js @@ -0,0 +1,15 @@ +const fetchPUT = async (data) => { + // 현재 미사용 + console.log(data); + if (true) return; + const result = await fetch('/path', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + console.log(result); +}; + +export { fetchPUT }; From 4b7cd9f5ea6d919256d1397b46a145508f238c4a Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Tue, 11 May 2021 16:16:18 +0900 Subject: [PATCH 04/22] =?UTF-8?q?[#35]feat::sparkles:=20=EC=A0=90=EC=88=98?= =?UTF-8?q?,=EB=B2=A0=EC=9D=B4=EC=8A=A4=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/GamePlay.jsx | 41 +++++++++------- fe/src/components/game-play/board/Board.jsx | 14 +++--- fe/src/components/game-play/board/Screen.jsx | 5 +- fe/src/components/game-play/score/Score.jsx | 13 +++-- fe/src/hooks/useScoreNBase.js | 51 ++++++++++++++++++++ 5 files changed, 94 insertions(+), 30 deletions(-) create mode 100644 fe/src/hooks/useScoreNBase.js diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index 473632857..001f9cd38 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -7,8 +7,9 @@ import Log from './log/Log'; import PopUpScore from './popup/score/Score'; import PopUpRoster from './popup/roster/Roster'; import PopUp from '../ui/PopUp'; +import useScoreNBase from '../../hooks/useScoreNBase'; -const ScoreContext = createContext(); +export const ScoreNBaseContext = createContext(); const MemberListContext = createContext(); const LogContext = createContext(); @@ -16,45 +17,49 @@ const memberListReducer = (state, action) => { let next = 0; const newState = state.map((member, idx) => { let { safety, at_bat, out, state } = member; - if(action.type === 'out') out++ - else safety++ - at_bat++ - if(action.id === member.id) { + if (action.type === 'out') out++; + else safety++; + at_bat++; + if (action.id === member.id) { next = idx + 1 === member.length ? 0 : idx + 1; - return {...member, safety, at_bat, out, state: !state}; + return { ...member, safety, at_bat, out, state: !state }; } }); newState[next].state = true; return newState; -} +}; const GamePlay = ({ home, away, game_id }) => { - const [turn, round, member_list] = [null, null, null]; const [inning, setInning] = useState({ turn, - round + round, }); + const { score, base, safetyDispatch } = useScoreNBase({ score: undefined, base: undefined }); // const [score, setScore] = useState(null); // const [memberList, memberListDispatch] = useReducer(memberListReducer, member_list); //member_list fetch해서 받아올아이 /* data, */ - const score = { home: data.home.score, away: data.away.score }; const memberList = { home: data.home.member_list, away: data.home.member_list }; const pitchers = { home: data.home.pitcher, away: data.home.pitcher }; + console.log(pitchers); return ( - - + + + + + + - {/* {/* */} - - {/* */} - - - + + + + + + ); diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index bd24a2f1b..5c1e2f629 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -1,8 +1,9 @@ import styled from 'styled-components'; -import { useReducer, useEffect } from 'react'; +import { useReducer, useContext, useEffect } from 'react'; import BallCount from './BallCount'; import Inning from './Inning'; import Screen from './Screen'; +import { ScoreNBaseContext } from '../GamePlay'; const ballCountReducer = (state, action) => { let newState = { ...state }; @@ -35,6 +36,7 @@ const Board = (props) => { ball: 0, out: 0, }); + const { safetyDispatch } = useContext(ScoreNBaseContext); const handleStrike = () => { if (ballCount.strike === 2) { handleOut(); @@ -53,18 +55,14 @@ const Board = (props) => { const handleOut = () => { if (ballCount.out === 2) { ballCountDispatch({ type: 'clear' }); - // 공수교대 - // if(turn) - // setTurn(false); - // else - // setRound(round + 1); - // setTurn(true); + safetyDispatch({ type: 'clear', turn: true }); } else { ballCountDispatch({ type: 'out' }); } }; - const handleSafety = () => { + const handleSafety = (power) => { ballCountDispatch({ type: 'safety' }); + safetyDispatch({ turn: true, power }); }; return ( diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index 8834f8b52..bd9d1aa30 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -18,17 +18,20 @@ const Screen = ({ handleStrike, handleBall, handleSafety }) => { //볼 handleBall(); } else { - handleSafety(); //안타 //멤버변경 if (randomNum <= 90) { //1루타 + handleSafety(1); } else if (randomNum <= 96) { //2루타 + handleSafety(2); } else if (randomNum <= 99) { //3루타 + handleSafety(3); } else { //홈런 + handleSafety(4); } } }; diff --git a/fe/src/components/game-play/score/Score.jsx b/fe/src/components/game-play/score/Score.jsx index 453f200e6..0fa7267f5 100644 --- a/fe/src/components/game-play/score/Score.jsx +++ b/fe/src/components/game-play/score/Score.jsx @@ -1,8 +1,15 @@ +import { useContext } from 'react'; import styled from 'styled-components'; +import { ScoreNBaseContext } from '../GamePlay'; -const Score = ({ teamName, score, turn }) => { +const Score = ({ teamName, turn }) => { + const { score } = useContext(ScoreNBaseContext); const TITLE = 'BASEBALL GAME ONLINE'; const TURN = 'Player'; + + const homeScore = score.home.reduce((acc, cur) => acc + cur, 0); + const awayScore = score.away.reduce((acc, cur) => acc + cur, 0); + return (
    {TITLE}
    @@ -13,11 +20,11 @@ const Score = ({ teamName, score, turn }) => { {turn &&
    {TURN}
    }
  • -
    {score.home}
    +
    {homeScore}
    vs
    -
    {score.away}
    +
    {awayScore}
    {teamName.away} {!turn &&
    {TURN}
    } diff --git a/fe/src/hooks/useScoreNBase.js b/fe/src/hooks/useScoreNBase.js new file mode 100644 index 000000000..db4373488 --- /dev/null +++ b/fe/src/hooks/useScoreNBase.js @@ -0,0 +1,51 @@ +import { useState } from 'react'; + +/* +한루 한루 주자가 뛰는 것을 애니메이션 넣어주기 위해서 한번에 계산하기 보다는 +for문으로 한번씩 나눠서 실행 +*/ + +const useScoreNBase = ({ + score: initialScore = { home: [0], away: [] }, + base: initialBase = { 1: false, 2: false, 3: false }, +}) => { + const [score, setScore] = useState(initialScore); + const [base, setBase] = useState(initialBase); + + const getNewScore = (team) => { + if (!base[3]) return score; + const newScore = { ...score }; + newScore[team][newScore[team].length - 1]++; + return newScore; + }; + const getNewBase = (index) => { + const newBase = { ...base }; + const baseStatus = Object.values(base); + const newBaseStatus = + index === 0 ? [true, ...baseStatus.slice(0, -1)] : [false, ...baseStatus.slice(0, -1)]; + newBaseStatus.forEach((status, idx) => (newBase[idx + 1] = status)); + return newBase; + }; + const safetyDispatch = ({ type, turn, power }) => { + console.log(score, base); + const team = turn ? 'home' : 'away'; + if (type === 'clear') { + const newScore = { ...score }; + newScore[team].push(0); + setScore(newScore); + setBase({ 1: false, 2: false, 3: false }); + return; + } + for (let i = 0; i < power; i++) { + //트렌지션 함수 자리 + const newScore = getNewScore(team); + const newBase = getNewBase(i); + setBase(newBase); + setScore(newScore); + } + }; + + return { score, base, safetyDispatch }; +}; + +export default useScoreNBase; From 36497c97b55d94eeb8e34fd42ff5d3325e8360a8 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Tue, 11 May 2021 16:31:53 +0900 Subject: [PATCH 05/22] =?UTF-8?q?fix::bug:=20player=20batter,=20pitcher=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/board/Board.jsx | 4 ++-- fe/src/components/game-play/player/Player.jsx | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 566e50604..217bff4f1 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -56,9 +56,9 @@ const Board = ({ memberListDispatch, inning, setInning }) => { const handleOut = () => { if (ballCount.out === 2) { ballCountDispatch({ type: 'clear' }); - safetyDispatch({ type: 'clear', turn: true }); if (inning.turn) setInning({ ...inning, turn: !inning.turn }); else setInning({ ...inning, round: inning.round + 1, turn: !inning.turn }); + safetyDispatch({ type: 'clear', turn: inning.turn }); } else { ballCountDispatch({ type: 'out' }); } @@ -69,7 +69,7 @@ const Board = ({ memberListDispatch, inning, setInning }) => { ballCountDispatch({ type: 'safety' }); // 멤버 안타 1, 타석 1 증가 memberListDispatch({ type: 'safety', turn: inning.turn }); - safetyDispatch({ turn: true, power }); + safetyDispatch({ turn: inning.turn, power }); }; useEffect(() => { diff --git a/fe/src/components/game-play/player/Player.jsx b/fe/src/components/game-play/player/Player.jsx index ca4a517a2..7ed22a34e 100644 --- a/fe/src/components/game-play/player/Player.jsx +++ b/fe/src/components/game-play/player/Player.jsx @@ -3,19 +3,20 @@ import styled from 'styled-components'; const Player = ({ memberList, turn, pitchers }) => { const HOME = 'home'; const AWAY = 'away'; - - const getPlayer = (members, id) => { + const getPlayer = () => { const result = {}; - for (const member of members) { - if (member.id === id) result.pitcher = member; + const batterTeam = turn ? HOME : AWAY; + const pitcherTeam = turn ? AWAY : HOME; + for (const member of memberList[batterTeam]) { if (member.state) result.batter = member; } + for (const member of memberList[pitcherTeam]) { + if (member.id === pitchers[pitcherTeam]) result.pitcher = member; + } return result; }; - const { pitcher, batter } = turn - ? getPlayer(memberList[HOME], pitchers[HOME]) - : getPlayer(memberList[AWAY], pitchers[AWAY]); + const { pitcher, batter } = getPlayer(); return ( From 78fb475470e4d58736d7a29530613ef43958c3b6 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Wed, 12 May 2021 16:48:50 +0900 Subject: [PATCH 06/22] =?UTF-8?q?[#40]feat::sparkles:=20=EC=A3=BC=EC=9E=90?= =?UTF-8?q?=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/GamePlay.jsx | 4 +- fe/src/components/game-play/board/Board.jsx | 5 +- fe/src/components/game-play/board/Screen.jsx | 123 +++++++++++++++---- fe/src/components/game-play/score/Score.jsx | 1 - fe/src/hooks/useScoreNBase.js | 44 +++---- 5 files changed, 125 insertions(+), 52 deletions(-) diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index 0414ff922..c15db9740 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -48,12 +48,12 @@ const GamePlay = ({ home, away, game_id }) => { const pitchers = { home: data.home.pitcher, away: data.away.pitcher }; return ( - + {/* - + */} diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 217bff4f1..7f7c5e367 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -65,11 +65,10 @@ const Board = ({ memberListDispatch, inning, setInning }) => { // 멤버 아웃 1, 타석 1 증가 memberListDispatch({ type: 'out', turn: inning.turn }); }; - const handleSafety = (power) => { + const handleSafety = () => { ballCountDispatch({ type: 'safety' }); // 멤버 안타 1, 타석 1 증가 memberListDispatch({ type: 'safety', turn: inning.turn }); - safetyDispatch({ turn: inning.turn, power }); }; useEffect(() => { @@ -79,7 +78,7 @@ const Board = ({ memberListDispatch, inning, setInning }) => { return ( - + ); diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index bd9d1aa30..b4d741932 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -1,49 +1,88 @@ -import React, { useState } from 'react'; +import React, { useState, useContext, useEffect } from 'react'; import styled from 'styled-components'; +import useScoreNBase from '../../../hooks/useScoreNBase'; +import { ScoreNBaseContext } from '../GamePlay'; -const Screen = ({ handleStrike, handleBall, handleSafety }) => { - const [baseData, setBaseData] = useState({ - 1: false, - 2: false, - 3: false, - }); +const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { + const { base, safetyDispatch } = useContext(ScoreNBaseContext); + const [isTransition, setIsTransition] = useState(false); + const [runFirstBase, setRunFirstBase] = useState(false); + const [currentPower, setCurrentPower] = useState(0); + + const playerRunType = [ + 'translateX(19.6rem)', + 'translateY(-19.6rem)', + 'translateX(-19.6rem)', + 'translateY(19.6rem)', + ]; + + const handleTransitionEnd = async () => { + if (currentPower === 0) return; + setRunFirstBase(false); + setCurrentPower(currentPower - 1); + safetyDispatch({ type: 'onBase', turn, runFirstBase }); + setIsTransition(false); + }; const handlePitchClick = () => { const randomNum = Math.ceil(Math.random() * 100); - if (randomNum <= 50) { + if (randomNum <= 60) { //스트라이크 handleStrike(); - // ballCountDispatch({ type: 'strike' }); - } else if (randomNum <= 80) { + } else if (randomNum <= 20) { //볼 handleBall(); } else { //안타 - //멤버변경 - if (randomNum <= 90) { + handleSafety(); + setRunFirstBase(true); + setIsTransition(true); + if (randomNum <= 10) { //1루타 - handleSafety(1); - } else if (randomNum <= 96) { + setCurrentPower(1); + } else if (randomNum <= 6) { //2루타 - handleSafety(2); - } else if (randomNum <= 99) { + setCurrentPower(2); + } else if (randomNum <= 3) { //3루타 - handleSafety(3); + setCurrentPower(3); } else { //홈런 - handleSafety(4); + setCurrentPower(4); } } }; + const baseList = Object.entries(base).map(([baseNum, status]) => { + if (status) + return ( +
    +
    +
    + ); + else + return ( +
    +
    +
    + ); + }); + return ( PITCH - -
    -
    -
    -
    + +
    +
    +
    + {baseList}
    ); @@ -76,20 +115,38 @@ const StyledPitch = styled.button` `; const StyledGround = styled.div` + position: relative; border: 3px solid #fff; width: 20rem; height: 20rem; margin: auto; - position: relative; transform: rotate(-45deg); + .runner { + width: 1.5rem; + height: 1.5rem; + background-color: red; + transition: ${({ isTransition }) => (isTransition ? 'all 0.5s' : '')}; + } + + .home { + z-index: 4; + } .base { position: absolute; + display: flex; + align-items: center; + justify-content: center; background-color: #fff; width: 2rem; height: 2rem; &:nth-child(1) { bottom: -1rem; left: -1rem; + .runner { + background-color: ${({ runFirstBase }) => (runFirstBase ? 'red' : 'rgba(0,0,0,0)')}; + transform: ${({ playerRunType, currentPower, runFirstBase }) => + runFirstBase && currentPower > 0 ? `${playerRunType[0]} rotate(45deg)` : `rotate(45deg)`}; + } &:before { content: ''; background-color: #fff; @@ -102,16 +159,34 @@ const StyledGround = styled.div` } } &:nth-child(2) { + z-index: 3; bottom: -1rem; right: -1rem; + .runner { + background-color: ${({ base }) => (base[1] ? 'red' : 'rgba(0,0,0,0)')}; + transform: ${({ playerRunType, currentPower }) => + currentPower > 0 ? `${playerRunType[1]} rotate(45deg)` : `rotate(45deg)`}; + } } &:nth-child(3) { + z-index: 2; top: -1rem; right: -1rem; + .runner { + background-color: ${({ base }) => (base[2] ? 'red' : 'rgba(0,0,0,0)')}; + transform: ${({ playerRunType, currentPower }) => + currentPower > 0 ? `${playerRunType[2]} rotate(45deg)` : `rotate(45deg)`}; + } } &:nth-child(4) { + z-index: 1; top: -1rem; left: -1rem; + .runner { + background-color: ${({ base }) => (base[3] ? 'red' : 'rgba(0,0,0,0)')}; + transform: ${({ playerRunType, currentPower }) => + currentPower > 0 ? `${playerRunType[3]} rotate(45deg)` : `rotate(45deg)`}; + } } } `; diff --git a/fe/src/components/game-play/score/Score.jsx b/fe/src/components/game-play/score/Score.jsx index 0fa7267f5..134a57770 100644 --- a/fe/src/components/game-play/score/Score.jsx +++ b/fe/src/components/game-play/score/Score.jsx @@ -6,7 +6,6 @@ const Score = ({ teamName, turn }) => { const { score } = useContext(ScoreNBaseContext); const TITLE = 'BASEBALL GAME ONLINE'; const TURN = 'Player'; - const homeScore = score.home.reduce((acc, cur) => acc + cur, 0); const awayScore = score.away.reduce((acc, cur) => acc + cur, 0); diff --git a/fe/src/hooks/useScoreNBase.js b/fe/src/hooks/useScoreNBase.js index db4373488..ab82a98e5 100644 --- a/fe/src/hooks/useScoreNBase.js +++ b/fe/src/hooks/useScoreNBase.js @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; /* 한루 한루 주자가 뛰는 것을 애니메이션 넣어주기 위해서 한번에 계산하기 보다는 @@ -12,36 +12,36 @@ const useScoreNBase = ({ const [score, setScore] = useState(initialScore); const [base, setBase] = useState(initialBase); - const getNewScore = (team) => { + const getNewScore = (score, team) => { if (!base[3]) return score; const newScore = { ...score }; - newScore[team][newScore[team].length - 1]++; + newScore[team][newScore[team].length - 1] += 1; return newScore; }; - const getNewBase = (index) => { + const getNewBase = (base, runFirstBase) => { const newBase = { ...base }; - const baseStatus = Object.values(base); - const newBaseStatus = - index === 0 ? [true, ...baseStatus.slice(0, -1)] : [false, ...baseStatus.slice(0, -1)]; + const baseStatus = Object.values(newBase); + const newBaseStatus = runFirstBase + ? [true, ...baseStatus.slice(0, -1)] + : [false, ...baseStatus.slice(0, -1)]; newBaseStatus.forEach((status, idx) => (newBase[idx + 1] = status)); return newBase; }; - const safetyDispatch = ({ type, turn, power }) => { - console.log(score, base); + const safetyDispatch = ({ type, turn, runFirstBase }) => { const team = turn ? 'home' : 'away'; - if (type === 'clear') { - const newScore = { ...score }; - newScore[team].push(0); - setScore(newScore); - setBase({ 1: false, 2: false, 3: false }); - return; - } - for (let i = 0; i < power; i++) { - //트렌지션 함수 자리 - const newScore = getNewScore(team); - const newBase = getNewBase(i); - setBase(newBase); - setScore(newScore); + switch (type) { + case 'clear': + const newScore = { ...score }; + newScore[team].push(0); + setScore(newScore); + setBase({ 1: false, 2: false, 3: false }); + return; + case 'onBase': + setBase(getNewBase(base, runFirstBase)); + setScore(getNewScore(score, team)); + return; + default: + throw Error('잘못된 safetyDispatch 타입입니다.'); } }; From a4e56cddfa94a002301aa0354951c63a0b9e35c6 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Wed, 12 May 2021 21:25:53 +0900 Subject: [PATCH 07/22] =?UTF-8?q?Wip.=20fetching=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/App.js | 15 ++++++-- fe/src/components/game-list/GameList.jsx | 10 +++-- fe/src/components/game-list/GameListItem.jsx | 13 +++++-- fe/src/components/game-play/GamePlay.jsx | 38 ++++++++++++------- fe/src/components/game-play/player/Player.jsx | 7 ++-- fe/src/hooks/useFetch.js | 27 +++++++++++++ 6 files changed, 84 insertions(+), 26 deletions(-) create mode 100644 fe/src/hooks/useFetch.js diff --git a/fe/src/App.js b/fe/src/App.js index bf5532a11..531501609 100644 --- a/fe/src/App.js +++ b/fe/src/App.js @@ -2,14 +2,19 @@ import styled from 'styled-components'; import GameList from './components/game-list/GameList'; import GamePlay from './components/game-play/GamePlay'; import background from './images/background.png'; +import { BrowserRouter as Router, Route, Link } from 'react-router-dom'; function App() { return ( - <> + - {/* */} - - + + + + + + + ); } @@ -34,3 +39,5 @@ const StyledBackground = styled.div` `; export default App; + +const DATA_LIST_URL = 'http://52.78.184.142/games'; diff --git a/fe/src/components/game-list/GameList.jsx b/fe/src/components/game-list/GameList.jsx index 5590a446f..8070ee1e9 100644 --- a/fe/src/components/game-list/GameList.jsx +++ b/fe/src/components/game-list/GameList.jsx @@ -1,12 +1,16 @@ import React from 'react'; import styled from 'styled-components'; +import useFetch from '../../hooks/useFetch'; import GameListItem from './GameListItem'; -const GameList = (props) => { +const DATA_LIST_URL = 'http://52.78.184.142/games'; + +const GameList = () => { + const { data: gameListData } = useFetch(DATA_LIST_URL, 'get'); const TITLE = 'BASEBALL GAME ONLINE'; const DESCRIPTION = '참가할 게임을 선택하세요!'; - const gameList = game_list.map(({ home, away, game_id }, idx) => ( - + const gameList = gameListData?.game_list.map(({ home, away, id }, idx) => ( + )); return ( diff --git a/fe/src/components/game-list/GameListItem.jsx b/fe/src/components/game-list/GameListItem.jsx index dacaec5d1..7ca304fcf 100644 --- a/fe/src/components/game-list/GameListItem.jsx +++ b/fe/src/components/game-list/GameListItem.jsx @@ -1,13 +1,20 @@ import React from 'react'; import styled from 'styled-components'; -const GameListItem = ({ home, away, game_id, idx }) => { +import { Link } from 'react-router-dom'; + +const GameListItem = ({ home, away, id, idx }) => { + const path = `games/${id}`; return (
    GAME {idx + 1}
    -
    {home}
    + +
    {home}
    +
    vs
    -
    {away}
    + +
    {away}
    +
    ); diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index c15db9740..f7de1e907 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -9,6 +9,7 @@ import PopUpRoster from './popup/roster/Roster'; import PopUp from '../ui/PopUp'; import useScoreNBase from '../../hooks/useScoreNBase'; import { fetchPUT } from '../../util/api.js'; +import useFetch from '../../hooks/useFetch'; export const ScoreNBaseContext = createContext(); const MemberListContext = createContext(); @@ -34,7 +35,10 @@ const memberListReducer = (state, action) => { }; const GamePlay = ({ home, away, game_id }) => { - const [turn, round, member_list] = [null, null, null]; + const path = window.location.pathname; + const gameID = +path.slice(7); + const GAME_PLAY_URL = `http://52.78.184.142${path}`; + const { data: gamePlayData } = useFetch(GAME_PLAY_URL, 'get'); const [inning, setInning] = useState({ turn: true, round: 1, @@ -44,25 +48,33 @@ const GamePlay = ({ home, away, game_id }) => { home: data.home.member_list, away: data.away.member_list, }); //member_list fetch해서 받아올아이 + debugger; + const homePitch = gamePlayData !== null ? gamePlayData.home.pitcherID : '모디'; + console.log('홈투수', homePitch); + const pitchers = { + home: data?.home.pitcher, + away: data?.away.pitcher, + }; - const pitchers = { home: data.home.pitcher, away: data.away.pitcher }; return ( - - {/* + { gamePlayData } && ( + + {/* */} - - - - - - - - - + + + + + + + + + + ) ); }; diff --git a/fe/src/components/game-play/player/Player.jsx b/fe/src/components/game-play/player/Player.jsx index 7ed22a34e..e6195abaf 100644 --- a/fe/src/components/game-play/player/Player.jsx +++ b/fe/src/components/game-play/player/Player.jsx @@ -3,6 +3,7 @@ import styled from 'styled-components'; const Player = ({ memberList, turn, pitchers }) => { const HOME = 'home'; const AWAY = 'away'; + console.log('pitchers', pitchers); const getPlayer = () => { const result = {}; const batterTeam = turn ? HOME : AWAY; @@ -23,14 +24,14 @@ const Player = ({ memberList, turn, pitchers }) => {
    투수
    -
    {pitcher.name}
    -
    #{pitcher.id}
    +
    {pitcher?.name}
    +
    #{pitcher?.id}
    타자
    -
    {batter.name}
    +
    {batter?.name}
    {batter.at_bat}타석 {batter.safety}안타
    diff --git a/fe/src/hooks/useFetch.js b/fe/src/hooks/useFetch.js new file mode 100644 index 000000000..3eacd124e --- /dev/null +++ b/fe/src/hooks/useFetch.js @@ -0,0 +1,27 @@ +import { useEffect, useState } from 'react'; + +const useFetch = (url, method) => { + const [data, setData] = useState(null); + + const fetchData = async (url, method) => { + try { + if (method === 'get') { + const res = await fetch(url); + const data = await res.json(); + setData(data); + } + } catch (err) { + console.log(err); + } + }; + + useEffect(() => { + if (method === 'get') { + fetchData(url, method); + } + }, []); + + return { data }; +}; + +export default useFetch; From a264287e2ab6169067d01d6dfcc8c1cd20fbd8c8 Mon Sep 17 00:00:00 2001 From: kowoohyuk Date: Thu, 13 May 2021 00:30:09 +0900 Subject: [PATCH 08/22] [#34, #38] feat: :sparkles: Pitch, Log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pitch에 따른 상세점수 관리 - Log 상태관리 구현 --- fe/src/components/game-play/GamePlay.jsx | 44 ++++++++++++++--- fe/src/components/game-play/board/Board.jsx | 10 +++- fe/src/components/game-play/log/Log.jsx | 54 +++++++++++---------- fe/src/components/ui/PopUp.jsx | 19 ++++++-- fe/src/hooks/useScoreNBase.js | 1 - 5 files changed, 88 insertions(+), 40 deletions(-) diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index 0414ff922..68436539c 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -12,12 +12,11 @@ import { fetchPUT } from '../../util/api.js'; export const ScoreNBaseContext = createContext(); const MemberListContext = createContext(); -const LogContext = createContext(); const memberListReducer = (state, action) => { let next = 0; const team = action.turn ? 'home' : 'away'; - const newTeam = state[team].map((member, idx, arr) => { + const newTeam = [...state[team]].map((member, idx, arr) => { let { safety, at_bat, out, state } = member; if (member.state) { if (action.type === 'out') out++; @@ -26,40 +25,69 @@ const memberListReducer = (state, action) => { next = idx + 1 === arr.length ? 0 : idx + 1; return { ...member, safety, at_bat, out, state: !state }; } else { - return member; + return {...member}; } }); newTeam[next].state = true; return { ...state, [team]: newTeam }; }; +const logListReducer = (state, action) => { + let newState = [...state]; + const target = newState.length > 0 && {...(newState[newState.length - 1])}; + switch(action.type) { + case 'next': + newState.push({ ...action.value, index : action.index, history: [] }); + break; + case 'strike': case 'ball': + target.history = [...target.history, { ...action }]; + newState[newState.length - 1] = target; + break; + case '4ball': case 'safety': case 'out': + target.history = [...target.history, { type: action.type, end : true }]; + target.state = false; + newState[newState.length - 1] = target; + break; + case 'clear': + newState = []; + break; + } + return newState; +}; + const GamePlay = ({ home, away, game_id }) => { - const [turn, round, member_list] = [null, null, null]; const [inning, setInning] = useState({ turn: true, round: 1, }); + const [logList, logListDispatch] = useReducer(logListReducer, []); const { score, base, safetyDispatch } = useScoreNBase({ score: undefined, base: undefined }); const [memberList, memberListDispatch] = useReducer(memberListReducer, { home: data.home.member_list, away: data.away.member_list, }); //member_list fetch해서 받아올아이 + useEffect(() => { + memberList[inning.turn ? 'home' : 'away'].forEach((member, index) => { + if(member.state) logListDispatch({ value: {...member}, type: 'next', index: index + 1 }) + }) + }, [memberList]); + const pitchers = { home: data.home.pitcher, away: data.away.pitcher }; return ( - + - + - - + + diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 217bff4f1..05fb39490 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -22,6 +22,7 @@ const ballCountReducer = (state, action) => { newState = { strike: 0, ball: 0, out: 0 }; break; case 'out': + newState.ball = 0; newState.strike = 0; newState.out++; break; @@ -31,7 +32,7 @@ const ballCountReducer = (state, action) => { return newState; }; -const Board = ({ memberListDispatch, inning, setInning }) => { +const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { const [ballCount, ballCountDispatch] = useReducer(ballCountReducer, { strike: 0, ball: 0, @@ -44,13 +45,17 @@ const Board = ({ memberListDispatch, inning, setInning }) => { //필요한 것들 } else { ballCountDispatch({ type: 'strike' }); + logListDispatch({ type: 'strike', ...ballCount, strike: ballCount.strike + 1 }); } }; const handleBall = () => { if (ballCount.ball === 3) { ballCountDispatch({ type: 'safety' }); + logListDispatch({ type: '4ball', end: true }); + memberListDispatch({ type: 'safety', turn: inning.turn }); } else { ballCountDispatch({ type: 'ball' }); + logListDispatch({ type: 'ball', ...ballCount, ball: ballCount.ball + 1 }); } }; const handleOut = () => { @@ -59,7 +64,9 @@ const Board = ({ memberListDispatch, inning, setInning }) => { if (inning.turn) setInning({ ...inning, turn: !inning.turn }); else setInning({ ...inning, round: inning.round + 1, turn: !inning.turn }); safetyDispatch({ type: 'clear', turn: inning.turn }); + logListDispatch({ type: 'clear' }); } else { + logListDispatch({ type: 'out', end: true }); ballCountDispatch({ type: 'out' }); } // 멤버 아웃 1, 타석 1 증가 @@ -69,6 +76,7 @@ const Board = ({ memberListDispatch, inning, setInning }) => { ballCountDispatch({ type: 'safety' }); // 멤버 안타 1, 타석 1 증가 memberListDispatch({ type: 'safety', turn: inning.turn }); + logListDispatch({ type: 'safety', end: true }); safetyDispatch({ turn: inning.turn, power }); }; diff --git a/fe/src/components/game-play/log/Log.jsx b/fe/src/components/game-play/log/Log.jsx index e2391dcc8..6a7c5e59f 100644 --- a/fe/src/components/game-play/log/Log.jsx +++ b/fe/src/components/game-play/log/Log.jsx @@ -1,39 +1,41 @@ import styled from 'styled-components'; -const Log = (props) => { - const team = props.data.home; - const { member_list } = team; - const log_list = member_list.map((member, i) => ( +const TYPE = { + 'strike': '스트라이크', + 'ball': '볼', + 'safety': '안타', + '4ball': '볼넷', + 'out': '아웃', +} + +const Log = ({ logList }) => { + const logs = logList.map((member, i) => ( + member.history.length > 0 &&
    -
    {i + 1}번 타자 {member.name}
    +
    {member.index}번 타자 {member.name}
    -
    -
    1
    -
    -
    S0 B1
    -
    -
    -
    2
    -
    스트라이크
    -
    S1 B1
    -
    -
    -
    3
    -
    스트라이크
    -
    S2 B1
    -
    -
    -
    -
    안타!
    -
    -
    + { member.history.map((v, i) => + v.end + ? +
    +
    +
    {TYPE[v.type]}!
    +
    +
    + : +
    +
    {i + 1}
    +
    {TYPE[v.type]}
    +
    S{v.strike} B{v.ball}
    +
    + )}
    )); return (
    - {log_list} + {logs}
    ); diff --git a/fe/src/components/ui/PopUp.jsx b/fe/src/components/ui/PopUp.jsx index 299a6f75b..01765bc6a 100644 --- a/fe/src/components/ui/PopUp.jsx +++ b/fe/src/components/ui/PopUp.jsx @@ -1,14 +1,14 @@ import React, {useState} from 'react'; import styled, { keyframes } from 'styled-components'; -const PopUp = ({ children, position }) => { +const PopUp = ({ children, position, emptyText = '' }) => { const [active, setActive] = useState(false); const handleClick = ({target}) => (target.className === 'childrenWrapper' || !target.closest('.childrenWrapper')) && setActive(false); return active ?
    {children}
    -
    : setActive(true)} />; + : setActive(true)}>{emptyText}; }; const toBottom = keyframes` @@ -52,11 +52,22 @@ const StyledPopUp = styled.div` `; const StyledEmpty = styled.div` - width:100vw; - height:5rem; + width: 10vw; + height: 3rem; position: absolute; + right: 30vw; + cursor: pointer; + color: #eee; + border-radius: ${props => props.position === 'top' ? '0 0 1rem 1rem' : '1rem 1rem 0 0' }; + background-color: rgba(0, 0, 0, 0.5); top: ${props => props.position === 'top' && '0px'}; bottom: ${props => props.position === 'bottom' && '0px'}; + text-align: center; + font-size: 1.25rem; + padding: 0.5rem 0; + &:hover { + background-color: rgba(0, 0, 0, 0.8); + } ` diff --git a/fe/src/hooks/useScoreNBase.js b/fe/src/hooks/useScoreNBase.js index db4373488..cebc0f0e8 100644 --- a/fe/src/hooks/useScoreNBase.js +++ b/fe/src/hooks/useScoreNBase.js @@ -27,7 +27,6 @@ const useScoreNBase = ({ return newBase; }; const safetyDispatch = ({ type, turn, power }) => { - console.log(score, base); const team = turn ? 'home' : 'away'; if (type === 'clear') { const newScore = { ...score }; From c728aeb460f2cb14d550dba8ff3983e3ec8de640 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Thu, 13 May 2021 02:06:05 +0900 Subject: [PATCH 09/22] =?UTF-8?q?feat::sparkles:=20fetch=EB=A1=9C=20Player?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/package-lock.json | 88 +++++++++++++++++++ fe/package.json | 1 + fe/src/components/game-play/GamePlay.jsx | 21 +++-- fe/src/components/game-play/player/Player.jsx | 17 ++-- 4 files changed, 109 insertions(+), 18 deletions(-) diff --git a/fe/package-lock.json b/fe/package-lock.json index 2307f59ed..794c3669f 100644 --- a/fe/package-lock.json +++ b/fe/package-lock.json @@ -7190,6 +7190,19 @@ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -10075,6 +10088,15 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, "mini-css-extract-plugin": { "version": "0.11.3", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz", @@ -12526,6 +12548,52 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==" }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, "react-scripts": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz", @@ -12962,6 +13030,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -14635,6 +14708,16 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -15108,6 +15191,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/fe/package.json b/fe/package.json index 7fb9f0a9d..fa8900a54 100644 --- a/fe/package.json +++ b/fe/package.json @@ -10,6 +10,7 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-icons": "^4.2.0", + "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "styled-components": "^5.2.3", "web-vitals": "^1.1.1" diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index f7de1e907..a9426e38d 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -16,6 +16,7 @@ const MemberListContext = createContext(); const LogContext = createContext(); const memberListReducer = (state, action) => { + if (action.type === 'init') return action.value; let next = 0; const team = action.turn ? 'home' : 'away'; const newTeam = state[team].map((member, idx, arr) => { @@ -44,18 +45,20 @@ const GamePlay = ({ home, away, game_id }) => { round: 1, }); const { score, base, safetyDispatch } = useScoreNBase({ score: undefined, base: undefined }); - const [memberList, memberListDispatch] = useReducer(memberListReducer, { - home: data.home.member_list, - away: data.away.member_list, - }); //member_list fetch해서 받아올아이 - debugger; - const homePitch = gamePlayData !== null ? gamePlayData.home.pitcherID : '모디'; - console.log('홈투수', homePitch); + const [memberList, memberListDispatch] = useReducer(memberListReducer, null); const pitchers = { - home: data?.home.pitcher, - away: data?.away.pitcher, + home: gamePlayData?.home.pitcherId, + away: gamePlayData?.away.pitcherId, }; + useEffect(() => { + const memberListData = { + home: gamePlayData?.home.member_list, + away: gamePlayData?.away.member_list, + }; + memberListDispatch({ type: 'init', value: memberListData }); + }, [gamePlayData]); + return ( { gamePlayData } && ( diff --git a/fe/src/components/game-play/player/Player.jsx b/fe/src/components/game-play/player/Player.jsx index e6195abaf..5128c379a 100644 --- a/fe/src/components/game-play/player/Player.jsx +++ b/fe/src/components/game-play/player/Player.jsx @@ -3,37 +3,36 @@ import styled from 'styled-components'; const Player = ({ memberList, turn, pitchers }) => { const HOME = 'home'; const AWAY = 'away'; - console.log('pitchers', pitchers); const getPlayer = () => { + if (!memberList || !memberList[HOME] || !memberList[AWAY]) return; const result = {}; const batterTeam = turn ? HOME : AWAY; const pitcherTeam = turn ? AWAY : HOME; for (const member of memberList[batterTeam]) { - if (member.state) result.batter = member; + if (member.status) result.batter = member; } for (const member of memberList[pitcherTeam]) { if (member.id === pitchers[pitcherTeam]) result.pitcher = member; } return result; }; - - const { pitcher, batter } = getPlayer(); - + const player = getPlayer(); + console.log(player); return (
    투수
    -
    {pitcher?.name}
    -
    #{pitcher?.id}
    +
    {player?.pitcher.name}
    +
    #{player?.pitcher.id}
    타자
    -
    {batter?.name}
    +
    {player?.batter.name}
    - {batter.at_bat}타석 {batter.safety}안타 + {player?.batter.at_bat || 0}타석 {player?.batter.safety || 0}안타
    From e8a7cf335c15fd9afddf65358149d7423c230a1e Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Thu, 13 May 2021 13:04:53 +0900 Subject: [PATCH 10/22] chore. chore --- chore/app.js | 13 ++++++ chore/package.json | 16 ++++++++ chore/src/components/Directory.js | 16 ++++++++ chore/src/components/FileNode.js | 30 ++++++++++++++ chore/src/components/ImgModal.js | 30 ++++++++++++++ chore/src/components/PrevBtn.js | 11 +++++ chore/src/model/model.js | 27 +++++++++++++ chore/src/view/main.js | 67 +++++++++++++++++++++++++++++++ 8 files changed, 210 insertions(+) create mode 100644 chore/app.js create mode 100644 chore/package.json create mode 100644 chore/src/components/Directory.js create mode 100644 chore/src/components/FileNode.js create mode 100644 chore/src/components/ImgModal.js create mode 100644 chore/src/components/PrevBtn.js create mode 100644 chore/src/model/model.js create mode 100644 chore/src/view/main.js diff --git a/chore/app.js b/chore/app.js new file mode 100644 index 000000000..d2baf25df --- /dev/null +++ b/chore/app.js @@ -0,0 +1,13 @@ +import Model from './model/model.js'; +import Main from './view/main.js'; + +const dataInit = async (model) => { + const res = await fetch('https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev'); + const data = await res.json(); + console.log(JSON.stringify(data)); + model.setData(data); +}; + +const model = new Model(); +new Main({ model, data: [] }).init(); +dataInit(model); diff --git a/chore/package.json b/chore/package.json new file mode 100644 index 000000000..cb77b54c8 --- /dev/null +++ b/chore/package.json @@ -0,0 +1,16 @@ +{ + "name": "sample", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "serve -l 5000", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "rotoshine", + "license": "ISC", + "dependencies": { + "serve": "^11.3.2" + } +} diff --git a/chore/src/components/Directory.js b/chore/src/components/Directory.js new file mode 100644 index 000000000..dde2d0765 --- /dev/null +++ b/chore/src/components/Directory.js @@ -0,0 +1,16 @@ +class Directory { + constructor({ id, name, type, parent }) { + this.id = id; + this.name = name; + this.type = type; + this.parent = parent; + } + render() { + return `
    + +
    ${this.name}
    +
    `; + } +} + +export default Directory; diff --git a/chore/src/components/FileNode.js b/chore/src/components/FileNode.js new file mode 100644 index 000000000..04a20f82f --- /dev/null +++ b/chore/src/components/FileNode.js @@ -0,0 +1,30 @@ +class ImgModal { + constructor({ filePath }) { + this.filePath = filePath; + this._app = document.querySelector('.App'); + this.init(); + } + init() { + this.addEvent(); + } + render() { + const imgModal = this.getHTML(); + console.log('imgModal', imgModal); + this._app.insertAdjacentElement('beforeend', imgModal); + } + addEvent() { + this._app.addEventListener('click', this.handleClick.bind(this)); + } + handleClick({ target }) { + if (tagName === 'IMG') return; + } + getHTML() { + const modalHTML = document.createElement('div'); + modalHTML.classList.add('Modal', 'ImageViewer'); + modalHTML.innerHTML = `
    + `; + return modalHTML; + } +} + +export default ImgModal; diff --git a/chore/src/components/ImgModal.js b/chore/src/components/ImgModal.js new file mode 100644 index 000000000..04a20f82f --- /dev/null +++ b/chore/src/components/ImgModal.js @@ -0,0 +1,30 @@ +class ImgModal { + constructor({ filePath }) { + this.filePath = filePath; + this._app = document.querySelector('.App'); + this.init(); + } + init() { + this.addEvent(); + } + render() { + const imgModal = this.getHTML(); + console.log('imgModal', imgModal); + this._app.insertAdjacentElement('beforeend', imgModal); + } + addEvent() { + this._app.addEventListener('click', this.handleClick.bind(this)); + } + handleClick({ target }) { + if (tagName === 'IMG') return; + } + getHTML() { + const modalHTML = document.createElement('div'); + modalHTML.classList.add('Modal', 'ImageViewer'); + modalHTML.innerHTML = `
    + `; + return modalHTML; + } +} + +export default ImgModal; diff --git a/chore/src/components/PrevBtn.js b/chore/src/components/PrevBtn.js new file mode 100644 index 000000000..bc088bf9d --- /dev/null +++ b/chore/src/components/PrevBtn.js @@ -0,0 +1,11 @@ +class PrevBtn { + constructor() {} + render() { + return `
    +
    + +
    `; + } +} + +export default PrevBtn; diff --git a/chore/src/model/model.js b/chore/src/model/model.js new file mode 100644 index 000000000..ba688057b --- /dev/null +++ b/chore/src/model/model.js @@ -0,0 +1,27 @@ +class Model { + constructor(data) { + this._observers = new Set(); + this.data = data; + this.history = []; + } + setData(newData) { + this.history.push(newData); + this.data = newData; + this.notify(newData); + } + popHistory() { + this.history.pop(); + return this.history.pop(); + } + subscribe(observer) { + this._observers.add(observer); + } + unsubscribe(observer) { + this._observers = [...this._observers].filter((subscriber) => subscriber !== observer); + } + notify(data) { + this._observers.forEach((observer) => observer(data)); + } +} + +export default Model; diff --git a/chore/src/view/main.js b/chore/src/view/main.js new file mode 100644 index 000000000..cad0ce50f --- /dev/null +++ b/chore/src/view/main.js @@ -0,0 +1,67 @@ +import Directory from '../components/Directory.js'; +import FileNode from '../components/FileNode.js'; +import ImgModal from '../components/ImgModal.js'; +import PrevBtn from '../components/PrevBtn.js'; + +class Main { + constructor({ model, data }) { + this.model = model; + this.data = data; + this._app = document.querySelector('.App'); + } + init() { + this.addEvent(); + this.render(this.data); + this.model.subscribe(this.render.bind(this)); + } + addEvent() { + this._app.addEventListener('click', this.handleClick.bind(this)); + } + render(data) { + const dataHTML = this.getHTML(data); + this._app.innerHTML = dataHTML; + } + handleClick({ target }) { + if (!target.closest('.directory') && !target.closest('.file') && !target.closest('.prevBtn')) + return; + if (target.closest('.directory')?.classList.contains('directory')) { + this.handleDirClick(target.closest('.directory').dataset.id); + } else if (target.closest('.file')?.classList.contains('file')) { + console.log('file'); + console.log(target.closest('.file').dataset.filepath); + this.handleFileClick(target.closest('.file').dataset.filepath); + } else if (target.closest('.prevBtn')?.classList.contains('prevBtn')) { + console.log('prevBtn'); + this.handlePrevBtnClick(); + } + } + async handleDirClick(id) { + const res = await fetch( + `https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev/${id}` + ); + const data = await res.json(); + this.model.setData(data); + } + async handleFileClick(filePath) { + new ImgModal({ filePath }).render(); + } + handlePrevBtnClick() { + const data = this.model.popHistory(); + this.model.setData(data); + } + getHTML(data) { + let prevFlag = false; + const prevBtn = new PrevBtn().render(); + const HTMLList = data.map((v) => { + console.log(data); + if (!prevFlag && v.parent) prevFlag = true; + if (v.type === 'DIRECTORY') return new Directory(v).render(); + else if (v.type === 'FILE') return new FileNode(v).render(); + }); + console.log(HTMLList); + if (prevFlag || HTMLList.length === 0) HTMLList.unshift(prevBtn); + return HTMLList.join(''); + } +} + +export default Main; From 974e1170965fe45a3777a696212c0cb5590adfe3 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Thu, 13 May 2021 14:24:44 +0900 Subject: [PATCH 11/22] =?UTF-8?q?chore.=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chore/app.js | 13 ---- chore/package.json | 16 ----- chore/src/components/Directory.js | 16 ----- chore/src/components/FileNode.js | 30 --------- chore/src/components/ImgModal.js | 30 --------- chore/src/components/PrevBtn.js | 11 --- chore/src/model/model.js | 27 -------- chore/src/view/main.js | 67 ------------------- fe/src/components/game-play/board/Screen.jsx | 6 +- fe/src/components/game-play/player/Player.jsx | 1 - 10 files changed, 3 insertions(+), 214 deletions(-) delete mode 100644 chore/app.js delete mode 100644 chore/package.json delete mode 100644 chore/src/components/Directory.js delete mode 100644 chore/src/components/FileNode.js delete mode 100644 chore/src/components/ImgModal.js delete mode 100644 chore/src/components/PrevBtn.js delete mode 100644 chore/src/model/model.js delete mode 100644 chore/src/view/main.js diff --git a/chore/app.js b/chore/app.js deleted file mode 100644 index d2baf25df..000000000 --- a/chore/app.js +++ /dev/null @@ -1,13 +0,0 @@ -import Model from './model/model.js'; -import Main from './view/main.js'; - -const dataInit = async (model) => { - const res = await fetch('https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev'); - const data = await res.json(); - console.log(JSON.stringify(data)); - model.setData(data); -}; - -const model = new Model(); -new Main({ model, data: [] }).init(); -dataInit(model); diff --git a/chore/package.json b/chore/package.json deleted file mode 100644 index cb77b54c8..000000000 --- a/chore/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "sample", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "serve -l 5000", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "rotoshine", - "license": "ISC", - "dependencies": { - "serve": "^11.3.2" - } -} diff --git a/chore/src/components/Directory.js b/chore/src/components/Directory.js deleted file mode 100644 index dde2d0765..000000000 --- a/chore/src/components/Directory.js +++ /dev/null @@ -1,16 +0,0 @@ -class Directory { - constructor({ id, name, type, parent }) { - this.id = id; - this.name = name; - this.type = type; - this.parent = parent; - } - render() { - return `
    - -
    ${this.name}
    -
    `; - } -} - -export default Directory; diff --git a/chore/src/components/FileNode.js b/chore/src/components/FileNode.js deleted file mode 100644 index 04a20f82f..000000000 --- a/chore/src/components/FileNode.js +++ /dev/null @@ -1,30 +0,0 @@ -class ImgModal { - constructor({ filePath }) { - this.filePath = filePath; - this._app = document.querySelector('.App'); - this.init(); - } - init() { - this.addEvent(); - } - render() { - const imgModal = this.getHTML(); - console.log('imgModal', imgModal); - this._app.insertAdjacentElement('beforeend', imgModal); - } - addEvent() { - this._app.addEventListener('click', this.handleClick.bind(this)); - } - handleClick({ target }) { - if (tagName === 'IMG') return; - } - getHTML() { - const modalHTML = document.createElement('div'); - modalHTML.classList.add('Modal', 'ImageViewer'); - modalHTML.innerHTML = `
    - `; - return modalHTML; - } -} - -export default ImgModal; diff --git a/chore/src/components/ImgModal.js b/chore/src/components/ImgModal.js deleted file mode 100644 index 04a20f82f..000000000 --- a/chore/src/components/ImgModal.js +++ /dev/null @@ -1,30 +0,0 @@ -class ImgModal { - constructor({ filePath }) { - this.filePath = filePath; - this._app = document.querySelector('.App'); - this.init(); - } - init() { - this.addEvent(); - } - render() { - const imgModal = this.getHTML(); - console.log('imgModal', imgModal); - this._app.insertAdjacentElement('beforeend', imgModal); - } - addEvent() { - this._app.addEventListener('click', this.handleClick.bind(this)); - } - handleClick({ target }) { - if (tagName === 'IMG') return; - } - getHTML() { - const modalHTML = document.createElement('div'); - modalHTML.classList.add('Modal', 'ImageViewer'); - modalHTML.innerHTML = `
    - `; - return modalHTML; - } -} - -export default ImgModal; diff --git a/chore/src/components/PrevBtn.js b/chore/src/components/PrevBtn.js deleted file mode 100644 index bc088bf9d..000000000 --- a/chore/src/components/PrevBtn.js +++ /dev/null @@ -1,11 +0,0 @@ -class PrevBtn { - constructor() {} - render() { - return `
    -
    - -
    `; - } -} - -export default PrevBtn; diff --git a/chore/src/model/model.js b/chore/src/model/model.js deleted file mode 100644 index ba688057b..000000000 --- a/chore/src/model/model.js +++ /dev/null @@ -1,27 +0,0 @@ -class Model { - constructor(data) { - this._observers = new Set(); - this.data = data; - this.history = []; - } - setData(newData) { - this.history.push(newData); - this.data = newData; - this.notify(newData); - } - popHistory() { - this.history.pop(); - return this.history.pop(); - } - subscribe(observer) { - this._observers.add(observer); - } - unsubscribe(observer) { - this._observers = [...this._observers].filter((subscriber) => subscriber !== observer); - } - notify(data) { - this._observers.forEach((observer) => observer(data)); - } -} - -export default Model; diff --git a/chore/src/view/main.js b/chore/src/view/main.js deleted file mode 100644 index cad0ce50f..000000000 --- a/chore/src/view/main.js +++ /dev/null @@ -1,67 +0,0 @@ -import Directory from '../components/Directory.js'; -import FileNode from '../components/FileNode.js'; -import ImgModal from '../components/ImgModal.js'; -import PrevBtn from '../components/PrevBtn.js'; - -class Main { - constructor({ model, data }) { - this.model = model; - this.data = data; - this._app = document.querySelector('.App'); - } - init() { - this.addEvent(); - this.render(this.data); - this.model.subscribe(this.render.bind(this)); - } - addEvent() { - this._app.addEventListener('click', this.handleClick.bind(this)); - } - render(data) { - const dataHTML = this.getHTML(data); - this._app.innerHTML = dataHTML; - } - handleClick({ target }) { - if (!target.closest('.directory') && !target.closest('.file') && !target.closest('.prevBtn')) - return; - if (target.closest('.directory')?.classList.contains('directory')) { - this.handleDirClick(target.closest('.directory').dataset.id); - } else if (target.closest('.file')?.classList.contains('file')) { - console.log('file'); - console.log(target.closest('.file').dataset.filepath); - this.handleFileClick(target.closest('.file').dataset.filepath); - } else if (target.closest('.prevBtn')?.classList.contains('prevBtn')) { - console.log('prevBtn'); - this.handlePrevBtnClick(); - } - } - async handleDirClick(id) { - const res = await fetch( - `https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev/${id}` - ); - const data = await res.json(); - this.model.setData(data); - } - async handleFileClick(filePath) { - new ImgModal({ filePath }).render(); - } - handlePrevBtnClick() { - const data = this.model.popHistory(); - this.model.setData(data); - } - getHTML(data) { - let prevFlag = false; - const prevBtn = new PrevBtn().render(); - const HTMLList = data.map((v) => { - console.log(data); - if (!prevFlag && v.parent) prevFlag = true; - if (v.type === 'DIRECTORY') return new Directory(v).render(); - else if (v.type === 'FILE') return new FileNode(v).render(); - }); - console.log(HTMLList); - if (prevFlag || HTMLList.length === 0) HTMLList.unshift(prevBtn); - return HTMLList.join(''); - } -} - -export default Main; diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index b4d741932..e7a68e3ee 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -26,10 +26,10 @@ const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { const handlePitchClick = () => { const randomNum = Math.ceil(Math.random() * 100); - if (randomNum <= 60) { + if (randomNum <= 30) { //스트라이크 handleStrike(); - } else if (randomNum <= 20) { + } else if (randomNum <= 90) { //볼 handleBall(); } else { @@ -37,7 +37,7 @@ const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { handleSafety(); setRunFirstBase(true); setIsTransition(true); - if (randomNum <= 10) { + if (randomNum <= 100) { //1루타 setCurrentPower(1); } else if (randomNum <= 6) { diff --git a/fe/src/components/game-play/player/Player.jsx b/fe/src/components/game-play/player/Player.jsx index 5128c379a..39eaea26a 100644 --- a/fe/src/components/game-play/player/Player.jsx +++ b/fe/src/components/game-play/player/Player.jsx @@ -17,7 +17,6 @@ const Player = ({ memberList, turn, pitchers }) => { return result; }; const player = getPlayer(); - console.log(player); return (
    From 37569af78fb08ea040816d247cacc45eee669b16 Mon Sep 17 00:00:00 2001 From: kowoohyuk Date: Thu, 13 May 2021 14:57:50 +0900 Subject: [PATCH 12/22] =?UTF-8?q?[#38]=20wip:=20:gear:=20=EB=B3=91?= =?UTF-8?q?=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/GamePlay.jsx | 21 +++++++++++--------- fe/src/components/game-play/board/Board.jsx | 1 - fe/src/components/game-play/board/Screen.jsx | 19 +++++------------- 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index d266280bf..d569f8412 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -19,18 +19,18 @@ const memberListReducer = (state, action) => { let next = 0; const team = action.turn ? 'home' : 'away'; const newTeam = [...state[team]].map((member, idx, arr) => { - let { safety, at_bat, out, state } = member; - if (member.state) { + let { safety, at_bat, out, status } = member; + if (member.status) { if (action.type === 'out') out++; else safety++; at_bat++; next = idx + 1 === arr.length ? 0 : idx + 1; - return { ...member, safety, at_bat, out, state: !state }; + return { ...member, safety, at_bat, out, status: !status }; } else { return {...member}; } }); - newTeam[next].state = true; + newTeam[next].status = true; return { ...state, [team]: newTeam }; }; @@ -47,7 +47,7 @@ const logListReducer = (state, action) => { break; case '4ball': case 'safety': case 'out': target.history = [...target.history, { type: action.type, end : true }]; - target.state = false; + target.status = false; newState[newState.length - 1] = target; break; case 'clear': @@ -74,6 +74,8 @@ const GamePlay = ({ home, away, game_id }) => { away: gamePlayData?.away.pitcherId, }; + const teamName = { home, away }; + useEffect(() => { const memberListData = { home: gamePlayData?.home.member_list, @@ -83,12 +85,13 @@ const GamePlay = ({ home, away, game_id }) => { }, [gamePlayData]); useEffect(() => { - memberList[inning.turn ? 'home' : 'away'].forEach((member, index) => { - if(member.state) logListDispatch({ value: {...member}, type: 'next', index: index + 1 }) - }) + if(memberList && memberList.home) { + memberList[inning.turn ? 'home' : 'away'].forEach((member, index) => { + if(member.status) logListDispatch({ value: {...member}, type: 'next', index: index + 1 }) + }); + } }, [memberList]); - const pitchers = { home: data.home.pitcher, away: data.away.pitcher }; return ( diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 76c80407f..b07039df2 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -77,7 +77,6 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { // 멤버 안타 1, 타석 1 증가 memberListDispatch({ type: 'safety', turn: inning.turn }); logListDispatch({ type: 'safety', end: true }); - safetyDispatch({ turn: inning.turn, power }); }; useEffect(() => { diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index e7a68e3ee..86227064e 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -53,20 +53,11 @@ const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { } }; - const baseList = Object.entries(base).map(([baseNum, status]) => { - if (status) - return ( -
    -
    -
    - ); - else - return ( -
    -
    -
    - ); - }); + const baseList = Object.entries(base).map(([baseNum, status], idx) => +
    +
    +
    + ); return ( From 220363f67d87c714ff926df6a6fcef847dde54c5 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Thu, 13 May 2021 15:39:56 +0900 Subject: [PATCH 13/22] =?UTF-8?q?feat::sparkles:=20score=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/GamePlay.jsx | 37 ++++++++++++------- fe/src/components/game-play/board/Board.jsx | 2 +- .../game-play/popup/score/Score.jsx | 6 +-- .../game-play/popup/score/ScoreList.jsx | 3 +- fe/src/hooks/useFetch.js | 13 ++++--- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index d569f8412..a6994354c 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -27,7 +27,7 @@ const memberListReducer = (state, action) => { next = idx + 1 === arr.length ? 0 : idx + 1; return { ...member, safety, at_bat, out, status: !status }; } else { - return {...member}; + return { ...member }; } }); newTeam[next].status = true; @@ -36,17 +36,21 @@ const memberListReducer = (state, action) => { const logListReducer = (state, action) => { let newState = [...state]; - const target = newState.length > 0 && {...(newState[newState.length - 1])}; - switch(action.type) { + const target = newState.length > 0 && { ...newState[newState.length - 1] }; + // eslint-disable-next-line default-case + switch (action.type) { case 'next': - newState.push({ ...action.value, index : action.index, history: [] }); + newState.push({ ...action.value, index: action.index, history: [] }); break; - case 'strike': case 'ball': + case 'strike': + case 'ball': target.history = [...target.history, { ...action }]; newState[newState.length - 1] = target; break; - case '4ball': case 'safety': case 'out': - target.history = [...target.history, { type: action.type, end : true }]; + case '4ball': + case 'safety': + case 'out': + target.history = [...target.history, { type: action.type, end: true }]; target.status = false; newState[newState.length - 1] = target; break; @@ -67,15 +71,21 @@ const GamePlay = ({ home, away, game_id }) => { round: 1, }); const [logList, logListDispatch] = useReducer(logListReducer, []); - const { score, base, safetyDispatch } = useScoreNBase({ score: undefined, base: undefined }); + const { score, base, safetyDispatch } = useScoreNBase({ + score: { home: [0], away: [] }, + base: undefined, + }); + console.log('score', score); const [memberList, memberListDispatch] = useReducer(memberListReducer, null); + const teamName = { + home: 'json', + away: 'kyle', + }; const pitchers = { home: gamePlayData?.home.pitcherId, away: gamePlayData?.away.pitcherId, }; - const teamName = { home, away }; - useEffect(() => { const memberListData = { home: gamePlayData?.home.member_list, @@ -85,9 +95,10 @@ const GamePlay = ({ home, away, game_id }) => { }, [gamePlayData]); useEffect(() => { - if(memberList && memberList.home) { + if (memberList && memberList.home) { memberList[inning.turn ? 'home' : 'away'].forEach((member, index) => { - if(member.status) logListDispatch({ value: {...member}, type: 'next', index: index + 1 }) + if (member.status) + logListDispatch({ value: { ...member }, type: 'next', index: index + 1 }); }); } }, [memberList]); @@ -95,7 +106,7 @@ const GamePlay = ({ home, away, game_id }) => { return ( - + diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index b07039df2..1847707c0 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -63,7 +63,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { ballCountDispatch({ type: 'clear' }); if (inning.turn) setInning({ ...inning, turn: !inning.turn }); else setInning({ ...inning, round: inning.round + 1, turn: !inning.turn }); - safetyDispatch({ type: 'clear', turn: inning.turn }); + safetyDispatch({ type: 'clear', turn: !inning.turn }); logListDispatch({ type: 'clear' }); } else { logListDispatch({ type: 'out', end: true }); diff --git a/fe/src/components/game-play/popup/score/Score.jsx b/fe/src/components/game-play/popup/score/Score.jsx index bee530063..e2f60bdc0 100644 --- a/fe/src/components/game-play/popup/score/Score.jsx +++ b/fe/src/components/game-play/popup/score/Score.jsx @@ -2,15 +2,15 @@ import React from 'react'; import styled from 'styled-components'; import ScoreList from './ScoreList'; -const Score = (props) => { +const Score = ({ score, teamName }) => { //props로 받아올 아이들 1. team 2. player(home or away) const ROUND = new Array(12).fill().map((_, idx) => idx + 1); return ( - - + + ); }; diff --git a/fe/src/components/game-play/popup/score/ScoreList.jsx b/fe/src/components/game-play/popup/score/ScoreList.jsx index c7105bc2e..a84b05c0b 100644 --- a/fe/src/components/game-play/popup/score/ScoreList.jsx +++ b/fe/src/components/game-play/popup/score/ScoreList.jsx @@ -4,11 +4,10 @@ import { IoBaseballOutline } from 'react-icons/io5'; const ScoreList = ({ team, dataType, data, isPlayer }) => { const isInRound = dataType === 'round'; - const scoreList = new Array(12).fill(''); data.forEach((v, idx) => (scoreList[idx] = v)); - isInRound ? scoreList.push('R') : scoreList.push(data.reduce((acc, cur) => acc + cur)); + isInRound ? scoreList.push('R') : scoreList.push(data.reduce((acc, cur) => acc + cur, 0)); const scoreDivList = scoreList.map((score, idx, arr) => (
    { +const useFetch = (url, method, value) => { const [data, setData] = useState(null); - const fetchData = async (url, method) => { + const fetchData = async (url, method, value) => { try { if (method === 'get') { const res = await fetch(url); const data = await res.json(); setData(data); + } else if (method === 'put') { + const res = await fetch(url, { + method: 'put', + headers: '', + }); } } catch (err) { console.log(err); @@ -16,9 +21,7 @@ const useFetch = (url, method) => { }; useEffect(() => { - if (method === 'get') { - fetchData(url, method); - } + fetchData(url, method, value); }, []); return { data }; From e1e0b2071de670860e94c525d34b07b0e9924e51 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Thu, 13 May 2021 15:44:39 +0900 Subject: [PATCH 14/22] =?UTF-8?q?feat:sparkles:=20=EB=B3=BC=EB=84=B7?= =?UTF-8?q?=EC=9D=BC=EB=95=8C=20=EC=A7=84=EB=A3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/board/Board.jsx | 5 ++++- fe/src/components/game-play/board/Screen.jsx | 13 ++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 1847707c0..bada8c52b 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -86,7 +86,10 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { return ( - + ); diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index 86227064e..02e2ecf6f 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -3,7 +3,7 @@ import styled from 'styled-components'; import useScoreNBase from '../../../hooks/useScoreNBase'; import { ScoreNBaseContext } from '../GamePlay'; -const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { +const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) => { const { base, safetyDispatch } = useContext(ScoreNBaseContext); const [isTransition, setIsTransition] = useState(false); const [runFirstBase, setRunFirstBase] = useState(false); @@ -31,12 +31,15 @@ const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { handleStrike(); } else if (randomNum <= 90) { //볼 + if (ballCount.ball === 3) { + setIsTransition(true); + setRunFirstBase(true); + setCurrentPower(1); + } handleBall(); } else { //안타 handleSafety(); - setRunFirstBase(true); - setIsTransition(true); if (randomNum <= 100) { //1루타 setCurrentPower(1); @@ -53,11 +56,11 @@ const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { } }; - const baseList = Object.entries(base).map(([baseNum, status], idx) => + const baseList = Object.entries(base).map(([baseNum, status], idx) => (
    - ); + )); return ( From a9e3b22f64d7ef7ef0ed69b62f12fcf7f7fc5c66 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Thu, 13 May 2021 16:24:22 +0900 Subject: [PATCH 15/22] =?UTF-8?q?Wip::gear:=20Score=20fetch=20=EC=A4=80?= =?UTF-8?q?=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/GamePlay.jsx | 6 +++--- .../game-play/popup/score/Score.jsx | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index a6994354c..85309f28c 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -25,6 +25,7 @@ const memberListReducer = (state, action) => { else safety++; at_bat++; next = idx + 1 === arr.length ? 0 : idx + 1; + return { ...member, safety, at_bat, out, status: !status }; } else { return { ...member }; @@ -36,8 +37,8 @@ const memberListReducer = (state, action) => { const logListReducer = (state, action) => { let newState = [...state]; + console.log(newState); const target = newState.length > 0 && { ...newState[newState.length - 1] }; - // eslint-disable-next-line default-case switch (action.type) { case 'next': newState.push({ ...action.value, index: action.index, history: [] }); @@ -75,7 +76,6 @@ const GamePlay = ({ home, away, game_id }) => { score: { home: [0], away: [] }, base: undefined, }); - console.log('score', score); const [memberList, memberListDispatch] = useReducer(memberListReducer, null); const teamName = { home: 'json', @@ -113,7 +113,7 @@ const GamePlay = ({ home, away, game_id }) => { - + diff --git a/fe/src/components/game-play/popup/score/Score.jsx b/fe/src/components/game-play/popup/score/Score.jsx index e2f60bdc0..09838eda7 100644 --- a/fe/src/components/game-play/popup/score/Score.jsx +++ b/fe/src/components/game-play/popup/score/Score.jsx @@ -1,17 +1,24 @@ import React from 'react'; import styled from 'styled-components'; +import useFetch from '../../../../hooks/useFetch'; import ScoreList from './ScoreList'; -const Score = ({ score, teamName }) => { +const Score = ({ score, teamName, gameID }) => { + const SCORE_URL = `http://52.78.184.142/games/${gameID}/detail-score`; //props로 받아올 아이들 1. team 2. player(home or away) const ROUND = new Array(12).fill().map((_, idx) => idx + 1); + // const { data: score } = useFetch(SCORE_URL, 'get'); + console.log(score); return ( - - - - - + score && + score.home && ( + + + + + + ) ); }; From 26042135f6035e21fdb0b8ad2c8407b3a1f23a2d Mon Sep 17 00:00:00 2001 From: kowoohyuk Date: Thu, 13 May 2021 16:25:32 +0900 Subject: [PATCH 16/22] =?UTF-8?q?[#38]=20wip:=20:gear:=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-list/GameList.jsx | 44 ++++---------------- fe/src/components/game-list/GameListItem.jsx | 7 +++- fe/src/components/game-play/GamePlay.jsx | 40 ++++++++++++++++-- fe/src/components/game-play/board/Board.jsx | 11 ++--- fe/src/components/game-play/board/Screen.jsx | 11 +++-- fe/src/components/game-play/log/Log.jsx | 4 +- fe/src/hooks/useFetch.js | 28 +++++++++++-- 7 files changed, 90 insertions(+), 55 deletions(-) diff --git a/fe/src/components/game-list/GameList.jsx b/fe/src/components/game-list/GameList.jsx index 8070ee1e9..368dd2689 100644 --- a/fe/src/components/game-list/GameList.jsx +++ b/fe/src/components/game-list/GameList.jsx @@ -1,19 +1,24 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import styled from 'styled-components'; import useFetch from '../../hooks/useFetch'; import GameListItem from './GameListItem'; +import { Link } from 'react-router-dom'; const DATA_LIST_URL = 'http://52.78.184.142/games'; const GameList = () => { + const game_id = localStorage.getItem('game_id'); + if(game_id) { + window.location.href = 'games/' + game_id; + } const { data: gameListData } = useFetch(DATA_LIST_URL, 'get'); const TITLE = 'BASEBALL GAME ONLINE'; const DESCRIPTION = '참가할 게임을 선택하세요!'; const gameList = gameListData?.game_list.map(({ home, away, id }, idx) => ( )); - - return ( + + return game_id ? null : ( {TITLE} {DESCRIPTION} @@ -71,37 +76,4 @@ const StyledList = styled.div` } `; -const game_list = [ - { - home: '베리베리 스트로베리', - away: '엄마는 외계인', - game_id: 0, - }, - { - home: 'twins', - away: 'tigers', - game_id: 1, - }, - { - home: 'rockets', - away: 'dodgers', - game_id: 2, - }, - { - home: 'rockets', - away: 'dodgers', - game_id: 2, - }, - { - home: 'rockets', - away: 'dodgers', - game_id: 2, - }, - { - home: 'rockets', - away: 'dodgers', - game_id: 2, - }, -]; - export default GameList; diff --git a/fe/src/components/game-list/GameListItem.jsx b/fe/src/components/game-list/GameListItem.jsx index 7ca304fcf..84845bcf6 100644 --- a/fe/src/components/game-list/GameListItem.jsx +++ b/fe/src/components/game-list/GameListItem.jsx @@ -4,15 +4,18 @@ import { Link } from 'react-router-dom'; const GameListItem = ({ home, away, id, idx }) => { const path = `games/${id}`; + const onClick = e => { + localStorage.setItem('select', e.target.textContent); + } return (
    GAME {idx + 1}
    - +
    {home}
    vs
    - +
    {away}
    diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index d569f8412..93d91af4d 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -14,6 +14,8 @@ import useFetch from '../../hooks/useFetch'; export const ScoreNBaseContext = createContext(); const MemberListContext = createContext(); +const DATA_PLAYER_URL = 'http://52.78.184.142'; + const memberListReducer = (state, action) => { if (action.type === 'init') return action.value; let next = 0; @@ -21,10 +23,24 @@ const memberListReducer = (state, action) => { const newTeam = [...state[team]].map((member, idx, arr) => { let { safety, at_bat, out, status } = member; if (member.status) { + console.log(idx, action); if (action.type === 'out') out++; else safety++; at_bat++; next = idx + 1 === arr.length ? 0 : idx + 1; + + console.log('???!'); + // put: /players/{player_id} + + /* + const { data: result } = useFetch(DATA_PLAYER_URL + '/players/' + member.id, 'put', { + local + }); + */ +// { +// "game_id": 6, +// "at_bat": true // true: 안타, false: 아웃 +// } return { ...member, safety, at_bat, out, status: !status }; } else { return {...member}; @@ -36,7 +52,8 @@ const memberListReducer = (state, action) => { const logListReducer = (state, action) => { let newState = [...state]; - const target = newState.length > 0 && {...(newState[newState.length - 1])}; + console.log(newState); + const target = newState.length > 0 && {...newState[newState.length - 1]}; switch(action.type) { case 'next': newState.push({ ...action.value, index : action.index, history: [] }); @@ -60,7 +77,8 @@ const logListReducer = (state, action) => { const GamePlay = ({ home, away, game_id }) => { const path = window.location.pathname; const gameID = +path.slice(7); - const GAME_PLAY_URL = `http://52.78.184.142${path}`; + localStorage.setItem('game_id', gameID); + const GAME_PLAY_URL = DATA_PLAYER_URL + path; const { data: gamePlayData } = useFetch(GAME_PLAY_URL, 'get'); const [inning, setInning] = useState({ turn: true, @@ -92,6 +110,22 @@ const GamePlay = ({ home, away, game_id }) => { } }, [memberList]); + useEffect(() => { + // post:/games/{game_id} + console.log(inning, memberList); + // const { data: result } = useFetch(DATA_PLAYER_URL + '/games/' + game_id, 'put', { + // game_id, + // "team_id": 1, 종료된 팀 아이디 + // "round" : 3, 종료된 라운드 + // "player_id": 3, 마지막 아웃 된 타자 + // }); +// { +// "game_id": 6, +// "at_bat": true // true: 안타, false: 아웃 +// } + + }, [inning]); + return ( @@ -104,7 +138,7 @@ const GamePlay = ({ home, away, game_id }) => { - +
    diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index b07039df2..a8d2cb808 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -32,7 +32,7 @@ const ballCountReducer = (state, action) => { return newState; }; -const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { +const Board = ({ memberListDispatch, inning, setInning, logListDispatch, game_id }) => { const [ballCount, ballCountDispatch] = useReducer(ballCountReducer, { strike: 0, ball: 0, @@ -52,7 +52,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { if (ballCount.ball === 3) { ballCountDispatch({ type: 'safety' }); logListDispatch({ type: '4ball', end: true }); - memberListDispatch({ type: 'safety', turn: inning.turn }); + memberListDispatch({ type: 'safety', turn: inning.turn, game_id }); } else { ballCountDispatch({ type: 'ball' }); logListDispatch({ type: 'ball', ...ballCount, ball: ballCount.ball + 1 }); @@ -60,6 +60,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { }; const handleOut = () => { if (ballCount.out === 2) { + // 여기에 공수교대 ballCountDispatch({ type: 'clear' }); if (inning.turn) setInning({ ...inning, turn: !inning.turn }); else setInning({ ...inning, round: inning.round + 1, turn: !inning.turn }); @@ -70,12 +71,12 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { ballCountDispatch({ type: 'out' }); } // 멤버 아웃 1, 타석 1 증가 - memberListDispatch({ type: 'out', turn: inning.turn }); + memberListDispatch({ type: 'out', turn: inning.turn, game_id }); }; const handleSafety = () => { ballCountDispatch({ type: 'safety' }); // 멤버 안타 1, 타석 1 증가 - memberListDispatch({ type: 'safety', turn: inning.turn }); + memberListDispatch({ type: 'safety', turn: inning.turn, game_id }); logListDispatch({ type: 'safety', end: true }); }; @@ -86,7 +87,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { return ( - + ); diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index 86227064e..426396d84 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -3,7 +3,7 @@ import styled from 'styled-components'; import useScoreNBase from '../../../hooks/useScoreNBase'; import { ScoreNBaseContext } from '../GamePlay'; -const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { +const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) => { const { base, safetyDispatch } = useContext(ScoreNBaseContext); const [isTransition, setIsTransition] = useState(false); const [runFirstBase, setRunFirstBase] = useState(false); @@ -26,11 +26,16 @@ const Screen = ({ handleStrike, handleBall, handleSafety, turn }) => { const handlePitchClick = () => { const randomNum = Math.ceil(Math.random() * 100); - if (randomNum <= 30) { + if (randomNum <= 0) { //스트라이크 handleStrike(); - } else if (randomNum <= 90) { + } else if (randomNum <= 0) { //볼 + if(ballCount.ball === 3) { + setIsTransition(true); + setRunFirstBase(true); + setCurrentPower(1); + } handleBall(); } else { //안타 diff --git a/fe/src/components/game-play/log/Log.jsx b/fe/src/components/game-play/log/Log.jsx index 6a7c5e59f..ad029a20d 100644 --- a/fe/src/components/game-play/log/Log.jsx +++ b/fe/src/components/game-play/log/Log.jsx @@ -17,13 +17,13 @@ const Log = ({ logList }) => { { member.history.map((v, i) => v.end ? -
    +
    {TYPE[v.type]}!
    : -
    +
    {i + 1}
    {TYPE[v.type]}
    S{v.strike} B{v.ball}
    diff --git a/fe/src/hooks/useFetch.js b/fe/src/hooks/useFetch.js index 3eacd124e..f8a6a3537 100644 --- a/fe/src/hooks/useFetch.js +++ b/fe/src/hooks/useFetch.js @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; -const useFetch = (url, method) => { +const useFetch = (url, method, value = '') => { const [data, setData] = useState(null); const fetchData = async (url, method) => { @@ -9,6 +9,28 @@ const useFetch = (url, method) => { const res = await fetch(url); const data = await res.json(); setData(data); + } else if (method === 'post') { + console.log('post', value); + const res = await fetch(url, { + method: 'post', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(value), + }); + const data = await res.json(); + console.log(res, data); + } else if (method === 'put') { + console.log('put', value); + const res = await fetch(url, { + method: 'put', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(value), + }); + const data = await res.json(); + console.log(res, data); } } catch (err) { console.log(err); @@ -16,9 +38,7 @@ const useFetch = (url, method) => { }; useEffect(() => { - if (method === 'get') { - fetchData(url, method); - } + fetchData(url, method, value); }, []); return { data }; From b97820870613d0cfd01260a16d2a46c09ec2d54e Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Fri, 14 May 2021 01:34:34 +0900 Subject: [PATCH 17/22] =?UTF-8?q?fix::bug:=20=EC=95=88=ED=83=80=20?= =?UTF-8?q?=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/GamePlay.jsx | 14 +++++++------- fe/src/components/game-play/board/Screen.jsx | 6 ++++-- fe/src/components/game-play/score/Score.jsx | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index 85309f28c..69195644c 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -37,7 +37,6 @@ const memberListReducer = (state, action) => { const logListReducer = (state, action) => { let newState = [...state]; - console.log(newState); const target = newState.length > 0 && { ...newState[newState.length - 1] }; switch (action.type) { case 'next': @@ -76,20 +75,21 @@ const GamePlay = ({ home, away, game_id }) => { score: { home: [0], away: [] }, base: undefined, }); + console.log(gamePlayData); const [memberList, memberListDispatch] = useReducer(memberListReducer, null); const teamName = { - home: 'json', - away: 'kyle', + home: gamePlayData?.home?.name, + away: gamePlayData?.away?.name, }; const pitchers = { - home: gamePlayData?.home.pitcherId, - away: gamePlayData?.away.pitcherId, + home: gamePlayData?.home?.pitcherId, + away: gamePlayData?.away?.pitcherId, }; useEffect(() => { const memberListData = { - home: gamePlayData?.home.member_list, - away: gamePlayData?.away.member_list, + home: gamePlayData?.home?.member_list, + away: gamePlayData?.away?.member_list, }; memberListDispatch({ type: 'init', value: memberListData }); }, [gamePlayData]); diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index 02e2ecf6f..0f37238ef 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -26,10 +26,10 @@ const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) => const handlePitchClick = () => { const randomNum = Math.ceil(Math.random() * 100); - if (randomNum <= 30) { + if (randomNum <= 60) { //스트라이크 handleStrike(); - } else if (randomNum <= 90) { + } else if (randomNum <= 80) { //볼 if (ballCount.ball === 3) { setIsTransition(true); @@ -39,6 +39,8 @@ const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) => handleBall(); } else { //안타 + setIsTransition(true); + setRunFirstBase(true); handleSafety(); if (randomNum <= 100) { //1루타 diff --git a/fe/src/components/game-play/score/Score.jsx b/fe/src/components/game-play/score/Score.jsx index 134a57770..22980e728 100644 --- a/fe/src/components/game-play/score/Score.jsx +++ b/fe/src/components/game-play/score/Score.jsx @@ -36,7 +36,7 @@ const Score = ({ teamName, turn }) => { const StyledScore = styled.div` .title { - font-size: 3rem; + font-size: 2rem; font-weight: 600; color: #fff; text-align: center; From cd02daa55cde2ab0932ad5d1ed6892519e4e4b22 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Fri, 14 May 2021 02:04:18 +0900 Subject: [PATCH 18/22] =?UTF-8?q?Chore::wrench:=20fetch=ED=95=A0=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/board/Board.jsx | 5 ++++- fe/src/components/game-play/board/Screen.jsx | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index bada8c52b..2d730be54 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -42,7 +42,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { const handleStrike = () => { if (ballCount.strike === 2) { handleOut(); - //필요한 것들 + //3번 API fetch { "game_id": 6, "at_bat": false } //game_id는 컨텍스트 사용 } else { ballCountDispatch({ type: 'strike' }); logListDispatch({ type: 'strike', ...ballCount, strike: ballCount.strike + 1 }); @@ -53,6 +53,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { ballCountDispatch({ type: 'safety' }); logListDispatch({ type: '4ball', end: true }); memberListDispatch({ type: 'safety', turn: inning.turn }); + //3번 API fetch { "game_id": 6, "at_bat": true } } else { ballCountDispatch({ type: 'ball' }); logListDispatch({ type: 'ball', ...ballCount, ball: ballCount.ball + 1 }); @@ -60,6 +61,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { }; const handleOut = () => { if (ballCount.out === 2) { + //7번 API { "game_id": 6, "team_id":1, "round":3, "at_bat": 3 } ??타자를 번호를 보내는거네??? ballCountDispatch({ type: 'clear' }); if (inning.turn) setInning({ ...inning, turn: !inning.turn }); else setInning({ ...inning, round: inning.round + 1, turn: !inning.turn }); @@ -73,6 +75,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch }) => { memberListDispatch({ type: 'out', turn: inning.turn }); }; const handleSafety = () => { + //3번 API fetch { "game_id": 6, "at_bat": true } ballCountDispatch({ type: 'safety' }); // 멤버 안타 1, 타석 1 증가 memberListDispatch({ type: 'safety', turn: inning.turn }); diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index 0f37238ef..3a8051960 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -32,6 +32,9 @@ const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) => } else if (randomNum <= 80) { //볼 if (ballCount.ball === 3) { + if (base[3]) { + //4번 API {"game_id": 7,"home": 1,"away": 2, "round": 3} 모든정보 컨텍스트로 + } setIsTransition(true); setRunFirstBase(true); setCurrentPower(1); @@ -39,6 +42,9 @@ const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) => handleBall(); } else { //안타 + if (base[3]) { + //4번 API {"game_id": 7,"home": 1,"away": 2, "round": 3} 모든정보 컨텍스트로 + } setIsTransition(true); setRunFirstBase(true); handleSafety(); From f19c72a18e52e367bf9a54169db6231acd9394e3 Mon Sep 17 00:00:00 2001 From: kowoohyuk Date: Fri, 14 May 2021 11:06:59 +0900 Subject: [PATCH 19/22] =?UTF-8?q?[#38]=20:wip=20:gear:=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EC=A4=91...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-list/GameListItem.jsx | 1 + fe/src/components/game-play/GamePlay.jsx | 42 ++++++++-------- fe/src/components/game-play/board/Board.jsx | 4 +- fe/src/components/game-play/board/Screen.jsx | 50 ++++++++++++++++--- fe/src/components/game-play/player/Player.jsx | 2 +- .../game-play/popup/roster/Roster.jsx | 7 ++- .../game-play/popup/roster/RosterPlayer.jsx | 14 +++--- .../game-play/popup/roster/TeamRoster.jsx | 13 +++-- .../game-play/popup/score/Score.jsx | 1 - fe/src/components/game-play/score/Score.jsx | 6 +-- 10 files changed, 88 insertions(+), 52 deletions(-) diff --git a/fe/src/components/game-list/GameListItem.jsx b/fe/src/components/game-list/GameListItem.jsx index 84845bcf6..f8b0c0fcb 100644 --- a/fe/src/components/game-list/GameListItem.jsx +++ b/fe/src/components/game-list/GameListItem.jsx @@ -6,6 +6,7 @@ const GameListItem = ({ home, away, id, idx }) => { const path = `games/${id}`; const onClick = e => { localStorage.setItem('select', e.target.textContent); + localStorage.setItem('teams', JSON.stringify({ home, away })); } return ( diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index d7fe58ad3..1b8cdce44 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -21,15 +21,13 @@ const memberListReducer = (state, action) => { let next = 0; const team = action.turn ? 'home' : 'away'; const newTeam = [...state[team]].map((member, idx, arr) => { - let { safety, at_bat, out, status } = member; + let { plate_appearance, atBat, outCount, status } = member; if (member.status) { - console.log(idx, action); - if (action.type === 'out') out++; - else safety++; - at_bat++; + if (action.type === 'out') outCount++; + else plate_appearance++; + atBat++; next = idx + 1 === arr.length ? 0 : idx + 1; - console.log('???!'); // put: /players/{player_id} /* @@ -39,9 +37,9 @@ const memberListReducer = (state, action) => { */ // { // "game_id": 6, -// "at_bat": true // true: 안타, false: 아웃 +// "atBat": true // true: 안타, false: 아웃 // } - return { ...member, safety, at_bat, out, status: !status }; + return { ...member, plate_appearance, atBat, outCount, status: !status }; } else { return { ...member }; } @@ -52,7 +50,6 @@ const memberListReducer = (state, action) => { const logListReducer = (state, action) => { let newState = [...state]; - console.log(newState); const target = newState.length > 0 && { ...newState[newState.length - 1] }; switch (action.type) { case 'next': @@ -80,6 +77,7 @@ const logListReducer = (state, action) => { const GamePlay = ({ home, away, game_id }) => { const path = window.location.pathname; const gameID = +path.slice(7); + const selectTeam = localStorage.getItem('select'); localStorage.setItem('game_id', gameID); const GAME_PLAY_URL = DATA_PLAYER_URL + path; const { data: gamePlayData } = useFetch(GAME_PLAY_URL, 'get'); @@ -94,18 +92,17 @@ const GamePlay = ({ home, away, game_id }) => { }); const [memberList, memberListDispatch] = useReducer(memberListReducer, null); const teamName = { - home: 'json', - away: 'kyle', + ...JSON.parse(localStorage.getItem('teams')) }; const pitchers = { - home: gamePlayData?.home.pitcherId, - away: gamePlayData?.away.pitcherId, + home: gamePlayData?.home?.pitcherId, + away: gamePlayData?.away?.pitcherId, }; useEffect(() => { const memberListData = { - home: gamePlayData?.home.member_list, - away: gamePlayData?.away.member_list, + home: gamePlayData?.home?.member_list, + away: gamePlayData?.away?.member_list, }; memberListDispatch({ type: 'init', value: memberListData }); }, [gamePlayData]); @@ -113,15 +110,16 @@ const GamePlay = ({ home, away, game_id }) => { useEffect(() => { if (memberList && memberList.home) { memberList[inning.turn ? 'home' : 'away'].forEach((member, index) => { - if (member.status) + if (member.status) { logListDispatch({ value: { ...member }, type: 'next', index: index + 1 }); + } }); } }, [memberList]); useEffect(() => { // post:/games/{game_id} - console.log(inning, memberList); + // console.log(inning, memberList); // const { data: result } = useFetch(DATA_PLAYER_URL + '/games/' + game_id, 'put', { // game_id, // "team_id": 1, 종료된 팀 아이디 @@ -130,7 +128,7 @@ const GamePlay = ({ home, away, game_id }) => { // }); // { // "game_id": 6, -// "at_bat": true // true: 안타, false: 아웃 +// "atBat": true // true: 안타, false: 아웃 // } }, [inning]); @@ -138,16 +136,16 @@ const GamePlay = ({ home, away, game_id }) => { return ( - + - + - + - + diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 85b8a0789..61436ff23 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -32,7 +32,7 @@ const ballCountReducer = (state, action) => { return newState; }; -const Board = ({ memberListDispatch, inning, setInning, logListDispatch, game_id }) => { +const Board = ({ memberListDispatch, inning, setInning, logListDispatch, game_id, teamName, selectTeam }) => { const [ballCount, ballCountDispatch] = useReducer(ballCountReducer, { strike: 0, ball: 0, @@ -88,7 +88,7 @@ const Board = ({ memberListDispatch, inning, setInning, logListDispatch, game_id diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index 62f56ad6d..2de968bba 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -1,9 +1,9 @@ -import React, { useState, useContext, useEffect } from 'react'; +import React, { useState, useContext, useEffect, useRef } from 'react'; import styled from 'styled-components'; import useScoreNBase from '../../../hooks/useScoreNBase'; import { ScoreNBaseContext } from '../GamePlay'; -const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) => { +const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn, teamName, selectTeam }) => { const { base, safetyDispatch } = useContext(ScoreNBaseContext); const [isTransition, setIsTransition] = useState(false); const [runFirstBase, setRunFirstBase] = useState(false); @@ -26,19 +26,21 @@ const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) => const handlePitchClick = () => { const randomNum = Math.ceil(Math.random() * 100); - if (randomNum <= 0) { + if (randomNum <= 55) { //스트라이크 handleStrike(); - } else if (randomNum <= 0) { + } else if (randomNum <= 90) { //볼 if (ballCount.ball === 3) { + setCurrentPower(1); setIsTransition(true); setRunFirstBase(true); - setCurrentPower(1); } handleBall(); } else { //안타 + setIsTransition(true); + setRunFirstBase(true); handleSafety(); if (randomNum <= 100) { //1루타 @@ -62,9 +64,45 @@ const Screen = ({ handleStrike, handleBall, handleSafety, ballCount, turn }) =>
    )); + const isPitch = (turn && teamName.home != selectTeam) || (!turn && teamName.away != selectTeam); + + const savedCallback = useRef(); + + function callback() { + handlePitchClick(); + } + + useEffect(() => { + savedCallback.current = callback; + }); + + useEffect(() => { + function tick() { + savedCallback.current(); + } + if(!isPitch) { + let id = setInterval(tick, 1000); + return () => clearInterval(id); + } else { + return null; + } + }, []); + + + // useEffect(() => { + // let interval = setInterval(() => handlePitchClick(), 1000); + // clearInterval(interval); + // if(!isPitch) { + // interval = setInterval(() => handlePitchClick(), 1000); + // } else { + // clearInterval(interval); + // } + // return () => clearInterval(interval); + // }, [turn]) + return ( - PITCH + {isPitch && PITCH} {
    {player?.batter.name}
    - {player?.batter.at_bat || 0}타석 {player?.batter.safety || 0}안타 + {player?.batter.atBat || 0}타석 {player?.batter.plate_appearance || 0}안타
    diff --git a/fe/src/components/game-play/popup/roster/Roster.jsx b/fe/src/components/game-play/popup/roster/Roster.jsx index 5ab0e0433..d343efa70 100644 --- a/fe/src/components/game-play/popup/roster/Roster.jsx +++ b/fe/src/components/game-play/popup/roster/Roster.jsx @@ -1,11 +1,10 @@ import styled from 'styled-components'; import TeamRoster from './TeamRoster'; -const Roster = ({ memberList }) => { - // team_name 필요 +const Roster = ({ memberList, teamName, selectTeam }) => { return ( - - + + ); } diff --git a/fe/src/components/game-play/popup/roster/RosterPlayer.jsx b/fe/src/components/game-play/popup/roster/RosterPlayer.jsx index 6e37095aa..e3fbc2de4 100644 --- a/fe/src/components/game-play/popup/roster/RosterPlayer.jsx +++ b/fe/src/components/game-play/popup/roster/RosterPlayer.jsx @@ -1,15 +1,17 @@ import React from 'react'; +// const { atBat, plate_appearance, outCountCount } = member; -const RosterPlayer = ({ name, at_bat, safety, out, player_name }) => { - const getAverage = (at_bat, safety) => (safety / at_bat) ? (safety / at_bat).toFixed(3) : 0; +const RosterPlayer = ({ name, atBat, plate_appearance, outCount, player_name }) => { + + const getAverage = (atBat, plate_appearance) => (plate_appearance / atBat) ? (plate_appearance / atBat).toFixed(3) : 0; const class_name = 'roster--member' + (name === player_name ? ' active' : ''); return (
  • {name}
    -
    {at_bat}
    -
    {safety}
    -
    {out}
    -
    {getAverage(at_bat, safety)}
    +
    {atBat}
    +
    {plate_appearance}
    +
    {outCount}
    +
    {getAverage(atBat, plate_appearance)}
  • ); }; diff --git a/fe/src/components/game-play/popup/roster/TeamRoster.jsx b/fe/src/components/game-play/popup/roster/TeamRoster.jsx index 316e6fe15..e406e3357 100644 --- a/fe/src/components/game-play/popup/roster/TeamRoster.jsx +++ b/fe/src/components/game-play/popup/roster/TeamRoster.jsx @@ -1,25 +1,24 @@ import styled from 'styled-components'; import RosterPlayer from './RosterPlayer'; -const TeamRoster = ({ memberList, player = false }) => { +const TeamRoster = ({ memberList, teamName, selectTeam }) => { const player_name = 'abc'; - const team_name = '베리베리 스트로베리'; const HEADS = ['타자', '타석', '안타', '아웃', '평균']; const TOTALTEXT = 'Totals'; const heads = HEADS.map((head, idx) =>
    {head}
    ); let [totalAtBat, totalSafety, totalOut] = [0, 0, 0]; const members = memberList.map((member, idx) => { - const { at_bat, safety, out } = member; - totalAtBat += at_bat; - totalSafety += safety; - totalOut += out; + const { atBat, plate_appearance, outCount } = member; + totalAtBat += atBat; + totalSafety += plate_appearance; + totalOut += outCount; return }); return ( -
    {team_name} {player &&
    Player
    }
    +
    {teamName} {teamName === selectTeam &&
    Player
    }
    • {heads} diff --git a/fe/src/components/game-play/popup/score/Score.jsx b/fe/src/components/game-play/popup/score/Score.jsx index 09838eda7..ffa1dcaa7 100644 --- a/fe/src/components/game-play/popup/score/Score.jsx +++ b/fe/src/components/game-play/popup/score/Score.jsx @@ -9,7 +9,6 @@ const Score = ({ score, teamName, gameID }) => { const ROUND = new Array(12).fill().map((_, idx) => idx + 1); // const { data: score } = useFetch(SCORE_URL, 'get'); - console.log(score); return ( score && score.home && ( diff --git a/fe/src/components/game-play/score/Score.jsx b/fe/src/components/game-play/score/Score.jsx index 134a57770..b3a19e6e1 100644 --- a/fe/src/components/game-play/score/Score.jsx +++ b/fe/src/components/game-play/score/Score.jsx @@ -2,7 +2,7 @@ import { useContext } from 'react'; import styled from 'styled-components'; import { ScoreNBaseContext } from '../GamePlay'; -const Score = ({ teamName, turn }) => { +const Score = ({ teamName, selectTeam }) => { const { score } = useContext(ScoreNBaseContext); const TITLE = 'BASEBALL GAME ONLINE'; const TURN = 'Player'; @@ -16,7 +16,7 @@ const Score = ({ teamName, turn }) => {
      {teamName.home} - {turn &&
      {TURN}
      } + {teamName.home == selectTeam &&
      {TURN}
      }
      {homeScore}
      @@ -26,7 +26,7 @@ const Score = ({ teamName, turn }) => {
      {awayScore}
      {teamName.away} - {!turn &&
      {TURN}
      } + {teamName.away == selectTeam &&
      {TURN}
      }
    From 2ee108c3678e5fe91989aecb1ca994c48a379694 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Fri, 14 May 2021 12:21:10 +0900 Subject: [PATCH 20/22] =?UTF-8?q?feat::sparkles:=20fetch=20put,=20post?= =?UTF-8?q?=EC=9A=94=EC=B2=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-play/GamePlay.jsx | 99 ++++++++----------- fe/src/components/game-play/board/Board.jsx | 52 ++++++++-- fe/src/components/game-play/board/Screen.jsx | 40 ++++---- .../game-play/popup/score/ScoreList.jsx | 4 +- fe/src/components/game-play/score/Score.jsx | 5 +- fe/src/util/api.js | 27 +++-- 6 files changed, 128 insertions(+), 99 deletions(-) diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index 2ec3cc24a..49bbaa854 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -12,6 +12,7 @@ import { fetchPUT } from '../../util/api.js'; import useFetch from '../../hooks/useFetch'; export const ScoreNBaseContext = createContext(); +export const GameIdContext = createContext(); const MemberListContext = createContext(); const DATA_PLAYER_URL = 'http://52.78.184.142'; @@ -27,18 +28,6 @@ const memberListReducer = (state, action) => { else plate_appearance++; atBat++; next = idx + 1 === arr.length ? 0 : idx + 1; - - // put: /players/{player_id} - - /* - const { data: result } = useFetch(DATA_PLAYER_URL + '/players/' + member.id, 'put', { - local - }); - */ - // { - // "game_id": 6, - // "atBat": true // true: 안타, false: 아웃 - // } return { ...member, plate_appearance, atBat, outCount, status: !status }; } else { return { ...member }; @@ -92,6 +81,10 @@ const GamePlay = ({ home, away, game_id }) => { }); console.log(gamePlayData); const [memberList, memberListDispatch] = useReducer(memberListReducer, null); + const teamId = { + home: gamePlayData?.home?.teamId, + away: gamePlayData?.away?.teamId, + }; const teamName = { home: gamePlayData?.home?.name, away: gamePlayData?.away?.name, @@ -106,6 +99,7 @@ const GamePlay = ({ home, away, game_id }) => { home: gamePlayData?.home?.member_list, away: gamePlayData?.away?.member_list, }; + setInning({ turn: gamePlayData?.turn || true, round: gamePlayData?.round || 1 }); memberListDispatch({ type: 'init', value: memberListData }); }, [gamePlayData]); @@ -119,53 +113,42 @@ const GamePlay = ({ home, away, game_id }) => { } }, [memberList]); - useEffect(() => { - // post:/games/{game_id} - // console.log(inning, memberList); - // const { data: result } = useFetch(DATA_PLAYER_URL + '/games/' + game_id, 'put', { - // game_id, - // "team_id": 1, 종료된 팀 아이디 - // "round" : 3, 종료된 라운드 - // "player_id": 3, 마지막 아웃 된 타자 - // }); - // { - // "game_id": 6, - // "atBat": true // true: 안타, false: 아웃 - // } - }, [inning]); - return ( - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + ); }; diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index 1597761eb..d7a0b0ad7 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -3,8 +3,11 @@ import { useState, useReducer, useContext, useEffect } from 'react'; import BallCount from './BallCount'; import Inning from './Inning'; import Screen from './Screen'; -import { ScoreNBaseContext } from '../GamePlay'; -import { fetchPUT } from '../../../util/api.js'; +import { GameIdContext, ScoreNBaseContext } from '../GamePlay'; +import { fetchPUT, fetchPOST } from '../../../util/api.js'; +import useFetch from '../../../hooks/useFetch'; + +const URL = 'http://52.78.184.142'; const ballCountReducer = (state, action) => { let newState = { ...state }; @@ -39,18 +42,30 @@ const Board = ({ logListDispatch, game_id, teamName, + teamId, selectTeam, + memberList, }) => { const [ballCount, ballCountDispatch] = useReducer(ballCountReducer, { strike: 0, ball: 0, out: 0, }); - const { safetyDispatch } = useContext(ScoreNBaseContext); + const { score, base, safetyDispatch } = useContext(ScoreNBaseContext); + const { gameID } = useContext(GameIdContext); + + const getPlayerId = () => memberList[inning.turn ? 'home' : 'away'].find((v) => v.status)?.id; + + const currentRoundScore = { + game_id: gameID, + home: score.home[inning.round - 1], + away: score.away[inning.round - 1] + 1 || null, + round: inning.round, + }; + const handleStrike = () => { if (ballCount.strike === 2) { handleOut(); - //3번 API fetch { "game_id": 6, "at_bat": false } //game_id는 컨텍스트 사용 } else { ballCountDispatch({ type: 'strike' }); logListDispatch({ type: 'strike', ...ballCount, strike: ballCount.strike + 1 }); @@ -58,25 +73,39 @@ const Board = ({ }; const handleBall = () => { if (ballCount.ball === 3) { + if (base[3]) { + //4번 API {"game_id": 7,"home": 1,"away": 2, "round": 3} 모든정보 컨텍스트로 + fetchPUT(`${URL}/games/${gameID}`, currentRoundScore); + } + const playerId = getPlayerId(); + fetchPUT(`${URL}/players/${playerId}`, { game_id: gameID, at_bat: true }); ballCountDispatch({ type: 'safety' }); logListDispatch({ type: '4ball', end: true }); memberListDispatch({ type: 'safety', turn: inning.turn, game_id }); - //3번 API fetch { "game_id": 6, "at_bat": true } } else { ballCountDispatch({ type: 'ball' }); logListDispatch({ type: 'ball', ...ballCount, ball: ballCount.ball + 1 }); } }; const handleOut = () => { + const playerId = getPlayerId(); if (ballCount.out === 2) { //7번 API { "game_id": 6, "team_id":1, "round":3, "at_bat": 3 } ??타자를 번호를 보내는거네??? // 여기에 공수교대 + // + fetchPOST(`${URL}/games/${gameID}`, { + game_id: gameID, + round: inning.round, + player_id: playerId, + team_id: inning.turn ? teamId.home : teamId.away, + }); ballCountDispatch({ type: 'clear' }); if (inning.turn) setInning({ ...inning, turn: !inning.turn }); else setInning({ ...inning, round: inning.round + 1, turn: !inning.turn }); safetyDispatch({ type: 'clear', turn: !inning.turn }); logListDispatch({ type: 'clear' }); } else { + fetchPUT(`${URL}/players/${playerId}`, { game_id: gameID, at_bat: false }); logListDispatch({ type: 'out', end: true }); ballCountDispatch({ type: 'out' }); } @@ -84,16 +113,21 @@ const Board = ({ memberListDispatch({ type: 'out', turn: inning.turn, game_id }); }; const handleSafety = () => { - //3번 API fetch { "game_id": 6, "at_bat": true } + if (base[3]) { + //4번 API {"game_id": 7,"home": 1,"away": 2, "round": 3} 모든정보 컨텍스트로 + fetchPUT(`${URL}/games/${gameID}`, currentRoundScore); + } + const playerId = getPlayerId(); + fetchPUT(`${URL}/players/${playerId}`, { game_id: gameID, at_bat: true }); ballCountDispatch({ type: 'safety' }); // 멤버 안타 1, 타석 1 증가 memberListDispatch({ type: 'safety', turn: inning.turn, game_id }); logListDispatch({ type: 'safety', end: true }); }; - useEffect(() => { - return () => fetchPUT(inning); - }, [inning]); + // useEffect(() => { + // return () => fetchPUT(inning); + // }, [inning]); return ( diff --git a/fe/src/components/game-play/board/Screen.jsx b/fe/src/components/game-play/board/Screen.jsx index adc061bc7..f5e8ce6a7 100644 --- a/fe/src/components/game-play/board/Screen.jsx +++ b/fe/src/components/game-play/board/Screen.jsx @@ -40,9 +40,6 @@ const Screen = ({ } else if (randomNum <= 80) { //볼 if (ballCount.ball === 3) { - if (base[3]) { - //4번 API {"game_id": 7,"home": 1,"away": 2, "round": 3} 모든정보 컨텍스트로 - } setCurrentPower(1); setIsTransition(true); setRunFirstBase(true); @@ -50,7 +47,6 @@ const Screen = ({ handleBall(); } else { //안타 - //4번 API {"game_id": 7,"home": 1,"away": 2, "round": 3} 모든정보 컨텍스트로 setIsTransition(true); setRunFirstBase(true); handleSafety(); @@ -80,25 +76,25 @@ const Screen = ({ const savedCallback = useRef(); - function callback() { - handlePitchClick(); - } + // function callback() { + // handlePitchClick(); + // } - useEffect(() => { - savedCallback.current = callback; - }); + // useEffect(() => { + // savedCallback.current = callback; + // }); - useEffect(() => { - function tick() { - savedCallback.current(); - } - if (!isPitch) { - let id = setInterval(tick, 1000); - return () => clearInterval(id); - } else { - return null; - } - }, []); + // useEffect(() => { + // function tick() { + // savedCallback.current(); + // } + // if (!isPitch) { + // let id = setInterval(tick, 1000); + // return () => clearInterval(id); + // } else { + // return null; + // } + // }, []); // useEffect(() => { // let interval = setInterval(() => handlePitchClick(), 1000); @@ -113,7 +109,7 @@ const Screen = ({ return ( - {isPitch && PITCH} + PITCH { const StyledScore = styled.div` .title { - font-size: 2rem; + font-size: 2.5rem; font-weight: 600; color: #fff; text-align: center; @@ -54,13 +54,14 @@ const StyledScore = styled.div` display: flex; justify-content: center; align-items: center; - font-size: 5rem; + font-size: 3rem; } .teams-vs { font-size: 4rem; color: #777; } .teams-name { + font-size: 3rem; position: relative; } .turn { diff --git a/fe/src/util/api.js b/fe/src/util/api.js index 360c5adee..18a1973d9 100644 --- a/fe/src/util/api.js +++ b/fe/src/util/api.js @@ -1,8 +1,5 @@ -const fetchPUT = async (data) => { - // 현재 미사용 - console.log(data); - if (true) return; - const result = await fetch('/path', { +const fetchPUT = async (url, data) => { + const result = await fetch(url, { method: 'PUT', headers: { 'Content-Type': 'application/json', @@ -12,4 +9,22 @@ const fetchPUT = async (data) => { console.log(result); }; -export { fetchPUT }; +const fetchGET = async (url) => { + const result = await fetch(url); + const data = await result.json(); + return data; +}; + +const fetchPOST = async (url, data) => { + console.log(data); + const result = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + console.log(result); +}; + +export { fetchPUT, fetchGET, fetchPOST }; From cade1412272a6e7d69b7bdf64840fd9249701d19 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Fri, 14 May 2021 14:50:23 +0900 Subject: [PATCH 21/22] =?UTF-8?q?feat::sparkles:=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/src/components/game-list/GameListItem.jsx | 11 +++- fe/src/components/game-play/GamePlay.jsx | 1 - fe/src/components/game-play/board/Board.jsx | 4 +- fe/src/components/game-play/log/Log.jsx | 56 ++++++++++---------- fe/src/components/game-play/score/Score.jsx | 7 +-- 5 files changed, 43 insertions(+), 36 deletions(-) diff --git a/fe/src/components/game-list/GameListItem.jsx b/fe/src/components/game-list/GameListItem.jsx index f8b0c0fcb..4333e45ea 100644 --- a/fe/src/components/game-list/GameListItem.jsx +++ b/fe/src/components/game-list/GameListItem.jsx @@ -4,10 +4,10 @@ import { Link } from 'react-router-dom'; const GameListItem = ({ home, away, id, idx }) => { const path = `games/${id}`; - const onClick = e => { + const onClick = (e) => { localStorage.setItem('select', e.target.textContent); localStorage.setItem('teams', JSON.stringify({ home, away })); - } + }; return (
    GAME {idx + 1}
    @@ -56,6 +56,13 @@ const StyledGameItem = styled.div` font-weight: 600; color: #777; } + a { + text-decoration: none; + color: #000; + } + a:visited { + color: #000; + } } `; diff --git a/fe/src/components/game-play/GamePlay.jsx b/fe/src/components/game-play/GamePlay.jsx index 49bbaa854..9ecf9d26a 100644 --- a/fe/src/components/game-play/GamePlay.jsx +++ b/fe/src/components/game-play/GamePlay.jsx @@ -79,7 +79,6 @@ const GamePlay = ({ home, away, game_id }) => { score: { home: [0], away: [] }, base: undefined, }); - console.log(gamePlayData); const [memberList, memberListDispatch] = useReducer(memberListReducer, null); const teamId = { home: gamePlayData?.home?.teamId, diff --git a/fe/src/components/game-play/board/Board.jsx b/fe/src/components/game-play/board/Board.jsx index d7a0b0ad7..a7c4cf270 100644 --- a/fe/src/components/game-play/board/Board.jsx +++ b/fe/src/components/game-play/board/Board.jsx @@ -58,8 +58,8 @@ const Board = ({ const currentRoundScore = { game_id: gameID, - home: score.home[inning.round - 1], - away: score.away[inning.round - 1] + 1 || null, + home: score.home[inning.round - 1] + inning.turn, + away: !inning.turn ? score.away[inning.round - 1] + 1 : null, round: inning.round, }; diff --git a/fe/src/components/game-play/log/Log.jsx b/fe/src/components/game-play/log/Log.jsx index ad029a20d..3891328be 100644 --- a/fe/src/components/game-play/log/Log.jsx +++ b/fe/src/components/game-play/log/Log.jsx @@ -1,42 +1,43 @@ import styled from 'styled-components'; const TYPE = { - 'strike': '스트라이크', - 'ball': '볼', - 'safety': '안타', + strike: '스트라이크', + ball: '볼', + safety: '안타', '4ball': '볼넷', - 'out': '아웃', -} + out: '아웃', +}; const Log = ({ logList }) => { const logs = logList.map((member, i) => ( - member.history.length > 0 && -
    -
    {member.index}번 타자 {member.name}
    -
    - { member.history.map((v, i) => - v.end - ? -
    -
    -
    {TYPE[v.type]}!
    -
    -
    - : -
    -
    {i + 1}
    -
    {TYPE[v.type]}
    -
    S{v.strike} B{v.ball}
    -
    +
    +
    + {member.index}번 타자 {member.name} +
    +
    + {member.history.map((v, i) => + v.end ? ( +
    +
    +
    {TYPE[v.type]}!
    +
    +
    + ) : ( +
    +
    {i + 1}
    +
    {TYPE[v.type]}
    +
    + S{v.strike} B{v.ball} +
    +
    + ) )}
    )); return ( -
    - {logs} -
    +
    {logs}
    ); }; @@ -97,7 +98,6 @@ const StyledLog = styled.div` color: #ff4545; } } - `; -export default Log; \ No newline at end of file +export default Log; diff --git a/fe/src/components/game-play/score/Score.jsx b/fe/src/components/game-play/score/Score.jsx index 812e4538b..ef8f45b0d 100644 --- a/fe/src/components/game-play/score/Score.jsx +++ b/fe/src/components/game-play/score/Score.jsx @@ -52,7 +52,6 @@ const StyledScore = styled.div` .home, .away { display: flex; - justify-content: center; align-items: center; font-size: 3rem; } @@ -73,13 +72,15 @@ const StyledScore = styled.div` } } .home { + justify-content: flex-end; .teams-score { - margin-left: 3rem; + margin: 0 3rem; } } .away { + justify-content: flex-start; .teams-score { - margin-right: 3rem; + margin: 0 3rem; } } `; From a4b5fda275129da7b6a340f101856be49157f694 Mon Sep 17 00:00:00 2001 From: hayoung123 <67357426+hayoung123@users.noreply.github.com> Date: Fri, 14 May 2021 15:51:53 +0900 Subject: [PATCH 22/22] =?UTF-8?q?Build.=20=EB=B9=8C=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fe/.gitignore | 2 - fe/build/asset-manifest.json | 24 +++++++++ fe/build/favicon.ico | Bin 0 -> 3870 bytes fe/build/index.html | 1 + fe/build/static/css/2.679831fc.chunk.css | 2 + fe/build/static/css/2.679831fc.chunk.css.map | 1 + fe/build/static/css/main.4c1ffa95.chunk.css | 2 + .../static/css/main.4c1ffa95.chunk.css.map | 1 + fe/build/static/js/2.b91792ed.chunk.js | 3 ++ .../static/js/2.b91792ed.chunk.js.LICENSE.txt | 50 ++++++++++++++++++ fe/build/static/js/2.b91792ed.chunk.js.map | 1 + fe/build/static/js/main.1bcfabba.chunk.js | 2 + fe/build/static/js/main.1bcfabba.chunk.js.map | 1 + fe/build/static/js/runtime-main.8ce5e419.js | 2 + .../static/js/runtime-main.8ce5e419.js.map | 1 + fe/build/static/media/background.9127295c.png | Bin 0 -> 522717 bytes 16 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 fe/build/asset-manifest.json create mode 100644 fe/build/favicon.ico create mode 100644 fe/build/index.html create mode 100644 fe/build/static/css/2.679831fc.chunk.css create mode 100644 fe/build/static/css/2.679831fc.chunk.css.map create mode 100644 fe/build/static/css/main.4c1ffa95.chunk.css create mode 100644 fe/build/static/css/main.4c1ffa95.chunk.css.map create mode 100644 fe/build/static/js/2.b91792ed.chunk.js create mode 100644 fe/build/static/js/2.b91792ed.chunk.js.LICENSE.txt create mode 100644 fe/build/static/js/2.b91792ed.chunk.js.map create mode 100644 fe/build/static/js/main.1bcfabba.chunk.js create mode 100644 fe/build/static/js/main.1bcfabba.chunk.js.map create mode 100644 fe/build/static/js/runtime-main.8ce5e419.js create mode 100644 fe/build/static/js/runtime-main.8ce5e419.js.map create mode 100644 fe/build/static/media/background.9127295c.png diff --git a/fe/.gitignore b/fe/.gitignore index 4d29575de..3efc6cac7 100644 --- a/fe/.gitignore +++ b/fe/.gitignore @@ -8,8 +8,6 @@ # testing /coverage -# production -/build # misc .DS_Store diff --git a/fe/build/asset-manifest.json b/fe/build/asset-manifest.json new file mode 100644 index 000000000..d2663593f --- /dev/null +++ b/fe/build/asset-manifest.json @@ -0,0 +1,24 @@ +{ + "files": { + "main.css": "/static/css/main.4c1ffa95.chunk.css", + "main.js": "/static/js/main.1bcfabba.chunk.js", + "main.js.map": "/static/js/main.1bcfabba.chunk.js.map", + "runtime-main.js": "/static/js/runtime-main.8ce5e419.js", + "runtime-main.js.map": "/static/js/runtime-main.8ce5e419.js.map", + "static/css/2.679831fc.chunk.css": "/static/css/2.679831fc.chunk.css", + "static/js/2.b91792ed.chunk.js": "/static/js/2.b91792ed.chunk.js", + "static/js/2.b91792ed.chunk.js.map": "/static/js/2.b91792ed.chunk.js.map", + "index.html": "/index.html", + "static/css/2.679831fc.chunk.css.map": "/static/css/2.679831fc.chunk.css.map", + "static/css/main.4c1ffa95.chunk.css.map": "/static/css/main.4c1ffa95.chunk.css.map", + "static/js/2.b91792ed.chunk.js.LICENSE.txt": "/static/js/2.b91792ed.chunk.js.LICENSE.txt", + "static/media/background.9127295c.png": "/static/media/background.9127295c.png" + }, + "entrypoints": [ + "static/js/runtime-main.8ce5e419.js", + "static/css/2.679831fc.chunk.css", + "static/js/2.b91792ed.chunk.js", + "static/css/main.4c1ffa95.chunk.css", + "static/js/main.1bcfabba.chunk.js" + ] +} \ No newline at end of file diff --git a/fe/build/favicon.ico b/fe/build/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 zcma);c{J4h9>;%nil|2-o+rCuEF-(I%-F}ijC~o(k~HKAkr0)!FCj~d>`RtpD?8b; zXOC1OD!V*IsqUwzbMF1)-gEDD=A573Z-&G7^LoAC9|WO7Xc0Cx1g^Zu0u_SjAPB3vGa^W|sj)80f#V0@M_CAZTIO(t--xg= z!sii`1giyH7EKL_+Wi0ab<)&E_0KD!3Rp2^HNB*K2@PHCs4PWSA32*-^7d{9nH2_E zmC{C*N*)(vEF1_aMamw2A{ZH5aIDqiabnFdJ|y0%aS|64E$`s2ccV~3lR!u<){eS` z#^Mx6o(iP1Ix%4dv`t@!&Za-K@mTm#vadc{0aWDV*_%EiGK7qMC_(`exc>-$Gb9~W!w_^{*pYRm~G zBN{nA;cm^w$VWg1O^^<6vY`1XCD|s_zv*g*5&V#wv&s#h$xlUilPe4U@I&UXZbL z0)%9Uj&@yd03n;!7do+bfixH^FeZ-Ema}s;DQX2gY+7g0s(9;`8GyvPY1*vxiF&|w z>!vA~GA<~JUqH}d;DfBSi^IT*#lrzXl$fNpq0_T1tA+`A$1?(gLb?e#0>UELvljtQ zK+*74m0jn&)5yk8mLBv;=@}c{t0ztT<v;Avck$S6D`Z)^c0(jiwKhQsn|LDRY&w(Fmi91I7H6S;b0XM{e zXp0~(T@k_r-!jkLwd1_Vre^v$G4|kh4}=Gi?$AaJ)3I+^m|Zyj#*?Kp@w(lQdJZf4 z#|IJW5z+S^e9@(6hW6N~{pj8|NO*>1)E=%?nNUAkmv~OY&ZV;m-%?pQ_11)hAr0oAwILrlsGawpxx4D43J&K=n+p3WLnlDsQ$b(9+4 z?mO^hmV^F8MV{4Lx>(Q=aHhQ1){0d*(e&s%G=i5rq3;t{JC zmgbn5Nkl)t@fPH$v;af26lyhH!k+#}_&aBK4baYPbZy$5aFx4}ka&qxl z$=Rh$W;U)>-=S-0=?7FH9dUAd2(q#4TCAHky!$^~;Dz^j|8_wuKc*YzfdAht@Q&ror?91Dm!N03=4=O!a)I*0q~p0g$Fm$pmr$ zb;wD;STDIi$@M%y1>p&_>%?UP($15gou_ue1u0!4(%81;qcIW8NyxFEvXpiJ|H4wz z*mFT(qVx1FKufG11hByuX%lPk4t#WZ{>8ka2efjY`~;AL6vWyQKpJun2nRiZYDij$ zP>4jQXPaP$UC$yIVgGa)jDV;F0l^n(V=HMRB5)20V7&r$jmk{UUIe zVjKroK}JAbD>B`2cwNQ&GDLx8{pg`7hbA~grk|W6LgiZ`8y`{Iq0i>t!3p2}MS6S+ zO_ruKyAElt)rdS>CtF7j{&6rP-#c=7evGMt7B6`7HG|-(WL`bDUAjyn+k$mx$CH;q2Dz4x;cPP$hW=`pFfLO)!jaCL@V2+F)So3}vg|%O*^T1j>C2lx zsURO-zIJC$^$g2byVbRIo^w>UxK}74^TqUiRR#7s_X$e)$6iYG1(PcW7un-va-S&u zHk9-6Zn&>T==A)lM^D~bk{&rFzCi35>UR!ZjQkdSiNX*-;l4z9j*7|q`TBl~Au`5& z+c)*8?#-tgUR$Zd%Q3bs96w6k7q@#tUn`5rj+r@_sAVVLqco|6O{ILX&U-&-cbVa3 zY?ngHR@%l{;`ri%H*0EhBWrGjv!LE4db?HEWb5mu*t@{kv|XwK8?npOshmzf=vZA@ zVSN9sL~!sn?r(AK)Q7Jk2(|M67Uy3I{eRy z_l&Y@A>;vjkWN5I2xvFFTLX0i+`{qz7C_@bo`ZUzDugfq4+>a3?1v%)O+YTd6@Ul7 zAfLfm=nhZ`)P~&v90$&UcF+yXm9sq!qCx3^9gzIcO|Y(js^Fj)Rvq>nQAHI92ap=P z10A4@prk+AGWCb`2)dQYFuR$|H6iDE8p}9a?#nV2}LBCoCf(Xi2@szia7#gY>b|l!-U`c}@ zLdhvQjc!BdLJvYvzzzngnw51yRYCqh4}$oRCy-z|v3Hc*d|?^Wj=l~18*E~*cR_kU z{XsxM1i{V*4GujHQ3DBpl2w4FgFR48Nma@HPgnyKoIEY-MqmMeY=I<%oG~l!f<+FN z1ZY^;10j4M4#HYXP zw5eJpA_y(>uLQ~OucgxDLuf}fVs272FaMxhn4xnDGIyLXnw>Xsd^J8XhcWIwIoQ9} z%FoSJTAGW(SRGwJwb=@pY7r$uQRK3Zd~XbxU)ts!4XsJrCycrWSI?e!IqwqIR8+Jh zlRjZ`UO1I!BtJR_2~7AbkbSm%XQqxEPkz6BTGWx8e}nQ=w7bZ|eVP4?*Tb!$(R)iC z9)&%bS*u(lXqzitAN)Oo=&Ytn>%Hzjc<5liuPi>zC_nw;Z0AE3Y$Jao_Q90R-gl~5 z_xAb2J%eArrC1CN4G$}-zVvCqF1;H;abAu6G*+PDHSYFx@Tdbfox*uEd3}BUyYY-l zTfEsOqsi#f9^FoLO;ChK<554qkri&Av~SIM*{fEYRE?vH7pTAOmu2pz3X?Wn*!ROX ztd54huAk&mFBemMooL33RV-*1f0Q3_(7hl$<#*|WF9P!;r;4_+X~k~uKEqdzZ$5Al zV63XN@)j$FN#cCD;ek1R#l zv%pGrhB~KWgoCj%GT?%{@@o(AJGt*PG#l3i>lhmb_twKH^EYvacVY-6bsCl5*^~L0 zonm@lk2UvvTKr2RS%}T>^~EYqdL1q4nD%0n&Xqr^cK^`J5W;lRRB^R-O8b&HENO||mo0xaD+S=I8RTlIfVgqN@SXDr2&-)we--K7w= zJVU8?Z+7k9dy;s;^gDkQa`0nz6N{T?(A&Iz)2!DEecLyRa&FI!id#5Z7B*O2=PsR0 zEvc|8{NS^)!d)MDX(97Xw}m&kEO@5jqRaDZ!+%`wYOI<23q|&js`&o4xvjP7D_xv@ z5hEwpsp{HezI9!~6O{~)lLR@oF7?J7i>1|5a~UuoN=q&6N}EJPV_GD`&M*v8Y`^2j zKII*d_@Fi$+i*YEW+Hbzn{iQk~yP z>7N{S4)r*!NwQ`(qcN#8SRQsNK6>{)X12nbF`*7#ecO7I)Q$uZsV+xS4E7aUn+U(K baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/fe/build/index.html b/fe/build/index.html new file mode 100644 index 000000000..b97d43d3b --- /dev/null +++ b/fe/build/index.html @@ -0,0 +1 @@ +React App
    \ No newline at end of file diff --git a/fe/build/static/css/2.679831fc.chunk.css b/fe/build/static/css/2.679831fc.chunk.css new file mode 100644 index 000000000..15fd7d9fc --- /dev/null +++ b/fe/build/static/css/2.679831fc.chunk.css @@ -0,0 +1,2 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none} +/*# sourceMappingURL=2.679831fc.chunk.css.map */ \ No newline at end of file diff --git a/fe/build/static/css/2.679831fc.chunk.css.map b/fe/build/static/css/2.679831fc.chunk.css.map new file mode 100644 index 000000000..85c1c537d --- /dev/null +++ b/fe/build/static/css/2.679831fc.chunk.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack://node_modules/normalize.css/normalize.css"],"names":[],"mappings":"AAAA,2EAA2E,CAU3E,KACE,gBAAiB,CACjB,6BACF,CASA,KACE,QACF,CAMA,KACE,aACF,CAOA,GACE,aAAc,CACd,cACF,CAUA,GACE,sBAAuB,CACvB,QAAS,CACT,gBACF,CAOA,IACE,+BAAiC,CACjC,aACF,CASA,EACE,4BACF,CAOA,YACE,kBAAmB,CACnB,yBAA0B,CAC1B,wCAAiC,CAAjC,gCACF,CAMA,SAEE,kBACF,CAOA,cAGE,+BAAiC,CACjC,aACF,CAMA,MACE,aACF,CAOA,QAEE,aAAc,CACd,aAAc,CACd,iBAAkB,CAClB,uBACF,CAEA,IACE,aACF,CAEA,IACE,SACF,CASA,IACE,iBACF,CAUA,sCAKE,mBAAoB,CACpB,cAAe,CACf,gBAAiB,CACjB,QACF,CAOA,aAEE,gBACF,CAOA,cAEE,mBACF,CAMA,gDAIE,yBACF,CAMA,wHAIE,iBAAkB,CAClB,SACF,CAMA,4GAIE,6BACF,CAMA,SACE,0BACF,CASA,OACE,qBAAsB,CACtB,aAAc,CACd,aAAc,CACd,cAAe,CACf,SAAU,CACV,kBACF,CAMA,SACE,uBACF,CAMA,SACE,aACF,CAOA,6BAEE,qBAAsB,CACtB,SACF,CAMA,kFAEE,WACF,CAOA,cACE,4BAA6B,CAC7B,mBACF,CAMA,yCACE,uBACF,CAOA,6BACE,yBAA0B,CAC1B,YACF,CASA,QACE,aACF,CAMA,QACE,iBACF,CAiBA,kBACE,YACF","file":"2.679831fc.chunk.css","sourcesContent":["/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box; /* 1 */\n height: 0; /* 1 */\n overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none; /* 1 */\n text-decoration: underline; /* 2 */\n text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-size: 100%; /* 1 */\n line-height: 1.15; /* 1 */\n margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput { /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect { /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box; /* 1 */\n color: inherit; /* 2 */\n display: table; /* 1 */\n max-width: 100%; /* 1 */\n padding: 0; /* 3 */\n white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}\n"]} \ No newline at end of file diff --git a/fe/build/static/css/main.4c1ffa95.chunk.css b/fe/build/static/css/main.4c1ffa95.chunk.css new file mode 100644 index 000000000..1197f3010 --- /dev/null +++ b/fe/build/static/css/main.4c1ffa95.chunk.css @@ -0,0 +1,2 @@ +*{box-sizing:border-box}body{margin:0;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} +/*# sourceMappingURL=main.4c1ffa95.chunk.css.map */ \ No newline at end of file diff --git a/fe/build/static/css/main.4c1ffa95.chunk.css.map b/fe/build/static/css/main.4c1ffa95.chunk.css.map new file mode 100644 index 000000000..58aa8a599 --- /dev/null +++ b/fe/build/static/css/main.4c1ffa95.chunk.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack://src/index.css"],"names":[],"mappings":"AAAA,EACE,qBACF,CAEA,KACE,QAAS,CACT,eAAgB,CAChB,mJAEY,CACZ,kCAAmC,CACnC,iCACF","file":"main.4c1ffa95.chunk.css","sourcesContent":["* {\r\n box-sizing: border-box;\r\n}\r\n\r\nbody {\r\n margin: 0;\r\n overflow: hidden;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\r\n 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\r\n sans-serif;\r\n -webkit-font-smoothing: antialiased;\r\n -moz-osx-font-smoothing: grayscale;\r\n}\r\n"]} \ No newline at end of file diff --git a/fe/build/static/js/2.b91792ed.chunk.js b/fe/build/static/js/2.b91792ed.chunk.js new file mode 100644 index 000000000..be6786353 --- /dev/null +++ b/fe/build/static/js/2.b91792ed.chunk.js @@ -0,0 +1,3 @@ +/*! For license information please see 2.b91792ed.chunk.js.LICENSE.txt */ +(this.webpackJsonpbaseball=this.webpackJsonpbaseball||[]).push([[2],[function(e,t,n){"use strict";e.exports=n(42)},function(e,t,n){"use strict";e.exports=n(35)},function(e,t,n){"use strict";function r(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";(function(e){n.d(t,"b",(function(){return Ne}));var r=n(19),o=n(1),a=n.n(o),i=n(31),l=n.n(i),u=n(32),c=n(33),s=n(27),f=n(25),d=n.n(f);function p(){return(p=Object.assign||function(e){for(var t=1;t1?t-1:0),r=1;r0?" Args: "+n.join(", "):""))}var C=function(){function e(e){this.groupSizes=new Uint32Array(512),this.length=512,this.tag=e}var t=e.prototype;return t.indexOfGroup=function(e){for(var t=0,n=0;n=this.groupSizes.length){for(var n=this.groupSizes,r=n.length,o=r;e>=o;)(o<<=1)<0&&x(16,""+e);this.groupSizes=new Uint32Array(o),this.groupSizes.set(n),this.length=o;for(var a=r;a=this.length||0===this.groupSizes[e])return t;for(var n=this.groupSizes[e],r=this.indexOfGroup(e),o=r+n,a=r;a=0;n--){var r=t[n];if(r&&1===r.nodeType&&r.hasAttribute(k))return r}}(n),a=void 0!==o?o.nextSibling:null;r.setAttribute(k,"active"),r.setAttribute("data-styled-version","5.2.3");var i=z();return i&&r.setAttribute("nonce",i),n.insertBefore(r,a),r},M=function(){function e(e){var t=this.element=D(e);t.appendChild(document.createTextNode("")),this.sheet=function(e){if(e.sheet)return e.sheet;for(var t=document.styleSheets,n=0,r=t.length;n=0){var n=document.createTextNode(t),r=this.nodes[e];return this.element.insertBefore(n,r||null),this.length++,!0}return!1},t.deleteRule=function(e){this.element.removeChild(this.nodes[e]),this.length--},t.getRule=function(e){return e0&&(c+=e+",")})),r+=""+l+u+'{content:"'+c+'"}/*!sc*/\n'}}}return r}(this)},e}(),B=/(a)(d)/gi,V=function(e){return String.fromCharCode(e+(e>25?39:97))};function K(e){var t,n="";for(t=Math.abs(e);t>52;t=t/52|0)n=V(t%52)+n;return(V(t%52)+n).replace(B,"$1-$2")}var Q=function(e,t){for(var n=t.length;n;)e=33*e^t.charCodeAt(--n);return e},q=function(e){return Q(5381,e)};function Y(e){for(var t=0;t>>0);if(!t.hasNameForId(r,i)){var l=n(a,"."+i,void 0,r);t.insertRules(r,i,l)}o.push(i),this.staticRulesId=i}else{for(var u=this.rules.length,c=Q(this.baseHash,n.hash),s="",f=0;f>>0);if(!t.hasNameForId(r,m)){var v=n(s,"."+m,void 0,r);t.insertRules(r,m,v)}o.push(m)}}return o.join(" ")},e}(),J=/^\s*\/\/.*$/gm,Z=[":","[",".","#"];function ee(e){var t,n,r,o,a=void 0===e?y:e,i=a.options,l=void 0===i?y:i,c=a.plugins,s=void 0===c?v:c,f=new u.a(l),d=[],p=function(e){function t(t){if(t)try{e(t+"}")}catch(e){}}return function(n,r,o,a,i,l,u,c,s,f){switch(n){case 1:if(0===s&&64===r.charCodeAt(0))return e(r+";"),"";break;case 2:if(0===c)return r+"/*|*/";break;case 3:switch(c){case 102:case 112:return e(o[0]+r),"";default:return r+(0===f?"/*|*/":"")}case-2:r.split("/*|*/}").forEach(t)}}}((function(e){d.push(e)})),h=function(e,r,a){return 0===r&&-1!==Z.indexOf(a[n.length])||a.match(o)?e:"."+t};function m(e,a,i,l){void 0===l&&(l="&");var u=e.replace(J,""),c=a&&i?i+" "+a+" { "+u+" }":u;return t=l,n=a,r=new RegExp("\\"+n+"\\b","g"),o=new RegExp("(\\"+n+"\\b){2,}"),f(i||!a?"":a,c)}return f.use([].concat(s,[function(e,t,o){2===e&&o.length&&o[0].lastIndexOf(n)>0&&(o[0]=o[0].replace(r,h))},p,function(e){if(-2===e){var t=d;return d=[],t}}])),m.hash=s.length?s.reduce((function(e,t){return t.name||x(15),Q(e,t.name)}),5381).toString():"",m}var te=a.a.createContext(),ne=(te.Consumer,a.a.createContext()),re=(ne.Consumer,new H),oe=ee();function ae(){return Object(o.useContext)(te)||re}function ie(){return Object(o.useContext)(ne)||oe}function le(e){var t=Object(o.useState)(e.stylisPlugins),n=t[0],r=t[1],i=ae(),u=Object(o.useMemo)((function(){var t=i;return e.sheet?t=e.sheet:e.target&&(t=t.reconstructWithOptions({target:e.target},!1)),e.disableCSSOMInjection&&(t=t.reconstructWithOptions({useCSSOMInjection:!1})),t}),[e.disableCSSOMInjection,e.sheet,e.target]),c=Object(o.useMemo)((function(){return ee({options:{prefix:!e.disableVendorPrefixes},plugins:n})}),[e.disableVendorPrefixes,n]);return Object(o.useEffect)((function(){l()(n,e.stylisPlugins)||r(e.stylisPlugins)}),[e.stylisPlugins]),a.a.createElement(te.Provider,{value:u},a.a.createElement(ne.Provider,{value:c},e.children))}var ue=function(){function e(e,t){var n=this;this.inject=function(e,t){void 0===t&&(t=oe);var r=n.name+t.hash;e.hasNameForId(n.id,r)||e.insertRules(n.id,r,t(n.rules,r,"@keyframes"))},this.toString=function(){return x(12,String(n.name))},this.name=e,this.id="sc-keyframes-"+e,this.rules=t}return e.prototype.getName=function(e){return void 0===e&&(e=oe),this.name+e.hash},e}(),ce=/([A-Z])/,se=/([A-Z])/g,fe=/^ms-/,de=function(e){return"-"+e.toLowerCase()};function pe(e){return ce.test(e)?e.replace(se,de).replace(fe,"-ms-"):e}var he=function(e){return null==e||!1===e||""===e};function me(e,t,n,r){if(Array.isArray(e)){for(var o,a=[],i=0,l=e.length;i1?t-1:0),r=1;r?@[\\\]^`{|}~-]+/g,be=/(^-|-$)/g;function we(e){return e.replace(ge,"-").replace(be,"")}var ke=function(e){return K(q(e)>>>0)};function Se(e){return"string"==typeof e&&!0}var Ee=function(e){return"function"==typeof e||"object"==typeof e&&null!==e&&!Array.isArray(e)},xe=function(e){return"__proto__"!==e&&"constructor"!==e&&"prototype"!==e};function Ce(e,t,n){var r=e[n];Ee(t)&&Ee(r)?_e(r,t):e[n]=t}function _e(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r=0||(o[n]=e[n]);return o}(t,["componentId"]),a=r&&r+"-"+(Se(e)?e:we(b(e)));return Te(e,p({},o,{attrs:S,componentId:a}),n)},Object.defineProperty(x,"defaultProps",{get:function(){return this._foldedDefaultProps},set:function(t){this._foldedDefaultProps=r?_e({},e.defaultProps,t):t}}),x.toString=function(){return"."+x.styledComponentId},i&&d()(x,e,{attrs:!0,componentStyle:!0,displayName:!0,foldedComponentIds:!0,shouldForwardProp:!0,styledComponentId:!0,target:!0,withComponent:!0}),x}var Le=function(e){return function e(t,n,o){if(void 0===o&&(o=y),!Object(r.isValidElementType)(n))return x(1,String(n));var a=function(){return t(n,o,ve.apply(void 0,arguments))};return a.withConfig=function(r){return e(t,n,p({},o,{},r))},a.attrs=function(r){return e(t,n,p({},o,{attrs:Array.prototype.concat(o.attrs,r).filter(Boolean)}))},a}(Te,e)};["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","big","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","keygen","label","legend","li","link","main","map","mark","marquee","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr","circle","clipPath","defs","ellipse","foreignObject","g","image","line","linearGradient","marker","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","svg","text","tspan"].forEach((function(e){Le[e]=Le(e)}));!function(){function e(e,t){this.rules=e,this.componentId=t,this.isStatic=Y(e),H.registerId(this.componentId+1)}var t=e.prototype;t.createStyles=function(e,t,n,r){var o=r(me(this.rules,t,n,r).join(""),""),a=this.componentId+e;n.insertRules(a,a,o)},t.removeStyles=function(e,t){t.clearRules(this.componentId+e)},t.renderStyles=function(e,t,n,r){e>2&&H.registerId(this.componentId+e),this.removeStyles(e,n),this.createStyles(e,t,n,r)}}();function Ne(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r"+t+""},this.getStyleTags=function(){return e.sealed?x(2):e._emitSheetCSS()},this.getStyleElement=function(){var t;if(e.sealed)return x(2);var n=((t={})[k]="",t["data-styled-version"]="5.2.3",t.dangerouslySetInnerHTML={__html:e.instance.toString()},t),r=z();return r&&(n.nonce=r),[a.a.createElement("style",p({},n,{key:"sc-0-0"}))]},this.seal=function(){e.sealed=!0},this.instance=new H({isServer:!0}),this.sealed=!1}var t=e.prototype;t.collectStyles=function(e){return this.sealed?x(2):a.a.createElement(le,{sheet:this.instance},e)},t.interleaveWithNodeStream=function(e){return x(3)}}();t.a=Le}).call(this,n(48))},function(e,t,n){"use strict";n.d(t,"a",(function(){return a}));var r=n(20);function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0;d--){var p=i[d];"."===p?a(i,d):".."===p?(a(i,d),f++):f&&(a(i,d),f--)}if(!c)for(;f--;f)i.unshift("..");!c||""===i[0]||i[0]&&o(i[0])||i.unshift("");var h=i.join("/");return n&&"/"!==h.substr(-1)&&(h+="/"),h};function l(e){return e.valueOf?e.valueOf():Object.prototype.valueOf.call(e)}var u=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every((function(t,r){return e(t,n[r])}));if("object"===typeof t||"object"===typeof n){var r=l(t),o=l(n);return r!==t||o!==n?e(r,o):Object.keys(Object.assign({},t,n)).every((function(r){return e(t[r],n[r])}))}return!1},c=n(9);function s(e){return"/"===e.charAt(0)?e:"/"+e}function f(e){return"/"===e.charAt(0)?e.substr(1):e}function d(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function p(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function h(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function m(e,t,n,o){var a;"string"===typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e)).state=t:(void 0===(a=Object(r.a)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(l){throw l instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):l}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function v(e,t){return e.pathname===t.pathname&&e.search===t.search&&e.hash===t.hash&&e.key===t.key&&u(e.state,t.state)}function y(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"===typeof e?e(t,n):e;"string"===typeof a?"function"===typeof r?r(a,o):o(!0):o(!1!==a)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,o):n.push(o),f({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=m(e,t,d(),w.location);s.confirmTransitionTo(o,r,n,(function(e){e&&(w.entries[w.index]=o,f({action:r,location:o}))}))},go:b,goBack:function(){b(-1)},goForward:function(){b(1)},canGo:function(e){var t=w.index+e;return t>=0&&t=0||(o[n]=e[n]);return o}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(18);function o(e,t){if(e){if("string"===typeof e)return Object(r.a)(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Object(r.a)(e,t):void 0}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return f})),n.d(t,"b",(function(){return y}));var r=n(5),o=n(10),a=n(1),i=n.n(a),l=n(11),u=(n(17),n(6)),c=n(14),s=n(9),f=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;oe.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,l=!0,u=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return l=e.done,e},e:function(e){u=!0,i=e},f:function(){try{l||null==n.return||n.return()}finally{if(u)throw i}}}}},function(e,t,n){"use strict";var r=/^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|suppressHydrationWarning|valueLink|accept|acceptCharset|accessKey|action|allow|allowUserMedia|allowPaymentRequest|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|decoding|default|defer|dir|disabled|disablePictureInPicture|download|draggable|encType|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loading|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|inert|itemProp|itemScope|itemType|itemID|itemRef|on|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class|autofocus)|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/,o=function(e){var t={};return function(n){return void 0===t[n]&&(t[n]=e(n)),t[n]}}((function(e){return r.test(e)||111===e.charCodeAt(0)&&110===e.charCodeAt(1)&&e.charCodeAt(2)<91}));t.a=o},function(e,t,n){"use strict";e.exports=n(47)},function(e,t,n){"use strict";!function e(){if("undefined"!==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"===typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(36)},function(e,t,n){"use strict";var r=n(28),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function u(e){return r.isMemo(e)?i:l[e.$$typeof]||o}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=i;var c=Object.defineProperty,s=Object.getOwnPropertyNames,f=Object.getOwnPropertySymbols,d=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,n,r){if("string"!==typeof n){if(h){var o=p(n);o&&o!==h&&e(t,o,r)}var i=s(n);f&&(i=i.concat(f(n)));for(var l=u(t),m=u(n),v=0;vp)&&(F=(W=W.replace(" ",":")).length),0r&&(r=(t=t.trim()).charCodeAt(0)),r){case 38:return t.replace(v,"$1"+e.trim());case 58:return e.trim()+t.replace(v,"$1"+e.trim());default:if(0<1*n&&0u.charCodeAt(8))break;case 115:i=i.replace(u,"-webkit-"+u)+";"+i;break;case 207:case 102:i=i.replace(u,"-webkit-"+(102r.charCodeAt(0)&&(r=r.trim()),r=[r],0