asker-tool 2.1.7 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE.txt → LICENSE} +0 -0
  3. data/README.md +1 -1
  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 +11 -2
  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 +100 -50
  11. data/lib/asker/ai/stages/stage_d.rb +75 -90
  12. data/lib/asker/ai/stages/stage_f.rb +64 -36
  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 +8 -7
  17. data/lib/asker/checker.rb +6 -8
  18. data/lib/asker/cli.rb +27 -9
  19. data/lib/asker/data/code.rb +4 -1
  20. data/lib/asker/data/concept.rb +67 -21
  21. data/lib/asker/data/table.rb +2 -0
  22. data/lib/asker/data/template.rb +3 -1
  23. data/lib/asker/data/world.rb +7 -4
  24. data/lib/asker/displayer/code_displayer.rb +7 -0
  25. data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
  26. data/lib/asker/displayer/concept_ai_displayer.rb +23 -22
  27. data/lib/asker/displayer/concept_displayer.rb +9 -4
  28. data/lib/asker/displayer/stats_displayer.rb +8 -0
  29. data/lib/asker/exporter/concept_ai_gift_exporter.rb +7 -11
  30. data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
  31. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +6 -3
  32. data/lib/asker/exporter/concept_doc_exporter.rb +14 -1
  33. data/lib/asker/exporter/data_gift_exporter.rb +29 -0
  34. data/lib/asker/exporter/output_file_exporter.rb +9 -6
  35. data/lib/asker/files/{config.ini → asker.ini} +14 -4
  36. data/lib/asker/files/language/du/connectors.yaml +81 -0
  37. data/lib/asker/files/language/du/mistakes.yaml +82 -0
  38. data/lib/asker/files/language/du/templates.yaml +28 -49
  39. data/lib/asker/files/language/en/templates.yaml +19 -19
  40. data/lib/asker/files/language/es/mistakes.yaml +9 -7
  41. data/lib/asker/files/language/es/templates.yaml +19 -19
  42. data/lib/asker/files/language/fr/connectors.yaml +68 -84
  43. data/lib/asker/files/language/fr/templates.yaml +22 -22
  44. data/lib/asker/formatter/concept_string_formatter.rb +7 -4
  45. data/lib/asker/formatter/moodle/matching.erb +38 -0
  46. data/lib/asker/formatter/moodle/multichoice.erb +49 -0
  47. data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
  48. data/lib/asker/formatter/moodle/truefalse.erb +47 -0
  49. data/lib/asker/formatter/question_gift_formatter.rb +21 -19
  50. data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
  51. data/lib/asker/lang/lang_factory.rb +7 -1
  52. data/lib/asker/loader/code_loader.rb +1 -1
  53. data/lib/asker/loader/content_loader.rb +7 -7
  54. data/lib/asker/loader/directory_loader.rb +3 -3
  55. data/lib/asker/loader/embedded_file.rb +42 -0
  56. data/lib/asker/loader/file_loader.rb +1 -1
  57. data/lib/asker/loader/image_url_loader.rb +4 -3
  58. data/lib/asker/loader/input_loader.rb +1 -1
  59. data/lib/asker/loader/project_loader.rb +14 -5
  60. data/lib/asker/logger.rb +29 -4
  61. data/lib/asker/project.rb +14 -79
  62. data/lib/asker/skeleton.rb +3 -2
  63. data/lib/asker.rb +37 -9
  64. metadata +19 -22
@@ -1,160 +1,145 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'set'
4
4
 
5
5
  require_relative 'base_stage'
6
6
  require_relative '../question'
7
7
 
8
+ # range d1-d4
8
9
  class StageD < BaseStage
9
- # range d1-d4
10
-
10
+ # rubocop:disable Lint/BooleanSymbol
11
+ # rubocop:disable Metrics/MethodLength
12
+ # rubocop:disable Metrics/AbcSize
13
+ # rubocop:disable Metrics/BlockLength
14
+ # rubocop:disable Metrics/CyclomaticComplexity
15
+ # rubocop:disable Metrics/PerceivedComplexity
11
16
  def run
12
17
  # Stage D: process every definition, I mean every <def> tag
13
18
  questions = []
14
- return questions unless type == 'text'
19
+ return questions unless concept.type == 'text'
15
20
 
21
+ lang = concept.lang
16
22
  # for every <text> do this
17
- texts.each do |t|
18
- s=Set.new [name(:raw), lang.text_for(:none)]
19
- neighbors.each { |n| s.add n[:concept].name(:decorated) }
20
- a=s.to_a
23
+ concept.texts.each do |t|
24
+ s = Set.new [name(:raw), lang.text_for(:none)]
25
+ concept.neighbors.each { |n| s.add n[:concept].name(:decorated) }
26
+ a = s.to_a
21
27
 
22
28
  # Question choose between 4 options
23
29
  if s.count > 3
24
- q=Question.new(:choice)
25
- q.name="#{name(:id)}-#{num}-d1choose"
26
- q.text=random_image_for(name(:raw)) + lang.text_for(:d1,t)
27
- q.good=name(:raw)
30
+ q = Question.new(:choice)
31
+ q.name = "#{name(:id)}-#{num}-d1choose"
32
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
33
+ q.good = name(:raw)
28
34
  q.bads << lang.text_for(:none)
29
35
  q.bads << a[2]
30
36
  q.bads << a[3]
31
37
  questions << q
32
38
  end
33
39
 
34
- #Question choose between 4 options, good none (Syntax error)
35
- if s.count>3 and type=="text" then
36
- q=Question.new(:choice)
37
- q.name="#{name(:id)}-#{num}-d1none-misspelled"
38
- q.text=random_image_for(name(:raw)) + lang.text_for(:d1,t)
40
+ # Question choose between 4 options, good none (Syntax error)
41
+ if s.count > 3
42
+ q = Question.new(:choice)
43
+ q.name = "#{name(:id)}-#{num}-d1none-misspelled"
44
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
39
45
  q.good = lang.text_for(:none)
40
46
  q.bads << lang.do_mistake_to(name(:raw))
41
47
  q.bads << a[2]
42
48
  q.bads << a[3]
43
- q.feedback="Option misspelled!: #{name(:raw)}"
49
+ q.feedback = "Option misspelled!: #{name(:raw)}"
44
50
  questions << q
45
51
  end
46
52
 
47
53
  s.delete(name(:raw))
48
- a=s.to_a
54
+ a = s.to_a
49
55
 
50
- #Question choose between 4 options, good none
51
- if s.count>3 then
56
+ # Question choose between 4 options, good none
57
+ if s.count > 3
52
58
  q = Question.new(:choice)
53
- q.name="#{name(:id)}-#{num}-d1none"
54
- q.text=random_image_for(name(:raw)) + lang.text_for(:d1,t)
55
- q.good=lang.text_for(:none)
59
+ q.name = "#{name(:id)}-#{num}-d1none"
60
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d1, t)
61
+ q.good = lang.text_for(:none)
56
62
  q.bads << a[1]
57
63
  q.bads << a[2]
58
64
  q.bads << a[3]
59
65
  questions << q
60
66
  end
61
67
 
62
- #Question boolean => TRUE
63
- #q = Question.new(:boolean)
64
- #q.name="#{name}-#{num}-d2true"
65
- #q.text=random_image_for(name) + lang.text_for(:d2,name,t)
66
- #q.good="TRUE"
67
- #questions << q
68
-
68
+ # Question choice => mispelled
69
69
  q = Question.new(:choice)
70
- q.name="#{name(:id)}-#{num}-d2def-mispelled"
71
- q.text=random_image_for(name(:raw)) + lang.text_for(:d2,name(:decorated), lang.do_mistake_to(t) )
72
- q.good=lang.text_for(:misspelling)
70
+ q.name = "#{name(:id)}-#{num}-d2def-mispelled"
71
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d2, name(:decorated), lang.do_mistake_to(t))
72
+ q.good = lang.text_for(:misspelling)
73
73
  q.bads << lang.text_for(:true)
74
74
  q.bads << lang.text_for(:false)
75
- q.feedback="Definition text mispelled!: #{t}"
75
+ q.feedback = "Definition text mispelled!: #{t}"
76
76
  questions << q
77
77
 
78
- if type=="text"
79
- q = Question.new(:choice)
80
- q.name="#{name(:id)}-#{num}-d2name-mispelled"
81
- q.text=random_image_for(name(:raw)) + lang.text_for(:d2, lang.do_mistake_to(name(:raw)), t)
82
- q.good=lang.text_for(:misspelling)
83
- q.bads << lang.text_for(:true)
84
- q.bads << lang.text_for(:false)
85
- q.feedback="Concept name mispelled!: #{name(:raw)}"
86
- questions << q
87
- end
78
+ # Question choice => name mispelled
79
+ q = Question.new(:choice)
80
+ q.name = "#{name(:id)}-#{num}-d2name-mispelled"
81
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d2, lang.do_mistake_to(name(:raw)), t)
82
+ q.good = lang.text_for(:misspelling)
83
+ q.bads << lang.text_for(:true)
84
+ q.bads << lang.text_for(:false)
85
+ q.feedback = "Concept name mispelled!: #{name(:raw)}"
86
+ questions << q
88
87
 
88
+ # Question choice => true
89
89
  q = Question.new(:choice)
90
- q.name="#{name(:id)}-#{num}-d2true"
91
- q.text=random_image_for(name(:raw)) + lang.text_for(:d2, name(:raw), t )
90
+ q.name = "#{name(:id)}-#{num}-d2true"
91
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d2, name(:raw), t)
92
92
  q.good = lang.text_for(:true)
93
93
  q.bads << lang.text_for(:misspelling)
94
94
  q.bads << lang.text_for(:false)
95
95
  questions << q
96
96
 
97
- if a.size>1 then
97
+ # Question choice => false
98
+ if a.size > 1
98
99
  q = Question.new(:choice)
99
- q.name="#{name(:id)}-#{num}-d2false-misspelled"
100
- q.text=random_image_for(name(:raw)) + lang.text_for(:d2, a[1], t)
100
+ q.name = "#{name(:id)}-#{num}-d2false-misspelled"
101
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d2, a[1], t)
101
102
  q.good = lang.text_for(:false)
102
103
  q.bads << lang.text_for(:misspelling)
103
104
  q.bads << lang.text_for(:true)
104
105
  questions << q
105
106
  end
106
107
 
107
- #Question type <a4desc>: boolean => FALSE
108
- #if neighbors.count>0 then
109
- # q = Question.new(:boolean)
110
- # q.name="#{name}-#{num}-d2false"
111
- # q.text=random_image_for(name) + lang.text_for(:d2, neighbors[0][:concept].name, t)
112
- # q.good="FALSE"
113
- # questions << q
114
- #end
115
-
116
- if type=="text"
117
- #Question hidden name questions
118
- q = Question.new(:short)
119
- q.name="#{name(:id)}-#{num}-d3hidden"
120
- q.text=random_image_for(name(:raw)) + lang.text_for(:d3, lang.hide_text(name(:raw)), t )
121
- q.shorts << name(:raw)
122
- q.shorts << name(:raw).gsub("-"," ").gsub("_"," ")
123
- names.each do |n|
124
- q.shorts << n if n!=name
125
- end
126
- questions << q
127
- end
128
-
129
- # indexes = []
130
- # exclude = ["[", "]", "(", ")", "\"" ]
131
- # filtered[:words].each_with_index do |item,index|
132
- # flag=true
133
- # exclude.each { |e| flag=false if (item[:word].include?(e)) }
134
- # indexes << index if flag
135
- # end
108
+ # Question hidden name questions
109
+ q = Question.new(:short)
110
+ q.name = "#{name(:id)}-#{num}-d3hidden"
111
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d3, lang.hide_text(name(:raw)), t)
112
+ q.shorts << name(:raw)
113
+ q.shorts << name(:raw).gsub('-', ' ').gsub('_', ' ')
114
+ concept.names.each { |n| q.shorts << n if n != name }
115
+ questions << q
136
116
 
137
- #Question filtered text questions
138
- filtered=lang.text_with_connectors(t)
117
+ # Question filtered text questions
118
+ filtered = lang.text_with_connectors(t)
139
119
  indexes = filtered[:indexes]
140
120
 
141
- groups = (indexes.combination(4).to_a).shuffle
142
- max = (indexes.size/4).to_i
143
- groups[0,max].each do |e|
121
+ groups = indexes.combination(4).to_a.shuffle
122
+ max = (indexes.size / 4).to_i
123
+ groups[0, max].each do |e|
144
124
  e.sort!
145
125
  q = Question.new(:match)
146
126
  q.shuffle_off
147
127
  q.name = "#{name}-#{num}-d4filtered"
148
- s = lang.build_text_from_filtered( filtered, e)
149
- q.text = random_image_for(name(:raw)) + lang.text_for(:d4, name(:raw) , s)
150
- e.each_with_index do |value,index|
151
- q.matching << [ (index+1).to_s, filtered[:words][value][:word].downcase ]
128
+ s = lang.build_text_from_filtered(filtered, e)
129
+ q.text = random_image_for(name(:raw)) + lang.text_for(:d4, name(:raw), s)
130
+ e.each_with_index do |value, index|
131
+ q.matching << [(index + 1).to_s, filtered[:words][value][:word].downcase]
152
132
  end
153
133
  questions << q
154
134
  end
155
135
  end
156
136
 
157
- return questions
137
+ questions
158
138
  end
159
-
139
+ # rubocop:enable Lint/BooleanSymbol
140
+ # rubocop:enable Metrics/MethodLength
141
+ # rubocop:enable Metrics/AbcSize
142
+ # rubocop:enable Metrics/BlockLength
143
+ # rubocop:enable Metrics/CyclomaticComplexity
144
+ # rubocop:enable Metrics/PerceivedComplexity
160
145
  end
@@ -1,13 +1,20 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require_relative 'base_stage'
3
4
  require_relative '../question'
4
5
 
5
6
  # StageF: process tables with 1 field
7
+ # rubocop:disable Metrics/ClassLength
6
8
  class StageF < BaseStage
9
+ ##
10
+ # run stage_f: generate guqestion for tables with 1 field
11
+ # @param table (Table)
12
+ # @param list1 (Array) List of Rows from this table
13
+ # @param list2 (Array) List of Row from other tables
7
14
  def run(table, list1, list2)
8
15
  # process_table1field
9
16
  questions = []
10
- return questions if table.fields.count>1
17
+ return questions if table.fields.count > 1
11
18
 
12
19
  questions += run_only_this_concept(table, list1)
13
20
  questions += run_with_other_concepts(table, list1, list2)
@@ -15,29 +22,32 @@ class StageF < BaseStage
15
22
  questions
16
23
  end
17
24
 
18
- private
25
+ private
19
26
 
27
+ # rubocop:disable Metrics/AbcSize
28
+ # rubocop:disable Metrics/MethodLength
20
29
  def run_only_this_concept(table, list1)
21
30
  questions = []
22
- s1 = Set.new #Set of rows from this concept
31
+ lang = concept.lang
32
+ s1 = Set.new # Set of rows from this concept
23
33
  list1.each { |item| s1 << item[:data][0] }
24
34
  a1 = s1.to_a
25
35
  a1.shuffle!
26
36
 
27
37
  if a1.size > 3
28
- a1.each_cons(4) do |e1,e2,e3,e4|
29
- e = [ e1, e2, e3, e4 ]
38
+ a1.each_cons(4) do |e1, e2, e3, e4|
39
+ e = [e1, e2, e3, e4]
30
40
  questions += make_questions_with(e, table)
31
41
 
32
- #Question filtered text
33
- e = [ e1, e2, e3, e4 ]
42
+ # Question filtered text
43
+ e = [e1, e2, e3, e4]
34
44
  e.shuffle!
35
45
  t = "(a) #{e[0]}, (b) #{e[1]}, (c) #{e[2]}, (d) #{e[3]}"
36
- filtered=lang.text_with_connectors(t)
46
+ filtered = lang.text_with_connectors(t)
37
47
  indexes = filtered[:indexes]
38
48
 
39
- groups = (indexes.combination(4).to_a).shuffle
40
- max = (indexes.size/4).to_i
49
+ groups = indexes.combination(4).to_a.shuffle
50
+ max = (indexes.size / 4).to_i
41
51
  groups[0, max].each do |i|
42
52
  i.sort!
43
53
  q = Question.new(:match)
@@ -46,9 +56,10 @@ private
46
56
  s = lang.build_text_from_filtered(filtered, i)
47
57
  q.text = random_image_for(name(:raw))
48
58
  q.text += lang.text_for(:f3, name(:decorated), table.fields[0].capitalize, s)
49
- i.each_with_index do |value,index|
59
+ i.each_with_index do |value, index|
50
60
  q.matching << [(index + 1).to_s, filtered[:words][value][:word].downcase]
51
61
  end
62
+ q.matching << ['', lang.do_mistake_to(filtered[:words][rand(filtered[:words].size)][:word].downcase)]
52
63
  questions << q
53
64
  end
54
65
  end
@@ -58,59 +69,72 @@ private
58
69
  end
59
70
  questions
60
71
  end
72
+ # rubocop:enable Metrics/AbcSize
73
+ # rubocop:enable Metrics/MethodLength
61
74
 
62
- def make_questions_with(e, table)
75
+ # rubocop:disable Lint/BooleanSymbol
76
+ # rubocop:disable Metrics/MethodLength
77
+ # rubocop:disable Metrics/AbcSize
78
+ def make_questions_with(values, table)
63
79
  questions = []
80
+ lang = concept.lang
64
81
 
65
- e.shuffle!
82
+ values.shuffle!
66
83
  q = Question.new(:choice)
67
- q.name = "#{name(:id)}-#{num}-f1true#{e.size}-#{table.name}"
84
+ q.name = "#{name(:id)}-#{num}-f1true#{values.size}-#{table.name}"
68
85
  q.text = random_image_for(name(:raw))
69
- q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, e.join('</li><li>'))
86
+ q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, values.join('</li><li>'))
70
87
  q.good = lang.text_for(:true)
71
88
  q.bads << lang.text_for(:misspelling)
72
89
  q.bads << lang.text_for(:false)
73
90
 
74
- if type == 'text'
75
- e.shuffle!
91
+ if concept.type == 'text'
92
+ values.shuffle!
76
93
  q = Question.new(:short)
77
- q.name = "#{name(:id)}-#{num}-f1short#{e.size}-#{table.name}"
94
+ q.name = "#{name(:id)}-#{num}-f1short#{values.size}-#{table.name}"
78
95
  q.text = random_image_for(name(:raw))
79
- q.text += lang.text_for(:f1, lang.hide_text(name(:raw)), table.fields[0].capitalize, e.join('</li><li>'))
96
+ q.text += lang.text_for(:f1, lang.hide_text(name(:raw)), table.fields[0].capitalize, values.join('</li><li>'))
80
97
  q.shorts << name(:raw)
81
98
  q.shorts << name(:raw).tr('-_', ' ')
82
99
  questions << q
83
100
 
84
- e.shuffle!
85
- save = e[0]
86
- e[0] = lang.do_mistake_to(e[0])
101
+ values.shuffle!
102
+ save = values[0]
103
+ values[0] = lang.do_mistake_to(values[0])
87
104
  q = Question.new(:choice)
88
- q.name = "#{name(:id)}-#{num}-f1name-misspelled#{e.size}-#{table.name}"
105
+ q.name = "#{name(:id)}-#{num}-f1name-misspelled#{values.size}-#{table.name}"
89
106
  q.text = random_image_for(name(:raw))
90
- q.text += lang.text_for(:f1, lang.do_mistake_to(name(:decorated)), table.fields[0].capitalize, e.join('</li><li>'))
107
+ q.text += lang.text_for(:f1, lang.do_mistake_to(name(:decorated)), \
108
+ table.fields[0].capitalize, values.join('</li><li>'))
91
109
  q.good = lang.text_for(:misspelling)
92
110
  q.bads << lang.text_for(:true)
93
111
  q.bads << lang.text_for(:false)
94
112
  q.feedback = "Concept name #{name(:raw)} misspelled!"
95
- e[0] = save
113
+ values[0] = save
96
114
  questions << q
97
115
  end
98
116
 
99
- e.shuffle!
100
- save = e[0]
101
- e[0] = lang.do_mistake_to(e[0])
117
+ values.shuffle!
118
+ save = values[0]
119
+ values[0] = lang.do_mistake_to(values[0])
102
120
  q = Question.new(:choice)
103
- q.name = "#{name(:id)}-#{num}-f1true-misspelled#{e.size}-#{table.name}"
121
+ q.name = "#{name(:id)}-#{num}-f1true-misspelled#{values.size}-#{table.name}"
104
122
  q.text = random_image_for(name(:raw))
105
- q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, e.join('</li><li>'))
123
+ q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, values.join('</li><li>'))
106
124
  q.good = lang.text_for(:misspelling)
107
125
  q.bads << lang.text_for(:true)
108
126
  q.bads << lang.text_for(:false)
109
127
  q.feedback = "Text #{save} mispelled!"
110
- e[0] = save
128
+ values[0] = save
111
129
  questions << q
112
130
  end
131
+ # rubocop:enable Lint/BooleanSymbol
132
+ # rubocop:enable Metrics/MethodLength
133
+ # rubocop:enable Metrics/AbcSize
113
134
 
135
+ # rubocop:disable Lint/BooleanSymbol
136
+ # rubocop:disable Metrics/MethodLength
137
+ # rubocop:disable Metrics/AbcSize
114
138
  def run_with_other_concepts(table, list1, list2)
115
139
  questions = []
116
140
 
@@ -133,17 +157,17 @@ private
133
157
  q = Question.new(:choice)
134
158
  q.name = "#{name(:id)}-#{num}-f1false-#{table.name}"
135
159
  q.text = random_image_for(name(:raw))
136
- q.text += lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, e.join('</li><li>'))
137
- q.good = lang.text_for(:false)
138
- q.bads << lang.text_for(:misspelling)
139
- q.bads << lang.text_for(:true)
160
+ q.text += concept.lang.text_for(:f1, name(:decorated), table.fields[0].capitalize, e.join('</li><li>'))
161
+ q.good = concept.lang.text_for(:false)
162
+ q.bads << concept.lang.text_for(:misspelling)
163
+ q.bads << concept.lang.text_for(:true)
140
164
  questions << q
141
165
 
142
166
  f4 = a2.shuffle![0]
143
167
  q = Question.new(:choice)
144
168
  q.name = "#{name(:id)}-#{num}-f2outsider-#{table.name}"
145
169
  q.text = random_image_for(name(:raw))
146
- q.text += lang.text_for(:f2, name(:decorated), table.fields[0].capitalize)
170
+ q.text += concept.lang.text_for(:f2, name(:decorated), table.fields[0].capitalize)
147
171
  q.good = f4
148
172
  q.bads << e1
149
173
  q.bads << e2
@@ -153,4 +177,8 @@ private
153
177
 
154
178
  questions
155
179
  end
180
+ # rubocop:enable Lint/BooleanSymbol
181
+ # rubocop:enable Metrics/MethodLength
182
+ # rubocop:enable Metrics/AbcSize
156
183
  end
184
+ # rubocop:enable Metrics/ClassLength
@@ -1,42 +1,49 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- require 'base64_compatible' # TODO: Don't work with Moodle Gift images
4
3
  require 'set'
5
4
 
6
5
  require_relative 'base_stage'
7
6
  require_relative '../question'
8
7
 
8
+ # range i1, i2, i3, i4
9
9
  class StageI < BaseStage
10
- # range i1, i2, i3
11
-
10
+ # Stage I: process every image from <def> tag
11
+ # rubocop:disable Metrics/BlockLength
12
+ # rubocop:disable Metrics/MethodLength
13
+ # rubocop:disable Metrics/AbcSize
14
+ # rubocop:disable Metrics/CyclomaticComplexity
15
+ # rubocop:disable Metrics/PerceivedComplexity
12
16
  def run
13
- # Stage I: process every image from <def> tag
14
- questions=[]
15
- return questions unless type=="text"
17
+ questions = []
18
+ return questions unless concept.type == 'text'
16
19
 
20
+ lang = concept.lang
17
21
  # for every <image> do this
18
- images.each do |url|
19
- s=Set.new [name, lang.text_for(:none)]
20
- neighbors.each { |n| s.add n[:concept].name }
21
- a=s.to_a
22
-
23
- # Question type <f1>: choose between 4 options
24
- if s.count>3 then
25
- q=Question.new(:choice)
26
- q.name="#{name}-#{num}-i1choice"
27
- q.text=lang.text_for(:i1, url )
28
- q.good=name
22
+ concept.images.each do |image|
23
+ url = image[:text]
24
+ s = Set.new [name, lang.text_for(:none)]
25
+ concept.neighbors.each { |n| s.add n[:concept].name }
26
+ a = s.to_a
27
+
28
+ # Question type <i1>: choose between 4 options
29
+ if s.count > 3
30
+ q = Question.new(:choice)
31
+ q.name = "#{name}-#{num}-i1choice"
32
+ q.text = lang.text_for(:i1, url)
33
+ q.encode = image[:file]
34
+ q.good = name
29
35
  q.bads << lang.text_for(:none)
30
36
  q.bads << a[2]
31
37
  q.bads << a[3]
32
38
  questions << q
33
39
  end
34
40
 
35
- #Question type <i1>: choose between 4 options, good none (Syntax error)
36
- if s.count>3 then
37
- q=Question.new(:choice)
38
- q.name="#{name}-#{num}-i1misspelling"
39
- q.text=lang.text_for(:i1, url )
41
+ # Question type <i1>: choose between 4 options, good none (Syntax error)
42
+ if s.count > 3
43
+ q = Question.new(:choice)
44
+ q.name = "#{name}-#{num}-i1misspelling"
45
+ q.text = lang.text_for(:i1, url)
46
+ q.encode = image[:file]
40
47
  q.good = lang.text_for(:none)
41
48
  q.bads << lang.do_mistake_to(name)
42
49
  q.bads << a[2]
@@ -45,96 +52,76 @@ class StageI < BaseStage
45
52
  end
46
53
 
47
54
  s.delete(name)
48
- a=s.to_a
55
+ a = s.to_a
49
56
 
50
- #Question type <i1>: choose between 4 options, good none
51
- if s.count>3 then
57
+ # Question type <i1>: choose between 4 options, good none
58
+ if s.count > 3
52
59
  q = Question.new(:choice)
53
- q.name="#{name}-#{num}-i1none"
54
- q.text=lang.text_for(:i1, url )
55
- q.good=lang.text_for(:none)
60
+ q.name = "#{name}-#{num}-i1none"
61
+ q.text = lang.text_for(:i1, url)
62
+ q.encode = image[:file]
63
+ q.good = lang.text_for(:none)
56
64
  q.bads << a[1]
57
65
  q.bads << a[2]
58
66
  q.bads << a[3]
59
67
  questions << q
60
68
  end
61
69
 
62
- #Question type <f2>: boolean => TRUE
70
+ # Question type <i2>: boolean => TRUE
63
71
  q = Question.new(:boolean)
64
- q.name="#{name}-#{num}-i2true"
65
- q.text=lang.text_for(:i2, url, name )
66
- q.good="TRUE"
72
+ q.name = "#{name}-#{num}-i2true"
73
+ q.text = lang.text_for(:i2, url, name)
74
+ q.encode = image[:file]
75
+ q.good = 'TRUE'
67
76
  questions << q
68
77
 
69
- #Question type <i2>: boolean => FALSE
70
- if neighbors.count>0 then
78
+ # Question type <i2>: boolean => FALSE
79
+ if concept.neighbors.count.positive?
71
80
  q = Question.new(:boolean)
72
- q.name="#{name}-#{num}-i2false"
73
- q.text=lang.text_for(:i2, url, neighbors[0][:concept].name )
74
- q.good="FALSE"
81
+ q.name = "#{name}-#{num}-i2false"
82
+ q.text = lang.text_for(:i2, url, concept.neighbors[0][:concept].name)
83
+ q.encode = image[:file]
84
+ q.good = 'FALSE'
75
85
  questions << q
76
86
  end
77
87
 
78
- #Question type <i3>: hidden name questions
88
+ # Question type <i3>: hidden name questions
79
89
  q = Question.new(:short)
80
- q.name="#{name}-#{num}-i3short"
81
- q.text=lang.text_for(:i3, url, lang.hide_text(name) )
90
+ q.name = "#{name}-#{num}-i3short"
91
+ q.text = lang.text_for(:i3, url, lang.hide_text(name))
92
+ q.encode = image[:file]
82
93
  q.shorts << name
83
- q.shorts << name.gsub("-"," ").gsub("_"," ")
94
+ q.shorts << name.gsub('-', ' ').gsub('_', ' ')
84
95
  questions << q
85
96
 
86
- #Question filtered text questions
87
- texts.each do |t|
88
- filtered=lang.text_with_connectors(t)
89
-
90
- if filtered[:words].size>=4 then
91
- # indexes=Set.new
92
- # words=filtered[:words]
93
- # while indexes.size<4
94
- # i=rand(filtered[:words].size)
95
- # flag=true
96
- # flag=false if words[i].include?("[") or words[i].include?("]") or words[i].include?("(") or words[i].include?(")") or words[i].include?("\"")
97
- # indexes << i if flag
98
- # end
99
- # indexes=indexes.to_a.sort
100
- indexes = filtered[:indexes]
101
- groups = (indexes.combination(4).to_a).shuffle
102
- max = (indexes.size/4).to_i
103
- groups[0,max].each do |e|
104
- q = Question.new(:match)
105
- q.shuffle_off
106
- q.name = "#{name}-#{num}-i4filtered"
107
- e.sort!
108
- s=lang.build_text_from_filtered( filtered, e )
109
- q.text = lang.text_for(:i4, url , s)
110
- e.each_with_index do |value,index|
111
- q.matching << [ (index+1).to_s, filtered[:words][value][:word].downcase ]
112
- end
97
+ # Question filtered text questions
98
+ concept.texts.each do |t|
99
+ filtered = lang.text_with_connectors(t)
100
+ next if filtered[:words].size < 4
101
+
102
+ indexes = filtered[:indexes]
103
+ groups = indexes.combination(4).to_a.shuffle
104
+ max = (indexes.size / 4).to_i
105
+ groups[0, max].each do |e|
106
+ q = Question.new(:match)
107
+ q.shuffle_off
108
+ q.name = "#{name}-#{num}-i4filtered"
109
+ q.encode = image[:file]
110
+ e.sort!
111
+ s = lang.build_text_from_filtered(filtered, e)
112
+ q.text = lang.text_for(:i4, url, s)
113
+ e.each_with_index do |value, index|
114
+ q.matching << [index.next.to_s, filtered[:words][value][:word].downcase]
113
115
  end
114
- questions << q
115
116
  end
116
- end #each texts
117
- end #each images
118
- return questions
119
- end
120
-
121
- private
122
-
123
- def html_for_raw_image(filename)
124
- dirname = File.dirname(@concept_ia.filename)
125
- filepath = File.join(dirname,filename)
126
- content = File.open(filepath).read
127
- content64 = Base64Compatible.encode64( content )
128
- output =""
129
- until(content64.nil?) do
130
- output = output + content64[0,76]+"\n"
131
- tmp = content64[76,9999999]
132
- content64 = tmp
117
+ questions << q
118
+ end
133
119
  end
134
-
135
- ext = File.extname(filename)
136
- output = "<img src='data:image/#{ext};base64,#{output}' />"
137
- return output
120
+ questions
138
121
  end
139
-
122
+ # rubocop:enable Metrics/BlockLength
123
+ # rubocop:enable Metrics/MethodLength
124
+ # rubocop:enable Metrics/AbcSize
125
+ # rubocop:enable Metrics/CyclomaticComplexity
126
+ # rubocop:enable Metrics/PerceivedComplexity
140
127
  end