asker-tool 2.6.0 → 2.7.1
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 +4 -4
- data/README.md +5 -5
- data/lib/asker/ai/ai.rb +6 -6
- data/lib/asker/ai/ai_calculate.rb +3 -3
- data/lib/asker/ai/code/base_code_ai.rb +5 -30
- data/lib/asker/ai/code/code_ai_factory.rb +6 -12
- data/lib/asker/ai/code/javascript_code_ai.rb +33 -34
- data/lib/asker/ai/code/python_code_ai.rb +35 -36
- data/lib/asker/ai/code/ruby_code_ai.rb +33 -33
- data/lib/asker/ai/code/sql_code_ai.rb +20 -21
- data/lib/asker/ai/concept_ai.rb +12 -22
- data/lib/asker/ai/problem/problem_ai.rb +226 -0
- data/lib/asker/ai/question.rb +34 -45
- data/lib/asker/ai/stages/base_stage.rb +7 -7
- data/lib/asker/ai/stages/stage_b.rb +62 -28
- data/lib/asker/ai/stages/stage_d.rb +10 -10
- data/lib/asker/ai/stages/stage_f.rb +17 -17
- data/lib/asker/ai/stages/stage_i.rb +8 -18
- data/lib/asker/ai/stages/stage_s.rb +28 -26
- data/lib/asker/ai/stages/stage_t.rb +40 -51
- data/lib/asker/application.rb +15 -14
- data/lib/asker/check_input/check_haml_data.rb +52 -51
- data/lib/asker/check_input/check_table.rb +17 -20
- data/lib/asker/check_input.rb +10 -23
- data/lib/asker/cli.rb +43 -24
- data/lib/asker/data/code.rb +10 -9
- data/lib/asker/data/column.rb +21 -17
- data/lib/asker/data/concept.rb +24 -37
- data/lib/asker/data/data_field.rb +2 -2
- data/lib/asker/data/problem.rb +112 -0
- data/lib/asker/data/project_data.rb +11 -15
- data/lib/asker/data/row.rb +25 -23
- data/lib/asker/data/table.rb +25 -46
- data/lib/asker/data/template.rb +7 -7
- data/lib/asker/data/world.rb +3 -3
- data/lib/asker/{formatter → deprecated}/question_moodlexml_formatter.rb +19 -21
- data/lib/asker/displayer/code_displayer.rb +10 -10
- data/lib/asker/displayer/concept_ai_displayer.erb +1 -1
- data/lib/asker/displayer/concept_ai_displayer.rb +17 -17
- data/lib/asker/displayer/concept_displayer.rb +4 -2
- data/lib/asker/displayer/problem_displayer.rb +45 -0
- data/lib/asker/displayer/stats_displayer.rb +7 -12
- data/lib/asker/exporter/code_gift_exporter.rb +2 -2
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +4 -4
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +7 -7
- data/lib/asker/exporter/concept_doc_exporter.rb +5 -5
- data/lib/asker/exporter/data_gift_exporter.rb +14 -15
- data/lib/asker/exporter/data_moodle_exporter.rb +51 -20
- data/lib/asker/exporter/output_file_exporter.rb +9 -8
- data/lib/asker/exporter/problem_gift_exporter.rb +30 -0
- data/lib/asker/files/language/ca/templates.yaml +6 -0
- data/lib/asker/files/language/du/templates.yaml +6 -0
- data/lib/asker/files/language/en/templates.yaml +7 -1
- data/lib/asker/files/language/es/templates.yaml +6 -0
- data/lib/asker/files/language/fr/templates.yaml +6 -0
- data/lib/asker/formatter/code_string_formatter.rb +5 -5
- data/lib/asker/formatter/concept_doc_formatter.rb +3 -3
- data/lib/asker/formatter/concept_string_formatter.rb +6 -6
- data/lib/asker/formatter/moodle/ddmatch.erb +40 -0
- data/lib/asker/formatter/moodle/gapfill.erb +57 -0
- data/lib/asker/formatter/moodle/ordering.erb +41 -0
- data/lib/asker/formatter/question_gift_formatter.rb +41 -14
- data/lib/asker/formatter/question_hash_formatter.rb +5 -6
- data/lib/asker/formatter/question_moodle_formatter.rb +14 -7
- data/lib/asker/formatter/rb2haml_formatter.rb +8 -7
- data/lib/asker/lang/lang.rb +16 -16
- data/lib/asker/lang/lang_factory.rb +13 -16
- data/lib/asker/lang/text_actions.rb +20 -18
- data/lib/asker/loader/code_loader.rb +10 -22
- data/lib/asker/loader/content_loader.rb +42 -49
- data/lib/asker/loader/directory_loader.rb +13 -16
- data/lib/asker/loader/embedded_file.rb +14 -14
- data/lib/asker/loader/file_loader.rb +5 -4
- data/lib/asker/loader/haml_loader.rb +4 -3
- data/lib/asker/loader/image_url_loader.rb +6 -5
- data/lib/asker/loader/input_loader.rb +24 -10
- data/lib/asker/loader/problem_loader.rb +88 -0
- data/lib/asker/loader/project_loader.rb +5 -12
- data/lib/asker/logger.rb +19 -10
- data/lib/asker/skeleton.rb +19 -35
- data/lib/asker/start.rb +44 -0
- data/lib/asker/version.rb +1 -1
- data/lib/asker.rb +7 -52
- metadata +12 -6
- data/lib/asker/ai/code/problem_code_ai.rb +0 -176
- data/lib/asker/exporter/code_moodle_exporter.rb +0 -15
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +0 -15
data/lib/asker/cli.rb
CHANGED
@@ -1,50 +1,70 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require_relative
|
6
|
-
require_relative
|
3
|
+
require "rainbow"
|
4
|
+
require "thor"
|
5
|
+
require_relative "version"
|
6
|
+
require_relative "../asker"
|
7
7
|
|
8
8
|
##
|
9
9
|
# Command Line User Interface
|
10
10
|
class CLI < Thor
|
11
|
-
map [
|
11
|
+
map ["-h", "--help"] => "help"
|
12
12
|
|
13
|
-
map [
|
14
|
-
desc
|
13
|
+
map ["-v", "--version"] => "version"
|
14
|
+
desc "version", "Show the program version"
|
15
15
|
def version
|
16
16
|
puts "#{Asker::NAME} version #{Asker::VERSION}"
|
17
17
|
exit 0
|
18
18
|
end
|
19
19
|
|
20
|
-
map [
|
21
|
-
desc
|
20
|
+
map ["--init"] => "init"
|
21
|
+
desc "init", "Create default INI config file"
|
22
22
|
def init
|
23
23
|
Asker.init
|
24
24
|
exit 0
|
25
25
|
end
|
26
26
|
|
27
|
-
map [
|
28
|
-
desc
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
map ["new", "--new"] => "create_input"
|
28
|
+
desc "new PATH", "Create Asker sample input file"
|
29
|
+
long_desc <<-LONGDESC
|
30
|
+
|
31
|
+
Create Asker sample input file (HAML format).
|
32
|
+
|
33
|
+
Examples:
|
34
|
+
|
35
|
+
(1) #{Rainbow("asker new foo/bar.haml").aqua}, Create "foo" dir and "bar.haml" file.
|
36
|
+
Path to input file can be relative or absolute.
|
37
|
+
|
38
|
+
(2) #{Rainbow("asker new foo").aqua}, Create "foo" dir and sample HAML file.
|
39
|
+
Path to directory can be relative or absolute.
|
40
|
+
|
41
|
+
LONGDESC
|
32
42
|
def create_input(dirname)
|
33
43
|
Asker.create_input(dirname)
|
34
44
|
exit 0
|
35
45
|
end
|
36
46
|
|
37
|
-
map [
|
38
|
-
desc
|
47
|
+
map ["--check"] => "check"
|
48
|
+
desc "check FILEPATH", "Check HAML input file syntax"
|
49
|
+
long_desc <<-LONGDESC
|
50
|
+
|
51
|
+
Check HAML input file syntax.
|
52
|
+
|
53
|
+
Examples:
|
54
|
+
|
55
|
+
(*) #{Rainbow("asker check foo/bar.haml").aqua}, Check "bar.haml" input file.
|
56
|
+
Path to input file can be relative or absolute.
|
57
|
+
|
58
|
+
LONGDESC
|
39
59
|
def check(filename)
|
40
60
|
# Enable/disable color output
|
41
|
-
Rainbow.enabled = false if options[
|
61
|
+
Rainbow.enabled = false if options["color"] == false
|
42
62
|
# Asker start processing input file
|
43
63
|
Asker.check(filename)
|
44
64
|
end
|
45
65
|
|
46
|
-
map [
|
47
|
-
desc
|
66
|
+
map ["f", "-f", "--file"] => "file"
|
67
|
+
desc "[file] FILEPATH", "Build output files, from HAML/XML input file."
|
48
68
|
long_desc <<-LONGDESC
|
49
69
|
|
50
70
|
Build questions about contents defined into input file specified.
|
@@ -53,15 +73,14 @@ class CLI < Thor
|
|
53
73
|
|
54
74
|
Examples:
|
55
75
|
|
56
|
-
(1) #{Rainbow(
|
76
|
+
(1) #{Rainbow("asker foo/bar.haml").aqua}, Build questions from HAML input file.
|
77
|
+
Path to input file can be relative or absolute.
|
57
78
|
|
58
|
-
(2) #{Rainbow(
|
59
|
-
|
60
|
-
(3) #{Rainbow('asker projects/foo/foo.yaml').aqua}, Build questions from YAML project file.
|
79
|
+
(2) #{Rainbow("asker foo/bar.xml").aqua}, Build questions from XML input file.
|
80
|
+
Path to input file can be relative or absolute.
|
61
81
|
|
62
82
|
LONGDESC
|
63
83
|
def file(filename)
|
64
|
-
# Asker start processing input file
|
65
84
|
Asker.start(filename)
|
66
85
|
end
|
67
86
|
|
data/lib/asker/data/code.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "../ai/code/code_ai_factory"
|
4
|
+
require_relative "../logger"
|
4
5
|
|
5
6
|
class Code
|
6
7
|
attr_reader :dirname, :filename, :type
|
@@ -23,7 +24,7 @@ class Code
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def lines_to_s(lines)
|
26
|
-
out =
|
27
|
+
out = ""
|
27
28
|
lines.each_with_index do |line, index|
|
28
29
|
out << format("%2d| #{line}\n", (index + 1))
|
29
30
|
end
|
@@ -36,7 +37,7 @@ class Code
|
|
36
37
|
return if filepath.nil?
|
37
38
|
|
38
39
|
unless File.exist? filepath
|
39
|
-
|
40
|
+
Logger.warn "Code: Unknown file (#{filepath})"
|
40
41
|
return
|
41
42
|
end
|
42
43
|
content = File.read(filepath)
|
@@ -45,16 +46,16 @@ class Code
|
|
45
46
|
|
46
47
|
def encode_and_split(text, encoding = :default)
|
47
48
|
# Convert text to UTF-8 deleting unknown chars
|
48
|
-
text ||=
|
49
|
-
flag = [:default,
|
50
|
-
return text.encode(
|
49
|
+
text ||= "" # Ensure text is not nil
|
50
|
+
flag = [:default, "UTF-8"].include? encoding
|
51
|
+
return text.encode("UTF-8", invalid: :replace).split("\n") if flag
|
51
52
|
|
52
53
|
# Convert text from input ENCODING to UTF-8
|
53
|
-
ec = Encoding::Converter.new(encoding.to_s,
|
54
|
+
ec = Encoding::Converter.new(encoding.to_s, "UTF-8")
|
54
55
|
begin
|
55
56
|
text = ec.convert(text)
|
56
|
-
rescue
|
57
|
-
|
57
|
+
rescue => e
|
58
|
+
Logger.warn "Code: Encoding error (#{e}) with filename (#{@filename})"
|
58
59
|
end
|
59
60
|
|
60
61
|
text.split("\n")
|
data/lib/asker/data/column.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../logger"
|
4
|
+
|
3
5
|
# Contain data information for every column
|
4
6
|
# Params:
|
5
7
|
# * +pRow+ - Parent row for this column
|
@@ -9,28 +11,27 @@ class Column
|
|
9
11
|
attr_reader :row, :index, :id, :raw, :lang, :type, :simple
|
10
12
|
|
11
13
|
##
|
12
|
-
# initialize Column
|
13
14
|
# @param row (Row)
|
14
15
|
# @param index (Integer)
|
15
16
|
# @param xml_data (XMLdata)
|
16
17
|
def initialize(row, index, xml_data)
|
17
|
-
@row
|
18
|
-
@index
|
19
|
-
@id
|
20
|
-
@raw
|
21
|
-
@lang
|
22
|
-
@type
|
23
|
-
@simple = {
|
18
|
+
@row = row
|
19
|
+
@index = index
|
20
|
+
@id = "#{@row.id}.#{@index}"
|
21
|
+
@raw = ""
|
22
|
+
@lang = @row.langs[@index]
|
23
|
+
@type = @row.types[@index]
|
24
|
+
@simple = {lang: true, type: true}
|
24
25
|
read_data_from_xml(xml_data)
|
25
26
|
end
|
26
27
|
|
27
28
|
def to_html
|
28
29
|
case @type
|
29
|
-
when
|
30
|
+
when "text"
|
30
31
|
return @raw
|
31
|
-
when
|
32
|
-
return "<img src=\"#{raw}\" alt
|
33
|
-
when
|
32
|
+
when "image_url"
|
33
|
+
return "<img src=\"#{raw}\" alt=\"image\">"
|
34
|
+
when "textfile_path"
|
34
35
|
return "<pre>#{raw}</pre>"
|
35
36
|
end
|
36
37
|
"ERROR type #{@type}"
|
@@ -39,7 +40,10 @@ class Column
|
|
39
40
|
private
|
40
41
|
|
41
42
|
def read_data_from_xml(xml_data)
|
42
|
-
|
43
|
+
if xml_data.elements.count.positive?
|
44
|
+
Logger.error "Column: Do not use elements!"
|
45
|
+
exit 1
|
46
|
+
end
|
43
47
|
|
44
48
|
@raw = xml_data.text.strip.to_s
|
45
49
|
|
@@ -49,9 +53,9 @@ class Column
|
|
49
53
|
end
|
50
54
|
|
51
55
|
def read_lang_from_xml(xml_data)
|
52
|
-
return unless xml_data.attributes[
|
56
|
+
return unless xml_data.attributes["lang"]
|
53
57
|
|
54
|
-
code = xml_data.attributes[
|
58
|
+
code = xml_data.attributes["lang"].strip
|
55
59
|
return if code == @lang.code
|
56
60
|
|
57
61
|
@lang = LangFactory.instance.get(code)
|
@@ -60,9 +64,9 @@ class Column
|
|
60
64
|
end
|
61
65
|
|
62
66
|
def read_type_from_xml(xml_data)
|
63
|
-
return unless xml_data.attributes[
|
67
|
+
return unless xml_data.attributes["type"]
|
64
68
|
|
65
|
-
type = xml_data.attributes[
|
69
|
+
type = xml_data.attributes["type"].strip
|
66
70
|
return if type == @type.to_s
|
67
71
|
|
68
72
|
@type = type
|
data/lib/asker/data/concept.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
require
|
2
|
-
require 'rexml/document'
|
1
|
+
require "rexml/document"
|
3
2
|
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
3
|
+
require_relative "../lang/lang_factory"
|
4
|
+
require_relative "../loader/embedded_file"
|
5
|
+
require_relative "../logger"
|
6
|
+
require_relative "table"
|
7
|
+
require_relative "data_field"
|
8
8
|
|
9
9
|
class Concept
|
10
10
|
attr_reader :id # Unique identifer (Integer)
|
11
|
-
attr_reader :lang # Lang
|
11
|
+
attr_reader :lang # Lang object
|
12
12
|
attr_reader :context # Context inherits from map
|
13
13
|
attr_reader :names # Names used to identify or name this concept
|
14
14
|
attr_reader :type # type = text -> Name values are only text
|
@@ -24,24 +24,16 @@ class Concept
|
|
24
24
|
# @param filename (String)
|
25
25
|
# @param lang_code (String)
|
26
26
|
# @param context (Array)
|
27
|
-
def initialize(xml_data, filename,
|
27
|
+
def initialize(xml_data, filename, lang, context)
|
28
28
|
@@id += 1
|
29
29
|
@id = @@id
|
30
30
|
|
31
31
|
@filename = filename
|
32
32
|
@process = false
|
33
|
-
@lang = LangFactory.instance.get(lang_code)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
elsif context.nil?
|
38
|
-
@context = []
|
39
|
-
else
|
40
|
-
@context = context.split(',')
|
41
|
-
@context.collect!(&:strip)
|
42
|
-
end
|
43
|
-
@names = ['concept.' + @id.to_s]
|
44
|
-
@type = 'text'
|
33
|
+
@lang = lang # LangFactory.instance.get(lang_code)
|
34
|
+
@context = context
|
35
|
+
@names = ["concept." + @id.to_s]
|
36
|
+
@type = "text"
|
45
37
|
|
46
38
|
@data = {}
|
47
39
|
@data[:tags] = []
|
@@ -60,7 +52,7 @@ class Concept
|
|
60
52
|
end
|
61
53
|
|
62
54
|
def text
|
63
|
-
@data[:texts][0] ||
|
55
|
+
@data[:texts][0] || "..."
|
64
56
|
end
|
65
57
|
|
66
58
|
def process?
|
@@ -71,16 +63,14 @@ class Concept
|
|
71
63
|
p = calculate_nearness_to_concept(other)
|
72
64
|
return if p.zero?
|
73
65
|
|
74
|
-
@data[:neighbors] << {
|
66
|
+
@data[:neighbors] << {concept: other, value: p}
|
75
67
|
# Sort neighbors list
|
76
68
|
@data[:neighbors].sort! { |a, b| a[:value] <=> b[:value] }
|
77
69
|
@data[:neighbors].reverse!
|
78
70
|
end
|
79
71
|
|
80
72
|
def calculate_nearness_to_concept(other)
|
81
|
-
|
82
|
-
# Application.instance.config['ai']['formula_weights']
|
83
|
-
weights = a.split(',').map(&:to_f)
|
73
|
+
weights = ProjectData.instance.get(:weights).split(",").map(&:to_f)
|
84
74
|
|
85
75
|
max1 = @context.count
|
86
76
|
max2 = @data[:tags].count
|
@@ -105,7 +95,7 @@ class Concept
|
|
105
95
|
end
|
106
96
|
@data[:texts].each do |t|
|
107
97
|
text = t.clone
|
108
|
-
text.split(
|
98
|
+
text.split(" ").each do |word|
|
109
99
|
reference_to += 1 unless other.names.index(word.downcase).nil?
|
110
100
|
end
|
111
101
|
end
|
@@ -157,26 +147,25 @@ class Concept
|
|
157
147
|
when "table"
|
158
148
|
@data[:tables] << Table.new(self, i)
|
159
149
|
else
|
160
|
-
|
161
|
-
puts Rainbow(text).color(:red)
|
150
|
+
Logger.warn "Concept #{name} with unkown attribute: #{i.name}"
|
162
151
|
end
|
163
152
|
end
|
164
153
|
end
|
165
154
|
|
166
155
|
def process_names(value)
|
167
156
|
@names = []
|
168
|
-
j = value.text.split(
|
157
|
+
j = value.text.split(",")
|
169
158
|
j.each { |k| @names << k.strip }
|
170
|
-
@type = value.attributes[
|
159
|
+
@type = value.attributes["type"].strip if value.attributes["type"]
|
171
160
|
end
|
172
161
|
|
173
162
|
def process_tags(value)
|
174
163
|
if value.text.nil? || value.text.size.zero?
|
175
|
-
|
176
|
-
|
164
|
+
Logger.warn "Concept: Concept #{name} without <tags>"
|
165
|
+
return []
|
177
166
|
end
|
178
167
|
|
179
|
-
@data[:tags] = value.text.split(
|
168
|
+
@data[:tags] = value.text.split(",")
|
180
169
|
@data[:tags].collect!(&:strip)
|
181
170
|
end
|
182
171
|
|
@@ -190,14 +179,12 @@ class Concept
|
|
190
179
|
@data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
|
191
180
|
when nil
|
192
181
|
if value.text.nil?
|
193
|
-
warn
|
182
|
+
Logger.warn "Concept: def/text empty!"
|
194
183
|
else
|
195
184
|
@data[:texts] << value.text.strip
|
196
185
|
end
|
197
186
|
else
|
198
|
-
|
199
|
-
puts Rainbow(msg).red.bright
|
200
|
-
exit 1
|
187
|
+
Logger.warn "Concept: Unknown def/type (#{value.attributes["type"]})"
|
201
188
|
end
|
202
189
|
end
|
203
190
|
end
|
@@ -12,7 +12,7 @@ class DataField
|
|
12
12
|
# initialize DataField
|
13
13
|
def initialize(data, id, type)
|
14
14
|
@data = data
|
15
|
-
@id
|
15
|
+
@id = id.to_i # TODO: revise where it comes from? Is it unique value?
|
16
16
|
@type = type.to_sym
|
17
17
|
end
|
18
18
|
|
@@ -94,7 +94,7 @@ class DataField
|
|
94
94
|
# rubocop:enable Metrics/MethodLength
|
95
95
|
|
96
96
|
def to_screen(text)
|
97
|
-
return text[0, 7] +
|
97
|
+
return text[0, 7] + "..." + text[-15, 15] if text.size > 25
|
98
98
|
|
99
99
|
text
|
100
100
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require_relative "../logger"
|
2
|
+
|
3
|
+
class Problem
|
4
|
+
attr_accessor :lang
|
5
|
+
attr_accessor :context
|
6
|
+
attr_accessor :process
|
7
|
+
attr_accessor :filename
|
8
|
+
attr_accessor :varnames
|
9
|
+
attr_accessor :cases
|
10
|
+
attr_accessor :descs
|
11
|
+
attr_accessor :asks
|
12
|
+
attr_accessor :questions
|
13
|
+
|
14
|
+
@@id = 0
|
15
|
+
def initialize
|
16
|
+
@@id += 1
|
17
|
+
@id = @@id
|
18
|
+
@lang = nil
|
19
|
+
@context = nil
|
20
|
+
@process = false
|
21
|
+
@filename = "?"
|
22
|
+
@varnames = []
|
23
|
+
@cases = []
|
24
|
+
@descs = []
|
25
|
+
@asks = []
|
26
|
+
@questions = []
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.from(values)
|
30
|
+
problem = Problem.new
|
31
|
+
fields = %i[filename varnames cases descs asks]
|
32
|
+
fields.each do |fieldname|
|
33
|
+
methodname = "#{fieldname}=".to_sym
|
34
|
+
problem.send(methodname, values[fieldname])
|
35
|
+
end
|
36
|
+
problem.validate
|
37
|
+
problem
|
38
|
+
end
|
39
|
+
|
40
|
+
def desc
|
41
|
+
@descs.first
|
42
|
+
end
|
43
|
+
|
44
|
+
def process?
|
45
|
+
@process
|
46
|
+
end
|
47
|
+
|
48
|
+
def name
|
49
|
+
"problem#{@id}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate
|
53
|
+
validate_varnames
|
54
|
+
validate_cases
|
55
|
+
validate_asks
|
56
|
+
validate_descs
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def validate_varnames
|
62
|
+
if !@varnames.size.zero? && @cases.size.zero?
|
63
|
+
Logger.warn "Problem: No problem/varnames defined with no problem/case"
|
64
|
+
end
|
65
|
+
|
66
|
+
@varnames.each_with_index do |varname1, index1|
|
67
|
+
@varnames.each_with_index do |varname2, index2|
|
68
|
+
next if index1 == index2
|
69
|
+
if varname1.include? varname2
|
70
|
+
Logger.error "Problem: varname(#{varname1}) includes varname(#{varname2}). Change one of them!"
|
71
|
+
exit 1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate_cases
|
78
|
+
@cases.each do |acase|
|
79
|
+
if acase.size != @varnames.size
|
80
|
+
Logger.error "Problem: problem/cases size not equal to problem/varnames size"
|
81
|
+
Logger.error " : cases size #{acase.size} (#{acase.join(",")})"
|
82
|
+
Logger.error " : varnames size #{@varnames.size} (#{@varnames.join(",")})"
|
83
|
+
exit 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def validate_asks
|
89
|
+
if @asks.size.zero?
|
90
|
+
Logger.warn "Problem: No problem/ask"
|
91
|
+
end
|
92
|
+
|
93
|
+
@asks.each do |ask|
|
94
|
+
Logger.warn "Problem: No problem/ask/text" if ask[:text].nil?
|
95
|
+
if ask[:answer].nil? && ask[:steps].size.zero?
|
96
|
+
Logger.error "Problem: No problem/ask/answer and no problem/ask/steps"
|
97
|
+
exit 1
|
98
|
+
end
|
99
|
+
if !ask[:answer].nil? && !ask[:steps].size.zero?
|
100
|
+
Logger.error "Problem: Choose problem/ask/answer or problem/ask/steps"
|
101
|
+
exit 1
|
102
|
+
end
|
103
|
+
if ask[:steps].size > 0 && ask[:steps].size < 4
|
104
|
+
Logger.warn "Problem: problem/ask/steps less than 4"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def validate_descs
|
110
|
+
# require "debug"; binding.break
|
111
|
+
end
|
112
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "singleton"
|
4
4
|
|
5
5
|
class ProjectData
|
6
6
|
include Singleton
|
@@ -11,11 +11,11 @@ class ProjectData
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def reset
|
14
|
-
@default = {
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
@default = {inputbasedir: FileUtils.pwd,
|
15
|
+
stages: {d: true, b: true, f: true, i: true, s: true, t: true},
|
16
|
+
threshold: 0.5,
|
17
|
+
outputdir: "output",
|
18
|
+
weights: "1, 1, 1"}
|
19
19
|
@param = {}
|
20
20
|
end
|
21
21
|
|
@@ -36,17 +36,15 @@ class ProjectData
|
|
36
36
|
# IMPORTANT: We need at least these values
|
37
37
|
# * process_file
|
38
38
|
# * inputdirs
|
39
|
-
# rubocop:disable Metrics/MethodLength
|
40
|
-
# rubocop:disable Metrics/AbcSize
|
41
39
|
def open
|
42
|
-
ext = File.extname(@param[:process_file]) ||
|
40
|
+
ext = File.extname(@param[:process_file]) || ".haml"
|
43
41
|
@param[:projectname] = @param[:projectname] ||
|
44
|
-
|
42
|
+
File.basename(@param[:process_file], ext)
|
45
43
|
|
46
|
-
@param[:logname] = "#{@param[:projectname]}
|
44
|
+
@param[:logname] = "#{@param[:projectname]}.log"
|
47
45
|
@param[:outputname] = "#{@param[:projectname]}-gift.txt"
|
48
|
-
@param[:lessonname] = "#{@param[:projectname]}
|
49
|
-
@param[:yamlname] = "#{@param[:projectname]}.yaml"
|
46
|
+
@param[:lessonname] = "#{@param[:projectname]}.txt"
|
47
|
+
@param[:yamlname] = "#{@param[:projectname]}-questions.yaml"
|
50
48
|
@param[:moodlename] = "#{@param[:projectname]}-moodle.xml"
|
51
49
|
|
52
50
|
outputdir = get(:outputdir)
|
@@ -58,6 +56,4 @@ class ProjectData
|
|
58
56
|
|
59
57
|
Dir.mkdir(outputdir) unless Dir.exist?(outputdir)
|
60
58
|
end
|
61
|
-
# rubocop:enable Metrics/MethodLength
|
62
|
-
# rubocop:enable Metrics/AbcSize
|
63
59
|
end
|
data/lib/asker/data/row.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "column"
|
4
|
+
require_relative "../logger"
|
4
5
|
|
5
|
-
##
|
6
|
-
# Row objects
|
7
6
|
class Row
|
8
7
|
attr_reader :table, :index, :id
|
9
8
|
attr_reader :langs, :types, :raws, :columns
|
@@ -15,14 +14,14 @@ class Row
|
|
15
14
|
# @param index (Integer)
|
16
15
|
# @param xml_data (XML)
|
17
16
|
def initialize(table, index, xml_data)
|
18
|
-
@table
|
19
|
-
@index
|
20
|
-
@id
|
21
|
-
@langs
|
22
|
-
@types
|
23
|
-
@raws
|
17
|
+
@table = table
|
18
|
+
@index = index
|
19
|
+
@id = "#{@table.id}.#{@index}"
|
20
|
+
@langs = @table.langs
|
21
|
+
@types = @table.types
|
22
|
+
@raws = []
|
24
23
|
@columns = []
|
25
|
-
@simple
|
24
|
+
@simple = {lang: true, type: true}
|
26
25
|
read_data_from_xml(xml_data)
|
27
26
|
end
|
28
27
|
|
@@ -40,14 +39,17 @@ class Row
|
|
40
39
|
build_row_with_n_columns(xml_data)
|
41
40
|
end
|
42
41
|
|
43
|
-
|
42
|
+
unless @columns.size == @table.fields.size
|
43
|
+
Logger.error "Row: columns size != table.fields.size (#{xml_data})"
|
44
|
+
exit 1
|
45
|
+
end
|
44
46
|
end
|
45
47
|
|
46
48
|
def build_row_with_1_column(xml_data)
|
47
49
|
# When row tag only has text, we add this text as one value array
|
48
50
|
# This is usefull for tables with only one columns
|
49
51
|
@columns = [Column.new(self, @raws.size, xml_data)]
|
50
|
-
@raws
|
52
|
+
@raws = [xml_data.text.strip.to_s]
|
51
53
|
|
52
54
|
# read attributes from XML data
|
53
55
|
read_lang_from_xml(xml_data)
|
@@ -55,9 +57,9 @@ class Row
|
|
55
57
|
end
|
56
58
|
|
57
59
|
def read_lang_from_xml(xml_data)
|
58
|
-
return unless xml_data.attributes[
|
60
|
+
return unless xml_data.attributes["lang"]
|
59
61
|
|
60
|
-
code = xml_data.attributes[
|
62
|
+
code = xml_data.attributes["lang"].strip
|
61
63
|
return if code == @langs[0].code
|
62
64
|
|
63
65
|
@langs = [LangFactory.instance.get(code)]
|
@@ -66,9 +68,9 @@ class Row
|
|
66
68
|
end
|
67
69
|
|
68
70
|
def read_type_from_xml(xml_data)
|
69
|
-
return unless xml_data.attributes[
|
71
|
+
return unless xml_data.attributes["type"]
|
70
72
|
|
71
|
-
type = xml_data.attributes[
|
73
|
+
type = xml_data.attributes["type"].strip
|
72
74
|
return if type == @types[0]
|
73
75
|
|
74
76
|
@types = [type]
|
@@ -80,11 +82,11 @@ class Row
|
|
80
82
|
def build_row_with_n_columns(xml_data)
|
81
83
|
xml_data.elements.each do |i|
|
82
84
|
case i.name
|
83
|
-
when
|
85
|
+
when "lang"
|
84
86
|
read_langs_from_xml(i)
|
85
|
-
when
|
87
|
+
when "type"
|
86
88
|
read_types_from_xml(i)
|
87
|
-
when
|
89
|
+
when "col"
|
88
90
|
# When row has several columns, we add every value to the array
|
89
91
|
@columns << Column.new(self, @raws.size, i) # Column Objects
|
90
92
|
@raws << i.text.to_s
|
@@ -94,9 +96,9 @@ class Row
|
|
94
96
|
# rubocop:enable Metrics/MethodLength
|
95
97
|
|
96
98
|
def read_langs_from_xml(xml_data)
|
97
|
-
j = xml_data.text.split(
|
99
|
+
j = xml_data.text.split(",")
|
98
100
|
codes = @langs.map(&:code)
|
99
|
-
return if j.join(
|
101
|
+
return if j.join(",") == codes.join(",")
|
100
102
|
|
101
103
|
@langs = []
|
102
104
|
j.each { |k| @langs << LangFactory.instance.get(k.strip.to_s) }
|
@@ -105,8 +107,8 @@ class Row
|
|
105
107
|
end
|
106
108
|
|
107
109
|
def read_types_from_xml(xml_data)
|
108
|
-
j = xml_data.text.split(
|
109
|
-
return if j.join(
|
110
|
+
j = xml_data.text.split(",")
|
111
|
+
return if j.join(",") == @types.join(",")
|
110
112
|
|
111
113
|
@types = []
|
112
114
|
j.each { |k| @types << k.strip.to_s }
|