shunkuntype 1.1.0 → 1.1.2
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.
- checksums.yaml +4 -4
- data/.hyper_card/history/plot_modes.md +791 -0
- data/.hyper_card/history/plot_modes_251118.md +836 -0
- data/README.md +3 -14
- data/lib/shunkuntype/db.rb +9 -21
- data/lib/shunkuntype/speed.rb +12 -4
- data/lib/shunkuntype/version.rb +1 -1
- data/lib/shunkuntype.rb +97 -2
- metadata +5 -8
- data/shunkuntype/speed_data.txt +0 -6
- data/shunkuntype/training_data.txt +0 -36
data/README.md
CHANGED
|
@@ -25,22 +25,11 @@ Usage: shunkuntype [options]
|
|
|
25
25
|
-v, --version show program Version.
|
|
26
26
|
-c, --check Check speed
|
|
27
27
|
-d, --drill [VAL] one minute Drill [VAL]
|
|
28
|
-
-h, --
|
|
29
|
-
-
|
|
30
|
-
-s, --submit Submit data to dmz0
|
|
31
|
-
--review [VALUE] Review training, VALUE=html or hiki
|
|
28
|
+
-h, --help show help message
|
|
29
|
+
-l, --log view training Log
|
|
32
30
|
```
|
|
33
31
|
For the first time, shunkun makes .shunkuntype directory on the home dir,
|
|
34
|
-
and put
|
|
35
|
-
The training and speed data will be sent to the server, when --submit.
|
|
36
|
-
The --review will get the data download, and show the training and speed data in hiki or html formats,
|
|
37
|
-
where the png files created by gnuplot.
|
|
38
|
-
|
|
39
|
-
For activating server all training member has ssh access, and the write permission on the directory.
|
|
40
|
-
The format of the server_data.txt is as follows:
|
|
41
|
-
```
|
|
42
|
-
[login_name]\@[server_name]:directory
|
|
43
|
-
```
|
|
32
|
+
and put two data files(training, speed).
|
|
44
33
|
|
|
45
34
|
## Development
|
|
46
35
|
|
data/lib/shunkuntype/db.rb
CHANGED
|
@@ -6,37 +6,25 @@ require 'fileutils'
|
|
|
6
6
|
module DataFiles
|
|
7
7
|
|
|
8
8
|
def self.prepare
|
|
9
|
-
|
|
9
|
+
speed_path = Shunkuntype::SPEED_FILE
|
|
10
|
+
training_path = Shunkuntype::TRAINING_FILE
|
|
10
11
|
|
|
11
|
-
create_file_if_not_exists(
|
|
12
|
+
create_file_if_not_exists(speed_path)
|
|
13
|
+
create_file_if_not_exists(training_path)
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
def self.create_file_if_not_exists(path)
|
|
15
17
|
create_file_path(path)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
unless File.exist?(path)
|
|
19
|
+
File.open(path, 'w') {} # 空ファイルを作成
|
|
20
|
+
puts "Created #{path}"
|
|
21
|
+
end
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
def self.create_file_path(path)
|
|
22
25
|
FileUtils.mkdir_p File.dirname(path)
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
if File::exist?("./speed_data.txt") then
|
|
27
|
-
system "mv ./speed_data.txt #{Shunkuntype::SPEED_FILE}"
|
|
28
|
-
print "moving ./speed_data.txt #{Shunkuntype::SPEED_FILE}.\n"
|
|
29
|
-
end
|
|
30
|
-
if File::exist?("./training_data.txt") then
|
|
31
|
-
system "mv ./training_data.txt #{Shunkuntype::TRAINING_FILE}"
|
|
32
|
-
print "moving ./training_data.txt #{Shunkuntype::TRAINING_FILE}.\n"
|
|
33
|
-
if File::exist?(Shunkuntype::TRAINING_FILE) then
|
|
34
|
-
print "#{Shunkuntype::TRAINING_FILE} exits.\n"
|
|
35
|
-
File::open(Shunkuntype::TRAINING_FILE,'a')
|
|
36
|
-
print "make #{Shunkuntype::TRAINING_FILE}\n"
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
private_class_method :create_file_if_not_exists, :create_file_path, :create_data_files
|
|
28
|
+
private_class_method :create_file_if_not_exists, :create_file_path
|
|
41
29
|
end
|
|
42
30
|
|
data/lib/shunkuntype/speed.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "shunkuntype"
|
|
2
|
+
require_relative "db" # 追加
|
|
2
3
|
|
|
3
4
|
class SpeedCheck
|
|
4
5
|
attr_reader :number, :period
|
|
@@ -22,17 +23,24 @@ class SpeedCheck
|
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def check_data_files
|
|
26
|
+
retried = false
|
|
25
27
|
begin
|
|
26
|
-
file=open(Shunkuntype::SPEED_FILE,"r")
|
|
28
|
+
file = open(Shunkuntype::SPEED_FILE, "r")
|
|
27
29
|
if file
|
|
28
30
|
puts "#{Shunkuntype::SPEED_FILE} opened succcessfully"
|
|
29
31
|
end
|
|
30
32
|
rescue
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
if retried
|
|
34
|
+
puts "Failed to create #{Shunkuntype::SPEED_FILE}. Please check permissions."
|
|
35
|
+
exit 1
|
|
36
|
+
end
|
|
37
|
+
puts "#{Shunkuntype::SPEED_FILE} does not exist in this directory. Creating required files..."
|
|
38
|
+
DataFiles.prepare
|
|
39
|
+
retried = true
|
|
40
|
+
retry
|
|
33
41
|
end
|
|
34
42
|
end
|
|
35
|
-
|
|
43
|
+
|
|
36
44
|
def mk_random_words
|
|
37
45
|
data=[]
|
|
38
46
|
data_dir=File.expand_path('../../../lib/data', __FILE__)
|
data/lib/shunkuntype/version.rb
CHANGED
data/lib/shunkuntype.rb
CHANGED
|
@@ -24,7 +24,6 @@ end
|
|
|
24
24
|
class Command
|
|
25
25
|
|
|
26
26
|
def self.run(argv=[])
|
|
27
|
-
print "Shunkuntype says 'Hello world'.\n"
|
|
28
27
|
new(argv).execute
|
|
29
28
|
end
|
|
30
29
|
|
|
@@ -35,7 +34,8 @@ class Command
|
|
|
35
34
|
def execute
|
|
36
35
|
DataFiles.prepare
|
|
37
36
|
|
|
38
|
-
@
|
|
37
|
+
@mode = nil
|
|
38
|
+
|
|
39
39
|
command_parser = OptionParser.new do |opt|
|
|
40
40
|
opt.on('-v', '--version','show program Version.') { |v|
|
|
41
41
|
opt.version = Shunkuntype::VERSION
|
|
@@ -45,8 +45,103 @@ class Command
|
|
|
45
45
|
opt.on('-d', '--drill [VAL]','one minute Drill [VAL]', Integer) {|v| Training.new(v) }
|
|
46
46
|
opt.on('-h', '--help','show help message') { puts opt; exit }
|
|
47
47
|
opt.on('-l','--log','view training log') {|v| FinishCheck.new }
|
|
48
|
+
opt.on('-r MODE', '--record MODE',
|
|
49
|
+
"Show record data in readable format.\n" \
|
|
50
|
+
" MODE can be:\n" \
|
|
51
|
+
" all Show both speed and training data (default)\n" \
|
|
52
|
+
" plot Output matplotlib code for plotting\n" \
|
|
53
|
+
" speed_data Show only speed data\n" \
|
|
54
|
+
" training_data Show only training data"
|
|
55
|
+
) {|mode| @mode = mode }
|
|
56
|
+
# opt.on('-r', '--record', 'Show both speed and training data (same as -r all)') { @mode = 'all' }
|
|
48
57
|
end
|
|
49
58
|
command_parser.parse!(@argv)
|
|
59
|
+
# データ表示
|
|
60
|
+
case @mode
|
|
61
|
+
when 'plot', 'python'
|
|
62
|
+
print_python_plot_code
|
|
63
|
+
exit
|
|
64
|
+
when 'speed_data'
|
|
65
|
+
print_csv_pretty(Shunkuntype::SPEED_FILE, %w[Time Words TimeSec Score])
|
|
66
|
+
exit
|
|
67
|
+
when 'training_data'
|
|
68
|
+
print_csv_pretty(Shunkuntype::TRAINING_FILE, %w[Time Words TimeSec Score])
|
|
69
|
+
exit
|
|
70
|
+
when 'all'
|
|
71
|
+
print_pretty_data
|
|
72
|
+
exit
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
@argv << '--help' if @argv.size==0
|
|
76
|
+
command_parser.parse!(@argv)
|
|
50
77
|
exit
|
|
51
78
|
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def print_pretty_data
|
|
83
|
+
print_csv_pretty(Shunkuntype::SPEED_FILE, %w[Time Words TimeSec Score])
|
|
84
|
+
print_csv_pretty(Shunkuntype::TRAINING_FILE, %w[Time Words TimeSec Score])
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def print_csv_pretty(path, headers)
|
|
88
|
+
if File.exist?(path)
|
|
89
|
+
puts "== #{File.basename(path)} =="
|
|
90
|
+
puts headers.join("\t")
|
|
91
|
+
File.foreach(path) do |line|
|
|
92
|
+
puts line.chomp.split(',').join("\t")
|
|
93
|
+
end
|
|
94
|
+
puts
|
|
95
|
+
else
|
|
96
|
+
puts "#{path} not found."
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def print_python_plot_code
|
|
101
|
+
speed_path = Shunkuntype::SPEED_FILE
|
|
102
|
+
training_path = Shunkuntype::TRAINING_FILE
|
|
103
|
+
puts "# Python (matplotlib) code for plotting your typing data"
|
|
104
|
+
puts "# Save this as plot_typing.py and run: python plot_typing.py"
|
|
105
|
+
puts <<~PYTHON
|
|
106
|
+
import matplotlib.pyplot as plt
|
|
107
|
+
import csv
|
|
108
|
+
from datetime import datetime
|
|
109
|
+
|
|
110
|
+
def load_data(path):
|
|
111
|
+
times, scores = [], []
|
|
112
|
+
try:
|
|
113
|
+
with open(path) as f:
|
|
114
|
+
reader = csv.reader(f)
|
|
115
|
+
for row in reader:
|
|
116
|
+
if len(row) < 4:
|
|
117
|
+
continue
|
|
118
|
+
# row[0]: time, row[2]: score
|
|
119
|
+
try:
|
|
120
|
+
t = datetime.strptime(row[0].split('.')[0], '%Y-%m-%d %H:%M:%S %z')
|
|
121
|
+
s = float(row[2])
|
|
122
|
+
times.append(t)
|
|
123
|
+
scores.append(s)
|
|
124
|
+
except Exception:
|
|
125
|
+
continue
|
|
126
|
+
except FileNotFoundError:
|
|
127
|
+
pass
|
|
128
|
+
return times, scores
|
|
129
|
+
|
|
130
|
+
speed_times, speed_scores = load_data("#{speed_path}")
|
|
131
|
+
train_times, train_scores = load_data("#{training_path}")
|
|
132
|
+
|
|
133
|
+
plt.figure(figsize=(10,5))
|
|
134
|
+
if speed_times:
|
|
135
|
+
plt.plot(speed_times, speed_scores, 'o-', label='Speed')
|
|
136
|
+
if train_times:
|
|
137
|
+
plt.plot(train_times, train_scores, 's-', label='Training')
|
|
138
|
+
plt.xlabel('Date')
|
|
139
|
+
plt.ylabel('Score')
|
|
140
|
+
plt.title('Typing Progress')
|
|
141
|
+
plt.legend()
|
|
142
|
+
plt.grid(True)
|
|
143
|
+
plt.tight_layout()
|
|
144
|
+
plt.show()
|
|
145
|
+
PYTHON
|
|
146
|
+
end
|
|
52
147
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shunkuntype
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shigeto R. Nishitani
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: systemu
|
|
@@ -122,6 +121,8 @@ files:
|
|
|
122
121
|
- ".hyper_card/docs/shunkun_report.pdf"
|
|
123
122
|
- ".hyper_card/docs/speed.png"
|
|
124
123
|
- ".hyper_card/docs/work.png"
|
|
124
|
+
- ".hyper_card/history/plot_modes.md"
|
|
125
|
+
- ".hyper_card/history/plot_modes_251118.md"
|
|
125
126
|
- ".hyper_card/history/test_cli_bdd.md"
|
|
126
127
|
- ".hyper_card/history/test_cli_bdd_251114.md"
|
|
127
128
|
- ".hyper_card/history/tidy.md"
|
|
@@ -244,13 +245,10 @@ files:
|
|
|
244
245
|
- lib/shunkuntype/training.rb
|
|
245
246
|
- lib/shunkuntype/version.rb
|
|
246
247
|
- shunkuntype.gemspec
|
|
247
|
-
- shunkuntype/speed_data.txt
|
|
248
|
-
- shunkuntype/training_data.txt
|
|
249
248
|
homepage: https://github.com/daddygongon/shunkuntype
|
|
250
249
|
licenses:
|
|
251
250
|
- MIT
|
|
252
251
|
metadata: {}
|
|
253
|
-
post_install_message:
|
|
254
252
|
rdoc_options: []
|
|
255
253
|
require_paths:
|
|
256
254
|
- lib
|
|
@@ -265,8 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
265
263
|
- !ruby/object:Gem::Version
|
|
266
264
|
version: '0'
|
|
267
265
|
requirements: []
|
|
268
|
-
rubygems_version: 3.
|
|
269
|
-
signing_key:
|
|
266
|
+
rubygems_version: 3.6.7
|
|
270
267
|
specification_version: 4
|
|
271
268
|
summary: type training.
|
|
272
269
|
test_files: []
|
data/shunkuntype/speed_data.txt
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
2024-11-06 21:13:42 +0900,20,39.937564,184.7884362701741
|
|
2
|
-
2025-09-09 17:30:33 +0900,20,37.889581,177.35746404796612
|
|
3
|
-
2025-09-09 17:35:35 +0900,20,37.433635,160.28365933471326
|
|
4
|
-
2025-11-14 11:37:14 +0900,20,46.516022,145.75622997168588
|
|
5
|
-
2025-11-14 15:43:37 +0900,20,39.598636,165.1572038996495
|
|
6
|
-
2025-11-14 16:08:21 +0900,20,37.490195,166.4435194322142
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
2021-04-06 14:41:09 +0900,STEP-1.txt,28,60
|
|
2
|
-
2021-04-06 14:42:24 +0900,STEP-2.txt,46,60
|
|
3
|
-
2021-04-06 14:44:15 +0900,STEP-91.txt,28,60
|
|
4
|
-
2021-06-02 17:42:48 +0900,STEP-1.txt,55,60
|
|
5
|
-
2021-07-08 11:59:48 +0900,STEP-3.txt,23,60
|
|
6
|
-
2021-07-08 12:01:20 +0900,STEP-36.txt,16,60
|
|
7
|
-
2021-07-08 12:02:53 +0900,STEP-9.txt,15,60
|
|
8
|
-
2022-03-08 15:16:08 +0900,STEP-1.txt,57,60
|
|
9
|
-
2022-03-08 15:18:41 +0900,STEP-5.txt,38,60
|
|
10
|
-
2022-03-08 15:20:14 +0900,STEP-7.txt,48,60
|
|
11
|
-
2022-03-08 15:22:06 +0900,STEP-4.txt,1,60
|
|
12
|
-
2022-03-08 15:23:58 +0900,STEP-4.txt,44,60
|
|
13
|
-
2022-03-09 13:14:02 +0900,STEP-8.txt,35,60
|
|
14
|
-
2022-04-14 14:40:28 +0900,STEP-3.txt,12,60
|
|
15
|
-
2022-04-14 14:42:18 +0900,STEP-4.txt,40,60
|
|
16
|
-
2022-04-18 14:00:48 +0900,STEP-1.txt,4,60
|
|
17
|
-
2022-04-18 14:04:04 +0900,STEP-46.txt,47,60
|
|
18
|
-
2022-04-20 16:38:30 +0900,STEP-1.txt,50,60
|
|
19
|
-
2022-04-20 16:40:17 +0900,STEP-2.txt,51,60
|
|
20
|
-
2022-06-02 13:09:59 +0900,STEP-2.txt,15,60
|
|
21
|
-
2023-05-25 17:24:23 +0900,STEP-6.txt,50,60
|
|
22
|
-
2023-05-25 17:25:40 +0900,STEP-10.txt,55,60
|
|
23
|
-
2023-05-25 17:26:47 +0900,STEP-11.txt,39,60
|
|
24
|
-
2023-05-25 17:27:59 +0900,STEP-12.txt,44,60
|
|
25
|
-
2023-07-27 11:36:42 +0900,STEP-15.txt,36,60
|
|
26
|
-
2024-04-24 11:36:58 +0900,STEP-1.txt,60,60
|
|
27
|
-
2024-04-24 11:39:15 +0900,STEP-20.txt,48,60
|
|
28
|
-
2024-08-22 11:57:27 +0900,STEP-51.txt,46,60
|
|
29
|
-
2025-02-05 12:22:37 +0900,STEP-15.txt,42,60
|
|
30
|
-
2025-11-14 11:35:56 +0900,STEP-16.txt,44,60
|
|
31
|
-
2025-11-14 15:28:03 +0900,STEP-1.txt,0,60
|
|
32
|
-
2025-11-14 15:31:52 +0900,STEP-1.txt,0,60
|
|
33
|
-
2025-11-14 15:32:49 +0900,STEP-1.txt,0,60
|
|
34
|
-
2025-11-14 15:39:20 +0900,STEP-1.txt,0,60
|
|
35
|
-
2025-11-14 15:40:03 +0900,STEP-1.txt,0,60
|
|
36
|
-
2025-11-14 15:53:27 +0900,STEP-1.txt,0,60
|