battleroom 0.0.79 → 0.0.80

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/battleroom/battleroom_machinery.rb +63 -19
  3. data/lib/battleroom/config/boot.rb +18 -0
  4. data/lib/battleroom/config/pry_config.rb +10 -4
  5. data/lib/battleroom/data/array_questions.rb +5 -2
  6. data/lib/battleroom/data/hash_questions.rb +9 -0
  7. data/lib/battleroom/data/method_questions.rb +53 -1
  8. data/lib/battleroom/data/scratch.rb +0 -0
  9. data/lib/battleroom/data/variable_assignment_questions.rb +4 -3
  10. data/lib/battleroom/data_generation_machinery.rb +17 -9
  11. data/lib/battleroom/helpers/array_formatter.rb +3 -0
  12. data/lib/battleroom/helpers/hash_formatter.rb +3 -0
  13. data/lib/battleroom/models/array_access_question.rb +2 -0
  14. data/lib/battleroom/models/array_assignment_question.rb +17 -12
  15. data/lib/battleroom/models/data_structure_access_question.rb +4 -6
  16. data/lib/battleroom/models/data_structure_assignment_question.rb +3 -3
  17. data/lib/battleroom/models/follow_up_question.rb +12 -0
  18. data/lib/battleroom/models/hash_access_question.rb +2 -0
  19. data/lib/battleroom/models/hash_assignment_question.rb +4 -2
  20. data/lib/battleroom/models/method_definition_question.rb +12 -16
  21. data/lib/battleroom/models/method_invocation_question.rb +42 -25
  22. data/lib/battleroom/models/nested_data_structure_access_question.rb +2 -0
  23. data/lib/battleroom/models/question.rb +6 -6
  24. data/lib/battleroom/models/variable_assignment_question.rb +75 -0
  25. data/lib/battleroom/models/variable_reassignment_question.rb +29 -0
  26. data/lib/battleroom/models/variable_reference_question.rb +93 -0
  27. data/lib/battleroom.rb +6 -42
  28. metadata +30 -9
  29. data/lib/battleroom/models/variable_question.rb +0 -63
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 340c1d7b9d05a1f38b513a5d48f3fd0ab96b1547
4
- data.tar.gz: ab44f38b9d800263c0b4a9c72390535aa9de6fee
3
+ metadata.gz: 4121f41892684e9effe768d41855f85ef301794b
4
+ data.tar.gz: 0c63c05faee0c39886da9fe0e9bf41e9a558dcb7
5
5
  SHA512:
6
- metadata.gz: 8b1547328ed465de041958c01675f2a32e64862c8edb38213c8107ffd33ca1e49801ecad951e0ee1311d09c52d8944493577b1dfddd4c0e123b5ce8004bbc329
7
- data.tar.gz: 84eb2f9983d8fd8706a1005c58bbe2517b6b44156c2d7ff1f409e670f8ad572452b86c9b4f63d6ddcf25ff2c9571af17a70a66c7d6cd482451f3b0d4bd19dd76
6
+ metadata.gz: 9ea92effce91cb05b7273e2e3c34467602d4dc1c91e355a0855497c69d69eda0f612b3f5a34da3aeb7f237f1058c8611029923071d100f00c5d2020aa311453a
7
+ data.tar.gz: fff9c79d3257ee39e67efabeb1c26dcf8479bd6c1150482c1240609eb6b82febf38037d06321295801a0936f0034957e88d58b9bc28a71dab4b4c094db10ae65
@@ -5,6 +5,9 @@ module BattleroomMachinery
5
5
  'Beautiful!',
6
6
  'Lovely!',
7
7
  'Splendid!',
8
+ 'Awesome.',
9
+ 'Stand up job, my friend.',
10
+ 'Nailed it.',
8
11
  'Nice job! Keep it rolling!',
9
12
  'Capital work, battlestar!',
10
13
  'Exemplary work!',
@@ -23,21 +26,21 @@ module BattleroomMachinery
23
26
  end
24
27
 
25
28
  def print_menu_options
26
- puts ' What would you like to work on?'.blue
27
- puts '1. Variable assignment'
28
- puts '2. Accessing values in arrays and hashes'
29
- puts '3. Adding values to arrays and hashes'
30
- puts '4. Accessing values from within nested data structures'
31
- puts '5. Defining methods'
32
- puts "Q. Quit\r\n\n"
29
+ battleprint ' What would you like to work on?'.blue
30
+ battleprint '1. Working with Variables'
31
+ battleprint '2. Accessing Values in Arrays and Hashes'
32
+ battleprint '3. Adding Values to Arrays and Hashes'
33
+ battleprint '4. Working with Methods'
34
+ battleprint "Q. Quit\r\n\n"
33
35
  end
34
36
 
35
37
  def random_congratulation
36
38
  CONGRATULATIONS.sample
37
39
  end
38
40
 
41
+
39
42
  def print_congratulation
40
- puts "#{random_congratulation}\n".green
43
+ battleprint "\n#{random_congratulation}\n".green
41
44
  end
42
45
 
43
46
  def rotate_array(array)
@@ -47,22 +50,62 @@ module BattleroomMachinery
47
50
 
48
51
  def print_colorized_error_prompt(error)
49
52
  method_or_variable = (error.class == NoMethodError) ? "method" : "variable"
50
- puts "\nYou're referencing a #{method_or_variable} that doesn't exist, probably as the result of a mispelling. This results in a common error that says: \n".red
51
- puts "\tundefined local variable or method \'WHATEVER_YOU_MISTYPED\'\n".green
52
- puts "Get used to it and try again.\n".red
53
+ battleprint "\nYou're referencing a #{method_or_variable} that doesn't exist, probably as the result of a mispelling. This results in a common Ruby error that reads: \n".red
54
+ battleprint "\tundefined local variable or method \'WHATEVER_YOU_MISTYPED\'\n".green
55
+ battleprint "Get used to it and try again.\n".red
56
+ end
57
+
58
+ def indent_all_lines_for_stdout(string_to_indent)
59
+ string_to_indent.gsub(/^.*/) { |match| "\t" + match }
60
+ end
61
+
62
+ def dynamic_word_wrap(string)
63
+ string.wrap(150)
53
64
  end
54
65
 
55
- def print_unexpected_end_of_input_explanation
56
- puts "\nNope! You just triggered a common Ruby error that reads:\n".red
57
- puts "\tsyntax error, unexpected end-of-input\n".green
58
- puts "Basically, you told Ruby you were going to assign a value to a variable, but you neglected to provide a valid value. Try again.\n".red
66
+ def battleprint(string)
67
+ puts dynamic_word_wrap(string)
68
+ end
69
+
70
+ def isolate_variable_name_from_name_error(error)
71
+ /`(.+)'/i.match(error.message)
72
+ end
73
+
74
+ def window_width
75
+ begin
76
+ width_string = `tput cols`
77
+ # for cases where systems don't respond to the tput command
78
+ rescue StandardError => e
79
+ width_string = "80"
80
+ end
81
+ width_string.strip.to_i
82
+ end
83
+
84
+ def print_unexpected_end_of_input_explanation(error)
85
+ battleprint "\nNope! You just triggered a common Ruby error that reads:\n".red
86
+ battleprint "\tsyntax error, unexpected end-of-input\n".green
87
+ if error.message.include?(']')
88
+ battleprint "Basically, you used an opening square bracket '[', but didn't pair it with a closing square bracket. Try again.\n".red
89
+ else
90
+ battleprint "Basically, you told Ruby you were going to assign a value to a variable, but you neglected to provide a valid value. Try again.\n".red
91
+ end
92
+ end
93
+
94
+ def determine_variable_follow_up_question(eval_scope, question)
95
+ if question.variable_value == true || question.variable_value == false
96
+ VariableReassignmentQuestion.new(eval_scope, question)
97
+ elsif question.variable_value.class == Symbol || question.variable_value.class == String
98
+ nil
99
+ else
100
+ VariableReferenceQuestion.new(eval_scope, question)
101
+ end
59
102
  end
60
103
 
61
104
  def print_colorized_type_error_prompt(error)
62
- puts "\nNope! You just triggered a common Ruby error that reads:\n".red
63
- puts "\tin '[]', #{error.message}".green
105
+ battleprint "\nNope! You just triggered a common Ruby error that reads:\n".red
106
+ battleprint "\tin '[]', #{error.message}".green
64
107
  error.message.match /conversion\sof\s(.+)\sinto\sInteger/i
65
- puts "\nBasically, you put a #{$1} between square brackets, whereas Ruby ".red +
108
+ battleprint "\nBasically, you put a #{$1} between square brackets, whereas Ruby ".red +
66
109
  "was expecting an index value, i.e. an integer. This commonly arises ".red +
67
110
  "when programmers think they're dealing with a hash, when in fact ".red +
68
111
  "they're dealing with an array. Try again.\n".red
@@ -84,7 +127,7 @@ module BattleroomMachinery
84
127
 
85
128
  def naughty_input?(user_input)
86
129
  if user_input.match(/(require|`|binding)/)
87
- puts "No way no how! Try again.\n".red
130
+ battleprint "No way no how! Try again.\n".red
88
131
  true
89
132
  else
90
133
  false
@@ -95,4 +138,5 @@ module BattleroomMachinery
95
138
  return 'Boolean' if klass.to_s.match /(TrueClass|FalseClass)/
96
139
  klass.to_s
97
140
  end
141
+
98
142
  end
@@ -0,0 +1,18 @@
1
+ require 'readline'
2
+ require 'faker'
3
+ require 'awesome_print'
4
+ require 'pry'
5
+ require 'colorize'
6
+ require 'coderay'
7
+ require 'word_wrap'
8
+
9
+ path = File.expand_path("../models/*.rb", File.dirname(__FILE__))
10
+ Dir[path].each { |file| require file }
11
+
12
+ require_relative './pry_config'
13
+
14
+ require_relative '../battleroom_machinery'
15
+
16
+ include BattleroomMachinery
17
+
18
+
@@ -4,21 +4,27 @@ I18n.config.enforce_available_locales = false
4
4
  def configure_pry
5
5
  Pry.config.default_window_size = 0
6
6
  Pry.config.quiet = true
7
- Pry.prompt = [proc { "> ".blue }, proc { "* ".blue }]
7
+ Pry.prompt = [
8
+ proc { "> ".blue },
9
+ proc { "* ".blue }
10
+ ]
8
11
  Pry.config.memory_size = 10
9
12
 
10
13
  Pry::Commands.delete("exit")
11
14
 
12
- # Pry::Hooks.new.clear_all
13
-
14
15
  Pry.config.hooks.add_hook :before_eval, :self_terminate do |last_input, pry_instance|
15
16
  $input = last_input
16
- puts ''
17
17
  unless last_input.include?("revert_pry_to_defaults")
18
18
  pry_instance.run_command("continue")
19
19
  end
20
20
  end
21
+ end
21
22
 
23
+ def restore_pry_defaults
24
+ Pry.config.default_window_size = 15
25
+ Pry.config.quiet = false
26
+ Pry.prompt = Pry::DEFAULT_PROMPT
27
+ Pry.config.hooks.delete_hook :before_eval, :self_terminate
22
28
  end
23
29
 
24
30
  configure_pry
@@ -36,6 +36,7 @@ ARRAY_QUESTIONS = [
36
36
  'sci_fi_titles',
37
37
  'books',
38
38
  'paperback_titles',
39
+ 'fav_books',
39
40
  ].shuffle,
40
41
  },
41
42
  {
@@ -50,7 +51,8 @@ ARRAY_QUESTIONS = [
50
51
  'lovers',
51
52
  'admirers',
52
53
  'haters',
53
- 'stalker_names'
54
+ 'stalker_names',
55
+ 'teammates'
54
56
  ].shuffle,
55
57
  },
56
58
  {
@@ -62,7 +64,8 @@ ARRAY_QUESTIONS = [
62
64
  'fav_ages',
63
65
  'jersey_numbers',
64
66
  'lucky_numbers',
65
- 'unlucky_numbers'
67
+ 'unlucky_numbers',
68
+ 'totals',
66
69
  ].shuffle,
67
70
  },
68
71
  {
@@ -2,6 +2,13 @@ require_relative '../data_generation_machinery'
2
2
  include DataGenerationMachinery
3
3
  require 'active_support/inflector'
4
4
 
5
+ #=======================================
6
+ # Contribution Guidelines
7
+ #=======================================
8
+
9
+ # 1. All hashes must have *at least* 5 key values pairs.
10
+ # 2. All questions must have a possible variables names key, be hashes with *at least* 5 key values pairs
11
+
5
12
  HASH_QUESTIONS = [
6
13
  {
7
14
  data_structure: {
@@ -35,6 +42,8 @@ HASH_QUESTIONS = [
35
42
  stars: ['Nicholas Cage', 'Meryl Streep'],
36
43
  rt_rating: 98.0,
37
44
  released: 2002,
45
+ director: 'Spike Jonze',
46
+ based_on: 'The Orchid Thief',
38
47
  screenwriters: ['Charlie Kaufman', 'Donald Kaufman'],
39
48
  },
40
49
  possible_variable_names: ['adaptation'],
@@ -3,6 +3,9 @@ area_arg_two = rand(1..9)
3
3
  volume_arg_one = rand(1..9)
4
4
  volume_arg_two = rand(1..9)
5
5
  volume_arg_three = rand(1..9)
6
+ double_arg = rand(2..50)
7
+ square_arg = rand(2..12)
8
+ cube_arg = rand(2..5)
6
9
 
7
10
  METHOD_QUESTONS = [
8
11
  {
@@ -26,4 +29,53 @@ METHOD_QUESTONS = [
26
29
  eval_string: "sum(#{area_arg_one}, #{area_arg_two})",
27
30
  eval_answer: area_arg_one + area_arg_two
28
31
  },
29
- ]
32
+ {
33
+ method_name: "double",
34
+ arg_count: 1,
35
+ spec: "returns its lone argument multiplied by 2",
36
+ eval_string: "double(#{double_arg})",
37
+ eval_answer: double_arg * 2
38
+ },
39
+ {
40
+ method_name: "triple",
41
+ arg_count: 1,
42
+ spec: "returns its lone argument multiplied by 3",
43
+ eval_string: "triple(#{area_arg_two})",
44
+ eval_answer: area_arg_two * 3
45
+ },
46
+ {
47
+ method_name: "quadruple",
48
+ arg_count: 1,
49
+ spec: "returns its lone argument multiplied by 4",
50
+ eval_string: "quadruple(#{area_arg_one})",
51
+ eval_answer: area_arg_one * 4
52
+ },
53
+ {
54
+ method_name: "square",
55
+ arg_count: 1,
56
+ spec: "returns its lone argument to the 2nd power",
57
+ eval_string: "square(#{square_arg})",
58
+ eval_answer: square_arg ** 2
59
+ },
60
+ {
61
+ method_name: "cube",
62
+ arg_count: 1,
63
+ spec: "returns its lone argument to the 3rd power",
64
+ eval_string: "cube(#{cube_arg})",
65
+ eval_answer: cube_arg ** 3
66
+ },
67
+ {
68
+ method_name: "kelvin_to_celcius",
69
+ arg_count: 1,
70
+ spec: "returns its lone argument minus the Float value \e[0;33;49m273.15\e[0m",
71
+ eval_string: "kelvin_to_celcius(#{cube_arg})",
72
+ eval_answer: cube_arg - 273.15
73
+ },
74
+ {
75
+ method_name: "celcius_to_kelvin",
76
+ arg_count: 1,
77
+ spec: "returns its lone argument added to the Float value \e[0;33;49m273.15\e[0m",
78
+ eval_string: "celcius_to_kelvin(#{square_arg})",
79
+ eval_answer: square_arg + 273.15
80
+ },
81
+ ].shuffle
File without changes
@@ -14,12 +14,15 @@ VARIABLE_QUESTIONS = [
14
14
  # :album_count,
15
15
  # :year_of_birth
16
16
  # ]
17
- # }
17
+ # },
18
18
  {
19
19
  possible_variable_names: [
20
+ 'sign_in_count',
21
+ 'unread_emails_count',
20
22
  'fish_count',
21
23
  'cat_count',
22
24
  'user_count',
25
+ 'admin_count',
23
26
  'number_of_dogs',
24
27
  'num_steaks',
25
28
  'fav_number',
@@ -95,7 +98,6 @@ VARIABLE_QUESTIONS = [
95
98
  possible_variable_names: [
96
99
  'pilot_name',
97
100
  'point_guard',
98
- 'gardener',
99
101
  'cook',
100
102
  'chef',
101
103
  'boss',
@@ -117,7 +119,6 @@ VARIABLE_QUESTIONS = [
117
119
  'team_captain',
118
120
  'instructor_name',
119
121
  'friend_for_life',
120
- 'thief',
121
122
  'dancer',
122
123
  'lead_singer',
123
124
  'drummer',
@@ -31,7 +31,7 @@ module DataGenerationMachinery
31
31
  def gen_user
32
32
  password_or_pw = [:password, :pw].sample
33
33
  admin_or_is_admin = [:admin, :is_admin].sample
34
- phone_of_phone_num = [:phone, :phone_num, :phone_number].sample
34
+ phone_or_phone_num = [:phone, :phone_num, :phone_number].sample
35
35
  occupation_or_job_title = [:occupation, :job_title].sample
36
36
  zip_or_zip_code = [:zip, :zip_code].sample
37
37
  first_name = Faker::Name::first_name
@@ -43,14 +43,14 @@ module DataGenerationMachinery
43
43
  password_or_pw => gen_password,
44
44
  email: Faker::Internet.free_email(first_name),
45
45
  admin_or_is_admin => [true, false].sample,
46
- phone_of_phone_num => gen_phone_number,
46
+ phone_or_phone_num => gen_phone_number,
47
47
  accepts_marketing: [true, false].sample,
48
48
  accepts_promotional_emails: [true, false].sample,
49
49
  occupation_or_job_title => Faker::Name.title,
50
50
  zip_or_zip_code => Faker::Address.zip
51
51
  }
52
52
 
53
- data = {
53
+ {
54
54
  data_structure: user,
55
55
  possible_variable_names: [
56
56
  snake_case(first_name),
@@ -65,7 +65,15 @@ module DataGenerationMachinery
65
65
  def gen_business_email_address(business_name)
66
66
  possible_intro_words = ['info', 'hello', 'greetings', 'contact', 'team']
67
67
  intro_word = possible_intro_words.sample
68
- biz_email_address = "#{intro_word}@#{business_name.parameterize}.com"
68
+ "#{intro_word}@#{business_name.parameterize}.com"
69
+ end
70
+
71
+ def gen_business_name_under_16_characters
72
+ name = Faker::Company.name
73
+ while name.length > 15
74
+ name = Faker::Company.name
75
+ end
76
+ name
69
77
  end
70
78
 
71
79
  def gen_business
@@ -73,12 +81,12 @@ module DataGenerationMachinery
73
81
  email_key = [:email, :public_email, :info_email, :contact_email].sample
74
82
  web_key = [:url, :website, :homepage_url].sample
75
83
  address_key = [:street_address, :address].sample
76
- established_key = [:established, :inception_year].sample
77
- name = Faker::Company.name
84
+ established_key = [:established].sample
85
+ name = gen_business_name_under_16_characters
78
86
  email_address = gen_business_email_address(name)
79
87
  business = {
80
88
  name_or_business_name => name,
81
- public_email: email_address,
89
+ email_key => email_address,
82
90
  web_key => Faker::Internet.url("#{name.parameterize}.com", ''),
83
91
  phone_num: gen_phone_number,
84
92
  address_key => Faker::Address.street_address,
@@ -86,7 +94,7 @@ module DataGenerationMachinery
86
94
  state: Faker::Address.state_abbr,
87
95
  established_key => rand(1901..2014),
88
96
  }
89
- data = {
97
+ {
90
98
  data_structure: business,
91
99
  possible_variable_names: [
92
100
  snake_case(name),
@@ -112,7 +120,7 @@ module DataGenerationMachinery
112
120
  latitude[which_key_to_use] => Faker::Address.latitude.slice(0, rand(7..9)).to_f,
113
121
  longitude[which_key_to_use] => Faker::Address.longitude.slice(0, rand(7..9)).to_f
114
122
  }
115
- data = {
123
+ {
116
124
  data_structure: location,
117
125
  possible_variable_names: [
118
126
  snake_case(city),
@@ -0,0 +1,3 @@
1
+ module ArrayFormatter
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ module HashFormatter
2
+
3
+ end
@@ -8,6 +8,8 @@ class ArrayAccessQuestion < DataStructureAccessQuestion
8
8
  def initialize(scope)
9
9
  super(scope)
10
10
  format_array_for_access
11
+ print_data_structure_access_prompt
12
+ evaluate_data_structure_access_input
11
13
  end
12
14
 
13
15
  def format_array_for_access
@@ -8,6 +8,8 @@ class ArrayAssignmentQuestion < DataStructureAssignmentQuestion
8
8
  def initialize(scope)
9
9
  super(scope)
10
10
  format_array_for_assignment
11
+ print_data_structure_assignment_prompt
12
+ evaluate_data_structure_assignment_input
11
13
  end
12
14
 
13
15
  def format_array_for_assignment
@@ -30,9 +32,9 @@ class ArrayAssignmentQuestion < DataStructureAssignmentQuestion
30
32
  end
31
33
 
32
34
  def print_replace_array_value_prompt
33
- puts "Given the data structure below, replace the #{replacement_value_class_formatted} value ".blue +
34
- value_to_replace_formatted.yellow + " with the #{assignment_value_class} value ".blue +
35
- formatted_assignment_value.yellow + ".\n\n"
35
+ battleprint "Given the data structure below, replace the #{replacement_value_class_formatted} value ".blue +
36
+ value_to_replace_formatted.yellow + " with the #{assignment_value_class} value ".blue +
37
+ formatted_assignment_value.yellow + ".\n\n"
36
38
  end
37
39
 
38
40
  def print_data_structure_assignment_prompt
@@ -41,7 +43,7 @@ class ArrayAssignmentQuestion < DataStructureAssignmentQuestion
41
43
  self.replacement_value_class_formatted = format_class_for_output(value_to_replace.class)
42
44
  print_replace_array_value_prompt
43
45
  else
44
- puts "Use an array method to add the #{assignment_value_class} value ".blue + "#{formatted_assignment_value}".yellow + " to the ".blue + "end".blue.underline + " of the Array below.\n".blue
46
+ battleprint "Use an array method to add the #{assignment_value_class} value ".blue + "#{formatted_assignment_value}".yellow + " to the ".blue + "end".blue.underline + " of the Array below.\n".blue
45
47
  end
46
48
  print_data_structure
47
49
  end
@@ -51,23 +53,26 @@ class ArrayAssignmentQuestion < DataStructureAssignmentQuestion
51
53
  print_resulting_data_structure
52
54
  true
53
55
  else
54
- puts "\nNope! Here's what the data stucture would look like given your code:\n".red
55
- resulting_data_structure = evaluation_scope.eval(variable_name)
56
- ap(resulting_data_structure, { indent: -2, index: false, multiline: true, plain: true })
57
- puts "\nCheck your index and assignment values and try again.\n".red
56
+ print_incorrect_input_prompt
58
57
  end
59
58
  end
60
59
 
60
+ def print_incorrect_input_prompt
61
+ battleprint "\nNope! Here's what the data stucture would look like given your code:\n".red
62
+ resulting_data_structure = evaluation_scope.eval(variable_name)
63
+ ap(resulting_data_structure, { indent: -2, index: false, multiline: true, plain: true })
64
+ battleprint "\nCheck your index and assignment values and try again.\n".red
65
+ end
66
+
61
67
  def handles_user_workarounds(user_input)
62
68
  cheater_regex = Regexp.new("#{variable_name}\s+?\=\s+?(\\[)?")
63
69
  # checks if user reassigned the variable to a new array of identical values
64
70
  if user_input.match(cheater_regex)
65
71
  if $1
66
- puts 'You reassigned the variable to a new array object, when you could have worked with the array provided! Look up Ruby\'s Array#push method and try again!'.red
72
+ battleprint "You reassigned the variable to a new array object, when you could have worked with the array provided! Look up Ruby's Array#push method and try again!\n".red
67
73
  else
68
- puts 'You reassigned the variable '.red + variable_name.green + ' rather than working with the array provided. Try again.'.red
74
+ battleprint 'You reassigned the variable '.red + variable_name.green + " rather than working with the array provided. Try again.\n".red
69
75
  end
70
- puts ''
71
76
  true
72
77
  end
73
78
  end
@@ -82,7 +87,7 @@ class ArrayAssignmentQuestion < DataStructureAssignmentQuestion
82
87
  print_resulting_data_structure
83
88
  true
84
89
  else
85
- puts 'Nope! Try again.'.red
90
+ battleprint 'Nope! Try again.'.red
86
91
  end
87
92
  end
88
93
 
@@ -9,14 +9,14 @@ class DataStructureAccessQuestion < DataStructureQuestion
9
9
  def print_data_structure_access_prompt
10
10
  answer_value_class = format_class_for_output(answer_value.class)
11
11
  answer_value_string = format_value_for_stdout_and_eval(answer_value)
12
- puts "Given the data structure below, access the #{answer_value_class} value ".blue + answer_value_string.yellow + ".\n".blue
12
+ battleprint "Given the data structure below, access the #{answer_value_class} value ".blue + answer_value_string.yellow + ".\n".blue
13
13
  print "#{variable_name} = ".green
14
14
  if data_structure.to_s.length < 40
15
- puts data_structure.to_s.gsub('{', '{ ').gsub('=>', ' => ').gsub('}', ' }')
15
+ battleprint data_structure.to_s.gsub('{', '{ ').gsub('=>', ' => ').gsub('}', ' }')
16
16
  else
17
17
  ap(data_structure, { indent: -2, index: false, multiline: true, plain: true })
18
18
  end
19
- puts ''
19
+ battleprint ''
20
20
  end
21
21
 
22
22
  def evaluate_data_structure_access_input
@@ -25,11 +25,9 @@ class DataStructureAccessQuestion < DataStructureQuestion
25
25
  # provides the evaluation scope with variable assignment necessary for answer eval
26
26
  evaluation_scope.eval("#{variable_name} = #{data_structure.to_s}")
27
27
  if evaluation_scope.eval(user_submission) == answer_value && user_submission.include?(variable_name)
28
- # this last returned value of 'true' within the block is vital;
29
- # within the evaluation_loop method, the return value of yield is used
30
28
  true
31
29
  else
32
- puts "Remember, #{hint} Try again.\n".red
30
+ battleprint "Remember, #{hint} Try again.".red
33
31
  end
34
32
  rescue NameError => e
35
33
  print_colorized_error_prompt(e)
@@ -26,16 +26,16 @@ class DataStructureAssignmentQuestion < DataStructureQuestion
26
26
  def print_data_structure
27
27
  print "#{variable_name} = ".green
28
28
  ap(data_structure, { indent: -2, index: false, multiline: true, plain: true })
29
- puts ''
29
+ battleprint ''
30
30
  end
31
31
 
32
32
  def print_resulting_data_structure
33
33
  intro_congrat = POSSIBLE_INTRO_CONGRATULATIONS.sample
34
- puts "\n#{intro_congrat}. Here's the resulting data structure:\n".green
34
+ battleprint "\n#{intro_congrat}. Here's the resulting data structure:\n".green
35
35
  sleep 1.0
36
36
  resulting_data_structure = evaluation_scope.eval(variable_name)
37
37
  ap(resulting_data_structure, { indent: -2, index: false, multiline: true, plain: true })
38
- puts ''
38
+ battleprint ''
39
39
  sleep 3.2
40
40
  end
41
41
 
@@ -0,0 +1,12 @@
1
+ require_relative 'question'
2
+
3
+ class FollowUpQuestion < Question
4
+
5
+ attr_reader :original_question
6
+
7
+ def initialize(evaluation_scope, original_question)
8
+ @evaluation_scope = evaluation_scope
9
+ @original_question = original_question
10
+ end
11
+
12
+ end
@@ -8,6 +8,8 @@ class HashAccessQuestion < DataStructureAccessQuestion
8
8
  def initialize(scope)
9
9
  super(scope)
10
10
  format_hash
11
+ print_data_structure_access_prompt
12
+ evaluate_data_structure_access_input
11
13
  end
12
14
 
13
15
  def format_hash
@@ -8,6 +8,8 @@ class HashAssignmentQuestion < DataStructureAssignmentQuestion
8
8
  def initialize(scope)
9
9
  super(scope)
10
10
  format_hash_for_assignment
11
+ print_data_structure_assignment_prompt
12
+ evaluate_data_structure_assignment_input
11
13
  end
12
14
 
13
15
  def format_hash_for_assignment
@@ -20,7 +22,7 @@ class HashAssignmentQuestion < DataStructureAssignmentQuestion
20
22
  end
21
23
 
22
24
  def print_data_structure_assignment_prompt
23
- puts 'Given the Hash below, add a key of '.blue + assignment_key.yellow + " that points to the #{assignment_value_class} value of ".blue + "#{formatted_assignment_value}".yellow + ".\n\n"
25
+ battleprint 'Given the Hash below, add a key of '.blue + assignment_key.yellow + " that points to the #{assignment_value_class} value of ".blue + "#{formatted_assignment_value}".yellow + ".\n\n"
24
26
  print_data_structure
25
27
  end
26
28
 
@@ -29,7 +31,7 @@ class HashAssignmentQuestion < DataStructureAssignmentQuestion
29
31
  print_resulting_data_structure
30
32
  true
31
33
  else
32
- puts 'Nope! Try again!'.red
34
+ battleprint "Nope! Try again!".red
33
35
  end
34
36
  end
35
37
 
@@ -4,7 +4,7 @@ require_relative './question'
4
4
  class MethodDefinitionQuestion < Question
5
5
 
6
6
  attr_accessor :method_name, :arg_count, :spec, :eval_string, :eval_answer,
7
- :return_value
7
+ :return_value, :user_answer_verified
8
8
 
9
9
  @questions = METHOD_QUESTONS.shuffle
10
10
 
@@ -16,17 +16,12 @@ class MethodDefinitionQuestion < Question
16
16
  @eval_string = data[:eval_string]
17
17
  @eval_answer = data[:eval_answer]
18
18
  @input_mechanism = 'pry'
19
+ print_prompt
20
+ evaluate_method_definition_input
19
21
  end
20
22
 
21
23
  def print_prompt
22
- puts [
23
- 'Define a method called '.blue,
24
- method_name.yellow,
25
- ' that takes '.blue,
26
- arg_count.to_s.yellow,
27
- ' argument(s) and '.blue,
28
- spec.blue,
29
- ].join + "\n\n"
24
+ battleprint('Define a method called '.blue + method_name.yellow + ' that takes '.blue + arg_count.to_s.yellow + " argument(s) and #{spec}.\n".blue)
30
25
  end
31
26
 
32
27
  def handle_name_error_exceptions(error, user_submission)
@@ -38,17 +33,17 @@ class MethodDefinitionQuestion < Question
38
33
  end
39
34
 
40
35
  def handle_incorrect_method_definition(return_value)
41
- puts 'When calling '.red + eval_string + ", your method returned #{return_value || 'nil'}. It should have returned #{eval_answer}. Try again.\n".red
36
+ battleprint "\nWhen invoking your method via ".red + eval_string + ", your method returned #{return_value || 'nil'}. It should have returned #{eval_answer}. Try again.\n".red
42
37
  end
43
38
 
44
39
  def print_puts_explanation
45
- puts 'The last line of your method definition uses Ruby\'s "puts" method. The "puts" method is helpful for logging errors and statuses to the console, but its actual '.red + "return".red.underline + " value is always nil, and thus your method returns nil. Try again, this time without using \"puts\".\n".red
40
+ battleprint 'The last line of your method definition uses Ruby\'s "puts" method. The "puts" method is helpful for logging errors and statuses to the console, but its actual '.red + "return".red.underline + " value is always nil, and thus your method returns nil. Try again, this time without using \"puts\".\n".red
46
41
  end
47
42
 
48
43
  def print_no_method_error_prompt
49
- puts "\nYou just trigged a common Ruby error that reads: \n".red
50
- puts "\tundefined method \'WHATEVER_METHOD_YOU_TRIED_TO_INVOKE\'\n".green
51
- puts "Basically, you tried to use a method before you defined it, and Ruby said, \"You haven't told me how to do that yet.\" To let Ruby know that you're defining a method, you'll use the the \"def\" keyword, and end your method definition with the \"end\" keyword.\n".red
44
+ battleprint "\nYou just trigged a common Ruby error that reads: \n".red
45
+ battleprint "\tundefined method \'WHATEVER_METHOD_YOU_TRIED_TO_INVOKE\'\n".green
46
+ battleprint "Basically, you tried to use a method before you defined it, and Ruby said, \"You haven't told me how to do that yet.\" To let Ruby know that you're defining a method, you'll use the the \"def\" keyword, followed by the desired method name, and in many cases an optional list of arguments between parentheses. Once you've finished writing the method's inner code, you'll let Ruby know that your method definition is finished by using the \"end\" keyword.\n".red
52
47
  end
53
48
 
54
49
  def fresh_binding
@@ -60,7 +55,7 @@ class MethodDefinitionQuestion < Question
60
55
  if user_submission.match(definition_pattern)
61
56
  handle_incorrect_method_definition(user_submission)
62
57
  else
63
- puts "\nYou defined the wrong method, probably as the result of a mispelling. Try again.\n".red
58
+ battleprint "\nYou defined the wrong method, probably as the result of a mispelling. Try again.".red
64
59
  end
65
60
  end
66
61
 
@@ -68,7 +63,7 @@ class MethodDefinitionQuestion < Question
68
63
  e.message.match(/wrong number of arguments \((\d) for (\d)\)/)
69
64
  passed_arg_count = $1.to_i
70
65
  expected_arg_count = $2.to_i
71
- puts "Looks like you defined #{method_name} to take #{expected_arg_count} argument(s), when it should take #{arg_count}. Try again.\n".red
66
+ battleprint "\nLooks like you defined #{method_name} to take #{expected_arg_count} argument(s), when it should take #{arg_count}. Try again.\n".red
72
67
  end
73
68
 
74
69
  def clean_eval_scope_of_method_definition
@@ -88,6 +83,7 @@ class MethodDefinitionQuestion < Question
88
83
  evaluation_scope.eval(user_submission)
89
84
  return_value = evaluation_scope.eval(eval_string)
90
85
  if (return_value == eval_answer)
86
+ self.user_answer_verified = user_submission
91
87
  true
92
88
  else
93
89
  handle_incorrect_method_definition(return_value)
@@ -1,54 +1,71 @@
1
- require_relative './question'
1
+ require_relative './follow_up_question'
2
2
 
3
- class MethodInvocationQuestion < Question
3
+ class MethodInvocationQuestion < FollowUpQuestion
4
4
 
5
- attr_reader :original_question, :desired_answer_formatted, :desired_answer_class_formatted
5
+ attr_reader :desired_answer_formatted, :desired_answer_class_formatted
6
6
 
7
7
  def initialize(evaluation_scope, question_to_follow_up_on)
8
- @evaluation_scope = evaluation_scope
9
- @original_question = question_to_follow_up_on
8
+ super(evaluation_scope, question_to_follow_up_on)
10
9
  @desired_answer_formatted = format_value_for_stdout_and_eval(original_question.eval_answer)
11
10
  @desired_answer_class_formatted = format_class_for_output(original_question.eval_answer.class)
11
+ print_method_invocation_prompt
12
+ evaluate_user_input
12
13
  end
13
14
 
14
15
  def format_method_definition_for_stdout
15
16
  code = CodeRay.scan($input, :ruby)
16
- # adds indentation to all lines of method definition
17
- code.term.gsub(/^.*/) { |match| "\t" + match }
17
+ ansi_prepped_string = code.term
18
+ indent_all_lines_for_stdout(ansi_prepped_string)
18
19
  end
19
20
 
20
21
  def print_method_invocation_prompt
21
- puts "You now have the method defined below at your disposal.\n".blue
22
- puts format_method_definition_for_stdout
23
- puts "\nInvoke the '#{original_question.method_name}' method such that it returns the ".blue + desired_answer_class_formatted.blue + " value ".blue + desired_answer_formatted.yellow + "\n\n"
22
+ battleprint "You now have the method defined below at your disposal.\n".blue
23
+ battleprint format_method_definition_for_stdout
24
+ battleprint "\nInvoke the '#{original_question.method_name}' method such that it returns the ".blue + desired_answer_class_formatted.blue + " value ".blue + desired_answer_formatted.yellow + ".\n".blue
24
25
  end
25
26
 
26
27
  def print_no_method_error_prompt
27
- puts "\nYou just trigged a common Ruby error that reads: \n".red
28
- puts "\tundefined local variable or method \'WHATEVER_METHOD_YOU_TRIED_TO_INVOKE\'\n".green
29
- puts "Basically, you tried to invoke a method that doesn't exist. Try again.\n".red
28
+ battleprint "\nYou just trigged a common Ruby error that reads: \n".red
29
+ battleprint "\tundefined local variable or method \'WHATEVER_METHOD_YOU_TRIED_TO_INVOKE\'\n".green
30
+ battleprint "Basically, you tried to invoke a method that doesn't exist. Try again.\n".red
30
31
  end
31
32
 
32
33
  def print_name_error_prompt(error, user_submission)
33
- puts "You just triggered a common Ruby error that reads:\n".red
34
- puts "\tNameError: #{error.message}\n".green
35
- /`(.+)'/i.match(error.message)
36
- referenced_variable = $1
37
- passed_as_argument_pattern = Regexp.new("\(.*#{$1}.*\)")
38
- if user_submission.match(passed_as_argument_pattern)
39
- puts "You're trying to pass the '#{original_question.method_name}' method the value stored in the variable '#{referenced_variable}', but that variable hasn't been assigned a value.\n".red
34
+ battleprint "\nYou just triggered a common Ruby error that reads:\n".red
35
+ battleprint "\tNameError: #{error.message}\n".green
36
+ referenced_variable = isolate_variable_name_from_name_error(error)
37
+ parameters = isolate_argument_names_from_method_def
38
+ if parameters.find { |parameter| parameter == referenced_variable }
39
+ battleprint "Looks like the variable you referenced was one of the argument names in your method #{'definition'.red.underline}. The arguments in method definitions are just placeholders for whatever values end up getting passed in when the method is called. Think on this for a moment before trying again.\n".red
40
40
  else
41
- puts "Basically, you're referencing a variable, #{$1}, that hasn't been defined.\n".red
41
+ battleprint "Basically, you're referencing a variable, \"#{referenced_variable}\", that hasn't been assigned a value.\n".red
42
42
  end
43
43
  end
44
44
 
45
+ def isolate_variable_name_from_name_error(error)
46
+ error.name.to_s
47
+ end
48
+
45
49
  def print_argument_error_prompt(e)
46
50
  e.message.match(/wrong number of arguments \((\d) for (\d)\)/)
47
51
  passed_arg_count = $1.to_i
48
52
  expected_arg_count = $2.to_i
49
- puts "You just triggered a common Ruby error that reads:\n".red
50
- puts "\tArgumentError: #{e.message}\n".green
51
- puts "Basically, you defined the '#{original_question.method_name}' method to expect #{expected_arg_count} argument(s), and you're only passing #{passed_arg_count}. Try again.\n".red
53
+ battleprint "You just triggered a common Ruby error that reads:\n".red
54
+ battleprint "\tArgumentError: #{e.message}\n".green
55
+ battleprint "Basically, you defined the '#{original_question.method_name}' method to expect #{expected_arg_count} argument(s), and you're only passing it #{passed_arg_count}. Try again.\n".red
56
+ end
57
+
58
+ def isolate_argument_names_from_method_def
59
+ isolate_parameter_list_string_from_method_def.scan(/([^,\s]+)+/x).flatten
60
+ end
61
+
62
+ def isolate_parameter_list_string_from_method_def
63
+ original_question.user_answer_verified.match /\((.+)\)/
64
+ $1
65
+ end
66
+
67
+ def print_incorrect_input_prompt(return_from_eval)
68
+ battleprint "Your code returned the #{format_class_for_output(return_from_eval.class)} value #{return_from_eval.to_s} when it should have returned the #{desired_answer_class_formatted} value #{desired_answer_formatted}. Try again.".red
52
69
  end
53
70
 
54
71
  def evaluate_user_input
@@ -58,7 +75,7 @@ class MethodInvocationQuestion < Question
58
75
  if return_from_eval == original_question.eval_answer
59
76
  true
60
77
  else
61
- puts "Remember, to call a method, you simply enter its name followed by any arguments it might need. Try again.\n".red
78
+ print_incorrect_input_prompt(return_from_eval)
62
79
  end
63
80
  rescue NoMethodError => e
64
81
  print_no_method_error_prompt
@@ -14,6 +14,8 @@ class NestedDataStructureAccessQuestion < DataStructureAccessQuestion
14
14
  else
15
15
  self.answer_value = data_structure[data_structure.keys.sample]
16
16
  end
17
+ print_data_structure_access_prompt
18
+ evaluate_data_structure_access_input
17
19
  end
18
20
  end
19
21
 
@@ -1,8 +1,8 @@
1
- class Question
1
+ class Question
2
2
  attr_reader :data
3
3
  attr_accessor :variable_name, :variable_value, :data_structure,
4
4
  :data_structure_class, :answer_value, :explanation,
5
- :evaluation_scope, :input_mechanism
5
+ :evaluation_scope, :input_mechanism, :user_input
6
6
 
7
7
  def initialize(evaluation_scope)
8
8
  @evaluation_scope = evaluation_scope
@@ -28,18 +28,18 @@ class Question
28
28
 
29
29
  def handle_syntax_error_exceptions(error)
30
30
  if error.message.match /unexpected end-of-input/
31
- print_unexpected_end_of_input_explanation
31
+ print_unexpected_end_of_input_explanation(error)
32
32
  elsif error.message.include?('unterminated string meets end of file')
33
- puts 'Blurg! You neglected to provide closing quotes for your string. Try again!'.red
33
+ battleprint 'Blurg! You neglected to provide closing quotes for your string. Try again!'.red
34
34
  end
35
35
  end
36
36
 
37
37
  def get_input
38
38
  if input_mechanism == 'readline'
39
- Readline.readline('> '.blue, true)
39
+ Readline.readline('> '.blue, true).chomp
40
40
  else
41
41
  Pry.start_without_pry_debugger(evaluation_scope)
42
- $input
42
+ $input.chomp
43
43
  end
44
44
  end
45
45
 
@@ -0,0 +1,75 @@
1
+ require_relative 'question'
2
+ require_relative '../data/variable_assignment_questions'
3
+
4
+ class VariableAssignmentQuestion < Question
5
+
6
+ attr_accessor :formatted_value, :formatted_class
7
+ @questions = VARIABLE_QUESTIONS.shuffle
8
+
9
+ def initialize(eval_scope)
10
+ super(eval_scope)
11
+ @variable_value = rotate_array(data[:possible_variable_values]).first
12
+ @formatted_value = format_value_for_stdout_and_eval(variable_value)
13
+ print_variable_assignment_prompt
14
+ evaluate_variable_assignment_input
15
+ end
16
+
17
+ def print_variable_assignment_prompt
18
+ self.formatted_class = format_class_for_output(variable_value.class)
19
+ substrings = [
20
+ 'Assign the variable '.blue,
21
+ variable_name.yellow,
22
+ ' to the '.blue,
23
+ formatted_class.blue,
24
+ ' value '.blue,
25
+ formatted_value.yellow,
26
+ ".\n".blue
27
+ ]
28
+ battleprint substrings.join
29
+ end
30
+
31
+ def reveal_name_error_follies_to_user(user_input, errorbefor)
32
+ if user_input.include?(variable_name)
33
+ if !user_input.match(/[^=]=[^=]/i)
34
+ undefined_local_variable_prompt_for_correct_variable
35
+ else
36
+ misassignment_prompt
37
+ end
38
+ elsif !user_input.match(/("|')/) && variable_value.class == String
39
+ battleprint 'Rats! You\'ve just made a common rookie mistake! Strings are always surrounded by quotes. Otherwise, Ruby will think you\'re referencing a variable or method name. Try again.'.red
40
+ else
41
+ battleprint "Looks like you mistyped the variable name. Check for misspellings and try again.".red
42
+ end
43
+ end
44
+
45
+ def undefined_local_variable_prompt_for_correct_variable
46
+ battleprint "\nYou're referencing a variable that hasn't been assigned yet. This results in a common error that says: \n".red
47
+ battleprint "\tundefined local variable or method \'#{variable_name}\'\n".green
48
+ battleprint "To assign a value to a variable, you'll need to use the assignment operator ".red + ' = '.black.on_light_white + ", followed by a valid Ruby value.\n".red
49
+ end
50
+
51
+ def handle_base_exception(exception)
52
+ if exception.message.match(/unterminated string/)
53
+ battleprint 'Blurg! You neglected to provide closing quotes for your string. Try again!'.red
54
+ else
55
+ battleprint exception.message
56
+ end
57
+ end
58
+
59
+ def evaluate_variable_assignment_input
60
+ enter_evaluation_loop do |user_submission|
61
+ begin
62
+ evaluation_scope.eval(user_submission)
63
+ if evaluation_scope.eval("#{variable_name} == #{formatted_value}")
64
+ true
65
+ else
66
+ battleprint "You assigned the wrong value to #{variable_name}. Try again!".red
67
+ end
68
+ rescue NameError => e
69
+ reveal_name_error_follies_to_user(user_submission, e)
70
+ rescue Exception => e
71
+ handle_base_exception(e)
72
+ end
73
+ end
74
+ end
75
+ end # VariableQuestion
@@ -0,0 +1,29 @@
1
+ require_relative 'follow_up_question'
2
+
3
+ class VariableReassignmentQuestion < FollowUpQuestion
4
+
5
+ attr_accessor :toggled_boolean
6
+
7
+ def initialize(evaluation_scope, original_question)
8
+ super(evaluation_scope, original_question)
9
+ @toggled_boolean = !(original_question.variable_value)
10
+ print_variable_reassignment_prompt
11
+ evaluate_variable_reassignment_input
12
+ end
13
+
14
+ def print_variable_reassignment_prompt
15
+ battleprint "Times have changed! Reassign ".blue + original_question.variable_name.yellow + " to the Boolean value ".blue + toggled_boolean.to_s.yellow + ".\n".blue
16
+ end
17
+
18
+ def evaluate_variable_reassignment_input
19
+ enter_evaluation_loop do |user_submission|
20
+ input = user_submission
21
+ evaluation_scope.eval(input)
22
+ if (evaluation_scope.eval(original_question.variable_name) == toggled_boolean)
23
+ true
24
+ else
25
+ battleprint "Nope. Try again.".red
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,93 @@
1
+ require_relative './follow_up_question'
2
+
3
+ class VariableReferenceQuestion < FollowUpQuestion
4
+
5
+ attr_accessor :required_return_value
6
+
7
+ def initialize(scope, original_question)
8
+ super(scope, original_question)
9
+ print_variable_reference_prompt
10
+ evaluate_variable_reference_input
11
+ end
12
+
13
+ def print_variable_reference_prompt
14
+ battleprint "You now have the variable assignment below at your disposal.\n".blue
15
+ battleprint "\t#{original_question.variable_name} = #{original_question.formatted_value}\n\n"
16
+ prompt = develop_prompt
17
+ puts prompt
18
+ end
19
+
20
+ def a_value_within_12_more_or_12_less_than_the_original_assigned_value
21
+ range = (-12..12).to_a
22
+ range.delete(0)
23
+ original_question.variable_value + range.sample
24
+ end
25
+
26
+ def a_value_that_doesnt_result_from_imprecise_float_arithmetic
27
+ if original_question.variable_value < 15
28
+ new_target_value = original_question.variable_value + rand(1..15)
29
+ else
30
+ new_target_value = a_value_within_12_more_or_12_less_than_the_original_assigned_value
31
+ end
32
+ count = 1
33
+ while new_target_value.to_s.split(".").last.length > 4
34
+ new_target_value = original_question.variable_value + count
35
+ count += 1
36
+ end
37
+ new_target_value
38
+ end
39
+
40
+ def generate_appropriate_value
41
+ value = original_question.variable_value
42
+ if value.class == Fixnum
43
+ if value.even? # && [1,2,3,4,5].sample.even?
44
+ if value < 12
45
+ value * [3,4,5,6].sample
46
+ elsif value < 50
47
+ value * 2
48
+ else
49
+ value / 2
50
+ end
51
+ else
52
+ a_value_within_12_more_or_12_less_than_the_original_assigned_value
53
+ end
54
+ else
55
+ a_value_that_doesnt_result_from_imprecise_float_arithmetic()
56
+ end
57
+ end
58
+
59
+ def develop_prompt
60
+ case original_question.variable_value.class.to_s
61
+ when 'Fixnum', 'Float'
62
+ self.required_return_value = generate_appropriate_value()
63
+ prompt = "Use ".blue + original_question.variable_name.green + " in combination with an arithmetic operator like ".blue + " + ".black.on_light_white + ", ".blue + " - ".black.on_light_white + ", ".blue + " * ".black.on_light_white + ", or ".blue + " / ".black.on_light_white + " to return the #{original_question.formatted_class} value ".blue + required_return_value.to_s.green + ".\n".blue
64
+ else
65
+ battleprint "Something's gone wrong. This code should never run.".red
66
+ end
67
+ end
68
+
69
+ def provide_evaluation_scope_with_original_variable_assignment
70
+ evaluation_scope.eval("#{original_question.variable_name} = #{original_question.formatted_value}")
71
+ end
72
+
73
+ def evaluate_variable_reference_input
74
+ enter_evaluation_loop do |user_submission|
75
+ begin
76
+ provide_evaluation_scope_with_original_variable_assignment
77
+ returned_value = evaluation_scope.eval(user_submission)
78
+ if !user_submission.include?(original_question.variable_name)
79
+ battleprint "You didn't make use of the '#{original_question.variable_name}' variable, which is the entire purpose of this exercise. Try again.".red
80
+ elsif user_submission.include?("=")
81
+ battleprint "Looks like you simply assigned (or reassigned) a value to a variable, rather than making use of the value stored in '#{original_question.variable_name}'. Reread the directions and try again!".red
82
+ elsif (returned_value == required_return_value)
83
+ true
84
+ else
85
+ puts "Your code returned the #{format_class_for_output(returned_value.class)} value #{returned_value.to_s} when it should have returned the #{original_question.formatted_class} value #{format_value_for_stdout_and_eval(required_return_value)}. Try again.".red
86
+ end
87
+ rescue NameError, NoMethodError => e
88
+ print_colorized_error_prompt(e)
89
+ end
90
+ end
91
+ end
92
+
93
+ end
data/lib/battleroom.rb CHANGED
@@ -1,19 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'readline'
4
- require 'faker'
5
- require 'awesome_print'
6
- require 'pry'
7
- require 'colorize'
8
- require 'coderay'
9
-
10
- require_relative './battleroom/config/pry_config'
11
-
12
- path = File.expand_path("./battleroom/models/*.rb", File.dirname(__FILE__))
13
- Dir[path].each { |file| require file }
14
-
15
- require_relative 'battleroom/battleroom_machinery'
16
- include BattleroomMachinery
3
+ require_relative './battleroom/config/boot'
17
4
 
18
5
  clear_display
19
6
  print 'Welcome to the Battleroom.'.blue
@@ -30,49 +17,26 @@ loop do
30
17
  case choice
31
18
  when '1'
32
19
  10.times do
33
- q = VariableQuestion.new(b)
34
- q.print_variable_assignment_prompt
35
- q.evaluate_variable_assignment_input
20
+ q = VariableAssignmentQuestion.new(b)
21
+ determine_variable_follow_up_question(b, q)
36
22
  end
37
23
  when '2'
38
24
  5.times do
39
25
  q = [ArrayAccessQuestion.new(b), HashAccessQuestion.new(b)].sample
40
- q.print_data_structure_access_prompt
41
- q.evaluate_data_structure_access_input
42
26
  end
43
27
  when '3'
44
28
  5.times do
45
29
  q = [ArrayAssignmentQuestion.new(b), HashAssignmentQuestion.new(b)].sample
46
- q.print_data_structure_assignment_prompt
47
- q.evaluate_data_structure_assignment_input
48
30
  end
49
31
  when '4'
50
32
  5.times do
51
- q = NestedDataStructureAccessQuestion.new(b)
52
- q.print_data_structure_access_prompt
53
- q.evaluate_data_structure_access_input
54
- end
55
- when '5'
56
- # 5.times do
57
- # q = MethodDefinitionQuestion.new(b)
58
- # q.print_prompt
59
- # q.evaluate_method_definition_input
60
- # end
61
-
62
- #========================================
63
- # Method Defintiion Follow Up Development
64
- #========================================
65
- 2.times do
66
33
  q = MethodDefinitionQuestion.new(b)
67
- q.print_prompt
68
- q.evaluate_method_definition_input
69
34
  follow_up_question = MethodInvocationQuestion.new(b, q)
70
- follow_up_question.print_method_invocation_prompt
71
- follow_up_question.evaluate_user_input
72
35
  end
73
-
36
+ when '5'
37
+ 5.times { NestedDataStructureAccessQuestion.new(b) }
74
38
  else
75
- puts 'You entered a non-option. Try again.'.red
39
+ battleprint 'You entered a non-option. Try again.'.red
76
40
  end
77
41
  end
78
42
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: battleroom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.79
4
+ version: 0.0.80
5
5
  platform: ruby
6
6
  authors:
7
7
  - Travis Vander Hoop
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-05 00:00:00.000000000 Z
11
+ date: 2014-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faker
@@ -94,9 +94,23 @@ dependencies:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
96
  version: 1.1.0
97
- description: A command-line REPL designed to give novice Ruby programmers countless
98
- reps doing simple tasks like assigning variables, working with data structures,
99
- and defining and invoking methods.
97
+ - !ruby/object:Gem::Dependency
98
+ name: word_wrap
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 0.2.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 0.2.1
111
+ description: A REPL designed to give Ruby newbies countless reps doing simple tasks
112
+ like working with variables, manipulating data structures, and defining and invoking
113
+ methods.
100
114
  email: vanderhoop@me.com
101
115
  executables:
102
116
  - battleroom
@@ -106,25 +120,32 @@ files:
106
120
  - bin/battleroom
107
121
  - lib/battleroom.rb
108
122
  - lib/battleroom/battleroom_machinery.rb
123
+ - lib/battleroom/config/boot.rb
109
124
  - lib/battleroom/config/pry_config.rb
110
125
  - lib/battleroom/data/array_questions.rb
111
126
  - lib/battleroom/data/hash_questions.rb
112
127
  - lib/battleroom/data/method_questions.rb
113
128
  - lib/battleroom/data/nested_data_structure_access_questions.rb
129
+ - lib/battleroom/data/scratch.rb
114
130
  - lib/battleroom/data/variable_assignment_questions.rb
115
131
  - lib/battleroom/data_generation_machinery.rb
132
+ - lib/battleroom/helpers/array_formatter.rb
133
+ - lib/battleroom/helpers/hash_formatter.rb
116
134
  - lib/battleroom/models/array_access_question.rb
117
135
  - lib/battleroom/models/array_assignment_question.rb
118
136
  - lib/battleroom/models/data_structure_access_question.rb
119
137
  - lib/battleroom/models/data_structure_assignment_question.rb
120
138
  - lib/battleroom/models/data_structure_question.rb
139
+ - lib/battleroom/models/follow_up_question.rb
121
140
  - lib/battleroom/models/hash_access_question.rb
122
141
  - lib/battleroom/models/hash_assignment_question.rb
123
142
  - lib/battleroom/models/method_definition_question.rb
124
143
  - lib/battleroom/models/method_invocation_question.rb
125
144
  - lib/battleroom/models/nested_data_structure_access_question.rb
126
145
  - lib/battleroom/models/question.rb
127
- - lib/battleroom/models/variable_question.rb
146
+ - lib/battleroom/models/variable_assignment_question.rb
147
+ - lib/battleroom/models/variable_reassignment_question.rb
148
+ - lib/battleroom/models/variable_reference_question.rb
128
149
  homepage: https://github.com/vanderhoop/battleroom
129
150
  licenses:
130
151
  - MIT
@@ -148,7 +169,7 @@ rubyforge_project:
148
169
  rubygems_version: 2.2.2
149
170
  signing_key:
150
171
  specification_version: 4
151
- summary: A command-line REPL designed to give novice Ruby programmers countless reps
152
- doing simple tasks like assigning variables, working with data structures, and defining
153
- and invoking methods.
172
+ summary: A REPL designed to give Ruby newbies countless reps doing simple tasks like
173
+ working with variables, manipulating data structures, and defining and invoking
174
+ methods.
154
175
  test_files: []
@@ -1,63 +0,0 @@
1
- require_relative 'question'
2
- require_relative '../data/variable_assignment_questions'
3
-
4
- class VariableQuestion < Question
5
- attr_accessor :formatted_value
6
- # using a class instance variable, as manipulating a single class var
7
- # in the parent class is troublesome
8
- @questions = VARIABLE_QUESTIONS.shuffle
9
-
10
- def initialize(eval_scope)
11
- super(eval_scope)
12
- @variable_value = rotate_array(data[:possible_variable_values]).first
13
- @formatted_value = format_value_for_stdout_and_eval(variable_value)
14
- end
15
-
16
- def print_variable_assignment_prompt
17
- formatted_class = format_class_for_output(variable_value.class)
18
- substrings = [
19
- 'Create a variable '.blue,
20
- variable_name.yellow,
21
- ' and assign it the '.blue,
22
- formatted_class.blue,
23
- ' value '.blue,
24
- formatted_value.yellow
25
- ]
26
- puts substrings.join
27
- end
28
-
29
- def reveal_name_error_follies_to_user(user_input)
30
- if user_input.include?(variable_name) && !user_input.match(/[^=]=[^=]/i)
31
- puts 'You\'re not using the assignment operator!'.red
32
- elsif !user_input.match(/("|')/) && variable_value.class == String
33
- puts 'Rats! You\'ve just made a common rookie mistake! ' +
34
- 'Strings are always surrounded by quotes. Otherwise, Ruby will ' +
35
- 'think you\'re referencing a variable or method name. Try again.'.red
36
- else
37
- puts 'Looks like you mistyped the variable name. Check for misspellings and try again.'.red
38
- end
39
- end
40
-
41
- def evaluate_variable_assignment_input
42
- enter_evaluation_loop do |user_submission|
43
- begin
44
- evaluation_scope.eval(user_submission)
45
- if evaluation_scope.eval("#{variable_name} == #{formatted_value}")
46
- # this last returned value of 'true' is vital;
47
- # the return value of yield is used in a conditional
48
- true
49
- else
50
- puts "You mis-assigned #{variable_name}. Try again!".red
51
- end
52
- rescue NameError => e
53
- reveal_name_error_follies_to_user(user_submission)
54
- rescue Exception => e
55
- if e.message.match(/unterminated string/)
56
- puts 'Blurg! You neglected to provide closing quotes for your string. Try again!'.red
57
- else
58
- puts e.message
59
- end
60
- end
61
- end
62
- end
63
- end # VariableQuestion