├── 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 |       
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 |
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 |
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 | | handleRun(0)}>
1251 |
1254 | |
1255 | handleRun(1)}>
1256 |
1259 | |
1260 | handleRun(2)}>
1261 |
1264 | |
1265 |
1266 |
1269 | |
1270 | setModalOpen(true)}>
1271 |
1274 | |
1275 |
1276 |
1277 | | handleRun(3)}>
1278 |
1281 | |
1282 | handleRun(4)}>
1283 |
1286 | |
1287 | handleRun(6)}>
1288 |
1291 | |
1292 |
1293 |
1296 | |
1297 |
1298 |
1299 |
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 | | {recentOver.overNo}. |
1314 | {recentOver.bowler}: |
1315 |
1316 |
1317 | {recentOver.stack.map((run, index) => (
1318 | {run}
1319 | ))}
1320 |
1321 | |
1322 |
1323 | {recentOver.runs}
1324 | |
1325 |
1326 | ))}
1327 |
1328 |
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 | | Batter |
1348 | R(B) |
1349 | 4s |
1350 | 6s |
1351 | SR |
1352 |
1353 |
1354 |
1355 | {inning1.batters.map((batter, i) => {
1356 | return (
1357 |
1358 | | {batter.name} |
1359 |
1360 | {batter.run}({batter.ball})
1361 | |
1362 | {batter.four} |
1363 | {batter.six} |
1364 | {batter.strikeRate} |
1365 |
1366 | )
1367 | })}
1368 |
1369 | | Extras: |
1370 | {inningNo === 1 ? extras.total : inning1.extra.total} |
1371 | wd:{inningNo === 1 ? extras.wide : inning1.extra.wide} |
1372 | nb:{inningNo === 1 ? extras.noBall : inning1.extra.noBall} |
1373 | |
1374 |
1375 |
1376 |
1377 |
1378 |
1379 |
1380 |
1381 |
1382 | | Bowler |
1383 | O |
1384 | M |
1385 | R |
1386 | W |
1387 | NB |
1388 | WD |
1389 | ECO |
1390 |
1391 |
1392 |
1393 | {inning1.bowlers.map((blr, i) => {
1394 | const { name, over, maiden, run, wicket, noBall, wide, economy } = blr
1395 | return (
1396 |
1397 | | {name} |
1398 | {over} |
1399 | {maiden} |
1400 | {run} |
1401 | {wicket} |
1402 | {noBall} |
1403 | {wide} |
1404 | {economy} |
1405 |
1406 | )
1407 | })}
1408 |
1409 |
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 | | Batter |
1428 | R(B) |
1429 | 4s |
1430 | 6s |
1431 | SR |
1432 |
1433 |
1434 |
1435 | {inning2.batters.map((batter, i) => {
1436 | return (
1437 |
1438 | | {batter.name} |
1439 |
1440 | {batter.run}({batter.ball})
1441 | |
1442 | {batter.four} |
1443 | {batter.six} |
1444 | {batter.strikeRate} |
1445 |
1446 | )
1447 | })}
1448 |
1449 | | Extras: |
1450 | {hasMatchEnded ? inning2.extra.total : extras.total} |
1451 | wd:{hasMatchEnded ? inning2.extra.wide : extras.wide} |
1452 | nb:{hasMatchEnded ? inning2.extra.noBall : extras.noBall} |
1453 | |
1454 |
1455 |
1456 |
1457 |
1458 |
1459 |
1460 |
1461 |
1462 | | Bowler |
1463 | O |
1464 | M |
1465 | R |
1466 | W |
1467 | NB |
1468 | WD |
1469 | ECO |
1470 |
1471 |
1472 |
1473 | {inning2.bowlers.map((blr, i) => {
1474 | const { name, over, maiden, run, wicket, noBall, wide, economy } = blr
1475 | return (
1476 |
1477 | | {name} |
1478 | {over} |
1479 | {maiden} |
1480 | {run} |
1481 | {wicket} |
1482 | {noBall} |
1483 | {wide} |
1484 | {economy} |
1485 |
1486 | )
1487 | })}
1488 |
1489 |
1490 |
1491 |
1492 | )}
1493 |
1494 |
1495 |
1496 | )
1497 | }
1498 |
1499 | export default ScoreBoard
1500 |
--------------------------------------------------------------------------------