asker-tool 2.1.2 → 2.1.7

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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE → LICENSE.txt} +0 -0
  3. data/README.md +17 -18
  4. data/bin/asker +1 -0
  5. data/lib/asker.rb +43 -74
  6. data/lib/asker/ai/ai.rb +4 -0
  7. data/lib/asker/ai/code/base_code_ai.rb +104 -0
  8. data/lib/asker/{code/ai → ai/code}/code_ai_factory.rb +11 -1
  9. data/lib/asker/{code/ai → ai/code}/javascript_code_ai.rb +2 -5
  10. data/lib/asker/ai/code/problem_code_ai.rb +176 -0
  11. data/lib/asker/{code/ai → ai/code}/python_code_ai.rb +2 -5
  12. data/lib/asker/{code/ai → ai/code}/ruby_code_ai.rb +14 -7
  13. data/lib/asker/{code/ai → ai/code}/sql_code_ai.rb +2 -5
  14. data/lib/asker/ai/concept_ai.rb +1 -0
  15. data/lib/asker/ai/stages/stage_t.rb +76 -76
  16. data/lib/asker/application.rb +19 -3
  17. data/lib/asker/checker.rb +152 -53
  18. data/lib/asker/cli.rb +19 -22
  19. data/lib/asker/data/code.rb +73 -0
  20. data/lib/asker/data/column.rb +31 -21
  21. data/lib/asker/data/concept.rb +42 -45
  22. data/lib/asker/data/data_field.rb +14 -0
  23. data/lib/asker/data/row.rb +75 -52
  24. data/lib/asker/data/table.rb +89 -42
  25. data/lib/asker/data/world.rb +58 -32
  26. data/lib/asker/{exporter/code_screen_exporter.rb → displayer/code_displayer.rb} +6 -6
  27. data/lib/asker/displayer/concept_ai_displayer.rb +132 -0
  28. data/lib/asker/displayer/concept_displayer.rb +29 -0
  29. data/lib/asker/displayer/stats_displayer.rb +14 -0
  30. data/lib/asker/exporter/code_gift_exporter.rb +10 -11
  31. data/lib/asker/exporter/concept_ai_gift_exporter.rb +23 -11
  32. data/lib/asker/exporter/concept_ai_yaml_exporter.rb +9 -7
  33. data/lib/asker/exporter/concept_doc_exporter.rb +9 -15
  34. data/lib/asker/exporter/output_file_exporter.rb +18 -0
  35. data/lib/asker/files/config.ini +37 -0
  36. data/lib/asker/files/example-code.haml +0 -0
  37. data/lib/asker/files/example-concept.haml +29 -0
  38. data/lib/asker/files/language/du/templates.yaml +50 -0
  39. data/lib/asker/files/language/en/connectors.yaml +44 -0
  40. data/lib/asker/files/language/en/mistakes.yaml +37 -0
  41. data/lib/asker/files/language/en/templates.yaml +29 -0
  42. data/lib/asker/files/language/es/connectors.yaml +92 -0
  43. data/lib/asker/files/language/es/mistakes.yaml +82 -0
  44. data/lib/asker/files/language/es/templates.yaml +29 -0
  45. data/lib/asker/files/language/fr/connectors.yaml +92 -0
  46. data/lib/asker/files/language/fr/mistakes.yaml +82 -0
  47. data/lib/asker/files/language/fr/templates.yaml +29 -0
  48. data/lib/asker/files/language/javascript/connectors.yaml +11 -0
  49. data/lib/asker/files/language/javascript/mistakes.yaml +30 -0
  50. data/lib/asker/files/language/javascript/templates.yaml +3 -0
  51. data/lib/asker/files/language/math/connectors.yaml +2 -0
  52. data/lib/asker/files/language/math/mistakes.yaml +2 -0
  53. data/lib/asker/files/language/math/templates.yaml +1 -0
  54. data/lib/asker/files/language/python/connectors.yaml +11 -0
  55. data/lib/asker/files/language/python/mistakes.yaml +26 -0
  56. data/lib/asker/files/language/python/templates.yaml +3 -0
  57. data/lib/asker/files/language/ruby/connectors.yaml +11 -0
  58. data/lib/asker/files/language/ruby/mistakes.yaml +33 -0
  59. data/lib/asker/files/language/ruby/templates.yaml +3 -0
  60. data/lib/asker/files/language/sql/connectors.yaml +6 -0
  61. data/lib/asker/files/language/sql/mistakes.yaml +11 -0
  62. data/lib/asker/files/language/sql/templates.yaml +2 -0
  63. data/lib/asker/formatter/concept_string_formatter.rb +9 -8
  64. data/lib/asker/formatter/question_gift_formatter.rb +9 -1
  65. data/lib/asker/lang/lang.rb +18 -12
  66. data/lib/asker/lang/lang_factory.rb +26 -5
  67. data/lib/asker/lang/text_actions.rb +87 -69
  68. data/lib/asker/loader/code_loader.rb +3 -3
  69. data/lib/asker/loader/content_loader.rb +9 -5
  70. data/lib/asker/loader/file_loader.rb +2 -11
  71. data/lib/asker/loader/haml_loader.rb +15 -0
  72. data/lib/asker/loader/image_url_loader.rb +5 -8
  73. data/lib/asker/loader/input_loader.rb +23 -7
  74. data/lib/asker/loader/project_loader.rb +32 -29
  75. data/lib/asker/logger.rb +3 -4
  76. data/lib/asker/project.rb +28 -52
  77. data/lib/asker/skeleton.rb +73 -0
  78. metadata +62 -73
  79. data/docs/changelog/v2.1.md +0 -99
  80. data/docs/commands.md +0 -15
  81. data/docs/contributions.md +0 -18
  82. data/docs/history.md +0 -40
  83. data/docs/idea.md +0 -44
  84. data/docs/inputs/README.md +0 -39
  85. data/docs/inputs/code.md +0 -69
  86. data/docs/inputs/concepts.md +0 -142
  87. data/docs/inputs/jedi.md +0 -68
  88. data/docs/inputs/tables.md +0 -112
  89. data/docs/inputs/templates.md +0 -87
  90. data/docs/install/README.md +0 -38
  91. data/docs/install/manual.md +0 -26
  92. data/docs/install/scripts.md +0 -26
  93. data/docs/revise/asker-file.md +0 -41
  94. data/docs/revise/buenas-practicas/01-convocatoria.md +0 -30
  95. data/docs/revise/buenas-practicas/02-formulario.md +0 -35
  96. data/docs/revise/buenas-practicas/03-descripcion.md +0 -63
  97. data/docs/revise/buenas-practicas/04-resultados.md +0 -17
  98. data/docs/revise/buenas-practicas/05-reproducir.md +0 -10
  99. data/docs/revise/ejemplos/01/README.md +0 -27
  100. data/docs/revise/ejemplos/02/README.md +0 -31
  101. data/docs/revise/ejemplos/03/README.md +0 -31
  102. data/docs/revise/ejemplos/04/README.md +0 -37
  103. data/docs/revise/ejemplos/05/README.md +0 -25
  104. data/docs/revise/ejemplos/06/README.md +0 -43
  105. data/docs/revise/ejemplos/README.md +0 -11
  106. data/docs/revise/projects.md +0 -74
  107. data/lib/asker/code/ai/base_code_ai.rb +0 -48
  108. data/lib/asker/code/code.rb +0 -53
  109. data/lib/asker/exporter/concept_ai_screen_exporter.rb +0 -115
  110. data/lib/asker/exporter/concept_screen_exporter.rb +0 -25
  111. data/lib/asker/exporter/main.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db562740b610fc29b5dd47354892919aa3041bc383f8ff6c818421f7a6ec5654
4
- data.tar.gz: 9eab6c83ed23bbceb48ff54c6a1e29bfae0f2b1f0fe4ecf52a9b6d27f1d0df30
3
+ metadata.gz: 180880dc684b6b39dabf66bf31366cee9e8b9793af6e92d256948edf36f5fcc7
4
+ data.tar.gz: 9c6cd45c7b3ec9b9dbde3d720092a8eabcbc98f3dd4056a413247cdd0d7b3a2e
5
5
  SHA512:
6
- metadata.gz: a9ef725d0968201216c953d237268bcbdbd96be1ffcb4888a9b4ab3a93150e69d4b97c37ec8bef16208efae484650ad5aad2acb74185ce2b913092e3eb1f2277
7
- data.tar.gz: 030dfc6afaece6e49b2f70401cadc7a2aba7bbdde2f2fc4cfa8e161128f541e1d7ba239ea312aa19c59c1e6ce9fb74ec355638bc0cfd430749740a0a0e7f476b
6
+ metadata.gz: 1238e0b8c18a6a37f0731479d39039559c1f2adb7b3c8372c1965f81bb9e946ed37637e7e420d6e188a0811d9da9f652eda53b6c8dd67d4d7f6a79bebf7bb2b7
7
+ data.tar.gz: fbefae58aa69fd054a900945867c88082548042d7306227fedb1f553b48773e4fb0354913ff5bfa029c206679b7d38f4562212798dd7814de98f319d0ae71d63
File without changes
data/README.md CHANGED
@@ -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
- Steps:
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
- To execute ASKER, we use `asker` command, with a path to an input file as argument. For example, to run our `jedi.haml` input file example, we do:
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
- * The program generates your output files into the `output` directory by default.
33
- * In this example, we use a demo input definition file `docs/examples/starwars/jedi.haml`, that contains conceptual entities about _"Jedi's"_ context.
34
- * [Example input files](https://github.com/dvarrui/asker/blob/devel/docs/examples).
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
- * [Commands](https://github.com/dvarrui/asker/blob/devel/docs/commands.md)
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
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/ruby
2
2
  require 'asker/cli'
3
+
3
4
  # Start Asker command line interface
4
5
  CLI.start(ARGV)
@@ -2,62 +2,29 @@
2
2
 
3
3
  require 'rainbow'
4
4
 
5
- require_relative 'asker/project'
6
- require_relative 'asker/data/concept'
7
- require_relative 'asker/data/world'
8
- require_relative 'asker/ai/concept_ai'
9
- require_relative 'asker/formatter/concept_string_formatter'
10
- require_relative 'asker/exporter/main'
5
+ require_relative 'asker/displayer/concept_displayer'
6
+ require_relative 'asker/displayer/stats_displayer'
7
+ require_relative 'asker/exporter/output_file_exporter'
11
8
  require_relative 'asker/loader/project_loader'
12
9
  require_relative 'asker/loader/input_loader'
13
10
  require_relative 'asker/checker'
11
+ require_relative 'asker/logger'
12
+ require_relative 'asker/skeleton'
14
13
 
15
- # This class does all the job
16
- # * start
17
- # * load_input_data
18
- # * create_output_files, show_create_output_files
19
- # * create_questions
20
- # * show_final_results
14
+ ##
15
+ # Asker main class
21
16
  class Asker
22
- # Initialize atributes
23
- def initialize
24
- @concepts_ai = []
25
- @concepts = []
26
- @codes = []
27
- end
28
-
29
17
  ##
30
- # Start working
31
- # @param args (Hash)
32
- def start(args = {})
33
- load_input_data(args)
34
- create_output_files
35
- show_final_results
18
+ # Create asker input demo files
19
+ # @param dirpath (String)
20
+ def self.create_input(dirpath)
21
+ Skeleton.create_input(dirpath)
36
22
  end
37
23
 
38
24
  ##
39
- # Load input data
40
- # @param args (Hash)
41
- def load_input_data(args)
42
- ProjectLoader.load(args)
43
- Project.instance.open
44
- data = InputLoader.load(Project.instance.get(:inputdirs).split(','))
45
- @concepts = data[:concepts]
46
- @codes = data[:codes]
47
- Project.instance.verbose "\n[INFO] Loading data from Internet"
48
- @world = World.new(@concepts)
49
- ConceptScreenExporter.export_all(@concepts)
50
- end
51
-
52
- ##
53
- # Create output files
54
- # * Gift
55
- # * YAML
56
- # * TXT Doc
57
- def create_output_files
58
- show_create_output_files
59
- create_questions
60
- ConceptDocExporter.new(@concepts).export
25
+ # Create asker configuration files
26
+ def self.create_configuration
27
+ Skeleton.create_configuration
61
28
  end
62
29
 
63
30
  ##
@@ -67,37 +34,39 @@ class Asker
67
34
  Checker.check(filepath)
68
35
  end
69
36
 
70
- private
71
-
72
- def show_create_output_files
73
- p = Project.instance
74
- p.verbose "\n[INFO] Creating output files"
75
- p.verbose " ├── Gift questions file => #{Rainbow(p.outputpath).bright}"
76
- p.verbose " ├── YAML questions file => #{Rainbow(p.yamlpath).bright}"
77
- p.verbose " └── Lesson file => #{Rainbow(p.lessonpath).bright}"
37
+ ##
38
+ # Start working
39
+ # @param filepath (String) HAML or XML filepath
40
+ def self.start(filepath)
41
+ project, data = load_input(filepath)
42
+ ConceptDisplayer.show(data[:concepts])
43
+ create_output(project, data)
78
44
  end
79
45
 
80
46
  ##
81
- # Create questions for every "concept"
82
- # Export output to:
83
- # * GIFT format file
84
- # * YAML format file
85
- # Create questions for every "code"
86
- # Export output to GIFT format file
87
- def create_questions
88
- @concepts.each do |concept|
89
- concept_ai = ConceptAI.new(concept, @world)
90
- concept_ai.make_questions
91
- @concepts_ai << concept_ai
92
- end
93
- ConceptAIGiftExporter.export_all(@concepts_ai)
94
- ConceptAIYAMLExporter.export_all(@concepts_ai)
95
- CodeGiftExporter.export_all(@codes) # UNDER DEVELOPMENT
47
+ # Load input data
48
+ # @param args (Hash)
49
+ private_class_method def self.load_input(args)
50
+ project = ProjectLoader.load(args)
51
+ project.open # Open output files
52
+ data = InputLoader.load(project.get(:inputdirs).split(','))
53
+ [project, data]
96
54
  end
97
55
 
98
- def show_final_results
99
- ConceptAIScreenExporter.export_all(@concepts_ai)
100
- CodeScreenExporter.export_all(@codes)
101
- Project.instance.close
56
+ ##
57
+ # Create output files: Gift, YAML, TXT Doc
58
+ # rubocop:disable Metrics/AbcSize
59
+ private_class_method def self.create_output(project, data)
60
+ Logger.verbose "\n[INFO] Creating output files"
61
+ Logger.verbose ' ├── Gift questions file => ' +
62
+ Rainbow(project.get(:outputpath)).bright
63
+ Logger.verbose ' ├── YAML questions file => ' +
64
+ Rainbow(project.get(:yamlpath)).bright
65
+ Logger.verbose ' └── Lesson file => ' +
66
+ Rainbow(project.get(:lessonpath)).bright
67
+ OutputFileExporter.export(data, project)
68
+ StatsDisplayer.show(data)
69
+ project.close # Logger use Project.get(:logfile) until the end
102
70
  end
71
+ # rubocop:enable Metrics/AbcSize
103
72
  end
@@ -46,6 +46,8 @@ module AI
46
46
  end
47
47
  end
48
48
 
49
+ # rubocop:disable Metrics/AbcSize
50
+ # rubocop:disable Metrics/MethodLength
49
51
  def exclude_questions
50
52
  param = Application.instance.config['questions']['exclude']
51
53
  return if param.nil?
@@ -61,6 +63,8 @@ module AI
61
63
  @questions = input
62
64
  @excluded_questions = output
63
65
  end
66
+ # rubocop:enable Metrics/AbcSize
67
+ # rubocop:enable Metrics/MethodLength
64
68
 
65
69
  def string_has_this_tags?(input, tags)
66
70
  flag = false
@@ -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(data_object)
8
- @data_object = data_object
9
- @lines = data_object.lines
7
+ def initialize(code)
10
8
  @lang = LangFactory.instance.get('javascript')
11
- @num = 0
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