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 +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
|
+
[![Gem Version](https://badge.fury.io/rb/asker-tool.svg)](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
|
+
![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 (`
|
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.
|