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.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +53 -0
- data/bin/asker +4 -0
- data/docs/changelog/v2.1.md +99 -0
- data/docs/commands.md +15 -0
- data/docs/contributions.md +18 -0
- data/docs/history.md +40 -0
- data/docs/idea.md +44 -0
- data/docs/inputs/README.md +39 -0
- data/docs/inputs/code.md +69 -0
- data/docs/inputs/concepts.md +142 -0
- data/docs/inputs/jedi.md +68 -0
- data/docs/inputs/tables.md +112 -0
- data/docs/inputs/templates.md +87 -0
- data/docs/install/README.md +38 -0
- data/docs/install/manual.md +26 -0
- data/docs/install/scripts.md +26 -0
- data/docs/revise/asker-file.md +41 -0
- data/docs/revise/buenas-practicas/01-convocatoria.md +30 -0
- data/docs/revise/buenas-practicas/02-formulario.md +35 -0
- data/docs/revise/buenas-practicas/03-descripcion.md +63 -0
- data/docs/revise/buenas-practicas/04-resultados.md +17 -0
- data/docs/revise/buenas-practicas/05-reproducir.md +10 -0
- data/docs/revise/ejemplos/01/README.md +27 -0
- data/docs/revise/ejemplos/02/README.md +31 -0
- data/docs/revise/ejemplos/03/README.md +31 -0
- data/docs/revise/ejemplos/04/README.md +37 -0
- data/docs/revise/ejemplos/05/README.md +25 -0
- data/docs/revise/ejemplos/06/README.md +43 -0
- data/docs/revise/ejemplos/README.md +11 -0
- data/docs/revise/projects.md +74 -0
- data/lib/asker.rb +103 -0
- data/lib/asker/ai/ai.rb +70 -0
- data/lib/asker/ai/ai_calculate.rb +55 -0
- data/lib/asker/ai/concept_ai.rb +49 -0
- data/lib/asker/ai/question.rb +58 -0
- data/lib/asker/ai/stages/base_stage.rb +16 -0
- data/lib/asker/ai/stages/main.rb +8 -0
- data/lib/asker/ai/stages/stage_b.rb +87 -0
- data/lib/asker/ai/stages/stage_d.rb +160 -0
- data/lib/asker/ai/stages/stage_f.rb +156 -0
- data/lib/asker/ai/stages/stage_i.rb +140 -0
- data/lib/asker/ai/stages/stage_s.rb +52 -0
- data/lib/asker/ai/stages/stage_t.rb +170 -0
- data/lib/asker/application.rb +30 -0
- data/lib/asker/checker.rb +356 -0
- data/lib/asker/cli.rb +85 -0
- data/lib/asker/code/ai/base_code_ai.rb +48 -0
- data/lib/asker/code/ai/code_ai_factory.rb +26 -0
- data/lib/asker/code/ai/javascript_code_ai.rb +167 -0
- data/lib/asker/code/ai/python_code_ai.rb +167 -0
- data/lib/asker/code/ai/ruby_code_ai.rb +169 -0
- data/lib/asker/code/ai/sql_code_ai.rb +69 -0
- data/lib/asker/code/code.rb +53 -0
- data/lib/asker/data/column.rb +62 -0
- data/lib/asker/data/concept.rb +183 -0
- data/lib/asker/data/data_field.rb +87 -0
- data/lib/asker/data/row.rb +93 -0
- data/lib/asker/data/table.rb +96 -0
- data/lib/asker/data/template.rb +65 -0
- data/lib/asker/data/world.rb +53 -0
- data/lib/asker/exporter/code_gift_exporter.rb +35 -0
- data/lib/asker/exporter/code_screen_exporter.rb +45 -0
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +33 -0
- data/lib/asker/exporter/concept_ai_screen_exporter.rb +115 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +33 -0
- data/lib/asker/exporter/concept_doc_exporter.rb +21 -0
- data/lib/asker/exporter/concept_screen_exporter.rb +25 -0
- data/lib/asker/exporter/main.rb +9 -0
- data/lib/asker/files/config.ini +40 -0
- data/lib/asker/formatter/code_string_formatter.rb +16 -0
- data/lib/asker/formatter/concept_doc_formatter.rb +37 -0
- data/lib/asker/formatter/concept_string_formatter.rb +66 -0
- data/lib/asker/formatter/question_gift_formatter.rb +65 -0
- data/lib/asker/formatter/question_hash_formatter.rb +40 -0
- data/lib/asker/formatter/question_moodlexml_formatter.rb +71 -0
- data/lib/asker/formatter/rb2haml_formatter.rb +26 -0
- data/lib/asker/lang/lang.rb +42 -0
- data/lib/asker/lang/lang_factory.rb +19 -0
- data/lib/asker/lang/text_actions.rb +150 -0
- data/lib/asker/loader/code_loader.rb +53 -0
- data/lib/asker/loader/content_loader.rb +101 -0
- data/lib/asker/loader/directory_loader.rb +58 -0
- data/lib/asker/loader/file_loader.rb +33 -0
- data/lib/asker/loader/image_url_loader.rb +61 -0
- data/lib/asker/loader/input_loader.rb +24 -0
- data/lib/asker/loader/project_loader.rb +71 -0
- data/lib/asker/logger.rb +21 -0
- data/lib/asker/project.rb +170 -0
- metadata +261 -0
data/lib/asker/ai/ai.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'stages/main'
|
4
|
+
require_relative 'ai_calculate'
|
5
|
+
|
6
|
+
# Description: Method to be included into every ConceptAI instance.
|
7
|
+
# * make_questions: use AI to fill @questions Array
|
8
|
+
module AI
|
9
|
+
include AI_calculate
|
10
|
+
|
11
|
+
def make_questions
|
12
|
+
return unless process?
|
13
|
+
|
14
|
+
make_questions_stages_di
|
15
|
+
# Process every table of this concept
|
16
|
+
tables.each do |tab|
|
17
|
+
list1, list2 = get_list1_and_list2_from(tab)
|
18
|
+
make_questions_stages_bsf(tab, list1, list2)
|
19
|
+
make_questions_stages_t(tab, list1, list2)
|
20
|
+
end
|
21
|
+
# -------------------------------------------------------
|
22
|
+
# Exclude questions as is defined into config.ini params
|
23
|
+
exclude_questions
|
24
|
+
end
|
25
|
+
|
26
|
+
def make_questions_stages_di
|
27
|
+
@questions[:d] = StageD.new(self).run # Process every def{type=text}
|
28
|
+
@questions[:i] = StageI.new(self).run # Process every def{type=image_url}
|
29
|
+
end
|
30
|
+
|
31
|
+
def make_questions_stages_bsf(tab, list1, list2)
|
32
|
+
# Stage B: process table to make match questions
|
33
|
+
@questions[:b] += StageB.new(self).run(tab, list1, list2)
|
34
|
+
# Stage S: process tables with sequences
|
35
|
+
@questions[:s] += StageS.new(self).run(tab, list1, list2)
|
36
|
+
# Stage F: process tables with only 1 field
|
37
|
+
@questions[:f] += StageF.new(self).run(tab, list1, list2)
|
38
|
+
end
|
39
|
+
|
40
|
+
def make_questions_stages_t(tab, list1, list2)
|
41
|
+
# Stage T: process_tableXfields
|
42
|
+
list3 = list1 + list2
|
43
|
+
list1.each do |row|
|
44
|
+
reorder_list_with_row(list3, row)
|
45
|
+
@questions[:t] += StageT.new(self).run(tab, row, list3)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def exclude_questions
|
50
|
+
param = Application.instance.config['questions']['exclude']
|
51
|
+
return if param.nil?
|
52
|
+
|
53
|
+
tags = param.split(',').each(&:strip!)
|
54
|
+
input = { d: [], b: [], f: [], i: [], s: [], t: [] }
|
55
|
+
output = { d: [], b: [], f: [], i: [], s: [], t: [] }
|
56
|
+
|
57
|
+
@questions.each_pair do |key, qlist|
|
58
|
+
output[key] = qlist.select { |q| string_has_this_tags?(q.name, tags) }
|
59
|
+
input[key] = @questions[key] - output[key]
|
60
|
+
end
|
61
|
+
@questions = input
|
62
|
+
@excluded_questions = output
|
63
|
+
end
|
64
|
+
|
65
|
+
def string_has_this_tags?(input, tags)
|
66
|
+
flag = false
|
67
|
+
tags.each { |e| flag = true if input.include? e }
|
68
|
+
flag
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Methods that calculate something
|
4
|
+
module AI_calculate
|
5
|
+
def get_list1_and_list2_from(ltable)
|
6
|
+
# create <list1> with all the rows from the table
|
7
|
+
list1 = []
|
8
|
+
count = 1
|
9
|
+
ltable.rows.each do |i|
|
10
|
+
list1 << { id: count, weight: 0, data: i }
|
11
|
+
count += 1
|
12
|
+
end
|
13
|
+
|
14
|
+
# create a <list2> with similar rows (same table name) from the neighbours tables
|
15
|
+
list2 = []
|
16
|
+
neighbors.each do |n|
|
17
|
+
n[:concept].tables.each do |t2|
|
18
|
+
next if t2.name != ltable.name
|
19
|
+
t2.rows.each do |i|
|
20
|
+
list2 << { id: count, weight: 0, data: i }
|
21
|
+
count += 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
return list1, list2
|
26
|
+
end
|
27
|
+
|
28
|
+
def calculate_nearness_between_texts(text1, text2)
|
29
|
+
return 0.0 if text2.nil? || text2.empty?
|
30
|
+
|
31
|
+
words = text1.split(' ')
|
32
|
+
count = 0
|
33
|
+
words.each { |w| count += 1 if text2.include?(w) }
|
34
|
+
(count * 100 / words.count)
|
35
|
+
end
|
36
|
+
|
37
|
+
def reorder_list_with_row(list, row)
|
38
|
+
# evaluate every row of the list2
|
39
|
+
list.each do |r|
|
40
|
+
if r[:id] == row[:id]
|
41
|
+
r[:weight] = -300
|
42
|
+
else
|
43
|
+
val = 0
|
44
|
+
s = row[:data].count
|
45
|
+
s.times do |i|
|
46
|
+
val += calculate_nearness_between_texts(row[:data][i], r[:data][i])
|
47
|
+
end
|
48
|
+
val /= s
|
49
|
+
r[:weight] = val
|
50
|
+
end
|
51
|
+
end
|
52
|
+
list.sort! { |a, b| a[:weight] <=> b[:weight] }
|
53
|
+
list.reverse!
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../lang/lang'
|
4
|
+
require_relative 'ai'
|
5
|
+
require_relative 'question'
|
6
|
+
|
7
|
+
# ConceptAI: Add more info to every Concept instance.
|
8
|
+
# Encapsulating AI data => questions
|
9
|
+
# * concept
|
10
|
+
# * questions
|
11
|
+
# * num
|
12
|
+
# * random_image_for
|
13
|
+
class ConceptAI
|
14
|
+
include AI
|
15
|
+
|
16
|
+
attr_reader :concept
|
17
|
+
attr_reader :questions
|
18
|
+
attr_reader :excluded_questions
|
19
|
+
|
20
|
+
def initialize(concept, world)
|
21
|
+
@concept = concept
|
22
|
+
@world = world
|
23
|
+
@questions = { d: [], b: [], f: [], i: [], s: [], t: [] }
|
24
|
+
@excluded_questions = { d: [], b: [], f: [], i: [], s: [], t: [] }
|
25
|
+
@num = 0 # Used to add a unique number to every question
|
26
|
+
end
|
27
|
+
|
28
|
+
def num
|
29
|
+
@num += 1
|
30
|
+
@num.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
# If a method call is missing, then delegate to concept parent.
|
34
|
+
def method_missing(method, *args, &block)
|
35
|
+
@concept.send(method, *args, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def random_image_for(_conceptname)
|
39
|
+
return '' if rand <= Project.instance.get(:threshold)
|
40
|
+
|
41
|
+
keys = @world.image_urls.keys
|
42
|
+
keys.shuffle!
|
43
|
+
values = @world.image_urls[keys[0]] # keys[0] could be conceptname
|
44
|
+
return '' if values.nil?
|
45
|
+
|
46
|
+
values.shuffle!
|
47
|
+
"<img src=\"#{values[0]}\" alt\=\"image\"><br/>"
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
# Define Question class
|
5
|
+
class Question
|
6
|
+
attr_accessor :name, :comment, :text
|
7
|
+
attr_accessor :good, :bads, :matching, :shorts
|
8
|
+
attr_accessor :feedback
|
9
|
+
attr_reader :type
|
10
|
+
attr_accessor :tags, :lang
|
11
|
+
|
12
|
+
def initialize(type = :choice)
|
13
|
+
reset(type)
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset(type = :choice)
|
17
|
+
@name = ''
|
18
|
+
@comment = ''
|
19
|
+
@text = ''
|
20
|
+
@type = type
|
21
|
+
@good = ''
|
22
|
+
@bads = []
|
23
|
+
@matching = []
|
24
|
+
@shorts = []
|
25
|
+
@feedback = nil
|
26
|
+
shuffle_on
|
27
|
+
@tags = Set.new
|
28
|
+
@lang = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_choice
|
32
|
+
@type = :choice
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_match
|
36
|
+
@type = :match
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_boolean
|
40
|
+
@type = :boolean
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_short
|
44
|
+
@type = :short
|
45
|
+
end
|
46
|
+
|
47
|
+
def shuffle_off
|
48
|
+
@shuffle = false
|
49
|
+
end
|
50
|
+
|
51
|
+
def shuffle_on
|
52
|
+
@shuffle = true
|
53
|
+
end
|
54
|
+
|
55
|
+
def shuffle?
|
56
|
+
@shuffle
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
class BaseStage
|
3
|
+
def initialize(concept_ai)
|
4
|
+
@concept_ai = concept_ai
|
5
|
+
end
|
6
|
+
|
7
|
+
# If a method we call is missing, pass the call onto
|
8
|
+
# the object we delegate to.
|
9
|
+
def method_missing(m, *args, &block)
|
10
|
+
@concept_ai.send(m, *args, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
raise 'Implement run method!'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
require_relative 'base_stage'
|
6
|
+
require_relative '../question'
|
7
|
+
|
8
|
+
class StageB < BaseStage
|
9
|
+
# range b1
|
10
|
+
|
11
|
+
def run(pTable, pList1, pList2)
|
12
|
+
# process table match
|
13
|
+
questions = []
|
14
|
+
return questions if pTable.fields.count < 2
|
15
|
+
|
16
|
+
return questions unless type == 'text'
|
17
|
+
|
18
|
+
if pTable.fields.count>1 then
|
19
|
+
questions += process_table_match2fields(pTable, pList1, pList2, 0, 1)
|
20
|
+
elsif pTable.fields.count>2 then
|
21
|
+
questions += process_table_match2fields(pTable, pList1, pList2, 0, 2)
|
22
|
+
questions += process_table_match2fields(pTable, pList1, pList2, 1, 2)
|
23
|
+
elsif pTable.fields.count>3 then
|
24
|
+
questions += process_table_match2fields(pTable, pList1, pList2, 0, 3)
|
25
|
+
questions += process_table_match2fields(pTable, pList1, pList2, 1, 3)
|
26
|
+
questions += process_table_match2fields(pTable, pList1, pList2, 2, 3)
|
27
|
+
end
|
28
|
+
|
29
|
+
questions
|
30
|
+
end
|
31
|
+
|
32
|
+
def process_table_match2fields(pTable, pList1, pList2, pIndex1, pIndex2)
|
33
|
+
questions = []
|
34
|
+
|
35
|
+
if pList1.count>3
|
36
|
+
pList1.each_cons(4) do |e1,e2,e3,e4|
|
37
|
+
e = [ e1, e2, e3, e4 ]
|
38
|
+
|
39
|
+
#Question type <b1match>: match 4 items from the same table
|
40
|
+
e.shuffle!
|
41
|
+
q=Question.new(:match)
|
42
|
+
q.name="#{name}-#{num.to_s}-b1match4x4-#{pTable.name}"
|
43
|
+
q.text= random_image_for(name) + lang.text_for(:b1, name, pTable.fields[pIndex1].capitalize, pTable.fields[pIndex2].capitalize )
|
44
|
+
q.matching << [ e[0][:data][pIndex1], e[0][:data][pIndex2] ]
|
45
|
+
q.matching << [ e[1][:data][pIndex1], e[1][:data][pIndex2] ]
|
46
|
+
q.matching << [ e[2][:data][pIndex1], e[2][:data][pIndex2] ]
|
47
|
+
q.matching << [ e[3][:data][pIndex1], e[3][:data][pIndex2] ]
|
48
|
+
questions << q
|
49
|
+
|
50
|
+
# Question type <b1match>: match 3 items from table-A and 1 item with error
|
51
|
+
e.shuffle!
|
52
|
+
q=Question.new(:match)
|
53
|
+
q.name="#{name}-#{num.to_s}-b1match3x1misspelled-#{pTable.name}"
|
54
|
+
q.text= random_image_for(name) + lang.text_for(:b1, name, pTable.fields[pIndex1].capitalize, pTable.fields[pIndex2].capitalize )
|
55
|
+
q.matching << [ e[0][:data][pIndex1], e[0][:data][pIndex2] ]
|
56
|
+
q.matching << [ e[1][:data][pIndex1], e[1][:data][pIndex2] ]
|
57
|
+
q.matching << [ e[2][:data][pIndex1], e[2][:data][pIndex2] ]
|
58
|
+
q.matching << [ lang.do_mistake_to(e[3][:data][pIndex1]), lang.text_for(:misspelling) ]
|
59
|
+
questions << q
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
if pList1.count>2 and pList2.count>0
|
64
|
+
s=Set.new
|
65
|
+
pList1.each do |i|
|
66
|
+
s.add( i[:data][pIndex1]+"<=>"+i[:data][pIndex2] )
|
67
|
+
end
|
68
|
+
s.add( pList2[0][:data][pIndex1]+"<=>"+pList2[0][:data][pIndex2] )
|
69
|
+
a=s.to_a
|
70
|
+
|
71
|
+
# Question 3 items from table-A, and 1 item from table-B
|
72
|
+
if s.count > 3
|
73
|
+
q=Question.new(:match)
|
74
|
+
q.name="#{name}-#{num.to_s}-b1match3x1-#{pTable.name}"
|
75
|
+
q.text= random_image_for(name) + lang.text_for(:b1, name , pTable.fields[pIndex1].capitalize, pTable.fields[pIndex2].capitalize)
|
76
|
+
q.matching << [ pList1[0][:data][pIndex1], pList1[0][:data][pIndex2] ]
|
77
|
+
q.matching << [ pList1[1][:data][pIndex1], pList1[1][:data][pIndex2] ]
|
78
|
+
q.matching << [ pList1[2][:data][pIndex1], pList1[2][:data][pIndex2] ]
|
79
|
+
q.matching << [ pList2[0][:data][pIndex1], lang.text_for(:error) ]
|
80
|
+
questions << q
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
return questions
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
require_relative 'base_stage'
|
6
|
+
require_relative '../question'
|
7
|
+
|
8
|
+
class StageD < BaseStage
|
9
|
+
# range d1-d4
|
10
|
+
|
11
|
+
def run
|
12
|
+
# Stage D: process every definition, I mean every <def> tag
|
13
|
+
questions = []
|
14
|
+
return questions unless type == 'text'
|
15
|
+
|
16
|
+
# 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
|
21
|
+
|
22
|
+
# Question choose between 4 options
|
23
|
+
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)
|
28
|
+
q.bads << lang.text_for(:none)
|
29
|
+
q.bads << a[2]
|
30
|
+
q.bads << a[3]
|
31
|
+
questions << q
|
32
|
+
end
|
33
|
+
|
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)
|
39
|
+
q.good = lang.text_for(:none)
|
40
|
+
q.bads << lang.do_mistake_to(name(:raw))
|
41
|
+
q.bads << a[2]
|
42
|
+
q.bads << a[3]
|
43
|
+
q.feedback="Option misspelled!: #{name(:raw)}"
|
44
|
+
questions << q
|
45
|
+
end
|
46
|
+
|
47
|
+
s.delete(name(:raw))
|
48
|
+
a=s.to_a
|
49
|
+
|
50
|
+
#Question choose between 4 options, good none
|
51
|
+
if s.count>3 then
|
52
|
+
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)
|
56
|
+
q.bads << a[1]
|
57
|
+
q.bads << a[2]
|
58
|
+
q.bads << a[3]
|
59
|
+
questions << q
|
60
|
+
end
|
61
|
+
|
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
|
+
|
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)
|
73
|
+
q.bads << lang.text_for(:true)
|
74
|
+
q.bads << lang.text_for(:false)
|
75
|
+
q.feedback="Definition text mispelled!: #{t}"
|
76
|
+
questions << q
|
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
|
88
|
+
|
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 )
|
92
|
+
q.good = lang.text_for(:true)
|
93
|
+
q.bads << lang.text_for(:misspelling)
|
94
|
+
q.bads << lang.text_for(:false)
|
95
|
+
questions << q
|
96
|
+
|
97
|
+
if a.size>1 then
|
98
|
+
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)
|
101
|
+
q.good = lang.text_for(:false)
|
102
|
+
q.bads << lang.text_for(:misspelling)
|
103
|
+
q.bads << lang.text_for(:true)
|
104
|
+
questions << q
|
105
|
+
end
|
106
|
+
|
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
|
136
|
+
|
137
|
+
#Question filtered text questions
|
138
|
+
filtered=lang.text_with_connectors(t)
|
139
|
+
indexes = filtered[:indexes]
|
140
|
+
|
141
|
+
groups = (indexes.combination(4).to_a).shuffle
|
142
|
+
max = (indexes.size/4).to_i
|
143
|
+
groups[0,max].each do |e|
|
144
|
+
e.sort!
|
145
|
+
q = Question.new(:match)
|
146
|
+
q.shuffle_off
|
147
|
+
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 ]
|
152
|
+
end
|
153
|
+
questions << q
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
return questions
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|