cw 0.2.4 → 0.3.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.cw_config +18 -0
  3. data/.gitignore +10 -1
  4. data/LICENSE +2 -1
  5. data/README.md +212 -96
  6. data/Rakefile +15 -2
  7. data/VERSION +1 -1
  8. data/Vagrantfile +45 -0
  9. data/cw.gemspec +6 -1
  10. data/data/text/book_to_read.txt +4 -0
  11. data/data/text/english.txt +10000 -0
  12. data/example.rb +172 -106
  13. data/lib/cw.rb +10 -126
  14. data/lib/cw/alphabet.rb +53 -46
  15. data/lib/cw/audio_player.rb +83 -72
  16. data/lib/cw/book.rb +160 -185
  17. data/lib/cw/book_details.rb +38 -49
  18. data/lib/cw/cl.rb +101 -95
  19. data/lib/cw/common_words.rb +76 -0
  20. data/lib/cw/config.rb +50 -0
  21. data/lib/cw/current_word.rb +23 -24
  22. data/lib/cw/cw_dsl.rb +264 -131
  23. data/lib/cw/cw_encoding.rb +63 -69
  24. data/lib/cw/cw_stream.rb +86 -82
  25. data/lib/cw/cw_threads.rb +132 -22
  26. data/lib/cw/element.rb +60 -54
  27. data/lib/cw/file_details.rb +26 -11
  28. data/lib/cw/key_input.rb +53 -35
  29. data/lib/cw/numbers.rb +26 -19
  30. data/lib/cw/os.rb +13 -0
  31. data/lib/cw/play.rb +92 -0
  32. data/lib/cw/print.rb +102 -100
  33. data/lib/cw/process.rb +3 -0
  34. data/lib/cw/progress.rb +20 -17
  35. data/lib/cw/randomize.rb +56 -52
  36. data/lib/cw/repeat_word.rb +59 -66
  37. data/lib/cw/reveal.rb +32 -31
  38. data/lib/cw/rss.rb +52 -48
  39. data/lib/cw/sentence.rb +83 -76
  40. data/lib/cw/speak.rb +8 -4
  41. data/lib/cw/spoken.rb +8 -4
  42. data/lib/cw/str.rb +62 -30
  43. data/lib/cw/test_letters.rb +20 -28
  44. data/lib/cw/test_words.rb +25 -31
  45. data/lib/cw/tester.rb +219 -226
  46. data/lib/cw/text_helpers.rb +19 -15
  47. data/lib/cw/timing.rb +63 -67
  48. data/lib/cw/tone_generator.rb +176 -153
  49. data/lib/cw/tone_helpers.rb +15 -23
  50. data/lib/cw/voice.rb +12 -8
  51. data/lib/cw/words.rb +136 -106
  52. data/run_script_tests.rb +165 -0
  53. data/test/my_words.txt +1 -0
  54. data/test/test_common_words.rb +71 -0
  55. data/test/test_config.rb +98 -0
  56. data/test/test_current_word.rb +62 -0
  57. data/test/test_cw.rb +87 -120
  58. data/test/test_cw_threads.rb +123 -0
  59. data/test/test_filtering.rb +439 -0
  60. data/test/test_params.rb +28 -0
  61. data/test/test_play.rb +51 -0
  62. data/test/test_stream.rb +83 -83
  63. data/test/test_tester.rb +9 -27
  64. data/test/test_timing.rb +212 -0
  65. metadata +94 -12
  66. data/lib/cw/config_file.rb +0 -69
  67. data/lib/cw/monitor_keys.rb +0 -37
  68. data/lib/cw/params.rb +0 -104
@@ -1,80 +1,74 @@
1
- # encoding: utf-8
1
+ # encoding: utf-8
2
+
3
+ module CWG
2
4
 
3
5
  class CwEncoding
4
6
 
7
+ ENCODINGS = {
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
+ }
52
+
5
53
  def fetch char
6
- encode(char)
54
+ ENCODINGS[char]
7
55
  end
8
56
 
9
57
  def encodings
10
- @encodings ||= construct_encodings
11
- end
12
-
13
- def construct_encodings
14
- @encodings = encode_a_n().merge(encode_0_2);
15
- @encodings.merge!(encode_3_space)
16
- end
17
-
18
- def encode char
19
- encodings[char]
58
+ ENCODINGS
20
59
  end
21
60
 
22
- def encode_a_n
23
- {
24
- 'a' => [:dot, :dash],
25
- 'b' => [:dash, :dot, :dot, :dot],
26
- 'c' => [:dash, :dot, :dash, :dot],
27
- 'd' => [:dash, :dot, :dot],
28
- 'e' => [:dot],
29
- 'f' => [:dot, :dot, :dash, :dot],
30
- 'g' => [:dash, :dash, :dot],
31
- 'h' => [:dot, :dot, :dot, :dot],
32
- 'i' => [:dot, :dot],
33
- 'j' => [:dot, :dash, :dash, :dash],
34
- 'k' => [:dash, :dot, :dash],
35
- 'l' => [:dot, :dash, :dot, :dot],
36
- 'm' => [:dash, :dash],
37
- 'n' => [:dash, :dot]
38
- }
61
+ def match_elements arg
62
+ chars = []
63
+ ENCODINGS.each_pair do |key, value|
64
+ chars << key unless value.include?(:dot) if arg[0] == :dashes
65
+ chars << key unless value.include?(:dash) if arg[0] == :dots
66
+ chars << key if (value.size < arg[1] )if arg[0] == :less_than
67
+ chars << key if (value.size > arg[1] )if arg[0] == :greater_than
68
+ chars << key if (value.size == arg[1] )if arg[0] == :size
69
+ chars.delete(' ')
70
+ end
71
+ chars
39
72
  end
40
-
41
- def encode_0_2
42
- {
43
- 'o' => [:dash, :dash, :dash],
44
- 'p' => [:dot, :dash, :dash, :dot],
45
- 'q' => [:dash, :dash, :dot, :dash],
46
- 'r' => [:dot, :dash, :dot],
47
- 's' => [:dot, :dot, :dot],
48
- 't' => [:dash],
49
- 'u' => [:dot, :dot, :dash],
50
- 'v' => [:dot, :dot, :dot, :dash],
51
- 'w' => [:dot, :dash, :dash],
52
- 'x' => [:dash, :dot, :dot, :dash],
53
- 'y' => [:dash, :dot, :dash, :dash],
54
- 'z' => [:dash, :dash, :dot, :dot],
55
- '1' => [:dot, :dash, :dash, :dash, :dash],
56
- '2' => [:dot, :dot, :dash, :dash, :dash]
57
- }
58
- end
59
-
60
- def encode_3_space
61
- {
62
- '3' => [:dot, :dot, :dot, :dash, :dash],
63
- '4' => [:dot, :dot, :dot, :dot, :dash],
64
- '5' => [:dot, :dot, :dot, :dot, :dot],
65
- '6' => [:dash, :dot, :dot, :dot, :dot],
66
- '7' => [:dash, :dash, :dot, :dot, :dot],
67
- '8' => [:dash, :dash, :dash, :dot, :dot],
68
- '9' => [:dash, :dash, :dash, :dash, :dot],
69
- '0' => [:dash, :dash, :dash, :dash, :dash],
70
- '.' => [:dot, :dash, :dot, :dash, :dot, :dash],
71
- ',' => [:dash, :dash, :dot, :dot, :dash, :dash],
72
- '=' => [:dash, :dot, :dot,:dot, :dash],
73
- '!' => [:dot, :dot, :dash, :dash, :dot],
74
- '/' => [:dash, :dot, :dot, :dash, :dot],
75
- '?' => [:dot, :dot, :dash, :dash, :dot, :dot],
76
- ' ' => []
77
- }
78
- end
79
-
80
73
  end
74
+ end
@@ -1,107 +1,111 @@
1
1
  # encoding: utf-8
2
2
 
3
- class CwStream
3
+ module CWG
4
4
 
5
- include Element
5
+ class CwStream
6
6
 
7
- attr_accessor :active_region
8
- attr_accessor :stream
7
+ include Element
9
8
 
10
- def initialize
11
- @active_region = 6
12
- empty
13
- end
9
+ attr_accessor :active_region
10
+ attr_accessor :stream
14
11
 
15
- def empty
16
- @stream, @success, @first_element, @last_element = {},{}, 0, 0
17
- end
12
+ def initialize
13
+ @active_region = 6
14
+ empty
15
+ end
18
16
 
19
- def add_word word
20
- @stream[@last_element] = word.strip
21
- @success[@last_element] = nil
22
- inc_last_element
23
- end
17
+ def empty
18
+ @stream, @success, @first_element, @last_element = {},{}, 0, 0
19
+ end
24
20
 
25
- def add_char char
26
- @stream[@last_element] = char
27
- @success[@last_element] = nil
28
- inc_last_element
29
- end
21
+ def push word
22
+ @stream[@last_element] = word.strip
23
+ @success[@last_element] = nil
24
+ inc_last_element
25
+ end
30
26
 
31
- def mark(element, type)
32
- @success[element] = type
33
- end
27
+ def add_char char
28
+ @stream[@last_element] = char
29
+ @success[@last_element] = nil
30
+ inc_last_element
31
+ end
34
32
 
35
- def mark_success element
36
- mark element, true
37
- end
33
+ def mark(element, type)
34
+ @success[element] = type
35
+ end
38
36
 
39
- def mark_fail element
40
- mark element, false
41
- end
37
+ def mark_success element
38
+ mark element, true
39
+ end
42
40
 
43
- def stream_empty?
44
- @first_element == @last_element
45
- end
41
+ def mark_fail element
42
+ mark element, false
43
+ end
46
44
 
47
- def inactive_region
48
- stream_empty? ? nil : @last_element - @active_region - 1
49
- end
45
+ def stream_empty?
46
+ @first_element == @last_element
47
+ end
48
+
49
+ def inactive_region
50
+ stream_empty? ? nil : @last_element - @active_region - 1
51
+ end
50
52
 
51
- def fail_unmarked_inactive_elements
52
- if(( ! stream_empty?) && (count > @active_region))
53
- @first_element.upto(inactive_region) do |count|
54
- @success[count] = false unless @success[count] == true
53
+ def fail_unmarked_inactive_elements
54
+ if(( ! stream_empty?) && (count > @active_region))
55
+ @first_element.upto(inactive_region) do |count|
56
+ @success[count] = false unless @success[count] == true
57
+ end
55
58
  end
56
59
  end
57
- end
58
60
 
59
- def first
60
- @stream[@first_element]
61
- end
61
+ def first
62
+ @stream[@first_element]
63
+ end
62
64
 
63
- def pop
64
- unless stream_empty?
65
- ele = @first_element
66
- inc_first_element
67
- success = @success.delete(ele)
68
- success = success == nil ? false : success
69
- { :value => @stream.delete(ele),
70
- :success => success
71
- }
72
- else
73
- nil
65
+ def pop
66
+ unless stream_empty?
67
+ ele = @first_element
68
+ inc_first_element
69
+ success = @success.delete(ele)
70
+ success = success == nil ? false : success
71
+ { :value => @stream.delete(ele),
72
+ :success => success
73
+ }
74
+ else
75
+ nil
76
+ end
74
77
  end
75
- end
76
78
 
77
- # def pop_marked
78
- # return_val = {}
79
- # fail_unmarked_inactive_elements
80
- # @first_element.upto(@last_element) do |ele|
81
- # unless stream_empty?
82
- # if(ele < inactive_region)
83
- # val = pop
84
- #
85
- # return_val[ele] = {pop => @success[ele]}
86
- # elsif(@success[ele] == true || @success[ele] == false)
87
- # return_val[ele] = {pop => @success[ele]}
88
- # else
89
- # break
90
- # end
91
- # end
92
- # end
93
- # return_val == {} ? nil : return_val
94
- # end
95
-
96
- def pop_next_marked
97
- fail_unmarked_inactive_elements
98
- unless stream_empty?
99
- if(@first_element < inactive_region)
100
- pop
101
- elsif(@success[@first_element] == true || @success[@first_element] == false)
102
- pop
79
+ # def pop_marked
80
+ # return_val = {}
81
+ # fail_unmarked_inactive_elements
82
+ # @first_element.upto(@last_element) do |ele|
83
+ # unless stream_empty?
84
+ # if(ele < inactive_region)
85
+ # val = pop
86
+ #
87
+ # return_val[ele] = {pop => @success[ele]}
88
+ # elsif(@success[ele] == true || @success[ele] == false)
89
+ # return_val[ele] = {pop => @success[ele]}
90
+ # else
91
+ # break
92
+ # end
93
+ # end
94
+ # end
95
+ # return_val == {} ? nil : return_val
96
+ # end
97
+
98
+ def pop_next_marked
99
+ fail_unmarked_inactive_elements
100
+ unless stream_empty?
101
+ if(@first_element < inactive_region)
102
+ pop
103
+ elsif(@success[@first_element] == true || @success[@first_element] == false)
104
+ pop
105
+ end
103
106
  end
104
107
  end
108
+
105
109
  end
106
110
 
107
111
  end
@@ -1,36 +1,146 @@
1
1
  # encoding: utf-8
2
2
 
3
- class CWThreads
3
+ module CWG
4
4
 
5
- attr_accessor :threads
5
+ class CWThreads
6
6
 
7
- def initialize context, processes
8
- @context = context
9
- @processes = processes
10
- end
7
+ attr_reader :threads
8
+
9
+ def initialize context, processes
10
+ @context = context
11
+ @processes = processes
12
+ end
11
13
 
12
- def kill
13
- sleep 0.2
14
- if @threads.is_a?(Array)
15
- @threads.each do |th|
16
- th.exit if th.is_a? Thread
14
+ def start_threads
15
+ @threads = @processes.collect do |th|
16
+ {:thread =>
17
+ Thread.new do
18
+ @context.send th
19
+ end,
20
+ :name => th
21
+ }
17
22
  end
18
23
  end
19
- end
20
24
 
21
- def start_threads
22
- @threads = @processes.collect do |th|
23
- Thread.new{@context.send th}
25
+ def monitor_threads
26
+ exiting = false
27
+ loop do
28
+ sleep 0.5
29
+ @threads.each do |th|
30
+ if thread_false_or_nil?(th)
31
+ exiting = true
32
+ unless Cfg.config["exit"]
33
+ # puts "** #{th[:name].to_s.gsub('_',' ')} quit unexpectedly!**"
34
+ if th[:thread].backtrace
35
+ STDERR.puts th[:thread].backtrace.join("\n \\_ ")
36
+ end
37
+ end
38
+ end
39
+ end
40
+ # print_threads_status
41
+ exiting = true if(Cfg.config["exit"])
42
+ break if exiting
43
+ end
44
+ close_threads if exiting
24
45
  end
25
- end
26
46
 
27
- def wait_for_threads
28
- @threads.each { |th| th.join }
29
- end
47
+ def kill_thread thread
48
+ thread[:thread].kill
49
+ end
50
+
51
+ def kill_open_threads
52
+ @threads.each do |thread|
53
+ unless thread_false_or_nil?(thread)
54
+ kill_thread thread
55
+ end
56
+ end
57
+ end
58
+
59
+ def thread_false_or_nil? th
60
+ if(th[:thread].status == false)
61
+ return true
62
+ end
63
+
64
+ if(th[:thread].status.nil?)
65
+ return true
66
+ end
67
+ end
68
+
69
+ def wait_for_threads
70
+ Cfg.config.params["exit"] = false
71
+ loop do
72
+ alive = false
73
+ sleep 0.1
74
+ @threads.each { |th|
75
+ if thread_false_or_nil? th
76
+ elsif th[:name] != :monitor_keys_thread
77
+ alive = true
78
+ end
79
+ }
80
+ break unless alive
81
+ end
82
+ threads.each {|th|
83
+ if(th[:name] == :monitor_keys_thread)
84
+ kill_thread th
85
+ end
86
+ sleep 0.1
87
+ }
88
+ end
89
+
90
+ def print_threads_status
91
+ @threads.each do |thread|
92
+ puts "\r"
93
+ print "#{thread[:name]} = "
94
+ p thread[:thread].status
95
+ end
96
+ end
97
+
98
+ def kill_monitor_keys_thread_maybe thread
99
+ kill_thread(thread) unless thread_false_or_nil?(thread)
100
+ end
101
+
102
+ def any_thread_open?
103
+ @threads.each do |thread|
104
+ # print "status "
105
+ # p thread
106
+ if(thread[:name] == :monitor_keys_thread)
107
+ kill_monitor_keys_thread_maybe thread
108
+ else
109
+ unless thread_false_or_nil?(thread)
110
+ return true
111
+ end
112
+ end
113
+ end
114
+ nil
115
+ end
116
+
117
+ def force_kill
118
+ puts "exiting"
119
+ # puts "Forcing kill!\r"
120
+ kill_open_threads
121
+ # print_threads_status
122
+ system("stty -raw echo")
123
+ sleep 0.2
124
+ exit(1)
125
+ end
126
+
127
+ def close_threads
128
+ await_termination_count = 0
129
+ loop do
130
+ sleep 0.1
131
+ break unless any_thread_open?()
132
+ # print_threads_status
133
+ await_termination_count += 1
134
+ force_kill if(await_termination_count >= 30)
135
+ end
136
+ end
137
+
138
+ def run
139
+ start_threads
140
+ monitor_threads
141
+ system("stty -raw echo")
142
+ end
30
143
 
31
- def run
32
- start_threads
33
- wait_for_threads
34
144
  end
35
145
 
36
146
  end