├── public ├── _redirects ├── favicon.ico ├── images │ ├── 1.PNG │ ├── 2.PNG │ ├── 3.PNG │ ├── 4.PNG │ ├── 5.PNG │ ├── 6.PNG │ └── 7.PNG └── index.html ├── src ├── constants │ ├── BattingStatus.js │ └── OutType.js ├── components │ ├── NotFound.js │ ├── ui │ │ ├── Theme.js │ │ └── RadioGroupBoxStyle.js │ ├── StepperContainer.js │ ├── ScoreBoard.css │ ├── HorizontalStepper.js │ └── ScoreBoard.js ├── index.js ├── util │ └── MathUtil.js ├── main │ ├── Container.js │ └── Main.js ├── App.js └── index.css ├── .gitignore ├── package.json └── README.md /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafjava/gully-cricket-score-board/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/images/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafjava/gully-cricket-score-board/HEAD/public/images/1.PNG -------------------------------------------------------------------------------- /public/images/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafjava/gully-cricket-score-board/HEAD/public/images/2.PNG -------------------------------------------------------------------------------- /public/images/3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafjava/gully-cricket-score-board/HEAD/public/images/3.PNG -------------------------------------------------------------------------------- /public/images/4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafjava/gully-cricket-score-board/HEAD/public/images/4.PNG -------------------------------------------------------------------------------- /public/images/5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafjava/gully-cricket-score-board/HEAD/public/images/5.PNG -------------------------------------------------------------------------------- /public/images/6.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafjava/gully-cricket-score-board/HEAD/public/images/6.PNG -------------------------------------------------------------------------------- /public/images/7.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafjava/gully-cricket-score-board/HEAD/public/images/7.PNG -------------------------------------------------------------------------------- /src/constants/BattingStatus.js: -------------------------------------------------------------------------------- 1 | export const BATTING = 'Batting' 2 | export const YET_TO_BAT = 'Yet to Bat' 3 | export const OUT = 'Out' 4 | -------------------------------------------------------------------------------- /src/components/NotFound.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const NotFound = () => { 4 | return

NotFound

5 | } 6 | 7 | export default NotFound 8 | -------------------------------------------------------------------------------- /src/components/ui/Theme.js: -------------------------------------------------------------------------------- 1 | const { createTheme } = require('@material-ui/core') 2 | 3 | export const theme = createTheme({ 4 | palette: { 5 | common: {}, 6 | }, 7 | typography: {}, 8 | }) 9 | -------------------------------------------------------------------------------- /src/constants/OutType.js: -------------------------------------------------------------------------------- 1 | export const BOLD = 'Bold' 2 | export const CATCH = 'Catch' 3 | export const STUMP = 'Stump' 4 | export const HIT_WICKET = 'Hit Wicket' 5 | export const RUN_OUT = 'Run Out' 6 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import './index.css'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /src/util/MathUtil.js: -------------------------------------------------------------------------------- 1 | class MathUtil { 2 | static getRandomNo() { 3 | const min = 100 4 | const max = 999 5 | return Math.floor(Math.random() * (max - min + 1) + min) 6 | } 7 | } 8 | 9 | export default MathUtil 10 | -------------------------------------------------------------------------------- /src/main/Container.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react' 2 | import Main from './Main' 3 | 4 | const Container = () => { 5 | return ( 6 | 7 |
8 | 9 | ) 10 | } 11 | 12 | export default Container 13 | -------------------------------------------------------------------------------- /src/components/ui/RadioGroupBoxStyle.js: -------------------------------------------------------------------------------- 1 | export const radioGroupBoxstyle = { 2 | position: 'absolute', 3 | top: '61%', 4 | left: '50%', 5 | transform: 'translate(-50%, -50%)', 6 | width: 340, 7 | bgcolor: 'background.paper', 8 | border: '2px solid #3f51b5', 9 | boxShadow: 24, 10 | p: '4px', 11 | } 12 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { ThemeProvider } from '@material-ui/core' 2 | import React from 'react' 3 | import { theme } from './components/ui/Theme' 4 | import Container from './main/Container' 5 | 6 | function App() { 7 | return ( 8 | 9 | 10 | 11 | ) 12 | } 13 | 14 | export default App 15 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Roboto', 'Segoe UI', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 4 | 'Helvetica Neue', sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/main/Main.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { BrowserRouter, Route, Switch } from 'react-router-dom' 3 | import NotFound from '../components/NotFound' 4 | import ScoreBoard from '../components/ScoreBoard' 5 | import StepperContainer from '../components/StepperContainer' 6 | 7 | const Main = () => { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | 19 | export default Main 20 | -------------------------------------------------------------------------------- /src/components/StepperContainer.js: -------------------------------------------------------------------------------- 1 | import { AppBar, Box, Container, Toolbar, Typography } from '@material-ui/core' 2 | import React from 'react' 3 | import HorizontalStepper from './HorizontalStepper' 4 | 5 | const StepperContainer = () => { 6 | return ( 7 |
8 | 9 | 10 | Multi Step Form 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | ) 20 | } 21 | 22 | export default StepperContainer 23 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Cricket Score Board 11 | 12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gully-cricket-score-board", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.7.0", 7 | "@emotion/styled": "^11.6.0", 8 | "@material-ui/core": "^4.12.3", 9 | "@mui/icons-material": "^5.2.1", 10 | "@mui/material": "^5.2.3", 11 | "@testing-library/jest-dom": "^5.16.1", 12 | "@testing-library/react": "^12.1.2", 13 | "@testing-library/user-event": "^13.5.0", 14 | "formik": "^2.2.9", 15 | "react": "^17.0.2", 16 | "react-autosuggest": "^10.1.0", 17 | "react-dom": "^17.0.2", 18 | "react-router-dom": "^5.2.0", 19 | "react-scripts": "4.0.3", 20 | "yup": "^0.32.11" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": "react-app" 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What is this? 2 | 3 | A gully cricket score board used to maintain the score of the team and individual players with runs, balls & strike rate including bowler's total over, maiden, runs given, economy, etc. This project was build using React JS and bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Screenshot 6 | 7 | ![Select Teams](public/images/1.PNG) ![Overs](public/images/2.PNG) ![Who is Batting](public/images/3.PNG) ![Wicket Type](public/images/4.PNG) ![2nd Inning winning hint](public/images/5.PNG) ![Match Won](public/images/6.PNG) ![Score Board](public/images/7.PNG) 8 | 9 | ## Recommendation 10 | 11 | This application is best viewed in Mobile/Phone browser. 12 | 13 | ## Problem 14 | 15 | Currently data has been managed using state. Hence don't refresh the page until the completion of match otherwise all data will be gone. For that you can use android application which you can **download** from the **Release Section**. 16 | 17 | ## Is this live? 18 | 19 | Yes, this application is live and deployed in Netlify. You can check here [gully-cricket-score-board](https://gully-cricket.netlify.app/). 20 | 21 | ## Available Scripts 22 | 23 | In the project directory, you can run: 24 | 25 | ### `npm start` 26 | 27 | Runs the app in the development mode. Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 28 | 29 | The page will reload if you make edits. You will also see any lint errors in the console. 30 | 31 | ### `npm test` 32 | 33 | Launches the test runner in the interactive watch mode. See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 34 | 35 | ### `npm run build` 36 | 37 | Builds the app for production to the `build` folder. It correctly bundles React in production mode and optimizes the build for the best performance. 38 | 39 | The build is minified and the filenames include the hashes. Your app is ready to be deployed! 40 | 41 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 42 | -------------------------------------------------------------------------------- /src/components/ScoreBoard.css: -------------------------------------------------------------------------------- 1 | .inning { 2 | background: #3f51b5; 3 | color: white; 4 | padding: 0.5rem; 5 | font-size: 1.2rem; 6 | display: flex; 7 | justify-content: space-between; 8 | align-items: center; 9 | } 10 | #end-inning { 11 | height: 100%; 12 | padding: 4px; 13 | outline: none; 14 | border: 1px solid #fff; 15 | border-radius: 4px; 16 | } 17 | #end-inning:active { 18 | color: #fff; 19 | background-color: #3f51b5; 20 | } 21 | .score-container { 22 | margin: 0.5rem; 23 | } 24 | .run-out-player { 25 | height: 2rem; 26 | max-width: 9.3rem; 27 | } 28 | .run-out-player-error { 29 | color: #ff0000; 30 | font-size: 0.7rem; 31 | text-align: right; 32 | padding-right: 0rem; 33 | } 34 | .hide { 35 | display: none; 36 | } 37 | .badge { 38 | background: #ffff4d; 39 | color: #000000; 40 | text-align: center; 41 | font-size: 0.75rem; 42 | font-weight: 500; 43 | padding: 8px; 44 | margin-bottom: 8px; 45 | } 46 | .badge-flex { 47 | display: flex; 48 | align-items: center; 49 | justify-content: space-between; 50 | } 51 | .score { 52 | display: flex; 53 | align-items: center; 54 | justify-content: space-between; 55 | font-size: 1.05rem; 56 | font-weight: bold; 57 | padding: 4px; 58 | } 59 | .batting-container { 60 | display: flex; 61 | align-items: center; 62 | justify-content: flex-start; 63 | margin: 0.8rem 0; 64 | } 65 | .batting-container table { 66 | width: 100%; 67 | border: none; 68 | border-spacing: unset; 69 | } 70 | table thead { 71 | padding: 8px; 72 | background-color: #3f51b517; 73 | } 74 | .batting-container table td { 75 | padding: 8px 4px; 76 | } 77 | .bowler { 78 | display: flex; 79 | align-items: center; 80 | background-color: #3f51b517; 81 | padding: 8px; 82 | } 83 | .react-autosuggest__container { 84 | padding-left: 4px; 85 | position: relative; 86 | } 87 | .react-autosuggest__input { 88 | max-width: 6.5rem; 89 | } 90 | .react-autosuggest__input--focused { 91 | /* outline: none; */ 92 | } 93 | .react-autosuggest__input--open { 94 | border-bottom-left-radius: 0; 95 | border-bottom-right-radius: 0; 96 | } 97 | .react-autosuggest__suggestions-container { 98 | display: none; 99 | } 100 | .react-autosuggest__suggestions-container--open { 101 | display: block; 102 | position: absolute; 103 | top: 1.3rem; 104 | width: 6.85rem; 105 | border: 1px solid #808080; 106 | background-color: #fff; 107 | font-weight: 400; 108 | font-size: 0.8rem; 109 | z-index: 2; 110 | } 111 | .react-autosuggest__suggestions-list { 112 | margin: 0; 113 | padding: 0; 114 | list-style-type: none; 115 | } 116 | .react-autosuggest__suggestion { 117 | cursor: pointer; 118 | padding: 4px; 119 | } 120 | .react-autosuggest__suggestion--highlighted { 121 | background-color: #ddd; 122 | } 123 | .bowler-runs { 124 | display: flex; 125 | align-items: center; 126 | justify-content: space-between; 127 | padding: 8px; 128 | } 129 | .score-types-container table { 130 | width: 100%; 131 | height: 100%; 132 | border-spacing: 8px; 133 | } 134 | .score-types-container table .score-types { 135 | background: #3f51b517; 136 | } 137 | .score-types-container table td { 138 | border: 1px solid #3f51b5; 139 | } 140 | .score-types-button { 141 | display: block; 142 | width: 100%; 143 | height: 100%; 144 | padding: 8px; 145 | outline: none; 146 | border: none; 147 | } 148 | .score-types-button:active { 149 | color: white; 150 | background-color: #3f51b5; 151 | } 152 | .score-types-button-noball { 153 | color: #000; 154 | background-color: #ffff4d; 155 | } 156 | .icon-button { 157 | padding: 0 4px !important; 158 | } 159 | .icon-size { 160 | font-size: 1rem !important; 161 | } 162 | .delete-icon-size { 163 | font-size: 1.3rem !important; 164 | } 165 | .strike-icon-button { 166 | padding: 0 !important; 167 | } 168 | .batter-name { 169 | max-width: 6.5rem; 170 | } 171 | .extras-container { 172 | margin: 0.8rem 0; 173 | display: flex; 174 | justify-content: space-between; 175 | padding: 8px; 176 | background: #3f51b517; 177 | } 178 | .recent-over-container { 179 | margin: 0.8rem 0; 180 | } 181 | .recent-over-text { 182 | background-color: #3f51b517; 183 | padding: 8px; 184 | } 185 | .recent-over-details table { 186 | width: 100%; 187 | font-size: 0.9rem; 188 | } 189 | .recent-over-runs { 190 | display: flex; 191 | justify-content: space-around; 192 | gap: 4px; 193 | padding: 8px; 194 | } 195 | .recent-over-total-run { 196 | text-align: center; 197 | border-left: 1px solid #ccc; 198 | font-weight: bold; 199 | padding: 0 2px; 200 | } 201 | .text-center { 202 | text-align: center; 203 | } 204 | .score-board-container { 205 | margin: 0.8rem 0; 206 | } 207 | .score-board-innings { 208 | display: flex; 209 | justify-content: space-between; 210 | padding: 6px 4px; 211 | color: #fff; 212 | background: #737373; 213 | font-size: 0.95rem; 214 | } 215 | .score-board-text { 216 | color: #fff; 217 | background: #404040; 218 | padding: 8px; 219 | } 220 | .sb-batting { 221 | display: flex; 222 | align-items: center; 223 | justify-content: flex-start; 224 | } 225 | .sb-batting table { 226 | width: 100%; 227 | border: none; 228 | border-spacing: unset; 229 | } 230 | .sb-batting table thead { 231 | font-size: 0.9rem; 232 | } 233 | .sb-batting table tbody { 234 | font-size: 0.85rem; 235 | } 236 | .sb-batting table td { 237 | padding: 8px 4px; 238 | } 239 | .score-board-extras { 240 | margin: 0.8rem 0; 241 | display: flex; 242 | justify-content: space-between; 243 | padding: 6px 4px; 244 | font-size: 0.85rem; 245 | background: #3f51b517; 246 | } 247 | .sb-bowling { 248 | display: flex; 249 | align-items: center; 250 | justify-content: flex-start; 251 | } 252 | .sb-bowling table { 253 | width: 100%; 254 | border: none; 255 | border-spacing: unset; 256 | } 257 | .sb-bowling table thead { 258 | font-size: 0.9rem; 259 | } 260 | .sb-bowling table tbody { 261 | font-size: 0.85rem; 262 | } 263 | .sb-bowling table td { 264 | padding: 8px 4px; 265 | } 266 | -------------------------------------------------------------------------------- /src/components/HorizontalStepper.js: -------------------------------------------------------------------------------- 1 | import { TextField } from '@material-ui/core' 2 | import Button from '@material-ui/core/Button' 3 | import Step from '@material-ui/core/Step' 4 | import StepLabel from '@material-ui/core/StepLabel' 5 | import Stepper from '@material-ui/core/Stepper' 6 | import { makeStyles } from '@material-ui/core/styles' 7 | import Typography from '@material-ui/core/Typography' 8 | import FormControl from '@mui/material/FormControl' 9 | import FormControlLabel from '@mui/material/FormControlLabel' 10 | import FormLabel from '@mui/material/FormLabel' 11 | import Radio from '@mui/material/Radio' 12 | import RadioGroup from '@mui/material/RadioGroup' 13 | import { Formik } from 'formik' 14 | import React from 'react' 15 | import { useHistory } from 'react-router-dom' 16 | import * as Yup from 'yup' 17 | 18 | const useStyles = makeStyles((theme) => ({ 19 | mainContainer: { 20 | margin: 'auto', 21 | border: '1px solid #ccc', 22 | borderRadius: '4px', 23 | }, 24 | formContainer: { 25 | margin: '2rem 0 2rem', 26 | display: 'flex', 27 | flexDirection: 'column', 28 | alignItems: 'center', 29 | }, 30 | formGroup: { 31 | marginBottom: '2rem', 32 | }, 33 | resetContainer: { 34 | display: 'flex', 35 | flexDirection: 'column', 36 | justifyContent: 'center', 37 | }, 38 | backButton: { 39 | marginRight: theme.spacing(1), 40 | }, 41 | instructions: { 42 | marginTop: theme.spacing(1), 43 | marginBottom: theme.spacing(1), 44 | }, 45 | textField: { 46 | '& > *': { 47 | margin: theme.spacing(1), 48 | width: '25ch', 49 | }, 50 | }, 51 | textfieldWidth: { 52 | width: 200, 53 | }, 54 | teamNameHeading: { 55 | fontWeight: 'bold', 56 | // padding: '16px', 57 | // paddingBottom: '0px', 58 | }, 59 | center: { 60 | textAlign: 'center', 61 | }, 62 | })) 63 | const HorizontalStepper = () => { 64 | const history = useHistory() 65 | const classes = useStyles() 66 | const [activeStep, setActiveStep] = React.useState(0) 67 | const [isSubmitting, setSubmitting] = React.useState(false) 68 | 69 | const steps = ['Team', 'Overs', 'Batting'] 70 | const handleNext = () => { 71 | setActiveStep((prevActiveStep) => prevActiveStep + 1) 72 | } 73 | const handleBack = () => { 74 | setActiveStep((prevActiveStep) => prevActiveStep - 1) 75 | } 76 | const initialValues = { 77 | team1: '', 78 | team2: '', 79 | maxOver: '', 80 | batting: '', 81 | } 82 | const validationSchema = [ 83 | Yup.object().shape({ 84 | team1: Yup.string().required('Team Name is required'), 85 | team2: Yup.string().required('Team Name is required'), 86 | }), 87 | Yup.object().shape({ 88 | maxOver: Yup.string().required('Over is required'), 89 | }), 90 | Yup.object().shape({ 91 | batting: Yup.string().required('Please choose who is Batting'), 92 | }), 93 | ] 94 | const currentValidationSchema = validationSchema[activeStep] 95 | function isLastStep() { 96 | return activeStep === steps.length - 1 97 | } 98 | return ( 99 |
100 | 101 | {steps.map((label) => ( 102 | 103 | {label} 104 | 105 | ))} 106 | 107 |
108 | { 113 | handleNext() 114 | actions.setTouched({}) 115 | actions.setSubmitting(false) 116 | if (isLastStep()) { 117 | setSubmitting(true) 118 | const data = JSON.stringify(values) 119 | localStorage.setItem('data', data) 120 | history.push('/score') 121 | setSubmitting(false) 122 | } 123 | }} 124 | > 125 | {(prp) => { 126 | const { values, touched, errors, handleChange, handleBlur, handleSubmit, setFieldValue } = prp 127 | return ( 128 |
129 |
130 | {activeStep === 0 && ( 131 |
132 |
133 | 144 |
145 |
146 | VS 147 |
148 |
149 | 160 |
161 |
162 | )} 163 | {activeStep === 1 && ( 164 |
165 |
166 | How many overs? 167 |
168 | 179 |
180 |
181 |
182 | )} 183 | {activeStep === 2 && ( 184 |
185 |
186 | 187 | Who is Batting? 188 | { 192 | setFieldValue('batting', event.currentTarget.value) 193 | }} 194 | > 195 | } label={values.team1} /> 196 | } label={values.team2} /> 197 | 198 | 199 |
200 |
201 | )} 202 |
203 | 206 | 209 |
210 |
211 |
212 | ) 213 | }} 214 |
215 |
216 |
217 | ) 218 | } 219 | 220 | export default HorizontalStepper 221 | -------------------------------------------------------------------------------- /src/components/ScoreBoard.js: -------------------------------------------------------------------------------- 1 | import DeleteIcon from '@mui/icons-material/Delete' 2 | import EditIcon from '@mui/icons-material/Edit' 3 | import { IconButton } from '@mui/material' 4 | import Box from '@mui/material/Box' 5 | import { pink } from '@mui/material/colors' 6 | import FormControl from '@mui/material/FormControl' 7 | import FormControlLabel from '@mui/material/FormControlLabel' 8 | import Modal from '@mui/material/Modal' 9 | import Radio from '@mui/material/Radio' 10 | import RadioGroup from '@mui/material/RadioGroup' 11 | import React, { useEffect, useState } from 'react' 12 | import { useHistory } from 'react-router-dom' 13 | import Autosuggest from 'react-autosuggest' 14 | import { BATTING, OUT } from '../constants/BattingStatus' 15 | import { BOLD, CATCH, HIT_WICKET, RUN_OUT, STUMP } from '../constants/OutType' 16 | import MathUtil from '../util/MathUtil' 17 | import './ScoreBoard.css' 18 | import { radioGroupBoxstyle } from './ui/RadioGroupBoxStyle' 19 | 20 | const ScoreBoard = () => { 21 | const [inningNo, setInningNo] = useState(1) 22 | const [match, setMatch] = useState({ inning1: { batters: [], bowlers: [] }, inning2: { batters: [], bowlers: [] } }) 23 | const [currentRunStack, setCurrentRunStack] = useState([]) 24 | const [totalRuns, setTotalRuns] = useState(0) 25 | const [extras, setExtras] = useState({ total: 0, wide: 0, noBall: 0 }) 26 | const [runsByOver, setRunsByOver] = useState(0) 27 | const [wicketCount, setWicketCount] = useState(0) 28 | const [totalOvers, setTotalOvers] = useState(0) 29 | const [batters, setBatters] = useState([]) 30 | const [ballCount, setBallCount] = useState(0) 31 | const [overCount, setOverCount] = useState(0) 32 | const [recentOvers, setRecentOvers] = useState([]) 33 | const [batter1, setBatter1] = useState({}) 34 | const [batter2, setBatter2] = useState({}) 35 | const [battingOrder, setBattingOrder] = useState(0) 36 | const [isBatter1Edited, setBatter1Edited] = useState(false) 37 | const [isBatter2Edited, setBatter2Edited] = useState(false) 38 | const [isBowlerEdited, setBowlerEdited] = useState(false) 39 | const [bowler, setBowler] = useState({}) 40 | const [bowlers, setBowlers] = useState([]) 41 | const [inputBowler, setInputBowler] = useState('') 42 | const [isModalOpen, setModalOpen] = React.useState(false) 43 | const [outType, setOutType] = React.useState('') 44 | const [runOutPlayerId, setRunOutPlayerId] = React.useState('') 45 | const [remainingBalls, setRemainingBalls] = useState(0) 46 | const [remainingRuns, setRemainingRuns] = useState(0) 47 | const [strikeValue, setStrikeValue] = React.useState('strike') 48 | const [isNoBall, setNoBall] = useState(false) 49 | const [suggestions, setSuggestions] = useState([]) 50 | const [hasNameSuggested, setNameSuggested] = useState(false) 51 | const [hasMatchEnded, setMatchEnded] = useState(false) 52 | 53 | let data = JSON.parse(localStorage.getItem('data')) 54 | const { batting, team1, team2 } = data 55 | const maxOver = parseInt(data.maxOver) 56 | const history = useHistory() 57 | 58 | useEffect(() => { 59 | const endInningButton = document.getElementById('end-inning') 60 | endInningButton.disabled = true 61 | }, []) 62 | 63 | const handleEndInning = (e) => { 64 | const endInningButton = document.getElementById('end-inning') 65 | if (endInningButton.textContent === 'Reset') { 66 | history.push('/') 67 | } else { 68 | if (batter1.id !== undefined) { 69 | const { id, name, run, ball, four, six, strikeRate, onStrike } = batter1 70 | batters.push({ 71 | id, 72 | name, 73 | run, 74 | ball, 75 | four, 76 | six, 77 | strikeRate, 78 | onStrike, 79 | battingOrder: batter1.battingOrder, 80 | battingStatus: BATTING, 81 | }) 82 | } 83 | if (batter2.id !== undefined) { 84 | batters.push({ 85 | id: batter2.id, 86 | name: batter2.name, 87 | run: batter2.run, 88 | ball: batter2.ball, 89 | four: batter2.four, 90 | six: batter2.six, 91 | strikeRate: batter2.strikeRate, 92 | onStrike: batter2.onStrike, 93 | battingOrder: batter2.battingOrder, 94 | battingStatus: BATTING, 95 | }) 96 | } 97 | if (bowler.id !== undefined) { 98 | const currentDisplayOver = Math.round((ballCount === 6 ? 1 : ballCount * 0.1) * 10) / 10 99 | let isMaidenOver = true 100 | let countWicket = 0 101 | let countNoBall = 0 102 | let countWide = 0 103 | const deliveries = ['1', '2', '3', '4', '6', 'wd'] 104 | for (let delivery of currentRunStack) { 105 | delivery = delivery.toString() 106 | if (deliveries.includes(delivery) || delivery.includes('nb')) { 107 | isMaidenOver = false 108 | } 109 | if (delivery === 'W') { 110 | countWicket++ 111 | } 112 | if (delivery.includes('nb')) { 113 | countNoBall++ 114 | } 115 | if (delivery.includes('wd')) { 116 | countWide++ 117 | } 118 | } 119 | if (ballCount !== 6) { 120 | isMaidenOver = false 121 | } 122 | const index = bowlers.findIndex((blr) => { 123 | return blr.id === bowler.id 124 | }) 125 | if (index !== -1) { 126 | const existingBowler = bowlers[index] 127 | const { maiden, wicket, noBall, wide, over } = existingBowler 128 | const bowlerTotalOver = over + ballCount / 6 129 | existingBowler.over = existingBowler.over + currentDisplayOver 130 | existingBowler.maiden = isMaidenOver ? maiden + 1 : maiden 131 | existingBowler.run = existingBowler.run + runsByOver 132 | existingBowler.wicket = wicket + countWicket 133 | existingBowler.noBall = noBall + countNoBall 134 | existingBowler.wide = wide + countWide 135 | existingBowler.economy = Math.round((existingBowler.run / bowlerTotalOver) * 100) / 100 136 | bowlers[index] = existingBowler 137 | setBowlers(bowlers) 138 | } else { 139 | if (ballCount !== 6) { 140 | bowlers.push({ 141 | id: bowler.id, 142 | name: bowler.name, 143 | over: currentDisplayOver, 144 | maiden: isMaidenOver ? 1 : 0, 145 | run: runsByOver, 146 | wicket: countWicket, 147 | noBall: countNoBall, 148 | wide: countWide, 149 | economy: Math.round((runsByOver / (ballCount / 6)) * 100) / 100, 150 | }) 151 | setBowlers(bowlers) 152 | } 153 | } 154 | } 155 | if (inningNo === 1) { 156 | setMatch((state) => { 157 | const totalFours = batters.map((batter) => batter.four).reduce((prev, next) => prev + next) 158 | const totalSixes = batters.map((batter) => batter.four).reduce((prev, next) => prev + next) 159 | return { 160 | ...state, 161 | inning1: { 162 | runs: totalRuns, 163 | wickets: wicketCount, 164 | runRate: crr, 165 | overs: totalOvers, 166 | four: totalFours, 167 | six: totalSixes, 168 | extra: extras, 169 | batters, 170 | bowlers, 171 | }, 172 | } 173 | }) 174 | setInningNo(2) 175 | setCurrentRunStack([]) 176 | setTotalRuns(0) 177 | setExtras({ total: 0, wide: 0, noBall: 0 }) 178 | setRunsByOver(0) 179 | setWicketCount(0) 180 | setTotalOvers(0) 181 | setBallCount(0) 182 | setOverCount(0) 183 | setRecentOvers([]) 184 | setBatter1({}) 185 | setBatter2({}) 186 | setBatters([]) 187 | setBowlers([]) 188 | setBattingOrder(0) 189 | setInputBowler('') 190 | setBowler({}) 191 | setRemainingBalls(maxOver * 6) 192 | setRemainingRuns(totalRuns + 1) 193 | const bowlerNameElement = document.querySelector('.react-autosuggest__input') 194 | bowlerNameElement.disabled = false 195 | const batter1NameElement = document.getElementById('batter1Name') 196 | batter1NameElement.value = '' 197 | batter1NameElement.disabled = false 198 | const batter2NameElement = document.getElementById('batter2Name') 199 | batter2NameElement.value = '' 200 | batter2NameElement.disabled = false 201 | setStrikeValue('strike') 202 | endInningButton.disabled = true 203 | } else { 204 | setMatch((state) => { 205 | const totalFours = batters.map((batter) => batter.four).reduce((prev, next) => prev + next) 206 | const totalSixes = batters.map((batter) => batter.four).reduce((prev, next) => prev + next) 207 | return { 208 | ...state, 209 | inning2: { 210 | runs: totalRuns, 211 | wickets: wicketCount, 212 | runRate: crr, 213 | overs: totalOvers, 214 | four: totalFours, 215 | six: totalSixes, 216 | extra: extras, 217 | batters, 218 | bowlers, 219 | }, 220 | } 221 | }) 222 | endInningButton.textContent = 'Reset' 223 | setMatchEnded(true) 224 | } 225 | } 226 | } 227 | const handleBatter1Blur = (e) => { 228 | let name = e.target.value 229 | name = name.charAt(0).toUpperCase() + name.slice(1) 230 | e.target.value = name 231 | e.target.disabled = true 232 | if (isBatter1Edited) { 233 | setBatter1((state) => ({ 234 | ...state, 235 | name: name, 236 | })) 237 | setBatter1Edited(false) 238 | } else { 239 | const randomNo = MathUtil.getRandomNo() 240 | setBatter1({ 241 | id: name + randomNo, 242 | name: name, 243 | run: 0, 244 | ball: 0, 245 | four: 0, 246 | six: 0, 247 | strikeRate: 0, 248 | onStrike: strikeValue === 'strike' ? true : false, 249 | battingOrder: battingOrder + 1, 250 | battingStatus: BATTING, 251 | }) 252 | setBattingOrder(battingOrder + 1) 253 | } 254 | } 255 | const handleBatter2Blur = (e) => { 256 | let name = e.target.value 257 | name = name.charAt(0).toUpperCase() + name.slice(1) 258 | e.target.value = name 259 | e.target.disabled = true 260 | if (isBatter2Edited) { 261 | setBatter2((state) => ({ 262 | ...state, 263 | name: name, 264 | })) 265 | setBatter2Edited(false) 266 | } else { 267 | const randomNo = MathUtil.getRandomNo() 268 | setBatter2({ 269 | id: name + randomNo, 270 | name: name, 271 | run: 0, 272 | ball: 0, 273 | four: 0, 274 | six: 0, 275 | strikeRate: 0, 276 | onStrike: strikeValue === 'non-strike' ? true : false, 277 | battingOrder: battingOrder + 1, 278 | battingStatus: BATTING, 279 | }) 280 | setBattingOrder(battingOrder + 1) 281 | } 282 | } 283 | const handleBowlerBlur = (e) => { 284 | let name = e.target.value 285 | if (name !== '') { 286 | name = name.charAt(0).toUpperCase() + name.slice(1) 287 | setInputBowler(name) 288 | e.target.value = name 289 | e.target.disabled = true 290 | if (isBowlerEdited) { 291 | setBowler((state) => ({ 292 | ...state, 293 | name: name, 294 | })) 295 | setBowlerEdited(false) 296 | } else { 297 | if (hasNameSuggested) { 298 | setNameSuggested(false) 299 | } else { 300 | const randomNo = MathUtil.getRandomNo() 301 | const id = name + randomNo 302 | setBowler({ 303 | id, 304 | name, 305 | }) 306 | } 307 | } 308 | } 309 | } 310 | const onSuggestionsFetchRequested = (param) => { 311 | const inputValue = param.value.trim().toLowerCase() 312 | const suggestionArr = inputValue.length === 0 ? [] : bowlers.filter((bowlerObj) => bowlerObj.name.toLowerCase().includes(inputValue)) 313 | setSuggestions(suggestionArr) 314 | } 315 | const getSuggestionValue = (suggestion) => { 316 | setBowler({ 317 | id: suggestion.id, 318 | name: suggestion.name, 319 | }) 320 | setNameSuggested(true) 321 | return suggestion.name 322 | } 323 | const inputProps = { 324 | value: inputBowler, 325 | onChange: (e, { newValue }) => { 326 | setInputBowler(newValue) 327 | }, 328 | onBlur: handleBowlerBlur, 329 | } 330 | const overCompleted = (runsByOverParam, currentRunStackParam) => { 331 | const bowlerNameElement = document.querySelector('.react-autosuggest__input') 332 | if (overCount + 1 === maxOver) { 333 | const endInningButton = document.getElementById('end-inning') 334 | endInningButton.disabled = false 335 | } else { 336 | bowlerNameElement.disabled = false 337 | } 338 | disableAllScoreButtons() 339 | setRecentOvers((state) => [ 340 | ...state, 341 | { overNo: overCount + 1, bowler: bowler.name, runs: runsByOverParam, stack: currentRunStackParam }, 342 | ]) 343 | setInputBowler('') 344 | setBowler({}) 345 | setCurrentRunStack([]) 346 | setRunsByOver(0) 347 | setBallCount(0) 348 | setOverCount(overCount + 1) 349 | const index = bowlers.findIndex((blr) => blr.id === bowler.id) 350 | let isMaidenOver = true 351 | let countWicket = 0 352 | let countNoBall = 0 353 | let countWide = 0 354 | const deliveries = ['1', '2', '3', '4', '6', 'wd'] 355 | for (let delivery of currentRunStackParam) { 356 | delivery = delivery.toString() 357 | if (deliveries.includes(delivery) || delivery.includes('nb')) { 358 | isMaidenOver = false 359 | } 360 | if (delivery === 'W') { 361 | countWicket++ 362 | } 363 | if (delivery.includes('nb')) { 364 | countNoBall++ 365 | } 366 | if (delivery.includes('wd')) { 367 | countWide++ 368 | } 369 | } 370 | if (index !== -1) { 371 | const existingBowler = bowlers[index] 372 | const { over, maiden, run, wicket, noBall, wide } = existingBowler 373 | existingBowler.over = over + 1 374 | existingBowler.maiden = isMaidenOver ? maiden + 1 : maiden 375 | existingBowler.run = run + runsByOverParam 376 | existingBowler.wicket = wicket + countWicket 377 | existingBowler.noBall = noBall + countNoBall 378 | existingBowler.wide = wide + countWide 379 | existingBowler.economy = Math.round((existingBowler.run / existingBowler.over) * 100) / 100 380 | bowlers[index] = existingBowler 381 | setBowlers(bowlers) 382 | } else { 383 | setBowlers((state) => [ 384 | ...state, 385 | { 386 | id: bowler.id, 387 | name: bowler.name, 388 | over: 1, 389 | maiden: isMaidenOver ? 1 : 0, 390 | run: runsByOverParam, 391 | wicket: countWicket, 392 | noBall: countNoBall, 393 | wide: countWide, 394 | economy: runsByOverParam, 395 | }, 396 | ]) 397 | } 398 | } 399 | const newBatter1 = () => { 400 | const batter1NameElement = document.getElementById('batter1Name') 401 | batter1NameElement.value = '' 402 | batter1NameElement.disabled = false 403 | const { id, name, run, ball, four, six, strikeRate, onStrike } = batter1 404 | setBatters((state) => [ 405 | ...state, 406 | { 407 | id, 408 | name, 409 | run, 410 | ball, 411 | four, 412 | six, 413 | strikeRate, 414 | onStrike, 415 | battingOrder: batter1.battingOrder, 416 | battingStatus: OUT, 417 | }, 418 | ]) 419 | setBatter1({}) 420 | } 421 | const newBatter2 = () => { 422 | const batter2NameElement = document.getElementById('batter2Name') 423 | batter2NameElement.value = '' 424 | batter2NameElement.disabled = false 425 | const { id, name, run, ball, four, six, strikeRate, onStrike } = batter2 426 | setBatters((state) => [ 427 | ...state, 428 | { 429 | id, 430 | name, 431 | run, 432 | ball, 433 | four, 434 | six, 435 | strikeRate, 436 | onStrike, 437 | battingOrder: batter2.battingOrder, 438 | battingStatus: OUT, 439 | }, 440 | ]) 441 | setBatter2({}) 442 | } 443 | const editBatter1Name = () => { 444 | if (overCount !== maxOver && wicketCount !== 10 && !hasMatchEnded) { 445 | const batter1NameElement = document.getElementById('batter1Name') 446 | batter1NameElement.disabled = false 447 | setBatter1Edited(true) 448 | } 449 | } 450 | const editBatter2Name = () => { 451 | if (overCount !== maxOver && wicketCount !== 10 && !hasMatchEnded) { 452 | const batter2NameElement = document.getElementById('batter2Name') 453 | batter2NameElement.disabled = false 454 | setBatter2Edited(true) 455 | } 456 | } 457 | const editBowlerName = () => { 458 | if (overCount !== maxOver && wicketCount !== 10 && !hasMatchEnded) { 459 | const bowlerNameElement = document.querySelector('.react-autosuggest__input') 460 | bowlerNameElement.disabled = false 461 | setBowlerEdited(true) 462 | } 463 | } 464 | const undoWicket = (isNoBallParam) => { 465 | if (!isNoBallParam) { 466 | setBallCount(ballCount - 1) 467 | setTotalOvers(Math.round((totalOvers - 0.1) * 10) / 10) 468 | } 469 | setWicketCount(wicketCount - 1) 470 | const batter = batters[batters.length - 1] 471 | const { id, name, run, ball, four, six, strikeRate, onStrike } = batter 472 | if (batter1.name === undefined || batter1.onStrike) { 473 | const batter1NameElement = document.getElementById('batter1Name') 474 | batter1NameElement.value = batter.name 475 | batter1NameElement.disabled = true 476 | setBatter1({ 477 | id, 478 | name, 479 | run, 480 | ball, 481 | four, 482 | six, 483 | strikeRate, 484 | onStrike, 485 | battingOrder: batter.battingOrder, 486 | battingStatus: BATTING, 487 | }) 488 | if (!batter.onStrike) { 489 | changeStrikeRadio() 490 | setBatter2((state) => ({ 491 | ...state, 492 | onStrike: true, 493 | })) 494 | } 495 | } else if (batter2.name === undefined || batter2.onStrike) { 496 | const batter2NameElement = document.getElementById('batter2Name') 497 | batter2NameElement.value = batter.name 498 | batter2NameElement.disabled = true 499 | setBatter2({ 500 | id, 501 | name, 502 | run, 503 | ball, 504 | four, 505 | six, 506 | strikeRate, 507 | onStrike, 508 | battingOrder: batter.battingOrder, 509 | battingStatus: BATTING, 510 | }) 511 | if (!batter.onStrike) { 512 | changeStrikeRadio() 513 | setBatter1((state) => ({ 514 | ...state, 515 | onStrike: true, 516 | })) 517 | } 518 | } 519 | batters.pop() 520 | setBatters(batters) 521 | } 522 | const undoRun = (run, isNoBallParam) => { 523 | if (isNoBallParam) { 524 | setTotalRuns(totalRuns - (run + 1)) 525 | setRunsByOver(runsByOver - (run + 1)) 526 | } else { 527 | setTotalRuns(totalRuns - run) 528 | setRunsByOver(runsByOver - run) 529 | setBallCount(ballCount - 1) 530 | setTotalOvers(Math.round((totalOvers - 0.1) * 10) / 10) 531 | currentRunStack.pop() 532 | setCurrentRunStack(currentRunStack) 533 | } 534 | if (batter1.onStrike) { 535 | if (run % 2 === 0) { 536 | setBatter1((state) => { 537 | const updatedRun = state.run - run 538 | const updatedBall = state.ball - 1 539 | const updatedSr = updatedRun / updatedBall 540 | const sr = Math.round(isNaN(updatedSr) ? 0 : updatedSr * 100 * 100) / 100 541 | let four = state.four 542 | if (run === 4) { 543 | four = four - 1 544 | } 545 | let six = state.six 546 | if (run === 6) { 547 | six = six - 1 548 | } 549 | return { 550 | ...state, 551 | run: updatedRun, 552 | ball: updatedBall, 553 | four: four, 554 | six: six, 555 | strikeRate: sr, 556 | } 557 | }) 558 | } else { 559 | changeStrikeRadio() 560 | switchBatterStrike() 561 | setBatter2((state) => { 562 | const updatedRun = state.run - run 563 | const updatedBall = state.ball - 1 564 | const updatedSr = updatedRun / updatedBall 565 | const sr = Math.round(isNaN(updatedSr) ? 0 : updatedSr * 100 * 100) / 100 566 | let four = state.four 567 | if (run === 4) { 568 | four = four - 1 569 | } 570 | let six = state.six 571 | if (run === 6) { 572 | six = six - 1 573 | } 574 | return { 575 | ...state, 576 | run: updatedRun, 577 | ball: updatedBall, 578 | four: four, 579 | six: six, 580 | strikeRate: sr, 581 | } 582 | }) 583 | } 584 | } else if (batter2.onStrike) { 585 | if (run % 2 === 0) { 586 | setBatter2((state) => { 587 | const updatedRun = state.run - run 588 | const updatedBall = state.ball - 1 589 | const updatedSr = updatedRun / updatedBall 590 | const sr = Math.round(isNaN(updatedSr) ? 0 : updatedSr * 100 * 100) / 100 591 | let four = state.four 592 | if (run === 4) { 593 | four = four - 1 594 | } 595 | let six = state.six 596 | if (run === 6) { 597 | six = six - 1 598 | } 599 | return { 600 | ...state, 601 | run: updatedRun, 602 | ball: updatedBall, 603 | four: four, 604 | six: six, 605 | strikeRate: sr, 606 | } 607 | }) 608 | } else { 609 | changeStrikeRadio() 610 | switchBatterStrike() 611 | setBatter1((state) => { 612 | const updatedRun = state.run - run 613 | const updatedBall = state.ball - 1 614 | const updatedSr = updatedRun / updatedBall 615 | const sr = Math.round(isNaN(updatedSr) ? 0 : updatedSr * 100 * 100) / 100 616 | let four = state.four 617 | if (run === 4) { 618 | four = four - 1 619 | } 620 | let six = state.six 621 | if (run === 6) { 622 | six = six - 1 623 | } 624 | return { 625 | ...state, 626 | run: updatedRun, 627 | ball: updatedBall, 628 | four: four, 629 | six: six, 630 | strikeRate: sr, 631 | } 632 | }) 633 | } 634 | } 635 | } 636 | const undoDelivery = () => { 637 | if (currentRunStack.length > 0) { 638 | const last = currentRunStack[currentRunStack.length - 1] 639 | if (typeof last === 'number') { 640 | const run = parseInt(last) 641 | undoRun(run, false) 642 | } else { 643 | currentRunStack.pop() 644 | setCurrentRunStack(currentRunStack) 645 | if (last === 'wd') { 646 | setTotalRuns(totalRuns - 1) 647 | setExtras((state) => ({ 648 | ...state, 649 | total: state.total - 1, 650 | wide: state.wide - 1, 651 | })) 652 | } else if (last === 'W') { 653 | undoWicket(false) 654 | } else { 655 | const lastChar = last.substr(last.length - 1) 656 | const run = parseInt(lastChar) 657 | if (isNaN(run)) { 658 | setTotalRuns(totalRuns - 1) 659 | setRunsByOver(runsByOver - 1) 660 | if (last !== 'nb') { 661 | undoWicket(true) 662 | } 663 | } else { 664 | undoRun(run, true) 665 | } 666 | } 667 | } 668 | } 669 | } 670 | const handleStrikeChange = (e) => { 671 | changeStrikeRadio(e.target.value) 672 | if (e.target.value === 'strike') { 673 | switchBatterStrike('batter1') 674 | } else { 675 | switchBatterStrike('batter2') 676 | } 677 | } 678 | const changeStrikeRadio = (strikeParam) => { 679 | if (strikeParam === undefined) { 680 | setStrikeValue(strikeValue === 'strike' ? 'non-strike' : 'strike') 681 | } else { 682 | setStrikeValue(strikeParam) 683 | } 684 | } 685 | const switchBatterStrike = (strikeParam) => { 686 | if (strikeParam === undefined) { 687 | setBatter1((state) => ({ 688 | ...state, 689 | onStrike: !state.onStrike, 690 | })) 691 | setBatter2((state) => ({ 692 | ...state, 693 | onStrike: !state.onStrike, 694 | })) 695 | } else { 696 | if (strikeParam === 'batter1') { 697 | setBatter1((state) => ({ 698 | ...state, 699 | onStrike: true, 700 | })) 701 | setBatter2((state) => ({ 702 | ...state, 703 | onStrike: false, 704 | })) 705 | } else if (strikeParam === 'batter2') { 706 | setBatter1((state) => ({ 707 | ...state, 708 | onStrike: false, 709 | })) 710 | setBatter2((state) => ({ 711 | ...state, 712 | onStrike: true, 713 | })) 714 | } 715 | } 716 | } 717 | const handleRun = (run) => { 718 | if (isNoBall) { 719 | setCurrentRunStack((state) => [...state, 'nb' + run]) 720 | removeNoBallEffect() 721 | } else { 722 | setBallCount(ballCount + 1) 723 | setCurrentRunStack((state) => [...state, run]) 724 | } 725 | setTotalRuns(totalRuns + run) 726 | setRunsByOver(runsByOver + run) 727 | if (inningNo === 2) { 728 | if (!isNoBall) { 729 | setRemainingBalls(remainingBalls - 1) 730 | } 731 | setRemainingRuns(remainingRuns - run) 732 | } 733 | if (ballCount === 5) { 734 | if (isNoBall) { 735 | if (run % 2 !== 0) { 736 | changeStrikeRadio() 737 | } 738 | } else { 739 | setTotalOvers(overCount + 1) 740 | const arr = [...currentRunStack] 741 | arr.push(run) 742 | overCompleted(runsByOver + run, arr) 743 | if (run % 2 === 0) { 744 | changeStrikeRadio() 745 | } 746 | } 747 | } else { 748 | if (!isNoBall) { 749 | setTotalOvers(Math.round((totalOvers + 0.1) * 10) / 10) 750 | } 751 | if (run % 2 !== 0) { 752 | changeStrikeRadio() 753 | } 754 | } 755 | if (batter1.onStrike) { 756 | setBatter1((state) => { 757 | const updatedRun = state.run + run 758 | const updatedBall = state.ball + 1 759 | const sr = Math.round((updatedRun / updatedBall) * 100 * 100) / 100 760 | let four = state.four 761 | if (run === 4) { 762 | four = four + 1 763 | } 764 | let six = state.six 765 | if (run === 6) { 766 | six = six + 1 767 | } 768 | return { 769 | ...state, 770 | run: updatedRun, 771 | ball: updatedBall, 772 | four: four, 773 | six: six, 774 | strikeRate: sr, 775 | } 776 | }) 777 | if (isNoBall) { 778 | if (run % 2 !== 0) { 779 | switchBatterStrike() 780 | } 781 | } else { 782 | if ((ballCount === 5 && run % 2 === 0) || (ballCount !== 5 && run % 2 !== 0)) { 783 | switchBatterStrike() 784 | } 785 | } 786 | } else { 787 | setBatter2((state) => { 788 | const updatedRun = state.run + run 789 | const updatedBall = state.ball + 1 790 | const sr = Math.round((updatedRun / updatedBall) * 100 * 100) / 100 791 | let four = state.four 792 | if (run === 4) { 793 | four = four + 1 794 | } 795 | let six = state.six 796 | if (run === 6) { 797 | six = six + 1 798 | } 799 | return { 800 | ...state, 801 | run: updatedRun, 802 | ball: updatedBall, 803 | four: four, 804 | six: six, 805 | strikeRate: sr, 806 | } 807 | }) 808 | if ((ballCount === 5 && run % 2 === 0) || (ballCount !== 5 && run % 2 !== 0)) { 809 | switchBatterStrike() 810 | } 811 | } 812 | } 813 | const handleNoBall = () => { 814 | if (inningNo === 2) { 815 | setRemainingRuns(remainingRuns - 1) 816 | } 817 | setTotalRuns(totalRuns + 1) 818 | setRunsByOver(runsByOver + 1) 819 | setExtras((state) => ({ 820 | ...state, 821 | total: state.total + 1, 822 | noBall: state.noBall + 1, 823 | })) 824 | addNoBallEffect() 825 | } 826 | const addNoBallEffect = () => { 827 | const scoreTypesButtons = document.querySelectorAll('.score-types-button') 828 | for (let i = 0; i < scoreTypesButtons.length; i++) { 829 | scoreTypesButtons[i].classList.add('score-types-button-noball') 830 | } 831 | setNoBall(true) 832 | } 833 | const removeNoBallEffect = () => { 834 | const scoreTypesButtons = document.querySelectorAll('.score-types-button') 835 | for (let i = 0; i < scoreTypesButtons.length; i++) { 836 | scoreTypesButtons[i].classList.remove('score-types-button-noball') 837 | } 838 | setNoBall(false) 839 | } 840 | const handleWide = () => { 841 | if (isNoBall) { 842 | setCurrentRunStack((state) => [...state, 'nb']) 843 | removeNoBallEffect() 844 | } else { 845 | if (inningNo === 2) { 846 | setRemainingRuns(remainingRuns - 1) 847 | } 848 | setCurrentRunStack((state) => [...state, 'wd']) 849 | setTotalRuns(totalRuns + 1) 850 | setRunsByOver(runsByOver + 1) 851 | setExtras((state) => ({ 852 | ...state, 853 | total: state.total + 1, 854 | wide: state.wide + 1, 855 | })) 856 | } 857 | } 858 | const handleWicket = (isRunOut, playerId) => { 859 | setRunOutPlayerId('') 860 | if (ballCount === 5) { 861 | if (isNoBall) { 862 | removeNoBallEffect() 863 | if (isRunOut) { 864 | setCurrentRunStack((state) => [...state, 'nbW']) 865 | setWicketCount(wicketCount + 1) 866 | disableAllScoreButtons() 867 | } else { 868 | setCurrentRunStack((state) => [...state, 'nb']) 869 | } 870 | } else { 871 | setTotalOvers(overCount + 1) 872 | const arr = [...currentRunStack] 873 | arr.push('W') 874 | overCompleted(runsByOver, arr) 875 | setWicketCount(wicketCount + 1) 876 | disableAllScoreButtons() 877 | } 878 | } else { 879 | if (isNoBall) { 880 | removeNoBallEffect() 881 | if (isRunOut) { 882 | setCurrentRunStack((state) => [...state, 'nbW']) 883 | setWicketCount(wicketCount + 1) 884 | disableAllScoreButtons() 885 | } else { 886 | setCurrentRunStack((state) => [...state, 'nb']) 887 | } 888 | } else { 889 | setBallCount(ballCount + 1) 890 | setCurrentRunStack((state) => [...state, 'W']) 891 | setTotalOvers(Math.round((totalOvers + 0.1) * 10) / 10) 892 | setWicketCount(wicketCount + 1) 893 | disableAllScoreButtons() 894 | } 895 | } 896 | if (isRunOut) { 897 | if (batter1.id === playerId) { 898 | newBatter1() 899 | changeStrikeRadio('strike') 900 | switchBatterStrike('batter1') 901 | } else { 902 | newBatter2() 903 | changeStrikeRadio('non-strike') 904 | switchBatterStrike('batter2') 905 | } 906 | } else { 907 | if (!isNoBall) { 908 | if (batter1.onStrike) { 909 | newBatter1() 910 | } else { 911 | newBatter2() 912 | } 913 | } 914 | } 915 | if (isNoBall) { 916 | if (isRunOut && wicketCount + 1 === 10) { 917 | const endInningButton = document.getElementById('end-inning') 918 | endInningButton.disabled = false 919 | const bowlerNameElement = document.querySelector('.react-autosuggest__input') 920 | bowlerNameElement.disabled = true 921 | const batter1NameElement = document.getElementById('batter1Name') 922 | batter1NameElement.disabled = true 923 | const batter2NameElement = document.getElementById('batter2Name') 924 | batter2NameElement.disabled = true 925 | setInputBowler('') 926 | } 927 | } else { 928 | if (wicketCount + 1 === 10) { 929 | const endInningButton = document.getElementById('end-inning') 930 | endInningButton.disabled = false 931 | const bowlerNameElement = document.querySelector('.react-autosuggest__input') 932 | bowlerNameElement.disabled = true 933 | const batter1NameElement = document.getElementById('batter1Name') 934 | batter1NameElement.disabled = true 935 | const batter2NameElement = document.getElementById('batter2Name') 936 | batter2NameElement.disabled = true 937 | setInputBowler('') 938 | } 939 | } 940 | } 941 | const handleCloseModal = () => { 942 | if (outType !== '') { 943 | if (outType === RUN_OUT) { 944 | if (runOutPlayerId !== '') { 945 | handleWicket(true, runOutPlayerId) 946 | } 947 | } else { 948 | handleWicket(false, '') 949 | } 950 | } 951 | setModalOpen(false) 952 | setOutType('') 953 | setRunOutPlayerId('') 954 | } 955 | const handleOutTypeChange = (e) => { 956 | const outTypeValue = e.target.value 957 | setOutType(outTypeValue) 958 | if (outTypeValue === RUN_OUT) { 959 | const runOutPlayerElement = document.getElementById('run-out-player') 960 | runOutPlayerElement.classList.remove('hide') 961 | const runOutPlayerErrorElement = document.getElementById('run-out-player-error') 962 | runOutPlayerErrorElement.classList.remove('hide') 963 | } 964 | } 965 | const handleRunOutPlayerChange = (e) => { 966 | const playerId = e.target.value 967 | const runOutPlayerErrorElement = document.getElementById('run-out-player-error') 968 | runOutPlayerErrorElement.classList.add('hide') 969 | setRunOutPlayerId(playerId) 970 | } 971 | const endMatch = () => { 972 | disableAllScoreButtons() 973 | const endInningButton = document.getElementById('end-inning') 974 | if (endInningButton.textContent === 'Score Board') { 975 | endInningButton.disabled = false 976 | } 977 | } 978 | const disableAllScoreButtons = () => { 979 | const scoreTypesButtons = document.querySelectorAll('.score-types-button') 980 | for (let i = 0; i < scoreTypesButtons.length; i++) { 981 | scoreTypesButtons[i].disabled = true 982 | } 983 | } 984 | const enableAllScoreButtons = () => { 985 | const scoreTypesButtons = document.querySelectorAll('.score-types-button') 986 | for (let i = 0; i < scoreTypesButtons.length; i++) { 987 | scoreTypesButtons[i].disabled = false 988 | } 989 | } 990 | if (batter1.name !== undefined && batter2.name !== undefined && inputBowler !== '') { 991 | enableAllScoreButtons() 992 | } 993 | let rrr = (remainingRuns / (remainingBalls / 6)).toFixed(2) 994 | rrr = isFinite(rrr) ? rrr : 0 995 | const overs = overCount + ballCount / 6 996 | let crr = (totalRuns / overs).toFixed(2) 997 | crr = isFinite(crr) ? crr : 0 998 | const inning1 = match.inning1 999 | const inning2 = match.inning2 1000 | const scoringTeam = batting === team1 ? team1 : team2 1001 | const chessingTeam = scoringTeam === team1 ? team2 : team1 1002 | let winningMessage = `${inningNo === 1 ? scoringTeam : chessingTeam} needs ${remainingRuns} ${ 1003 | remainingRuns <= 1 ? 'run' : 'runs' 1004 | } in ${remainingBalls} ${remainingBalls <= 1 ? 'ball' : 'balls'} to win` 1005 | if (inningNo === 2) { 1006 | var target = inning1.runs + 1 1007 | if (wicketCount < 10 && overCount <= maxOver && totalRuns >= target) { 1008 | winningMessage = `${chessingTeam} won by ${10 - wicketCount} wickets` 1009 | endMatch() 1010 | } 1011 | if ((wicketCount >= 10 || overCount >= maxOver) && totalRuns < target - 1) { 1012 | winningMessage = `${scoringTeam} won by ${target - totalRuns - 1} runs` 1013 | endMatch() 1014 | } 1015 | if (wicketCount < 10 && overCount === maxOver && totalRuns === target - 1) { 1016 | winningMessage = 'Match Tied' 1017 | endMatch() 1018 | } 1019 | } 1020 | const welcomeContent = ( 1021 | <> 1022 |
1023 |
Welcome to Gully Cricket Score Board
1024 |
1025 | 1026 | ) 1027 | const firstInningCompletedContent = ( 1028 | <> 1029 | {overCount === maxOver &&
1st inning completed
} 1030 | {wicketCount === 10 &&
All Out
} 1031 |
Please click "End Inning" button
1032 | 1033 | ) 1034 | const remainingRunsContent = ( 1035 | <> 1036 |
Target: {target}
1037 |
{winningMessage}
1038 |
RRR: {isNaN(rrr) ? 0 : rrr}
1039 | 1040 | ) 1041 | return ( 1042 |
1043 |
1044 |
1045 | {team1} vs {team2}, {inningNo === 1 ? '1st' : '2nd'} Inning 1046 |
1047 |
1048 | 1051 |
1052 |
1053 |
1054 | {inningNo === 2 ? remainingRunsContent : overCount === maxOver || wicketCount === 10 ? firstInningCompletedContent : welcomeContent} 1055 |
1056 |
1057 |
1058 | 1064 | 1065 | 1066 | 1073 | 1083 | } 1084 | label={CATCH} 1085 | /> 1086 | 1096 | } 1097 | label={STUMP} 1098 | /> 1099 | 1109 | } 1110 | label={HIT_WICKET} 1111 | /> 1112 | 1122 | } 1123 | label={BOLD} 1124 | /> 1125 | 1135 | } 1136 | label={RUN_OUT} 1137 | /> 1138 | 1145 | 1146 |
1147 | Please select run out player name 1148 |
1149 |
1150 |
1151 |
1152 |
1153 |
1154 |
1155 | {inningNo === 1 ? scoringTeam : chessingTeam} : {totalRuns}/{wicketCount} ({totalOvers}) 1156 |
1157 |
CRR : {isNaN(crr) ? 0 : crr}
1158 |
1159 |
1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 |
BattingR(B)4s6sSR
1173 | 1174 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | {batter1.run === undefined ? `0(0)` : `${batter1.run}(${batter1.ball})`}{batter1.four === undefined ? 0 : batter1.four}{batter1.six === undefined ? 0 : batter1.six}{batter1.strikeRate === undefined ? 0 : batter1.strikeRate}
1196 | 1197 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | {batter2.run === undefined ? `0(0)` : `${batter2.run}(${batter2.ball})`}{batter2.four === undefined ? 0 : batter2.four}{batter2.six === undefined ? 0 : batter2.six}{batter2.strikeRate === undefined ? 0 : batter2.strikeRate}
1219 |
1220 |
1221 |
1222 | Bowler: 1223 | { 1227 | setSuggestions([]) 1228 | }} 1229 | getSuggestionValue={getSuggestionValue} 1230 | renderSuggestion={(suggestion) =>
{suggestion.name}
} 1231 | inputProps={inputProps} 1232 | /> 1233 | 1234 | 1235 | 1236 |
1237 |
1238 | {currentRunStack.map((run, i) => ( 1239 |
{run}
1240 | ))} 1241 | 1242 | 1243 | 1244 |
1245 |
1246 |
1247 | 1248 | 1249 | 1250 | 1255 | 1260 | 1265 | 1270 | 1275 | 1276 | 1277 | 1282 | 1287 | 1292 | 1297 | 1298 | 1299 |
handleRun(0)}> 1251 | 1254 | handleRun(1)}> 1256 | 1259 | handleRun(2)}> 1261 | 1264 | 1266 | 1269 | setModalOpen(true)}> 1271 | 1274 |
handleRun(3)}> 1278 | 1281 | handleRun(4)}> 1283 | 1286 | handleRun(6)}> 1288 | 1291 | 1293 | 1296 |
1300 |
1301 |
1302 |
Extras: {extras.total}
1303 |
Wd: {extras.wide}
1304 |
NB: {extras.noBall}
1305 |
1306 |
1307 |
Recent Overs
1308 |
1309 | 1310 | 1311 | {recentOvers.map((recentOver, i) => ( 1312 | 1313 | 1314 | 1315 | 1322 | 1325 | 1326 | ))} 1327 | 1328 |
{recentOver.overNo}.{recentOver.bowler}: 1316 |
1317 | {recentOver.stack.map((run, index) => ( 1318 |
{run}
1319 | ))} 1320 |
1321 |
1323 |
{recentOver.runs}
1324 |
1329 |
1330 |
1331 |
1332 |
Score Board
1333 | {/* Inning1 Starts here */} 1334 |
1335 |
1336 |
{scoringTeam} Innings
1337 |
RR:{inningNo === 1 ? crr : inning1.runRate}
1338 |
1339 | {inningNo === 1 ? totalRuns : inning1.runs}-{inningNo === 1 ? wicketCount : inning1.wickets} ( 1340 | {inningNo === 1 ? totalOvers : inning1.overs} Ov) 1341 |
1342 |
1343 |
1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | {inning1.batters.map((batter, i) => { 1356 | return ( 1357 | 1358 | 1359 | 1362 | 1363 | 1364 | 1365 | 1366 | ) 1367 | })} 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | 1374 | 1375 | 1376 |
BatterR(B)4s6sSR
{batter.name} 1360 | {batter.run}({batter.ball}) 1361 | {batter.four}{batter.six}{batter.strikeRate}
Extras:{inningNo === 1 ? extras.total : inning1.extra.total}wd:{inningNo === 1 ? extras.wide : inning1.extra.wide}nb:{inningNo === 1 ? extras.noBall : inning1.extra.noBall}
1377 |
1378 |
1379 | 1380 | 1381 | 1382 | 1383 | 1384 | 1385 | 1386 | 1387 | 1388 | 1389 | 1390 | 1391 | 1392 | 1393 | {inning1.bowlers.map((blr, i) => { 1394 | const { name, over, maiden, run, wicket, noBall, wide, economy } = blr 1395 | return ( 1396 | 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | ) 1407 | })} 1408 | 1409 |
BowlerOMRWNBWDECO
{name}{over}{maiden}{run}{wicket}{noBall}{wide}{economy}
1410 |
1411 |
1412 | {/* Inning2 Starts here */} 1413 | {inningNo === 2 && ( 1414 |
1415 |
1416 |
{chessingTeam} Innings
1417 |
RR:{inningNo === 2 ? crr : inning2.runRate}
1418 |
1419 | {hasMatchEnded ? inning2.runs : totalRuns}-{hasMatchEnded ? inning2.wickets : wicketCount} ( 1420 | {hasMatchEnded ? inning2.overs : totalOvers} Ov) 1421 |
1422 |
1423 |
1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | {inning2.batters.map((batter, i) => { 1436 | return ( 1437 | 1438 | 1439 | 1442 | 1443 | 1444 | 1445 | 1446 | ) 1447 | })} 1448 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 | 1456 |
BatterR(B)4s6sSR
{batter.name} 1440 | {batter.run}({batter.ball}) 1441 | {batter.four}{batter.six}{batter.strikeRate}
Extras:{hasMatchEnded ? inning2.extra.total : extras.total}wd:{hasMatchEnded ? inning2.extra.wide : extras.wide}nb:{hasMatchEnded ? inning2.extra.noBall : extras.noBall}
1457 |
1458 |
1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | {inning2.bowlers.map((blr, i) => { 1474 | const { name, over, maiden, run, wicket, noBall, wide, economy } = blr 1475 | return ( 1476 | 1477 | 1478 | 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | 1485 | 1486 | ) 1487 | })} 1488 | 1489 |
BowlerOMRWNBWDECO
{name}{over}{maiden}{run}{wicket}{noBall}{wide}{economy}
1490 |
1491 |
1492 | )} 1493 |
1494 |
1495 |
1496 | ) 1497 | } 1498 | 1499 | export default ScoreBoard 1500 | --------------------------------------------------------------------------------