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 +4 -4
- data/README.md +12 -15
- data/lib/asker/ai/concept_ai.rb +1 -1
- data/lib/asker/application.rb +4 -13
- data/lib/asker/cli.rb +11 -29
- data/lib/asker/data/code.rb +1 -15
- data/lib/asker/data/concept.rb +8 -7
- data/lib/asker/{project.rb → data/project_data.rb} +5 -23
- data/lib/asker/data/world.rb +4 -15
- data/lib/asker/displayer/concept_ai_displayer.rb +1 -0
- data/lib/asker/files/language/en/templates.yaml +1 -1
- data/lib/asker/files/language/es/templates.yaml +1 -1
- data/lib/asker/formatter/concept_doc_formatter.rb +0 -4
- data/lib/asker/{checker.rb → input_checker.rb} +24 -27
- data/lib/asker/loader/content_loader.rb +6 -8
- data/lib/asker/loader/directory_loader.rb +1 -8
- data/lib/asker/loader/file_loader.rb +1 -3
- data/lib/asker/loader/image_url_loader.rb +4 -6
- data/lib/asker/loader/input_loader.rb +5 -6
- data/lib/asker/loader/project_loader.rb +7 -8
- data/lib/asker/logger.rb +14 -12
- data/lib/asker.rb +39 -37
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb2119553ee0f5bce53f1aebe3468aabb5488ce02c54004c09df4d1256867cf5
|
4
|
+
data.tar.gz: 29bc8b727e10beb791eac5a113751f6d26ec9036cf3158aec583a93505fb3ba5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3f277896c860c2987c25b4088922328f922fa52c8e2bb32ba92b6d90c6b86e05f2c0c9a056f3c69139148266f6bd4443192ca4d6892ee6e6884fb1e6cb3bad4
|
7
|
+
data.tar.gz: f9bb53fa2c7d5ee05566eb19657e4997d84dea2f521e1445a64fb658b06a7b6b1326e8b3d010fa21b5758c8538fc33ed1f675752493db4a366be9ac881944057
|
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
|
1
|
+
[](https://badge.fury.io/rb/asker-tool)
|
2
2
|
|
3
|
-
|
3
|
+
# ASKER (devel 2.3)
|
4
4
|
|
5
|
-
|
6
|
-
|
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
|
+

|
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 (`
|
27
|
+
Example: Running `asker` with our example input file as argument (`acdc.haml`):
|
29
28
|
|
30
29
|
```
|
31
|
-
asker docs/examples/
|
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](
|
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`
|
data/lib/asker/ai/concept_ai.rb
CHANGED
@@ -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 <=
|
49
|
+
return '' if rand <= ProjectData.instance.get(:threshold)
|
50
50
|
|
51
51
|
keys = @world.image_urls.keys
|
52
52
|
keys.shuffle!
|
data/lib/asker/application.rb
CHANGED
@@ -8,23 +8,16 @@ require 'rainbow'
|
|
8
8
|
class Application
|
9
9
|
include Singleton
|
10
10
|
|
11
|
-
VERSION = '2.2.
|
12
|
-
NAME = 'asker'
|
13
|
-
|
14
|
-
|
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 ['
|
11
|
+
map ['--help'] => 'help'
|
12
12
|
|
13
|
-
map ['
|
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
|
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 ['
|
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 ['
|
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.
|
53
|
+
Asker.init
|
72
54
|
end
|
73
55
|
|
74
|
-
map ['
|
75
|
-
desc 'new
|
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
|
80
|
-
Asker.
|
61
|
+
def new_input(dirname)
|
62
|
+
Asker.new_input(dirname)
|
81
63
|
end
|
82
64
|
|
83
65
|
##
|
data/lib/asker/data/code.rb
CHANGED
@@ -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
|
-
|
39
|
+
puts Rainbow("[ERROR] Unkown file #{filepath}").red.bright
|
54
40
|
return
|
55
41
|
end
|
56
42
|
content = File.read(filepath)
|
data/lib/asker/data/concept.rb
CHANGED
@@ -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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =
|
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
|
data/lib/asker/data/world.rb
CHANGED
@@ -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(
|
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(
|
61
|
-
return {} unless
|
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
|
@@ -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/>'
|
@@ -4,41 +4,36 @@ require 'rainbow'
|
|
4
4
|
|
5
5
|
##
|
6
6
|
# Check HAML file syntax
|
7
|
-
module
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 '../
|
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
|
-
|
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 =
|
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 =
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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 '../
|
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 =
|
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
|
-
|
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 =
|
46
|
+
project = ProjectData.instance
|
48
47
|
unless File.exist?(filepath)
|
49
48
|
msg = Rainbow("[ERROR] #{filepath} not found!").red.bright
|
50
|
-
|
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 =
|
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
|
-
|
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
|
11
|
-
@
|
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
|
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(
|
30
|
-
@logfile = File.open(
|
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 : #{
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
30
|
+
project_data, data = load_input(filepath)
|
42
31
|
ConceptDisplayer.show(data[:concepts])
|
43
|
-
create_output(
|
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
|
-
|
51
|
-
|
52
|
-
|
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.
|
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:
|
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/
|
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.
|
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
|
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.
|