asker-tool 2.1.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 (91) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +53 -0
  4. data/bin/asker +4 -0
  5. data/docs/changelog/v2.1.md +99 -0
  6. data/docs/commands.md +15 -0
  7. data/docs/contributions.md +18 -0
  8. data/docs/history.md +40 -0
  9. data/docs/idea.md +44 -0
  10. data/docs/inputs/README.md +39 -0
  11. data/docs/inputs/code.md +69 -0
  12. data/docs/inputs/concepts.md +142 -0
  13. data/docs/inputs/jedi.md +68 -0
  14. data/docs/inputs/tables.md +112 -0
  15. data/docs/inputs/templates.md +87 -0
  16. data/docs/install/README.md +38 -0
  17. data/docs/install/manual.md +26 -0
  18. data/docs/install/scripts.md +26 -0
  19. data/docs/revise/asker-file.md +41 -0
  20. data/docs/revise/buenas-practicas/01-convocatoria.md +30 -0
  21. data/docs/revise/buenas-practicas/02-formulario.md +35 -0
  22. data/docs/revise/buenas-practicas/03-descripcion.md +63 -0
  23. data/docs/revise/buenas-practicas/04-resultados.md +17 -0
  24. data/docs/revise/buenas-practicas/05-reproducir.md +10 -0
  25. data/docs/revise/ejemplos/01/README.md +27 -0
  26. data/docs/revise/ejemplos/02/README.md +31 -0
  27. data/docs/revise/ejemplos/03/README.md +31 -0
  28. data/docs/revise/ejemplos/04/README.md +37 -0
  29. data/docs/revise/ejemplos/05/README.md +25 -0
  30. data/docs/revise/ejemplos/06/README.md +43 -0
  31. data/docs/revise/ejemplos/README.md +11 -0
  32. data/docs/revise/projects.md +74 -0
  33. data/lib/asker.rb +103 -0
  34. data/lib/asker/ai/ai.rb +70 -0
  35. data/lib/asker/ai/ai_calculate.rb +55 -0
  36. data/lib/asker/ai/concept_ai.rb +49 -0
  37. data/lib/asker/ai/question.rb +58 -0
  38. data/lib/asker/ai/stages/base_stage.rb +16 -0
  39. data/lib/asker/ai/stages/main.rb +8 -0
  40. data/lib/asker/ai/stages/stage_b.rb +87 -0
  41. data/lib/asker/ai/stages/stage_d.rb +160 -0
  42. data/lib/asker/ai/stages/stage_f.rb +156 -0
  43. data/lib/asker/ai/stages/stage_i.rb +140 -0
  44. data/lib/asker/ai/stages/stage_s.rb +52 -0
  45. data/lib/asker/ai/stages/stage_t.rb +170 -0
  46. data/lib/asker/application.rb +30 -0
  47. data/lib/asker/checker.rb +356 -0
  48. data/lib/asker/cli.rb +85 -0
  49. data/lib/asker/code/ai/base_code_ai.rb +48 -0
  50. data/lib/asker/code/ai/code_ai_factory.rb +26 -0
  51. data/lib/asker/code/ai/javascript_code_ai.rb +167 -0
  52. data/lib/asker/code/ai/python_code_ai.rb +167 -0
  53. data/lib/asker/code/ai/ruby_code_ai.rb +169 -0
  54. data/lib/asker/code/ai/sql_code_ai.rb +69 -0
  55. data/lib/asker/code/code.rb +53 -0
  56. data/lib/asker/data/column.rb +62 -0
  57. data/lib/asker/data/concept.rb +183 -0
  58. data/lib/asker/data/data_field.rb +87 -0
  59. data/lib/asker/data/row.rb +93 -0
  60. data/lib/asker/data/table.rb +96 -0
  61. data/lib/asker/data/template.rb +65 -0
  62. data/lib/asker/data/world.rb +53 -0
  63. data/lib/asker/exporter/code_gift_exporter.rb +35 -0
  64. data/lib/asker/exporter/code_screen_exporter.rb +45 -0
  65. data/lib/asker/exporter/concept_ai_gift_exporter.rb +33 -0
  66. data/lib/asker/exporter/concept_ai_screen_exporter.rb +115 -0
  67. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +33 -0
  68. data/lib/asker/exporter/concept_doc_exporter.rb +21 -0
  69. data/lib/asker/exporter/concept_screen_exporter.rb +25 -0
  70. data/lib/asker/exporter/main.rb +9 -0
  71. data/lib/asker/files/config.ini +40 -0
  72. data/lib/asker/formatter/code_string_formatter.rb +16 -0
  73. data/lib/asker/formatter/concept_doc_formatter.rb +37 -0
  74. data/lib/asker/formatter/concept_string_formatter.rb +66 -0
  75. data/lib/asker/formatter/question_gift_formatter.rb +65 -0
  76. data/lib/asker/formatter/question_hash_formatter.rb +40 -0
  77. data/lib/asker/formatter/question_moodlexml_formatter.rb +71 -0
  78. data/lib/asker/formatter/rb2haml_formatter.rb +26 -0
  79. data/lib/asker/lang/lang.rb +42 -0
  80. data/lib/asker/lang/lang_factory.rb +19 -0
  81. data/lib/asker/lang/text_actions.rb +150 -0
  82. data/lib/asker/loader/code_loader.rb +53 -0
  83. data/lib/asker/loader/content_loader.rb +101 -0
  84. data/lib/asker/loader/directory_loader.rb +58 -0
  85. data/lib/asker/loader/file_loader.rb +33 -0
  86. data/lib/asker/loader/image_url_loader.rb +61 -0
  87. data/lib/asker/loader/input_loader.rb +24 -0
  88. data/lib/asker/loader/project_loader.rb +71 -0
  89. data/lib/asker/logger.rb +21 -0
  90. data/lib/asker/project.rb +170 -0
  91. metadata +261 -0
@@ -0,0 +1,48 @@
1
+
2
+ require_relative '../../lang/lang_factory'
3
+ require_relative '../../ai/question'
4
+
5
+ class BaseCodeAI
6
+ def name
7
+ File.basename(@data_object.filename)
8
+ end
9
+
10
+ def num
11
+ @num += 1
12
+ end
13
+
14
+ def clone_array(array)
15
+ out = []
16
+ array.each { |item| out << item.dup }
17
+ out
18
+ end
19
+
20
+ def lines_to_s(lines)
21
+ out = ''
22
+ lines.each_with_index do |line,index|
23
+ out << "%2d: #{line}\n"%(index+1)
24
+ end
25
+ out
26
+ end
27
+
28
+ def lines_to_html(lines)
29
+ out = ''
30
+ lines.each_with_index do |line,index|
31
+ out << "%2d: #{line}</br>"%(index+1)
32
+ end
33
+ out
34
+ end
35
+
36
+ def find_make_methods
37
+ list = self.public_methods.sort
38
+ list.select! { |name| name.to_s.start_with? 'make_'}
39
+ list.delete(:make_questions)
40
+ list
41
+ end
42
+
43
+ def make_questions
44
+ list = find_make_methods
45
+ list.each { |m| @questions += self.send m }
46
+ @questions
47
+ end
48
+ end
@@ -0,0 +1,26 @@
1
+
2
+ require_relative 'javascript_code_ai'
3
+ require_relative 'python_code_ai'
4
+ require_relative 'ruby_code_ai'
5
+ require_relative 'sql_code_ai'
6
+
7
+ module CodeAIFactory
8
+ def self.get(code)
9
+ type = code.type
10
+ case type
11
+ when :javascript
12
+ return JavascriptCodeAI.new(code)
13
+ when :python
14
+ return PythonCodeAI.new(code)
15
+ when :ruby
16
+ return RubyCodeAI.new(code)
17
+ when :sql
18
+ return SQLCodeAI.new(code)
19
+ when :vagrantfile
20
+ return RubyCodeAI.new(code)
21
+ else
22
+ puts "[ERROR] <#{type}> is not valid type"
23
+ end
24
+ nil
25
+ end
26
+ end
@@ -0,0 +1,167 @@
1
+
2
+ require_relative '../../lang/lang_factory'
3
+ require_relative '../../ai/question'
4
+ require_relative 'base_code_ai'
5
+
6
+ class JavascriptCodeAI < BaseCodeAI
7
+ def initialize(data_object)
8
+ @data_object = data_object
9
+ @lines = data_object.lines
10
+ @lang = LangFactory.instance.get('javascript')
11
+ @num = 0
12
+ @questions = []
13
+ end
14
+
15
+ def make_comment_error
16
+ questions = []
17
+ error_lines = []
18
+ @lines.each_with_index do |line,index|
19
+ if line.strip.start_with?('//')
20
+ lines = clone_array @lines
21
+ lines[index].sub!('//','').strip!
22
+
23
+ q = Question.new(:short)
24
+ q.name = "#{name}-#{num}-uncomment"
25
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
26
+ q.shorts << (index+1)
27
+ q.feedback = 'Comment symbol removed'
28
+ questions << q
29
+ elsif line.strip.size>0
30
+ lines = clone_array @lines
31
+ lines[index]='// ' + lines[index]
32
+
33
+ q = Question.new(:short)
34
+ q.name = "#{name}-#{num}-comment"
35
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
36
+ q.shorts << (index+1)
37
+ q.feedback = 'Comment symbol added'
38
+ questions << q
39
+ end
40
+ end
41
+ questions
42
+ end
43
+
44
+ def make_no_error_changes
45
+ questions = []
46
+ empty_lines = []
47
+ used_lines = []
48
+ @lines.each_with_index do |line,index|
49
+ if line.strip.size.zero?
50
+ empty_lines << index
51
+ else
52
+ used_lines << index
53
+ end
54
+ end
55
+
56
+ used_lines.each do |index|
57
+ lines = clone_array(@lines)
58
+ lines.insert(index, ' ' * (rand(4).to_i + 1))
59
+ if @lines.size < 4 || rand(2) == 0
60
+ q = Question.new(:short)
61
+ q.name = "#{name}-#{num}-codeok"
62
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
63
+ q.shorts << '0'
64
+ q.feedback = 'Code is OK'
65
+ questions << q
66
+ else
67
+ q = Question.new(:choice)
68
+ q.name = "#{name}-#{num}-codeok"
69
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
70
+ others = (1..@lines.size).to_a.shuffle!
71
+ q.good = '0'
72
+ q.bads << others[0].to_s
73
+ q.bads << others[1].to_s
74
+ q.bads << others[2].to_s
75
+ q.feedback = 'Code is OK'
76
+ end
77
+ end
78
+
79
+ questions
80
+ end
81
+
82
+ def make_syntax_error
83
+ questions = []
84
+
85
+ @lang.mistakes.each_pair do |key,values|
86
+ error_lines = []
87
+ @lines.each_with_index do |line,index|
88
+ error_lines << index if line.include?(key.to_s)
89
+ end
90
+
91
+ v = values.split(',')
92
+ v.each do |value|
93
+ error_lines.each do |index|
94
+ lines = clone_array(@lines)
95
+ lines[index].sub!(key.to_s, value)
96
+ if @lines.size < 4 || rand(2) == 0
97
+ q = Question.new(:short)
98
+ q.name = "#{name}-#{num}-syntaxerror"
99
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
100
+ q.shorts << (index+1)
101
+ q.feedback = "Syntax error: '#{value}' must be '#{key}'"
102
+ else
103
+ q = Question.new(:choice)
104
+ q.name = "#{name}-#{num}-syntaxerror"
105
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
106
+ others = (1..@lines.size).to_a.shuffle!
107
+ others.delete(index+1)
108
+ q.good = (index + 1).to_s
109
+ q.bads << others[0].to_s
110
+ q.bads << others[1].to_s
111
+ q.bads << others[2].to_s
112
+ q.feedback = "Syntax error: '#{value}' must be '#{key}'"
113
+ end
114
+ questions << q
115
+ end
116
+ end
117
+ end
118
+ questions
119
+ end
120
+
121
+ def make_variable_error
122
+ questions = []
123
+ error_lines = []
124
+ @lines.each_with_index do |line, index|
125
+ # Search Variable assignment
126
+ m = /var\s*(\w*);\s*\w*/.match(line)
127
+ i = []
128
+ unless m.nil?
129
+ varname = (m.values_at 1)[0]
130
+ # Search used Variable
131
+ @lines.each_with_index do |line2, index2|
132
+ next if index >= index2
133
+ i << index2 if line2.include?(varname)
134
+ end
135
+ end
136
+ next if i.size == 0
137
+ i.shuffle!
138
+ i.each do |k|
139
+ lines = clone_array @lines
140
+ temp = lines[index]
141
+ lines[index] = lines[k]
142
+ lines[k] = temp
143
+
144
+ if rand(2) == 0
145
+ q = Question.new(:short)
146
+ q.name = "#{name}-#{num}-variable"
147
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
148
+ q.shorts << (index + 1)
149
+ q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
150
+ else
151
+ q = Question.new(:choice)
152
+ q.name = "#{name}-#{num}-variable"
153
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
154
+ others = (1..@lines.size).to_a.shuffle!
155
+ others.delete(index+1)
156
+ q.good = (index + 1).to_s
157
+ q.bads << others[0].to_s
158
+ q.bads << others[1].to_s
159
+ q.bads << others[2].to_s
160
+ q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
161
+ end
162
+ questions << q
163
+ end
164
+ end
165
+ questions
166
+ end
167
+ end
@@ -0,0 +1,167 @@
1
+
2
+ require_relative '../../lang/lang_factory'
3
+ require_relative '../../ai/question'
4
+ require_relative 'base_code_ai'
5
+
6
+ class PythonCodeAI < BaseCodeAI
7
+ def initialize(data_object)
8
+ @data_object = data_object
9
+ @lines = data_object.lines
10
+ @lang = LangFactory.instance.get('python')
11
+ @num = 0
12
+ @questions = []
13
+ end
14
+
15
+ def make_comment_error
16
+ questions = []
17
+ error_lines = []
18
+ @lines.each_with_index do |line,index|
19
+ if line.strip.start_with?('#')
20
+ lines = clone_array @lines
21
+ lines[index].sub!('#','').strip!
22
+
23
+ q = Question.new(:short)
24
+ q.name = "#{name}-#{num}-uncomment"
25
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
26
+ q.shorts << (index+1)
27
+ q.feedback = 'Comment symbol removed'
28
+ questions << q
29
+ elsif line.strip.size>0
30
+ lines = clone_array @lines
31
+ lines[index]='# ' + lines[index]
32
+
33
+ q = Question.new(:short)
34
+ q.name = "#{name}-#{num}-comment"
35
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
36
+ q.shorts << (index+1)
37
+ q.feedback = 'Comment symbol added'
38
+ questions << q
39
+ end
40
+ end
41
+ questions
42
+ end
43
+
44
+ def make_no_error_changes
45
+ questions = []
46
+ empty_lines = []
47
+ used_lines = []
48
+ @lines.each_with_index do |line,index|
49
+ if line.strip.size.zero?
50
+ empty_lines << index
51
+ else
52
+ used_lines << index
53
+ end
54
+ end
55
+
56
+ used_lines.each do |index|
57
+ lines = clone_array(@lines)
58
+ lines.insert(index, ' ' * (rand(4).to_i + 1))
59
+ if @lines.size < 4 || rand(2) == 0
60
+ q = Question.new(:short)
61
+ q.name = "#{name}-#{num}-codeok"
62
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
63
+ q.shorts << '0'
64
+ q.feedback = 'Code is OK'
65
+ questions << q
66
+ else
67
+ q = Question.new(:choice)
68
+ q.name = "#{name}-#{num}-codeok"
69
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
70
+ others = (1..@lines.size).to_a.shuffle!
71
+ q.good = '0'
72
+ q.bads << others[0].to_s
73
+ q.bads << others[1].to_s
74
+ q.bads << others[2].to_s
75
+ q.feedback = 'Code is OK'
76
+ end
77
+ end
78
+
79
+ questions
80
+ end
81
+
82
+ def make_syntax_error
83
+ questions = []
84
+
85
+ @lang.mistakes.each_pair do |key,values|
86
+ error_lines = []
87
+ @lines.each_with_index do |line,index|
88
+ error_lines << index if line.include?(key.to_s)
89
+ end
90
+
91
+ v = values.split(',')
92
+ v.each do |value|
93
+ error_lines.each do |index|
94
+ lines = clone_array(@lines)
95
+ lines[index].sub!(key.to_s, value)
96
+ if @lines.size < 4 || rand(2) == 0
97
+ q = Question.new(:short)
98
+ q.name = "#{name}-#{num}-syntaxerror"
99
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
100
+ q.shorts << (index+1)
101
+ q.feedback = "Syntax error: '#{value}' must be '#{key}'"
102
+ else
103
+ q = Question.new(:choice)
104
+ q.name = "#{name}-#{num}-syntaxerror"
105
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
106
+ others = (1..@lines.size).to_a.shuffle!
107
+ others.delete(index+1)
108
+ q.good = (index + 1).to_s
109
+ q.bads << others[0].to_s
110
+ q.bads << others[1].to_s
111
+ q.bads << others[2].to_s
112
+ q.feedback = "Syntax error: '#{value}' must be '#{key}'"
113
+ end
114
+ questions << q
115
+ end
116
+ end
117
+ end
118
+ questions
119
+ end
120
+
121
+ def make_variable_error
122
+ questions = []
123
+ error_lines = []
124
+ @lines.each_with_index do |line, index|
125
+ # Search Variable assignment
126
+ m = /\s*(\w*)\s*\=\w*/.match(line)
127
+ i = []
128
+ unless m.nil?
129
+ varname = (m.values_at 1)[0]
130
+ # Search used Variable
131
+ @lines.each_with_index do |line2, index2|
132
+ next if index >= index2
133
+ i << index2 if line2.include?(varname)
134
+ end
135
+ end
136
+ next if i.size == 0
137
+ i.shuffle!
138
+ i.each do |k|
139
+ lines = clone_array @lines
140
+ temp = lines[index]
141
+ lines[index] = lines[k]
142
+ lines[k] = temp
143
+
144
+ if rand(2) == 0
145
+ q = Question.new(:short)
146
+ q.name = "#{name}-#{num}-variable"
147
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
148
+ q.shorts << (index + 1)
149
+ q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
150
+ else
151
+ q = Question.new(:choice)
152
+ q.name = "#{name}-#{num}-variable"
153
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
154
+ others = (1..@lines.size).to_a.shuffle!
155
+ others.delete(index+1)
156
+ q.good = (index + 1).to_s
157
+ q.bads << others[0].to_s
158
+ q.bads << others[1].to_s
159
+ q.bads << others[2].to_s
160
+ q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
161
+ end
162
+ questions << q
163
+ end
164
+ end
165
+ questions
166
+ end
167
+ end
@@ -0,0 +1,169 @@
1
+
2
+ require_relative '../../lang/lang_factory'
3
+ require_relative '../../ai/question'
4
+ require_relative 'base_code_ai'
5
+
6
+ class RubyCodeAI < BaseCodeAI
7
+ def initialize(data_object)
8
+ @data_object = data_object
9
+ @lines = data_object.lines
10
+ @lang = LangFactory.instance.get('ruby')
11
+ @num = 0
12
+ @questions = []
13
+ @reduce = 1
14
+ @reduce = 4 if @lines.size > 25
15
+ end
16
+
17
+ def make_comment_error
18
+ questions = []
19
+ error_lines = []
20
+ @lines.each_with_index do |line,index|
21
+ if line.strip.start_with?('#')
22
+ lines = clone_array @lines
23
+ lines[index].sub!('#','').strip!
24
+
25
+ q = Question.new(:short)
26
+ q.name = "#{name}-#{num}-uncomment"
27
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
28
+ q.shorts << (index+1)
29
+ q.feedback = 'Comment symbol removed'
30
+ questions << q
31
+ elsif line.strip.size>0
32
+ lines = clone_array @lines
33
+ lines[index]='# ' + lines[index]
34
+
35
+ q = Question.new(:short)
36
+ q.name = "#{name}-#{num}-comment"
37
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
38
+ q.shorts << (index+1)
39
+ q.feedback = 'Comment symbol added'
40
+ questions << q
41
+ end
42
+ end
43
+ questions.shuffle[0,@lines.size/@reduce]
44
+ end
45
+
46
+ def make_no_error_changes
47
+ questions = []
48
+ empty_lines = []
49
+ used_lines = []
50
+ @lines.each_with_index do |line,index|
51
+ if line.strip.size.zero?
52
+ empty_lines << index
53
+ else
54
+ used_lines << index
55
+ end
56
+ end
57
+
58
+ used_lines.each do |index|
59
+ lines = clone_array(@lines)
60
+ lines.insert(index, ' ' * (rand(4).to_i + 1))
61
+ if @lines.size < 4 || rand(2) == 0
62
+ q = Question.new(:short)
63
+ q.name = "#{name}-#{num}-codeok"
64
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
65
+ q.shorts << '0'
66
+ q.feedback = 'Code is OK'
67
+ questions << q
68
+ else
69
+ q = Question.new(:choice)
70
+ q.name = "#{name}-#{num}-codeok"
71
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
72
+ others = (1..@lines.size).to_a.shuffle!
73
+ q.good = '0'
74
+ q.bads << others[0].to_s
75
+ q.bads << others[1].to_s
76
+ q.bads << others[2].to_s
77
+ q.feedback = 'Code is OK'
78
+ end
79
+ end
80
+
81
+ questions.shuffle[0,@lines.size/@reduce]
82
+ end
83
+
84
+ def make_syntax_error
85
+ questions = []
86
+
87
+ @lang.mistakes.each_pair do |key,values|
88
+ error_lines = []
89
+ @lines.each_with_index do |line,index|
90
+ error_lines << index if line.include?(key.to_s)
91
+ end
92
+
93
+ v = values.split(',')
94
+ v.each do |value|
95
+ error_lines.each do |index|
96
+ lines = clone_array(@lines)
97
+ lines[index].sub!(key.to_s, value)
98
+ if @lines.size < 4 || rand(2) == 0
99
+ q = Question.new(:short)
100
+ q.name = "#{name}-#{num}-syntaxerror"
101
+ q.text = @lang.text_for(:code1,lines_to_html(lines))
102
+ q.shorts << (index+1)
103
+ q.feedback = "Syntax error: '#{value}' must be '#{key}'"
104
+ else
105
+ q = Question.new(:choice)
106
+ q.name = "#{name}-#{num}-syntaxerror"
107
+ q.text = @lang.text_for(:code2,lines_to_html(lines))
108
+ others = (1..@lines.size).to_a.shuffle!
109
+ others.delete(index+1)
110
+ q.good = (index + 1).to_s
111
+ q.bads << others[0].to_s
112
+ q.bads << others[1].to_s
113
+ q.bads << others[2].to_s
114
+ q.feedback = "Syntax error: '#{value}' must be '#{key}'"
115
+ end
116
+ questions << q
117
+ end
118
+ end
119
+ end
120
+ questions.shuffle[0,@lines.size/@reduce]
121
+ end
122
+
123
+ def make_variable_error
124
+ questions = []
125
+ error_lines = []
126
+ @lines.each_with_index do |line, index|
127
+ # Search Variable assignment
128
+ m = /\s*(\w*)\s*\=\w*/.match(line)
129
+ i = []
130
+ unless m.nil?
131
+ varname = (m.values_at 1)[0]
132
+ # Search used Variable
133
+ @lines.each_with_index do |line2, index2|
134
+ next if index >= index2
135
+ i << index2 if line2.include?(varname)
136
+ end
137
+ end
138
+ next if i.size == 0
139
+ i.shuffle!
140
+ i.each do |k|
141
+ lines = clone_array @lines
142
+ temp = lines[index]
143
+ lines[index] = lines[k]
144
+ lines[k] = temp
145
+
146
+ if rand(2) == 0
147
+ q = Question.new(:short)
148
+ q.name = "#{name}-#{num}-variable"
149
+ q.text = @lang.text_for(:code1, lines_to_html(lines))
150
+ q.shorts << (index + 1)
151
+ q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
152
+ else
153
+ q = Question.new(:choice)
154
+ q.name = "#{name}-#{num}-variable"
155
+ q.text = @lang.text_for(:code2, lines_to_html(lines))
156
+ others = (1..@lines.size).to_a.shuffle!
157
+ others.delete(index+1)
158
+ q.good = (index + 1).to_s
159
+ q.bads << others[0].to_s
160
+ q.bads << others[1].to_s
161
+ q.bads << others[2].to_s
162
+ q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
163
+ end
164
+ questions << q
165
+ end
166
+ end
167
+ questions.shuffle[0,@lines.size/@reduce]
168
+ end
169
+ end