asker-tool 2.1.6 → 2.2.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE.txt → LICENSE} +0 -0
  3. data/README.md +14 -15
  4. data/bin/asker +1 -1
  5. data/lib/asker/ai/ai.rb +6 -3
  6. data/lib/asker/ai/ai_calculate.rb +20 -6
  7. data/lib/asker/ai/concept_ai.rb +12 -3
  8. data/lib/asker/ai/question.rb +28 -6
  9. data/lib/asker/ai/stages/base_stage.rb +45 -6
  10. data/lib/asker/ai/stages/stage_b.rb +90 -49
  11. data/lib/asker/ai/stages/stage_d.rb +69 -90
  12. data/lib/asker/ai/stages/stage_f.rb +47 -38
  13. data/lib/asker/ai/stages/stage_i.rb +79 -92
  14. data/lib/asker/ai/stages/stage_s.rb +41 -36
  15. data/lib/asker/ai/stages/stage_t.rb +114 -73
  16. data/lib/asker/application.rb +7 -15
  17. data/lib/asker/check_input/input_data.rb +358 -0
  18. data/lib/asker/check_input.rb +51 -0
  19. data/lib/asker/cli.rb +28 -28
  20. data/lib/asker/data/code.rb +5 -16
  21. data/lib/asker/data/concept.rb +71 -24
  22. data/lib/asker/data/project_data.rb +63 -0
  23. data/lib/asker/data/table.rb +2 -0
  24. data/lib/asker/data/template.rb +3 -1
  25. data/lib/asker/data/world.rb +8 -16
  26. data/lib/asker/displayer/code_displayer.rb +7 -0
  27. data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
  28. data/lib/asker/displayer/concept_ai_displayer.rb +24 -22
  29. data/lib/asker/displayer/concept_displayer.rb +9 -4
  30. data/lib/asker/displayer/stats_displayer.rb +8 -0
  31. data/lib/asker/exporter/concept_ai_gift_exporter.rb +16 -10
  32. data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
  33. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +6 -3
  34. data/lib/asker/exporter/concept_doc_exporter.rb +14 -1
  35. data/lib/asker/exporter/data_gift_exporter.rb +29 -0
  36. data/lib/asker/exporter/output_file_exporter.rb +9 -6
  37. data/lib/asker/files/{config.ini → asker.ini} +14 -4
  38. data/lib/asker/files/language/du/connectors.yaml +81 -0
  39. data/lib/asker/files/language/du/mistakes.yaml +82 -0
  40. data/lib/asker/files/language/du/templates.yaml +28 -49
  41. data/lib/asker/files/language/en/templates.yaml +19 -19
  42. data/lib/asker/files/language/es/mistakes.yaml +9 -7
  43. data/lib/asker/files/language/es/templates.yaml +19 -19
  44. data/lib/asker/files/language/fr/connectors.yaml +68 -84
  45. data/lib/asker/files/language/fr/templates.yaml +22 -22
  46. data/lib/asker/formatter/concept_doc_formatter.rb +0 -4
  47. data/lib/asker/formatter/concept_string_formatter.rb +7 -4
  48. data/lib/asker/formatter/moodle/matching.erb +38 -0
  49. data/lib/asker/formatter/moodle/multichoice.erb +49 -0
  50. data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
  51. data/lib/asker/formatter/moodle/truefalse.erb +47 -0
  52. data/lib/asker/formatter/question_gift_formatter.rb +30 -20
  53. data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
  54. data/lib/asker/lang/lang_factory.rb +7 -1
  55. data/lib/asker/loader/code_loader.rb +1 -1
  56. data/lib/asker/loader/content_loader.rb +12 -14
  57. data/lib/asker/loader/directory_loader.rb +1 -8
  58. data/lib/asker/loader/embedded_file.rb +42 -0
  59. data/lib/asker/loader/file_loader.rb +1 -3
  60. data/lib/asker/loader/image_url_loader.rb +8 -9
  61. data/lib/asker/loader/input_loader.rb +5 -6
  62. data/lib/asker/loader/project_loader.rb +18 -10
  63. data/lib/asker/logger.rb +35 -8
  64. data/lib/asker/skeleton.rb +3 -2
  65. data/lib/asker.rb +72 -43
  66. metadata +43 -17
  67. data/lib/asker/checker.rb +0 -455
  68. data/lib/asker/project.rb +0 -146
@@ -0,0 +1,358 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+
5
+ class InputData
6
+ attr_reader :inputs, :outputs
7
+
8
+ def initialize(filepath)
9
+ @inputs = File.read(filepath).split("\n")
10
+ @outputs = []
11
+ @inputs.each_with_index do |line, index|
12
+ output = { id: index,
13
+ level: 0,
14
+ state: :none,
15
+ type: :none,
16
+ source: line,
17
+ msg: '' }
18
+ @outputs << output
19
+ end
20
+ @ok = false
21
+ end
22
+
23
+ def ok?
24
+ @ok
25
+ end
26
+
27
+ def show
28
+ @outputs.each do |i|
29
+ puts "#{i[:id]}: #{i[:state]} [#{i[:type]}] #{i[:msg]}"
30
+ end
31
+ end
32
+
33
+ def show_errors
34
+ errors = 0
35
+ # puts "Line : Error description"
36
+ @outputs.each do |i|
37
+ next if i[:state] == :ok
38
+
39
+ errors += 1
40
+ if errors < 11
41
+ data = { id: i[:id], msg: i[:msg], source: i[:source][0, 40] }
42
+ order = i[:id] + 1
43
+ data = { order: order, msg: i[:msg], source: i[:source][0, 40] }
44
+ puts format(' %<order>03d : %<msg>s. => %<source>s', data)
45
+ end
46
+ puts '...' if errors == 11
47
+ end
48
+
49
+ if errors.positive?
50
+ puts Rainbow("[ERROR] #{errors} errors " \
51
+ "from #{@inputs.size} lines!").red.bright
52
+ end
53
+ puts Rainbow('Syntax OK!').green if errors.zero?
54
+ end
55
+
56
+ def check
57
+ @ok = true
58
+ @inputs.each_with_index do |line, index|
59
+ check_empty_lines(line, index)
60
+ check_map(line, index)
61
+ check_concept(line, index)
62
+ check_names(line, index)
63
+ check_tags(line, index)
64
+ check_def(line, index)
65
+ check_table(line, index)
66
+ check_row(line, index)
67
+ check_col(line, index)
68
+ check_template(line, index)
69
+ check_code(line, index)
70
+ check_type(line, index)
71
+ check_path(line, index)
72
+ check_features(line, index)
73
+ check_unknown(line, index)
74
+ @ok = false unless @outputs[index][:state] == :ok
75
+ @ok = false if @outputs[index][:type] == :unkown
76
+ end
77
+ @ok
78
+ end
79
+
80
+ private
81
+
82
+ def check_empty_lines(line, index)
83
+ return unless line.strip.size.zero? || line.start_with?('#')
84
+
85
+ @outputs[index][:type] = :empty
86
+ @outputs[index][:level] = -1
87
+ @outputs[index][:state] = :ok
88
+ end
89
+
90
+ def check_map(line, index)
91
+ if index.zero?
92
+ @outputs[index][:type] = :map
93
+ if line.start_with?('%map{')
94
+ @outputs[index][:state] = :ok
95
+ else
96
+ @outputs[index][:state] = :err
97
+ @outputs[index][:msg] = 'Start with %map{'
98
+ end
99
+ elsif index.positive? && line.include?('%map{')
100
+ @outputs[index][:state] = :err
101
+ @outputs[index][:type] = :map
102
+ @outputs[index][:msg] = 'Write %map on line 0'
103
+ end
104
+ end
105
+
106
+ def check_concept(line, index)
107
+ return unless @outputs[index][:state] == :none
108
+ return unless line.include? '%concept'
109
+
110
+ @outputs[index][:type] = :concept
111
+ @outputs[index][:level] = 1
112
+ @outputs[index][:state] = :ok
113
+ if find_parent(index) != :map
114
+ @outputs[index][:state] = :err
115
+ @outputs[index][:msg] = 'Parent(map) not found!'
116
+ elsif line != ' %concept'
117
+ @outputs[index][:state] = :err
118
+ @outputs[index][:msg] = 'Write 2 spaces before %concept'
119
+ end
120
+ end
121
+
122
+ def check_names(line, index)
123
+ return unless @outputs[index][:state] == :none
124
+ return unless line.include? '%names'
125
+
126
+ @outputs[index][:type] = :names
127
+ @outputs[index][:level] = 2
128
+ @outputs[index][:state] = :ok
129
+ if find_parent(index) != :concept
130
+ @outputs[index][:state] = :err
131
+ @outputs[index][:msg] = 'Parent(concept) not found!'
132
+ elsif !line.start_with? ' %names'
133
+ @outputs[index][:state] = :err
134
+ @outputs[index][:msg] = 'Write 4 spaces before %names'
135
+ end
136
+ end
137
+
138
+ def check_tags(line, index)
139
+ return unless @outputs[index][:state] == :none
140
+ return unless line.include? '%tags'
141
+
142
+ @outputs[index][:type] = :tags
143
+ @outputs[index][:level] = 2
144
+ @outputs[index][:state] = :ok
145
+ if find_parent(index) != :concept
146
+ @outputs[index][:state] = :err
147
+ @outputs[index][:msg] = 'Parent(concept) not found!'
148
+ elsif !line.start_with? ' %tags'
149
+ @outputs[index][:state] = :err
150
+ @outputs[index][:msg] = 'Write 4 spaces before %tags'
151
+ end
152
+ end
153
+
154
+ def check_def(line, index)
155
+ return unless @outputs[index][:state] == :none
156
+ return unless line.include? '%def'
157
+
158
+ @outputs[index][:type] = :def
159
+ @outputs[index][:level] = 2
160
+ @outputs[index][:state] = :ok
161
+ if find_parent(index) != :concept
162
+ @outputs[index][:state] = :err
163
+ @outputs[index][:msg] = 'Parent(concept) not found!'
164
+ elsif !line.start_with? ' %def'
165
+ @outputs[index][:state] = :err
166
+ @outputs[index][:msg] = 'Write 4 spaces before %def'
167
+ end
168
+ end
169
+
170
+ def check_table(line, index)
171
+ return unless @outputs[index][:state] == :none
172
+ return unless line.include? '%table'
173
+
174
+ @outputs[index][:type] = :table
175
+ @outputs[index][:level] = 2
176
+ @outputs[index][:state] = :ok
177
+ if find_parent(index) != :concept
178
+ @outputs[index][:state] = :err
179
+ @outputs[index][:msg] = 'Parent(concept) not found!'
180
+ elsif !line.start_with? ' %table'
181
+ @outputs[index][:state] = :err
182
+ @outputs[index][:msg] = 'Write 4 spaces before %table'
183
+ end
184
+ end
185
+
186
+ def check_row(line, index)
187
+ return unless @outputs[index][:state] == :none
188
+ return unless line.include? '%row'
189
+
190
+ @outputs[index][:type] = :row
191
+ @outputs[index][:state] = :ok
192
+
193
+ case count_spaces(line)
194
+ when 6
195
+ @outputs[index][:level] = 3
196
+ parent = find_parent(index)
197
+ unless %i[table features].include? parent
198
+ @outputs[index][:state] = :err
199
+ @outputs[index][:msg] = 'Parent(table/features) not found!'
200
+ end
201
+ when 8
202
+ @outputs[index][:level] = 4
203
+ if find_parent(index) != :template
204
+ @outputs[index][:state] = :err
205
+ @outputs[index][:msg] = 'Parent(template) not found!'
206
+ end
207
+ else
208
+ @outputs[index][:state] = :err
209
+ @outputs[index][:msg] = 'Write 6 or 8 spaces before %row'
210
+ end
211
+ end
212
+
213
+ def check_col(line, index)
214
+ return unless @outputs[index][:state] == :none
215
+ return unless line.include? '%col'
216
+
217
+ @outputs[index][:type] = :col
218
+ @outputs[index][:state] = :ok
219
+ case count_spaces(line)
220
+ when 8
221
+ @outputs[index][:level] = 4
222
+ if find_parent(index) != :row
223
+ @outputs[index][:state] = :err
224
+ @outputs[index][:msg] = 'Parent(row) not found!'
225
+ end
226
+ when 10
227
+ @outputs[index][:level] = 5
228
+ if find_parent(index) != :row
229
+ @outputs[index][:state] = :err
230
+ @outputs[index][:msg] = 'Parent(row) not found!'
231
+ end
232
+ else
233
+ @outputs[index][:state] = :err
234
+ @outputs[index][:msg] = 'Write 8 or 10 spaces before %col'
235
+ end
236
+ check_text(line, index)
237
+ end
238
+
239
+ def check_text(line, index)
240
+ return unless @outputs[index][:state] == :ok
241
+
242
+ ok = ''
243
+ %w[< >].each do |char|
244
+ ok = char if line.include? char
245
+ end
246
+ return if ok == ''
247
+
248
+ @outputs[index][:state] = :err
249
+ @outputs[index][:msg] = "Char #{ok} not allow!"
250
+ end
251
+
252
+ def check_template(line, index)
253
+ return unless @outputs[index][:state] == :none
254
+ return unless line.include? '%template'
255
+
256
+ @outputs[index][:type] = :template
257
+ @outputs[index][:level] = 3
258
+ @outputs[index][:state] = :ok
259
+ if find_parent(index) != :table
260
+ @outputs[index][:state] = :err
261
+ @outputs[index][:msg] = 'Parent(concept) not found!'
262
+ elsif !line.start_with? ' %template'
263
+ @outputs[index][:state] = :err
264
+ @outputs[index][:msg] = 'Write 6 spaces before %template'
265
+ end
266
+ end
267
+
268
+ def check_code(line, index)
269
+ return unless @outputs[index][:state] == :none
270
+ return unless line.include? '%code'
271
+
272
+ @outputs[index][:type] = :code
273
+ @outputs[index][:level] = 1
274
+ @outputs[index][:state] = :ok
275
+ if find_parent(index) != :map
276
+ @outputs[index][:state] = :err
277
+ @outputs[index][:msg] = 'Parent(map) not found!'
278
+ elsif line != ' %code'
279
+ @outputs[index][:state] = :err
280
+ @outputs[index][:msg] = 'Write 2 spaces before %code'
281
+ end
282
+ end
283
+
284
+ def check_type(line, index)
285
+ return unless @outputs[index][:state] == :none
286
+ return unless line.include? '%type'
287
+
288
+ @outputs[index][:type] = :type
289
+ @outputs[index][:level] = 2
290
+ @outputs[index][:state] = :ok
291
+ if find_parent(index) != :code
292
+ @outputs[index][:state] = :err
293
+ @outputs[index][:msg] = 'Parent(code) not found!'
294
+ elsif !line.start_with? ' %type'
295
+ @outputs[index][:state] = :err
296
+ @outputs[index][:msg] = 'Write 4 spaces before %type'
297
+ end
298
+ end
299
+
300
+ def check_path(line, index)
301
+ return unless @outputs[index][:state] == :none
302
+ return unless line.include? '%path'
303
+
304
+ @outputs[index][:type] = :path
305
+ @outputs[index][:level] = 2
306
+ @outputs[index][:state] = :ok
307
+ if find_parent(index) != :code
308
+ @outputs[index][:state] = :err
309
+ @outputs[index][:msg] = 'Parent(code) not found!'
310
+ elsif !line.start_with? ' %path'
311
+ @outputs[index][:state] = :err
312
+ @outputs[index][:msg] = 'Write 4 spaces before %type'
313
+ end
314
+ end
315
+
316
+ def check_features(line, index)
317
+ return unless @outputs[index][:state] == :none
318
+ return unless line.include? '%features'
319
+
320
+ @outputs[index][:type] = :features
321
+ @outputs[index][:level] = 2
322
+ @outputs[index][:state] = :ok
323
+ if find_parent(index) != :code
324
+ @outputs[index][:state] = :err
325
+ @outputs[index][:msg] = 'Parent(code) not found!'
326
+ elsif !line.start_with? ' %features'
327
+ @outputs[index][:state] = :err
328
+ @outputs[index][:msg] = 'Write 4 spaces before %features'
329
+ end
330
+ end
331
+
332
+ def check_unknown(line, index)
333
+ return unless @outputs[index][:state] == :none
334
+
335
+ @outputs[index][:type] = :unknown
336
+ @outputs[index][:level] = count_spaces(line) / 2
337
+ @outputs[index][:state] = :err
338
+ @outputs[index][:msg] = "Unknown tag with parent(#{find_parent(index)})!"
339
+ end
340
+
341
+ def find_parent(index)
342
+ current_level = @outputs[index][:level]
343
+ return :noparent if current_level.zero?
344
+
345
+ i = index - 1
346
+ while i >= 0
347
+ return @outputs[i][:type] if @outputs[i][:level] == current_level - 1
348
+
349
+ i -= 1
350
+ end
351
+ :noparent
352
+ end
353
+
354
+ def count_spaces(line)
355
+ a = line.split('%')
356
+ a[0].count(' ')
357
+ end
358
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+ require_relative 'check_input/input_data'
5
+
6
+ class CheckInput
7
+ def initialize(verbose = true)
8
+ @verbose = verbose
9
+ end
10
+
11
+ def file(filepath)
12
+ @filepath = filepath
13
+ self
14
+ end
15
+
16
+ def verbose(verbose)
17
+ @verbose = verbose
18
+ self
19
+ end
20
+
21
+ def check
22
+ # Check HAML file syntax
23
+ exist = check_file_exist
24
+ return false unless exist
25
+ check_file_content
26
+ end
27
+
28
+ private
29
+
30
+ def check_file_exist
31
+ if @filepath.nil?
32
+ raise Rainbow("Can't check nil filename")
33
+ end
34
+ unless File.exist? @filepath
35
+ puts Rainbow('File not found!').red.bright if @verbose
36
+ return false
37
+ end
38
+ unless File.extname(@filepath) == '.haml'
39
+ puts Rainbow('Only check HAML files!').yellow.bright if @verbose
40
+ return false
41
+ end
42
+ true
43
+ end
44
+
45
+ def check_file_content
46
+ data = InputData.new(@filepath)
47
+ data.check
48
+ data.show_errors if @verbose
49
+ data.ok?
50
+ end
51
+ end
data/lib/asker/cli.rb CHANGED
@@ -8,46 +8,38 @@ require_relative '../asker'
8
8
  ##
9
9
  # Command Line User Interface
10
10
  class CLI < Thor
11
- map ['h', '-h', '--help'] => 'help'
11
+ map ['--help'] => 'help'
12
12
 
13
- map ['v', '-v', '--version'] => 'version'
13
+ map ['--version'] => 'version'
14
14
  desc 'version', 'Show the program version'
15
- ##
16
- # Show current version
17
15
  def version
18
- print Rainbow(Application::NAME).bright.blue
19
- puts " (version #{Rainbow(Application::VERSION).green})"
16
+ puts "#{Application::NAME} version #{Application::VERSION}"
20
17
  end
21
18
 
22
19
  map ['f', '-f', '--file'] => 'file'
23
- desc 'file NAME', 'Build output files, from HAML/XML input file.'
20
+ desc '[file] FILEPATH', 'Build output files, from HAML/XML input file.'
24
21
  long_desc <<-LONGDESC
25
- Create output files, from input file (HAML/XML format).
26
22
 
27
23
  Build questions about contents defined into input file specified.
28
24
 
25
+ Create output files, from input file (HAML/XML format).
26
+
29
27
  Examples:
30
28
 
31
- (1) #{Rainbow('asker input/foo/foo.haml').yellow}, Build questions from HAML file.
29
+ (1) #{Rainbow('asker input/foo/foo.haml').aqua}, Build questions from HAML file.
32
30
 
33
- (2) #{Rainbow('asker input/foo/foo.xml').yellow}, Build questions from XML file.
31
+ (2) #{Rainbow('asker input/foo/foo.xml').aqua}, Build questions from XML file.
34
32
 
35
- (3) #{Rainbow('asker projects/foo/foo.yaml').yellow}, Build questions from YAML project file.
33
+ (3) #{Rainbow('asker projects/foo/foo.yaml').aqua}, Build questions from YAML project file.
36
34
 
37
35
  LONGDESC
38
- ##
39
- # Create questions from input file
40
- # @param filename (String) Path to input file
41
36
  def file(filename)
42
37
  # Asker start processing input file
43
38
  Asker.start(filename)
44
39
  end
45
40
 
46
- map ['c', '-c', '--check'] => 'check'
47
- desc 'check', 'Check input HAML file syntax'
48
- ##
49
- # Check input file syntax
50
- # @param filename (String) Path to input file
41
+ map ['--check'] => 'check'
42
+ desc 'check FILEPATH', 'Check input HAML file syntax'
51
43
  def check(filename)
52
44
  # Enable/disable color output
53
45
  Rainbow.enabled = false if options['color'] == false
@@ -55,21 +47,19 @@ class CLI < Thor
55
47
  Asker.check(filename)
56
48
  end
57
49
 
58
- map ['i', '-i', '--init'] => 'init'
59
- desc 'init', 'Create default INI config fie'
60
- ##
61
- # Create default INI config file
50
+ map ['--init'] => 'init'
51
+ desc 'init', 'Create default INI config file'
62
52
  def init
63
- Asker.create_configuration
53
+ Asker.init
64
54
  end
65
55
 
66
- map ['n', '-b', '--new', 'new'] => 'create_input'
67
- desc 'new', 'Create Asker demo input files'
56
+ map ['new','--new'] => 'new_input'
57
+ desc 'new DIRPATH', 'Create Asker demo input files'
68
58
  ##
69
59
  # Create Asker demo input files
70
60
  # @param dirname (String) Path to folder
71
- def create_input(dirname)
72
- Asker.create_input(dirname)
61
+ def new_input(dirname)
62
+ Asker.new_input(dirname)
73
63
  end
74
64
 
75
65
  ##
@@ -79,4 +69,14 @@ class CLI < Thor
79
69
  def method_missing(method, *_args, &_block)
80
70
  file(method.to_s)
81
71
  end
72
+
73
+ def respond_to_missing?(_method_name)
74
+ true
75
+ end
76
+
77
+ ##
78
+ # Thor stop and show messages on screen on failure
79
+ def self.exit_on_failure?
80
+ true
81
+ end
82
82
  end
@@ -1,20 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../ai/code/code_ai_factory'
2
- require_relative '../project'
3
- require_relative '../logger'
4
- require_relative '../formatter/code_string_formatter'
5
4
 
6
- ##
7
- # Code data object
8
5
  class Code
9
6
  attr_reader :dirname, :filename, :type
10
7
  attr_accessor :process, :features
11
8
  attr_reader :lines, :questions
12
9
 
13
- ##
14
- # Initialize Code object
15
- # @param dirname (String)
16
- # @param filename (String)
17
- # @param type (String)
18
10
  def initialize(dirname, filename, type)
19
11
  @dirname = dirname
20
12
  @filename = filename
@@ -38,16 +30,13 @@ class Code
38
30
  out
39
31
  end
40
32
 
41
- def debug
42
- Logger.verbose CodeStringFormatter.to_s(self)
43
- end
44
-
45
33
  private
46
34
 
47
35
  def load(filepath)
48
36
  return if filepath.nil?
37
+
49
38
  unless File.exist? filepath
50
- Logger.verboseln Rainbow("[ERROR] Unkown file #{filepath}").red.bright
39
+ puts Rainbow("[ERROR] Unkown file #{filepath}").red.bright
51
40
  return
52
41
  end
53
42
  content = File.read(filepath)
@@ -56,7 +45,7 @@ class Code
56
45
 
57
46
  def encode_and_split(text, encoding = :default)
58
47
  # Convert text to UTF-8 deleting unknown chars
59
- text = text || '' # Ensure text is not nil
48
+ text ||= '' # Ensure text is not nil
60
49
  flag = [:default, 'UTF-8'].include? encoding
61
50
  return text.encode('UTF-8', invalid: :replace).split("\n") if flag
62
51