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.
- checksums.yaml +4 -4
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +1 -1
- data/bin/asker +1 -1
- data/lib/asker/ai/ai.rb +6 -3
- data/lib/asker/ai/ai_calculate.rb +20 -6
- data/lib/asker/ai/concept_ai.rb +11 -2
- data/lib/asker/ai/question.rb +28 -6
- data/lib/asker/ai/stages/base_stage.rb +45 -6
- data/lib/asker/ai/stages/stage_b.rb +100 -50
- data/lib/asker/ai/stages/stage_d.rb +75 -90
- data/lib/asker/ai/stages/stage_f.rb +64 -36
- data/lib/asker/ai/stages/stage_i.rb +79 -92
- data/lib/asker/ai/stages/stage_s.rb +41 -36
- data/lib/asker/ai/stages/stage_t.rb +114 -73
- data/lib/asker/application.rb +8 -7
- data/lib/asker/checker.rb +6 -8
- data/lib/asker/cli.rb +27 -9
- data/lib/asker/data/code.rb +4 -1
- data/lib/asker/data/concept.rb +67 -21
- data/lib/asker/data/table.rb +2 -0
- data/lib/asker/data/template.rb +3 -1
- data/lib/asker/data/world.rb +7 -4
- data/lib/asker/displayer/code_displayer.rb +7 -0
- data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
- data/lib/asker/displayer/concept_ai_displayer.rb +23 -22
- data/lib/asker/displayer/concept_displayer.rb +9 -4
- data/lib/asker/displayer/stats_displayer.rb +8 -0
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +7 -11
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +6 -3
- data/lib/asker/exporter/concept_doc_exporter.rb +14 -1
- data/lib/asker/exporter/data_gift_exporter.rb +29 -0
- data/lib/asker/exporter/output_file_exporter.rb +9 -6
- data/lib/asker/files/{config.ini → asker.ini} +14 -4
- data/lib/asker/files/language/du/connectors.yaml +81 -0
- data/lib/asker/files/language/du/mistakes.yaml +82 -0
- data/lib/asker/files/language/du/templates.yaml +28 -49
- data/lib/asker/files/language/en/templates.yaml +19 -19
- data/lib/asker/files/language/es/mistakes.yaml +9 -7
- data/lib/asker/files/language/es/templates.yaml +19 -19
- data/lib/asker/files/language/fr/connectors.yaml +68 -84
- data/lib/asker/files/language/fr/templates.yaml +22 -22
- data/lib/asker/formatter/concept_string_formatter.rb +7 -4
- data/lib/asker/formatter/moodle/matching.erb +38 -0
- data/lib/asker/formatter/moodle/multichoice.erb +49 -0
- data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
- data/lib/asker/formatter/moodle/truefalse.erb +47 -0
- data/lib/asker/formatter/question_gift_formatter.rb +21 -19
- data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
- data/lib/asker/lang/lang_factory.rb +7 -1
- data/lib/asker/loader/code_loader.rb +1 -1
- data/lib/asker/loader/content_loader.rb +7 -7
- data/lib/asker/loader/directory_loader.rb +3 -3
- data/lib/asker/loader/embedded_file.rb +42 -0
- data/lib/asker/loader/file_loader.rb +1 -1
- data/lib/asker/loader/image_url_loader.rb +4 -3
- data/lib/asker/loader/input_loader.rb +1 -1
- data/lib/asker/loader/project_loader.rb +14 -5
- data/lib/asker/logger.rb +29 -4
- data/lib/asker/project.rb +14 -79
- data/lib/asker/skeleton.rb +3 -2
- data/lib/asker.rb +37 -9
- metadata +19 -22
@@ -12,12 +12,11 @@ module ConceptStringFormatter
|
|
12
12
|
def self.to_s(concept)
|
13
13
|
tt = Terminal::Table.new
|
14
14
|
get_tt_rows(concept).each { |row| tt.add_row row }
|
15
|
-
|
15
|
+
tt.to_s
|
16
16
|
end
|
17
17
|
|
18
18
|
# rubocop:disable Metrics/AbcSize
|
19
19
|
# rubocop:disable Metrics/MethodLength
|
20
|
-
# rubocop:disable Layout/LineLength
|
21
20
|
private_class_method def self.get_tt_rows(concept)
|
22
21
|
rows = []
|
23
22
|
rows << [Rainbow(concept.id.to_s).bright,
|
@@ -31,13 +30,17 @@ module ConceptStringFormatter
|
|
31
30
|
rows << [Rainbow('Referenced by').blue,
|
32
31
|
concept.referenced_by.join(', ')[0...70].to_s]
|
33
32
|
rows << format_texts(concept)
|
34
|
-
|
33
|
+
unless concept.images.size.zero?
|
34
|
+
counter1 = 0
|
35
|
+
concept.images.each { |image| counter1 += 1 if image[:file] == :none }
|
36
|
+
counter2 = concept.images.size - counter1
|
37
|
+
rows << [Rainbow('.def(images)').blue, "#{counter1} text / #{counter2} file"]
|
38
|
+
end
|
35
39
|
rows << format_tables(concept) unless concept.tables.count.zero?
|
36
40
|
rows << format_neighbors(concept)
|
37
41
|
end
|
38
42
|
# rubocop:enable Metrics/AbcSize
|
39
43
|
# rubocop:enable Metrics/MethodLength
|
40
|
-
# rubocop:enable Layout/LineLength
|
41
44
|
|
42
45
|
private_class_method def self.format_texts(concept)
|
43
46
|
list = []
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<% unless question.comment.nil? || question.comment.empty? %>
|
2
|
+
<!-- question: <%= question.comment %> -->
|
3
|
+
<% end %>
|
4
|
+
<question type="matching">
|
5
|
+
<name>
|
6
|
+
<text><%= question.name %></text>
|
7
|
+
</name>
|
8
|
+
<questiontext format="html">
|
9
|
+
<text><![CDATA[<%= question.text %>]]></text>
|
10
|
+
<% unless question.encode == :none %>
|
11
|
+
<%= question.encode %>
|
12
|
+
<% end %>
|
13
|
+
</questiontext>
|
14
|
+
<generalfeedback format="html">
|
15
|
+
<text><![CDATA[<%= question.feedback.to_s %>]]></text>
|
16
|
+
</generalfeedback>
|
17
|
+
<defaultgrade>1.0000000</defaultgrade>
|
18
|
+
<penalty>0.3333333</penalty>
|
19
|
+
<hidden>0</hidden>
|
20
|
+
<shuffleanswers>true</shuffleanswers>
|
21
|
+
<correctfeedback format="html">
|
22
|
+
<text></text>
|
23
|
+
</correctfeedback>
|
24
|
+
<partiallycorrectfeedback format="html">
|
25
|
+
<text></text>
|
26
|
+
</partiallycorrectfeedback>
|
27
|
+
<incorrectfeedback format="html">
|
28
|
+
<text></text>
|
29
|
+
</incorrectfeedback>
|
30
|
+
<% question.matching.each do |i, j| %>
|
31
|
+
<subquestion format="html">
|
32
|
+
<text><![CDATA[<%= i %>]]></text>
|
33
|
+
<answer>
|
34
|
+
<text><![CDATA[<%= j %>]]></text>
|
35
|
+
</answer>
|
36
|
+
</subquestion>
|
37
|
+
<% end %>
|
38
|
+
</question>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<% unless question.comment.nil? || question.comment.empty? %>
|
2
|
+
<!-- question: <%= question.comment %> -->
|
3
|
+
<% end %>
|
4
|
+
<question type="multichoice">
|
5
|
+
<name>
|
6
|
+
<text><%= question.name %></text>
|
7
|
+
</name>
|
8
|
+
<questiontext format="html">
|
9
|
+
<text><![CDATA[<%= question.text %>]]></text>
|
10
|
+
<% unless question.encode == :none %>
|
11
|
+
<%= question.encode %>
|
12
|
+
<% end %>
|
13
|
+
</questiontext>
|
14
|
+
<generalfeedback format="html">
|
15
|
+
<text><![CDATA[<%= question.feedback.to_s %>]]></text>
|
16
|
+
</generalfeedback>
|
17
|
+
<defaultgrade>1.0000000</defaultgrade>
|
18
|
+
<penalty>0.3333333</penalty>
|
19
|
+
<hidden>0</hidden>
|
20
|
+
<single>true</single>
|
21
|
+
<shuffleanswers>true</shuffleanswers>
|
22
|
+
<answernumbering>abc</answernumbering>
|
23
|
+
<correctfeedback format="html">
|
24
|
+
<text></text>
|
25
|
+
</correctfeedback>
|
26
|
+
<partiallycorrectfeedback format="html">
|
27
|
+
<text></text>
|
28
|
+
</partiallycorrectfeedback>
|
29
|
+
<incorrectfeedback format="html">
|
30
|
+
<text></text>
|
31
|
+
</incorrectfeedback>
|
32
|
+
<answer fraction="100" format="html">
|
33
|
+
<text><%= question.good %></text>
|
34
|
+
<feedback format="html">
|
35
|
+
<text></text>
|
36
|
+
</feedback>
|
37
|
+
</answer>
|
38
|
+
<%
|
39
|
+
question.bads.shuffle! if question.shuffle?
|
40
|
+
question.bads.each do |i|
|
41
|
+
%>
|
42
|
+
<answer fraction="<%= penalty %>" format="html">
|
43
|
+
<text><![CDATA[<%= i %>]]></text>
|
44
|
+
<feedback format="html">
|
45
|
+
<text></text>
|
46
|
+
</feedback>
|
47
|
+
</answer>
|
48
|
+
<% end %>
|
49
|
+
</question>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<% unless question.comment.nil? || question.comment.empty? %>
|
2
|
+
<!-- question: <%= question.comment %> -->
|
3
|
+
<% end %>
|
4
|
+
<question type="shortanswer">
|
5
|
+
<name>
|
6
|
+
<text><%= question.name %></text>
|
7
|
+
</name>
|
8
|
+
<questiontext format="html">
|
9
|
+
<text><![CDATA[<%= question.text %>]]></text>
|
10
|
+
<% unless question.encode == :none %>
|
11
|
+
<%= question.encode %>
|
12
|
+
<% end %>
|
13
|
+
</questiontext>
|
14
|
+
<generalfeedback format="html">
|
15
|
+
<text><![CDATA[<%= question.feedback.to_s %>]]></text>
|
16
|
+
</generalfeedback>
|
17
|
+
<defaultgrade>1.0000000</defaultgrade>
|
18
|
+
<penalty>0.3333333</penalty>
|
19
|
+
<hidden>0</hidden>
|
20
|
+
<usecase>0</usecase>
|
21
|
+
<% question.shorts.uniq! %>
|
22
|
+
<% question.shorts.each do |i| %>
|
23
|
+
<answer fraction="100" format="moodle_auto_format">
|
24
|
+
<text><![CDATA[<%= i %>]]></text>
|
25
|
+
<feedback format="html">
|
26
|
+
<text></text>
|
27
|
+
</feedback>
|
28
|
+
</answer>
|
29
|
+
<% end %>
|
30
|
+
</question>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<% unless question.comment.nil? || question.comment.empty? %>
|
2
|
+
<!-- question: <%= question.comment %> -->
|
3
|
+
<% end %>
|
4
|
+
<question type="truefalse">
|
5
|
+
<name>
|
6
|
+
<text><%= question.name %></text>
|
7
|
+
</name>
|
8
|
+
<questiontext format="html">
|
9
|
+
<text><![CDATA[<%= question.text %>]]></text>
|
10
|
+
<% unless question.encode == :none %>
|
11
|
+
<%= question.encode %>
|
12
|
+
<% end %>
|
13
|
+
</questiontext>
|
14
|
+
<generalfeedback format="html">
|
15
|
+
<text><![CDATA[<%= question.feedback.to_s %>]]></text>
|
16
|
+
</generalfeedback>
|
17
|
+
<defaultgrade>1.0000000</defaultgrade>
|
18
|
+
<penalty>1.0000000</penalty>
|
19
|
+
<hidden>0</hidden>
|
20
|
+
<% if question.good == 'TRUE' %>
|
21
|
+
<answer fraction="100" format="moodle_auto_format">
|
22
|
+
<text>true</text>
|
23
|
+
<feedback format="html">
|
24
|
+
<text></text>
|
25
|
+
</feedback>
|
26
|
+
</answer>
|
27
|
+
<answer fraction="0" format="moodle_auto_format">
|
28
|
+
<text>false</text>
|
29
|
+
<feedback format="html">
|
30
|
+
<text></text>
|
31
|
+
</feedback>
|
32
|
+
</answer>
|
33
|
+
<% else %>
|
34
|
+
<answer fraction="0" format="moodle_auto_format">
|
35
|
+
<text>true</text>
|
36
|
+
<feedback format="html">
|
37
|
+
<text></text>
|
38
|
+
</feedback>
|
39
|
+
</answer>
|
40
|
+
<answer fraction="100" format="moodle_auto_format">
|
41
|
+
<text>false</text>
|
42
|
+
<feedback format="html">
|
43
|
+
<text></text>
|
44
|
+
</feedback>
|
45
|
+
</answer>
|
46
|
+
<% end %>
|
47
|
+
</question>
|
@@ -7,50 +7,52 @@ module QuestionGiftFormatter
|
|
7
7
|
# @param question (Question)
|
8
8
|
# @return String
|
9
9
|
def self.to_s(question)
|
10
|
-
|
10
|
+
s = ''
|
11
|
+
return s unless question.encode == :none
|
12
|
+
|
11
13
|
# Return question using gift format
|
12
|
-
cond =
|
13
|
-
s = "// #{
|
14
|
-
s << "::#{
|
14
|
+
cond = question.comment.nil? || question.comment.empty?
|
15
|
+
s = "// #{question.comment}\n" unless cond
|
16
|
+
s << "::#{question.name}::[html]#{sanitize(question.text)}\n"
|
15
17
|
|
16
|
-
case
|
18
|
+
case question.type
|
17
19
|
when :choice
|
18
20
|
s += "{\n"
|
19
|
-
a = [" =#{sanitize(
|
21
|
+
a = [" =#{sanitize(question.good)}\n"]
|
20
22
|
penalties = ['', '%-50%', '%-33.33333%', '%-25%', '%-20%']
|
21
|
-
penalty = penalties[
|
23
|
+
penalty = penalties[question.bads.size]
|
22
24
|
|
23
|
-
|
24
|
-
a.shuffle! if
|
25
|
+
question.bads.each { |i| a << (" ~#{penalty}" + sanitize(i) + "\n") }
|
26
|
+
a.shuffle! if question.shuffle?
|
25
27
|
a.each do |i|
|
26
28
|
text = i
|
27
29
|
text = i[0, 220] + '...(ERROR: text too long)' if text.size > 255
|
28
30
|
s << text
|
29
31
|
end
|
30
|
-
s += " #####{sanitize(
|
32
|
+
s += " #####{sanitize(question.feedback.to_s)}\n" if question.feedback
|
31
33
|
s += "}\n\n"
|
32
34
|
when :boolean
|
33
|
-
s << "{#{
|
35
|
+
s << "{#{question.good}#####{sanitize(question.feedback.to_s)}}\n\n"
|
34
36
|
when :match
|
35
37
|
s << "{\n"
|
36
38
|
a = []
|
37
|
-
|
39
|
+
question.matching.each do |i, j|
|
38
40
|
i = i[0, 220] + '...(ERROR: text too long)' if i.size > 255
|
39
41
|
j = j[0, 220] + '...(ERROR: text too long)' if j.size > 255
|
40
42
|
a << " =#{sanitize(i)} -> #{sanitize(j)}\n"
|
41
43
|
end
|
42
|
-
a.shuffle! if
|
44
|
+
a.shuffle! if question.shuffle?
|
43
45
|
a.each { |i| s << i }
|
44
46
|
s << "}\n\n"
|
45
47
|
when :short
|
46
48
|
s << "{\n"
|
47
|
-
|
48
|
-
|
49
|
+
question.shorts.uniq!
|
50
|
+
question.shorts.each do |i|
|
49
51
|
text = i
|
50
52
|
text = i[0, 220] + '...(ERROR: too long)' if text.size > 255
|
51
53
|
s << " =%100%#{text}#\n"
|
52
54
|
end
|
53
|
-
s << " #####{sanitize(
|
55
|
+
s << " #####{sanitize(question.feedback.to_s)}\n" if question.feedback
|
54
56
|
s << "}\n\n"
|
55
57
|
end
|
56
58
|
s
|
@@ -62,10 +64,10 @@ module QuestionGiftFormatter
|
|
62
64
|
# @return String
|
63
65
|
def self.sanitize(input = '')
|
64
66
|
output = input.dup
|
65
|
-
output.gsub!(
|
67
|
+
output.gsub!('#', '\#')
|
66
68
|
output.gsub!("\n", " ")
|
67
|
-
|
68
|
-
output.gsub!(
|
69
|
+
output.gsub!(':', '\:')
|
70
|
+
output.gsub!('=', '\=')
|
69
71
|
output.gsub!("\{", "\\{")
|
70
72
|
output.gsub!("\}", "\\}")
|
71
73
|
output
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
# Transform Questions into Gift format
|
6
|
+
module QuestionMoodleFormatter
|
7
|
+
##
|
8
|
+
# Convert question object into gift formatted string
|
9
|
+
# @param question (Question)
|
10
|
+
# @return String
|
11
|
+
def self.to_s(question)
|
12
|
+
case question.type
|
13
|
+
when :choice
|
14
|
+
penalties = ['', '-50', '-33.33333', '-25', '-20']
|
15
|
+
penalty = penalties[question.bads.size]
|
16
|
+
template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'multichoice.erb'))
|
17
|
+
when :boolean
|
18
|
+
template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'truefalse.erb'))
|
19
|
+
when :match
|
20
|
+
template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'matching.erb'))
|
21
|
+
when :short
|
22
|
+
template = File.read(File.join(File.dirname(__FILE__), 'moodle', 'shortanswer.erb'))
|
23
|
+
end
|
24
|
+
renderer = ERB.new(template)
|
25
|
+
renderer.result(binding)
|
26
|
+
end
|
27
|
+
end
|
@@ -29,7 +29,13 @@ class LangFactory
|
|
29
29
|
# Return Lang object associated to code
|
30
30
|
# @param code (String)
|
31
31
|
def get(code)
|
32
|
-
@langs[code]
|
32
|
+
return @langs[code] unless @langs[code].nil?
|
33
|
+
|
34
|
+
puts Rainbow("[ERROR] Unkown Lang code: #{code}").bright
|
35
|
+
puts Rainbow(' => Change input file code lang').bright
|
36
|
+
puts Rainbow(' => Revise configuration from config.ini').bright
|
37
|
+
puts Rainbow(' => Revise template files').bright
|
38
|
+
exit 1
|
33
39
|
end
|
34
40
|
|
35
41
|
##
|
@@ -13,6 +13,8 @@ module ContentLoader
|
|
13
13
|
# Load XML content into Asker data objects
|
14
14
|
# @param filepath (String) File path
|
15
15
|
# @param content (String) XML plane text content
|
16
|
+
# rubocop:disable Metrics/MethodLength
|
17
|
+
# rubocop:disable Metrics/AbcSize
|
16
18
|
def self.load(filepath, content)
|
17
19
|
concepts = []
|
18
20
|
codes = []
|
@@ -37,6 +39,8 @@ module ContentLoader
|
|
37
39
|
|
38
40
|
{ concepts: concepts, codes: codes }
|
39
41
|
end
|
42
|
+
# rubocop:enable Metrics/MethodLength
|
43
|
+
# rubocop:enable Metrics/AbcSize
|
40
44
|
|
41
45
|
##
|
42
46
|
# Read lang attr from input XML data
|
@@ -71,9 +75,7 @@ module ContentLoader
|
|
71
75
|
private_class_method def self.read_concept(xmldata, filepath, lang, context)
|
72
76
|
project = Project.instance
|
73
77
|
c = Concept.new(xmldata, filepath, lang, context)
|
74
|
-
if [
|
75
|
-
c.process = true
|
76
|
-
end
|
78
|
+
c.process = true if [File.basename(filepath), :default].include? project.get(:process_file)
|
77
79
|
c
|
78
80
|
end
|
79
81
|
|
@@ -84,9 +86,7 @@ module ContentLoader
|
|
84
86
|
private_class_method def self.read_code(xmldata, filepath)
|
85
87
|
project = Project.instance
|
86
88
|
c = CodeLoader.load(xmldata, filepath)
|
87
|
-
if [
|
88
|
-
c.process = true
|
89
|
-
end
|
89
|
+
c.process = true if [File.basename(filepath), :default].include? project.get(:process_file)
|
90
90
|
c
|
91
91
|
end
|
92
92
|
|
@@ -96,7 +96,7 @@ module ContentLoader
|
|
96
96
|
# @param content (String)
|
97
97
|
private_class_method def self.raise_error_with(filepath, content)
|
98
98
|
msg = Rainbow("[ERROR] ContentLoader: Format error in #{filepath}").red.bright
|
99
|
-
Logger.
|
99
|
+
Logger.verboseln msg
|
100
100
|
f = File.open('output/error.xml', 'w')
|
101
101
|
f.write(content)
|
102
102
|
f.close
|
@@ -13,7 +13,7 @@ module DirectoryLoader
|
|
13
13
|
files = (Dir.new(dirname).entries - ['.', '..']).sort
|
14
14
|
# Accept only HAML or XML files
|
15
15
|
accepted = files.select { |f| %w[.xml .haml].include? File.extname(f) }
|
16
|
-
Logger.
|
16
|
+
Logger.verboseln " * Input directory = #{Rainbow(dirname).bright}"
|
17
17
|
DirectoryLoader.load_files(accepted, dirname)
|
18
18
|
end
|
19
19
|
|
@@ -49,9 +49,9 @@ module DirectoryLoader
|
|
49
49
|
# @param last (Boolean) True if it is the last filename
|
50
50
|
def self.load_file(filepath, last = false)
|
51
51
|
if last
|
52
|
-
Logger.
|
52
|
+
Logger.verboseln " └── Input file = #{Rainbow(filepath).bright}"
|
53
53
|
else
|
54
|
-
Logger.
|
54
|
+
Logger.verboseln " ├── Input file = #{Rainbow(filepath).bright}"
|
55
55
|
end
|
56
56
|
FileLoader.load(filepath)
|
57
57
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
# Methods to load embedded files defined into asker input data file
|
6
|
+
# Example:
|
7
|
+
# * def line with :type = :image_url used to link external file as https://..."
|
8
|
+
# * def line with :type = :file used to load local file as image.png or file.txt"
|
9
|
+
module EmbeddedFile
|
10
|
+
##
|
11
|
+
# @param value (String)
|
12
|
+
# @param localdir (String) Input file base folder
|
13
|
+
# @return Hash
|
14
|
+
# rubocop:disable Metrics/MethodLength
|
15
|
+
# rubocop:disable Metrics/AbcSize
|
16
|
+
def self.load(value, localdir)
|
17
|
+
# When filename is an URL
|
18
|
+
if value.start_with?('https://') || value.start_with?('http://')
|
19
|
+
return { text: "<img src=\"#{value}\" alt=\"image\" width=\"400\" height=\"300\">", file: :none }
|
20
|
+
end
|
21
|
+
|
22
|
+
filepath = File.join(localdir, value)
|
23
|
+
unless File.exist?(filepath)
|
24
|
+
# When filename is unkown!
|
25
|
+
Logger.verbose Rainbow("[ERROR] Unknown file! #{filepath}").red.bright
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
# When filename is PNG, JPG o JPEG
|
29
|
+
if ['.png', '.jpg', '.jpeg'].include? File.extname(filepath)
|
30
|
+
# converts image into base64 strings
|
31
|
+
text = '<img src="@@PLUGINFILE@@/' + File.basename(filepath) \
|
32
|
+
+ '" alt="imagen" class="img-responsive atto_image_button_text-bottom">'
|
33
|
+
data = '<file name="' + File.basename(filepath) + '" path="/" encoding="base64">' \
|
34
|
+
+ Base64.strict_encode64(File.open(filepath, 'rb').read) + '</file>'
|
35
|
+
return { text: text, file: data }
|
36
|
+
end
|
37
|
+
# Suposse that filename is TXT file
|
38
|
+
return { text: "<pre>#{File.read(filepath)}</pre>", file: :none } if File.exist?(filepath)
|
39
|
+
end
|
40
|
+
# rubocop:enable Metrics/MethodLength
|
41
|
+
# rubocop:enable Metrics/AbcSize
|
42
|
+
end
|
@@ -45,11 +45,12 @@ module ImageUrlLoader
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def self.sanitize_string(input)
|
48
|
+
text = input.dup
|
48
49
|
r = [ ['á', 'a'], ['é', 'e'], ['í', 'i'], ['ó', 'o'], ['ú', 'u'], ['ñ', 'n'], ['Á', 'A'], ['É', 'E'], ['Í', 'I'], ['Ó', 'O'], ['Ú', 'U'], ['Ñ', 'N']]
|
49
|
-
r.each { |item|
|
50
|
+
r.each { |item| text.gsub!(item[0], item[1]) }
|
50
51
|
r = ['-', '_', ',', '"']
|
51
|
-
r.each { |item|
|
52
|
-
|
52
|
+
r.each { |item| text.gsub!(item, ' ') }
|
53
|
+
text.split(' ')
|
53
54
|
end
|
54
55
|
|
55
56
|
def self.sanitize_array(input)
|
@@ -13,7 +13,7 @@ module InputLoader
|
|
13
13
|
def self.load(inputdirs)
|
14
14
|
data = { concepts: [], codes: [], world: nil,
|
15
15
|
concepts_ai: [], codes_ai: [] }
|
16
|
-
Logger.
|
16
|
+
Logger.verboseln "\n[INFO] Loading input data"
|
17
17
|
inputdirs.each do |dirname|
|
18
18
|
temp = DirectoryLoader.load(dirname)
|
19
19
|
data[:concepts] += temp[:concepts]
|
@@ -14,22 +14,26 @@ module ProjectLoader
|
|
14
14
|
##
|
15
15
|
# Load project from args
|
16
16
|
# @param args (String or Hash)
|
17
|
+
# rubocop:disable Metrics/MethodLength
|
17
18
|
def self.load(args)
|
18
19
|
project = Project.instance
|
19
20
|
|
20
21
|
if args.class == Hash
|
21
22
|
project.param.merge!(args)
|
23
|
+
project.open
|
22
24
|
return project
|
23
25
|
elsif args.class == String
|
24
26
|
ProjectLoader.load_from_string(args)
|
27
|
+
project.open
|
25
28
|
return project
|
26
29
|
end
|
27
30
|
|
28
31
|
msg = '[ERROR] ProjectLoader:'
|
29
32
|
msg += "Configuration params format is <#{pArgs.class}>!"
|
30
|
-
Logger.
|
33
|
+
Logger.verboseln Rainbow(msg).red
|
31
34
|
raise msg
|
32
35
|
end
|
36
|
+
# rubocop:enable Metrics/MethodLength
|
33
37
|
|
34
38
|
##
|
35
39
|
# Load project from filepath. Options:
|
@@ -37,11 +41,13 @@ module ProjectLoader
|
|
37
41
|
# * XML filepath
|
38
42
|
# * YAML filepath
|
39
43
|
# @param filepath (String)
|
44
|
+
# rubocop:disable Metrics/MethodLength
|
45
|
+
# rubocop:disable Metrics/AbcSize
|
40
46
|
def self.load_from_string(filepath)
|
41
47
|
project = Project.instance
|
42
48
|
unless File.exist?(filepath)
|
43
49
|
msg = Rainbow("[ERROR] #{filepath} not found!").red.bright
|
44
|
-
Logger.
|
50
|
+
Logger.verboseln msg
|
45
51
|
exit 1
|
46
52
|
end
|
47
53
|
|
@@ -51,11 +57,13 @@ module ProjectLoader
|
|
51
57
|
return project
|
52
58
|
elsif File.extname(filepath) == '.yaml'
|
53
59
|
return load_from_yaml(filepath)
|
54
|
-
else
|
55
|
-
error_loading(filepath)
|
56
60
|
end
|
61
|
+
error_loading(filepath)
|
57
62
|
end
|
63
|
+
# rubocop:enable Metrics/MethodLength
|
64
|
+
# rubocop:enable Metrics/AbcSize
|
58
65
|
|
66
|
+
# rubocop:disable Security/YAMLLoad
|
59
67
|
def self.load_from_yaml(arg)
|
60
68
|
project = Project.instance
|
61
69
|
project.param.merge!(YAML.load(File.open(arg)))
|
@@ -63,12 +71,13 @@ module ProjectLoader
|
|
63
71
|
project.set(:projectdir, File.dirname(arg))
|
64
72
|
project
|
65
73
|
end
|
74
|
+
# rubocop:enable Security/YAMLLoad
|
66
75
|
|
67
76
|
##
|
68
77
|
# Error found and exit application.
|
69
78
|
def self.error_loading(arg)
|
70
79
|
msg = Rainbow("[ERROR] Loading... #{arg}").red.bright
|
71
|
-
Logger.
|
80
|
+
Logger.verboseln msg
|
72
81
|
exit 1
|
73
82
|
end
|
74
83
|
end
|
data/lib/asker/logger.rb
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'singleton'
|
3
4
|
require_relative 'application'
|
4
|
-
require_relative 'project'
|
5
5
|
|
6
6
|
# Display and log project messages
|
7
|
-
|
7
|
+
class Logger
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@logfile = null
|
12
|
+
end
|
13
|
+
|
8
14
|
##
|
9
15
|
# Display and log text
|
10
16
|
def self.verbose(msg)
|
11
|
-
|
12
|
-
|
17
|
+
print msg if Application.instance.config['global']['verbose'] == 'yes'
|
18
|
+
@logfile&.write(msg)
|
13
19
|
end
|
14
20
|
|
15
21
|
##
|
@@ -17,4 +23,23 @@ module Logger
|
|
17
23
|
def self.verboseln(msg)
|
18
24
|
verbose(msg + "\n")
|
19
25
|
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Create or reset logfile
|
29
|
+
def self.create(project)
|
30
|
+
@logfile = File.open(project.get(:logpath), 'w')
|
31
|
+
@logfile.write('=' * 50 + "\n")
|
32
|
+
@logfile.write("Created by : #{Application::NAME}")
|
33
|
+
@logfile.write(" (version #{Application::VERSION})\n")
|
34
|
+
@logfile.write("File : #{project.get(:logname)}\n")
|
35
|
+
@logfile.write("Time : #{Time.new}\n")
|
36
|
+
@logfile.write("Author : David Vargas Ruiz\n")
|
37
|
+
@logfile.write('=' * 50 + "\n\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Close Log file
|
42
|
+
def self.close
|
43
|
+
@logfile.close
|
44
|
+
end
|
20
45
|
end
|