asker-tool 2.1.5 → 2.1.6

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE → LICENSE.txt} +0 -0
  3. data/README.md +2 -3
  4. data/bin/asker +1 -0
  5. data/lib/asker.rb +10 -6
  6. data/lib/asker/ai/ai.rb +4 -0
  7. data/lib/asker/ai/code/base_code_ai.rb +104 -0
  8. data/lib/asker/{code/ai → ai/code}/code_ai_factory.rb +11 -1
  9. data/lib/asker/{code/ai → ai/code}/javascript_code_ai.rb +2 -5
  10. data/lib/asker/ai/code/problem_code_ai.rb +176 -0
  11. data/lib/asker/{code/ai → ai/code}/python_code_ai.rb +2 -5
  12. data/lib/asker/{code/ai → ai/code}/ruby_code_ai.rb +14 -7
  13. data/lib/asker/{code/ai → ai/code}/sql_code_ai.rb +2 -5
  14. data/lib/asker/ai/concept_ai.rb +1 -0
  15. data/lib/asker/ai/stages/stage_t.rb +76 -76
  16. data/lib/asker/application.rb +18 -2
  17. data/lib/asker/checker.rb +112 -30
  18. data/lib/asker/cli.rb +12 -25
  19. data/lib/asker/data/code.rb +73 -0
  20. data/lib/asker/data/column.rb +31 -21
  21. data/lib/asker/data/concept.rb +42 -45
  22. data/lib/asker/data/data_field.rb +14 -0
  23. data/lib/asker/data/row.rb +75 -52
  24. data/lib/asker/data/table.rb +89 -42
  25. data/lib/asker/data/world.rb +57 -33
  26. data/lib/asker/displayer/concept_ai_displayer.rb +56 -37
  27. data/lib/asker/displayer/concept_displayer.rb +7 -5
  28. data/lib/asker/displayer/stats_displayer.rb +4 -3
  29. data/lib/asker/exporter/concept_ai_gift_exporter.rb +5 -3
  30. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +7 -3
  31. data/lib/asker/exporter/output_file_exporter.rb +1 -1
  32. data/lib/asker/files/config.ini +37 -0
  33. data/lib/asker/files/example-concept.haml +0 -1
  34. data/lib/asker/{lang/locales → files/language}/du/templates.yaml +0 -0
  35. data/lib/asker/{lang/locales → files/language}/en/connectors.yaml +0 -0
  36. data/lib/asker/{lang/locales → files/language}/en/mistakes.yaml +0 -0
  37. data/lib/asker/{lang/locales → files/language}/en/templates.yaml +0 -0
  38. data/lib/asker/{lang/locales → files/language}/es/connectors.yaml +0 -0
  39. data/lib/asker/{lang/locales → files/language}/es/mistakes.yaml +0 -0
  40. data/lib/asker/{lang/locales → files/language}/es/templates.yaml +0 -0
  41. data/lib/asker/{lang/locales → files/language}/fr/connectors.yaml +0 -0
  42. data/lib/asker/{lang/locales → files/language}/fr/mistakes.yaml +0 -0
  43. data/lib/asker/{lang/locales → files/language}/fr/templates.yaml +0 -0
  44. data/lib/asker/{lang/locales → files/language}/javascript/connectors.yaml +0 -0
  45. data/lib/asker/{lang/locales → files/language}/javascript/mistakes.yaml +0 -0
  46. data/lib/asker/{lang/locales → files/language}/javascript/templates.yaml +0 -0
  47. data/lib/asker/{lang/locales → files/language}/math/connectors.yaml +0 -0
  48. data/lib/asker/{lang/locales → files/language}/math/mistakes.yaml +0 -0
  49. data/lib/asker/{lang/locales → files/language}/math/templates.yaml +0 -0
  50. data/lib/asker/{lang/locales → files/language}/python/connectors.yaml +0 -0
  51. data/lib/asker/{lang/locales → files/language}/python/mistakes.yaml +0 -0
  52. data/lib/asker/{lang/locales → files/language}/python/templates.yaml +0 -0
  53. data/lib/asker/{lang/locales → files/language}/ruby/connectors.yaml +0 -0
  54. data/lib/asker/{lang/locales → files/language}/ruby/mistakes.yaml +0 -0
  55. data/lib/asker/{lang/locales → files/language}/ruby/templates.yaml +0 -0
  56. data/lib/asker/{lang/locales → files/language}/sql/connectors.yaml +0 -0
  57. data/lib/asker/{lang/locales → files/language}/sql/mistakes.yaml +0 -0
  58. data/lib/asker/{lang/locales → files/language}/sql/templates.yaml +0 -0
  59. data/lib/asker/lang/lang.rb +17 -10
  60. data/lib/asker/lang/lang_factory.rb +26 -5
  61. data/lib/asker/lang/text_actions.rb +87 -69
  62. data/lib/asker/loader/code_loader.rb +3 -3
  63. data/lib/asker/loader/content_loader.rb +9 -5
  64. data/lib/asker/loader/file_loader.rb +2 -11
  65. data/lib/asker/loader/haml_loader.rb +15 -0
  66. data/lib/asker/loader/image_url_loader.rb +5 -8
  67. data/lib/asker/loader/input_loader.rb +8 -9
  68. data/lib/asker/loader/project_loader.rb +10 -8
  69. data/lib/asker/logger.rb +3 -3
  70. data/lib/asker/project.rb +24 -50
  71. data/lib/asker/skeleton.rb +22 -13
  72. metadata +39 -37
  73. data/lib/asker/code/ai/base_code_ai.rb +0 -48
  74. data/lib/asker/code/code.rb +0 -53
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39bc74c80c6c83d62fb43bee32e10d3c3503880132cbaaa81f5e14115c9286d7
4
- data.tar.gz: b60194338ffb8429c665d726b62f784c7a0787efb79db4a079b4c13bcbcd6fe8
3
+ metadata.gz: 31954f483d7ed78c542d50fcbfd3ce9419d49cca87a89a6dd717e9832e870386
4
+ data.tar.gz: 2dc8133f935ec289cafa318392d2575542f3083c165d0e86b6902ef7fbc2a427
5
5
  SHA512:
6
- metadata.gz: 11b8da624fedb21e507ec7f015e8e921d8d2a85efd613e1a85646114e4b505a73f303b96b2a76ce77653cf511143f495dffcb6477959eb43ad139446547e55ae
7
- data.tar.gz: f6c64ac247cada2b4099385e77b2e86b953f60d4250a01f2907ff811b92d10d50628ffeb0c1f8921bef5900be3f46bec18f664276e03441e8af7ae7183965f28
6
+ metadata.gz: c107cb11e05e15e635d4fd8e6c8ba04389a2fd70a1e0f03e4f468d61d8bb01b5b45083a9f162c2e0221359fefef14fa96f02f78af32b74a074fb7f673fceb0a1
7
+ data.tar.gz: 7f7e4305c1c2ec88e81245d3402f27f5ae1590b87ddfa45932cc19dfcf8c4d3d6d9d6326cbf6e03941194e71ceb65922bf85ca15f5dce6d1abc97293295ac6d5
File without changes
data/README.md CHANGED
@@ -7,7 +7,7 @@ Generate a lot of questions from an _input file_ base on your own _definitions_.
7
7
 
8
8
  ASKER helps trainers to create a huge amount of questions, from a definitions (_conceptual entities_) input file.
9
9
 
10
- * Free Software [LICENSE](https://github.com/dvarrui/asker/blob/devel/LICENSE).
10
+ * Free Software [LICENSE](https://github.com/dvarrui/asker/blob/devel/LICENSE.txt).
11
11
  * Multiplatform.
12
12
  * Ruby program.
13
13
 
@@ -25,14 +25,13 @@ Steps:
25
25
  1. Create an input file with your definitions (_conceptual entities_).
26
26
  1. Run _asker_ and get the results into `output` directory.
27
27
 
28
- Run `asker` with our example input file as argument (`jedi.haml`):
28
+ Example: Running `asker` with our example input file as argument (`jedi.haml`):
29
29
 
30
30
  ```
31
31
  asker docs/examples/starwars/jedi.haml
32
32
  ```
33
33
 
34
34
  * Output files created into the `output` folder.
35
- * This example use an example input definition file `docs/examples/starwars/jedi.haml`, with concepts about _"Jedi's"_. ;-)
36
35
  * More [example input files](https://github.com/dvarrui/asker/tree/devel/docs/examples).
37
36
  * More asker input files at `github/dvarrui/asker-inputs` repository.
38
37
 
data/bin/asker CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/ruby
2
2
  require 'asker/cli'
3
+
3
4
  # Start Asker command line interface
4
5
  CLI.start(ARGV)
data/lib/asker.rb CHANGED
@@ -17,8 +17,14 @@ class Asker
17
17
  ##
18
18
  # Create asker input demo files
19
19
  # @param dirpath (String)
20
- def self.create_skeleton(dirpath)
21
- Skeleton.create(dirpath)
20
+ def self.create_input(dirpath)
21
+ Skeleton.create_input(dirpath)
22
+ end
23
+
24
+ ##
25
+ # Create asker configuration files
26
+ def self.create_configuration
27
+ Skeleton.create_configuration
22
28
  end
23
29
 
24
30
  ##
@@ -33,7 +39,7 @@ class Asker
33
39
  # @param filepath (String) HAML or XML filepath
34
40
  def self.start(filepath)
35
41
  project, data = load_input(filepath)
36
- ConceptDisplayer.show(data[:concepts], project.get(:show_mode))
42
+ ConceptDisplayer.show(data[:concepts])
37
43
  create_output(project, data)
38
44
  end
39
45
 
@@ -50,7 +56,6 @@ class Asker
50
56
  ##
51
57
  # Create output files: Gift, YAML, TXT Doc
52
58
  # rubocop:disable Metrics/AbcSize
53
- # rubocop:disable Metrics/MethodLength
54
59
  private_class_method def self.create_output(project, data)
55
60
  Logger.verbose "\n[INFO] Creating output files"
56
61
  Logger.verbose ' ├── Gift questions file => ' +
@@ -60,9 +65,8 @@ class Asker
60
65
  Logger.verbose ' └── Lesson file => ' +
61
66
  Rainbow(project.get(:lessonpath)).bright
62
67
  OutputFileExporter.export(data, project)
63
- StatsDisplayer.show(data, project.get(:show_mode))
68
+ StatsDisplayer.show(data)
64
69
  project.close # Logger use Project.get(:logfile) until the end
65
70
  end
66
71
  # rubocop:enable Metrics/AbcSize
67
- # rubocop:enable Metrics/MethodLength
68
72
  end
data/lib/asker/ai/ai.rb CHANGED
@@ -46,6 +46,8 @@ module AI
46
46
  end
47
47
  end
48
48
 
49
+ # rubocop:disable Metrics/AbcSize
50
+ # rubocop:disable Metrics/MethodLength
49
51
  def exclude_questions
50
52
  param = Application.instance.config['questions']['exclude']
51
53
  return if param.nil?
@@ -61,6 +63,8 @@ module AI
61
63
  @questions = input
62
64
  @excluded_questions = output
63
65
  end
66
+ # rubocop:enable Metrics/AbcSize
67
+ # rubocop:enable Metrics/MethodLength
64
68
 
65
69
  def string_has_this_tags?(input, tags)
66
70
  flag = false
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative '../../lang/lang_factory'
4
+ require_relative '../../ai/question'
5
+
6
+ ##
7
+ # BaseCodeAI class
8
+ class BaseCodeAI
9
+ attr_reader :questions
10
+
11
+ ##
12
+ # Create CodeAI object from Code data
13
+ # @param code (Code)
14
+ def initialize(code)
15
+ @code = code
16
+ @lines = code.lines
17
+ @num = 0
18
+ @questions = []
19
+ make_questions
20
+ end
21
+
22
+ ##
23
+ # Return the name of code
24
+ # @return String
25
+ def name
26
+ File.basename(@code.filename)
27
+ end
28
+
29
+ def process?
30
+ @code.process?
31
+ end
32
+
33
+ def type
34
+ @code.type
35
+ end
36
+
37
+ def filename
38
+ @code.filename
39
+ end
40
+
41
+ def lines
42
+ @code.lines
43
+ end
44
+
45
+ ##
46
+ # Counter
47
+ # @return count
48
+ def num
49
+ @num += 1
50
+ end
51
+
52
+ ##
53
+ # Clone array
54
+ # @param array (Array)
55
+ # @return Array
56
+ def clone_array(array)
57
+ out = []
58
+ array.each { |item| out << item.dup }
59
+ out
60
+ end
61
+
62
+ ##
63
+ # Convert an array of lines into one String
64
+ # @param lines (Array)
65
+ # @return String
66
+ # rubocop:disable Style/FormatString
67
+ def lines_to_s(lines)
68
+ out = ''
69
+ lines.each_with_index do |line, index|
70
+ out << "%2d: #{line}\n" % (index + 1)
71
+ end
72
+ out
73
+ end
74
+
75
+ ##
76
+ # Convert an array of lines into one HTML String
77
+ # @param lines (Array)
78
+ # @return String
79
+ def lines_to_html(lines)
80
+ out = ''
81
+ lines.each_with_index do |line, index|
82
+ out << "%2d: #{line}</br>" % (index + 1)
83
+ end
84
+ out
85
+ end
86
+ # rubocop:enable Style/FormatString
87
+
88
+ ##
89
+ # Make questions
90
+ def make_questions
91
+ list = find_make_methods
92
+ list.each { |m| @questions += send m }
93
+ @questions
94
+ end
95
+
96
+ private
97
+
98
+ def find_make_methods
99
+ list = public_methods.sort
100
+ list.select! { |name| name.to_s.start_with? 'make_' }
101
+ list.delete(:make_questions)
102
+ list
103
+ end
104
+ end
@@ -1,15 +1,25 @@
1
1
 
2
+ require 'rainbow'
2
3
  require_relative 'javascript_code_ai'
4
+ require_relative 'problem_code_ai'
3
5
  require_relative 'python_code_ai'
4
6
  require_relative 'ruby_code_ai'
5
7
  require_relative 'sql_code_ai'
6
8
 
9
+ ##
10
+ # CodeAI factory
7
11
  module CodeAIFactory
12
+ ##
13
+ # Return CodeAI associated to Code.type
14
+ # @param code (Code)
15
+ # @return CodeAI
8
16
  def self.get(code)
9
17
  type = code.type
10
18
  case type
11
19
  when :javascript
12
20
  return JavascriptCodeAI.new(code)
21
+ when :problem
22
+ return ProblemCodeAI.new(code)
13
23
  when :python
14
24
  return PythonCodeAI.new(code)
15
25
  when :ruby
@@ -19,7 +29,7 @@ module CodeAIFactory
19
29
  when :vagrantfile
20
30
  return RubyCodeAI.new(code)
21
31
  else
22
- puts "[ERROR] <#{type}> is not valid type"
32
+ puts Rainbow("[ERROR] <#{type}> is not valid type").red.bright
23
33
  end
24
34
  nil
25
35
  end
@@ -4,12 +4,9 @@ require_relative '../../ai/question'
4
4
  require_relative 'base_code_ai'
5
5
 
6
6
  class JavascriptCodeAI < BaseCodeAI
7
- def initialize(data_object)
8
- @data_object = data_object
9
- @lines = data_object.lines
7
+ def initialize(code)
10
8
  @lang = LangFactory.instance.get('javascript')
11
- @num = 0
12
- @questions = []
9
+ super code
13
10
  end
14
11
 
15
12
  def make_comment_error
@@ -0,0 +1,176 @@
1
+
2
+ require_relative '../../lang/lang_factory'
3
+ require_relative '../../ai/question'
4
+ require_relative 'base_code_ai'
5
+
6
+ ##
7
+ # Class for RubyCodeAI objects
8
+ class ProblemCodeAI < BaseCodeAI
9
+ def initialize(code)
10
+ @reduce = 1
11
+ @reduce = 4 if code.lines.size > 25
12
+ @lang = LangFactory.instance.get('es')
13
+ super code
14
+ end
15
+
16
+ ##
17
+ # Make errors about comments
18
+ def make_comment_error
19
+ questions = []
20
+ error_lines = []
21
+ @lines.each_with_index do |line,index|
22
+ if line.strip.start_with?('#')
23
+ lines = clone_array @lines
24
+ lines[index].sub!('#','').strip!
25
+
26
+ q = Question.new(:short)
27
+ q.name = "#{name}-#{num}-uncomment"
28
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
29
+ q.shorts << (index+1)
30
+ q.feedback = 'Comment symbol removed'
31
+ questions << q
32
+ elsif line.strip.size>0
33
+ lines = clone_array @lines
34
+ lines[index]='# ' + lines[index]
35
+
36
+ q = Question.new(:short)
37
+ q.name = "#{name}-#{num}-comment"
38
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
39
+ q.shorts << (index+1)
40
+ q.feedback = 'Comment symbol added'
41
+ questions << q
42
+ end
43
+ end
44
+ questions.shuffle[0,@lines.size/@reduce]
45
+ end
46
+
47
+ ##
48
+ # Make questions without errors
49
+ def make_no_error_changes
50
+ questions = []
51
+ empty_lines = []
52
+ used_lines = []
53
+ @lines.each_with_index do |line,index|
54
+ if line.strip.size.zero?
55
+ empty_lines << index
56
+ else
57
+ used_lines << index
58
+ end
59
+ end
60
+
61
+ used_lines.each do |index|
62
+ lines = clone_array(@lines)
63
+ lines.insert(index, ' ' * (rand(4).to_i + 1))
64
+ if @lines.size < 4 || rand(2) == 0
65
+ q = Question.new(:short)
66
+ q.name = "#{name}-#{num}-codeok"
67
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
68
+ q.shorts << '0'
69
+ q.feedback = 'Code is OK'
70
+ questions << q
71
+ else
72
+ q = Question.new(:choice)
73
+ q.name = "#{name}-#{num}-codeok"
74
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
75
+ others = (1..@lines.size).to_a.shuffle!
76
+ q.good = '0'
77
+ q.bads << others[0].to_s
78
+ q.bads << others[1].to_s
79
+ q.bads << others[2].to_s
80
+ q.feedback = 'Code is OK'
81
+ end
82
+ end
83
+
84
+ questions.shuffle[0,@lines.size/@reduce]
85
+ end
86
+
87
+ ##
88
+ # Make questions with syntax errors
89
+ def make_syntax_error
90
+ questions = []
91
+
92
+ @lang.mistakes.each_pair do |key,values|
93
+ error_lines = []
94
+ @lines.each_with_index do |line,index|
95
+ error_lines << index if line.include?(key.to_s)
96
+ end
97
+
98
+ v = values.split(',')
99
+ v.each do |value|
100
+ error_lines.each do |index|
101
+ lines = clone_array(@lines)
102
+ lines[index].sub!(key.to_s, value)
103
+ if @lines.size < 4 || rand(2) == 0
104
+ q = Question.new(:short)
105
+ q.name = "#{name}-#{num}-syntaxerror"
106
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
107
+ q.shorts << (index+1)
108
+ q.feedback = "Syntax error: '#{value}' must be '#{key}'"
109
+ else
110
+ q = Question.new(:choice)
111
+ q.name = "#{name}-#{num}-syntaxerror"
112
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
113
+ others = (1..@lines.size).to_a.shuffle!
114
+ others.delete(index+1)
115
+ q.good = (index + 1).to_s
116
+ q.bads << others[0].to_s
117
+ q.bads << others[1].to_s
118
+ q.bads << others[2].to_s
119
+ q.feedback = "Syntax error: '#{value}' must be '#{key}'"
120
+ end
121
+ questions << q
122
+ end
123
+ end
124
+ end
125
+ questions.shuffle[0,@lines.size/@reduce]
126
+ end
127
+
128
+ ##
129
+ # Make questions with variable errors
130
+ def make_variable_error
131
+ questions = []
132
+ error_lines = []
133
+ @lines.each_with_index do |line, index|
134
+ # Search Variable assignment
135
+ m = /\s*(\w*)\s*\=\w*/.match(line)
136
+ i = []
137
+ unless m.nil?
138
+ varname = (m.values_at 1)[0]
139
+ # Search used Variable
140
+ @lines.each_with_index do |line2, index2|
141
+ next if index >= index2
142
+ i << index2 if line2.include?(varname)
143
+ end
144
+ end
145
+ next if i.size == 0
146
+ i.shuffle!
147
+ i.each do |k|
148
+ lines = clone_array @lines
149
+ temp = lines[index]
150
+ lines[index] = lines[k]
151
+ lines[k] = temp
152
+
153
+ if rand(2) == 0
154
+ q = Question.new(:short)
155
+ q.name = "#{name}-#{num}-variable"
156
+ q.text = @lang.text_for(:code1, lines_to_html(lines))
157
+ q.shorts << (index + 1)
158
+ q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
159
+ else
160
+ q = Question.new(:choice)
161
+ q.name = "#{name}-#{num}-variable"
162
+ q.text = @lang.text_for(:code2, lines_to_html(lines))
163
+ others = (1..@lines.size).to_a.shuffle!
164
+ others.delete(index+1)
165
+ q.good = (index + 1).to_s
166
+ q.bads << others[0].to_s
167
+ q.bads << others[1].to_s
168
+ q.bads << others[2].to_s
169
+ q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
170
+ end
171
+ questions << q
172
+ end
173
+ end
174
+ questions.shuffle[0,@lines.size/@reduce]
175
+ end
176
+ end
@@ -4,12 +4,9 @@ require_relative '../../ai/question'
4
4
  require_relative 'base_code_ai'
5
5
 
6
6
  class PythonCodeAI < BaseCodeAI
7
- def initialize(data_object)
8
- @data_object = data_object
9
- @lines = data_object.lines
7
+ def initialize(code)
10
8
  @lang = LangFactory.instance.get('python')
11
- @num = 0
12
- @questions = []
9
+ super code
13
10
  end
14
11
 
15
12
  def make_comment_error