typing-game-cli 4.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Results.js +11 -4
- package/dist/app.js +20 -6
- package/dist/cli.js +30 -4
- package/dist/helpers.js +20 -4
- package/dist/sentences/ambrose-bierce/what-occured-at-franklin.json +16 -0
- package/dist/sentences/daphne-du-maurier/rebecca.json +12 -0
- package/package.json +6 -4
- package/readme.md +16 -3
package/dist/Results.js
CHANGED
|
@@ -2,13 +2,19 @@ import React from 'react';
|
|
|
2
2
|
import { Text, Box } from 'ink';
|
|
3
3
|
import { nanoid } from 'nanoid';
|
|
4
4
|
import { format, parseISO } from 'date-fns';
|
|
5
|
-
import { getResults, getSortedByString } from './helpers.js';
|
|
5
|
+
import { getBestResultCompactString, getResults, getSortedByString } from './helpers.js';
|
|
6
6
|
import Menu from './Menu.js';
|
|
7
7
|
export default function Results({
|
|
8
8
|
sortBy,
|
|
9
|
-
isShowAllHistory
|
|
9
|
+
isShowAllHistory,
|
|
10
|
+
isCompactFormat,
|
|
11
|
+
topN
|
|
10
12
|
}) {
|
|
11
|
-
return /*#__PURE__*/React.createElement(Box, {
|
|
13
|
+
return isCompactFormat ? /*#__PURE__*/React.createElement(Box, {
|
|
14
|
+
flexDirection: "column",
|
|
15
|
+
justifyContent: "center",
|
|
16
|
+
paddingX: 1
|
|
17
|
+
}, /*#__PURE__*/React.createElement(Text, null, ` ${getBestResultCompactString()}`), /*#__PURE__*/React.createElement(Menu, null)) : /*#__PURE__*/React.createElement(Box, {
|
|
12
18
|
flexDirection: "column"
|
|
13
19
|
}, /*#__PURE__*/React.createElement(Box, {
|
|
14
20
|
flexDirection: "row",
|
|
@@ -22,7 +28,8 @@ export default function Results({
|
|
|
22
28
|
flexDirection: "column"
|
|
23
29
|
}, getResults({
|
|
24
30
|
sortBy: '-cpm',
|
|
25
|
-
showAll: false
|
|
31
|
+
showAll: false,
|
|
32
|
+
topN
|
|
26
33
|
}).map((result, i, array) => /*#__PURE__*/React.createElement(Box, {
|
|
27
34
|
key: nanoid(),
|
|
28
35
|
justifyContent: "center",
|
package/dist/app.js
CHANGED
|
@@ -7,7 +7,7 @@ import Gradient from 'ink-gradient';
|
|
|
7
7
|
import { proxy, useSnapshot } from 'valtio';
|
|
8
8
|
import random from 'just-random';
|
|
9
9
|
import { formatISO } from 'date-fns';
|
|
10
|
-
import { getBorderColor, getDefaultSuite, getRobotBorderColor, getStatusVariant, getMessageOrPlaceholder, isFinished, isWordTyped, calculateWPM, getTypingWord, getRemainingPart, getWpmTextColor, calculateCPS, calculateCPM, getBestResult, getScoreTextColor, getCompetitionResult, registerResult, registerBestFrames, getBestFrames, getOpponentFrames } from './helpers.js';
|
|
10
|
+
import { getBorderColor, getDefaultSuite, getRobotBorderColor, getStatusVariant, getMessageOrPlaceholder, isFinished, isWordTyped, calculateWPM, getTypingWord, getRemainingPart, getWpmTextColor, calculateCPS, calculateCPM, getBestResult, getScoreTextColor, getCompetitionResult, registerResult, registerBestFrames, getBestFrames, getOpponentFrames, getSuiteByTopic } from './helpers.js';
|
|
11
11
|
import { optionKeyColor } from './constants.js';
|
|
12
12
|
import Results from './Results.js';
|
|
13
13
|
import { config } from './config.js';
|
|
@@ -16,12 +16,13 @@ import { exitNow } from './cli.js';
|
|
|
16
16
|
const currentTime = () => Date.now();
|
|
17
17
|
const state = proxy({
|
|
18
18
|
status: 'PAUSED',
|
|
19
|
+
topic: null,
|
|
19
20
|
suite: getDefaultSuite(),
|
|
20
21
|
source: null,
|
|
21
22
|
firstPart: '',
|
|
22
23
|
highlightedPart: '',
|
|
23
24
|
erroredPart: '',
|
|
24
|
-
|
|
25
|
+
highlightingColor: 'green',
|
|
25
26
|
showOkCancelQuestion: false,
|
|
26
27
|
gameOver: false,
|
|
27
28
|
okCancelMessage: '',
|
|
@@ -53,14 +54,18 @@ const state = proxy({
|
|
|
53
54
|
isTimerVisible: true,
|
|
54
55
|
timerVisibilityCounter: 0,
|
|
55
56
|
isAnimatingEnd: false,
|
|
56
|
-
showGameResult: false
|
|
57
|
+
showGameResult: false,
|
|
58
|
+
topN: undefined
|
|
57
59
|
});
|
|
58
60
|
export default function App({
|
|
59
61
|
robotLevel,
|
|
62
|
+
topic,
|
|
60
63
|
displayResults = false,
|
|
61
64
|
sortBy,
|
|
62
65
|
isShowAllHistory,
|
|
63
|
-
|
|
66
|
+
isCompactFormat,
|
|
67
|
+
isCompetingAgainstBestResult,
|
|
68
|
+
topN
|
|
64
69
|
}) {
|
|
65
70
|
const snap = useSnapshot(state);
|
|
66
71
|
const {
|
|
@@ -76,7 +81,14 @@ export default function App({
|
|
|
76
81
|
if (isCompetingAgainstBestResult) {
|
|
77
82
|
state.isAgainstMyselft = true;
|
|
78
83
|
}
|
|
79
|
-
|
|
84
|
+
if (topN) {
|
|
85
|
+
state.topN = topN;
|
|
86
|
+
}
|
|
87
|
+
if (topic) {
|
|
88
|
+
state.topic = topic;
|
|
89
|
+
state.suite = getSuiteByTopic(topic);
|
|
90
|
+
}
|
|
91
|
+
}, [displayResults, isCompetingAgainstBestResult, topN, topic]);
|
|
80
92
|
useInput((input, key) => {
|
|
81
93
|
if (input === 'y') {
|
|
82
94
|
const foundBestResult = getBestResult();
|
|
@@ -214,7 +226,9 @@ export default function App({
|
|
|
214
226
|
if (snap.status === 'RESULTS') {
|
|
215
227
|
return /*#__PURE__*/React.createElement(Results, {
|
|
216
228
|
sortBy: sortBy,
|
|
217
|
-
isShowAllHistory: isShowAllHistory
|
|
229
|
+
isShowAllHistory: isShowAllHistory,
|
|
230
|
+
isCompactFormat: isCompactFormat,
|
|
231
|
+
topN: topN
|
|
218
232
|
});
|
|
219
233
|
}
|
|
220
234
|
return snap.status === 'PAUSED' ? /*#__PURE__*/React.createElement(Box, {
|
package/dist/cli.js
CHANGED
|
@@ -24,7 +24,9 @@ const cli = meow(`
|
|
|
24
24
|
--low Start a round with a robot having low typing speed.
|
|
25
25
|
--display-results Show cpm and wpm results
|
|
26
26
|
--sort-by Sort results by specified value (-cpm, cpm, -wpm, wpm, -date, date), Starting "-" indicates descending order, default is "-date"
|
|
27
|
-
--all-
|
|
27
|
+
--all-history Show all history when displaying results (otherwise (default) display last 10 results respecting sorting parameter)
|
|
28
|
+
--topic Use sentences from works written by specified author
|
|
29
|
+
--top-n Display top n results in displaying results mode
|
|
28
30
|
|
|
29
31
|
Short flags and aliases for options:
|
|
30
32
|
--against-my-best: -b, --best, --my-best, --myself, --against-my-best-result
|
|
@@ -36,6 +38,8 @@ const cli = meow(`
|
|
|
36
38
|
--sort-by -s
|
|
37
39
|
--show-all-history: -a, --all, --all-history
|
|
38
40
|
--clear-results: -c, --clear
|
|
41
|
+
--topic: --author
|
|
42
|
+
--top-n: --top
|
|
39
43
|
|
|
40
44
|
|
|
41
45
|
Examples
|
|
@@ -47,11 +51,14 @@ const cli = meow(`
|
|
|
47
51
|
$ typing-game-cli -m
|
|
48
52
|
$ typing-game-cli --low
|
|
49
53
|
$ typing-game-cli --display-results
|
|
54
|
+
$ typing-game-cli --display-results --top 5
|
|
50
55
|
$ typing-game-cli -r
|
|
51
56
|
$ typing-game-cli -r --sort-by="-wpm"
|
|
52
57
|
$ typing-game-cli -r -s="wpm"
|
|
53
58
|
$ typing-game-cli -r -s="-wpm" --all-history
|
|
54
59
|
$ typing-game-cli -r -s="-wpm" -a
|
|
60
|
+
$ typing-game-cli --topic mark-twain
|
|
61
|
+
$ typing-game-cli --author ambrose-bierce
|
|
55
62
|
`, {
|
|
56
63
|
importMeta: import.meta,
|
|
57
64
|
flags: {
|
|
@@ -99,6 +106,19 @@ const cli = meow(`
|
|
|
99
106
|
shortFlag: 'b',
|
|
100
107
|
aliases: ['best', 'myBest', 'myself', 'againstMyBestResult'],
|
|
101
108
|
default: false
|
|
109
|
+
},
|
|
110
|
+
compactResult: {
|
|
111
|
+
type: 'boolean',
|
|
112
|
+
aliases: ['cmpc'],
|
|
113
|
+
default: false
|
|
114
|
+
},
|
|
115
|
+
topN: {
|
|
116
|
+
type: 'number',
|
|
117
|
+
aliases: ['top']
|
|
118
|
+
},
|
|
119
|
+
topic: {
|
|
120
|
+
type: 'string',
|
|
121
|
+
aliases: ['author']
|
|
102
122
|
}
|
|
103
123
|
}
|
|
104
124
|
});
|
|
@@ -113,13 +133,19 @@ const {
|
|
|
113
133
|
displayResults,
|
|
114
134
|
sortBy,
|
|
115
135
|
showAllHistory,
|
|
116
|
-
againstMyBest
|
|
136
|
+
againstMyBest,
|
|
137
|
+
compactResult,
|
|
138
|
+
topN,
|
|
139
|
+
topic
|
|
117
140
|
} = cli.flags;
|
|
118
|
-
render(
|
|
141
|
+
render(/*#__PURE__*/React.createElement(App, {
|
|
119
142
|
robotLevel: robotLevel,
|
|
120
143
|
displayResults: displayResults,
|
|
121
144
|
sortBy: sortBy,
|
|
122
145
|
isShowAllHistory: showAllHistory,
|
|
123
|
-
isCompetingAgainstBestResult: againstMyBest
|
|
146
|
+
isCompetingAgainstBestResult: againstMyBest,
|
|
147
|
+
isCompactFormat: compactResult,
|
|
148
|
+
topN: topN,
|
|
149
|
+
topic: topic
|
|
124
150
|
}));
|
|
125
151
|
export { exitNow };
|
package/dist/helpers.js
CHANGED
|
@@ -3,8 +3,9 @@ import path from 'node:path';
|
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { fdir as Fdir } from 'fdir';
|
|
5
5
|
import random from 'just-random';
|
|
6
|
+
import compose from 'just-compose';
|
|
6
7
|
import sortBy from 'just-sort-by';
|
|
7
|
-
import { formatISO, isValid, parseISO } from 'date-fns';
|
|
8
|
+
import { format, formatISO, isValid, parseISO } from 'date-fns';
|
|
8
9
|
import Config from './config.js';
|
|
9
10
|
import { frames } from './robotFrames.js';
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -15,6 +16,13 @@ const sourcesPath = path.join(__dirname, 'sentences');
|
|
|
15
16
|
const isWon = value => value === won;
|
|
16
17
|
const isLost = value => value === lost;
|
|
17
18
|
const files = new Fdir().filter((path, _isDirectory) => path.endsWith('.json')).withFullPaths().crawl(sourcesPath).sync();
|
|
19
|
+
const getFilesByTopic = topic => {
|
|
20
|
+
return new Fdir().filter((path, _isDirectory) => path.endsWith('.json')).withFullPaths().crawl(path.join(sourcesPath, topic)).sync();
|
|
21
|
+
};
|
|
22
|
+
const readFile = file => fs.readFileSync(file, 'utf8');
|
|
23
|
+
const getSuiteByTopic = topic => {
|
|
24
|
+
return compose(getFilesByTopic, random, readFile, JSON.parse)(topic);
|
|
25
|
+
};
|
|
18
26
|
const getDefaultSuite = () => {
|
|
19
27
|
return JSON.parse(fs.readFileSync(random(files), 'utf8'));
|
|
20
28
|
};
|
|
@@ -109,7 +117,8 @@ const getRemainingPart = (source, typed, hasErroredPart = false) => {
|
|
|
109
117
|
};
|
|
110
118
|
const getResults = ({
|
|
111
119
|
sortBy: sortByValue = '-wpm',
|
|
112
|
-
showAll = false
|
|
120
|
+
showAll = false,
|
|
121
|
+
topN
|
|
113
122
|
}) => {
|
|
114
123
|
const config = new Config();
|
|
115
124
|
const data = config.get();
|
|
@@ -140,7 +149,7 @@ const getResults = ({
|
|
|
140
149
|
return -parseISO(item.date);
|
|
141
150
|
});
|
|
142
151
|
if (!showAll) {
|
|
143
|
-
return result.slice(0, 10);
|
|
152
|
+
return result.slice(0, topN === undefined ? 10 : topN);
|
|
144
153
|
}
|
|
145
154
|
return result;
|
|
146
155
|
};
|
|
@@ -159,6 +168,13 @@ const getBestResult = () => {
|
|
|
159
168
|
if (targetItems.length === 0) return null;
|
|
160
169
|
return sortBy(targetItems, item => -item.value.cpm)[0];
|
|
161
170
|
};
|
|
171
|
+
const getBestResultCompactString = () => {
|
|
172
|
+
const result = getBestResult();
|
|
173
|
+
if (!result) {
|
|
174
|
+
return 'There is no data, please run some rounds to collect stats.';
|
|
175
|
+
}
|
|
176
|
+
return `Date: ${format(parseISO(result.date), 'MM/dd/yyyy HH:mm')}; wpm: ${result.value.wpm}; cpm: ${result.value.cpm}.`;
|
|
177
|
+
};
|
|
162
178
|
const getResultByWordCount = ({
|
|
163
179
|
wordCount
|
|
164
180
|
}) => {
|
|
@@ -203,4 +219,4 @@ const registerBestFrames = (config, frames) => {
|
|
|
203
219
|
bestFrames: frames
|
|
204
220
|
});
|
|
205
221
|
};
|
|
206
|
-
export { getDefaultSuite, getStatusVariant, getWpmTextColor, getScoreTextColor, getMessage, getMessageOrPlaceholder, getBorderColor, getRobotBorderColor, getIntervalMs, isFinished, isWordTyped, calculateWPM, calculateCPS, calculateCPM, getCompetitionResult, getTypingWord, getRemainingPart, getResults, getBestResult, getBestFrames, getOpponentFrames, getResultByWordCount, getBestWpmResult, getSortedByString, getWordCount, registerResult, registerBestFrames };
|
|
222
|
+
export { getDefaultSuite, getStatusVariant, getWpmTextColor, getScoreTextColor, getMessage, getMessageOrPlaceholder, getBorderColor, getRobotBorderColor, getIntervalMs, isFinished, isWordTyped, calculateWPM, calculateCPS, calculateCPM, getCompetitionResult, getTypingWord, getRemainingPart, getResults, getBestResult, getBestResultCompactString, getBestFrames, getOpponentFrames, getResultByWordCount, getBestWpmResult, getSortedByString, getWordCount, getSuiteByTopic, registerResult, registerBestFrames };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sentences": [
|
|
3
|
+
"For several days, in snow and rain, General Schofield's little army had crouched in its hastily constructed defenses at Columbia, Tennessee. It had retreated in hot haste from Pulaski, thirty miles to the south, arriving just in time to foil Hood, who, marching from Florence, Alabama, by another road, with a force of more than double our strength, had hoped to intercept us. Had he succeeded, he would indubitably have bagged the whole bunch of us.",
|
|
4
|
+
"As it was, he simply took position in front of us and gave us plenty of employment, but did not attack; he knew a trick worth two of that. Duck River was directly in our rear; I suppose both our flanks rested on it. The town was between them. One night--that of November 27, 1864--we pulled up stakes and crossed to the north bank to continue our retreat to Nashville, where Thomas and safety lay - such safety as is known in war.",
|
|
5
|
+
"It was high time too, for before noon of the next day Forrest's cavalry forded the river a few miles above us and began pushing back our own horse toward Spring Hill, ten miles in our rear, on our only road. Why our infantry was not immediately put in motion toward the threatened point, so vital to our safety, General Schofield could have told better than I. Howbeit, we lay there inactive all day. The next morning - a bright and beautiful one - the brigade of Colonel P. Sidney Post was thrown out, up the river four or five miles, to see what it could see.",
|
|
6
|
+
"What it saw was Hood's head-of-column coming over on a pontoon bridge, and a right pretty spectacle it would have been to one whom it did not concern. It concerned us rather keenly. As a member of Colonel Post's staff, I was naturally favored with a good view of the performance. We formed in line of battle at a distance of perhaps a half-mile from the bridge-head, but that unending column of gray and steel gave us no more attention than if we had been a crowd of farmer-folk. Why should it?",
|
|
7
|
+
"It had only to face to the left to be itself a line of battle. Meantime it had more urgent business on hand than brushing away a small brigade whose only offense was curiosity; it was making for Spring Hill with all its legs and wheels. Hour after hour we watched that unceasing flow of infantry and artillery toward the rear of our army. It was an unnerving spectacle, yet we never for a moment doubted that, acting on the intelligence supplied by our succession of couriers, our entire force was moving rapidly to the point of contact. The battle of Spring Hill was obviously decreed.",
|
|
8
|
+
"Obviously, too, our brigade of observation would be among the last to have a hand in it. The thought annoyed us, made us restless and resentful. Our mounted men rode forward and back behind the line, nervous and distressed; the men in the ranks sought relief in frequent changes of posture, in shifting their weight from one leg to the other, in needless inspection of their weapons and in that unfailing resource of the discontented soldier, audible damning of those in the saddles of authority. But never for more than a moment at a time did anyone remove his eyes from that fascinating and portentous pageant.",
|
|
9
|
+
"Toward evening we were recalled, to learn that of our five divisions of infantry, with their batteries, numbering twenty-three thousand men, only one--Stanley's, four thousand weak--had been sent to Spring Hill to meet that formidable movement of Hood's three veteran corps! Why Stanley was not immediately effaced is still a matter of controversy. Hood, who was early on the ground, declared that he gave the needful orders and tried vainly to enforce them; Cheatham, in command of his leading corps, declared that he did not.",
|
|
10
|
+
"Doubtless the dispute is still being carried on between these chieftains from their beds of asphodel and moly in Elysium. So much is certain: Stanley drove away Forrest and successfully held the junction of the roads against Cleburne's division, the only infantry that attacked him. That night the entire Confederate army lay within a half mile of our road, while we all sneaked by, infantry, artillery, and trains. The enemy's camp-fires shone redly - miles of them - seeming only a stone's throw from our hurrying column.",
|
|
11
|
+
"His men were plainly visible about them, cooking their suppers - a sight so incredible that many of our own, thinking them friends, strayed over to them and did not return. At intervals of a few hundred yards we passed dim figures on horseback by the roadside, enjoining silence. Needless precaution; we could not have spoken if we had tried, for our hearts were in our throats. But fools are God's peculiar care, and one of his protective methods is the stupidity of other fools. By daybreak our last man and last wagon had passed the fateful spot unchallenged, and our first were entering Franklin, ten miles away.",
|
|
12
|
+
"Despite spirited cavalry attacks on trains and rear-guard, all were in Franklin by noon and such of the men as could be kept awake were throwing up a slight line of defense, inclosing the town. Franklin lies - or at that time did lie; I know not what exploration might now disclose - on the south bank of a small river, the Harpeth by name. For two miles southward was a nearly flat, open plain, extending to a range of low hills through which passed the turnpike by which we had come.",
|
|
13
|
+
"From some bluffs on the precipitous north bank of the river was a commanding overlook of all this open ground, which, although more than a mile away, seemed almost at one's feet. On this elevated ground the wagon-train had been parked and General Schofield had stationed himself - the former for security, the latter for outlook. Both were guarded by General Wood's infantry division, of which my brigade was a part. \"We are in beautiful luck,\" said a member of the division staff. With some prevision of what was to come and a lively recollection of the nervous strain of helpless observation, I did not think it luck."
|
|
14
|
+
],
|
|
15
|
+
"tags": ["ambrose-bierce", "what-occured-at-franklin"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sentences": [
|
|
3
|
+
"Last night I dreamt I went to Manderley again. It seemed to me I stood by the iron gate leading to the drive, and for a while I could not enter, for the way was barred to me. There was a padlock and a chain upon the gate. I called in my dream to the lodge-keeper, and had no answer, and peering closer through the rusted spokes of the gate I saw that the lodge was uninhabited.",
|
|
4
|
+
"There was a padlock and a chain upon the gate. I called in my dream to the lodge-keeper, and had no answer, and peering closer through the rusted spokes of the gate I saw that the lodge was uninhabited. No smoke came from the chimney, and the little lattice windows gaped forlorn. Then, like all dreamers, I was possessed of a sudden with supernatural powers and passed like a spirit through the barrier before me.",
|
|
5
|
+
"The drive wound away in front of me, twisting and turning as it had always done, but as I advanced I was aware that a change had come upon it; it was narrow and unkept, not the drive that we had known. At first I was puzzled and did not understand, and it was only when I bent my head to avoid the low swinging branch of a tree that I realised what had happened.",
|
|
6
|
+
"Nature had come into her own again and, little by, little, in her stealthy, insidious way had encroached upon the drive with long tenacious fingers. The woods, always a menace even in the past, had triumphed in the end. They crwoded, dark and uncrontrolled, to the borders of the drive. The beeches with white. naked limbs leant close to one another, their branches intermingled in a strange embrace, making a vault above my head like the archway of a church.",
|
|
7
|
+
"And there were other trees as well, trees that I did not recognise, squat oaks and tortured elms that straggled cheek by jowl with the beeches, and had trust themselves out of the quiet earth, along with monster shrubs amd plants, none of which I remembered. The drive was a ribbon now, a thread of its former self, with gravel surface gone, and choked with grass and moss. The trees had thrown out low branches, making an impediment to progress; the gnarled roots looked like skeleton claws.",
|
|
8
|
+
"Scattered here and again amongs his jungle growth I would recognise shrubs that had been land-marks in our time, things of culture and of gracem hydrangeas whose blue heads had been famous. No hand had checked their progress, and they had gone native now, rearing to monster height without a bloom, back and ugly as the nameless parasites that grew beside them.",
|
|
9
|
+
"On and on. now east, now west, would the poor thread that once had been out drive. Sometimes I thought it lost, but it appeared again, beneath a fallen tree perhaps or struggling on the other side of a muddied ditch created by the winter rains. I had not thought the way so long. Surely the miles had multiplied, even as the trees had done, and this path led but to a labirynth, some choked wilderness, and not to the house at all."
|
|
10
|
+
],
|
|
11
|
+
"tags": ["daphne-du-maurier", "maurier"]
|
|
12
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typing-game-cli",
|
|
3
3
|
"description": "Command line game to practice your typing speed by competing against typer-robot or against your best result",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "6.0.0",
|
|
5
5
|
"homepage": "https://github.com/akgondber/typing-game-cli",
|
|
6
6
|
"repository": "akgondber/typing-game-cli",
|
|
7
7
|
"author": "Rushan Alyautdinov <akgondber@gmail.com>",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "babel --out-dir=dist source --copy-files",
|
|
21
21
|
"dev": "babel --out-dir=dist --watch source",
|
|
22
|
-
"test": "prettier --check . && xo && ava",
|
|
22
|
+
"test": "prettier --check . && xo && loadr -- ava",
|
|
23
23
|
"justtest": "ava --serial",
|
|
24
24
|
"lint": "xo",
|
|
25
25
|
"go": "node dist/cli.js",
|
|
@@ -50,13 +50,14 @@
|
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@babel/cli": "^7.22.5",
|
|
53
|
-
"@babel/preset-react": "^7.
|
|
53
|
+
"@babel/preset-react": "^7.25.9",
|
|
54
54
|
"ava": "^6.1.2",
|
|
55
55
|
"eslint-config-xo-react": "^0.27.0",
|
|
56
56
|
"eslint-plugin-react": "^7.34.1",
|
|
57
57
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
58
58
|
"import-jsx": "^5.0.0",
|
|
59
59
|
"ink-testing-library": "^3.0.0",
|
|
60
|
+
"loadr": "^0.1.1",
|
|
60
61
|
"prettier": "^3.2.5",
|
|
61
62
|
"xo": "^0.58.0"
|
|
62
63
|
},
|
|
@@ -66,7 +67,8 @@
|
|
|
66
67
|
},
|
|
67
68
|
"nodeArguments": [
|
|
68
69
|
"--loader=import-jsx"
|
|
69
|
-
]
|
|
70
|
+
],
|
|
71
|
+
"timeout": "20s"
|
|
70
72
|
},
|
|
71
73
|
"xo": {
|
|
72
74
|
"extends": "xo-react",
|
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# typing-game-cli [![NPM version][npm-image]][npm-url]
|
|
2
2
|
|
|
3
|
-
> Command
|
|
3
|
+
> Command-line game to practice your typing speed by competing against typer-robot or against your best result.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -30,6 +30,9 @@ $ npm install --global typing-game-cli
|
|
|
30
30
|
--display-results Show cpm and wpm results
|
|
31
31
|
--sort-by Sort results by specified value (-cpm, cpm, -wpm, wpm, -date, date), Starting "-" indicates descending order, default is "-date"
|
|
32
32
|
--all-hostory Show all history when displaying results (otherwise (default) display last 10 results respecting sorting parameter)
|
|
33
|
+
--compact-result Display top result in compact format
|
|
34
|
+
--topic Use sentences from works written by specified author
|
|
35
|
+
--top-n Display top n results when `--display-results` is being used
|
|
33
36
|
|
|
34
37
|
Short flags and aliases for options:
|
|
35
38
|
--against-my-best: -b, --best, --my-best, --myself, --against-my-best-result
|
|
@@ -41,6 +44,9 @@ $ npm install --global typing-game-cli
|
|
|
41
44
|
--sort-by -s
|
|
42
45
|
--show-all-history: -a, --all, --all-history
|
|
43
46
|
--clear-results: -c, --clear
|
|
47
|
+
--compact-result --cmpc
|
|
48
|
+
--topic --author
|
|
49
|
+
--top-n --top
|
|
44
50
|
|
|
45
51
|
|
|
46
52
|
Examples
|
|
@@ -52,11 +58,14 @@ $ npm install --global typing-game-cli
|
|
|
52
58
|
$ typing-game-cli -m
|
|
53
59
|
$ typing-game-cli --low
|
|
54
60
|
$ typing-game-cli --display-results
|
|
61
|
+
$ typing-game-cli --display-results --top 3
|
|
55
62
|
$ typing-game-cli -r
|
|
56
63
|
$ typing-game-cli -r --sort-by="-wpm"
|
|
57
64
|
$ typing-game-cli -r -s="wpm"
|
|
58
65
|
$ typing-game-cli -r -s="-wpm" --all-history
|
|
59
66
|
$ typing-game-cli -r -s="-wpm" -a
|
|
67
|
+
$ typing-game-cli --topic ambrose-bierce
|
|
68
|
+
$ typing-game-cli --author mark-twain
|
|
60
69
|
```
|
|
61
70
|
|
|
62
71
|
## Demo
|
|
@@ -65,7 +74,7 @@ $ npm install --global typing-game-cli
|
|
|
65
74
|
|
|
66
75
|
## Screenshots
|
|
67
76
|
|
|
68
|
-
### Competition
|
|
77
|
+
### Competition against fast robot
|
|
69
78
|
|
|
70
79
|
```
|
|
71
80
|
$ typing-game-cli --fast
|
|
@@ -73,7 +82,7 @@ $ typing-game-cli --fast
|
|
|
73
82
|
|
|
74
83
|

|
|
75
84
|
|
|
76
|
-
### Competition
|
|
85
|
+
### Competition against best result
|
|
77
86
|
|
|
78
87
|
```
|
|
79
88
|
$ typing-game-cli --my-best
|
|
@@ -91,6 +100,10 @@ $ tgc -b
|
|
|
91
100
|
|
|
92
101
|

|
|
93
102
|
|
|
103
|
+
#### Example - Display top n results
|
|
104
|
+
|
|
105
|
+

|
|
106
|
+
|
|
94
107
|
## License
|
|
95
108
|
|
|
96
109
|
MIT © [Rushan Alyautdinov](https://github.com/akgondber)
|