asker-tool 2.1.7 → 2.2.3

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE.txt → LICENSE} +0 -0
  3. data/README.md +14 -15
  4. data/bin/asker +1 -1
  5. data/lib/asker/ai/ai.rb +6 -3
  6. data/lib/asker/ai/ai_calculate.rb +20 -6
  7. data/lib/asker/ai/concept_ai.rb +12 -3
  8. data/lib/asker/ai/question.rb +28 -6
  9. data/lib/asker/ai/stages/base_stage.rb +45 -6
  10. data/lib/asker/ai/stages/stage_b.rb +90 -49
  11. data/lib/asker/ai/stages/stage_d.rb +69 -90
  12. data/lib/asker/ai/stages/stage_f.rb +47 -38
  13. data/lib/asker/ai/stages/stage_i.rb +79 -92
  14. data/lib/asker/ai/stages/stage_s.rb +41 -36
  15. data/lib/asker/ai/stages/stage_t.rb +114 -73
  16. data/lib/asker/application.rb +7 -16
  17. data/lib/asker/check_input/check_haml_data.rb +264 -0
  18. data/lib/asker/check_input/check_table.rb +104 -0
  19. data/lib/asker/check_input.rb +51 -0
  20. data/lib/asker/cli.rb +47 -44
  21. data/lib/asker/data/code.rb +5 -16
  22. data/lib/asker/data/concept.rb +71 -24
  23. data/lib/asker/data/project_data.rb +63 -0
  24. data/lib/asker/data/table.rb +2 -0
  25. data/lib/asker/data/template.rb +3 -1
  26. data/lib/asker/data/world.rb +8 -16
  27. data/lib/asker/displayer/code_displayer.rb +7 -0
  28. data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
  29. data/lib/asker/displayer/concept_ai_displayer.rb +24 -22
  30. data/lib/asker/displayer/concept_displayer.rb +9 -4
  31. data/lib/asker/displayer/stats_displayer.rb +8 -0
  32. data/lib/asker/exporter/concept_ai_gift_exporter.rb +7 -11
  33. data/lib/asker/exporter/concept_ai_moodle_exporter.rb +45 -0
  34. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +6 -3
  35. data/lib/asker/exporter/concept_doc_exporter.rb +12 -2
  36. data/lib/asker/exporter/data_gift_exporter.rb +31 -0
  37. data/lib/asker/exporter/output_file_exporter.rb +9 -6
  38. data/lib/asker/files/{config.ini → asker.ini} +14 -4
  39. data/lib/asker/files/language/du/connectors.yaml +81 -0
  40. data/lib/asker/files/language/du/mistakes.yaml +82 -0
  41. data/lib/asker/files/language/du/templates.yaml +28 -49
  42. data/lib/asker/files/language/en/templates.yaml +19 -19
  43. data/lib/asker/files/language/es/mistakes.yaml +9 -7
  44. data/lib/asker/files/language/es/templates.yaml +19 -19
  45. data/lib/asker/files/language/fr/connectors.yaml +68 -84
  46. data/lib/asker/files/language/fr/templates.yaml +22 -22
  47. data/lib/asker/formatter/concept_doc_formatter.rb +0 -4
  48. data/lib/asker/formatter/concept_string_formatter.rb +7 -4
  49. data/lib/asker/formatter/moodle/matching.erb +38 -0
  50. data/lib/asker/formatter/moodle/multichoice.erb +49 -0
  51. data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
  52. data/lib/asker/formatter/moodle/truefalse.erb +47 -0
  53. data/lib/asker/formatter/question_gift_formatter.rb +21 -19
  54. data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
  55. data/lib/asker/lang/lang_factory.rb +7 -1
  56. data/lib/asker/loader/code_loader.rb +1 -1
  57. data/lib/asker/loader/content_loader.rb +12 -14
  58. data/lib/asker/loader/directory_loader.rb +1 -8
  59. data/lib/asker/loader/embedded_file.rb +42 -0
  60. data/lib/asker/loader/file_loader.rb +1 -6
  61. data/lib/asker/loader/haml_loader.rb +9 -5
  62. data/lib/asker/loader/image_url_loader.rb +8 -9
  63. data/lib/asker/loader/input_loader.rb +5 -6
  64. data/lib/asker/loader/project_loader.rb +18 -10
  65. data/lib/asker/logger.rb +36 -9
  66. data/lib/asker/skeleton.rb +3 -2
  67. data/lib/asker/version.rb +9 -0
  68. data/lib/asker.rb +72 -43
  69. metadata +60 -18
  70. data/lib/asker/checker.rb +0 -455
  71. data/lib/asker/project.rb +0 -146
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'file_loader'
4
- require_relative '../logger'
5
4
 
6
5
  # Load input data from one directory
7
6
  module DirectoryLoader
@@ -13,7 +12,6 @@ module DirectoryLoader
13
12
  files = (Dir.new(dirname).entries - ['.', '..']).sort
14
13
  # Accept only HAML or XML files
15
14
  accepted = files.select { |f| %w[.xml .haml].include? File.extname(f) }
16
- Logger.verbose " * Input directory = #{Rainbow(dirname).bright}"
17
15
  DirectoryLoader.load_files(accepted, dirname)
18
16
  end
19
17
 
@@ -24,7 +22,7 @@ module DirectoryLoader
24
22
  return if Dir.exist? dirname
25
23
 
26
24
  msg = Rainbow("[ERROR] #{dirname} directory dosn't exist!").color(:red)
27
- Logger.verboseln msg
25
+ puts msg
28
26
  raise msg
29
27
  end
30
28
 
@@ -48,11 +46,6 @@ module DirectoryLoader
48
46
  # @param filepath (String) Path to input file
49
47
  # @param last (Boolean) True if it is the last filename
50
48
  def self.load_file(filepath, last = false)
51
- if last
52
- Logger.verbose " └── Input file = #{Rainbow(filepath).bright}"
53
- else
54
- Logger.verbose " ├── Input file = #{Rainbow(filepath).bright}"
55
- end
56
49
  FileLoader.load(filepath)
57
50
  end
58
51
  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
@@ -2,21 +2,16 @@
2
2
 
3
3
  require_relative 'content_loader'
4
4
  require_relative 'haml_loader'
5
- require_relative '../logger'
6
5
 
7
6
  # Methods that load a filename and return list of concepts
8
7
  module FileLoader
9
- ##
10
- # Load asker data from file
11
- # @param filename (String) File name to be load
12
8
  def self.load(filename)
13
9
  if File.extname(filename).casecmp('.haml').zero?
14
10
  file_content = HamlLoader.load filename
15
11
  elsif File.extname(filename).casecmp('.xml').zero?
16
12
  file_content = File.read(filename)
17
13
  else
18
- msg = "[ERROR] FileLoader: Format error #{filename}"
19
- Logger.verbose msg
14
+ puts "[ERROR] FileLoader: Format error #{filename}"
20
15
  raise msg
21
16
  end
22
17
  ContentLoader.load(filename, file_content)
@@ -4,12 +4,16 @@ require 'haml'
4
4
 
5
5
  # HAML file loader
6
6
  module HamlLoader
7
- ##
8
- # Load HAML file name
9
- # @param filename (String) HAML file name
10
7
  def self.load(filename)
11
8
  template = File.read(filename)
12
- haml_engine = Haml::Engine.new(template)
13
- haml_engine.render
9
+ begin
10
+ haml_engine = Haml::Engine.new(template)
11
+ return haml_engine.render
12
+ rescue StandardError => e
13
+ puts "[ERROR] HamlLoader: Can't load <#{filename}> file!"
14
+ puts " => #{e}"
15
+ exit 0
16
+ end
14
17
  end
18
+
15
19
  end
@@ -1,8 +1,6 @@
1
1
 
2
2
  require 'net/http'
3
3
  require 'uri'
4
- require_relative '../application'
5
- require_relative '../logger'
6
4
 
7
5
  # Search URL images on Internet
8
6
  # Methods:
@@ -36,20 +34,21 @@ module ImageUrlLoader
36
34
  end
37
35
  end
38
36
  rescue
39
- Logger.verboseln '[ERROR] ImageUrlLoader'
40
- Logger.verboseln " => #{search_url}"
41
- Logger.verboseln ' => Check Internet connections'
42
- Logger.verboseln ' => Ensure URL is well formed'
37
+ puts '[ERROR] ImageUrlLoader'
38
+ puts " => #{search_url}"
39
+ puts ' => Check Internet connections'
40
+ puts ' => Ensure URL is well formed'
43
41
  end
44
42
  image_urls
45
43
  end
46
44
 
47
45
  def self.sanitize_string(input)
46
+ text = input.dup
48
47
  r = [ ['á', 'a'], ['é', 'e'], ['í', 'i'], ['ó', 'o'], ['ú', 'u'], ['ñ', 'n'], ['Á', 'A'], ['É', 'E'], ['Í', 'I'], ['Ó', 'O'], ['Ú', 'U'], ['Ñ', 'N']]
49
- r.each { |item| input.gsub!(item[0], item[1]) }
48
+ r.each { |item| text.gsub!(item[0], item[1]) }
50
49
  r = ['-', '_', ',', '"']
51
- r.each { |item| input.gsub!(item, ' ') }
52
- input.split(' ')
50
+ r.each { |item| text.gsub!(item, ' ') }
51
+ text.split(' ')
53
52
  end
54
53
 
55
54
  def self.sanitize_array(input)
@@ -3,30 +3,29 @@
3
3
  require_relative 'directory_loader'
4
4
  require_relative '../ai/concept_ai'
5
5
  require_relative '../data/world'
6
- require_relative '../logger'
7
6
 
8
7
  # Load DATA defined into our Project
9
8
  module InputLoader
10
9
  ##
11
10
  # Load input data from every input directory
12
11
  # @param inputdirs (Array)
13
- def self.load(inputdirs)
12
+ def self.load(inputdirs, internet = true)
14
13
  data = { concepts: [], codes: [], world: nil,
15
14
  concepts_ai: [], codes_ai: [] }
16
- Logger.verbose "\n[INFO] Loading input data"
15
+ #Logger.verboseln "\n[INFO] Loading input data"
17
16
  inputdirs.each do |dirname|
18
17
  temp = DirectoryLoader.load(dirname)
19
18
  data[:concepts] += temp[:concepts]
20
19
  data[:codes] += temp[:codes]
21
20
  end
22
- create_questions(data)
21
+ create_questions(data, internet)
23
22
  end
24
23
 
25
- private_class_method def self.create_questions(data)
24
+ private_class_method def self.create_questions(data, internet)
26
25
  # Create World data
27
26
  # * Calculate concept neighbours
28
27
  # * TO-DO: Calculate code neighbours
29
- data[:world] = World.new(data[:concepts])
28
+ data[:world] = World.new(data[:concepts], internet)
30
29
  # Create ConceptAI data (ConceptAI = concept + questions)
31
30
  data[:concepts].each do |concept|
32
31
  data[:concepts_ai] << ConceptAI.new(concept, data[:world])
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'yaml'
4
- require_relative '../project'
5
- require_relative '../logger'
4
+ require_relative '../data/project_data'
6
5
 
7
6
  # Load params into Project class using arg input
8
7
  # * load
@@ -14,22 +13,26 @@ module ProjectLoader
14
13
  ##
15
14
  # Load project from args
16
15
  # @param args (String or Hash)
16
+ # rubocop:disable Metrics/MethodLength
17
17
  def self.load(args)
18
- project = Project.instance
18
+ project = ProjectData.instance
19
19
 
20
20
  if args.class == Hash
21
21
  project.param.merge!(args)
22
+ project.open
22
23
  return project
23
24
  elsif args.class == String
24
25
  ProjectLoader.load_from_string(args)
26
+ project.open
25
27
  return project
26
28
  end
27
29
 
28
30
  msg = '[ERROR] ProjectLoader:'
29
31
  msg += "Configuration params format is <#{pArgs.class}>!"
30
- Logger.verbose Rainbow(msg).red
32
+ puts Rainbow(msg).red
31
33
  raise msg
32
34
  end
35
+ # rubocop:enable Metrics/MethodLength
33
36
 
34
37
  ##
35
38
  # Load project from filepath. Options:
@@ -37,11 +40,13 @@ module ProjectLoader
37
40
  # * XML filepath
38
41
  # * YAML filepath
39
42
  # @param filepath (String)
43
+ # rubocop:disable Metrics/MethodLength
44
+ # rubocop:disable Metrics/AbcSize
40
45
  def self.load_from_string(filepath)
41
- project = Project.instance
46
+ project = ProjectData.instance
42
47
  unless File.exist?(filepath)
43
48
  msg = Rainbow("[ERROR] #{filepath} not found!").red.bright
44
- Logger.verbose msg
49
+ puts msg
45
50
  exit 1
46
51
  end
47
52
 
@@ -51,24 +56,27 @@ module ProjectLoader
51
56
  return project
52
57
  elsif File.extname(filepath) == '.yaml'
53
58
  return load_from_yaml(filepath)
54
- else
55
- error_loading(filepath)
56
59
  end
60
+ error_loading(filepath)
57
61
  end
62
+ # rubocop:enable Metrics/MethodLength
63
+ # rubocop:enable Metrics/AbcSize
58
64
 
65
+ # rubocop:disable Security/YAMLLoad
59
66
  def self.load_from_yaml(arg)
60
- project = Project.instance
67
+ project = ProjectData.instance
61
68
  project.param.merge!(YAML.load(File.open(arg)))
62
69
  project.set(:configfilename, arg)
63
70
  project.set(:projectdir, File.dirname(arg))
64
71
  project
65
72
  end
73
+ # rubocop:enable Security/YAMLLoad
66
74
 
67
75
  ##
68
76
  # Error found and exit application.
69
77
  def self.error_loading(arg)
70
78
  msg = Rainbow("[ERROR] Loading... #{arg}").red.bright
71
- Logger.verbose msg
79
+ puts msg
72
80
  exit 1
73
81
  end
74
82
  end
data/lib/asker/logger.rb CHANGED
@@ -1,20 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'application'
4
- require_relative 'project'
3
+ require 'singleton'
4
+ require_relative 'version'
5
5
 
6
6
  # Display and log project messages
7
- module Logger
8
- ##
9
- # Display and log text
7
+ class Logger
8
+ include Singleton
9
+ @attr_verbose = 'yes'
10
+
11
+ def set_verbose(value)
12
+ @attr_verbose = value
13
+ end
14
+
10
15
  def self.verbose(msg)
11
- puts msg if Application.instance.config['global']['verbose'] == 'yes'
12
- Project.instance.get(:logfile)&.write("#{msg}\n")
16
+ print msg if @attr_verbose == 'yes'
17
+ @logfile&.write(msg)
13
18
  end
14
19
 
15
- ##
16
- # Display and log text line
17
20
  def self.verboseln(msg)
18
21
  verbose(msg + "\n")
19
22
  end
23
+
24
+ def log(msg)
25
+ verbose(msg)
26
+ end
27
+
28
+ def logln(msg)
29
+ verboseln(msg)
30
+ end
31
+ ##
32
+ # Create or reset logfile
33
+ def self.create(logpath, logname)
34
+ @logfile = File.open(logpath, 'w')
35
+ @logfile.write('=' * 50 + "\n")
36
+ @logfile.write("Created by : #{Version::NAME}")
37
+ @logfile.write(" (version #{Version::VERSION})\n")
38
+ @logfile.write("File : #{logname}\n")
39
+ @logfile.write("Time : #{Time.new}\n")
40
+ @logfile.write("Author : David Vargas Ruiz\n")
41
+ @logfile.write('=' * 50 + "\n\n")
42
+ end
43
+
44
+ def self.close
45
+ @logfile.close
46
+ end
20
47
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'fileutils'
4
4
  require 'rainbow'
5
+ require_relative 'version'
5
6
 
6
7
  # Skeleton: create skeleton for asker input files
7
8
  # * create
@@ -33,8 +34,8 @@ module Skeleton
33
34
  # Create default configuration files
34
35
  def self.create_configuration
35
36
  puts "\n[INFO] Creating configuration files"
36
- src = File.join(File.dirname(__FILE__), 'files', 'config.ini')
37
- dst = File.join('config.ini')
37
+ src = File.join(File.dirname(__FILE__), 'files', Version::CONFIGFILE)
38
+ dst = File.join(Version::CONFIGFILE)
38
39
  copyfile(src, dst)
39
40
  end
40
41
 
@@ -0,0 +1,9 @@
1
+
2
+ # Global parameters
3
+ module Version
4
+ VERSION = '2.2.3'
5
+ NAME = 'asker'
6
+ GEM = 'asker-tool'
7
+ CONFIGFILE = 'asker.ini'
8
+ HOMEPAGE = "https://github.com/teuton-software/#{NAME}/tree/v2.2"
9
+ end
data/lib/asker.rb CHANGED
@@ -2,71 +2,100 @@
2
2
 
3
3
  require 'rainbow'
4
4
 
5
+ require_relative 'asker/skeleton'
6
+ require_relative 'asker/check_input'
7
+
5
8
  require_relative 'asker/displayer/concept_displayer'
6
9
  require_relative 'asker/displayer/stats_displayer'
7
10
  require_relative 'asker/exporter/output_file_exporter'
8
- require_relative 'asker/loader/project_loader'
9
- require_relative 'asker/loader/input_loader'
10
- require_relative 'asker/checker'
11
11
  require_relative 'asker/logger'
12
- require_relative 'asker/skeleton'
13
12
 
14
- ##
15
- # Asker main class
13
+ require_relative 'asker/loader/project_loader'
14
+ require_relative 'asker/loader/input_loader'
16
15
  class Asker
17
- ##
18
- # Create asker input demo files
19
- # @param dirpath (String)
20
- def self.create_input(dirpath)
21
- Skeleton.create_input(dirpath)
16
+ def self.init
17
+ Skeleton.create_configuration
22
18
  end
23
19
 
24
- ##
25
- # Create asker configuration files
26
- def self.create_configuration
27
- Skeleton.create_configuration
20
+ def self.new_input(dirpath)
21
+ Skeleton.create_input(dirpath)
28
22
  end
29
23
 
30
- ##
31
- # Checking input file syntax
32
- # @param filepath (String)
33
24
  def self.check(filepath)
34
- Checker.check(filepath)
25
+ CheckInput.new.file(filepath).check
35
26
  end
36
27
 
37
- ##
38
- # Start working
39
- # @param filepath (String) HAML or XML filepath
40
28
  def self.start(filepath)
41
- project, data = load_input(filepath)
29
+ project_data, data = load_input(filepath)
42
30
  ConceptDisplayer.show(data[:concepts])
43
- create_output(project, data)
31
+ create_output(project_data, data)
44
32
  end
45
33
 
46
- ##
47
- # Load input data
48
- # @param args (Hash)
49
34
  private_class_method def self.load_input(args)
50
- project = ProjectLoader.load(args)
51
- project.open # Open output files
52
- data = InputLoader.load(project.get(:inputdirs).split(','))
53
- [project, data]
35
+ init_project_data
36
+ project_data = ProjectLoader.load(args)
37
+ init_logger(project_data)
38
+
39
+ inputdirs = project_data.get(:inputdirs).split(',')
40
+ internet = Application.instance.config['global']['internet'] == 'yes'
41
+ data = InputLoader.load(inputdirs, internet)
42
+ [project_data, data]
43
+ end
44
+
45
+ private_class_method def self.init_project_data()
46
+ project_data = ProjectData.instance
47
+ outputdir = Application.instance.config['output']['folder']
48
+ project_data.set(:outputdir, outputdir)
49
+
50
+ formula_weights = Application.instance.config['ai']['formula_weights']
51
+ project_data.set(:weights, formula_weights)
52
+ end
53
+
54
+ private_class_method def self.init_logger(project_data)
55
+ # Create log file where to save log messages
56
+ Logger.create(project_data.get(:logpath),
57
+ project_data.get(:logname))
58
+ Logger.instance.set_verbose(Application.instance.config['verbose'])
59
+ Logger.verboseln '[INFO] Project open'
60
+ Logger.verboseln ' ├── inputdirs = ' + Rainbow(project_data.get(:inputdirs)).bright
61
+ Logger.verboseln ' └── process_file = ' + Rainbow(project_data.get(:process_file)).bright
54
62
  end
55
63
 
56
- ##
57
- # Create output files: Gift, YAML, TXT Doc
58
- # rubocop:disable Metrics/AbcSize
59
64
  private_class_method def self.create_output(project, data)
60
- Logger.verbose "\n[INFO] Creating output files"
61
- Logger.verbose ' ├── Gift questions file => ' +
62
- Rainbow(project.get(:outputpath)).bright
63
- Logger.verbose ' ├── YAML questions file => ' +
64
- Rainbow(project.get(:yamlpath)).bright
65
- Logger.verbose ' └── Lesson file => ' +
66
- Rainbow(project.get(:lessonpath)).bright
65
+ Logger.verboseln "\n[INFO] Creating output files"
66
+ m = ' ├── Gift questions file => '
67
+ m += if Application.instance.config['output']['gift'] == 'yes'
68
+ Rainbow(project.get(:outputpath)).bright
69
+ else
70
+ "#{project.get(:outputpath)} (No)"
71
+ end
72
+ Logger.verboseln m
73
+
74
+ m = ' ├── Lesson file => '
75
+ m += if Application.instance.config['output']['doc'] == 'yes'
76
+ Rainbow(project.get(:lessonpath)).bright
77
+ else
78
+ "#{project.get(:lessonpath)} (No)"
79
+ end
80
+ Logger.verboseln m
81
+
82
+ m = ' ├── YAML questions file => '
83
+ m += if Application.instance.config['output']['yaml'] == 'yes'
84
+ Rainbow(project.get(:yamlpath)).bright
85
+ else
86
+ "#{project.get(:yamlpath)} (No)"
87
+ end
88
+ Logger.verboseln m
89
+
90
+ m = ' └── Moodle XML file => '
91
+ m += if Application.instance.config['output']['moodle'] == 'yes'
92
+ Rainbow(project.get(:moodlepath)).bright
93
+ else
94
+ "#{project.get(:moodlepath)} (No)"
95
+ end
96
+ Logger.verboseln m
67
97
  OutputFileExporter.export(data, project)
68
98
  StatsDisplayer.show(data)
69
- project.close # Logger use Project.get(:logfile) until the end
99
+ Logger.close
70
100
  end
71
- # rubocop:enable Metrics/AbcSize
72
101
  end