minitest-naga 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +85 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +93 -0
- data/LICENSE.txt +21 -0
- data/README.md +120 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/minitest-naga +4 -0
- data/helpers/test_helper.rb +55 -0
- data/lib/minitest/game/game.rb +223 -0
- data/lib/minitest/game/inventory.rb +33 -0
- data/lib/minitest/game/item.rb +82 -0
- data/lib/minitest/game/location.rb +56 -0
- data/lib/minitest/game/place.rb +16 -0
- data/lib/minitest/naga/achievement.rb +79 -0
- data/lib/minitest/naga/cli.rb +20 -0
- data/lib/minitest/naga/detector.rb +89 -0
- data/lib/minitest/naga/naga_api.rb +80 -0
- data/lib/minitest/naga/naga_reporter.rb +21 -0
- data/lib/minitest/naga/version.rb +5 -0
- data/lib/minitest/naga.rb +6 -0
- data/lib/minitest/naga_plugin.rb +19 -0
- data/minitest-naga.gemspec +44 -0
- metadata +228 -0
@@ -0,0 +1,223 @@
|
|
1
|
+
class Game
|
2
|
+
def initialize(credentials, detector)
|
3
|
+
@credentials = credentials
|
4
|
+
@detector = detector
|
5
|
+
start_game
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def start_game
|
11
|
+
if run
|
12
|
+
if !completed_beginning?
|
13
|
+
beginning
|
14
|
+
end
|
15
|
+
main
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def main
|
20
|
+
say("You stand at the Fast Travel station outside the office.")
|
21
|
+
say("'Welcome to the Fast Travel station at Naga! Where would you like to go?'")
|
22
|
+
selected = false
|
23
|
+
current_location = nil
|
24
|
+
# Output location options
|
25
|
+
while !selected do
|
26
|
+
choose do |menu|
|
27
|
+
menu.prompt = "> "
|
28
|
+
menu.shell = true
|
29
|
+
Location.all.each do |location|
|
30
|
+
menu.choice(location.name, location.description) do |_command, details|
|
31
|
+
say(location.to_s)
|
32
|
+
selected = true
|
33
|
+
current_location = location
|
34
|
+
end
|
35
|
+
end
|
36
|
+
menu.choice("Home") do |_command, details|
|
37
|
+
say("You go straight home.")
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
# Output places in chosen location
|
43
|
+
choose do |menu|
|
44
|
+
menu.prompt = "> "
|
45
|
+
current_location.places.each do |place|
|
46
|
+
menu.choice(place.name, place.description)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
# Call for item drop
|
50
|
+
item = Item.drop(@credentials)
|
51
|
+
if item
|
52
|
+
say(item.to_s)
|
53
|
+
say("Do you want to add it to your desk or backpack or leave it?")
|
54
|
+
choose do |menu|
|
55
|
+
menu.prompt = "> "
|
56
|
+
menu.confirm = true
|
57
|
+
menu.choice(:desk) do |_command, details|
|
58
|
+
Inventory.add_to_desk(item, @credentials)
|
59
|
+
item_achievements(item)
|
60
|
+
end
|
61
|
+
menu.choice(:backpack) do |_command, details|
|
62
|
+
Inventory.add(item, @credentials)
|
63
|
+
item_achievements(item)
|
64
|
+
end
|
65
|
+
menu.choice("leave it") do |_command, details|
|
66
|
+
say("You leave the item behind.")
|
67
|
+
end
|
68
|
+
menu.default = "leave it"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
say("After some time of exploring, you go home.")
|
72
|
+
end
|
73
|
+
|
74
|
+
def beginning
|
75
|
+
say("'Hello there! Welcome to the world of Naga! My name is Oak. People call me the Naga Prof!")
|
76
|
+
choose do |menu|
|
77
|
+
menu.prompt = "> "
|
78
|
+
menu.choice(:look) { say("You find yourself in the main office of Naga. The man standing in front of you is wearing a red shirt but not with a lab coat.") }
|
79
|
+
menu.choices(:ask) { say("'You're joking, right?', you ask.\n'I mean... I've got the red shirt, just not the lab coat.', he replies.") }
|
80
|
+
menu.choices(:laugh) { say("You laugh and then reminisce of the days of capturing creatures, enslaving them and making them fight. Your smile soon fades.") }
|
81
|
+
menu.choices(:silence) { say("You remain silent. 'Not the talkative kind I see. No worries, I'm sure you'll find a way to ease yourself in.'") }
|
82
|
+
menu.default = :silence
|
83
|
+
end
|
84
|
+
|
85
|
+
say("You've arrived at Naga, a bespoke software development company, your new workplace. It's 9.04am on a Monday.\nYou love Mondays.")
|
86
|
+
say("'Okay, my name is not really Oak. It's actually Ash. Pleased to meet you.'")
|
87
|
+
choose do |menu|
|
88
|
+
menu.prompt = "> "
|
89
|
+
menu.choice(:talk) { say("'Pleased to meet you.', you reply.") }
|
90
|
+
menu.choices(:ask) { say("'You're joking again, right?', you ask.\n'Nope! My name is actually Ash.', he replies.") }
|
91
|
+
menu.choices(:silence) { say("You remain silent.") }
|
92
|
+
menu.default = :silence
|
93
|
+
end
|
94
|
+
|
95
|
+
say("Ash explains that for the first couple of days of your internship you'll be shadowing him.")
|
96
|
+
say("'Here's your desk. Right next to mine for the time being.'")
|
97
|
+
choose do |menu|
|
98
|
+
menu.prompt = "> "
|
99
|
+
menu.choice(:look) { say("You notice it's small or 'smol' but there's still space to fit a couple of things.") }
|
100
|
+
menu.choices(:talk) { say("You don't know what to say so you just smile politely.") }
|
101
|
+
menu.choices(:silence) { say("You remain silent.") }
|
102
|
+
menu.default = :silence
|
103
|
+
end
|
104
|
+
|
105
|
+
say("'It's a tradition here at Naga for a newbie to select a mug for themselves to train... I mean keep. There are 3 mugs here! (When I was younger, I was a serious mug collector.)'")
|
106
|
+
collected = false
|
107
|
+
picked_mug = nil
|
108
|
+
while !collected do
|
109
|
+
choose do |menu|
|
110
|
+
menu.prompt = "> "
|
111
|
+
menu.shell = true
|
112
|
+
menu.confirm = true
|
113
|
+
green_mug = Item.get("Green Mug", @credentials)
|
114
|
+
red_mug = Item.get("Red Mug", @credentials)
|
115
|
+
blue_mug = Item.get("Blue Mug", @credentials)
|
116
|
+
menu.choice(green_mug.name, green_mug.description + " Level: " + green_mug.level.to_s) do |_command, details|
|
117
|
+
Inventory.add_to_desk(green_mug, @credentials)
|
118
|
+
collected = true
|
119
|
+
picked_mug = green_mug
|
120
|
+
say("'When this mug gets angry... You don't want to see it angry.', says Ash.")
|
121
|
+
end
|
122
|
+
menu.choice(red_mug.name, red_mug.description + " Level: " + red_mug.level.to_s) do |_command, details|
|
123
|
+
Inventory.add_to_desk(red_mug, @credentials)
|
124
|
+
collected = true
|
125
|
+
picked_mug = red_mug
|
126
|
+
say("'You're not too dissimilar to others, most people pick the red mug as well.', says Ash.")
|
127
|
+
end
|
128
|
+
menu.choice(blue_mug.name, blue_mug.description + " Level: " + blue_mug.level.to_s) do |_command, details|
|
129
|
+
Inventory.add_to_desk(blue_mug, @credentials)
|
130
|
+
collected = true
|
131
|
+
picked_mug = blue_mug
|
132
|
+
say("'Hey, my favourite colour is blue! Good choice newbie.', says Ash.")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
say("'Do you want to give a nickname to " + picked_mug.name.upcase + "?'")
|
137
|
+
choose do |menu|
|
138
|
+
menu.prompt = "> "
|
139
|
+
menu.choice(:yes) { say("'I was joking...', replies Ash.") }
|
140
|
+
menu.choices(:no) { say("You decided against nicknaming your mug.") }
|
141
|
+
menu.choices(:silence) { say("You remain silent.\nAsh smirks.") }
|
142
|
+
menu.default = :silence
|
143
|
+
end
|
144
|
+
|
145
|
+
say("'Wait!', exclaims Ash. 'Let's check out our mugs!'")
|
146
|
+
continue = ask("> [Hit Enter to continue] ")
|
147
|
+
say(".\n.\n.")
|
148
|
+
say("The Enter button loses 100HP and Ash wants to fight!")
|
149
|
+
continue = ask("> ")
|
150
|
+
say(".\n.\n.")
|
151
|
+
continue = ask("> ")
|
152
|
+
say("*BTFW* The Creator laughs. 'If all of this has gone over your head, I'm sincerely sorry. If it hasn't, then good on you.'")
|
153
|
+
continue = ask("> ")
|
154
|
+
say("*BTFW* 'First off, terrible writing I know. But go with it, it'll get worse.'")
|
155
|
+
continue = ask("> ")
|
156
|
+
say("*BTFW* 'Also, BTFW stands for Breaking the Fourth Wall. Not anything else...'")
|
157
|
+
continue = ask("> ")
|
158
|
+
say("*BTFW* 'Anyway, I just wanted to let you know about that mug you just received. If you sign in using our web application and go to your Inventory (or your Profile), you'll see that you have now added an item to your Desk. K bye.'")
|
159
|
+
continue = ask("> ")
|
160
|
+
say("'Anyway, ignore the Creator. They know nothing about unit testing or anything for that matter.' says Ash.")
|
161
|
+
say("'So enough with the chit chat, from now onwards, we're unit testing!'")
|
162
|
+
continue = ask("> ")
|
163
|
+
say("*BTFW* 'What Ash really means is that you'll be unit testing as well as collecting loot, unlocking achievements and going places!' exclaims the Creator. 'Okay, goodbye for real.'")
|
164
|
+
say("'Let's get to it!'")
|
165
|
+
say(".\n.\n.")
|
166
|
+
continue = ask("> ")
|
167
|
+
completed_beginning
|
168
|
+
end
|
169
|
+
|
170
|
+
def completed_beginning?
|
171
|
+
options = { headers: { "Content-Type" => "application/json" } }
|
172
|
+
url = NagaApi.BASE_URL + "users/beginning?authentication_token=" + @credentials[:authentication_token] + "&email=" + @credentials[:email]
|
173
|
+
response = HTTParty.get(url, options)
|
174
|
+
response.parsed_response["beginning"]
|
175
|
+
end
|
176
|
+
|
177
|
+
def completed_beginning
|
178
|
+
url = NagaApi.BASE_URL + "/users/beginning"
|
179
|
+
options = { headers: { "Content-Type" => "application/x-www-form-urlencoded" } }
|
180
|
+
options[:body] = "email=" + @credentials[:email] + "&authentication_token=" + @credentials[:authentication_token]
|
181
|
+
response = HTTParty.post(url, options)
|
182
|
+
if response["error"]
|
183
|
+
STDERR.puts(("\nError: " + response["error"]).colorize(:red))
|
184
|
+
STDERR.puts(("Unable to confirm completion of the beginning.").colorize(:red))
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def run
|
189
|
+
url = NagaApi.BASE_URL + "/users/run"
|
190
|
+
options = { headers: { "Content-Type" => "application/x-www-form-urlencoded" } }
|
191
|
+
options[:body] = "email=" + @credentials[:email] + "&authentication_token=" + @credentials[:authentication_token]
|
192
|
+
response = HTTParty.post(url, options)
|
193
|
+
if response["error"]
|
194
|
+
STDERR.puts(("\nError: " + response["error"]).colorize(:red))
|
195
|
+
elsif response["warning"]
|
196
|
+
runs = response["runs"]
|
197
|
+
max_runs = response["max_runs"]
|
198
|
+
level = response["level"]
|
199
|
+
if response["warning"] == "Runs available"
|
200
|
+
if response["level_up"]
|
201
|
+
puts "You just grew a level!".colorize(:black).colorize( :background => :green )
|
202
|
+
puts "You are now " + parsed_response["level"]["number"] + " and have " + parsed_response["level"]["xp"] + "."
|
203
|
+
end
|
204
|
+
puts "Level #{level["number"]} (#{level["name"]})".colorize(:blue)
|
205
|
+
puts "#{level["xp"]} XP / #{level["total_xp"]} XP".colorize(:green)
|
206
|
+
puts "You used up #{runs} / #{max_runs} energy bars today.".colorize(:magenta)
|
207
|
+
puts "=" *80
|
208
|
+
return true
|
209
|
+
else
|
210
|
+
puts "Level #{level["number"].to_s} (#{level["name"]})".colorize(:blue)
|
211
|
+
puts "#{level["xp"]} XP / #{level["total_xp"]} XP".colorize(:green)
|
212
|
+
puts "Sorry! You don't have anymore energy bars for today, you've reached your maximum amount of #{max_runs} energy bars. Come back tomorrow when you've regenerated to collect more loot!".colorize(:red)
|
213
|
+
return false
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def item_achievements(item)
|
219
|
+
@detector.bluebeard(item)
|
220
|
+
@detector.purple_rain(item)
|
221
|
+
@detector.i_am_legendary(item)
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Inventory
|
2
|
+
# public class methods
|
3
|
+
class << self
|
4
|
+
def add_to_desk(item, credentials)
|
5
|
+
url = NagaApi.BASE_URL + "inventory/desk/add"
|
6
|
+
options = { headers: { "Content-Type" => "application/x-www-form-urlencoded" } }
|
7
|
+
options[:body] = "email=" + credentials[:email] + "&authentication_token=" + credentials[:authentication_token] + "&item_id=" + item.id.to_s
|
8
|
+
response = HTTParty.post(url, options)
|
9
|
+
handle_add(response.parsed_response, item, "desk")
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(item, credentials)
|
13
|
+
url = NagaApi.BASE_URL + "inventory/add"
|
14
|
+
options = { headers: { "Content-Type" => "application/x-www-form-urlencoded" } }
|
15
|
+
options[:body] = "email=" + credentials[:email] + "&authentication_token=" + credentials[:authentication_token] + "&item_id=" + item.id.to_s
|
16
|
+
response = HTTParty.post(url, options)
|
17
|
+
handle_add(response.parsed_response, item, "backpack")
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def handle_add(parsed_response, item, storage)
|
23
|
+
if parsed_response["error"]
|
24
|
+
STDERR.puts(("\nError: " + parsed_response["error"] + "\n\n").colorize(:red))
|
25
|
+
elsif parsed_response["warning"] == "No desk space"
|
26
|
+
say("You received a " + item.name.upcase + "!")
|
27
|
+
say("But as you have no space on your desk, it's been added to your backpack instead.")
|
28
|
+
else
|
29
|
+
say("You received a " + item.name.upcase + " and added it to your " + storage + "!")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class Item
|
2
|
+
attr_accessor :id
|
3
|
+
attr_accessor :name
|
4
|
+
attr_accessor :description
|
5
|
+
attr_accessor :level
|
6
|
+
attr_accessor :colour
|
7
|
+
|
8
|
+
def initialize(id, name, description, level, colour)
|
9
|
+
@id = id
|
10
|
+
@name = name
|
11
|
+
@description = description
|
12
|
+
@level = level
|
13
|
+
@colour = colour
|
14
|
+
end
|
15
|
+
|
16
|
+
# public class methods
|
17
|
+
class << self
|
18
|
+
def all(credentials)
|
19
|
+
options = { headers: { "Content-Type" => "application/json" } }
|
20
|
+
url = NagaApi.BASE_URL + "items?" + "authentication_token=" + credentials[:authentication_token] + "&email=" + credentials[:email]
|
21
|
+
response = HTTParty.get(url, options)
|
22
|
+
items = {}
|
23
|
+
response.parsed_response["items"].each do |i|
|
24
|
+
item = Item.new(i["id"], i["name"], i["description"])
|
25
|
+
items[item.name] = item
|
26
|
+
end
|
27
|
+
items
|
28
|
+
end
|
29
|
+
|
30
|
+
def get(name, credentials)
|
31
|
+
options = { headers: { "Content-Type" => "application/json" } }
|
32
|
+
url = NagaApi.BASE_URL + "items/show/" + URI::encode(name) + "?authentication_token=" + credentials[:authentication_token] + "&email=" + credentials[:email]
|
33
|
+
response = HTTParty.get(url, options)
|
34
|
+
i = response.parsed_response["item"]
|
35
|
+
item = Item.new(i["id"], i["name"], i["description"], i["level"], i["colour"])
|
36
|
+
end
|
37
|
+
|
38
|
+
def drop(credentials)
|
39
|
+
options = { headers: { "Content-Type" => "application/json" } }
|
40
|
+
url = NagaApi.BASE_URL + "items/drop/?authentication_token=" + credentials[:authentication_token] + "&email=" + credentials[:email]
|
41
|
+
response = HTTParty.get(url, options)
|
42
|
+
i = response.parsed_response["item"]
|
43
|
+
if i
|
44
|
+
item = Item.new(i["id"], i["name"], i["description"], i["level"], i["colour"])
|
45
|
+
else
|
46
|
+
item = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def starter(credentials)
|
51
|
+
options = { headers: { "Content-Type" => "application/json" } }
|
52
|
+
url = NagaApi.BASE_URL + "items/starter?" + "authentication_token=" + credentials[:authentication_token] + "&email=" + credentials[:email]
|
53
|
+
response = HTTParty.get(url, options)
|
54
|
+
starter_items = {}
|
55
|
+
response.parsed_response["starter_items"].each do |i|
|
56
|
+
item = Item.new(i["id"], i["name"], i["description"])
|
57
|
+
starter_items[item.name] = item
|
58
|
+
end
|
59
|
+
starter_items
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_s
|
64
|
+
if self
|
65
|
+
colorized_name = self.name.upcase
|
66
|
+
case self.level
|
67
|
+
when 1
|
68
|
+
colorized_name = colorized_name.colorize(:white)
|
69
|
+
when 2
|
70
|
+
colorized_name = colorized_name.colorize(:green)
|
71
|
+
when 3
|
72
|
+
colorized_name = colorized_name.colorize(:blue)
|
73
|
+
when 4
|
74
|
+
colorized_name = colorized_name.colorize(:light_white)
|
75
|
+
when 5
|
76
|
+
colorized_name = colorized_name.colorize(:yellow)
|
77
|
+
end
|
78
|
+
say("You found a #{colorized_name}!")
|
79
|
+
say("It has a description: " + self.description + " Level: " + self.level.to_s)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class Location
|
2
|
+
attr_accessor :name
|
3
|
+
attr_accessor :description
|
4
|
+
attr_accessor :north
|
5
|
+
attr_accessor :east
|
6
|
+
attr_accessor :south
|
7
|
+
attr_accessor :west
|
8
|
+
|
9
|
+
def initialize(name, description, north, east, south, west)
|
10
|
+
@name = name
|
11
|
+
@description = description
|
12
|
+
@north = north
|
13
|
+
@east = east
|
14
|
+
@south = south
|
15
|
+
@west = west
|
16
|
+
end
|
17
|
+
|
18
|
+
# public class methods
|
19
|
+
class << self
|
20
|
+
def all
|
21
|
+
locations = []
|
22
|
+
sanctuary = Location.new(
|
23
|
+
"Sanctuary",
|
24
|
+
"A place you feel safe.",
|
25
|
+
Place.new("G-Mart", "A shop to buy things. Y'know buy tings."),
|
26
|
+
Place.new("Central Park", "A park in the centre of Sanctuary. Nearby is a cafe. Strange, there are 6 friends sitting on a sofa."),
|
27
|
+
Place.new("Sanctuary Museum", "A museum that includes the history of Sanctuary. Suprised?"),
|
28
|
+
Place.new("The Bench", "A bench on top of a hill where you can see everything. It's pretty so you go there a lot.")
|
29
|
+
)
|
30
|
+
city_of_the_bc = Location.new(
|
31
|
+
"City of the BC",
|
32
|
+
"A weird and wonderful city. It hides things because it cares. Not sure if that makes thing right...",
|
33
|
+
Place.new("Inside Out", "A club that makes you feel all the emotions."),
|
34
|
+
Place.new("Restaurant Name", "A restaurant where the owner could not think of a better name."),
|
35
|
+
Place.new("The Forest", "A forest with no goblins."),
|
36
|
+
Place.new("The Lake", "A lake with no sword stuck in the middle.")
|
37
|
+
)
|
38
|
+
locations.push(sanctuary)
|
39
|
+
locations.push(city_of_the_bc)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# public instance methods
|
44
|
+
def places
|
45
|
+
[self.north, self.east, self.south, self.west]
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
puts "You magically spawn to " + self.name + "."
|
50
|
+
puts "'You have arrived at " + self.name + ". Hope you have enjoyed your Fast Travel experience!'"
|
51
|
+
puts "North of you is " + self.north.name + " - " + self.north.description
|
52
|
+
puts "East of you is " + self.east.name + " - " + self.east.description
|
53
|
+
puts "South of you is " + self.south.name + " - " + self.south.description
|
54
|
+
puts "West of you is " + self.west.name + " - " + self.west.description
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Place
|
2
|
+
attr_accessor :name
|
3
|
+
attr_accessor :description
|
4
|
+
attr_accessor :loot
|
5
|
+
attr_accessor :interaction
|
6
|
+
|
7
|
+
def initialize(name, description)
|
8
|
+
@name = name
|
9
|
+
@description = description
|
10
|
+
end
|
11
|
+
|
12
|
+
# public instance methods
|
13
|
+
def to_s
|
14
|
+
puts "You arrive at " + self.name + "."
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class Achievement
|
2
|
+
attr_accessor :id
|
3
|
+
attr_accessor :name
|
4
|
+
attr_accessor :description
|
5
|
+
attr_accessor :xp
|
6
|
+
|
7
|
+
SPACE = " ".colorize(:yellow).colorize( :background => :black )
|
8
|
+
MAX_LENGTH = 70
|
9
|
+
PADDING = SPACE * 2
|
10
|
+
PADDING_LENGTH = 2
|
11
|
+
|
12
|
+
def initialize(id, name, description, xp, link, comment)
|
13
|
+
@id = id
|
14
|
+
@name = name
|
15
|
+
@description = description
|
16
|
+
@xp = xp
|
17
|
+
@link = link
|
18
|
+
@comment = comment
|
19
|
+
end
|
20
|
+
|
21
|
+
# public class methods
|
22
|
+
class << self
|
23
|
+
def locked_achievements(credentials)
|
24
|
+
options = { headers: { "Content-Type" => "application/json" } }
|
25
|
+
url = NagaApi.BASE_URL + "achievements?" + "authentication_token=" + credentials[:authentication_token] + "&email=" + credentials[:email]
|
26
|
+
response = HTTParty.get(url, options)
|
27
|
+
locked_achievements = {}
|
28
|
+
response.parsed_response["locked_achievements"].each do |locked_achievement|
|
29
|
+
achievement = Achievement.new(locked_achievement["id"], locked_achievement["name"], locked_achievement["description"], locked_achievement["xp"], locked_achievement["link"], locked_achievement["comment"])
|
30
|
+
locked_achievements[achievement.name] = achievement
|
31
|
+
end
|
32
|
+
locked_achievements
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# public instance methods
|
37
|
+
def unlock(credentials)
|
38
|
+
url = NagaApi.BASE_URL + "achievements/unlock"
|
39
|
+
options = { headers: { "Content-Type" => "application/x-www-form-urlencoded" } }
|
40
|
+
options[:body] = "email=" + credentials[:email] + "&authentication_token=" + credentials[:authentication_token] + "&achievement_id=" + self.id.to_s
|
41
|
+
response = HTTParty.post(url, options)
|
42
|
+
parsed_response = response.parsed_response
|
43
|
+
if parsed_response["error"]
|
44
|
+
STDERR.puts(("Error: " + parsed_response["error"]).colorize(:red))
|
45
|
+
else
|
46
|
+
self.to_s_unlock
|
47
|
+
if parsed_response["level_up"]
|
48
|
+
puts "You just grew a level!".colorize(:black).colorize( :background => :green )
|
49
|
+
puts "You are now Level #{parsed_response["level"]["number"].to_s} and have #{parsed_response["level"]["xp"].to_s} XP."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
puts @id
|
56
|
+
puts @name
|
57
|
+
puts @description
|
58
|
+
puts @xp
|
59
|
+
puts @link
|
60
|
+
puts @comment
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_s_unlock
|
64
|
+
puts SPACE * MAX_LENGTH
|
65
|
+
puts PADDING + "Achievement unlocked!".ljust(MAX_LENGTH-PADDING_LENGTH).colorize(:yellow).colorize( :background => :black )
|
66
|
+
puts PADDING + @name.ljust(MAX_LENGTH-PADDING_LENGTH).colorize(:yellow).colorize( :background => :black )
|
67
|
+
description = "> " + @description
|
68
|
+
puts PADDING + description.ljust(MAX_LENGTH-PADDING_LENGTH).colorize(:yellow).colorize( :background => :black )
|
69
|
+
xp = "> " + @xp.to_s + " XP"
|
70
|
+
if @comment && !@link
|
71
|
+
puts PADDING + @comment.ljust(MAX_LENGTH-PADDING_LENGTH).colorize(:yellow).colorize( :background => :black )
|
72
|
+
elsif @link && @comment
|
73
|
+
puts PADDING + @link.ljust(MAX_LENGTH-PADDING_LENGTH).colorize(:yellow).colorize( :background => :black )
|
74
|
+
puts PADDING + @comment.ljust(MAX_LENGTH-PADDING_LENGTH).colorize(:yellow).colorize( :background => :black )
|
75
|
+
end
|
76
|
+
puts PADDING + xp.ljust(MAX_LENGTH-PADDING_LENGTH).colorize(:yellow).colorize( :background => :black )
|
77
|
+
puts SPACE * MAX_LENGTH
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "minitest/naga"
|
3
|
+
require_relative "naga_api"
|
4
|
+
|
5
|
+
module Minitest
|
6
|
+
module Naga
|
7
|
+
class CLI < Thor
|
8
|
+
desc "about", "A little information about minitest-naga"
|
9
|
+
def about
|
10
|
+
puts "minitest-naga is created by Wen Ting Wang."
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "signout", "Sign out of Naga"
|
14
|
+
def signout
|
15
|
+
File.delete(NagaApi.FILE_PATH)
|
16
|
+
puts "Signed out."
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class Detector
|
2
|
+
def initialize(credentials)
|
3
|
+
@credentials = credentials
|
4
|
+
@locked_achievements = Achievement.locked_achievements(@credentials)
|
5
|
+
end
|
6
|
+
|
7
|
+
def my_first_time
|
8
|
+
achievement = @locked_achievements["My First Time"]
|
9
|
+
if achievement
|
10
|
+
achievement.unlock(@credentials)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def dressed_like_a_bat(count)
|
15
|
+
achievement = @locked_achievements["Dressed like a bat"]
|
16
|
+
if achievement
|
17
|
+
now = Time.now
|
18
|
+
start_time = Time.new(now.year, now.month, now.day, 22, 0, 0)
|
19
|
+
end_time = Time.new(now.year, now.month, now.day+1, 3, 59, 0)
|
20
|
+
if count == 237 && ((start_time..end_time).cover? Time.now)
|
21
|
+
achievement.unlock(@credentials)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def a_trip_to_the_whizz_palace(total_time)
|
27
|
+
achievement = @locked_achievements["A trip to the whizz palace"]
|
28
|
+
if achievement
|
29
|
+
if 300 <= total_time && total_time <= 600
|
30
|
+
achievement.unlock(@credentials)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def bluebeard(item)
|
36
|
+
achievement = @locked_achievements["Bluebeard"]
|
37
|
+
if achievement
|
38
|
+
if item.level == 3
|
39
|
+
achievement.unlock(@credentials)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def purple_rain(item)
|
45
|
+
achievement = @locked_achievements["Purple Rain"]
|
46
|
+
if achievement
|
47
|
+
if item.level == 4
|
48
|
+
achievement.unlock(@credentials)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def i_am_legendary(item)
|
54
|
+
achievement = @locked_achievements["I am Legendary"]
|
55
|
+
if achievement
|
56
|
+
if item.level == 5
|
57
|
+
achievement.unlock(@credentials)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def papyrus(count, failures, errors)
|
63
|
+
achievement = @locked_achievements["Papyrus"]
|
64
|
+
if achievement
|
65
|
+
if (count == 2009) && (failures == 0) && (errors == 0)
|
66
|
+
achievement.unlock(@credentials)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def cant_catch_em_all(count, failures)
|
72
|
+
achievement = @locked_achievements["Can't Catch 'Em All"]
|
73
|
+
if achievement
|
74
|
+
quarter = (count * 0.25).to_i
|
75
|
+
if (count >= 50) && (failures <= quarter)
|
76
|
+
achievement.unlock(@credentials)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def why_do_we_fall(count, failures)
|
82
|
+
achievement = @locked_achievements["Why do we fall? So we can learn to pick ourselves up."]
|
83
|
+
if achievement
|
84
|
+
if (count >= 2) && (failures == count)
|
85
|
+
achievement.unlock(@credentials)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class NagaApi
|
2
|
+
@@BASE_URL = "http://localhost:3000/api/v1/"
|
3
|
+
# @@BASE_URL = "https://naga-unit-testing.herokuapp.com/api/v1/"
|
4
|
+
@@FILE_PATH = File.join(Dir.home, ".minitest_naga")
|
5
|
+
|
6
|
+
attr_reader :credentials
|
7
|
+
attr_reader :email
|
8
|
+
attr_reader :authentication_token
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@options = { headers: { "Content-Type" => "application/x-www-form-urlencoded" } }
|
12
|
+
@authenticated = false
|
13
|
+
if File.file?(@@FILE_PATH)
|
14
|
+
@credentials = eval(File.read(@@FILE_PATH))
|
15
|
+
validate(@credentials)
|
16
|
+
else
|
17
|
+
authenticate
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.BASE_URL
|
22
|
+
@@BASE_URL
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.FILE_PATH
|
26
|
+
@@FILE_PATH
|
27
|
+
end
|
28
|
+
|
29
|
+
def credentials
|
30
|
+
@credentials = { email: @email, authentication_token: @authentication_token }
|
31
|
+
end
|
32
|
+
|
33
|
+
def authenticated?
|
34
|
+
@authenticated
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def authenticate
|
40
|
+
cli = HighLine.new
|
41
|
+
email = cli.ask "Enter your email: "
|
42
|
+
password = cli.ask("Enter your password: ") { |q| q.echo = false }
|
43
|
+
url = @@BASE_URL + "sessions"
|
44
|
+
options = @options
|
45
|
+
options[:body] = "email=" + email + "&password=" + password
|
46
|
+
response = HTTParty.post(url, options)
|
47
|
+
parsed_response = response.parsed_response
|
48
|
+
if parsed_response["error"]
|
49
|
+
STDERR.puts(("Error: " + parsed_response["error"]).colorize(:red))
|
50
|
+
@authenticated = false
|
51
|
+
authenticate
|
52
|
+
else
|
53
|
+
puts "Authentication successful".colorize(:green)
|
54
|
+
f = File.open(@@FILE_PATH, "w")
|
55
|
+
f.write(parsed_response)
|
56
|
+
f.close
|
57
|
+
@email = parsed_response["email"]
|
58
|
+
@authentication_token = parsed_response["authentication_token"]
|
59
|
+
@authenticated = true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def validate(credentials)
|
64
|
+
url = @@BASE_URL + "sessions/validate"
|
65
|
+
options = @options
|
66
|
+
options[:body] = "email=" + credentials["email"] + "&authentication_token=" + credentials["authentication_token"]
|
67
|
+
response = HTTParty.post(url, options)
|
68
|
+
parsed_response = response.parsed_response
|
69
|
+
if parsed_response["error"]
|
70
|
+
STDERR.puts(("Error: " + parsed_response["error"]).colorize(:red))
|
71
|
+
@authenticated = false
|
72
|
+
authenticate
|
73
|
+
else
|
74
|
+
@authenticated = true
|
75
|
+
@email = parsed_response["email"]
|
76
|
+
@authentication_token = parsed_response["authentication_token"]
|
77
|
+
puts "Signed in as " + @email
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|