Merge branch 'nahive-feature/issue-2'

separating alternative hiragana & katakana characters
This commit is contained in:
Antti Pilto 2018-09-09 14:53:07 +03:00
commit 2f0d034b2f
5 changed files with 4223 additions and 1112 deletions

5154
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load diff

View file

@ -16,22 +16,12 @@ class CharacterGroup extends Component {
getShowableCharacters(whichKana) { getShowableCharacters(whichKana) {
let strRomajiCharacters = ''; let strRomajiCharacters = '';
let strKanaCharacters = ''; let strKanaCharacters = '';
if(this.props.groupName!='h_group11' && this.props.groupName!='k_group11') {
Object.keys(this.props.characters).map(function(character) { Object.keys(this.props.characters).map(function(character) {
strRomajiCharacters+=this.props.characters[character][0]+' · '; strRomajiCharacters+=this.props.characters[character][0]+' · ';
strKanaCharacters+=character+' · '; strKanaCharacters+=character+' · ';
}, this); }, this);
strRomajiCharacters = strRomajiCharacters.slice(0, -2); strRomajiCharacters = strRomajiCharacters.slice(0, -2);
strKanaCharacters = strKanaCharacters.slice(0, -2); strKanaCharacters = strKanaCharacters.slice(0, -2);
}
else if(this.props.groupName=='h_group11') {
strRomajiCharacters = 'ga · ba · da · kya · sha... (58 characters)';
strKanaCharacters = 'ぎ · ば · だ · きゃ · しゃ... (58 characters)';
}
else if(this.props.groupName=='k_group11') {
strRomajiCharacters = 'ga · ba · da · kya · sha... (58 characters)';
strKanaCharacters = 'ガ · バ · ダ · キャ · シャ... (58 characters)';
}
if(whichKana=='romaji') return strRomajiCharacters; if(whichKana=='romaji') return strRomajiCharacters;
else return strKanaCharacters; else return strKanaCharacters;
} }
@ -42,7 +32,7 @@ class CharacterGroup extends Component {
render() { render() {
return ( return (
<div className="choose-row" <div className={'choose-row' + (this.props.groupName.endsWith('_a') ? ' alt-row' : '')}
onClick={()=>{ onClick={()=>{
this.props.handleToggleSelect(this.props.groupName); this.props.handleToggleSelect(this.props.groupName);
this.changeShownChars(this.getShowableCharacters('romaji')); this.changeShownChars(this.getShowableCharacters('romaji'));

View file

@ -9,7 +9,8 @@ class ChooseCharacters extends Component {
super(props); super(props);
this.state = { this.state = {
errMsg : '', errMsg : '',
selectedGroups: this.props.selectedGroups selectedGroups: this.props.selectedGroups,
showAlternatives: []
} }
this.startGame = this.startGame.bind(this); this.startGame = this.startGame.bind(this);
this.showGroupRows = this.showGroupRows.bind(this); this.showGroupRows = this.showGroupRows.bind(this);
@ -52,6 +53,16 @@ class ChooseCharacters extends Component {
this.setState({errMsg: '', selectedGroups: newSelectedGroups}); this.setState({errMsg: '', selectedGroups: newSelectedGroups});
} }
selectAllAlternative(whichKana) {
let thisKana = kanaDictionary[whichKana];
let newSelectedGroups = this.state.selectedGroups.slice();
Object.keys(thisKana).map(function(groupName) {
if(groupName.endsWith("_a"))
newSelectedGroups.push(groupName);
}, this);
this.setState({errMsg: '', selectedGroups: newSelectedGroups});
}
selectNone(whichKana) { selectNone(whichKana) {
let newSelectedGroups = []; let newSelectedGroups = [];
this.state.selectedGroups.map(function(groupName) { this.state.selectedGroups.map(function(groupName) {
@ -66,19 +77,98 @@ class ChooseCharacters extends Component {
this.setState({selectedGroups: newSelectedGroups}); this.setState({selectedGroups: newSelectedGroups});
} }
showGroupRows(whichKana) { selectNoneAlternative(whichKana) {
let thisKana = kanaDictionary[whichKana]; let newSelectedGroups = [];
return Object.keys(thisKana).map(function(groupName, idx) { this.state.selectedGroups.map(function(groupName) {
return ( let mustBeRemoved = false;
<CharacterGroup Object.keys(kanaDictionary[whichKana]).map(function(removableGroupName) {
if(removableGroupName===groupName && groupName.endsWith("_a"))
mustBeRemoved = true;
}, this);
if(!mustBeRemoved)
newSelectedGroups.push(groupName);
}, this);
this.setState({selectedGroups: newSelectedGroups});
}
toggleAlternative(whichKana) {
const idx = this.state.showAlternatives.indexOf(whichKana);
let newShowAlternatives = this.state.showAlternatives;
if(idx >= 0)
newShowAlternatives.splice(idx, 1);
else
newShowAlternatives.push(whichKana)
this.setState({showAlternatives: newShowAlternatives});
}
getSelectedAlternatives(whichKana) {
return this.state.selectedGroups.filter(groupName => {
return groupName.startsWith(whichKana == 'hiragana' ? 'h_' : 'k_') &&
groupName.endsWith('_a');
}).length;
}
getAmountOfAlternatives(whichKana) {
return Object.keys(kanaDictionary[whichKana]).filter(groupName => {
return groupName.endsWith("_a");
}).length;
}
alternativeToggleRow(whichKana, showAlternatives) {
let checkBtn = "glyphicon glyphicon-small glyphicon-"
let status;
if(this.getSelectedAlternatives(whichKana) >= this.getAmountOfAlternatives(whichKana))
status = 'check';
else if(this.getSelectedAlternatives(whichKana) > 0)
status = 'check half';
else
status = 'unchecked'
checkBtn += status
return <div
key={'alt_toggle_' + whichKana}
onClick={() => this.toggleAlternative(whichKana)}
className="choose-row"
>
<span
className={checkBtn}
onClick={ e => {
if(status == 'check')
this.selectNoneAlternative(whichKana);
else if(status == 'check half')
this.selectAllAlternative(whichKana);
else if(status == 'unchecked')
this.selectAllAlternative(whichKana);
e.stopPropagation();
}}
></span>
{
showAlternatives ? <span className="toggle-caret">&#9650;</span>
: <span className="toggle-caret">&#9660;</span>
}
Alternative characters (ga · ba · kya · sha..)
</div>
}
showGroupRows(whichKana, showAlternatives) {
const thisKana = kanaDictionary[whichKana];
let rows = [];
Object.keys(thisKana).forEach(function(groupName, idx) {
if(groupName.endsWith("group11_a"))
rows.push(this.alternativeToggleRow(whichKana, showAlternatives));
if(!groupName.endsWith("a") || showAlternatives) {
rows.push(<CharacterGroup
key={idx} key={idx}
groupName={groupName} groupName={groupName}
selected={this.isSelected(groupName)} selected={this.isSelected(groupName)}
characters={thisKana[groupName].characters} characters={thisKana[groupName].characters}
handleToggleSelect={this.toggleSelect} handleToggleSelect={this.toggleSelect}
/> />);
); }
}, this); }, this);
return rows;
} }
startGame() { startGame() {
@ -107,10 +197,12 @@ class ChooseCharacters extends Component {
<div className="panel panel-default"> <div className="panel panel-default">
<div className="panel-heading">Hiragana · ひらがな</div> <div className="panel-heading">Hiragana · ひらがな</div>
<div className="panel-body selection-areas"> <div className="panel-body selection-areas">
{this.showGroupRows('hiragana')} {this.showGroupRows('hiragana', this.state.showAlternatives.indexOf('hiragana') >= 0)}
</div> </div>
<div className="panel-footer text-center"> <div className="panel-footer text-center">
<a href="javascript:;" onClick={()=>this.selectAll('hiragana')}>All</a> &nbsp;&middot;&nbsp; <a href="javascript:;" onClick={()=>this.selectNone('hiragana')}>None</a> <a href="javascript:;" onClick={()=>this.selectAll('hiragana')}>All</a> &nbsp;&middot;&nbsp; <a href="javascript:;" onClick={()=>this.selectNone('hiragana')}>None</a>
&nbsp;&middot;&nbsp; <a href="javascript:;" onClick={()=>this.selectAllAlternative('hiragana')}>All alternative</a>
&nbsp;&middot;&nbsp; <a href="javascript:;" onClick={()=>this.selectNoneAlternative('hiragana')}>No alternative</a>
</div> </div>
</div> </div>
</div> </div>
@ -118,10 +210,12 @@ class ChooseCharacters extends Component {
<div className="panel panel-default"> <div className="panel panel-default">
<div className="panel-heading">Katakana · カタカナ</div> <div className="panel-heading">Katakana · カタカナ</div>
<div className="panel-body selection-areas"> <div className="panel-body selection-areas">
{this.showGroupRows('katakana')} {this.showGroupRows('katakana', this.state.showAlternatives.indexOf('katakana') >= 0)}
</div> </div>
<div className="panel-footer text-center"> <div className="panel-footer text-center">
<a href="javascript:;" onClick={()=>this.selectAll('katakana')}>All</a> &nbsp;&middot;&nbsp; <a href="javascript:;" onClick={()=>this.selectNone('katakana')}>None</a> <a href="javascript:;" onClick={()=>this.selectAll('katakana')}>All</a> &nbsp;&middot;&nbsp; <a href="javascript:;" onClick={()=>this.selectNone('katakana')}>None</a>
&nbsp;&middot;&nbsp; <a href="javascript:;" onClick={()=>this.selectAllAlternative('katakana')}>All alternative</a>
&nbsp;&middot;&nbsp; <a href="javascript:;" onClick={()=>this.selectNoneAlternative('katakana')}>No alternative</a>
</div> </div>
</div> </div>
</div> </div>

View file

@ -25,6 +25,13 @@
.choose-row:not(:last-child) { .choose-row:not(:last-child) {
border-bottom: 1px #eee solid; border-bottom: 1px #eee solid;
} }
.alt-row {
padding-left: 20px;
background-color: #fafafa;
}
.toggle-caret {
margin: 0 4px;
}
@media (min-width: 768px) { @media (min-width: 768px) {
.choose-row:hover { .choose-row:hover {
background-color: #f4f4f4; background-color: #f4f4f4;
@ -39,6 +46,9 @@
.glyphicon-check { .glyphicon-check {
color: green; color: green;
} }
.glyphicon-check.half {
color: #ccc;
}
.glyphicon-unchecked { .glyphicon-unchecked {
color: #ccc; color: #ccc;
} }
@ -71,7 +81,7 @@
height: 19px; height: 19px;
border-radius: 13px; border-radius: 13px;
cursor: pointer; cursor: pointer;
display: inline-block; display: block;
float: right; float: right;
margin-top: 1px; margin-top: 1px;
} }

View file

@ -10,8 +10,17 @@ export const kanaDictionary = {
'h_group8': { characters: { 'や': ['ya'], 'ゆ': ['yu'], 'よ': ['yo'] } }, 'h_group8': { characters: { 'や': ['ya'], 'ゆ': ['yu'], 'よ': ['yo'] } },
'h_group9': { characters: { 'ら': ['ra'], 'り': ['ri'], 'る': ['ru'], 'れ': ['re'], 'ろ': ['ro'] } }, 'h_group9': { characters: { 'ら': ['ra'], 'り': ['ri'], 'る': ['ru'], 'れ': ['re'], 'ろ': ['ro'] } },
'h_group10': { characters: { 'わ': ['wa'], 'を': ['wo','o'], 'ん': ['n'] } }, 'h_group10': { characters: { 'わ': ['wa'], 'を': ['wo','o'], 'ん': ['n'] } },
'h_group11': { characters: { 'が': ['ga'], 'ぎ': ['gi'], 'ぐ': ['gu'], 'げ': ['ge'], 'ご': ['go'], 'ざ': ['za'], 'じ': ['ji','zi'], 'ず': ['zu','du'], 'ぜ': ['ze'], 'ぞ': ['zo'], 'だ': ['da'], 'ぢ': ['ji','di','dzi'], 'づ': ['zu','dzu'], 'で': ['de'], 'ど': ['do'], 'ば': ['ba'], 'び': ['bi'], 'ぶ': ['bu'], 'べ': ['be'], 'ぼ': ['bo'], 'ぱ': ['pa'], 'ぴ': ['pi'], 'h_group11_a': { characters: { 'が': ['ga'], 'ぎ': ['gi'], 'ぐ': ['gu'], 'げ': ['ge'], 'ご': ['go'] } },
'ぷ': ['pu'], 'ぺ': ['pe'], 'ぽ': ['po'], 'きゃ': ['kya'], 'きゅ': ['kyu'], 'きょ': ['kyo'], 'しゃ': ['sha','sya'], 'しゅ': ['shu','syu'], 'しょ': ['sho','syo'], 'ちゃ': ['cha','cya'], 'ちゅ': ['chu','cyu'], 'ちょ': ['cho','cyo'], 'にゃ': ['nya'], 'にゅ': ['nyu'], 'にょ': ['nyo'], 'ひゃ': ['hya'], 'ひゅ': ['hyu'], 'ひょ': ['hyo'], 'みゃ': ['mya'], 'みゅ': ['myu'], 'みょ': ['myo'], 'りゃ': ['rya'], 'りゅ': ['ryu'], 'りょ': ['ryo'], 'ぎゃ': ['gya'], 'ぎゅ': ['gyu'], 'ぎょ': ['gyo'], 'じゃ': ['ja','jya'], 'じゅ': ['ju','jyu'], 'じょ': ['jo','jyo'], 'びゃ': ['bya'], 'びゅ': ['byu'], 'びょ': ['byo'], 'ぴゃ': ['pya'], 'ぴゅ': ['pyu'], 'ぴょ': ['pyo'] } } 'h_group12_a': { characters: { 'ざ': ['za'], 'じ': ['ji','zi'], 'ず': ['zu','du'], 'ぜ': ['ze'], 'ぞ': ['zo'] } },
'h_group13_a': { characters: { 'だ': ['da'], 'ぢ': ['ji','di','dzi'], 'づ': ['zu','dzu'], 'で': ['de'], 'ど': ['do'] } },
'h_group14_a': { characters: { 'ば': ['ba'], 'び': ['bi'], 'ぶ': ['bu'], 'べ': ['be'], 'ぼ': ['bo'] } },
'h_group15_a': { characters: { 'ぱ': ['pa'], 'ぴ': ['pi'], 'ぷ': ['pu'], 'ぺ': ['pe'], 'ぽ': ['po'] } },
'h_group16_a': { characters: { 'きゃ': ['kya'], 'きゅ': ['kyu'], 'きょ': ['kyo'], 'しゃ': ['sha','sya'], 'しゅ': ['shu','syu'], 'しょ': ['sho','syo'] } },
'h_group17_a': { characters: { 'ちゃ': ['cha','cya'], 'ちゅ': ['chu','cyu'], 'ちょ': ['cho','cyo'], 'にゃ': ['nya'], 'にゅ': ['nyu'], 'にょ': ['nyo'] } },
'h_group18_a': { characters: { 'ひゃ': ['hya'], 'ひゅ': ['hyu'], 'ひょ': ['hyo'], 'みゃ': ['mya'], 'みゅ': ['myu'], 'みょ': ['myo'] } },
'h_group19_a': { characters: { 'りゃ': ['rya'], 'りゅ': ['ryu'], 'りょ': ['ryo'], 'ぎゃ': ['gya'], 'ぎゅ': ['gyu'], 'ぎょ': ['gyo'] } },
'h_group20_a': { characters: { 'じゃ': ['ja','jya'], 'じゅ': ['ju','jyu'], 'じょ': ['jo','jyo'], 'びゃ': ['bya'], 'びゅ': ['byu'], 'びょ': ['byo'] } },
'h_group21_a': { characters: { 'ぴゃ': ['pya'], 'ぴゅ': ['pyu'], 'ぴょ': ['pyo'] } }
}, },
'katakana' : { 'katakana' : {
'k_group1': { characters: { 'ア': ['a'], 'イ': ['i'], 'ウ': ['u'], 'エ': ['e'], 'オ': ['o'] } }, 'k_group1': { characters: { 'ア': ['a'], 'イ': ['i'], 'ウ': ['u'], 'エ': ['e'], 'オ': ['o'] } },
@ -24,7 +33,21 @@ export const kanaDictionary = {
'k_group8': { characters: { 'ヤ': ['ya'], 'ユ': ['yu'], 'ヨ': ['yo'] } }, 'k_group8': { characters: { 'ヤ': ['ya'], 'ユ': ['yu'], 'ヨ': ['yo'] } },
'k_group9': { characters: { 'ラ': ['ra'], 'リ': ['ri'], 'ル': ['ru'], 'レ': ['re'], 'ロ': ['ro'] } }, 'k_group9': { characters: { 'ラ': ['ra'], 'リ': ['ri'], 'ル': ['ru'], 'レ': ['re'], 'ロ': ['ro'] } },
'k_group10': { characters: { 'ワ': ['wa'], 'ヲ': ['wo','o'], 'ン': ['n'] } }, 'k_group10': { characters: { 'ワ': ['wa'], 'ヲ': ['wo','o'], 'ン': ['n'] } },
'k_group11': { characters: { 'ガ': ['ga'], 'ギ': ['gi'], 'グ': ['gu'], 'ゲ': ['ge'], 'ゴ': ['go'], 'ザ': ['za'], 'ジ': ['ji','zi'], 'ズ': ['zu','du'], 'ゼ': ['ze'], 'ゾ': ['zo'], 'ダ': ['da'], 'ヂ': ['ji','di','dzi'], 'ヅ': ['zu','dzu'], 'デ': ['de'], 'ド': ['do'], 'バ': ['ba'], 'ビ': ['bi'], 'ブ': ['bu'], 'ベ': ['be'], 'ボ': ['bo'], 'パ': ['pa'], 'ピ': ['pi'], 'k_group11_a': { characters: { 'ガ': ['ga'], 'ギ': ['gi'], 'グ': ['gu'], 'ゲ': ['ge'], 'ゴ': ['go'] } },
'プ': ['pu'], 'ペ': ['pe'], 'ポ': ['po'], 'キャ': ['kya'], 'キュ': ['kyu'], 'キョ': ['kyo'], 'シャ': ['sha','sya'], 'シュ': ['shu','syu'], 'ショ': ['sho','syo'], 'チャ': ['cha','cya'], 'チュ': ['chu','cyu'], 'チョ': ['cho','cyo'], 'ニャ': ['nya'], 'ニュ': ['nyu'], 'ニョ': ['nyo'], 'ヒャ': ['hya'], 'ヒュ': ['hyu'], 'ヒョ': ['hyo'], 'ミャ': ['mya'], 'ミュ': ['myu'], 'ミョ': ['myo'], 'リャ': ['rya'], 'リュ': ['ryu'], 'リョ': ['ryo'], 'ギャ': ['gya'], 'ギュ': ['gyu'], 'ギョ': ['gyo'], 'ジャ': ['ja','jya'], 'ジュ': ['ju','jyu'], 'ジョ': ['jo','jyo'], 'ビャ': ['bya'], 'ビュ': ['byu'], 'ビョ': ['byo'], 'ピャ': ['pya'], 'ピュ': ['pyu'], 'ピョ': ['pyo'] } } 'k_group12_a': { characters: { 'ザ': ['za'], 'ジ': ['ji','zi'], 'ズ': ['zu','du'], 'ゼ': ['ze'], 'ゾ': ['zo'] } },
'k_group13_a': { characters: { 'ダ': ['da'], 'ヂ': ['ji','di','dzi'], 'ヅ': ['zu','dzu'], 'デ': ['de'], 'ド': ['do'] } },
'k_group14_a': { characters: { 'バ': ['ba'], 'ビ': ['bi'], 'ブ': ['bu'], 'ベ': ['be'], 'ボ': ['bo'] } },
'k_group15_a': { characters: { 'パ': ['pa'], 'ピ': ['pi'], 'プ': ['pu'], 'ペ': ['pe'], 'ポ': ['po'] } },
'k_group16_a': { characters: { 'キャ': ['kya'], 'キュ': ['kyu'], 'キョ': ['kyo'] } },
'k_group17_a': { characters: { 'シャ': ['sha','sya'], 'シュ': ['shu','syu'], 'ショ': ['sho','syo'] } },
'k_group18_a': { characters: { 'チャ': ['cha','cya'], 'チュ': ['chu','cyu'], 'チョ': ['cho','cyo'] } },
'k_group19_a': { characters: { 'ニャ': ['nya'], 'ニュ': ['nyu'], 'ニョ': ['nyo'] } },
'k_group20_a': { characters: { 'ヒャ': ['hya'], 'ヒュ': ['hyu'], 'ヒョ': ['hyo'] } },
'k_group21_a': { characters: { 'ミャ': ['mya'], 'ミュ': ['myu'], 'ミョ': ['myo'] } },
'k_group22_a': { characters: { 'リャ': ['rya'], 'リュ': ['ryu'], 'リョ': ['ryo'] } },
'k_group23_a': { characters: { 'ギャ': ['gya'], 'ギュ': ['gyu'], 'ギョ': ['gyo'] } },
'k_group24_a': { characters: { 'ジャ': ['ja','jya'], 'ジュ': ['ju','jyu'], 'ジョ': ['jo','jyo'] } },
'k_group25_a': { characters: { 'ビャ': ['bya'], 'ビュ': ['byu'], 'ビョ': ['byo'] } },
'k_group26_a': { characters: { 'ピャ': ['pya'], 'ピュ': ['pyu'], 'ピョ': ['pyo'] } }
} }
}; };