asker-tool 2.6.0 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 }
|