1 changed files with 162 additions and 0 deletions
@ -0,0 +1,162 @@ |
|||
import React from "react"; |
|||
import { Text, TouchableOpacity, View, SafeAreaView } from "react-native"; |
|||
import { useState, useEffect, useRef, useMemo } from "react"; |
|||
import { useDispatch } from "react-redux"; |
|||
import {generateAdditionChallenge} from '../libs/Random'; |
|||
import { styles } from "./styles/AppStyles"; |
|||
import NineKey from "../components/NineKey"; |
|||
import Autoscroll from "../components/Autoscroll"; |
|||
import Fade from "../components/Fade"; |
|||
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; |
|||
import Icons from '../themes/Icons'; |
|||
import Colors from "../themes/Colors"; |
|||
import Metrics from "../themes/Metrics"; |
|||
|
|||
function AdditionGame(props){ |
|||
|
|||
const [addChallenge, setAddChallenge]= useState(() => {return generateAdditionChallenge()}); |
|||
const challengeState = useRef(-1); |
|||
const squareMemo = useMemo(renderPairs, [challengeState.current]); |
|||
const [timerState, setTimerState] = useState(0); |
|||
const localTimer = useRef(null); |
|||
const startTime = useRef(0); |
|||
const answers = useRef(0); |
|||
const [scrollOrigin, setScrollOrigin] = useState(0); |
|||
const scrollDestination = useRef(Metrics.animated.gameScrollInterval); |
|||
const [headerText, setHeaderText] = useState('Ready?'); |
|||
const [headerColor, setHeaderColor] = useState(styles.green); |
|||
const [headerTextColor, setHeaderTextColor] = useState(styles.darkText); |
|||
const dispatch = useDispatch(); |
|||
|
|||
useEffect(() => { |
|||
let headerTimeout = null; |
|||
|
|||
switch(timerState){ |
|||
case 0: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.yellow); |
|||
setHeaderText('Set'); |
|||
setTimerState(1); |
|||
}, 1000); |
|||
break; |
|||
case 1: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.red); |
|||
setHeaderTextColor(styles.lightText); |
|||
setHeaderText('Go!'); |
|||
challengeState.current = 0; |
|||
setTimerState(2); |
|||
}, 1000); |
|||
break; |
|||
case 2: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.dark); |
|||
startTime.current = (Date.now()); |
|||
setHeaderText(0 + ' s'); |
|||
setTimerState(3); |
|||
}, 1000); |
|||
break; |
|||
case 3: |
|||
headerTimeout = setInterval(() => { |
|||
let elapsed = Math.round((Date.now() - startTime.current) / (1000)); |
|||
setHeaderText(elapsed + ' s'); |
|||
}, 1000); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
localTimer.current = headerTimeout; |
|||
|
|||
return () => { |
|||
clearTimeout(localTimer.current); |
|||
clearInterval(localTimer.current); |
|||
} |
|||
}, [timerState]); |
|||
|
|||
|
|||
|
|||
function selectAnswer(answer){ |
|||
//fix
|
|||
if (true) { |
|||
answers.current = answers.current + 1; |
|||
} |
|||
|
|||
let newOrigin = scrollDestination.current; |
|||
let newDestination = scrollDestination.current - Metrics.animated.gameScrollInterval; |
|||
|
|||
scrollDestination.current = newDestination; |
|||
challengeState.current = challengeState.current + 1; |
|||
setScrollOrigin(newOrigin); |
|||
|
|||
if (challengeState.current >= 20) { |
|||
completeChallenge(); |
|||
} |
|||
} |
|||
|
|||
function completeChallenge(){ |
|||
let unformatted = (Date.now() - startTime.current) / (1000); |
|||
let finalTime = Number.parseFloat(unformatted).toFixed(3); |
|||
clearInterval(localTimer.current); |
|||
setHeaderColor(styles.darkGreen); |
|||
setHeaderText(finalTime + ' s'); |
|||
setTimerState(4); |
|||
// dispatch(squareFinished(answers.current, finalTime));
|
|||
} |
|||
|
|||
function generateLine(left, right, pairIndex) { |
|||
return ( |
|||
<Fade key={pairIndex} faded={challengeState.current !== pairIndex} duration={250}> |
|||
<View style={[styles.buttonMargin]}> |
|||
<Text style={[styles.headerTitleFont, styles.darkText, styles.centeredText]}> |
|||
{left + ' + ' + right + ' = '} |
|||
</Text> |
|||
</View> |
|||
</Fade> |
|||
); |
|||
} |
|||
|
|||
function renderPairs(){ |
|||
return addChallenge.map((pair, index) => { |
|||
return generateLine(pair.left, pair.right, index); |
|||
}); |
|||
} |
|||
|
|||
return ( |
|||
<SafeAreaView style={styles.flex}> |
|||
<View style={[styles.timerView, headerColor, styles.centeredJustify]}> |
|||
<Text style={[headerTextColor, styles.headerTitleFont, styles.centeredText]}> |
|||
{headerText} |
|||
</Text> |
|||
</View> |
|||
<View style={[styles.flex, styles.flexColumn]}> |
|||
<Autoscroll |
|||
origin={scrollOrigin} |
|||
destination={scrollDestination.current} |
|||
duration={250} |
|||
> |
|||
<View style={[styles.gameView]} /> |
|||
{squareMemo} |
|||
<View style={[styles.gameView, styles.flexRow, styles.spaceEvenly, styles.centeredItems]}> |
|||
<MaterialIcon |
|||
name={Icons.squareIcons.check} |
|||
color={Colors.material.green800} |
|||
size={Metrics.icons.buttonIcon} |
|||
/> |
|||
<Text style={[styles.headerTitleFont, styles.greyText]}> |
|||
Finish |
|||
</Text> |
|||
</View> |
|||
</Autoscroll> |
|||
</View> |
|||
<View style={[styles.timerView, styles.dark, styles.centeredJustify]}> |
|||
<Text style={[styles.lightText, styles.headerTitleFont, styles.centeredText]}> |
|||
{answers.current + ' / ' + addChallenge.length} |
|||
</Text> |
|||
</View> |
|||
<NineKey onPress={selectAnswer}/> |
|||
</SafeAreaView> |
|||
); |
|||
} |
|||
|
|||
export default AdditionGame; |
Loading…
Reference in new issue