asker-tool 2.1.7 → 2.2.0

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 (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