fet 0.3.0 → 0.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6482a7f1b9a0e8375267c1220690f706e9058b0b485bb3079c174726425594ec
4
- data.tar.gz: 0fd439a8ac3631db1f88d345bb8c50a8f0baf1dd267017b88ec7884613f4b867
3
+ metadata.gz: 67009d9f1befb2258f255e646971889e81afdc34dc56fec363a5624bffb868f0
4
+ data.tar.gz: e0277de27773dd8bebd89d2f7aedad3c4e8aac24c6a0099a00656b22ce2620ce
5
5
  SHA512:
6
- metadata.gz: 8e3bec0d13c52547ab1f71aa2197b38ec85abf794f8d2e160fbb34bf45219e006a28e47cbab9d6f86e9067694cedbff2164621684fa9339ab21c424b3f722d7f
7
- data.tar.gz: bc68f79d35ba1114f79963f027ee3155b260f462e0a6589b3e5562f82615a1910ca01ea5b2fea5e2c99c4936b31e6a75c0b4f6ad788a10e0e4358079400abdb8
6
+ metadata.gz: 119ea1729a8c11ec5f0ec54a25f47b9007cf4d23c23c89f98ed8c4f5d66829b6dfb35363592a528b3293a7b01649b8348422bf8eb123702b7bd3cebe09a1bb1c
7
+ data.tar.gz: 64620f0f58519de0bfa633d783d652a5442ebc1b34ce9a7e91a0712e164152ddb2cc315338e94f7cc7c34cbc1c1feb6b3f556094cbadf2086c2503bb1d577eb0
data/.rubocop.yml CHANGED
@@ -40,6 +40,9 @@ Layout/CaseIndentation:
40
40
  Layout/LineLength:
41
41
  Max: 175
42
42
 
43
+ Style/Lambda:
44
+ EnforcedStyle: lambda
45
+
43
46
  Style/RedundantReturn:
44
47
  Enabled: false
45
48
 
File without changes
data/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
- ## [Released]
1
+ # [Unreleased]
2
+
3
+ # [Released]
4
+
5
+ ## [0.3.1] - 2021-09-27
6
+ - Allow limiting questions to specific degrees.
7
+ - Improve positioning of the score element in the UI.
8
+ - Add ability to show score summary over multiple games.
9
+ - Write game files to system temporary directory.
2
10
 
3
11
  ## [0.3.0] - 2021-09-06
4
12
 
data/Gemfile.lock CHANGED
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fet (0.3.0)
4
+ fet (0.3.1)
5
5
  gli (~> 2.20, >= 2.20.1)
6
6
  ice_nine (~> 0.11.2)
7
7
  midilib (~> 2.0, >= 2.0.5)
8
8
  ruby2d (~> 0.10.0)
9
+ terminal-table (~> 3.0, >= 3.0.1)
9
10
 
10
11
  GEM
11
12
  remote: https://rubygems.org/
@@ -55,6 +56,8 @@ GEM
55
56
  simplecov_json_formatter (~> 0.1)
56
57
  simplecov-html (0.12.3)
57
58
  simplecov_json_formatter (0.1.3)
59
+ terminal-table (3.0.1)
60
+ unicode-display_width (>= 1.1.1, < 3)
58
61
  timecop (0.9.4)
59
62
  unicode-display_width (2.0.0)
60
63
 
data/README.md CHANGED
@@ -8,6 +8,18 @@ Every level, a chord progression is played to identify a major/minor key, follow
8
8
  <img src="./assets/readme/demo.gif">
9
9
 
10
10
  ## Installation
11
+ ### Prerequisites
12
+ Install TiMidity++ for required performance improvements when converting MIDI to other formats.
13
+ #### OS X
14
+ ```sh
15
+ brew install timidity
16
+ ```
17
+ #### Ubuntu
18
+ ```sh
19
+ apt install timidity
20
+ ```
21
+
22
+ ### Gem
11
23
  Add this line to your application's Gemfile:
12
24
 
13
25
  ```ruby
@@ -29,7 +41,7 @@ The UI currently supports listening exercises, where a chord progression is play
29
41
 
30
42
  The binary can be executed as follows:
31
43
  ```sh
32
- fet play listening --degrees 1 --key-type major --next-on-correct --tempo 200
44
+ fet play listening --degrees 1 --key-type major --next-on-correct --tempo 200 --limit-degrees b6 --limit-degrees 5
33
45
  ```
34
46
 
35
47
  All flags are optional, and serve the following purposes:
@@ -40,6 +52,7 @@ All flags are optional, and serve the following purposes:
40
52
  | --key-type | Type of key to play, can be "major" or "minor". |
41
53
  | --[no-]next-on-correct | Go to the next level automatically when answered correctly. |
42
54
  | --tempo | The tempo at which the chord progression is played. |
55
+ | --limit-degrees | Limit to specific degrees. Can be supplied multiple times. |
43
56
 
44
57
  When using the UI, the following keyboard shortcuts are defined to allow for mouse-free interaction:
45
58
  | Keyboard Shortcut | Description |
@@ -49,7 +62,7 @@ When using the UI, the following keyboard shortcuts are defined to allow for mou
49
62
  | c | Repeat the chord progression only. |
50
63
  | n | Repeat the notes only. |
51
64
  | l | Repeat the question (looping). |
52
- | 1-7 | Select the degree, e.g. "2" selects the 2nd degree. |
65
+ | 1-7 | Select the degree, e.g. "2" selects the 2nd degree. Will also play that degree once the level is over. |
53
66
  | - | Modify the above degree to flatten it, e.g. "-" followed by "2" will select the b2nd degree. |
54
67
  | + | Modify the above degree to sharpen it, e.g. "+" followed by "4" will select the #4th degree. |
55
68
  | 0 | Make the degree natural, e.g. "+" followed by followed by "0" followed by "4" will select the 4th degree. |
data/bin/fet CHANGED
@@ -16,94 +16,11 @@ class App
16
16
  subcommand_option_handling(:normal)
17
17
  arguments(:strict)
18
18
 
19
- desc("Generate MIDI files for ear training")
20
- # arg_name "Describe arguments to generate here"
21
- command(:generate) do |c|
22
- c.desc("Generate MIDI files for listening")
23
- c.long_desc("Each MIDI file will contain a chord progression, followed by the specified number of degrees - first harmonically, then melodically after a pause.")
24
- c.command :listening do |listening|
25
- listening.desc("Tempo at which the chord progression is played at")
26
- listening.default_value(120)
27
- listening.flag([:t, :tempo], type: Integer)
28
-
29
- listening.desc("Number of degrees to play")
30
- listening.default_value(1)
31
- listening.flag([:d, :degrees], type: Integer, must_match: (1..11).map(&:to_s))
32
-
33
- listening.desc("Number of exercises to generate")
34
- listening.default_value(200)
35
- listening.flag([:e, :exercises], type: Integer)
36
-
37
- listening.desc("Generate all single degree listening exercises (ignores -e and -d flag)")
38
- listening.default_value(false)
39
- listening.switch [:a, :"all-single-degree"]
40
-
41
- listening.action do |global_options, options, args|
42
- Fet::Cli::Generate::Listening.run(global_options, options, args)
43
- end
44
- end
45
- end
46
-
47
- command(:generate) do |c|
48
- c.desc("Generate MIDI files for listening (single note)")
49
- c.long_desc("Each MIDI file will contain a chord progression, followed the same note across all files.")
50
- c.command :single_note_listening do |single_note_listening|
51
- single_note_listening.desc("Tempo at which the chord progression is played at")
52
- single_note_listening.default_value(120)
53
- single_note_listening.flag([:t, :tempo], type: Integer)
54
-
55
- single_note_listening.action do |global_options, options, args|
56
- Fet::Cli::Generate::SingleNoteListening.run(global_options, options, args)
57
- end
58
- end
59
- end
60
-
61
- command(:generate) do |c|
62
- c.desc("Generate MIDI files for singing")
63
- c.long_desc("Each MIDI file will contain a chord progression, followed by a specified pause, during which the degree should be sung."\
64
- " The degree is then played for confirmation.")
65
- c.command :singing do |singing|
66
- singing.desc("Tempo at which the chord progression is played at")
67
- singing.default_value(120)
68
- singing.flag([:t, :tempo], type: Integer)
69
-
70
- singing.desc("How many seconds to wait before playing the correct note")
71
- singing.default_value(3)
72
- singing.flag([:p, :pause], type: Integer)
73
-
74
- singing.action do |global_options, options, args|
75
- Fet::Cli::Generate::Singing.run(global_options, options, args)
76
- end
77
- end
78
- end
79
-
80
- desc("Run the ear training application")
81
- # arg_name "Describe arguments to generate here"
82
- command(:play) do |c|
83
- c.desc("Run the ear training application for listening")
84
- c.long_desc("Each level will contain a chord progression, followed by the specified number of degrees - first harmonically, then melodically after a pause.")
85
- c.command :listening do |listening|
86
- listening.desc("Tempo at which the chord progression is played at")
87
- listening.default_value(120)
88
- listening.flag([:t, :tempo], type: Integer)
89
-
90
- listening.desc("Number of degrees to play")
91
- listening.default_value(1)
92
- listening.flag([:d, :degrees], type: Integer, must_match: (1..11).map(&:to_s))
93
-
94
- listening.desc("Type of the chord progression")
95
- listening.default_value("major")
96
- listening.flag([:k, :"key-type"], type: String, must_match: ["major", "minor"])
97
-
98
- listening.desc("Automatically go to the next exercise when the answer was correct")
99
- listening.default_value(true)
100
- listening.switch [:n, :"next-on-correct"]
101
-
102
- listening.action do |global_options, options, args|
103
- Fet::Cli::Play::Listening.run(global_options, options, args)
104
- end
105
- end
106
- end
19
+ include ::Fet::Cli::Generate::ListeningCommand
20
+ include ::Fet::Cli::Generate::SingleNoteListeningCommand
21
+ include ::Fet::Cli::Generate::SingingCommand
22
+ include ::Fet::Cli::Play::ListeningCommand
23
+ include ::Fet::Cli::Score::SummaryCommand
107
24
 
108
25
  on_error do |exception|
109
26
  puts exception.backtrace
data/fet.gemspec CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_dependency "ice_nine", "~> 0.11.2"
33
33
  spec.add_dependency "midilib", "~> 2.0", ">= 2.0.5"
34
34
  spec.add_dependency "ruby2d", "~> 0.10.0"
35
+ spec.add_dependency "terminal-table", "~> 3.0", ">= 3.0.1"
35
36
 
36
37
  # RDoc configuration
37
38
  spec.extra_rdoc_files = ["README.rdoc", "fet.rdoc"]
data/fet.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  == fet - Functional Ear Trainer
2
2
 
3
- v0.2.0
3
+ v0.3.0
4
4
 
5
5
  === Global Options
6
6
  === --help
@@ -100,7 +100,7 @@ Run the ear training application
100
100
  ====== Command: <tt>listening </tt>
101
101
  Run the ear training application for listening
102
102
 
103
- Each level will contain a chord progression, followed by the specified number of degrees - first harmonically, then melodically after a pause.
103
+ Each level will play a chord progression, followed by the specified number of degrees harmonically. The correct degrees should be selected.
104
104
  ======= Options
105
105
  ======= -d|--degrees arg
106
106
 
@@ -118,6 +118,14 @@ Type of the chord progression
118
118
  [Must Match] ["major", "minor"]
119
119
 
120
120
 
121
+ ======= -l|--limit-degrees arg
122
+
123
+ Limit which degrees can play
124
+
125
+ [Default Value] []
126
+ [Must Match] ["1", "#1", "b2", "2", "#2", "b3", "3", "4", "#4", "b5", "5", "#5", "b6", "6", "#6", "b7", "7"]
127
+
128
+
121
129
  ======= -t|--tempo arg
122
130
 
123
131
  Tempo at which the chord progression is played at
@@ -130,3 +138,50 @@ Automatically go to the next exercise when the answer was correct
130
138
 
131
139
 
132
140
 
141
+ ==== Command: <tt>score </tt>
142
+ Score commands
143
+
144
+
145
+ ===== Commands
146
+ ====== Command: <tt>summary </tt>
147
+ Show the score summary
148
+
149
+
150
+ ======= Options
151
+ ======= -b|--begin-offset arg
152
+
153
+ Offset beginning index of resulting array
154
+
155
+ [Default Value] 0
156
+
157
+
158
+ ======= -d|--degrees arg
159
+
160
+ Number of degrees to play
161
+
162
+ [Default Value] 1
163
+ [Must Match] ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]
164
+
165
+
166
+ ======= -e|--end-offset arg
167
+
168
+ Offset end index of resulting array
169
+
170
+ [Default Value] 0
171
+
172
+
173
+ ======= -k|--key-type arg
174
+
175
+ Type of the chord progression
176
+
177
+ [Default Value] major
178
+ [Must Match] ["major", "minor"]
179
+
180
+
181
+ ======= -s|--seconds arg
182
+
183
+ Only include games that had greater or equal playtime to the specified amount (in seconds)
184
+
185
+ [Default Value] 0
186
+
187
+
@@ -11,7 +11,6 @@ module Fet
11
11
  tempo: options[:tempo],
12
12
  degrees: options[:degrees],
13
13
  all_single_degree: options[:"all-single-degree"],
14
- directory_prefix: options[:directory_prefix] || "",
15
14
  ).generate
16
15
  end
17
16
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fet
4
+ module Cli
5
+ module Generate
6
+ # Defines the CLI "generate listening" command
7
+ module ListeningCommand
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ extend ClassMethods
11
+
12
+ desc("Generate MIDI files for ear training")
13
+ command(:generate) do |c|
14
+ define_listening_command(c)
15
+ end
16
+ end
17
+ end
18
+
19
+ # Internal methods for the "generate listening" command
20
+ module ClassMethods
21
+ private
22
+
23
+ def define_listening_command(command)
24
+ command.desc("Generate MIDI files for listening")
25
+ command.long_desc(long_listening_command_description)
26
+ command.command :listening do |listening|
27
+ define_tempo_flag(listening)
28
+ define_degrees_flag(listening)
29
+ define_exerises_flag(listening)
30
+ define_all_single_degree_flag(listening)
31
+ define_action(listening)
32
+ end
33
+ end
34
+
35
+ def long_listening_command_description
36
+ return "Each MIDI file will contain a chord progression, followed by the specified number of degrees - first harmonically, then melodically after a pause."
37
+ end
38
+
39
+ def define_tempo_flag(command)
40
+ command.desc("Tempo at which the chord progression is played at")
41
+ command.default_value(120)
42
+ command.flag([:t, :tempo], type: Integer)
43
+ end
44
+
45
+ def define_degrees_flag(command)
46
+ command.desc("Number of degrees to play")
47
+ command.default_value(1)
48
+ command.flag([:d, :degrees], type: Integer, must_match: (1..11).map(&:to_s))
49
+ end
50
+
51
+ def define_exerises_flag(command)
52
+ command.desc("Number of exercises to generate")
53
+ command.default_value(200)
54
+ command.flag([:e, :exercises], type: Integer)
55
+ end
56
+
57
+ def define_all_single_degree_flag(command)
58
+ command.desc("Generate all single degree listening exercises (ignores -e and -d flag)")
59
+ command.default_value(false)
60
+ command.switch [:a, :"all-single-degree"]
61
+ end
62
+
63
+ def define_action(command)
64
+ command.action do |global_options, options, args|
65
+ Fet::Cli::Generate::Listening.run(global_options, options, args)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -9,7 +9,6 @@ module Fet
9
9
  Fet::Generator::Singing.new(
10
10
  tempo: options[:tempo],
11
11
  pause: options[:pause],
12
- directory_prefix: options[:directory_prefix] || "",
13
12
  ).generate
14
13
  end
15
14
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fet
4
+ module Cli
5
+ module Generate
6
+ # Defines the CLI "generate singing" command
7
+ module SingingCommand
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ extend ClassMethods
11
+
12
+ command(:generate) do |c|
13
+ define_singing_command(c)
14
+ end
15
+ end
16
+ end
17
+
18
+ # Internal methods for the "generate singing" command
19
+ module ClassMethods
20
+ private
21
+
22
+ def define_singing_command(command)
23
+ command.desc("Generate MIDI files for singing")
24
+ command.long_desc("Each MIDI file will contain a chord progression, followed by a specified pause, during which the degree should be sung."\
25
+ " The degree is then played for confirmation.")
26
+ command.command :singing do |singing|
27
+ define_tempo_flag(singing)
28
+ define_pause_flag(singing)
29
+ define_singing_action(singing)
30
+ end
31
+ end
32
+
33
+ def define_tempo_flag(command)
34
+ command.desc("Tempo at which the chord progression is played at")
35
+ command.default_value(120)
36
+ command.flag([:t, :tempo], type: Integer)
37
+ end
38
+
39
+ def define_pause_flag(command)
40
+ command.desc("How many seconds to wait before playing the correct note")
41
+ command.default_value(3)
42
+ command.flag([:p, :pause], type: Integer)
43
+ end
44
+
45
+ def define_singing_action(command)
46
+ command.action do |global_options, options, args|
47
+ Fet::Cli::Generate::Singing.run(global_options, options, args)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -8,7 +8,6 @@ module Fet
8
8
  def self.run(_global_options, options, _args)
9
9
  Fet::Generator::SingleNoteListening.new(
10
10
  tempo: options[:tempo],
11
- directory_prefix: options[:directory_prefix] || "",
12
11
  ).generate
13
12
  end
14
13
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fet
4
+ module Cli
5
+ module Generate
6
+ # Defines the CLI "generate single_note_listening" command
7
+ module SingleNoteListeningCommand
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ extend ClassMethods
11
+
12
+ command(:generate) do |c|
13
+ define_single_note_listening_command(c)
14
+ end
15
+ end
16
+ end
17
+
18
+ # Internal methods for the "generate single_note_listening" command
19
+ module ClassMethods
20
+ private
21
+
22
+ def define_single_note_listening_command(command)
23
+ command.desc("Generate MIDI files for listening (single note)")
24
+ command.long_desc("Each MIDI file will contain a chord progression, followed the same note across all files.")
25
+ command.command :single_note_listening do |single_note_listening|
26
+ define_tempo_flag(single_note_listening)
27
+ define_single_note_listening_action(single_note_listening)
28
+ end
29
+ end
30
+
31
+ def define_tempo_flag(command)
32
+ command.desc("Tempo at which the chord progression is played at")
33
+ command.default_value(120)
34
+ command.flag([:t, :tempo], type: Integer)
35
+ end
36
+
37
+ def define_single_note_listening_action(command)
38
+ command.action do |global_options, options, args|
39
+ Fet::Cli::Generate::SingleNoteListening.run(global_options, options, args)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -11,6 +11,7 @@ module Fet
11
11
  degrees: options[:degrees],
12
12
  key_type: options[:"key-type"],
13
13
  next_on_correct: options[:"next-on-correct"],
14
+ limit_degrees: options[:"limit-degrees"],
14
15
  ).start
15
16
  end
16
17
  end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fet
4
+ module Cli
5
+ module Play
6
+ # Defines the CLI "play listening" command
7
+ module ListeningCommand
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ extend ClassMethods
11
+
12
+ desc("Run the ear training application")
13
+ command(:play) do |c|
14
+ define_listening_command(c)
15
+ end
16
+ end
17
+ end
18
+
19
+ # Internal methods for the "play listening" command
20
+ module ClassMethods
21
+ private
22
+
23
+ def define_listening_command(command)
24
+ command.desc("Run the ear training application for listening")
25
+ command.long_desc("Each level will play a chord progression, followed by the specified number of degrees harmonically. The correct degrees should be selected.")
26
+ command.command :listening do |listening|
27
+ define_tempo_flag(listening)
28
+ define_degrees_flag(listening)
29
+ define_key_type_flag(listening)
30
+ define_next_on_correct_flag(listening)
31
+ define_limit_degrees_flag(listening)
32
+
33
+ define_listening_action(listening)
34
+ end
35
+ end
36
+
37
+ def define_tempo_flag(command)
38
+ command.desc("Tempo at which the chord progression is played at")
39
+ command.default_value(120)
40
+ command.flag([:t, :tempo], type: Integer)
41
+ end
42
+
43
+ def define_degrees_flag(command)
44
+ command.desc("Number of degrees to play")
45
+ command.default_value(1)
46
+ command.flag([:d, :degrees], type: Integer, must_match: (1..11).map(&:to_s))
47
+ end
48
+
49
+ def define_key_type_flag(command)
50
+ command.desc("Type of the chord progression")
51
+ command.default_value("major")
52
+ command.flag([:k, :"key-type"], type: String, must_match: ["major", "minor"])
53
+ end
54
+
55
+ def define_next_on_correct_flag(command)
56
+ command.desc("Automatically go to the next exercise when the answer was correct")
57
+ command.default_value(true)
58
+ command.switch [:n, :"next-on-correct"]
59
+ end
60
+
61
+ def define_limit_degrees_flag(command)
62
+ command.desc("Limit which degrees can play")
63
+ command.default_value([])
64
+ command.flag([:l, :"limit-degrees"], type: String, must_match: Fet::Degree::DEGREE_NAMES.flatten, multiple: true)
65
+ end
66
+
67
+ def define_listening_action(command)
68
+ command.action do |global_options, options, args|
69
+ Fet::Cli::Play::Listening.run(global_options, options, args)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fet
4
+ module Cli
5
+ module Score
6
+ # CLI implementation for the "score summary" command
7
+ module Summary
8
+ def self.run(_global_options, options, _args)
9
+ Fet::ScoreSummary.new(
10
+ minimum_session_length: options[:seconds],
11
+ number_of_degrees: options[:degrees],
12
+ key_type: options[:"key-type"],
13
+ begin_offset: options[:"begin-offset"],
14
+ end_offset: options[:"end-offset"],
15
+ ).summary
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fet
4
+ module Cli
5
+ module Score
6
+ # Defines the CLI "score summary" command
7
+ module SummaryCommand
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ extend ClassMethods
11
+
12
+ desc("Score commands")
13
+ command(:score) do |c|
14
+ define_summary_command(c)
15
+ end
16
+ end
17
+ end
18
+
19
+ # Internal methods for the "score summary" command
20
+ module ClassMethods
21
+ private
22
+
23
+ def define_summary_command(command)
24
+ command.desc("Show the score summary")
25
+ command.command :summary do |summary|
26
+ define_seconds_flag(summary)
27
+ define_degrees_flag(summary)
28
+ define_key_type_flag(summary)
29
+ define_begin_offset_flag(summary)
30
+ define_end_offset_flag(summary)
31
+ define_score_action(summary)
32
+ end
33
+ end
34
+
35
+ def define_seconds_flag(command)
36
+ command.desc("Only include games that had greater or equal playtime to the specified amount (in seconds)")
37
+ command.default_value(0)
38
+ command.flag([:s, :seconds], type: Integer)
39
+ end
40
+
41
+ def define_degrees_flag(command)
42
+ command.desc("Number of degrees to play")
43
+ command.default_value(1)
44
+ command.flag([:d, :degrees], type: Integer, must_match: (1..11).map(&:to_s))
45
+ end
46
+
47
+ def define_key_type_flag(command)
48
+ command.desc("Type of the chord progression")
49
+ command.default_value("major")
50
+ command.flag([:k, :"key-type"], type: String, must_match: ["major", "minor"])
51
+ end
52
+
53
+ def define_begin_offset_flag(command)
54
+ command.desc("Offset beginning index of resulting array")
55
+ command.default_value(0)
56
+ command.flag([:b, :"begin-offset"], type: Integer)
57
+ end
58
+
59
+ def define_end_offset_flag(command)
60
+ command.desc("Offset end index of resulting array")
61
+ command.default_value(0)
62
+ command.flag([:e, :"end-offset"], type: Integer)
63
+ end
64
+
65
+ def define_score_action(command)
66
+ command.action do |global_options, options, args|
67
+ Fet::Cli::Score::Summary.run(global_options, options, args)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end