Add letter distribution and word length stats
This commit is contained in:
parent
ae50f5f970
commit
526f22c329
|
@ -109,7 +109,7 @@ export function characterIsUppercase (character) {
|
|||
return character === character.toUpperCase();
|
||||
}
|
||||
|
||||
export function getWordsStats (words, partsOfSpeech) {
|
||||
export function getWordsStats (words, partsOfSpeech, isCaseSensitive = false) {
|
||||
const wordStats = {
|
||||
numberOfWords: [
|
||||
{
|
||||
|
@ -117,6 +117,19 @@ export function getWordsStats (words, partsOfSpeech) {
|
|||
value: words.length,
|
||||
},
|
||||
],
|
||||
wordLength: {
|
||||
shortest: 0,
|
||||
longest: 0,
|
||||
average: 0,
|
||||
},
|
||||
letterDistribution: [
|
||||
// {
|
||||
// letter: '',
|
||||
// number: 0,
|
||||
// percentage: 0.00,
|
||||
// }
|
||||
],
|
||||
totalLetters: 0,
|
||||
};
|
||||
|
||||
partsOfSpeech.forEach(partOfSpeech => {
|
||||
|
@ -132,5 +145,53 @@ export function getWordsStats (words, partsOfSpeech) {
|
|||
value: words.filter(word => !partsOfSpeech.includes(word.partOfSpeech)).length,
|
||||
});
|
||||
|
||||
let totalLetters = 0;
|
||||
const numberOfLetters = {};
|
||||
|
||||
words.forEach(word => {
|
||||
const shortestWord = wordStats.wordLength.shortest;
|
||||
const longestWord = wordStats.wordLength.longest;
|
||||
const wordLetters = word.name.split('');
|
||||
const lettersInWord = wordLetters.length;
|
||||
|
||||
totalLetters += lettersInWord;
|
||||
|
||||
if (shortestWord === 0 || lettersInWord < shortestWord) {
|
||||
wordStats.wordLength.shortest = lettersInWord;
|
||||
}
|
||||
|
||||
if (longestWord === 0 || lettersInWord > longestWord) {
|
||||
wordStats.wordLength.longest = lettersInWord;
|
||||
}
|
||||
|
||||
wordLetters.forEach(letter => {
|
||||
const letterToUse = isCaseSensitive ? letter : letter.toLowerCase();
|
||||
if (!numberOfLetters.hasOwnProperty(letterToUse)) {
|
||||
numberOfLetters[letterToUse] = 1;
|
||||
} else {
|
||||
numberOfLetters[letterToUse]++;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
wordStats.totalLetters = totalLetters;
|
||||
wordStats.wordLength.average = totalLetters / words.length;
|
||||
|
||||
for (const letter in numberOfLetters) {
|
||||
if (numberOfLetters.hasOwnProperty(letter)) {
|
||||
const number = numberOfLetters[letter];
|
||||
wordStats.letterDistribution.push({
|
||||
letter,
|
||||
number,
|
||||
percentage: number / totalLetters,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
wordStats.letterDistribution.sort((a, b) => {
|
||||
if (a.percentage === b.percentage) return 0;
|
||||
return (a.percentage > b.percentage) ? -1 : 1;
|
||||
});
|
||||
|
||||
return wordStats;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
import Inferno from 'inferno';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const StatsSection = (props) => {
|
||||
PropTypes.checkPropTypes({
|
||||
stats: PropTypes.object.isRequired,
|
||||
}, props, 'prop', 'StatsSection');
|
||||
|
||||
const {
|
||||
numberOfWords,
|
||||
wordLength,
|
||||
letterDistribution,
|
||||
totalLetters
|
||||
} = props.stats;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='columns'>
|
||||
<div className='column'>
|
||||
<strong>Number of Words</strong>
|
||||
<div className='field is-grouped is-grouped-multiline'>
|
||||
{numberOfWords.map(stat => {
|
||||
return (
|
||||
<div className='control'>
|
||||
<div className='tags has-addons'>
|
||||
<span className='tag'>
|
||||
{ stat.name }
|
||||
</span>
|
||||
<span className='tag is-white'>
|
||||
{ stat.value }
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='columns'>
|
||||
<div className='column'>
|
||||
<strong>Word Length</strong>
|
||||
<div className='field is-grouped is-grouped-multiline'>
|
||||
|
||||
<div className='control'>
|
||||
<div className='tags has-addons'>
|
||||
<span className='tag'>
|
||||
Shortest
|
||||
</span>
|
||||
<span className='tag is-white'>
|
||||
{ wordLength.shortest }
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='control'>
|
||||
<div className='tags has-addons'>
|
||||
<span className='tag'>
|
||||
Longest
|
||||
</span>
|
||||
<span className='tag is-white'>
|
||||
{ wordLength.longest }
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='control'>
|
||||
<div className='tags has-addons'>
|
||||
<span className='tag'>
|
||||
Average
|
||||
</span>
|
||||
<span className='tag is-white'>
|
||||
{ wordLength.average }
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='columns'>
|
||||
<div className='column'>
|
||||
<strong>Letter Distribution</strong>
|
||||
<div className='field is-grouped is-grouped-multiline'>
|
||||
{letterDistribution.map(stat => {
|
||||
return (
|
||||
<div className='control'>
|
||||
<div className='tags has-addons' title={ `${ stat.number } ${ stat.letter }'s total` }>
|
||||
<span className='tag'>
|
||||
{ stat.letter }
|
||||
</span>
|
||||
<span className='tag is-white'>
|
||||
{ stat.percentage.toFixed(2) }
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<span>{ totalLetters } Total Letters</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -8,6 +8,7 @@ import './styles.scss';
|
|||
|
||||
import { EditDictionaryModal } from '../../management/EditDictionaryModal';
|
||||
import { DetailsSection } from './DetailsSection';
|
||||
import { StatsSection } from './StatsSection';
|
||||
|
||||
const DISPLAY = {
|
||||
NONE: false,
|
||||
|
@ -28,7 +29,7 @@ export class DictionaryDetails extends Component {
|
|||
alphabeticalOrder: PropTypes.array,
|
||||
details: PropTypes.object,
|
||||
settings: PropTypes.object,
|
||||
stats: PropTypes.array,
|
||||
stats: PropTypes.object,
|
||||
updater: PropTypes.object,
|
||||
updateDisplay: PropTypes.func,
|
||||
}, props, 'prop', 'DictionaryDetails');
|
||||
|
@ -88,27 +89,7 @@ export class DictionaryDetails extends Component {
|
|||
|
||||
case DISPLAY.STATS : {
|
||||
displayJSX = (
|
||||
<div className='columns'>
|
||||
<div className='column'>
|
||||
<strong>Number of Words</strong>
|
||||
<div className='field is-grouped is-grouped-multiline'>
|
||||
{this.props.stats.numberOfWords.map(stat => {
|
||||
return (
|
||||
<div className='control'>
|
||||
<div className='tags has-addons'>
|
||||
<span className='tag'>
|
||||
{ stat.name }
|
||||
</span>
|
||||
<span className='tag is-white'>
|
||||
{ stat.value }
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<StatsSection stats={ this.props.stats } />
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class App extends Component {
|
|||
partsOfSpeech: dictionary.partsOfSpeech,
|
||||
details: dictionary.details,
|
||||
settings: dictionary.settings,
|
||||
stats: [],
|
||||
stats: {},
|
||||
alphabeticalOrder: dictionary.alphabeticalOrder,
|
||||
|
||||
displayedWords: [],
|
||||
|
@ -71,15 +71,15 @@ class App extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
updateDisplayedWords () {
|
||||
updateDisplayedWords (callback = () => {}) {
|
||||
// const {searchIn, searchTerm, filteredPartsOfSpeech} = this.state.searchConfig;
|
||||
|
||||
// TODO: Sort out searching to remove this temporary solution.
|
||||
dictionary.wordsPromise.then(words => {
|
||||
this.setState({
|
||||
displayedWords: words,
|
||||
stats: getWordsStats(words, this.state.partsOfSpeech),
|
||||
});
|
||||
stats: getWordsStats(words, this.state.partsOfSpeech, this.state.settings.caseSensitive),
|
||||
}, () => callback());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -58,12 +58,15 @@ export class Updater {
|
|||
updatedDetails['settings'] = this.dictionary.settings;
|
||||
}
|
||||
|
||||
console.log(updatedDetails);
|
||||
// console.log(updatedDetails);
|
||||
|
||||
if (updatedDetails.isEmpty()) {
|
||||
reject('No dictionary details have changed.');
|
||||
} else {
|
||||
this.app.setState(updatedDetails, () => {
|
||||
if (updatedDetails.hasOwnProperty('settings')) {
|
||||
this.app.updateDisplayedWords();
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue