Cleanup code
This commit is contained in:
parent
eaf95c395e
commit
f6bc13bfb9
|
@ -1,4 +1,4 @@
|
|||
# Kana Quiz 2
|
||||
# Kana Quiz
|
||||
Kana Quiz made with React.js.
|
||||
|
||||
See live at https://kana.pro/
|
||||
|
|
|
@ -7,20 +7,13 @@ import { removeHash } from '../../data/helperFuncs';
|
|||
const options = {};
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
gameState: 'chooseCharacters'
|
||||
}
|
||||
this.startGame = this.startGame.bind(this);
|
||||
this.endGame = this.endGame.bind(this);
|
||||
}
|
||||
state = { gameState: 'chooseCharacters' };
|
||||
|
||||
startGame() {
|
||||
startGame = () => {
|
||||
this.setState({gameState: 'game'});
|
||||
}
|
||||
|
||||
endGame() {
|
||||
endGame = () => {
|
||||
this.setState({gameState: 'chooseCharacters'});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
import React, { Component } from 'react';
|
||||
|
||||
class CharacterGroup extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shownChars : '',
|
||||
}
|
||||
this.changeShownChars = this.changeShownChars.bind(this);
|
||||
}
|
||||
state = { shownChars: '' }
|
||||
|
||||
changeShownChars(newString, e) {
|
||||
changeShownChars(newString) {
|
||||
this.setState({shownChars: newString})
|
||||
}
|
||||
|
||||
getShowableCharacters(whichKana) {
|
||||
let strRomajiCharacters = '';
|
||||
let strKanaCharacters = '';
|
||||
Object.keys(this.props.characters).map(function(character) {
|
||||
Object.keys(this.props.characters).map(character => {
|
||||
strRomajiCharacters+=this.props.characters[character][0]+' · ';
|
||||
strKanaCharacters+=character+' · ';
|
||||
}, this);
|
||||
});
|
||||
strRomajiCharacters = strRomajiCharacters.slice(0, -2);
|
||||
strKanaCharacters = strKanaCharacters.slice(0, -2);
|
||||
if(whichKana=='romaji') return strRomajiCharacters;
|
||||
|
@ -32,7 +26,8 @@ class CharacterGroup extends Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<div className={
|
||||
<div
|
||||
className={
|
||||
'choose-row' + (this.props.groupName.endsWith('_a') || this.props.groupName.endsWith('_s') ? ' alt-row' : '')
|
||||
}
|
||||
onClick={() => {
|
||||
|
|
|
@ -5,19 +5,13 @@ import './ChooseCharacters.scss';
|
|||
import CharacterGroup from './CharacterGroup';
|
||||
|
||||
class ChooseCharacters extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
state = {
|
||||
errMsg : '',
|
||||
selectedGroups: this.props.selectedGroups,
|
||||
showAlternatives: [],
|
||||
showSimilars: [],
|
||||
startIsVisible: true
|
||||
}
|
||||
this.toggleSelect = this.toggleSelect.bind(this);
|
||||
this.startGame = this.startGame.bind(this);
|
||||
this.testIsStartVisible = this.testIsStartVisible.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.testIsStartVisible();
|
||||
|
@ -34,7 +28,7 @@ class ChooseCharacters extends Component {
|
|||
this.testIsStartVisible();
|
||||
}
|
||||
|
||||
testIsStartVisible() {
|
||||
testIsStartVisible = () => {
|
||||
if(this.startRef) {
|
||||
const rect = this.startRef.getBoundingClientRect();
|
||||
if(rect.y > window.innerHeight && this.state.startIsVisible)
|
||||
|
@ -73,7 +67,7 @@ class ChooseCharacters extends Component {
|
|||
this.setState({errMsg: '', selectedGroups: this.state.selectedGroups.concat(groupName)});
|
||||
}
|
||||
|
||||
toggleSelect(groupName) {
|
||||
toggleSelect = groupName => {
|
||||
if(this.getIndex(groupName) > -1)
|
||||
this.removeSelect(groupName);
|
||||
else
|
||||
|
@ -214,7 +208,7 @@ class ChooseCharacters extends Component {
|
|||
<div className="col-xs-12">
|
||||
<div className="panel panel-default">
|
||||
<div className="panel-body welcome">
|
||||
<h4>Welcome to Kana Quiz!</h4>
|
||||
<h4>Welcome to Kana Pro!</h4>
|
||||
<p>Please choose the groups of characters that you'd like to be studying.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -266,7 +260,7 @@ class ChooseCharacters extends Component {
|
|||
this.state.errMsg != '' &&
|
||||
<div className="error-message">{this.state.errMsg}</div>
|
||||
}
|
||||
<button ref={c => this.startRef = c} className="btn btn-danger startgame-button" onClick={this.startGame}>Start the Quiz!</button>
|
||||
<button ref={c => this.startRef = c} className="btn btn-danger startgame-button" onClick={() => this.startGame()}>Start the Quiz!</button>
|
||||
</div>
|
||||
<div className="down-arrow"
|
||||
style={{display: this.state.startIsVisible ? 'none' : 'block'}}
|
||||
|
|
|
@ -4,39 +4,37 @@ import ShowStage from './ShowStage';
|
|||
import Question from './Question';
|
||||
|
||||
class Game extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showScreen: ''
|
||||
}
|
||||
this.showQuestion = this.showQuestion.bind(this);
|
||||
this.stageUp = this.stageUp.bind(this);
|
||||
this.lockStage = this.lockStage.bind(this);
|
||||
}
|
||||
|
||||
stageUp() {
|
||||
this.props.stageUp();
|
||||
this.setState({showScreen: 'stage'});
|
||||
}
|
||||
|
||||
lockStage(stage) {
|
||||
this.setState({showScreen: 'question'});
|
||||
this.props.lockStage(stage);
|
||||
}
|
||||
|
||||
showQuestion() {
|
||||
this.setState({showScreen: 'question'})
|
||||
}
|
||||
state = { showScreen: '' }
|
||||
|
||||
componentWillMount() {
|
||||
this.setState({showScreen: 'stage'});
|
||||
}
|
||||
|
||||
stageUp = () => {
|
||||
this.props.stageUp();
|
||||
this.setState({showScreen: 'stage'});
|
||||
}
|
||||
|
||||
lockStage = stage => {
|
||||
this.setState({showScreen: 'question'});
|
||||
this.props.lockStage(stage);
|
||||
}
|
||||
|
||||
showQuestion = () => {
|
||||
this.setState({showScreen: 'question'})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{ this.state.showScreen==='stage' ? <ShowStage lockStage={this.lockStage} handleShowQuestion={this.showQuestion} handleEndGame={this.props.handleEndGame} stage={this.props.stage} /> : '' }
|
||||
{ this.state.showScreen==='question' ? <Question isLocked={this.props.isLocked} handleStageUp={this.stageUp} stage={this.props.stage} decidedGroups={this.props.decidedGroups} /> : '' }
|
||||
{
|
||||
this.state.showScreen==='stage' &&
|
||||
<ShowStage lockStage={this.lockStage} handleShowQuestion={this.showQuestion} handleEndGame={this.props.handleEndGame} stage={this.props.stage} />
|
||||
}
|
||||
{
|
||||
this.state.showScreen==='question' &&
|
||||
<Question isLocked={this.props.isLocked} handleStageUp={this.stageUp} stage={this.props.stage} decidedGroups={this.props.decidedGroups} />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,7 @@ import { findRomajisAtKanaKey, removeFromArray, arrayContains, shuffle, cartesia
|
|||
import './Question.scss';
|
||||
|
||||
class Question extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
state = {
|
||||
previousQuestion: [],
|
||||
previousAnswer: '',
|
||||
currentAnswer: '',
|
||||
|
@ -15,11 +13,11 @@ class Question extends Component {
|
|||
answerOptions: [],
|
||||
stageProgress: 0
|
||||
}
|
||||
this.setNewQuestion = this.setNewQuestion.bind(this);
|
||||
this.handleAnswer = this.handleAnswer.bind(this);
|
||||
this.handleAnswerChange = this.handleAnswerChange.bind(this);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
}
|
||||
// this.setNewQuestion = this.setNewQuestion.bind(this);
|
||||
// this.handleAnswer = this.handleAnswer.bind(this);
|
||||
// this.handleAnswerChange = this.handleAnswerChange.bind(this);
|
||||
// this.handleSubmit = this.handleSubmit.bind(this);
|
||||
// }
|
||||
|
||||
getRandomKanas(amount, include, exclude) {
|
||||
let randomizedKanas = this.askableKanaKeys.slice();
|
||||
|
@ -41,22 +39,22 @@ class Question extends Component {
|
|||
|
||||
// let's remove kanas that have the same answer as included
|
||||
let searchFor = findRomajisAtKanaKey(include, kanaDictionary)[0];
|
||||
randomizedKanas = randomizedKanas.filter(function(character) {
|
||||
randomizedKanas = randomizedKanas.filter(character => {
|
||||
return searchFor!=findRomajisAtKanaKey(character, kanaDictionary)[0];
|
||||
}, this);
|
||||
});
|
||||
|
||||
// now let's remove "duplicate" kanas (if two kanas have same answers)
|
||||
let tempRandomizedKanas = randomizedKanas.slice();
|
||||
randomizedKanas = randomizedKanas.filter(function(r) {
|
||||
randomizedKanas = randomizedKanas.filter(r => {
|
||||
let dupeFound = false;
|
||||
searchFor = findRomajisAtKanaKey(r, kanaDictionary)[0];
|
||||
tempRandomizedKanas.shift();
|
||||
tempRandomizedKanas.map(function(w) {
|
||||
tempRandomizedKanas.forEach(w => {
|
||||
if(findRomajisAtKanaKey(w, kanaDictionary)[0]==searchFor)
|
||||
dupeFound = true;
|
||||
}, this);
|
||||
});
|
||||
return !dupeFound;
|
||||
}, this);
|
||||
});
|
||||
|
||||
// alright, let's cut the array and add included to the end
|
||||
randomizedKanas = randomizedKanas.slice(0, amount-1); // -1 so we have room to add included
|
||||
|
@ -97,18 +95,18 @@ class Question extends Component {
|
|||
else if(this.props.stage==4) {
|
||||
let tempAllowedAnswers = [];
|
||||
|
||||
this.currentQuestion.map(function(key, idx) {
|
||||
this.currentQuestion.forEach(key => {
|
||||
tempAllowedAnswers.push(findRomajisAtKanaKey(key, kanaDictionary));
|
||||
}, this);
|
||||
});
|
||||
|
||||
cartesianProduct(tempAllowedAnswers).map(function(answer) {
|
||||
cartesianProduct(tempAllowedAnswers).forEach(answer => {
|
||||
this.allowedAnswers.push(answer.join(''));
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
// console.log(this.allowedAnswers);
|
||||
}
|
||||
|
||||
handleAnswer(answer) {
|
||||
handleAnswer = answer => {
|
||||
if(this.props.stage<=2) document.activeElement.blur(); // reset answer button's :active
|
||||
this.previousQuestion = this.currentQuestion;
|
||||
this.setState({previousQuestion: this.previousQuestion});
|
||||
|
@ -120,10 +118,8 @@ class Question extends Component {
|
|||
else
|
||||
this.stageProgress = this.stageProgress > 0 ? this.stageProgress - 1 : 0;
|
||||
this.setState({stageProgress: this.stageProgress});
|
||||
if(this.stageProgress >= quizSettings.stageLength[this.props.stage] &&
|
||||
!this.props.isLocked) {
|
||||
let that = this;
|
||||
setTimeout(function() { that.props.handleStageUp(); }, 300);
|
||||
if(this.stageProgress >= quizSettings.stageLength[this.props.stage] && !this.props.isLocked) {
|
||||
setTimeout(() => { this.props.handleStageUp() }, 300);
|
||||
}
|
||||
else
|
||||
this.setNewQuestion();
|
||||
|
@ -136,22 +132,22 @@ class Question extends Component {
|
|||
this.previousQuestion = '';
|
||||
this.previousAnswer = '';
|
||||
this.stageProgress = 0;
|
||||
Object.keys(kanaDictionary).map(function(whichKana) {
|
||||
Object.keys(kanaDictionary).forEach(whichKana => {
|
||||
// console.log(whichKana); // 'hiragana' or 'katakana'
|
||||
Object.keys(kanaDictionary[whichKana]).map(function(groupName) {
|
||||
Object.keys(kanaDictionary[whichKana]).forEach(groupName => {
|
||||
// console.log(groupName); // 'h_group1', ...
|
||||
// do we want to include this group?
|
||||
if(arrayContains(groupName, this.props.decidedGroups)) {
|
||||
// let's merge the group to our askableKanas
|
||||
this.askableKanas = Object.assign(this.askableKanas, kanaDictionary[whichKana][groupName]['characters']);
|
||||
Object.keys(kanaDictionary[whichKana][groupName]['characters']).map(function(key) {
|
||||
Object.keys(kanaDictionary[whichKana][groupName]['characters']).forEach(key => {
|
||||
// let's add all askable kana keys to array
|
||||
this.askableKanaKeys.push(key);
|
||||
this.askableRomajis.push(kanaDictionary[whichKana][groupName]['characters'][key][0]);
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
}, this);
|
||||
});
|
||||
});
|
||||
// console.log(this.askableKanas);
|
||||
}
|
||||
|
||||
|
@ -172,12 +168,24 @@ class Question extends Component {
|
|||
if(this.previousQuestion=='')
|
||||
resultString = <div className="previous-result none">Let's go! Which character is this?</div>
|
||||
else {
|
||||
let rightAnswer = (this.props.stage==2?findRomajisAtKanaKey(this.previousQuestion, kanaDictionary)[0]:this.previousQuestion.join(''))+' = '+
|
||||
this.previousAllowedAnswers[0];
|
||||
let rightAnswer = (
|
||||
this.props.stage==2 ?
|
||||
findRomajisAtKanaKey(this.previousQuestion, kanaDictionary)[0]
|
||||
: this.previousQuestion.join('')
|
||||
)+' = '+ this.previousAllowedAnswers[0];
|
||||
|
||||
if(this.isInAllowedAnswers(this.previousAnswer))
|
||||
resultString = <div className="previous-result correct" title="Correct answer!"><span className="pull-left glyphicon glyphicon-none"></span>{rightAnswer}<span className="pull-right glyphicon glyphicon-ok"></span></div>
|
||||
resultString = (
|
||||
<div className="previous-result correct" title="Correct answer!">
|
||||
<span className="pull-left glyphicon glyphicon-none"></span>{rightAnswer}<span className="pull-right glyphicon glyphicon-ok"></span>
|
||||
</div>
|
||||
);
|
||||
else
|
||||
resultString = <div className="previous-result wrong" title="Wrong answer!"><span className="pull-left glyphicon glyphicon-none"></span>{rightAnswer}<span className="pull-right glyphicon glyphicon-remove"></span></div>
|
||||
resultString = (
|
||||
<div className="previous-result wrong" title="Wrong answer!">
|
||||
<span className="pull-left glyphicon glyphicon-none"></span>{rightAnswer}<span className="pull-right glyphicon glyphicon-remove"></span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return resultString;
|
||||
}
|
||||
|
@ -190,11 +198,11 @@ class Question extends Component {
|
|||
else return false;
|
||||
}
|
||||
|
||||
handleAnswerChange(e) {
|
||||
handleAnswerChange = e => {
|
||||
this.setState({currentAnswer: e.target.value.replace(/\s+/g, '')});
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
if(this.state.currentAnswer!='') {
|
||||
this.handleAnswer(this.state.currentAnswer.toLowerCase());
|
||||
|
|
|
@ -4,38 +4,10 @@ import ChooseCharacters from '../ChooseCharacters/ChooseCharacters';
|
|||
import Game from '../Game/Game';
|
||||
|
||||
class GameContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.startGame = this.startGame.bind(this);
|
||||
this.state = {
|
||||
state = {
|
||||
stage:1,
|
||||
isLocked: false,
|
||||
decidedGroups: ['h_group1']
|
||||
}
|
||||
this.stageUp = this.stageUp.bind(this);
|
||||
this.lockStage = this.lockStage.bind(this);
|
||||
}
|
||||
|
||||
startGame(decidedGroups) {
|
||||
if(parseInt(this.state.stage)<1 || isNaN(parseInt(this.state.stage)))
|
||||
this.setState({stage: 1});
|
||||
else if(parseInt(this.state.stage)>4)
|
||||
this.setState({stage: 4});
|
||||
|
||||
this.setState({decidedGroups: decidedGroups});
|
||||
this.props.handleStartGame();
|
||||
}
|
||||
|
||||
stageUp() {
|
||||
this.setState({stage: this.state.stage+1});
|
||||
}
|
||||
|
||||
lockStage(stage, forceLock) {
|
||||
// if(stage<1 || stage>4) stage=1; // don't use this to allow backspace
|
||||
if(forceLock)
|
||||
this.setState({stage: stage, isLocked: true});
|
||||
else
|
||||
this.setState({stage: stage, isLocked: !this.state.isLocked});
|
||||
decidedGroups: JSON.parse(localStorage.getItem('decidedGroups') || null) || []
|
||||
}
|
||||
|
||||
componentWillReceiveProps() {
|
||||
|
@ -43,24 +15,49 @@ class GameContainer extends Component {
|
|||
this.setState({stage: 1});
|
||||
}
|
||||
|
||||
startGame = decidedGroups => {
|
||||
if(parseInt(this.state.stage)<1 || isNaN(parseInt(this.state.stage)))
|
||||
this.setState({stage: 1});
|
||||
else if(parseInt(this.state.stage)>4)
|
||||
this.setState({stage: 4});
|
||||
|
||||
this.setState({decidedGroups: decidedGroups});
|
||||
localStorage.setItem('decidedGroups', JSON.stringify(decidedGroups));
|
||||
this.props.handleStartGame();
|
||||
}
|
||||
|
||||
stageUp = () => {
|
||||
this.setState({stage: this.state.stage+1});
|
||||
}
|
||||
|
||||
lockStage = (stage, forceLock) => {
|
||||
// if(stage<1 || stage>4) stage=1; // don't use this to allow backspace
|
||||
if(forceLock)
|
||||
this.setState({stage: stage, isLocked: true});
|
||||
else
|
||||
this.setState({stage: stage, isLocked: !this.state.isLocked});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{ this.props.gameState==='chooseCharacters' ?
|
||||
{ this.props.gameState==='chooseCharacters' &&
|
||||
<ChooseCharacters selectedGroups={this.state.decidedGroups}
|
||||
handleStartGame={this.startGame}
|
||||
stage={this.state.stage}
|
||||
isLocked={this.state.isLocked}
|
||||
lockStage={this.lockStage}
|
||||
/> : '' }
|
||||
{ this.props.gameState==='game' ?
|
||||
/>
|
||||
}
|
||||
{ this.props.gameState==='game' &&
|
||||
<Game decidedGroups={this.state.decidedGroups}
|
||||
handleEndGame={this.props.handleEndGame}
|
||||
stageUp={this.stageUp}
|
||||
stage={this.state.stage}
|
||||
isLocked={this.state.isLocked}
|
||||
lockStage={this.lockStage}
|
||||
/> : '' }
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,21 +3,20 @@ import './Navbar.scss';
|
|||
|
||||
class Navbar extends Component {
|
||||
render() {
|
||||
let leftLink;
|
||||
switch(this.props.gameState) {
|
||||
case 'chooseCharacters':
|
||||
default:
|
||||
leftLink = <li id="nav-kanaquiz"><p className="nav navbar-text">Kana Quiz <span>2</span></p></li>
|
||||
break;
|
||||
case 'game':
|
||||
leftLink = <li id="nav-choosecharacters"><a href="javascript:;" onClick={this.props.handleEndGame}><span className="glyphicon glyphicon-small glyphicon-arrow-left"></span> Back to menu</a></li>
|
||||
}
|
||||
return (
|
||||
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<div className="container">
|
||||
<div id="navbar">
|
||||
<ul className="nav navbar-nav">
|
||||
{leftLink}
|
||||
{
|
||||
this.props.gameState == 'game' ? (
|
||||
<li id="nav-choosecharacters">
|
||||
<a href="javascript:;" onClick={this.props.handleEndGame}>
|
||||
<span className="glyphicon glyphicon-small glyphicon-arrow-left"></span> Back to menu
|
||||
</a>
|
||||
</li>
|
||||
) : <li id="nav-kanaquiz"><p className="nav navbar-text">Kana Pro</p></li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Kana Quiz 2: Learn hiragana & katakana fast and easy</title>
|
||||
<title>Kana Pro: Learn hiragana & katakana fast and easy</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="Description" content="Application for studying hiragana & katakana characters.">
|
||||
</head>
|
||||
<body>
|
||||
<div class="app"></div>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,7 +1,10 @@
|
|||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Bootstrap from './assets/stylesheets/bootstrap.min.css';
|
||||
import App from './components/App/App';
|
||||
|
||||
let element = React.createElement(App, {});
|
||||
render(element, document.querySelector('.app'));
|
||||
let appEl = document.getElementById('app');
|
||||
if(!appEl) // in case of old index.html in cache
|
||||
appEl = document.querySelector('.app');
|
||||
|
||||
ReactDOM.render(<App />, appEl);
|
||||
|
|
Loading…
Reference in a new issue