diff --git a/src/components/App/App.jsx b/src/components/App/App.jsx index e75f29d..35955b7 100644 --- a/src/components/App/App.jsx +++ b/src/components/App/App.jsx @@ -12,7 +12,7 @@ class App extends Component { super(props); this.state = { isAuthenticated: this.isAuthenticated(), - gameState: 'chooseCharacters' + gameState: 'game' /*profile: auth.getProfile()*/ } auth.on('profile_updated', (newProfile) => { diff --git a/src/components/ChooseCharacters/ChooseCharacters.jsx b/src/components/ChooseCharacters/ChooseCharacters.jsx index cbbca61..8afcbeb 100644 --- a/src/components/ChooseCharacters/ChooseCharacters.jsx +++ b/src/components/ChooseCharacters/ChooseCharacters.jsx @@ -8,17 +8,17 @@ class ChooseCharacters extends Component { super(props); this.state = { errMsg : '', - selectedKana: ['h_group1'] + selectedGroups: this.props.selectedGroups } this.startGame = this.startGame.bind(this); - this.showKanaRows = this.showKanaRows.bind(this); + this.showGroupRows = this.showGroupRows.bind(this); this.toggleSelect = this.toggleSelect.bind(this); this.selectAll = this.selectAll.bind(this); this.selectNone = this.selectNone.bind(this); } getIndex(groupName) { - return this.state.selectedKana.indexOf(groupName); + return this.state.selectedGroups.indexOf(groupName); } isSelected(groupName) { @@ -27,13 +27,13 @@ class ChooseCharacters extends Component { removeSelect(groupName) { if(this.getIndex(groupName)<0) return; - let newSelectedKana = this.state.selectedKana.slice(); - newSelectedKana.splice(this.getIndex(groupName), 1); - this.setState({selectedKana: newSelectedKana}); + let newSelectedGroups = this.state.selectedGroups.slice(); + newSelectedGroups.splice(this.getIndex(groupName), 1); + this.setState({selectedGroups: newSelectedGroups}); } addSelect(groupName) { - this.setState({errMsg: '', selectedKana: this.state.selectedKana.concat(groupName)}); + this.setState({errMsg: '', selectedGroups: this.state.selectedGroups.concat(groupName)}); } toggleSelect(groupName) { @@ -43,29 +43,29 @@ class ChooseCharacters extends Component { selectAll(whichKana) { let thisKana = kanaDictionary[whichKana]; - let newSelectedKana = this.state.selectedKana.slice(); + let newSelectedGroups = this.state.selectedGroups.slice(); Object.keys(thisKana).map(function(groupName) { if(!this.isSelected(groupName)) - newSelectedKana.push(groupName); + newSelectedGroups.push(groupName); }, this); - this.setState({errMsg: '', selectedKana: newSelectedKana}); + this.setState({errMsg: '', selectedGroups: newSelectedGroups}); } selectNone(whichKana) { - let newSelectedKana = []; - this.state.selectedKana.map(function(groupName) { + let newSelectedGroups = []; + this.state.selectedGroups.map(function(groupName) { let mustBeRemoved = false; Object.keys(kanaDictionary[whichKana]).map(function(removableGroupName) { if(removableGroupName===groupName) mustBeRemoved = true; }, this); if(!mustBeRemoved) - newSelectedKana.push(groupName); + newSelectedGroups.push(groupName); }, this); - this.setState({selectedKana: newSelectedKana}); + this.setState({selectedGroups: newSelectedGroups}); } - showKanaRows(whichKana) { + showGroupRows(whichKana) { let thisKana = kanaDictionary[whichKana]; return Object.keys(thisKana).map(function(groupName, idx) { return ( @@ -81,11 +81,11 @@ class ChooseCharacters extends Component { } startGame() { - if(this.state.selectedKana.length < 1) { + if(this.state.selectedGroups.length < 1) { this.setState({ errMsg: 'Choose at least one group!'}); return; } - this.props.handleStartGame(this.state.selectedKana); + this.props.handleStartGame(this.state.selectedGroups); } render() { @@ -104,9 +104,9 @@ class ChooseCharacters extends Component {
-
Hiragana ひらがな
+
Hiragana · ひらがなProgress
- {this.showKanaRows('hiragana')} + {this.showGroupRows('hiragana')}
this.selectAll('hiragana')}>All  ·  this.selectNone('hiragana')}>None @@ -115,9 +115,9 @@ class ChooseCharacters extends Component {
-
Katakana カタカナ
+
Katakana · カタカナProgress
- {this.showKanaRows('katakana')} + {this.showGroupRows('katakana')}
this.selectAll('katakana')}>All  ·  this.selectNone('katakana')}>None diff --git a/src/components/ChooseCharacters/ChooseCharacters.scss b/src/components/ChooseCharacters/ChooseCharacters.scss index 8b86190..436cb3c 100644 --- a/src/components/ChooseCharacters/ChooseCharacters.scss +++ b/src/components/ChooseCharacters/ChooseCharacters.scss @@ -11,6 +11,9 @@ .panel-heading { font-weight: bold; } + .panel-heading span { + color: #aaa; + } .panel-footer a { text-decoration: none; color: #337ab7; @@ -18,7 +21,6 @@ .choose-row { font-size: 1em; padding: 5px; - user-select: none; } .choose-row:not(:last-child) { border-bottom: 1px #eee solid; diff --git a/src/components/Game/Game.jsx b/src/components/Game/Game.jsx new file mode 100644 index 0000000..9cb50fb --- /dev/null +++ b/src/components/Game/Game.jsx @@ -0,0 +1,40 @@ +import React, { Component } from 'react'; +import { kanaDictionary } from '../../data/kanaDictionary'; +import './Game.scss'; +import ShowStage from './ShowStage'; +import Question from './Question'; + +class Game extends Component { + constructor(props) { + super(props); + this.state = { + stage: 0, + showScreen: '' + } + this.showQuestion = this.showQuestion.bind(this); + this.stageUp = this.stageUp.bind(this); + } + + stageUp() { + this.setState({stage: this.state.stage+1, showScreen: 'stage'}); + } + + showQuestion() { + this.setState({showScreen: 'question'}) + } + + componentWillMount() { + this.stageUp(); + } + + render() { + return ( +
+ { this.state.showScreen==='stage' ? : '' } + { this.state.showScreen==='question' ? : '' } +
+ ); + } +} + +export default Game; \ No newline at end of file diff --git a/src/components/Game/Game.scss b/src/components/Game/Game.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Game/Question.jsx b/src/components/Game/Question.jsx new file mode 100644 index 0000000..f555265 --- /dev/null +++ b/src/components/Game/Question.jsx @@ -0,0 +1,102 @@ +import React, { Component } from 'react'; +import { kanaDictionary } from '../../data/kanaDictionary'; +import { arrayContains, shuffle } from '../../data/helperFuncs'; +import './Question.scss'; + +class Question extends Component { + constructor(props) { + super(props); + this.state = { + previousQuestion: {}, + currentQuestion: '' + } + } + + // getQuestionIndex(question) { + // return this.state.selectedGroups.indexOf(question); + // } + + // removeSelect(groupName) { + // if(this.getQuestionIndex(groupName)<0) return; + // let newSelectedGroups = this.state.selectedGroups.slice(); + // newSelectedGroups.splice(this.getIndex(groupName), 1); + // this.setState({selectedGroups: newSelectedGroups}); + // } + + getRandomKanas(amount) { + let randomizedKanas = []; + if(this.state.previousQuestion.length > 0) + removeFromAskable(this.state.previousQuestion); + shuffle(this.askableCharacterKeys); + for(let i = 0; i < amount; i++) { + randomizedKanas.push(this.askableCharacterKeys[i]); + } + return randomizedKanas; + // console.log(this.askableCharacters); + //return this.askableCharacterKeys[Math.floor(Math.random() * this.askableCharacterKeys.length)]; + } + + removeFromAskable(question) { + console.log('here'); + //console.log(this.getQuestionIndex(question)); + } + + setNewQuestion() { + let question = this.getRandomKanas(1); + this.setState({currentQuestion: question[0]}); + //console.log(question); + } + + setAllowedAnswers() { + + } + + initializeCharacters() { + this.askableCharacters = {}; + this.askableCharacterKeys = []; + Object.keys(kanaDictionary).map(function(whichKana) { + // console.log(whichKana); // 'hiragana' or 'katakana' + Object.keys(kanaDictionary[whichKana]).map(function(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 askableCharacters + this.askableCharacters = Object.assign(this.askableCharacters, kanaDictionary[whichKana][groupName]['characters']); + + Object.keys(kanaDictionary[whichKana][groupName]['characters']).map(function(key) { + // let's add all askable kana keys to array + this.askableCharacterKeys.push(key); + kanaDictionary[whichKana][groupName]['characters'][key].map(function(romaji) { + console.log(romaji); + }, this); + }, this); + } + }, this); + }, this); + // console.log(this.askableCharacters); + } + + + + componentWillMount() { + } + + componentDidMount() { + this.initializeCharacters(); + this.setNewQuestion(); + this.setAnswerOptions(); + this.setAllowedAnswers(); + } + + render() { + return ( +
+
{this.state.currentQuestion}
+ +
+ ); + } + +} + +export default Question; \ No newline at end of file diff --git a/src/components/Game/Question.scss b/src/components/Game/Question.scss new file mode 100644 index 0000000..0874f6f --- /dev/null +++ b/src/components/Game/Question.scss @@ -0,0 +1,6 @@ +.question { + .big-character { + font-size: 5em; + } + margin-top: 70px; +} \ No newline at end of file diff --git a/src/components/Game/ShowStage.jsx b/src/components/Game/ShowStage.jsx new file mode 100644 index 0000000..73a4325 --- /dev/null +++ b/src/components/Game/ShowStage.jsx @@ -0,0 +1,52 @@ +import React, { Component } from 'react'; +import './ShowStage.scss'; +import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; + +class ShowStage extends Component { + constructor(props) { + super(props); + this.state = { + stageContent: '' + } + this.showStage = this.showStage.bind(this); + this.removeStage = this.removeStage.bind(this); + } + + removeStage() { + this.setState({stageContent: ''}); + clearTimeout(this.timeoutID); + this.timeoutID = setTimeout(this.props.handleShowQuestion, 1) // how soon we go to question (1000) + } + + showStage() { + let stageDescription; + let stageSecondaryDescription = false; + if(this.props.stage===1) stageDescription = 'Choose one'; + if(this.props.stage===2) { stageDescription = 'Choose one'; stageSecondaryDescription = 'Reverse'; } + if(this.props.stage===3) stageDescription = 'Write the answer'; + if(this.props.stage===4) { stageDescription = 'Write the answer'; stageSecondaryDescription = 'Three at once'; } + let stageContent =

Stage {this.props.stage}

{stageDescription}

{stageSecondaryDescription?

{stageSecondaryDescription}

:''}
; + this.setState({stageContent: stageContent}); + } + + componentDidMount() { + this.timeoutID = setTimeout(this.removeStage, 1); // how soon we start fading out (1500) + this.showStage(); + } + + componentWillUnmount() { + clearTimeout(this.timeoutID); + } + + render() { + return ( +
+ + {this.state.stageContent} + +
+ ); + } +} + +export default ShowStage; \ No newline at end of file diff --git a/src/components/Game/ShowStage.scss b/src/components/Game/ShowStage.scss new file mode 100644 index 0000000..e1770e1 --- /dev/null +++ b/src/components/Game/ShowStage.scss @@ -0,0 +1,24 @@ +.show-stage { + margin-top: 200px; + h3 { + margin-top: 30px; + } +} + +.stage-enter { + opacity: 0.01; +} + +.stage-enter.stage-enter-active { + opacity: 1; + transition: opacity 1s ease-in; +} + +.stage-leave { + opacity: 1; +} + +.stage-leave.stage-leave-active { + opacity: 0.01; + transition: opacity 1s ease-in; +} diff --git a/src/components/GameContainer/GameContainer.jsx b/src/components/GameContainer/GameContainer.jsx index 0318bca..df877c2 100644 --- a/src/components/GameContainer/GameContainer.jsx +++ b/src/components/GameContainer/GameContainer.jsx @@ -1,24 +1,34 @@ import React, { Component } from 'react'; import { kanaDictionary } from '../../data/kanaDictionary'; 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 = { + decidedGroups: ['h_group1', 'h_group2'] + } } - startGame(options) { + startGame(decidedGroups) { // console.log(options); // prints array + this.setState({decidedGroups: decidedGroups}); this.props.handleStartGame(); } render() { - let currentScreen = this.props.gameState==='chooseCharacters' ? : - (this.props.gameState==='game' ? '' : ''); return (
- {currentScreen} + { this.props.gameState==='chooseCharacters' ? + : '' } + { this.props.gameState==='game' ? + : '' }
) } diff --git a/src/components/Navbar/Navbar.jsx b/src/components/Navbar/Navbar.jsx index f81c73d..ac6936f 100644 --- a/src/components/Navbar/Navbar.jsx +++ b/src/components/Navbar/Navbar.jsx @@ -7,7 +7,7 @@ class Navbar extends Component { switch(this.props.gameState) { case 'chooseCharacters': default: - leftLink = + leftLink = break; case 'game': leftLink = diff --git a/src/components/Navbar/Navbar.scss b/src/components/Navbar/Navbar.scss index 9e10a4a..754557a 100644 --- a/src/components/Navbar/Navbar.scss +++ b/src/components/Navbar/Navbar.scss @@ -17,11 +17,10 @@ .nav a:hover { color: #bbb !important; } -#nav-kanaquiz a, #nav-kanaquiz { +.navbar-text { color: #fff !important; - span { - color: #fff !important; - } + cursor: default; + margin-bottom: 0; } #nav-kanaquiz a:hover { cursor: default; diff --git a/src/data/helperFuncs.js b/src/data/helperFuncs.js new file mode 100644 index 0000000..72d21fa --- /dev/null +++ b/src/data/helperFuncs.js @@ -0,0 +1,16 @@ +export function arrayContains(needle, arrhaystack) { + return (arrhaystack.indexOf(needle) > -1); +} + +export function shuffle(array) { + var i = 0 + , j = 0 + , temp = null + + for (i = array.length - 1; i > 0; i -= 1) { + j = Math.floor(Math.random() * (i + 1)) + temp = array[i] + array[i] = array[j] + array[j] = temp + } +} \ No newline at end of file