asker-tool 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +53 -0
  4. data/bin/asker +4 -0
  5. data/docs/changelog/v2.1.md +99 -0
  6. data/docs/commands.md +15 -0
  7. data/docs/contributions.md +18 -0
  8. data/docs/history.md +40 -0
  9. data/docs/idea.md +44 -0
  10. data/docs/inputs/README.md +39 -0
  11. data/docs/inputs/code.md +69 -0
  12. data/docs/inputs/concepts.md +142 -0
  13. data/docs/inputs/jedi.md +68 -0
  14. data/docs/inputs/tables.md +112 -0
  15. data/docs/inputs/templates.md +87 -0
  16. data/docs/install/README.md +38 -0
  17. data/docs/install/manual.md +26 -0
  18. data/docs/install/scripts.md +26 -0
  19. data/docs/revise/asker-file.md +41 -0
  20. data/docs/revise/buenas-practicas/01-convocatoria.md +30 -0
  21. data/docs/revise/buenas-practicas/02-formulario.md +35 -0
  22. data/docs/revise/buenas-practicas/03-descripcion.md +63 -0
  23. data/docs/revise/buenas-practicas/04-resultados.md +17 -0
  24. data/docs/revise/buenas-practicas/05-reproducir.md +10 -0
  25. data/docs/revise/ejemplos/01/README.md +27 -0
  26. data/docs/revise/ejemplos/02/README.md +31 -0
  27. data/docs/revise/ejemplos/03/README.md +31 -0
  28. data/docs/revise/ejemplos/04/README.md +37 -0
  29. data/docs/revise/ejemplos/05/README.md +25 -0
  30. data/docs/revise/ejemplos/06/README.md +43 -0
  31. data/docs/revise/ejemplos/README.md +11 -0
  32. data/docs/revise/projects.md +74 -0
  33. data/lib/asker.rb +103 -0
  34. data/lib/asker/ai/ai.rb +70 -0
  35. data/lib/asker/ai/ai_calculate.rb +55 -0
  36. data/lib/asker/ai/concept_ai.rb +49 -0
  37. data/lib/asker/ai/question.rb +58 -0
  38. data/lib/asker/ai/stages/base_stage.rb +16 -0
  39. data/lib/asker/ai/stages/main.rb +8 -0
  40. data/lib/asker/ai/stages/stage_b.rb +87 -0
  41. data/lib/asker/ai/stages/stage_d.rb +160 -0
  42. data/lib/asker/ai/stages/stage_f.rb +156 -0
  43. data/lib/asker/ai/stages/stage_i.rb +140 -0
  44. data/lib/asker/ai/stages/stage_s.rb +52 -0
  45. data/lib/asker/ai/stages/stage_t.rb +170 -0
  46. data/lib/asker/application.rb +30 -0
  47. data/lib/asker/checker.rb +356 -0
  48. data/lib/asker/cli.rb +85 -0
  49. data/lib/asker/code/ai/base_code_ai.rb +48 -0
  50. data/lib/asker/code/ai/code_ai_factory.rb +26 -0
  51. data/lib/asker/code/ai/javascript_code_ai.rb +167 -0
  52. data/lib/asker/code/ai/python_code_ai.rb +167 -0
  53. data/lib/asker/code/ai/ruby_code_ai.rb +169 -0
  54. data/lib/asker/code/ai/sql_code_ai.rb +69 -0
  55. data/lib/asker/code/code.rb +53 -0
  56. data/lib/asker/data/column.rb +62 -0
  57. data/lib/asker/data/concept.rb +183 -0
  58. data/lib/asker/data/data_field.rb +87 -0
  59. data/lib/asker/data/row.rb +93 -0
  60. data/lib/asker/data/table.rb +96 -0
  61. data/lib/asker/data/template.rb +65 -0
  62. data/lib/asker/data/world.rb +53 -0
  63. data/lib/asker/exporter/code_gift_exporter.rb +35 -0
  64. data/lib/asker/exporter/code_screen_exporter.rb +45 -0
  65. data/lib/asker/exporter/concept_ai_gift_exporter.rb +33 -0
  66. data/lib/asker/exporter/concept_ai_screen_exporter.rb +115 -0
  67. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +33 -0
  68. data/lib/asker/exporter/concept_doc_exporter.rb +21 -0
  69. data/lib/asker/exporter/concept_screen_exporter.rb +25 -0
  70. data/lib/asker/exporter/main.rb +9 -0
  71. data/lib/asker/files/config.ini +40 -0
  72. data/lib/asker/formatter/code_string_formatter.rb +16 -0
  73. data/lib/asker/formatter/concept_doc_formatter.rb +37 -0
  74. data/lib/asker/formatter/concept_string_formatter.rb +66 -0
  75. data/lib/asker/formatter/question_gift_formatter.rb +65 -0
  76. data/lib/asker/formatter/question_hash_formatter.rb +40 -0
  77. data/lib/asker/formatter/question_moodlexml_formatter.rb +71 -0
  78. data/lib/asker/formatter/rb2haml_formatter.rb +26 -0
  79. data/lib/asker/lang/lang.rb +42 -0
  80. data/lib/asker/lang/lang_factory.rb +19 -0
  81. data/lib/asker/lang/text_actions.rb +150 -0
  82. data/lib/asker/loader/code_loader.rb +53 -0
  83. data/lib/asker/loader/content_loader.rb +101 -0
  84. data/lib/asker/loader/directory_loader.rb +58 -0
  85. data/lib/asker/loader/file_loader.rb +33 -0
  86. data/lib/asker/loader/image_url_loader.rb +61 -0
  87. data/lib/asker/loader/input_loader.rb +24 -0
  88. data/lib/asker/loader/project_loader.rb +71 -0
  89. data/lib/asker/logger.rb +21 -0
  90. data/lib/asker/project.rb +170 -0
  91. metadata +261 -0
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+ require_relative '../project'
5
+ require_relative '../formatter/question_hash_formatter'
6
+
7
+ # Use to export data from ConceptIA to YAML format
8
+ module ConceptAIYAMLExporter
9
+ def self.export_all(concepts_ai)
10
+ questions = []
11
+ concepts_ai.each do |concept_ai|
12
+ questions += get_questions_from concept_ai
13
+ end
14
+ project = Project.instance
15
+ params = { lang: project.get(:lang) ,
16
+ projectname: project.get(:projectname) }
17
+ output = { params: params, questions: questions }
18
+ project.yamlfile.write(output.to_yaml)
19
+ end
20
+
21
+ def self.get_questions_from(concept_ai)
22
+ data = []
23
+ return data unless concept_ai.process?
24
+ stages = Project.instance.stages
25
+ stages.each_key do |stage|
26
+ concept_ai.questions[stage].each do |question|
27
+ question.lang = concept_ai.lang
28
+ data << QuestionHashFormatter.to_hash(question)
29
+ end
30
+ end
31
+ data
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative '../project'
4
+ require_relative '../formatter/concept_doc_formatter'
5
+
6
+ class ConceptDocExporter
7
+
8
+ def initialize(concepts)
9
+ @concepts = concepts
10
+ end
11
+
12
+ def export
13
+ file = Project.instance.lessonfile
14
+ @concepts.each do |concept|
15
+ if concept.process
16
+ file.write(ConceptDocFormatter.to_s(concept))
17
+ end
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,25 @@
1
+
2
+ require_relative '../formatter/concept_string_formatter'
3
+
4
+ # Show Concept Data on screen
5
+ module ConceptScreenExporter
6
+ def self.export_all(concepts)
7
+ project = Project.instance
8
+ return if project.show_mode == :none
9
+ msg = "\n[INFO] Showing concept data <"
10
+ msg += Rainbow(project.show_mode.to_s).bright + '>'
11
+ project.verbose msg
12
+
13
+ case project.show_mode
14
+ when :resume
15
+ s = "* Concepts (#{concepts.count}): "
16
+ concepts.each { |c| s += c.name + ', ' }
17
+ project.verbose s
18
+ when :default
19
+ # Only show Concepts with process attr true
20
+ concepts.each do |c|
21
+ project.verbose ConceptStringFormatter.to_s(c) if c.process?
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+
2
+ require_relative 'code_gift_exporter'
3
+ require_relative 'code_screen_exporter'
4
+
5
+ require_relative 'concept_ai_gift_exporter'
6
+ require_relative 'concept_ai_screen_exporter'
7
+ require_relative 'concept_ai_yaml_exporter'
8
+ require_relative 'concept_doc_exporter'
9
+ require_relative 'concept_screen_exporter'
@@ -0,0 +1,40 @@
1
+ [global]
2
+ ; Connect Google and download find images URLs
3
+ ; Accept yes|no
4
+ internet = no
5
+
6
+ [questions]
7
+ ; Exclude questions with this texts into their names.
8
+ ; Accept Comma separated strings.
9
+ exclude =
10
+
11
+ ; ### stage_b ###
12
+ ; b1: b1match4x4, b1match3x1misspelled, b1match3x1
13
+ ; ### stage_d ###
14
+ ; d1: d1choose, d1none, d1none-misspelled
15
+ ; d2: d2def-mispelled, d2name-mispelled, d2true, d2false-misspelled
16
+ ; d3: d3hidden
17
+ ; d4: d4filtered
18
+ ; ### stage_f
19
+ ; f1: f1true, f1short, f1name-misspelled, f1true-misspelled, f1false
20
+ ; f2: f2outsider
21
+ ; f3: f3filtered
22
+ ; ### stage_i
23
+ ; i1
24
+ ; i2
25
+ ; i3
26
+ ; i4
27
+ ; ### stage_s
28
+ ; s1
29
+ ; ### stage_t
30
+ ; t1table
31
+ ; t2table
32
+ ; t3table
33
+ ; t4table
34
+ ; t5table
35
+ ; t6table
36
+ ; t7table
37
+ ; t8table
38
+ ; t9table
39
+ ; ### code
40
+ ; code1
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+ require 'terminal-table'
5
+
6
+ # Define methods to trasnforme Code object into String
7
+ module CodeStringFormatter
8
+ def self.to_s(code)
9
+ t = Terminal::Table.new
10
+ msg = Rainbow(code.filename).white.bg(:blue).bright
11
+ t.add_row [Rainbow('Code').bright, msg]
12
+ t.add_row [Rainbow('Type').blue, code.type.to_s]
13
+ t.add_row [Rainbow('Lines').blue, code.lines_to_s(code.lines)]
14
+ "#{t}\n"
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'rainbow'
4
+ require 'terminal-table'
5
+
6
+ require_relative '../project'
7
+
8
+ ##
9
+ # Formatter Concept to Doc
10
+ module ConceptDocFormatter
11
+ ##
12
+ # Formatter Concept into Doc
13
+ # @param concept (Concept)
14
+ def self.to_s(concept)
15
+ out = ''
16
+ out << "\n#{Rainbow(concept.name).bg(:blue).bright}\n\n"
17
+ concept.texts.each { |i| out << "* #{i}\n" }
18
+ out << "\n"
19
+ concept.tables.each do |table|
20
+ out << table_to_s(table)
21
+ end
22
+ out
23
+ end
24
+
25
+ ##
26
+ # Formatter Table to Doc
27
+ # @param table (Table)
28
+ # @return String
29
+ def self.table_to_s(table)
30
+ my_screen_table = Terminal::Table.new do |st|
31
+ st << table.fields
32
+ st << :separator
33
+ table.rows.each { |r| st.add_row r }
34
+ end
35
+ "#{my_screen_table}\n"
36
+ end
37
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+ require 'terminal-table'
5
+
6
+ # Define methods to transform Concept into String
7
+ module ConceptStringFormatter
8
+ ##
9
+ # Formatter Concept to String
10
+ # @param concept (Concept)
11
+ # @return String
12
+ def self.to_s(concept)
13
+ tt = Terminal::Table.new
14
+ rows = get_tt_rows(concept)
15
+ rows.each { |row| tt.add_row row }
16
+ "#{tt}\n"
17
+ end
18
+
19
+ # rubocop:disable Metrics/AbcSize
20
+ # rubocop:disable Metrics/MethodLength
21
+ def self.get_tt_rows(concept)
22
+ rows = []
23
+ rows << [Rainbow(concept.id.to_s).bright,
24
+ Rainbow(concept.name(:screen)).white.bg(:blue).bright +
25
+ " (lang=#{concept.lang.lang}) "]
26
+ rows << [Rainbow('Filename').blue, concept.filename]
27
+ rows << [Rainbow('Context').blue, concept.context.join(', ').to_s]
28
+ rows << [Rainbow('Tags').blue, concept.tags.join(', ').to_s]
29
+ rows << [Rainbow('Reference to').blue,
30
+ concept.reference_to.join(', ')[0...70].to_s]
31
+ rows << [Rainbow('Referenced by').blue,
32
+ concept.referenced_by.join(', ')[0...70].to_s]
33
+ rows << format_texts(concept)
34
+ rows << [Rainbow('.def(images)').blue, concept.images.size.to_s]
35
+ rows << format_tables(concept)
36
+ rows << format_neighbors(concept)
37
+ end
38
+ # rubocop:enable Metrics/AbcSize
39
+ # rubocop:enable Metrics/MethodLength
40
+
41
+ def self.format_texts(concept)
42
+ list = []
43
+ concept.texts.each do |i|
44
+ if i.size < 60
45
+ list << i.to_s
46
+ next
47
+ end
48
+ list << i[0...70].to_s + '...'
49
+ end
50
+ [Rainbow('.def(text)').blue, list.join("\n")]
51
+ end
52
+
53
+ def self.format_tables(concept)
54
+ return [] if concept.tables.count.zero?
55
+
56
+ list = concept.tables.map(&:to_s)
57
+ [Rainbow('.tables').color(:blue), list.join("\n")]
58
+ end
59
+
60
+ def self.format_neighbors(concept)
61
+ list = concept.neighbors[0..4].map do |i|
62
+ i[:concept].name(:screen) + '(' + i[:value].to_s[0..4] + ')'
63
+ end
64
+ [Rainbow('.neighbors').blue, list.join("\n")]
65
+ end
66
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+
3
+ # Transform Questions into Gift format
4
+ module QuestionGiftFormatter
5
+ def self.to_s(question)
6
+ @question = question
7
+ # Return question using gift format
8
+ cond = @question.comment.nil? && @question.comment.empty?
9
+ s = "// #{@question.comment}\n" unless cond
10
+ s << "::#{@question.name}::[html]#{sanitize(@question.text)}\n"
11
+
12
+ case @question.type
13
+ when :choice
14
+ s += "{\n"
15
+ a = [" =#{sanitize(@question.good)}\n"]
16
+ penalties = ['', '%-50%', '%-33.33333%', '%-25%', '%-20%']
17
+ penalty = penalties[@question.bads.size]
18
+
19
+ @question.bads.each { |i| a << (" ~#{penalty}" + sanitize(i) + "\n") }
20
+ a.shuffle! if @question.shuffle?
21
+ a.each do |i|
22
+ text = i
23
+ text = i[0, 220] + '...(ERROR: text too long)' if text.size > 255
24
+ s << text
25
+ end
26
+ s += " #####{sanitize(@question.feedback.to_s)}\n" if @question.feedback
27
+ s += "}\n\n"
28
+ when :boolean
29
+ s << "{#{@question.good}#####{sanitize(@question.feedback.to_s)}}\n\n"
30
+ when :match
31
+ s << "{\n"
32
+ a = []
33
+ @question.matching.each do |i, j|
34
+ i = i[0, 220] + '...(ERROR: text too long)' if i.size > 255
35
+ j = j[0, 220] + '...(ERROR: text too long)' if j.size > 255
36
+ a << " =#{sanitize(i)} -> #{sanitize(j)}\n"
37
+ end
38
+ a.shuffle! if @question.shuffle?
39
+ a.each { |i| s << i }
40
+ s << "}\n\n"
41
+ when :short
42
+ s << "{\n"
43
+ @question.shorts.uniq!
44
+ @question.shorts.each do |i|
45
+ text = i
46
+ text = i[0, 220] + '...(ERROR: too long)' if text.size > 255
47
+ s << " =%100%#{text}#\n"
48
+ end
49
+ s << " #####{sanitize(@question.feedback.to_s)}\n" if @question.feedback
50
+ s << "}\n\n"
51
+ end
52
+ s
53
+ end
54
+
55
+ def self.sanitize(input = '')
56
+ output = input.dup
57
+ output.gsub!("#", "\\#")
58
+ output.gsub!("\n", " ")
59
+ #output.gsub!(":", "\\:")
60
+ output.gsub!("=", "\\=")
61
+ output.gsub!("\{", "\\{")
62
+ output.gsub!("\}", "\\}")
63
+ output
64
+ end
65
+ end
@@ -0,0 +1,40 @@
1
+
2
+ # Transform Questions into YAML format
3
+ module QuestionHashFormatter
4
+ def self.to_hash(question)
5
+ @question = question
6
+ # Return question using YAML format
7
+ s = {}
8
+ s[:comment] = @question.comment
9
+ s[:name] = @question.name
10
+ s[:text] = sanitize(@question.text)
11
+ s[:type] = @question.type
12
+ s[:feedback] = sanitize(@question.feedback.to_s)
13
+ s[:lang] = @question.lang.code.to_sym
14
+ case @question.type
15
+ when :choice
16
+ s[:answer] = sanitize(@question.good)
17
+ s[:options] = (@question.bads + [@question.good]).shuffle
18
+ when :boolean
19
+ s[:answer] = @question.good
20
+ when :match
21
+ s[:answer] = @question.matching
22
+ s[:matching] = @question.matching
23
+ when :short
24
+ @question.shorts.uniq!
25
+ s[:answer] = @question.shorts
26
+ end
27
+ s
28
+ end
29
+
30
+ def self.sanitize(input = '')
31
+ output = input.dup
32
+ output.gsub!("#", "\\#")
33
+ output.gsub!("\n", " ")
34
+ #output.gsub!(":", "\\:")
35
+ output.gsub!("=", "\\=")
36
+ output.gsub!("\{", "\\{")
37
+ output.gsub!("\}", "\\}")
38
+ output
39
+ end
40
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+
3
+ # Transform Questions into Gift format
4
+ module QuestionMoodleXMLFormatter
5
+ def self.to_s(question)
6
+ @question = question
7
+
8
+ case @question.type
9
+ when :choice
10
+ s += choice_to_s(question)
11
+ when :boolean
12
+ when :match
13
+ when :short
14
+ end
15
+ s.flaten!
16
+ end
17
+
18
+ def self.choice_to_s(question)
19
+ s = []
20
+
21
+ penalties = ['', '%-50%', '%-33.33333%', '%-25%', '%-20%']
22
+ penalty = penalties[question.bads.size]
23
+
24
+ s << "<!-- question: #{question.name} -->"
25
+ s << '<question type="multichoice">'
26
+ s << ' <name>'
27
+ s << " <text>#{question.name}</text>"
28
+ s << ' </name>'
29
+ s << ' <questiontext format="html">'
30
+ s << " <text><![CDATA[#{question.text}]]></text>"
31
+ s << ' </questiontext>'
32
+ s << ' <generalfeedback format="html">'
33
+ s << " <text>#{question.feedback}</text>"
34
+ s << ' </generalfeedback>'
35
+ s << ' <defaultgrade>1.0000000</defaultgrade>'
36
+ s << " <penalty>#{penalty}</penalty>"
37
+ s << ' <hidden>0</hidden>'
38
+ s << ' <single>true</single>'
39
+ s << " <shuffleanswers>#{question.shuffle?}</shuffleanswers>"
40
+ s << ' <answernumbering>abc</answernumbering>'
41
+ s << ' <incorrectfeedback format="html">'
42
+ s << " <text>#{question.feedback}</text>"
43
+ s << ' </incorrectfeedback>'
44
+ s << ' <answer fraction="100" format="html">'
45
+ s << " <text>#{question.good}</text>"
46
+ s << ' </answer>'
47
+ s << ' <answer fraction="-25" format="html">'
48
+ s << " <text>#{question.bad[0]}</text>"
49
+ s << ' </answer>'
50
+ s << ' </question>'
51
+ s << ' <answer fraction="-25" format="html">'
52
+ s << " <text>#{question.bad[1]}</text>"
53
+ s << ' </answer>'
54
+ s << ' </question>'
55
+ s << ' <answer fraction="-25" format="html">'
56
+ s << " <text>#{question.bad[2]}</text>"
57
+ s << ' </answer>'
58
+ s << ' </question>'
59
+ s
60
+ end
61
+
62
+ def self.sanitize(input = '')
63
+ output = input.dup
64
+ output.tr!("\n", " ")
65
+ output.tr!(":", "\:")
66
+ output.tr!("=", "\\=")
67
+ # output.gsub!('{', "\\{")
68
+ # output.gsub!('}', "\\}")
69
+ output
70
+ end
71
+ end
@@ -0,0 +1,26 @@
1
+ # UNDER DEVELOPMENT!!
2
+
3
+ module Rb2HamlExporter
4
+ def self.export(filename)
5
+ check_file filename
6
+ rbcontent = File.read(filename)
7
+ puts rbcontent
8
+ end
9
+
10
+ def self.check_file(filename)
11
+ unless File.extname(filename).casecmp('.rb').zero?
12
+ msg = "[ERROR] Rb2HamlExporter: File name error #{filename}"
13
+ raise msg
14
+ end
15
+ unless File.exist? filename
16
+ msg = "[ERROR] Rb2HamlExporter: File #{filename} not found!"
17
+ raise msg
18
+ end
19
+ end
20
+
21
+ class Map
22
+ end
23
+
24
+ end
25
+
26
+ Rb2HamlExporter.export('docs/examples/home/rb/furniture.rb')