asker-tool 2.2.0 → 2.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a17926e45cfc0549f76ae3d8ec9c5313565847e3615653f7520344e03eea63f7
4
- data.tar.gz: 717620e1a5d56c65dc0ec601de61ffef208f3e21087e71e84a4c421e9e65c67f
3
+ metadata.gz: cb2119553ee0f5bce53f1aebe3468aabb5488ce02c54004c09df4d1256867cf5
4
+ data.tar.gz: 29bc8b727e10beb791eac5a113751f6d26ec9036cf3158aec583a93505fb3ba5
5
5
  SHA512:
6
- metadata.gz: 9ec3c2b84781c6c723edfbb0e5570edaabb8e26fd0d732bb9fa155d7b6fb5762115a44ba75899af7e0e0b399d6b764562de77dd31b0b2fe128c5dd97b39caf7d
7
- data.tar.gz: 3f1aa7b3ce5a9f59f3c373bd246f5fd8e8000a163ec539f943f32144fff057f80b44ae06bc127a31eb3ad71de0bb431d010a737491e57695c202e97534674a69
6
+ metadata.gz: b3f277896c860c2987c25b4088922328f922fa52c8e2bb32ba92b6d90c6b86e05f2c0c9a056f3c69139148266f6bd4443192ca4d6892ee6e6884fb1e6cb3bad4
7
+ data.tar.gz: f9bb53fa2c7d5ee05566eb19657e4997d84dea2f521e1445a64fb658b06a7b6b1326e8b3d010fa21b5758c8538fc33ed1f675752493db4a366be9ac881944057
data/README.md CHANGED
@@ -1,9 +1,10 @@
1
- # ASKER (version 2.2)
1
+ [![Gem Version](https://badge.fury.io/rb/asker-tool.svg)](https://badge.fury.io/rb/asker-tool)
2
2
 
3
- Generate a lot of questions from an _input file_ base on your own _definitions_.
3
+ # ASKER (devel 2.3)
4
4
 
5
- ---
6
- # Description
5
+ Generate a lot of questions from an _input_ text file with on your own _definitions_. In a way, this _input file_ is a concept map.
6
+
7
+ ![logo](./docs/images/logo.png)
7
8
 
8
9
  ASKER helps trainers to create a huge amount of questions, from a definitions (_conceptual entities_) input file.
9
10
 
@@ -11,32 +12,29 @@ ASKER helps trainers to create a huge amount of questions, from a definitions (_
11
12
  * Multiplatform.
12
13
  * Ruby program.
13
14
 
14
- ---
15
- # Installation
15
+ ## Installation
16
16
 
17
17
  1. Install Ruby on your system.
18
18
  2. `gem install asker-tool`
19
19
 
20
- ---
21
- # Usage
20
+ ## Usage
22
21
 
23
22
  Steps:
24
23
 
25
24
  1. Create an input file with your definitions (_conceptual entities_).
26
25
  1. Run _asker_ and get the results into `output` directory.
27
26
 
28
- Example: Running `asker` with our example input file as argument (`jedi.haml`):
27
+ Example: Running `asker` with our example input file as argument (`acdc.haml`):
29
28
 
30
29
  ```
31
- asker docs/examples/starwars/jedi.haml
30
+ asker docs/examples/bands/acdc.haml
32
31
  ```
33
32
 
34
33
  * Output files created into the `output` folder.
35
- * More [example input files](https://github.com/dvarrui/asker/tree/devel/docs/examples).
34
+ * More [example input files](./docs/examples).
36
35
  * More asker input files at `github/dvarrui/asker-inputs` repository.
37
36
 
38
- ---
39
- # Documentation
37
+ ## Documentation
40
38
 
41
39
  * [Installation](https://github.com/dvarrui/asker/blob/devel/docs/install/README.md)
42
40
  * [Inputs](https://github.com/dvarrui/asker/blob/devel/docs/inputs/README.md)
@@ -45,8 +43,7 @@ asker docs/examples/starwars/jedi.haml
45
43
  * [Base idea](https://github.com/dvarrui/asker/blob/devel/docs/idea.md)
46
44
  * [History](https://github.com/dvarrui/asker/blob/devel/docs/history.md)
47
45
 
48
- ---
49
- # Contact
46
+ ## Contact
50
47
 
51
48
  * **Email**: `teuton.software@protonmail.com`
52
49
  * **Twitter**: `@SoftwareTeuton`
@@ -46,7 +46,7 @@ class ConceptAI
46
46
  ##
47
47
  # Generates random image URL
48
48
  def random_image_for(_conceptname)
49
- return '' if rand <= Project.instance.get(:threshold)
49
+ return '' if rand <= ProjectData.instance.get(:threshold)
50
50
 
51
51
  keys = @world.image_urls.keys
52
52
  keys.shuffle!
@@ -8,23 +8,16 @@ require 'rainbow'
8
8
  class Application
9
9
  include Singleton
10
10
 
11
- VERSION = '2.2.0' # Application version
12
- NAME = 'asker' # Application name
13
- HOMEPAGE = "https://github.com/dvarrui/#{NAME}/tree/v2.2"
14
- GEM = 'asker-tool' # Gem name
15
- CONFIGFILE = 'asker.ini' # Config filename
11
+ VERSION = '2.2.1'
12
+ NAME = 'asker'
13
+ GEM = 'asker-tool'
14
+ CONFIGFILE = 'asker.ini'
16
15
  attr_reader :config
17
16
 
18
- ##
19
- # Initialize Application singleton
20
17
  def initialize
21
18
  reset
22
19
  end
23
20
 
24
- ##
25
- # Initialize config values from external "config.ini" file.
26
- # rubocop:disable Metrics/AbcSize
27
- # rubocop:disable Metrics/MethodLength
28
21
  def reset
29
22
  filename = File.join(Dir.pwd, CONFIGFILE)
30
23
  filename = File.join(File.dirname(__FILE__), 'files', CONFIGFILE) unless File.exist? filename
@@ -42,6 +35,4 @@ class Application
42
35
  Rainbow.enabled = false
43
36
  Rainbow.enabled = true if @config['global']['color'].downcase == 'yes'
44
37
  end
45
- # rubocop:enable Metrics/MethodLength
46
- # rubocop:enable Metrics/AbcSize
47
38
  end
data/lib/asker/cli.rb CHANGED
@@ -8,18 +8,16 @@ require_relative '../asker'
8
8
  ##
9
9
  # Command Line User Interface
10
10
  class CLI < Thor
11
- map ['h', '-h', '--help'] => 'help'
11
+ map ['--help'] => 'help'
12
12
 
13
- map ['v', '-v', '--version'] => 'version'
13
+ map ['--version'] => 'version'
14
14
  desc 'version', 'Show the program version'
15
- ##
16
- # Show current version
17
15
  def version
18
16
  puts "#{Application::NAME} version #{Application::VERSION}"
19
17
  end
20
18
 
21
19
  map ['f', '-f', '--file'] => 'file'
22
- desc 'file NAME', 'Build output files, from HAML/XML input file.'
20
+ desc '[file] FILEPATH', 'Build output files, from HAML/XML input file.'
23
21
  long_desc <<-LONGDESC
24
22
 
25
23
  Build questions about contents defined into input file specified.
@@ -35,19 +33,13 @@ class CLI < Thor
35
33
  (3) #{Rainbow('asker projects/foo/foo.yaml').aqua}, Build questions from YAML project file.
36
34
 
37
35
  LONGDESC
38
- ##
39
- # Create questions from input file
40
- # @param filename (String) Path to input file
41
36
  def file(filename)
42
37
  # Asker start processing input file
43
38
  Asker.start(filename)
44
39
  end
45
40
 
46
- map ['c', '-c', '--check'] => 'check'
47
- desc 'check', 'Check input HAML file syntax'
48
- ##
49
- # Check input file syntax
50
- # @param filename (String) Path to input file
41
+ map ['--check'] => 'check'
42
+ desc 'check FILEPATH', 'Check input HAML file syntax'
51
43
  def check(filename)
52
44
  # Enable/disable color output
53
45
  Rainbow.enabled = false if options['color'] == false
@@ -55,29 +47,19 @@ class CLI < Thor
55
47
  Asker.check(filename)
56
48
  end
57
49
 
58
- map ['h', '-h', '--homepage', 'homepage'] => 'show_homepage'
59
- desc 'homepage', 'Documentation homepage'
60
- ##
61
- # Show documentation homepage
62
- def show_homepage()
63
- puts Application::HOMEPAGE
64
- end
65
-
66
- map ['i', '-i', '--init'] => 'init'
50
+ map ['--init'] => 'init'
67
51
  desc 'init', 'Create default INI config file'
68
- ##
69
- # Create default INI config file
70
52
  def init
71
- Asker.create_configuration
53
+ Asker.init
72
54
  end
73
55
 
74
- map ['n', '-n', '--new', 'new'] => 'create_input'
75
- desc 'new [FOLDER]', 'Create Asker demo input files'
56
+ map ['new','--new'] => 'new_input'
57
+ desc 'new DIRPATH', 'Create Asker demo input files'
76
58
  ##
77
59
  # Create Asker demo input files
78
60
  # @param dirname (String) Path to folder
79
- def create_input(dirname)
80
- Asker.create_input(dirname)
61
+ def new_input(dirname)
62
+ Asker.new_input(dirname)
81
63
  end
82
64
 
83
65
  ##
@@ -1,22 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../ai/code/code_ai_factory'
4
- require_relative '../project'
5
- require_relative '../logger'
6
- require_relative '../formatter/code_string_formatter'
7
4
 
8
- ##
9
- # Code data object
10
5
  class Code
11
6
  attr_reader :dirname, :filename, :type
12
7
  attr_accessor :process, :features
13
8
  attr_reader :lines, :questions
14
9
 
15
- ##
16
- # Initialize Code object
17
- # @param dirname (String)
18
- # @param filename (String)
19
- # @param type (String)
20
10
  def initialize(dirname, filename, type)
21
11
  @dirname = dirname
22
12
  @filename = filename
@@ -40,17 +30,13 @@ class Code
40
30
  out
41
31
  end
42
32
 
43
- def debug
44
- Logger.verbose CodeStringFormatter.to_s(self)
45
- end
46
-
47
33
  private
48
34
 
49
35
  def load(filepath)
50
36
  return if filepath.nil?
51
37
 
52
38
  unless File.exist? filepath
53
- Logger.verboseln Rainbow("[ERROR] Unkown file #{filepath}").red.bright
39
+ puts Rainbow("[ERROR] Unkown file #{filepath}").red.bright
54
40
  return
55
41
  end
56
42
  content = File.read(filepath)
@@ -3,8 +3,6 @@
3
3
  require 'rainbow'
4
4
  require 'rexml/document'
5
5
 
6
- require_relative '../application'
7
- require_relative '../logger'
8
6
  require_relative '../lang/lang_factory'
9
7
  require_relative '../loader/embedded_file'
10
8
  require_relative 'table'
@@ -24,7 +22,7 @@ class Concept
24
22
  attr_reader :data # Data about this concept
25
23
  attr_accessor :process # (Boolean) if it is necesary generate questions
26
24
 
27
- @@id = 0 # Global Concept counter
25
+ @@id = 0 # Global Concept counter (concept identifier)
28
26
 
29
27
  ##
30
28
  # Initilize Concept
@@ -93,7 +91,8 @@ class Concept
93
91
  # rubocop:disable Metrics/AbcSize
94
92
  # rubocop:disable Metrics/CyclomaticComplexity
95
93
  def calculate_nearness_to_concept(other)
96
- a = Application.instance.config['ai']['formula_weights']
94
+ a = ProjectData.instance.get(:weights)
95
+ #Application.instance.config['ai']['formula_weights']
97
96
  weights = a.split(',').map(&:to_f)
98
97
 
99
98
  max1 = @context.count
@@ -180,7 +179,7 @@ class Concept
180
179
  @data[:tables] << Table.new(self, i)
181
180
  else
182
181
  text = " [ERROR] Concept #{name} with unkown attribute: #{i.name}"
183
- Logger.verboseln Rainbow(text).color(:red)
182
+ puts Rainbow(text).color(:red)
184
183
  end
185
184
  end
186
185
  end
@@ -195,7 +194,7 @@ class Concept
195
194
 
196
195
  def process_tags(value)
197
196
  if value.text.nil? || value.text.size.zero?
198
- Logger.verboseln Rainbow("[ERROR] Concept #{name} has tags empty!").red.briht
197
+ puts Rainbow("[ERROR] Concept #{name} has tags empty!").red.briht
199
198
  exit 1
200
199
  end
201
200
 
@@ -208,14 +207,16 @@ class Concept
208
207
  def process_def(value)
209
208
  case value.attributes['type']
210
209
  when 'image_url'
210
+ # Link with remote image
211
211
  @data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
212
212
  when 'file'
213
+ # Load local images and text files
213
214
  @data[:images] << EmbeddedFile.load(value.text.strip, File.dirname(@filename))
214
215
  when nil
215
216
  @data[:texts] << value.text.strip
216
217
  else
217
218
  msg = "[ERROR] Unknown type: #{value.attributes['type']}"
218
- Logger.verboseln Rainbow(msg).red.bright
219
+ puts Rainbow(msg).red.bright
219
220
  exit 1
220
221
  end
221
222
  end
@@ -1,43 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'singleton'
4
- require 'rainbow'
5
- require_relative 'application'
6
- require_relative 'logger'
7
4
 
8
- # Contains Project data and methods
9
- class Project
5
+ class ProjectData
10
6
  include Singleton
11
7
  attr_reader :default, :param
12
8
 
13
- ##
14
- # Initialize
15
9
  def initialize
16
10
  reset
17
11
  end
18
12
 
19
- ##
20
- # Reset project params
21
13
  def reset
22
14
  @default = { inputbasedir: FileUtils.pwd,
23
15
  stages: { d: true, b: true, f: true, i: true, s: true, t: true },
24
- threshold: 0.5 }
16
+ threshold: 0.5,
17
+ outputdir: 'output',
18
+ weights: '1, 1, 1' }
25
19
  @param = {}
26
20
  end
27
21
 
28
- ##
29
- # Get value param
30
- # @param key (Symbol) key
31
22
  def get(key)
32
23
  return @param[key] unless @param[key].nil?
33
24
 
34
25
  @default[key]
35
26
  end
36
27
 
37
- ##
38
- # Set value param
39
- # @param key (Symbol) key
40
- # @param value (String) value
41
28
  def set(key, value)
42
29
  @param[key] = value
43
30
  end
@@ -52,7 +39,6 @@ class Project
52
39
  # rubocop:disable Metrics/MethodLength
53
40
  # rubocop:disable Metrics/AbcSize
54
41
  def open
55
- config = Application.instance.config
56
42
  ext = File.extname(@param[:process_file]) || '.haml'
57
43
  @param[:projectname] = @param[:projectname] ||
58
44
  File.basename(@param[:process_file], ext)
@@ -63,7 +49,7 @@ class Project
63
49
  @param[:yamlname] = "#{@param[:projectname]}.yaml"
64
50
  @param[:moodlename] = "#{@param[:projectname]}-moodle.xml"
65
51
 
66
- outputdir = config['output']['folder']
52
+ outputdir = get(:outputdir)
67
53
  @param[:logpath] = File.join(outputdir, get(:logname))
68
54
  @param[:outputpath] = File.join(outputdir, get(:outputname))
69
55
  @param[:lessonpath] = File.join(outputdir, get(:lessonname))
@@ -71,10 +57,6 @@ class Project
71
57
  @param[:moodlepath] = File.join(outputdir, get(:moodlename))
72
58
 
73
59
  Dir.mkdir(outputdir) unless Dir.exist?(outputdir)
74
- Logger.create(self) # Create log file where to save log messages
75
- Logger.verboseln '[INFO] Project open'
76
- Logger.verboseln ' ├── inputdirs = ' + Rainbow(get(:inputdirs)).bright
77
- Logger.verboseln ' └── process_file = ' + Rainbow(get(:process_file)).bright
78
60
  end
79
61
  # rubocop:enable Metrics/MethodLength
80
62
  # rubocop:enable Metrics/AbcSize
@@ -1,22 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../loader/image_url_loader'
4
- require_relative '../project'
5
- require_relative '../logger'
6
4
 
7
- ##
8
- # World data
9
5
  class World
10
6
  attr_reader :concepts, :filenames, :contexts, :image_urls
11
7
 
12
- ##
13
- # Initialize World object
14
- # @param concepts (Array)
15
- # @param show_progress (Boolean)
16
- def initialize(concepts, show_progress = true)
8
+ def initialize(concepts, internet = true)
17
9
  find_neighbors_for_every_concept(concepts)
18
10
  @concepts, @filenames, @contexts = get_lists_from(concepts)
19
- @image_urls = find_url_images_from_internet(show_progress)
11
+ @image_urls = find_url_images_from_internet(internet)
20
12
  end
21
13
 
22
14
  ##
@@ -57,10 +49,9 @@ class World
57
49
  # rubocop:disable Metrics/AbcSize
58
50
  # rubocop:disable Metrics/CyclomaticComplexity
59
51
  # rubocop:disable Metrics/PerceivedComplexity
60
- def find_url_images_from_internet(show_progress)
61
- return {} unless Application.instance.config['global']['internet'] == 'yes'
52
+ def find_url_images_from_internet(internet)
53
+ return {} unless internet
62
54
 
63
- Logger.verbose "\n[INFO] Loading data from Internet" if show_progress
64
55
  threads = []
65
56
  searchs = []
66
57
  urls = {}
@@ -68,11 +59,9 @@ class World
68
59
  @concepts&.each_key { |key| searchs << key }
69
60
  @contexts.each { |filter| searchs << filter.join(' ').to_s }
70
61
  searchs.each do |search|
71
- Logger.verbose('.') if show_progress
72
62
  threads << Thread.new { urls[search] = ImageUrlLoader.load(search) }
73
63
  end
74
64
  threads.each(&:join) # wait for all threads to finish
75
- Logger.verbose("\n") if show_progress
76
65
  urls
77
66
  end
78
67
  # rubocop:enable Metrics/MethodLength
@@ -39,6 +39,7 @@ class ConceptAIDisplayer
39
39
  next unless concept_ai.concept.process?
40
40
 
41
41
  e = concept_ai.concept.texts.size
42
+ e += concept_ai.concept.images.size
42
43
  concept_ai.concept.tables.each { |t| e += t.fields.size * t.rows.size }
43
44
 
44
45
  sd = sb = sf = 0
@@ -13,7 +13,7 @@
13
13
  :f2: 'The next items are "<%=text2%>".<br/>Choose the option that not belongs concept <b><%=text1%></b>.'
14
14
  :f3: 'The next items are "<%=text2%>" from <b><%=text1%></b> concept:<br><p><%=text3%></p>(Put every word into the right position)'
15
15
  :i1: '<%=text1%><br/>Choose the best association for the previous image.<br/>'
16
- :i2: '<%=text1%><br/>The previous image corresponds to <b><%=text2%></b>.'
16
+ :i2: '<%=text1%><br/>The previous image/text corresponds to <b><%=text2%></b>.'
17
17
  :i3: '<%=text1%><br/>Write the best answer <%=text2%>, for the previous image.<br/>'
18
18
  :i4: '<%=text1%><br/>Definition:<br/> <i><%=text2%></i><br/><br/>(Put every word in the right text position)'
19
19
  :s1: "About <b><%=text1%></b> concept, sort every \"<%=text2%>\", so It is true that \"<%=text3%>\".<br/>"
@@ -13,7 +13,7 @@
13
13
  :f2: 'Los siguientes elementos son "<%=text2%>".<br/>Selecciona la opción que no pertenezca al concepto <b><%=text1%></b>.'
14
14
  :f3: 'Los siguientes elementos son "<%=text2%>" del concepto <b><%=text1%></b>:<br><p><%=text3%></p>(Coloca cada palabra en su posición correcta dentro del texto)'
15
15
  :i1: '<%=text1%><br/>Elige la opción que mejor se corresponda con la imagen anterior.<br/>'
16
- :i2: '<%=text1%><br/>La imagen anterior corresponde a <b><%=text2%></b>.'
16
+ :i2: '<%=text1%><br/>La imagen/texto anterior corresponde a <b><%=text2%></b>.'
17
17
  :i3: '<%=text1%><br/>Escribe la opción <%=text2%>, que mejor corresponda con la imagen anterior.<br/>'
18
18
  :i4: '<%=text1%><br/>Definición: <i><%=text2%></i><br/><br/>(Coloca cada palabra en su posición correcta dentro del texto)'
19
19
  :s1: 'En relación al concepto <b><%=text1%></b>, ordena cada/las/los "<%=text2%>" de modo que se cumpla el criterio "<%=text3%>".<br/>'
@@ -3,10 +3,6 @@
3
3
  require 'rainbow'
4
4
  require 'terminal-table'
5
5
 
6
- require_relative '../project'
7
-
8
- ##
9
- # Formatter Concept to Doc
10
6
  module ConceptDocFormatter
11
7
  ##
12
8
  # Formatter Concept into Doc
@@ -4,41 +4,36 @@ require 'rainbow'
4
4
 
5
5
  ##
6
6
  # Check HAML file syntax
7
- module Checker
8
- ##
9
- # Check:
10
- # * file exist
11
- # * filename extension
12
- # * and HAML syntax
13
- # @param filepath (String)
14
- def self.check(filepath)
7
+ module InputChecker
8
+
9
+ def self.check(filepath, verbose = true)
10
+ exist = check_file_exist(filepath, verbose)
11
+ return false unless exist
12
+ check_file_content(filepath, verbose)
13
+ end
14
+
15
+ def self.check_file_exist(filepath, verbose = true)
15
16
  unless File.exist? filepath
16
- puts Rainbow('File not found!').red.bright
17
+ puts Rainbow('File not found!').red.bright if verbose
17
18
  return false
18
19
  end
19
20
  unless File.extname(filepath) == '.haml'
20
- puts Rainbow('Only check HAML files!').yellow.bright
21
+ puts Rainbow('Only check HAML files!').yellow.bright if verbose
21
22
  return false
22
23
  end
23
- check_filepath(filepath)
24
+ true
24
25
  end
25
26
 
26
- ##
27
- # Check HAML syntax
28
- # @param filepath (String)
29
- def self.check_filepath(filepath)
27
+ def self.check_file_content(filepath, verbose = true)
30
28
  data = Data.new(filepath)
31
29
  data.check
32
- data.show_errors
30
+ data.show_errors if verbose
33
31
  data.ok?
34
32
  end
35
33
 
36
- ##
37
- # Internal class that revise syntax
38
34
  # rubocop:disable Metrics/ClassLength
39
35
  class Data
40
- attr_reader :inputs
41
- attr_reader :outputs
36
+ attr_reader :inputs, :outputs
42
37
 
43
38
  # rubocop:disable Metrics/MethodLength
44
39
  def initialize(filepath)
@@ -67,8 +62,6 @@ module Checker
67
62
  end
68
63
  end
69
64
 
70
- # rubocop:disable Metrics/AbcSize
71
- # rubocop:disable Metrics/MethodLength
72
65
  def show_errors
73
66
  errors = 0
74
67
  # puts "Line : Error description"
@@ -78,7 +71,9 @@ module Checker
78
71
  errors += 1
79
72
  if errors < 11
80
73
  data = { id: i[:id], msg: i[:msg], source: i[:source][0, 40] }
81
- puts format(' %<id>03d : %<msg>s. => %<source>s', data)
74
+ order = i[:id] + 1
75
+ data = { order: order, msg: i[:msg], source: i[:source][0, 40] }
76
+ puts format(' %<order>03d : %<msg>s. => %<source>s', data)
82
77
  end
83
78
  puts '...' if errors == 11
84
79
  end
@@ -259,14 +254,15 @@ module Checker
259
254
  @outputs[index][:type] = :row
260
255
  @outputs[index][:state] = :ok
261
256
 
262
- if count_spaces(line) == 6
257
+ case count_spaces(line)
258
+ when 6
263
259
  @outputs[index][:level] = 3
264
260
  parent = find_parent(index)
265
261
  unless %i[table features].include? parent
266
262
  @outputs[index][:state] = :err
267
263
  @outputs[index][:msg] = 'Parent(table/features) not found!'
268
264
  end
269
- elsif count_spaces(line) == 8
265
+ when 8
270
266
  @outputs[index][:level] = 4
271
267
  if find_parent(index) != :template
272
268
  @outputs[index][:state] = :err
@@ -288,13 +284,14 @@ module Checker
288
284
 
289
285
  @outputs[index][:type] = :col
290
286
  @outputs[index][:state] = :ok
291
- if count_spaces(line) == 8
287
+ case count_spaces(line)
288
+ when 8
292
289
  @outputs[index][:level] = 4
293
290
  if find_parent(index) != :row
294
291
  @outputs[index][:state] = :err
295
292
  @outputs[index][:msg] = 'Parent(row) not found!'
296
293
  end
297
- elsif count_spaces(line) == 10
294
+ when 10
298
295
  @outputs[index][:level] = 5
299
296
  if find_parent(index) != :row
300
297
  @outputs[index][:state] = :err
@@ -4,8 +4,7 @@ require 'rainbow'
4
4
  require 'rexml/document'
5
5
  require_relative '../data/concept'
6
6
  require_relative 'code_loader'
7
- require_relative '../logger'
8
- require_relative '../project'
7
+ require_relative '../data/project_data'
9
8
 
10
9
  # Define methods that load data from XML contents
11
10
  module ContentLoader
@@ -33,7 +32,7 @@ module ContentLoader
33
32
  when 'code'
34
33
  codes << read_code(xmldata, filepath)
35
34
  else
36
- Logger.verboseln Rainbow("[ERROR] Unkown tag <#{xmldata.name}>").red
35
+ puts Rainbow("[ERROR] Unkown tag <#{xmldata.name}>").red
37
36
  end
38
37
  end
39
38
 
@@ -49,7 +48,7 @@ module ContentLoader
49
48
  begin
50
49
  lang = xmldata.root.attributes['lang']
51
50
  rescue StandardError
52
- lang = Project.instance.lang
51
+ lang = ProjectData.instance.lang
53
52
  end
54
53
  lang
55
54
  end
@@ -73,7 +72,7 @@ module ContentLoader
73
72
  # @param lang
74
73
  # @param context
75
74
  private_class_method def self.read_concept(xmldata, filepath, lang, context)
76
- project = Project.instance
75
+ project = ProjectData.instance
77
76
  c = Concept.new(xmldata, filepath, lang, context)
78
77
  c.process = true if [File.basename(filepath), :default].include? project.get(:process_file)
79
78
  c
@@ -84,7 +83,7 @@ module ContentLoader
84
83
  # @param xmldata (XML Object)
85
84
  # @param filepath (String)
86
85
  private_class_method def self.read_code(xmldata, filepath)
87
- project = Project.instance
86
+ project = ProjectData.instance
88
87
  c = CodeLoader.load(xmldata, filepath)
89
88
  c.process = true if [File.basename(filepath), :default].include? project.get(:process_file)
90
89
  c
@@ -95,8 +94,7 @@ module ContentLoader
95
94
  # @param filepath (String)
96
95
  # @param content (String)
97
96
  private_class_method def self.raise_error_with(filepath, content)
98
- msg = Rainbow("[ERROR] ContentLoader: Format error in #{filepath}").red.bright
99
- Logger.verboseln msg
97
+ puts Rainbow("[ERROR] ContentLoader: Format error in #{filepath}").red.bright
100
98
  f = File.open('output/error.xml', 'w')
101
99
  f.write(content)
102
100
  f.close
@@ -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.verboseln " * 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.verboseln " └── Input file = #{Rainbow(filepath).bright}"
53
- else
54
- Logger.verboseln " ├── Input file = #{Rainbow(filepath).bright}"
55
- end
56
49
  FileLoader.load(filepath)
57
50
  end
58
51
  end
@@ -2,7 +2,6 @@
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
@@ -15,8 +14,7 @@ module FileLoader
15
14
  elsif File.extname(filename).casecmp('.xml').zero?
16
15
  file_content = File.read(filename)
17
16
  else
18
- msg = "[ERROR] FileLoader: Format error #{filename}"
19
- Logger.verboseln msg
17
+ puts "[ERROR] FileLoader: Format error #{filename}"
20
18
  raise msg
21
19
  end
22
20
  ContentLoader.load(filename, file_content)
@@ -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,10 +34,10 @@ 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
@@ -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.verboseln "\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
@@ -16,7 +15,7 @@ module ProjectLoader
16
15
  # @param args (String or Hash)
17
16
  # rubocop:disable Metrics/MethodLength
18
17
  def self.load(args)
19
- project = Project.instance
18
+ project = ProjectData.instance
20
19
 
21
20
  if args.class == Hash
22
21
  project.param.merge!(args)
@@ -30,7 +29,7 @@ module ProjectLoader
30
29
 
31
30
  msg = '[ERROR] ProjectLoader:'
32
31
  msg += "Configuration params format is <#{pArgs.class}>!"
33
- Logger.verboseln Rainbow(msg).red
32
+ puts Rainbow(msg).red
34
33
  raise msg
35
34
  end
36
35
  # rubocop:enable Metrics/MethodLength
@@ -44,10 +43,10 @@ module ProjectLoader
44
43
  # rubocop:disable Metrics/MethodLength
45
44
  # rubocop:disable Metrics/AbcSize
46
45
  def self.load_from_string(filepath)
47
- project = Project.instance
46
+ project = ProjectData.instance
48
47
  unless File.exist?(filepath)
49
48
  msg = Rainbow("[ERROR] #{filepath} not found!").red.bright
50
- Logger.verboseln msg
49
+ puts msg
51
50
  exit 1
52
51
  end
53
52
 
@@ -65,7 +64,7 @@ module ProjectLoader
65
64
 
66
65
  # rubocop:disable Security/YAMLLoad
67
66
  def self.load_from_yaml(arg)
68
- project = Project.instance
67
+ project = ProjectData.instance
69
68
  project.param.merge!(YAML.load(File.open(arg)))
70
69
  project.set(:configfilename, arg)
71
70
  project.set(:projectdir, File.dirname(arg))
@@ -77,7 +76,7 @@ module ProjectLoader
77
76
  # Error found and exit application.
78
77
  def self.error_loading(arg)
79
78
  msg = Rainbow("[ERROR] Loading... #{arg}").red.bright
80
- Logger.verboseln msg
79
+ puts msg
81
80
  exit 1
82
81
  end
83
82
  end
data/lib/asker/logger.rb CHANGED
@@ -6,39 +6,41 @@ require_relative 'application'
6
6
  # Display and log project messages
7
7
  class Logger
8
8
  include Singleton
9
+ @attr_verbose = 'yes'
9
10
 
10
- def initialize
11
- @logfile = null
11
+ def set_verbose(value)
12
+ @attr_verbose = value
12
13
  end
13
14
 
14
- ##
15
- # Display and log text
16
15
  def self.verbose(msg)
17
- print msg if Application.instance.config['global']['verbose'] == 'yes'
16
+ print msg if @attr_verbose == 'yes'
18
17
  @logfile&.write(msg)
19
18
  end
20
19
 
21
- ##
22
- # Display and log text line
23
20
  def self.verboseln(msg)
24
21
  verbose(msg + "\n")
25
22
  end
26
23
 
24
+ def log(msg)
25
+ verbose(msg)
26
+ end
27
+
28
+ def logln(msg)
29
+ verboseln(msg)
30
+ end
27
31
  ##
28
32
  # Create or reset logfile
29
- def self.create(project)
30
- @logfile = File.open(project.get(:logpath), 'w')
33
+ def self.create(logpath, logname)
34
+ @logfile = File.open(logpath, 'w')
31
35
  @logfile.write('=' * 50 + "\n")
32
36
  @logfile.write("Created by : #{Application::NAME}")
33
37
  @logfile.write(" (version #{Application::VERSION})\n")
34
- @logfile.write("File : #{project.get(:logname)}\n")
38
+ @logfile.write("File : #{logname}\n")
35
39
  @logfile.write("Time : #{Time.new}\n")
36
40
  @logfile.write("Author : David Vargas Ruiz\n")
37
41
  @logfile.write('=' * 50 + "\n\n")
38
42
  end
39
43
 
40
- ##
41
- # Close Log file
42
44
  def self.close
43
45
  @logfile.close
44
46
  end
data/lib/asker.rb CHANGED
@@ -2,61 +2,66 @@
2
2
 
3
3
  require 'rainbow'
4
4
 
5
+ require_relative 'asker/skeleton'
6
+ require_relative 'asker/input_checker'
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'
11
+ require_relative 'asker/logger'
12
+
8
13
  require_relative 'asker/loader/project_loader'
9
14
  require_relative 'asker/loader/input_loader'
10
- require_relative 'asker/checker'
11
- require_relative 'asker/logger'
12
- require_relative 'asker/skeleton'
13
15
 
14
- ##
15
- # Asker main class
16
16
  class Asker
17
- ##
18
- # Create asker input demo files
19
- # @param dirpath (String)
20
- def self.create_input(dirpath)
21
- Skeleton.create_input(dirpath)
17
+ def self.init
18
+ Skeleton.create_configuration
22
19
  end
23
20
 
24
- ##
25
- # Create asker configuration files
26
- def self.create_configuration
27
- Skeleton.create_configuration
21
+ def self.new_input(dirpath)
22
+ Skeleton.create_input(dirpath)
28
23
  end
29
24
 
30
- ##
31
- # Checking input file syntax
32
- # @param filepath (String)
33
25
  def self.check(filepath)
34
- Checker.check(filepath)
26
+ InputChecker.check(filepath)
35
27
  end
36
28
 
37
- ##
38
- # Start working
39
- # @param filepath (String) HAML or XML filepath
40
29
  def self.start(filepath)
41
- project, data = load_input(filepath)
30
+ project_data, data = load_input(filepath)
42
31
  ConceptDisplayer.show(data[:concepts])
43
- create_output(project, data)
32
+ create_output(project_data, data)
44
33
  end
45
34
 
46
- ##
47
- # Load input data
48
- # @param args (Hash)
49
35
  private_class_method def self.load_input(args)
50
- project = ProjectLoader.load(args)
51
- data = InputLoader.load(project.get(:inputdirs).split(','))
52
- [project, data]
36
+ init_project_data
37
+ project_data = ProjectLoader.load(args)
38
+ init_logger(project_data)
39
+
40
+ inputdirs = project_data.get(:inputdirs).split(',')
41
+ internet = Application.instance.config['global']['internet'] == 'yes'
42
+ data = InputLoader.load(inputdirs, internet)
43
+ [project_data, data]
44
+ end
45
+
46
+ private_class_method def self.init_project_data()
47
+ project_data = ProjectData.instance
48
+ outputdir = Application.instance.config['output']['folder']
49
+ project_data.set(:outputdir, outputdir)
50
+
51
+ formula_weights = Application.instance.config['ai']['formula_weights']
52
+ project_data.set(:weights, formula_weights)
53
+ end
54
+
55
+ private_class_method def self.init_logger(project_data)
56
+ # Create log file where to save log messages
57
+ Logger.create(project_data.get(:logpath),
58
+ project_data.get(:logname))
59
+ Logger.instance.set_verbose(Application.instance.config['verbose'])
60
+ Logger.verboseln '[INFO] Project open'
61
+ Logger.verboseln ' ├── inputdirs = ' + Rainbow(project_data.get(:inputdirs)).bright
62
+ Logger.verboseln ' └── process_file = ' + Rainbow(project_data.get(:process_file)).bright
53
63
  end
54
64
 
55
- ##
56
- # Create output files: Gift, YAML, TXT Doc
57
- # rubocop:disable Metrics/AbcSize
58
- # rubocop:disable Metrics/MethodLength
59
- # rubocop:disable Metrics/PerceivedComplexity
60
65
  private_class_method def self.create_output(project, data)
61
66
  Logger.verboseln "\n[INFO] Creating output files"
62
67
  m = ' ├── Gift questions file => '
@@ -94,7 +99,4 @@ class Asker
94
99
  StatsDisplayer.show(data)
95
100
  Logger.close
96
101
  end
97
- # rubocop:enable Metrics/AbcSize
98
- # rubocop:enable Metrics/MethodLength
99
- # rubocop:enable Metrics/PerceivedComplexity
100
102
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asker-tool
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Vargas Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-21 00:00:00.000000000 Z
11
+ date: 2022-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml
@@ -142,12 +142,12 @@ files:
142
142
  - lib/asker/ai/stages/stage_s.rb
143
143
  - lib/asker/ai/stages/stage_t.rb
144
144
  - lib/asker/application.rb
145
- - lib/asker/checker.rb
146
145
  - lib/asker/cli.rb
147
146
  - lib/asker/data/code.rb
148
147
  - lib/asker/data/column.rb
149
148
  - lib/asker/data/concept.rb
150
149
  - lib/asker/data/data_field.rb
150
+ - lib/asker/data/project_data.rb
151
151
  - lib/asker/data/row.rb
152
152
  - lib/asker/data/table.rb
153
153
  - lib/asker/data/template.rb
@@ -206,6 +206,7 @@ files:
206
206
  - lib/asker/formatter/question_moodle_formatter.rb
207
207
  - lib/asker/formatter/question_moodlexml_formatter.rb
208
208
  - lib/asker/formatter/rb2haml_formatter.rb
209
+ - lib/asker/input_checker.rb
209
210
  - lib/asker/lang/lang.rb
210
211
  - lib/asker/lang/lang_factory.rb
211
212
  - lib/asker/lang/text_actions.rb
@@ -219,9 +220,8 @@ files:
219
220
  - lib/asker/loader/input_loader.rb
220
221
  - lib/asker/loader/project_loader.rb
221
222
  - lib/asker/logger.rb
222
- - lib/asker/project.rb
223
223
  - lib/asker/skeleton.rb
224
- homepage: https://github.com/dvarrui/asker/tree/v2.2
224
+ homepage: https://github.com/teuton-software/asker/tree/v2.2
225
225
  licenses:
226
226
  - GPL-3.0
227
227
  metadata: {}
@@ -233,14 +233,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
233
  requirements:
234
234
  - - ">="
235
235
  - !ruby/object:Gem::Version
236
- version: 2.5.0
236
+ version: 2.6.9
237
237
  required_rubygems_version: !ruby/object:Gem::Requirement
238
238
  requirements:
239
239
  - - ">="
240
240
  - !ruby/object:Gem::Version
241
241
  version: '0'
242
242
  requirements: []
243
- rubygems_version: 3.2.32
243
+ rubygems_version: 3.1.2
244
244
  signing_key:
245
245
  specification_version: 4
246
246
  summary: Asker generates questions from input definitions file.