battleroom 0.0.79 → 0.0.80
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/lib/battleroom/battleroom_machinery.rb +63 -19
- data/lib/battleroom/config/boot.rb +18 -0
- data/lib/battleroom/config/pry_config.rb +10 -4
- data/lib/battleroom/data/array_questions.rb +5 -2
- data/lib/battleroom/data/hash_questions.rb +9 -0
- data/lib/battleroom/data/method_questions.rb +53 -1
- data/lib/battleroom/data/scratch.rb +0 -0
- data/lib/battleroom/data/variable_assignment_questions.rb +4 -3
- data/lib/battleroom/data_generation_machinery.rb +17 -9
- data/lib/battleroom/helpers/array_formatter.rb +3 -0
- data/lib/battleroom/helpers/hash_formatter.rb +3 -0
- data/lib/battleroom/models/array_access_question.rb +2 -0
- data/lib/battleroom/models/array_assignment_question.rb +17 -12
- data/lib/battleroom/models/data_structure_access_question.rb +4 -6
- data/lib/battleroom/models/data_structure_assignment_question.rb +3 -3
- data/lib/battleroom/models/follow_up_question.rb +12 -0
- data/lib/battleroom/models/hash_access_question.rb +2 -0
- data/lib/battleroom/models/hash_assignment_question.rb +4 -2
- data/lib/battleroom/models/method_definition_question.rb +12 -16
- data/lib/battleroom/models/method_invocation_question.rb +42 -25
- data/lib/battleroom/models/nested_data_structure_access_question.rb +2 -0
- data/lib/battleroom/models/question.rb +6 -6
- data/lib/battleroom/models/variable_assignment_question.rb +75 -0
- data/lib/battleroom/models/variable_reassignment_question.rb +29 -0
- data/lib/battleroom/models/variable_reference_question.rb +93 -0
- data/lib/battleroom.rb +6 -42
- metadata +30 -9
- data/lib/battleroom/models/variable_question.rb +0 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4121f41892684e9effe768d41855f85ef301794b
|
4
|
+
data.tar.gz: 0c63c05faee0c39886da9fe0e9bf41e9a558dcb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
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
|
56
|
-
puts
|
57
|
-
|
58
|
-
|
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
|
-
|
63
|
-
|
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
|
-
|
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
|
-
|
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 = [
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
77
|
-
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
|
-
|
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
|
-
|
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
|
-
|
123
|
+
{
|
116
124
|
data_structure: location,
|
117
125
|
possible_variable_names: [
|
118
126
|
snake_case(city),
|
@@ -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
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
29
|
+
battleprint ''
|
30
30
|
end
|
31
31
|
|
32
32
|
def print_resulting_data_structure
|
33
33
|
intro_congrat = POSSIBLE_INTRO_CONGRATULATIONS.sample
|
34
|
-
|
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
|
-
|
38
|
+
battleprint ''
|
39
39
|
sleep 3.2
|
40
40
|
end
|
41
41
|
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
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
|
-
|
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 './
|
1
|
+
require_relative './follow_up_question'
|
2
2
|
|
3
|
-
class MethodInvocationQuestion <
|
3
|
+
class MethodInvocationQuestion < FollowUpQuestion
|
4
4
|
|
5
|
-
attr_reader
|
5
|
+
attr_reader :desired_answer_formatted, :desired_answer_class_formatted
|
6
6
|
|
7
7
|
def initialize(evaluation_scope, question_to_follow_up_on)
|
8
|
-
|
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
|
-
|
17
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
78
|
+
print_incorrect_input_prompt(return_from_eval)
|
62
79
|
end
|
63
80
|
rescue NoMethodError => e
|
64
81
|
print_no_method_error_prompt
|
@@ -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
|
-
|
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
|
-
|
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 =
|
34
|
-
q
|
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
|
-
|
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.
|
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-
|
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
|
-
|
98
|
-
|
99
|
-
|
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/
|
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
|
152
|
-
|
153
|
-
|
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
|