asker-tool 2.1.3 → 2.2.0
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 +18 -19
- data/bin/asker +2 -1
- data/lib/asker/ai/ai.rb +10 -3
- data/lib/asker/ai/ai_calculate.rb +20 -6
- data/lib/asker/ai/code/base_code_ai.rb +104 -0
- data/lib/asker/{code/ai → ai/code}/code_ai_factory.rb +11 -1
- data/lib/asker/{code/ai → ai/code}/javascript_code_ai.rb +2 -5
- data/lib/asker/ai/code/problem_code_ai.rb +176 -0
- data/lib/asker/{code/ai → ai/code}/python_code_ai.rb +2 -5
- data/lib/asker/{code/ai → ai/code}/ruby_code_ai.rb +14 -7
- data/lib/asker/{code/ai → ai/code}/sql_code_ai.rb +2 -5
- data/lib/asker/ai/concept_ai.rb +12 -2
- data/lib/asker/ai/question.rb +28 -6
- data/lib/asker/ai/stages/base_stage.rb +45 -6
- data/lib/asker/ai/stages/stage_b.rb +100 -50
- data/lib/asker/ai/stages/stage_d.rb +75 -90
- data/lib/asker/ai/stages/stage_f.rb +64 -36
- data/lib/asker/ai/stages/stage_i.rb +79 -92
- data/lib/asker/ai/stages/stage_s.rb +41 -36
- data/lib/asker/ai/stages/stage_t.rb +149 -108
- data/lib/asker/application.rb +24 -7
- data/lib/asker/checker.rb +149 -52
- data/lib/asker/cli.rb +37 -32
- data/lib/asker/data/code.rb +76 -0
- data/lib/asker/data/column.rb +31 -21
- data/lib/asker/data/concept.rb +108 -65
- data/lib/asker/data/data_field.rb +14 -0
- data/lib/asker/data/row.rb +75 -52
- data/lib/asker/data/table.rb +91 -42
- data/lib/asker/data/template.rb +3 -1
- data/lib/asker/data/world.rb +61 -32
- data/lib/asker/{exporter/code_screen_exporter.rb → displayer/code_displayer.rb} +13 -6
- data/lib/asker/displayer/concept_ai_displayer.erb +10 -0
- data/lib/asker/displayer/concept_ai_displayer.rb +133 -0
- data/lib/asker/displayer/concept_displayer.rb +34 -0
- data/lib/asker/displayer/stats_displayer.rb +22 -0
- data/lib/asker/exporter/code_gift_exporter.rb +10 -11
- data/lib/asker/exporter/concept_ai_gift_exporter.rb +21 -13
- data/lib/asker/exporter/concept_ai_moodle_exporter.rb +44 -0
- data/lib/asker/exporter/concept_ai_yaml_exporter.rb +14 -9
- data/lib/asker/exporter/concept_doc_exporter.rb +21 -14
- data/lib/asker/exporter/data_gift_exporter.rb +29 -0
- data/lib/asker/exporter/output_file_exporter.rb +21 -0
- data/lib/asker/files/{config.ini → asker.ini} +48 -1
- data/lib/asker/files/example-concept.haml +24 -8
- data/lib/asker/files/language/du/connectors.yaml +81 -0
- data/lib/asker/files/language/du/mistakes.yaml +82 -0
- data/lib/asker/files/language/du/templates.yaml +29 -0
- data/lib/asker/files/language/en/connectors.yaml +44 -0
- data/lib/asker/files/language/en/mistakes.yaml +37 -0
- data/lib/asker/files/language/en/templates.yaml +29 -0
- data/lib/asker/files/language/es/connectors.yaml +92 -0
- data/lib/asker/files/language/es/mistakes.yaml +84 -0
- data/lib/asker/files/language/es/templates.yaml +29 -0
- data/lib/asker/files/language/fr/connectors.yaml +76 -0
- data/lib/asker/files/language/fr/mistakes.yaml +82 -0
- data/lib/asker/files/language/fr/templates.yaml +29 -0
- data/lib/asker/files/language/javascript/connectors.yaml +11 -0
- data/lib/asker/files/language/javascript/mistakes.yaml +30 -0
- data/lib/asker/files/language/javascript/templates.yaml +3 -0
- data/lib/asker/files/language/math/connectors.yaml +2 -0
- data/lib/asker/files/language/math/mistakes.yaml +2 -0
- data/lib/asker/files/language/math/templates.yaml +1 -0
- data/lib/asker/files/language/python/connectors.yaml +11 -0
- data/lib/asker/files/language/python/mistakes.yaml +26 -0
- data/lib/asker/files/language/python/templates.yaml +3 -0
- data/lib/asker/files/language/ruby/connectors.yaml +11 -0
- data/lib/asker/files/language/ruby/mistakes.yaml +33 -0
- data/lib/asker/files/language/ruby/templates.yaml +3 -0
- data/lib/asker/files/language/sql/connectors.yaml +6 -0
- data/lib/asker/files/language/sql/mistakes.yaml +11 -0
- data/lib/asker/files/language/sql/templates.yaml +2 -0
- data/lib/asker/formatter/concept_string_formatter.rb +13 -9
- data/lib/asker/formatter/moodle/matching.erb +38 -0
- data/lib/asker/formatter/moodle/multichoice.erb +49 -0
- data/lib/asker/formatter/moodle/shortanswer.erb +30 -0
- data/lib/asker/formatter/moodle/truefalse.erb +47 -0
- data/lib/asker/formatter/question_gift_formatter.rb +30 -20
- data/lib/asker/formatter/question_moodle_formatter.rb +27 -0
- data/lib/asker/lang/lang.rb +18 -12
- data/lib/asker/lang/lang_factory.rb +32 -5
- data/lib/asker/lang/text_actions.rb +87 -69
- data/lib/asker/loader/code_loader.rb +4 -4
- data/lib/asker/loader/content_loader.rb +16 -12
- data/lib/asker/loader/directory_loader.rb +3 -3
- data/lib/asker/loader/embedded_file.rb +42 -0
- data/lib/asker/loader/file_loader.rb +3 -12
- data/lib/asker/loader/haml_loader.rb +15 -0
- data/lib/asker/loader/image_url_loader.rb +9 -11
- data/lib/asker/loader/input_loader.rb +24 -8
- data/lib/asker/loader/project_loader.rb +42 -30
- data/lib/asker/logger.rb +30 -6
- data/lib/asker/project.rb +28 -117
- data/lib/asker/skeleton.rb +40 -29
- data/lib/asker.rb +68 -79
- metadata +57 -74
- data/docs/changelog/v2.1.md +0 -99
- data/docs/commands.md +0 -12
- data/docs/contributions.md +0 -18
- data/docs/history.md +0 -40
- data/docs/idea.md +0 -44
- data/docs/inputs/README.md +0 -39
- data/docs/inputs/code.md +0 -69
- data/docs/inputs/concepts.md +0 -142
- data/docs/inputs/jedi.md +0 -68
- data/docs/inputs/tables.md +0 -112
- data/docs/inputs/templates.md +0 -87
- data/docs/install/README.md +0 -38
- data/docs/install/manual.md +0 -26
- data/docs/install/scripts.md +0 -38
- data/docs/revise/asker-file.md +0 -41
- data/docs/revise/buenas-practicas/01-convocatoria.md +0 -30
- data/docs/revise/buenas-practicas/02-formulario.md +0 -35
- data/docs/revise/buenas-practicas/03-descripcion.md +0 -63
- data/docs/revise/buenas-practicas/04-resultados.md +0 -17
- data/docs/revise/buenas-practicas/05-reproducir.md +0 -10
- data/docs/revise/ejemplos/01/README.md +0 -27
- data/docs/revise/ejemplos/02/README.md +0 -31
- data/docs/revise/ejemplos/03/README.md +0 -31
- data/docs/revise/ejemplos/04/README.md +0 -37
- data/docs/revise/ejemplos/05/README.md +0 -25
- data/docs/revise/ejemplos/06/README.md +0 -43
- data/docs/revise/ejemplos/README.md +0 -11
- data/docs/revise/projects.md +0 -74
- data/lib/asker/code/ai/base_code_ai.rb +0 -48
- data/lib/asker/code/code.rb +0 -53
- data/lib/asker/exporter/concept_ai_screen_exporter.rb +0 -115
- data/lib/asker/exporter/concept_screen_exporter.rb +0 -25
- data/lib/asker/exporter/main.rb +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a17926e45cfc0549f76ae3d8ec9c5313565847e3615653f7520344e03eea63f7
|
|
4
|
+
data.tar.gz: 717620e1a5d56c65dc0ec601de61ffef208f3e21087e71e84a4c421e9e65c67f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9ec3c2b84781c6c723edfbb0e5570edaabb8e26fd0d732bb9fa155d7b6fb5762115a44ba75899af7e0e0b399d6b764562de77dd31b0b2fe128c5dd97b39caf7d
|
|
7
|
+
data.tar.gz: 3f1aa7b3ce5a9f59f3c373bd246f5fd8e8000a163ec539f943f32144fff057f80b44ae06bc127a31eb3ad71de0bb431d010a737491e57695c202e97534674a69
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ASKER (version 2.
|
|
1
|
+
# ASKER (version 2.2)
|
|
2
2
|
|
|
3
3
|
Generate a lot of questions from an _input file_ base on your own _definitions_.
|
|
4
4
|
|
|
@@ -7,41 +7,40 @@ Generate a lot of questions from an _input file_ base on your own _definitions_.
|
|
|
7
7
|
|
|
8
8
|
ASKER helps trainers to create a huge amount of questions, from a definitions (_conceptual entities_) input file.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
1. Create an input file with your definitions (_conceptual entities_).
|
|
13
|
-
1. Run _asker_ and get the results into `output` directory.
|
|
14
|
-
|
|
15
|
-
Features:
|
|
16
|
-
|
|
17
|
-
* Free Software [LICENSE](https://github.com/dvarrui/asker/blob/devel/LICENSE).
|
|
10
|
+
* Free Software [LICENSE](https://github.com/dvarrui/asker/blob/devel/LICENSE.txt).
|
|
18
11
|
* Multiplatform.
|
|
19
|
-
* Input file formats: HAML, XML.
|
|
20
|
-
* Output file format: GIFT (Moodle cuestionairs).
|
|
21
12
|
* Ruby program.
|
|
22
13
|
|
|
14
|
+
---
|
|
15
|
+
# Installation
|
|
16
|
+
|
|
17
|
+
1. Install Ruby on your system.
|
|
18
|
+
2. `gem install asker-tool`
|
|
19
|
+
|
|
23
20
|
---
|
|
24
21
|
# Usage
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
Steps:
|
|
24
|
+
|
|
25
|
+
1. Create an input file with your definitions (_conceptual entities_).
|
|
26
|
+
1. Run _asker_ and get the results into `output` directory.
|
|
27
|
+
|
|
28
|
+
Example: Running `asker` with our example input file as argument (`jedi.haml`):
|
|
27
29
|
|
|
28
30
|
```
|
|
29
31
|
asker docs/examples/starwars/jedi.haml
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* More examples at `github/dvarrui/asker-inputs` repository.
|
|
34
|
+
* Output files created into the `output` folder.
|
|
35
|
+
* More [example input files](https://github.com/dvarrui/asker/tree/devel/docs/examples).
|
|
36
|
+
* More asker input files at `github/dvarrui/asker-inputs` repository.
|
|
36
37
|
|
|
37
38
|
---
|
|
38
39
|
# Documentation
|
|
39
40
|
|
|
40
41
|
* [Installation](https://github.com/dvarrui/asker/blob/devel/docs/install/README.md)
|
|
41
|
-
1. Install Ruby on your system.
|
|
42
|
-
2. `gem install asker-tool`
|
|
43
42
|
* [Inputs](https://github.com/dvarrui/asker/blob/devel/docs/inputs/README.md)
|
|
44
|
-
* [
|
|
43
|
+
* [Usage](https://github.com/dvarrui/asker/blob/devel/docs/usage.md)
|
|
45
44
|
* [Contributions](https://github.com/dvarrui/asker/blob/devel/docs/contributions.md)
|
|
46
45
|
* [Base idea](https://github.com/dvarrui/asker/blob/devel/docs/idea.md)
|
|
47
46
|
* [History](https://github.com/dvarrui/asker/blob/devel/docs/history.md)
|
data/bin/asker
CHANGED
data/lib/asker/ai/ai.rb
CHANGED
|
@@ -6,14 +6,14 @@ require_relative 'ai_calculate'
|
|
|
6
6
|
# Description: Method to be included into every ConceptAI instance.
|
|
7
7
|
# * make_questions: use AI to fill @questions Array
|
|
8
8
|
module AI
|
|
9
|
-
include
|
|
9
|
+
include AICalculate
|
|
10
10
|
|
|
11
11
|
def make_questions
|
|
12
|
-
return unless process?
|
|
12
|
+
return unless concept.process?
|
|
13
13
|
|
|
14
14
|
make_questions_stages_di
|
|
15
15
|
# Process every table of this concept
|
|
16
|
-
tables.each do |tab|
|
|
16
|
+
concept.tables.each do |tab|
|
|
17
17
|
list1, list2 = get_list1_and_list2_from(tab)
|
|
18
18
|
make_questions_stages_bsf(tab, list1, list2)
|
|
19
19
|
make_questions_stages_t(tab, list1, list2)
|
|
@@ -23,11 +23,13 @@ module AI
|
|
|
23
23
|
exclude_questions
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# Make questions for states D and I
|
|
26
27
|
def make_questions_stages_di
|
|
27
28
|
@questions[:d] = StageD.new(self).run # Process every def{type=text}
|
|
28
29
|
@questions[:i] = StageI.new(self).run # Process every def{type=image_url}
|
|
29
30
|
end
|
|
30
31
|
|
|
32
|
+
# Make questions for stages B, S and F
|
|
31
33
|
def make_questions_stages_bsf(tab, list1, list2)
|
|
32
34
|
# Stage B: process table to make match questions
|
|
33
35
|
@questions[:b] += StageB.new(self).run(tab, list1, list2)
|
|
@@ -37,6 +39,7 @@ module AI
|
|
|
37
39
|
@questions[:f] += StageF.new(self).run(tab, list1, list2)
|
|
38
40
|
end
|
|
39
41
|
|
|
42
|
+
# Make questions for stage T
|
|
40
43
|
def make_questions_stages_t(tab, list1, list2)
|
|
41
44
|
# Stage T: process_tableXfields
|
|
42
45
|
list3 = list1 + list2
|
|
@@ -46,6 +49,8 @@ module AI
|
|
|
46
49
|
end
|
|
47
50
|
end
|
|
48
51
|
|
|
52
|
+
# rubocop:disable Metrics/AbcSize
|
|
53
|
+
# rubocop:disable Metrics/MethodLength
|
|
49
54
|
def exclude_questions
|
|
50
55
|
param = Application.instance.config['questions']['exclude']
|
|
51
56
|
return if param.nil?
|
|
@@ -61,6 +66,8 @@ module AI
|
|
|
61
66
|
@questions = input
|
|
62
67
|
@excluded_questions = output
|
|
63
68
|
end
|
|
69
|
+
# rubocop:enable Metrics/AbcSize
|
|
70
|
+
# rubocop:enable Metrics/MethodLength
|
|
64
71
|
|
|
65
72
|
def string_has_this_tags?(input, tags)
|
|
66
73
|
flag = false
|
|
@@ -1,29 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Methods that calculate something
|
|
4
|
-
module
|
|
5
|
-
|
|
4
|
+
module AICalculate
|
|
5
|
+
##
|
|
6
|
+
# Calculate and return list1 and list2
|
|
7
|
+
# * return list1 (Array) List with all the rows from the table
|
|
8
|
+
# * return list2 (Array) List with similar rows (same table name) from the neighbours tables
|
|
9
|
+
# @param p_table (Table)
|
|
10
|
+
# rubocop:disable Metrics/MethodLength
|
|
11
|
+
# rubocop:disable Metrics/AbcSize
|
|
12
|
+
def get_list1_and_list2_from(p_table)
|
|
6
13
|
# create <list1> with all the rows from the table
|
|
7
14
|
list1 = []
|
|
8
15
|
count = 1
|
|
9
|
-
|
|
16
|
+
p_table.rows.each do |i|
|
|
10
17
|
list1 << { id: count, weight: 0, data: i }
|
|
11
18
|
count += 1
|
|
12
19
|
end
|
|
13
20
|
|
|
14
21
|
# create a <list2> with similar rows (same table name) from the neighbours tables
|
|
15
22
|
list2 = []
|
|
16
|
-
neighbors.each do |n|
|
|
23
|
+
concept.neighbors.each do |n|
|
|
17
24
|
n[:concept].tables.each do |t2|
|
|
18
|
-
next if t2.name !=
|
|
25
|
+
next if t2.name != p_table.name
|
|
26
|
+
|
|
19
27
|
t2.rows.each do |i|
|
|
20
28
|
list2 << { id: count, weight: 0, data: i }
|
|
21
29
|
count += 1
|
|
22
30
|
end
|
|
23
31
|
end
|
|
24
32
|
end
|
|
25
|
-
|
|
33
|
+
[list1, list2]
|
|
26
34
|
end
|
|
35
|
+
# rubocop:enable Metrics/MethodLength
|
|
36
|
+
# rubocop:enable Metrics/AbcSize
|
|
27
37
|
|
|
28
38
|
def calculate_nearness_between_texts(text1, text2)
|
|
29
39
|
return 0.0 if text2.nil? || text2.empty?
|
|
@@ -34,6 +44,8 @@ module AI_calculate
|
|
|
34
44
|
(count * 100 / words.count)
|
|
35
45
|
end
|
|
36
46
|
|
|
47
|
+
# rubocop:disable Metrics/MethodLength
|
|
48
|
+
# rubocop:disable Metrics/AbcSize
|
|
37
49
|
def reorder_list_with_row(list, row)
|
|
38
50
|
# evaluate every row of the list2
|
|
39
51
|
list.each do |r|
|
|
@@ -52,4 +64,6 @@ module AI_calculate
|
|
|
52
64
|
list.sort! { |a, b| a[:weight] <=> b[:weight] }
|
|
53
65
|
list.reverse!
|
|
54
66
|
end
|
|
67
|
+
# rubocop:enable Metrics/MethodLength
|
|
68
|
+
# rubocop:enable Metrics/AbcSize
|
|
55
69
|
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: false
|
|
2
|
+
|
|
3
|
+
require_relative '../../lang/lang_factory'
|
|
4
|
+
require_relative '../../ai/question'
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# BaseCodeAI class
|
|
8
|
+
class BaseCodeAI
|
|
9
|
+
attr_reader :questions
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Create CodeAI object from Code data
|
|
13
|
+
# @param code (Code)
|
|
14
|
+
def initialize(code)
|
|
15
|
+
@code = code
|
|
16
|
+
@lines = code.lines
|
|
17
|
+
@num = 0
|
|
18
|
+
@questions = []
|
|
19
|
+
make_questions
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Return the name of code
|
|
24
|
+
# @return String
|
|
25
|
+
def name
|
|
26
|
+
File.basename(@code.filename)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def process?
|
|
30
|
+
@code.process?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def type
|
|
34
|
+
@code.type
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def filename
|
|
38
|
+
@code.filename
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def lines
|
|
42
|
+
@code.lines
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# Counter
|
|
47
|
+
# @return count
|
|
48
|
+
def num
|
|
49
|
+
@num += 1
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Clone array
|
|
54
|
+
# @param array (Array)
|
|
55
|
+
# @return Array
|
|
56
|
+
def clone_array(array)
|
|
57
|
+
out = []
|
|
58
|
+
array.each { |item| out << item.dup }
|
|
59
|
+
out
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# Convert an array of lines into one String
|
|
64
|
+
# @param lines (Array)
|
|
65
|
+
# @return String
|
|
66
|
+
# rubocop:disable Style/FormatString
|
|
67
|
+
def lines_to_s(lines)
|
|
68
|
+
out = ''
|
|
69
|
+
lines.each_with_index do |line, index|
|
|
70
|
+
out << "%2d: #{line}\n" % (index + 1)
|
|
71
|
+
end
|
|
72
|
+
out
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# Convert an array of lines into one HTML String
|
|
77
|
+
# @param lines (Array)
|
|
78
|
+
# @return String
|
|
79
|
+
def lines_to_html(lines)
|
|
80
|
+
out = ''
|
|
81
|
+
lines.each_with_index do |line, index|
|
|
82
|
+
out << "%2d: #{line}</br>" % (index + 1)
|
|
83
|
+
end
|
|
84
|
+
out
|
|
85
|
+
end
|
|
86
|
+
# rubocop:enable Style/FormatString
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# Make questions
|
|
90
|
+
def make_questions
|
|
91
|
+
list = find_make_methods
|
|
92
|
+
list.each { |m| @questions += send m }
|
|
93
|
+
@questions
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def find_make_methods
|
|
99
|
+
list = public_methods.sort
|
|
100
|
+
list.select! { |name| name.to_s.start_with? 'make_' }
|
|
101
|
+
list.delete(:make_questions)
|
|
102
|
+
list
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
|
|
2
|
+
require 'rainbow'
|
|
2
3
|
require_relative 'javascript_code_ai'
|
|
4
|
+
require_relative 'problem_code_ai'
|
|
3
5
|
require_relative 'python_code_ai'
|
|
4
6
|
require_relative 'ruby_code_ai'
|
|
5
7
|
require_relative 'sql_code_ai'
|
|
6
8
|
|
|
9
|
+
##
|
|
10
|
+
# CodeAI factory
|
|
7
11
|
module CodeAIFactory
|
|
12
|
+
##
|
|
13
|
+
# Return CodeAI associated to Code.type
|
|
14
|
+
# @param code (Code)
|
|
15
|
+
# @return CodeAI
|
|
8
16
|
def self.get(code)
|
|
9
17
|
type = code.type
|
|
10
18
|
case type
|
|
11
19
|
when :javascript
|
|
12
20
|
return JavascriptCodeAI.new(code)
|
|
21
|
+
when :problem
|
|
22
|
+
return ProblemCodeAI.new(code)
|
|
13
23
|
when :python
|
|
14
24
|
return PythonCodeAI.new(code)
|
|
15
25
|
when :ruby
|
|
@@ -19,7 +29,7 @@ module CodeAIFactory
|
|
|
19
29
|
when :vagrantfile
|
|
20
30
|
return RubyCodeAI.new(code)
|
|
21
31
|
else
|
|
22
|
-
puts "[ERROR] <#{type}> is not valid type"
|
|
32
|
+
puts Rainbow("[ERROR] <#{type}> is not valid type").red.bright
|
|
23
33
|
end
|
|
24
34
|
nil
|
|
25
35
|
end
|
|
@@ -4,12 +4,9 @@ require_relative '../../ai/question'
|
|
|
4
4
|
require_relative 'base_code_ai'
|
|
5
5
|
|
|
6
6
|
class JavascriptCodeAI < BaseCodeAI
|
|
7
|
-
def initialize(
|
|
8
|
-
@data_object = data_object
|
|
9
|
-
@lines = data_object.lines
|
|
7
|
+
def initialize(code)
|
|
10
8
|
@lang = LangFactory.instance.get('javascript')
|
|
11
|
-
|
|
12
|
-
@questions = []
|
|
9
|
+
super code
|
|
13
10
|
end
|
|
14
11
|
|
|
15
12
|
def make_comment_error
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
|
|
2
|
+
require_relative '../../lang/lang_factory'
|
|
3
|
+
require_relative '../../ai/question'
|
|
4
|
+
require_relative 'base_code_ai'
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Class for RubyCodeAI objects
|
|
8
|
+
class ProblemCodeAI < BaseCodeAI
|
|
9
|
+
def initialize(code)
|
|
10
|
+
@reduce = 1
|
|
11
|
+
@reduce = 4 if code.lines.size > 25
|
|
12
|
+
@lang = LangFactory.instance.get('es')
|
|
13
|
+
super code
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Make errors about comments
|
|
18
|
+
def make_comment_error
|
|
19
|
+
questions = []
|
|
20
|
+
error_lines = []
|
|
21
|
+
@lines.each_with_index do |line,index|
|
|
22
|
+
if line.strip.start_with?('#')
|
|
23
|
+
lines = clone_array @lines
|
|
24
|
+
lines[index].sub!('#','').strip!
|
|
25
|
+
|
|
26
|
+
q = Question.new(:short)
|
|
27
|
+
q.name = "#{name}-#{num}-uncomment"
|
|
28
|
+
q.text = @lang.text_for(:code1,lines_to_html(lines))
|
|
29
|
+
q.shorts << (index+1)
|
|
30
|
+
q.feedback = 'Comment symbol removed'
|
|
31
|
+
questions << q
|
|
32
|
+
elsif line.strip.size>0
|
|
33
|
+
lines = clone_array @lines
|
|
34
|
+
lines[index]='# ' + lines[index]
|
|
35
|
+
|
|
36
|
+
q = Question.new(:short)
|
|
37
|
+
q.name = "#{name}-#{num}-comment"
|
|
38
|
+
q.text = @lang.text_for(:code1,lines_to_html(lines))
|
|
39
|
+
q.shorts << (index+1)
|
|
40
|
+
q.feedback = 'Comment symbol added'
|
|
41
|
+
questions << q
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
questions.shuffle[0,@lines.size/@reduce]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Make questions without errors
|
|
49
|
+
def make_no_error_changes
|
|
50
|
+
questions = []
|
|
51
|
+
empty_lines = []
|
|
52
|
+
used_lines = []
|
|
53
|
+
@lines.each_with_index do |line,index|
|
|
54
|
+
if line.strip.size.zero?
|
|
55
|
+
empty_lines << index
|
|
56
|
+
else
|
|
57
|
+
used_lines << index
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
used_lines.each do |index|
|
|
62
|
+
lines = clone_array(@lines)
|
|
63
|
+
lines.insert(index, ' ' * (rand(4).to_i + 1))
|
|
64
|
+
if @lines.size < 4 || rand(2) == 0
|
|
65
|
+
q = Question.new(:short)
|
|
66
|
+
q.name = "#{name}-#{num}-codeok"
|
|
67
|
+
q.text = @lang.text_for(:code1,lines_to_html(lines))
|
|
68
|
+
q.shorts << '0'
|
|
69
|
+
q.feedback = 'Code is OK'
|
|
70
|
+
questions << q
|
|
71
|
+
else
|
|
72
|
+
q = Question.new(:choice)
|
|
73
|
+
q.name = "#{name}-#{num}-codeok"
|
|
74
|
+
q.text = @lang.text_for(:code2,lines_to_html(lines))
|
|
75
|
+
others = (1..@lines.size).to_a.shuffle!
|
|
76
|
+
q.good = '0'
|
|
77
|
+
q.bads << others[0].to_s
|
|
78
|
+
q.bads << others[1].to_s
|
|
79
|
+
q.bads << others[2].to_s
|
|
80
|
+
q.feedback = 'Code is OK'
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
questions.shuffle[0,@lines.size/@reduce]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
##
|
|
88
|
+
# Make questions with syntax errors
|
|
89
|
+
def make_syntax_error
|
|
90
|
+
questions = []
|
|
91
|
+
|
|
92
|
+
@lang.mistakes.each_pair do |key,values|
|
|
93
|
+
error_lines = []
|
|
94
|
+
@lines.each_with_index do |line,index|
|
|
95
|
+
error_lines << index if line.include?(key.to_s)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
v = values.split(',')
|
|
99
|
+
v.each do |value|
|
|
100
|
+
error_lines.each do |index|
|
|
101
|
+
lines = clone_array(@lines)
|
|
102
|
+
lines[index].sub!(key.to_s, value)
|
|
103
|
+
if @lines.size < 4 || rand(2) == 0
|
|
104
|
+
q = Question.new(:short)
|
|
105
|
+
q.name = "#{name}-#{num}-syntaxerror"
|
|
106
|
+
q.text = @lang.text_for(:code1,lines_to_html(lines))
|
|
107
|
+
q.shorts << (index+1)
|
|
108
|
+
q.feedback = "Syntax error: '#{value}' must be '#{key}'"
|
|
109
|
+
else
|
|
110
|
+
q = Question.new(:choice)
|
|
111
|
+
q.name = "#{name}-#{num}-syntaxerror"
|
|
112
|
+
q.text = @lang.text_for(:code2,lines_to_html(lines))
|
|
113
|
+
others = (1..@lines.size).to_a.shuffle!
|
|
114
|
+
others.delete(index+1)
|
|
115
|
+
q.good = (index + 1).to_s
|
|
116
|
+
q.bads << others[0].to_s
|
|
117
|
+
q.bads << others[1].to_s
|
|
118
|
+
q.bads << others[2].to_s
|
|
119
|
+
q.feedback = "Syntax error: '#{value}' must be '#{key}'"
|
|
120
|
+
end
|
|
121
|
+
questions << q
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
questions.shuffle[0,@lines.size/@reduce]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
##
|
|
129
|
+
# Make questions with variable errors
|
|
130
|
+
def make_variable_error
|
|
131
|
+
questions = []
|
|
132
|
+
error_lines = []
|
|
133
|
+
@lines.each_with_index do |line, index|
|
|
134
|
+
# Search Variable assignment
|
|
135
|
+
m = /\s*(\w*)\s*\=\w*/.match(line)
|
|
136
|
+
i = []
|
|
137
|
+
unless m.nil?
|
|
138
|
+
varname = (m.values_at 1)[0]
|
|
139
|
+
# Search used Variable
|
|
140
|
+
@lines.each_with_index do |line2, index2|
|
|
141
|
+
next if index >= index2
|
|
142
|
+
i << index2 if line2.include?(varname)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
next if i.size == 0
|
|
146
|
+
i.shuffle!
|
|
147
|
+
i.each do |k|
|
|
148
|
+
lines = clone_array @lines
|
|
149
|
+
temp = lines[index]
|
|
150
|
+
lines[index] = lines[k]
|
|
151
|
+
lines[k] = temp
|
|
152
|
+
|
|
153
|
+
if rand(2) == 0
|
|
154
|
+
q = Question.new(:short)
|
|
155
|
+
q.name = "#{name}-#{num}-variable"
|
|
156
|
+
q.text = @lang.text_for(:code1, lines_to_html(lines))
|
|
157
|
+
q.shorts << (index + 1)
|
|
158
|
+
q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
|
|
159
|
+
else
|
|
160
|
+
q = Question.new(:choice)
|
|
161
|
+
q.name = "#{name}-#{num}-variable"
|
|
162
|
+
q.text = @lang.text_for(:code2, lines_to_html(lines))
|
|
163
|
+
others = (1..@lines.size).to_a.shuffle!
|
|
164
|
+
others.delete(index+1)
|
|
165
|
+
q.good = (index + 1).to_s
|
|
166
|
+
q.bads << others[0].to_s
|
|
167
|
+
q.bads << others[1].to_s
|
|
168
|
+
q.bads << others[2].to_s
|
|
169
|
+
q.feedback = "Variable error! Swapped lines #{(index+1)} with #{(k+1)}"
|
|
170
|
+
end
|
|
171
|
+
questions << q
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
questions.shuffle[0,@lines.size/@reduce]
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -4,12 +4,9 @@ require_relative '../../ai/question'
|
|
|
4
4
|
require_relative 'base_code_ai'
|
|
5
5
|
|
|
6
6
|
class PythonCodeAI < BaseCodeAI
|
|
7
|
-
def initialize(
|
|
8
|
-
@data_object = data_object
|
|
9
|
-
@lines = data_object.lines
|
|
7
|
+
def initialize(code)
|
|
10
8
|
@lang = LangFactory.instance.get('python')
|
|
11
|
-
|
|
12
|
-
@questions = []
|
|
9
|
+
super code
|
|
13
10
|
end
|
|
14
11
|
|
|
15
12
|
def make_comment_error
|
|
@@ -3,17 +3,18 @@ require_relative '../../lang/lang_factory'
|
|
|
3
3
|
require_relative '../../ai/question'
|
|
4
4
|
require_relative 'base_code_ai'
|
|
5
5
|
|
|
6
|
+
##
|
|
7
|
+
# Class for RubyCodeAI objects
|
|
6
8
|
class RubyCodeAI < BaseCodeAI
|
|
7
|
-
def initialize(
|
|
8
|
-
@data_object = data_object
|
|
9
|
-
@lines = data_object.lines
|
|
10
|
-
@lang = LangFactory.instance.get('ruby')
|
|
11
|
-
@num = 0
|
|
12
|
-
@questions = []
|
|
9
|
+
def initialize(code)
|
|
13
10
|
@reduce = 1
|
|
14
|
-
@reduce = 4 if
|
|
11
|
+
@reduce = 4 if code.lines.size > 25
|
|
12
|
+
@lang = LangFactory.instance.get('ruby')
|
|
13
|
+
super code
|
|
15
14
|
end
|
|
16
15
|
|
|
16
|
+
##
|
|
17
|
+
# Make errors about comments
|
|
17
18
|
def make_comment_error
|
|
18
19
|
questions = []
|
|
19
20
|
error_lines = []
|
|
@@ -43,6 +44,8 @@ class RubyCodeAI < BaseCodeAI
|
|
|
43
44
|
questions.shuffle[0,@lines.size/@reduce]
|
|
44
45
|
end
|
|
45
46
|
|
|
47
|
+
##
|
|
48
|
+
# Make questions without errors
|
|
46
49
|
def make_no_error_changes
|
|
47
50
|
questions = []
|
|
48
51
|
empty_lines = []
|
|
@@ -81,6 +84,8 @@ class RubyCodeAI < BaseCodeAI
|
|
|
81
84
|
questions.shuffle[0,@lines.size/@reduce]
|
|
82
85
|
end
|
|
83
86
|
|
|
87
|
+
##
|
|
88
|
+
# Make questions with syntax errors
|
|
84
89
|
def make_syntax_error
|
|
85
90
|
questions = []
|
|
86
91
|
|
|
@@ -120,6 +125,8 @@ class RubyCodeAI < BaseCodeAI
|
|
|
120
125
|
questions.shuffle[0,@lines.size/@reduce]
|
|
121
126
|
end
|
|
122
127
|
|
|
128
|
+
##
|
|
129
|
+
# Make questions with variable errors
|
|
123
130
|
def make_variable_error
|
|
124
131
|
questions = []
|
|
125
132
|
error_lines = []
|
|
@@ -4,12 +4,9 @@ require_relative '../../ai/question'
|
|
|
4
4
|
require_relative 'base_code_ai'
|
|
5
5
|
|
|
6
6
|
class SQLCodeAI < BaseCodeAI
|
|
7
|
-
def initialize(
|
|
8
|
-
@data_object = data_object
|
|
9
|
-
@lines = data_object.lines
|
|
7
|
+
def initialize(code)
|
|
10
8
|
@lang = LangFactory.instance.get('sql')
|
|
11
|
-
|
|
12
|
-
@questions = []
|
|
9
|
+
super code
|
|
13
10
|
end
|
|
14
11
|
|
|
15
12
|
def make_comment_error
|
data/lib/asker/ai/concept_ai.rb
CHANGED
|
@@ -17,14 +17,21 @@ class ConceptAI
|
|
|
17
17
|
attr_reader :questions
|
|
18
18
|
attr_reader :excluded_questions
|
|
19
19
|
|
|
20
|
+
##
|
|
21
|
+
# Initialize ConcepAI
|
|
22
|
+
# @param concept (Concept)
|
|
23
|
+
# @param world (World)
|
|
20
24
|
def initialize(concept, world)
|
|
21
25
|
@concept = concept
|
|
22
26
|
@world = world
|
|
23
27
|
@questions = { d: [], b: [], f: [], i: [], s: [], t: [] }
|
|
24
28
|
@excluded_questions = { d: [], b: [], f: [], i: [], s: [], t: [] }
|
|
25
|
-
@num = 0 #
|
|
29
|
+
@num = 0 # Add a unique number to every question
|
|
30
|
+
make_questions
|
|
26
31
|
end
|
|
27
32
|
|
|
33
|
+
##
|
|
34
|
+
# Generates and return new "num" value
|
|
28
35
|
def num
|
|
29
36
|
@num += 1
|
|
30
37
|
@num.to_s
|
|
@@ -32,9 +39,12 @@ class ConceptAI
|
|
|
32
39
|
|
|
33
40
|
# If a method call is missing, then delegate to concept parent.
|
|
34
41
|
def method_missing(method, *args, &block)
|
|
42
|
+
raise "[DEBUG] ConceptAI.#{method}(#{args})"
|
|
35
43
|
@concept.send(method, *args, &block)
|
|
36
44
|
end
|
|
37
45
|
|
|
46
|
+
##
|
|
47
|
+
# Generates random image URL
|
|
38
48
|
def random_image_for(_conceptname)
|
|
39
49
|
return '' if rand <= Project.instance.get(:threshold)
|
|
40
50
|
|
|
@@ -44,6 +54,6 @@ class ConceptAI
|
|
|
44
54
|
return '' if values.nil?
|
|
45
55
|
|
|
46
56
|
values.shuffle!
|
|
47
|
-
"<img src=\"#{values[0]}\" alt
|
|
57
|
+
"<img src=\"#{values[0]}\" alt=\"image\"><br/>"
|
|
48
58
|
end
|
|
49
59
|
end
|