asker-tool 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
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