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