asker-tool 2.2.0 → 2.2.1

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