monkeymusic 0.0.11 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +401 -0
- data/bin/monkeymusic +2 -2
- data/bin/monkeymusic-browser +6 -0
- data/levels/demo_level.rb +5 -5
- data/levels/testlevel.rb +6 -6
- data/lib/monkey_music.rb +0 -1
- data/lib/monkey_music/metadata/track.rb +3 -3
- data/lib/monkey_music/player.rb +8 -4
- data/lib/monkey_music/runner.rb +12 -23
- data/lib/monkey_music/ui/browser.rb +5 -3
- data/lib/monkey_music/ui/console.rb +1 -1
- data/lib/monkey_music/units/monkey.rb +2 -2
- data/lib/monkey_music/units/track.rb +5 -5
- data/lib/monkey_music/units/user.rb +3 -3
- data/lib/monkey_music_generate/runner.rb +7 -6
- data/lib/monkey_music_generate/score_system.rb +7 -7
- data/users/demo_user.yaml +162 -162
- metadata +4 -4
- data/README.markdown +0 -38
- data/demo_player +0 -98
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NTE5MDBiNmY2YzUxN2IxOGRjODJlY2RjZmY1NjJkM2IwMGEwNDgxYw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ODljNDQ5YzdjNjg3ZGNkOWQzOTYxZTk3MjRiY2JlYTYzNjliNzUzNg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MmFiNzI1ZTEyZTVmMWFiZDIyYjhlMzk2MTYwNzdjNTUxZTUwYzJjZjMwNzJl
|
10
|
+
ZmU5ZmYwMmIxMWE2NDU3OGM5NWJiYzFiZGIzYmY2ZmIyYTEyMDdiMDdlYjQz
|
11
|
+
OWNhZDJlNThkMGJmODVlYTQ3ZDJjMTM0NGFiOTg2NWQ5ZGRmY2Q=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YjhjYjUwN2IxYTM1YTk0M2ZkNzRjNTFjMjIxYzZlZDAwMTc4MGU1ZDE5MWE0
|
14
|
+
ZDczMTE4YjAxMjQ5ZDJmYmFhNzZmMmE2Yzc2NzViM2MwMmRlMDZkMDlhMWZh
|
15
|
+
MDRjYzA3OGJjMmFmNGRkYmUxODdkMWM1YTZiNTFjNjNiNjQyOTQ=
|
data/README.md
ADDED
@@ -0,0 +1,401 @@
|
|
1
|
+
Monkey Music Challenge
|
2
|
+
======================
|
3
|
+
{: .logo}
|
4
|
+
|
5
|
+
Introduction
|
6
|
+
------------
|
7
|
+
|
8
|
+
The Spotify backend is consists of a multitude of individual services. One such service is the music recommendation service, which is responsible for finding and recommending new tracks to Spotify users, according to their music taste.
|
9
|
+
|
10
|
+
The music recommendation service has lately been getting some pretty negative feedback from users. The word out on Twitter is that even monkeys could find better music recommendations!
|
11
|
+
|
12
|
+
Therefore, upper management has made an informed decision that the next version of the music recommendation service shall be operated entirely by monkeys. As product manager for the music recommendation service, your job is to make sure that the monkeys do a good job.
|
13
|
+
|
14
|
+
You have therefore decided to write a computer program that helps monkeys find good track recommendations for Spotify users.
|
15
|
+
|
16
|
+
This is all entirely fictional of course.
|
17
|
+
{: .tip}
|
18
|
+
|
19
|
+
Task summary
|
20
|
+
------------
|
21
|
+
|
22
|
+
The task consists of implementing a program to play the Monkey Music game. The goal of the game is to score points by gathering track recommendations and giving them to a Spotify user.
|
23
|
+
|
24
|
+
The game
|
25
|
+
--------
|
26
|
+
|
27
|
+
Every game of Monkey Music is broken up into a number of turns.
|
28
|
+
|
29
|
+
Every turn, your program will be executed and fed information about the current state of the level by reading from `stdin`. Your program responds by printing one command to `stdout`. The command decides what your monkey does during the current turn.
|
30
|
+
|
31
|
+
Fate decides the order in which monkeys execute their commands in a turn.
|
32
|
+
{: .tip}
|
33
|
+
|
34
|
+
Before every turn, execution of your program starts. After every turn, execution of your program stops.
|
35
|
+
|
36
|
+
Rules
|
37
|
+
-----
|
38
|
+
|
39
|
+
### Scoring
|
40
|
+
|
41
|
+
Your monkey will pick up tracks and deliver them to a user.
|
42
|
+
|
43
|
+
When a track is delivered, you will recieve a score according to how well the track fits the music taste of the user. The player with the highest score at the end of the game will be the winner.
|
44
|
+
|
45
|
+
You should try to get as high a score as possible.
|
46
|
+
{. tip}
|
47
|
+
|
48
|
+
### Turn limit
|
49
|
+
|
50
|
+
Every game is played for a limited amount of turns. This limit is different for different levels.
|
51
|
+
|
52
|
+
The game ends when the turn limit is reached.
|
53
|
+
|
54
|
+
### Time limit
|
55
|
+
|
56
|
+
Every time your program is executed, the execution time will be measured. Every level has a total time limit, that your program should not exceed.
|
57
|
+
|
58
|
+
If your execution time reaches the time limit, your monkey will run out of energy and fall asleep for `5` turns. Afte sleeping for `5` turns, the remaining execution time of your program will be replenished.
|
59
|
+
|
60
|
+
### Carrying capacity
|
61
|
+
|
62
|
+
The number of tracks your monkey can pick up and hold at any given time is called carrying capacity.
|
63
|
+
|
64
|
+
The carrying capacity of your monkey is different for every level.
|
65
|
+
|
66
|
+
Level layout
|
67
|
+
------------
|
68
|
+
|
69
|
+
The level is a `n x m` grid of cells. It is sent to the standard input of your program.
|
70
|
+
|
71
|
+
Each cell contains one of the following things:
|
72
|
+
|
73
|
+
### Monkeys
|
74
|
+
|
75
|
+
* ASCII: `M[id]`
|
76
|
+
|
77
|
+
You, and your competitors each have your own monkey to control.
|
78
|
+
Every monkey is identified by a unique numerical id.
|
79
|
+
|
80
|
+
### Walls
|
81
|
+
|
82
|
+
* ASCII: `#`
|
83
|
+
|
84
|
+
Walls are inanimate objects that monkeys cannot pass through.
|
85
|
+
|
86
|
+
### Tracks
|
87
|
+
|
88
|
+
* ASCII: `[URI]`
|
89
|
+
|
90
|
+
Tracks are identified by their unique Spotify URI. Every track URI starts with `spotify:track:`, followed by `22` alphanumerical characters.
|
91
|
+
|
92
|
+
Example: `spotify:track:5H85hOp2oMlhMh9JlkdJP2`.
|
93
|
+
|
94
|
+
Tracks can be picked up and carried around by monkeys.
|
95
|
+
|
96
|
+
### The User
|
97
|
+
|
98
|
+
* ASCII: `U`
|
99
|
+
|
100
|
+
The user is where monkeys deliver their track recommendations. Monkeys are
|
101
|
+
scored for every track delivered to the user, according to how well the track fits the user's music taste.
|
102
|
+
|
103
|
+
### Empty
|
104
|
+
|
105
|
+
* ASCII: `[SPACE]`
|
106
|
+
|
107
|
+
Nothing to do here.
|
108
|
+
|
109
|
+
A cell can only contain one thing at any time.
|
110
|
+
{: .tip}
|
111
|
+
|
112
|
+
User toplists
|
113
|
+
-------------
|
114
|
+
|
115
|
+
How well tracks match the music taste of a user is decided by the user's toplists.
|
116
|
+
|
117
|
+
Every Spotify user has a track toplist, an album toplist and an artist toplist. Every entry in a toplist is a comma-separated string of metadata.
|
118
|
+
|
119
|
+
The toplists are sent to the standard input of your program on the following formats:
|
120
|
+
|
121
|
+
### Track toplist
|
122
|
+
|
123
|
+
First an integer `n`, followed by `n` lines of track metadata entries.
|
124
|
+
|
125
|
+
n
|
126
|
+
track,album,artist,year
|
127
|
+
track,album,artist,year
|
128
|
+
...
|
129
|
+
|
130
|
+
### Album toplist
|
131
|
+
|
132
|
+
First an integer `n`, followed by `n` lines of album metadata entries.
|
133
|
+
|
134
|
+
[n]
|
135
|
+
album,artist,year
|
136
|
+
album,artist,year
|
137
|
+
...
|
138
|
+
|
139
|
+
### Artist toplist
|
140
|
+
|
141
|
+
First an integer `n`, followed by `n` lines of artist metadata entries.
|
142
|
+
|
143
|
+
n
|
144
|
+
artist
|
145
|
+
artist
|
146
|
+
...
|
147
|
+
|
148
|
+
### Disliked artist toplist
|
149
|
+
|
150
|
+
You will also receive a list of artists that the user does not like.
|
151
|
+
|
152
|
+
First an integer `n`, followed by `n` lines of artist entries.
|
153
|
+
|
154
|
+
n
|
155
|
+
artist
|
156
|
+
artist
|
157
|
+
...
|
158
|
+
|
159
|
+
Spotify does not actually keep toplists of disliked artists. ;)
|
160
|
+
{: .tip}
|
161
|
+
|
162
|
+
Score system
|
163
|
+
------------
|
164
|
+
|
165
|
+
Each track is scored according to the user toplists by placing it into 1 out of 5 score tiers.
|
166
|
+
|
167
|
+
There are three positive tiers: `1`, `2` and `3`. There are two negative tiers, `-1` and `-2`
|
168
|
+
|
169
|
+
The following criteria decide which tier a track belongs to:
|
170
|
+
|
171
|
+
### Tier -2: Disliked artist
|
172
|
+
|
173
|
+
The track artist is in the user's disliked artist toplist. To recommend one of
|
174
|
+
these tracks is an epic fail.
|
175
|
+
|
176
|
+
### Tier -1: Played to death
|
177
|
+
|
178
|
+
The track is already in the user's track toplist. There is not much point
|
179
|
+
in recommending it.
|
180
|
+
|
181
|
+
### Tier += 1: Favorite artist
|
182
|
+
|
183
|
+
The track artist is in the user's artist toplist.
|
184
|
+
|
185
|
+
### Tier += 1: Favorite album
|
186
|
+
|
187
|
+
If track album in the user's album toplist.
|
188
|
+
|
189
|
+
### Tier += 1: Favorite decade
|
190
|
+
|
191
|
+
The year of the track belongs to the user's top decade.
|
192
|
+
|
193
|
+
This is an interesting one. Every user has a top decade, which is the decade that is most prominent in the user's track toplist and album toplist.
|
194
|
+
|
195
|
+
### Tally
|
196
|
+
|
197
|
+
Your track will be scored according to it's tier:
|
198
|
+
|
199
|
+
**Tier -2:** -16 points
|
200
|
+
|
201
|
+
**Tier -1:** -4 points
|
202
|
+
|
203
|
+
**Tier 1:** 4 points
|
204
|
+
|
205
|
+
**Tier 2:** 16 points
|
206
|
+
|
207
|
+
**Tier 3:** 64 points
|
208
|
+
|
209
|
+
Tier 3 tracks are obviously very valuable, so be on the lookout for these.
|
210
|
+
{: .tip}
|
211
|
+
|
212
|
+
Game progression
|
213
|
+
----------------
|
214
|
+
|
215
|
+
### Initialization phase
|
216
|
+
|
217
|
+
The game consists of two different phases.
|
218
|
+
|
219
|
+
The first phase is the initialization phase, it occurs once every game.
|
220
|
+
|
221
|
+
During the initialization phase, your program will be given information about the level that will be useful during the entire course of the game.
|
222
|
+
|
223
|
+
The information that can be read from `stdin` during the `init` phase is:
|
224
|
+
|
225
|
+
INIT\n
|
226
|
+
M[id]\n
|
227
|
+
[WIDTH]\n
|
228
|
+
[HEIGHT]\n
|
229
|
+
[TURN LIMIT]\n
|
230
|
+
[n]\n
|
231
|
+
[TRACK],[ALBUM],[ARTIST],[YEAR]\n
|
232
|
+
[n]\n
|
233
|
+
[ALBUM],[ARTIST],[YEAR]\n
|
234
|
+
[n]\n
|
235
|
+
[ARTIST]\n
|
236
|
+
[n]\n
|
237
|
+
[ARTIST]\n
|
238
|
+
|
239
|
+
* The string `"INIT"`
|
240
|
+
* The id of your monkey
|
241
|
+
* The `width` of the map
|
242
|
+
* The `height` of the map
|
243
|
+
* The `turn limit` of the game
|
244
|
+
* The number of entries in the user's track toplist
|
245
|
+
* The track toplist entries
|
246
|
+
* The number of entries in the user's album toplist
|
247
|
+
* The album toplist
|
248
|
+
* The number of entries in the user's artist toplist
|
249
|
+
* The artist toplist
|
250
|
+
* The number of entries in the user's disliked artist toplist
|
251
|
+
* The disliked artist toplist
|
252
|
+
|
253
|
+
After the initialization phase, execution of your program will stop until the next phase.
|
254
|
+
|
255
|
+
Make sure to keep the data from the initialization phase in a persistent cache!
|
256
|
+
{: .tip}
|
257
|
+
|
258
|
+
### Turn phases
|
259
|
+
|
260
|
+
After the initialization phase, a number of turn phases will follow.
|
261
|
+
|
262
|
+
The total number of turn phases is decided by the turn limit of the level.
|
263
|
+
|
264
|
+
The information that can be read from `stdin` during a turn phase is:
|
265
|
+
|
266
|
+
TURN\n
|
267
|
+
M[ID]\n
|
268
|
+
[TURN NUMBER]\n
|
269
|
+
[REMAINING CAPACITY]\n
|
270
|
+
[REMAINING TIME]\n
|
271
|
+
[n]\n
|
272
|
+
[URI],[TRACK],[ALBUM],[ARTIST],[YEAR]\n
|
273
|
+
[LEVEL]\n
|
274
|
+
|
275
|
+
* The string `"TURN"`
|
276
|
+
* The id of your monkey
|
277
|
+
* The turn number
|
278
|
+
* The remaining carrying capacity of your monkey
|
279
|
+
* The remaining execution time of your program
|
280
|
+
* The number of available metadata lookup results
|
281
|
+
* Your metadata lookup results from the previous turn
|
282
|
+
* The current state of the level
|
283
|
+
|
284
|
+
After reading the turn information from `stdin`, your program will print a command for your monkey to `stdout`.
|
285
|
+
|
286
|
+
Monkey commands
|
287
|
+
---------------
|
288
|
+
|
289
|
+
Commands are sent from the standard output of your program.
|
290
|
+
In each turn of the game, every monkey executes one command.
|
291
|
+
|
292
|
+
Commands which the monkeys can execute are:
|
293
|
+
|
294
|
+
[MOVE] | [METADATA LOOKUP] | B,[COMMAND],[COMMAND],[COMMAND]
|
295
|
+
|
296
|
+
### Move
|
297
|
+
|
298
|
+
You can command the monkey to move in the four cardinal directions using
|
299
|
+
the commands:
|
300
|
+
|
301
|
+
W
|
302
|
+
|
303
|
+
Moves the monkey one cell to the left.
|
304
|
+
|
305
|
+
E
|
306
|
+
|
307
|
+
Moves the monkey one cell to the right.
|
308
|
+
|
309
|
+
N
|
310
|
+
|
311
|
+
Moves the monkey one cell up.
|
312
|
+
|
313
|
+
S
|
314
|
+
|
315
|
+
Moves the monkey one cell down.
|
316
|
+
|
317
|
+
Trying to move to an already occupied cell will casue the monkey to stand
|
318
|
+
still for the duration of the round.
|
319
|
+
{: .tip}
|
320
|
+
|
321
|
+
### Metadata lookup
|
322
|
+
|
323
|
+
You can lookup the metadata of a track on the level by issuing a metadata
|
324
|
+
lookup command:
|
325
|
+
|
326
|
+
spotify:track:......................
|
327
|
+
|
328
|
+
You will recieve the result of the metadata lookup the following turn.
|
329
|
+
|
330
|
+
Your monkey must every turn choose between moving and looking up the metadata of a track!
|
331
|
+
{: .tip}
|
332
|
+
|
333
|
+
### Boost
|
334
|
+
|
335
|
+
B,[COMMAND],[COMMAND],[COMMAND]
|
336
|
+
|
337
|
+
Once every game, the monkey can issue a boost command and then issue three other comma separated commands during the same turn.
|
338
|
+
|
339
|
+
You can only issue the boost command once every game. Choose wisely!
|
340
|
+
{: .tip}
|
341
|
+
|
342
|
+
The turn input after having issued this command:
|
343
|
+
|
344
|
+
B,W,spotify:track:5H85hOp2oMlhMh9JlkdJP2,spotify:track:5H85hOp2oMlhMh9JlkdJP2
|
345
|
+
|
346
|
+
could look like:
|
347
|
+
|
348
|
+
TURN
|
349
|
+
10
|
350
|
+
M1
|
351
|
+
1
|
352
|
+
4529
|
353
|
+
2
|
354
|
+
spotify:track:5H85hOp2oMlhMh9JlkdJP2,TODO,TODO,TODO,TODO
|
355
|
+
spotify:track:5H85hOp2oMlhMh9JlkdJP2,TODO,TODO,TODO,TODO
|
356
|
+
|
357
|
+
### Picking up tracks
|
358
|
+
|
359
|
+
When standing next to a track and executing a move command toward the track, your monkey will remain in the same cell and pick up the track. If the carrying capacity of your monkey is maxed out, nothing will happen.
|
360
|
+
|
361
|
+
Once a track is picked up, there is no way to get rid of it but to deliver it.
|
362
|
+
{: .tip}
|
363
|
+
|
364
|
+
### Delivering tracks
|
365
|
+
|
366
|
+
When standing next to the user and issuing a move command toward the track, your monkey will remain in the same cell and deliver all currently carried tracks to the user. You will then recieve score according to the score system.
|
367
|
+
|
368
|
+
Be careful about picking up negative tier tracks. You'll have to deliver them.
|
369
|
+
{: .tip}
|
370
|
+
|
371
|
+
Requirements
|
372
|
+
------------
|
373
|
+
|
374
|
+
Monkey Music depends on Ruby 1.9.
|
375
|
+
|
376
|
+
If your OS does not provide it by default, you can always get it using RVM.
|
377
|
+
|
378
|
+
Installation
|
379
|
+
------------
|
380
|
+
|
381
|
+
To install the challenge runtime:
|
382
|
+
|
383
|
+
> gem install monkeymusic
|
384
|
+
|
385
|
+
To get started quickly:
|
386
|
+
|
387
|
+
> monkeymusic demo
|
388
|
+
|
389
|
+
To see something on the screen:
|
390
|
+
|
391
|
+
> monkeymusic -p demo_player
|
392
|
+
|
393
|
+
You can probably learn a lot about the game from reading the `demo_player`.
|
394
|
+
|
395
|
+
Handing in
|
396
|
+
----------
|
397
|
+
|
398
|
+
Your competition entry is to be handed in as a zip archive containing
|
399
|
+
everything needed to run your program.
|
400
|
+
|
401
|
+
When unpacked, your program should be runned through an executable file called `runme`.
|
data/bin/monkeymusic
CHANGED
data/levels/demo_level.rb
CHANGED
@@ -4,11 +4,11 @@ time_limit 20000
|
|
4
4
|
|
5
5
|
legend "1" => Monkey.player(1),
|
6
6
|
"2" => Monkey.player(2),
|
7
|
-
"X" => Track.
|
8
|
-
"x" => Track.
|
9
|
-
"l" => Track.
|
10
|
-
"t" => Track.
|
11
|
-
"T" => Track.
|
7
|
+
"X" => Track.tier(-2),
|
8
|
+
"x" => Track.tier(-1),
|
9
|
+
"l" => Track.tier(1),
|
10
|
+
"t" => Track.tier(2),
|
11
|
+
"T" => Track.tier(3),
|
12
12
|
"U" => User,
|
13
13
|
"#" => Wall
|
14
14
|
|