cw 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cw_config +9 -18
- data/.gitignore +1 -0
- data/README.md +10 -4
- data/VERSION +1 -1
- data/calculator.rb +63 -0
- data/chart.rb +33 -0
- data/chart2.rb +35 -0
- data/chart3.rb +47 -0
- data/chart4.rb +45 -0
- data/cw.gemspec +5 -3
- data/data/callsign/callsign.yaml +78 -0
- data/data/code/code.yaml +215 -0
- data/example.rb +18 -0
- data/lib/cw.rb +3 -0
- data/lib/cw/alphabet.rb +21 -6
- data/lib/cw/audio_player.rb +5 -8
- data/lib/cw/book.rb +0 -4
- data/lib/cw/book_details.rb +19 -8
- data/lib/cw/callsign.rb +59 -0
- data/lib/cw/cl.rb +12 -11
- data/lib/cw/common_words.rb +26 -3
- data/lib/cw/config.rb +14 -3
- data/lib/cw/cw_dsl.rb +11 -0
- data/lib/cw/cw_encoding.rb +49 -53
- data/lib/cw/file_details.rb +92 -19
- data/lib/cw/print.rb +10 -0
- data/lib/cw/read.rb +341 -0
- data/lib/cw/tone_generator.rb +6 -11
- data/lib/cw/words.rb +1 -1
- data/run_script_tests.rb +1 -1
- data/test/test_config.rb +0 -20
- data/test/test_cw.rb +14 -14
- metadata +20 -11
data/example.rb
CHANGED
@@ -198,6 +198,24 @@ cw do
|
|
198
198
|
word_count 4
|
199
199
|
end
|
200
200
|
|
201
|
+
cw do
|
202
|
+
comment "test 5 callsigns"
|
203
|
+
wpm 20
|
204
|
+
callsign * 5
|
205
|
+
end
|
206
|
+
|
207
|
+
puts "cq de callsign k 5 times"
|
208
|
+
5.times do
|
209
|
+
cw do
|
210
|
+
comment 'random frequency, random wpm callsign with pre and postamble'
|
211
|
+
frequency 500 + rand(400)
|
212
|
+
wpm 25 + rand(10)
|
213
|
+
callsign
|
214
|
+
(words.unshift "cqde") << 'k'
|
215
|
+
print_letters
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
201
219
|
# See documentation for more details - and more commands.
|
202
220
|
|
203
221
|
puts 'done'
|
data/lib/cw.rb
CHANGED
data/lib/cw/alphabet.rb
CHANGED
@@ -19,19 +19,29 @@ module CWG
|
|
19
19
|
@options = options
|
20
20
|
end
|
21
21
|
|
22
|
-
#
|
22
|
+
# alphabet()
|
23
|
+
# Returns alphabet as string
|
24
|
+
# == Parameters:
|
25
|
+
# none
|
23
26
|
|
24
27
|
def alphabet
|
25
28
|
'abcdefghijklmnopqrstuvwxyz'
|
26
29
|
end
|
27
30
|
|
28
|
-
#
|
31
|
+
# reverse_alphabet_maybe()
|
32
|
+
# reverse letters if reverse option set
|
33
|
+
# == Parameters:
|
34
|
+
# none
|
29
35
|
|
30
36
|
def reverse_alphabet_maybe
|
31
37
|
@letters.reverse! if @options[:reverse]
|
32
38
|
end
|
33
39
|
|
40
|
+
# shuffle_alphabet_maybe()
|
34
41
|
# shuffle alphabet if :shuffle option defined
|
42
|
+
# don't shuffle if in test environment
|
43
|
+
# == Parameters:
|
44
|
+
# none
|
35
45
|
|
36
46
|
def shuffle_alphabet_maybe
|
37
47
|
unless(ENV["CW_ENV"] == "test")
|
@@ -39,7 +49,10 @@ module CWG
|
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
42
|
-
#
|
52
|
+
# include_letters()
|
53
|
+
# include letters if :include option defined
|
54
|
+
# == Parameters:
|
55
|
+
# none
|
43
56
|
|
44
57
|
def include_letters
|
45
58
|
if @options[:include]
|
@@ -47,7 +60,10 @@ module CWG
|
|
47
60
|
end
|
48
61
|
end
|
49
62
|
|
50
|
-
#
|
63
|
+
# exclude_letters()
|
64
|
+
# exclude letters if :exclude option defined
|
65
|
+
# == Parameters:
|
66
|
+
# none
|
51
67
|
|
52
68
|
def exclude_letters
|
53
69
|
if @options[:exclude]
|
@@ -55,6 +71,7 @@ module CWG
|
|
55
71
|
end
|
56
72
|
end
|
57
73
|
|
74
|
+
# generate()
|
58
75
|
# generate alphabet with options acted upon
|
59
76
|
# == Returns:
|
60
77
|
# alphabet or filtered alphabet
|
@@ -67,7 +84,5 @@ module CWG
|
|
67
84
|
reverse_alphabet_maybe
|
68
85
|
@letters.split('').join(' ')
|
69
86
|
end
|
70
|
-
|
71
87
|
end
|
72
|
-
|
73
88
|
end
|
data/lib/cw/audio_player.rb
CHANGED
@@ -7,6 +7,7 @@ module CWG
|
|
7
7
|
|
8
8
|
class AudioPlayer
|
9
9
|
|
10
|
+
include FileDetails
|
10
11
|
include CWG::OStest
|
11
12
|
|
12
13
|
def tone
|
@@ -33,11 +34,9 @@ module CWG
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def play_filename_for_ebook2cw
|
36
|
-
@play_filename ||= File.
|
37
|
-
|
38
|
-
|
39
|
-
def audio_dir
|
40
|
-
Cfg.config["audio_dir"]
|
37
|
+
@play_filename ||= File.join(audio_dir, audio_filename)
|
38
|
+
puts "@play_filename = #{@play_filename}"
|
39
|
+
@play_filename
|
41
40
|
end
|
42
41
|
|
43
42
|
def temp_filename_for_ebook2cw
|
@@ -55,7 +54,6 @@ module CWG
|
|
55
54
|
File.rename(play_filename_for_ebook2cw + '0000.mp3', play_filename_for_ebook2cw)
|
56
55
|
end
|
57
56
|
|
58
|
-
#FIXME dry_run
|
59
57
|
def convert_words_with_ebook2cw words
|
60
58
|
words = words.delete("\n")
|
61
59
|
cl = Cl.new.cl_echo(words)
|
@@ -64,7 +62,7 @@ module CWG
|
|
64
62
|
end
|
65
63
|
|
66
64
|
def convert_words words
|
67
|
-
tone.generate words
|
65
|
+
tone.generate words if Cfg.config["use_ebook2cw"].nil?
|
68
66
|
convert_words_with_ebook2cw words if Cfg.config["use_ebook2cw"]
|
69
67
|
end
|
70
68
|
|
@@ -73,7 +71,6 @@ module CWG
|
|
73
71
|
tone.play_filename
|
74
72
|
end
|
75
73
|
|
76
|
-
#FIXME dry_run
|
77
74
|
def play
|
78
75
|
cmd = play_command + ' ' + play_filename
|
79
76
|
@pid = ! @dry_run ? Process.spawn(cmd) : cmd
|
data/lib/cw/book.rb
CHANGED
data/lib/cw/book_details.rb
CHANGED
@@ -8,21 +8,32 @@ module CWG
|
|
8
8
|
|
9
9
|
include FileDetails
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
11
|
+
BOOK_NAME = "book.txt"
|
12
|
+
BOOK_DIR = TEXT
|
13
|
+
USER_BOOK_DEFAULT_DIR = "books"
|
15
14
|
|
16
15
|
def book_name
|
17
|
-
|
16
|
+
@book_name ||=
|
17
|
+
Cfg.config["book_name"] ?
|
18
|
+
Cfg.config["book_name"] :
|
19
|
+
BOOK_NAME
|
20
|
+
end
|
21
|
+
|
22
|
+
def is_user_book_default_dir?
|
23
|
+
File.exists? USER_BOOK_DEFAULT_DIR
|
18
24
|
end
|
19
25
|
|
20
|
-
def
|
21
|
-
|
26
|
+
def book_dir
|
27
|
+
@book_dir ||=
|
28
|
+
Cfg.config["book_dir"] ?
|
29
|
+
File.join(WORK_DIR, Cfg.config["book_dir"]) :
|
30
|
+
is_user_book_default_dir? ?
|
31
|
+
USER_BOOK_DEFAULT_DIR :
|
32
|
+
BOOK_DIR
|
22
33
|
end
|
23
34
|
|
24
35
|
def book_location
|
25
|
-
File.expand_path(book_name,
|
36
|
+
File.expand_path(book_name, book_dir)
|
26
37
|
end
|
27
38
|
|
28
39
|
def arguments args
|
data/lib/cw/callsign.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module CWG
|
2
|
+
|
3
|
+
class Callsign
|
4
|
+
|
5
|
+
include FileDetails
|
6
|
+
|
7
|
+
def callsigns
|
8
|
+
if @callsigns.nil?
|
9
|
+
@callsigns = load_callsigns
|
10
|
+
end
|
11
|
+
@callsigns
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_callsigns
|
15
|
+
File.open(CALLS_FILENAME, "r") do |calls|
|
16
|
+
YAML::load(calls)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def rand_val
|
22
|
+
rand(100)
|
23
|
+
end
|
24
|
+
|
25
|
+
def select_part country = :uk, partial
|
26
|
+
pc = rand_val
|
27
|
+
weight = callsigns[country][partial][:weight]
|
28
|
+
tot_wt = 0
|
29
|
+
weight.each_with_index do |wt, idx|
|
30
|
+
tot_wt += wt
|
31
|
+
if pc < tot_wt
|
32
|
+
part = callsigns[country][partial][:option][idx]
|
33
|
+
return part unless(part.class == Range)
|
34
|
+
return part.to_a.sample
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def partial_name count
|
40
|
+
"partial_#{count}".to_sym
|
41
|
+
end
|
42
|
+
|
43
|
+
def construct
|
44
|
+
call = ''
|
45
|
+
0.upto(4) do |count|
|
46
|
+
call << select_part(partial_name(count))
|
47
|
+
end
|
48
|
+
call.strip
|
49
|
+
end
|
50
|
+
|
51
|
+
def * number
|
52
|
+
calls = []
|
53
|
+
number.times do
|
54
|
+
calls << construct
|
55
|
+
end
|
56
|
+
calls
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/cw/cl.rb
CHANGED
@@ -6,6 +6,8 @@ module CWG
|
|
6
6
|
|
7
7
|
class Cl
|
8
8
|
|
9
|
+
include FileDetails
|
10
|
+
|
9
11
|
def initialize
|
10
12
|
@tone = {
|
11
13
|
sinewave: 0,
|
@@ -34,22 +36,21 @@ module CWG
|
|
34
36
|
freq ? "-f #{freq} " : ''
|
35
37
|
end
|
36
38
|
|
39
|
+
def wave type
|
40
|
+
return '' unless(Cfg.config["tone"].to_s == type)
|
41
|
+
"-T #{@tone[type.to_sym]} "
|
42
|
+
end
|
43
|
+
|
37
44
|
def cl_squarewave
|
38
|
-
|
39
|
-
return '' unless Cfg.config["tone"].to_s == "squarewave"
|
40
|
-
"-T #{@tone[:squarewave]} "
|
45
|
+
wave 'squarewave'
|
41
46
|
end
|
42
47
|
|
43
48
|
def cl_sawtooth
|
44
|
-
|
45
|
-
return '' unless Cfg.config["tone"].to_s == "sawtooth"
|
46
|
-
"-T #{@tone[:sawtooth]} "
|
49
|
+
wave "sawtooth"
|
47
50
|
end
|
48
51
|
|
49
52
|
def cl_sinewave
|
50
|
-
|
51
|
-
return '' unless Cfg.config["tone"].to_s == "sinewave"
|
52
|
-
"-T #{@tone[:sinewave]} "
|
53
|
+
wave "sinewave"
|
53
54
|
end
|
54
55
|
|
55
56
|
def cl_author
|
@@ -64,11 +65,11 @@ module CWG
|
|
64
65
|
|
65
66
|
def cl_noise
|
66
67
|
Cfg.config["noise"] ?
|
67
|
-
"-N
|
68
|
+
"-N 10 -B 800 " : ''
|
68
69
|
end
|
69
70
|
|
70
71
|
def cl_audio_filename
|
71
|
-
"-o \"#{File.
|
72
|
+
"-o \"#{File.join(audio_dir, audio_filename)}\" "
|
72
73
|
end
|
73
74
|
|
74
75
|
def coarse_quality(quality)
|
data/lib/cw/common_words.rb
CHANGED
@@ -8,8 +8,31 @@ module CWG
|
|
8
8
|
@words = []
|
9
9
|
end
|
10
10
|
|
11
|
+
def custom_dict_dir
|
12
|
+
File.join(WORK_DIR, Cfg.config["dictionary_dir"])
|
13
|
+
end
|
14
|
+
|
15
|
+
def dictionary_dir
|
16
|
+
@dictionary_dir ||=
|
17
|
+
Cfg.config["dictionary_dir"] ?
|
18
|
+
custom_dict_dir :
|
19
|
+
DICT_DIR
|
20
|
+
end
|
21
|
+
|
22
|
+
def dict_filename
|
23
|
+
@dict_filename ||=
|
24
|
+
Cfg.config["dictionary_name"] ?
|
25
|
+
Cfg.config["dictionary_name"] :
|
26
|
+
DICT_FILENAME
|
27
|
+
end
|
28
|
+
|
29
|
+
def dictionary
|
30
|
+
@dictionary ||=
|
31
|
+
File.join(dictionary_dir, dict_filename)
|
32
|
+
end
|
33
|
+
|
11
34
|
def all
|
12
|
-
File.foreach(
|
35
|
+
File.foreach(dictionary).collect do |line|
|
13
36
|
line.chomp
|
14
37
|
end
|
15
38
|
end
|
@@ -17,7 +40,7 @@ module CWG
|
|
17
40
|
def low last
|
18
41
|
results = []
|
19
42
|
count = 0
|
20
|
-
File.foreach(
|
43
|
+
File.foreach(dictionary).collect do |line|
|
21
44
|
if count <= last
|
22
45
|
results << line.chomp
|
23
46
|
end
|
@@ -30,7 +53,7 @@ module CWG
|
|
30
53
|
def mid first, last
|
31
54
|
results = []
|
32
55
|
count = 0
|
33
|
-
File.foreach(
|
56
|
+
File.foreach(dictionary).collect do |line|
|
34
57
|
if (count >= first) && (count <= last)
|
35
58
|
results << line.chomp
|
36
59
|
end
|
data/lib/cw/config.rb
CHANGED
@@ -18,18 +18,29 @@ module CWG
|
|
18
18
|
|
19
19
|
def self.config
|
20
20
|
unless @config
|
21
|
-
@config = ParseConfig.new(
|
21
|
+
@config = ParseConfig.new(CONFIG_PATH)
|
22
22
|
CONFIG_METHODS.each do |method|
|
23
23
|
unless @config[method.to_s]
|
24
24
|
@config.add method.to_s, nil
|
25
25
|
end
|
26
26
|
end
|
27
|
+
self.user_config
|
28
|
+
@config.params["wpm"] = 50 if(ENV["CW_ENV"] == "test")
|
29
|
+
@config.params["effective_wpm"] = 50 if(ENV["CW_ENV"] == "test")
|
30
|
+
# puts " @config[wpm] = #{@config['wpm']}"
|
27
31
|
end
|
28
|
-
@config
|
29
|
-
@config.params["effective_wpm"] = 50 if(ENV["CW_ENV"] == "test")
|
32
|
+
# puts "@config = #{@config.params}"
|
30
33
|
@config
|
31
34
|
end
|
32
35
|
|
36
|
+
def self.user_config
|
37
|
+
user_cfg = File.join(WORK_DIR, CONFIG_FILENAME)
|
38
|
+
if File.exist? user_cfg
|
39
|
+
temp = ParseConfig.new(user_cfg);
|
40
|
+
@config.params = @config.params.merge(temp.params)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
33
44
|
def self.reset
|
34
45
|
@config = nil
|
35
46
|
end
|
data/lib/cw/cw_dsl.rb
CHANGED
@@ -148,6 +148,7 @@ module CWG
|
|
148
148
|
def word_count(wordcount)
|
149
149
|
Cfg.config.params["word_count"] = wordcount
|
150
150
|
@words.count wordcount
|
151
|
+
Cfg.config.params["words_counted"] = true
|
151
152
|
end
|
152
153
|
|
153
154
|
def beginning_with(* letters)
|
@@ -247,6 +248,7 @@ module CWG
|
|
247
248
|
|
248
249
|
def run
|
249
250
|
return if Cfg.config["no_run"]
|
251
|
+
word_count(Cfg.config["word_count"])unless Cfg.config.params["words_counted"]
|
250
252
|
self.send run_default
|
251
253
|
end
|
252
254
|
|
@@ -270,6 +272,15 @@ module CWG
|
|
270
272
|
Cfg.config.params["use_ebook2cw"] = nil
|
271
273
|
end
|
272
274
|
|
275
|
+
def callsign count = 1
|
276
|
+
callsign = Callsign.new
|
277
|
+
@words.assign callsign.* count
|
278
|
+
end
|
279
|
+
|
280
|
+
def read filename = :default
|
281
|
+
Read.new(filename)
|
282
|
+
end
|
283
|
+
|
273
284
|
def words ; @words.all ; end
|
274
285
|
def load_common_words ; @words.load 1000 ; end
|
275
286
|
def load_most_common_words ; @words.load 500 ; end
|
data/lib/cw/cw_encoding.rb
CHANGED
@@ -4,71 +4,67 @@ module CWG
|
|
4
4
|
|
5
5
|
class CwEncoding
|
6
6
|
|
7
|
-
|
8
|
-
'a' => [:dot, :dash],
|
9
|
-
'b' => [:dash, :dot, :dot, :dot],
|
10
|
-
'c' => [:dash, :dot, :dash, :dot],
|
11
|
-
'd' => [:dash, :dot, :dot],
|
12
|
-
'e' => [:dot],
|
13
|
-
'f' => [:dot, :dot, :dash, :dot],
|
14
|
-
'g' => [:dash, :dash, :dot],
|
15
|
-
'h' => [:dot, :dot, :dot, :dot],
|
16
|
-
'i' => [:dot, :dot],
|
17
|
-
'j' => [:dot, :dash, :dash, :dash],
|
18
|
-
'k' => [:dash, :dot, :dash],
|
19
|
-
'l' => [:dot, :dash, :dot, :dot],
|
20
|
-
'm' => [:dash, :dash],
|
21
|
-
'n' => [:dash, :dot],
|
22
|
-
'o' => [:dash, :dash, :dash],
|
23
|
-
'p' => [:dot, :dash, :dash, :dot],
|
24
|
-
'q' => [:dash, :dash, :dot, :dash],
|
25
|
-
'r' => [:dot, :dash, :dot],
|
26
|
-
's' => [:dot, :dot, :dot],
|
27
|
-
't' => [:dash],
|
28
|
-
'u' => [:dot, :dot, :dash],
|
29
|
-
'v' => [:dot, :dot, :dot, :dash],
|
30
|
-
'w' => [:dot, :dash, :dash],
|
31
|
-
'x' => [:dash, :dot, :dot, :dash],
|
32
|
-
'y' => [:dash, :dot, :dash, :dash],
|
33
|
-
'z' => [:dash, :dash, :dot, :dot],
|
34
|
-
'1' => [:dot, :dash, :dash, :dash, :dash],
|
35
|
-
'2' => [:dot, :dot, :dash, :dash, :dash],
|
36
|
-
'3' => [:dot, :dot, :dot, :dash, :dash],
|
37
|
-
'4' => [:dot, :dot, :dot, :dot, :dash],
|
38
|
-
'5' => [:dot, :dot, :dot, :dot, :dot],
|
39
|
-
'6' => [:dash, :dot, :dot, :dot, :dot],
|
40
|
-
'7' => [:dash, :dash, :dot, :dot, :dot],
|
41
|
-
'8' => [:dash, :dash, :dash, :dot, :dot],
|
42
|
-
'9' => [:dash, :dash, :dash, :dash, :dot],
|
43
|
-
'0' => [:dash, :dash, :dash, :dash, :dash],
|
44
|
-
'.' => [:dot, :dash, :dot, :dash, :dot, :dash],
|
45
|
-
',' => [:dash, :dash, :dot, :dot, :dash, :dash],
|
46
|
-
'=' => [:dash, :dot, :dot,:dot, :dash],
|
47
|
-
'!' => [:dot, :dot, :dash, :dash, :dot],
|
48
|
-
'/' => [:dash, :dot, :dot, :dash, :dot],
|
49
|
-
'?' => [:dot, :dot, :dash, :dash, :dot, :dot],
|
50
|
-
' ' => []
|
51
|
-
}
|
7
|
+
include FileDetails
|
52
8
|
|
53
|
-
def
|
54
|
-
|
9
|
+
def initialize
|
10
|
+
@char_lookup = "*eish54v*3uf***!2arl***+*wp**j*1tndb6=x/*kc**y**mgz7*q**o*8**90*".split('').map(&:to_sym)
|
55
11
|
end
|
56
12
|
|
57
13
|
def encodings
|
58
|
-
|
14
|
+
if @encodings.nil?
|
15
|
+
@encodings = load_code
|
16
|
+
end
|
17
|
+
@encodings
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_code
|
21
|
+
File.open(CODE_FILENAME, "r") do |code|
|
22
|
+
YAML::load(code)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch char
|
27
|
+
encodings[char]
|
59
28
|
end
|
60
29
|
|
61
30
|
def match_elements arg
|
62
31
|
chars = []
|
63
|
-
|
64
|
-
chars << key unless value.include?(:dot)
|
32
|
+
encodings.each_pair do |key, value|
|
33
|
+
chars << key unless value.include?(:dot) if arg[0] == :dashes
|
65
34
|
chars << key unless value.include?(:dash) if arg[0] == :dots
|
66
|
-
chars << key if (value.size < arg[1] )if arg[0]
|
67
|
-
chars << key if (value.size > arg[1] )if arg[0]
|
68
|
-
chars << key if (value.size == arg[1] )if arg[0]
|
35
|
+
chars << key if ( value.size < arg[1] ) if arg[0] == :less_than
|
36
|
+
chars << key if ( value.size > arg[1] ) if arg[0] == :greater_than
|
37
|
+
chars << key if ( value.size == arg[1] ) if arg[0] == :size
|
69
38
|
chars.delete(' ')
|
70
39
|
end
|
71
40
|
chars
|
72
41
|
end
|
42
|
+
|
43
|
+
def fast_match code
|
44
|
+
index = 0
|
45
|
+
dash_jump = 64
|
46
|
+
code.each do |ele|
|
47
|
+
# puts "ele: #{ele}"
|
48
|
+
dash_jump = dash_jump / 2
|
49
|
+
index = index + ((ele == :dot) ? 1 : dash_jump)
|
50
|
+
end
|
51
|
+
return @char_lookup[index].to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def fetch_char code
|
55
|
+
length = code.length
|
56
|
+
case length
|
57
|
+
when 1..5
|
58
|
+
return ' ' if code == [:space]
|
59
|
+
# return fast_match code
|
60
|
+
return encodings.key(code)
|
61
|
+
when 0
|
62
|
+
return '*'
|
63
|
+
else
|
64
|
+
temp = encodings.key(code)
|
65
|
+
return temp if temp
|
66
|
+
return '*' unless temp
|
67
|
+
end
|
68
|
+
end
|
73
69
|
end
|
74
70
|
end
|