/
api.py
139 lines (124 loc) · 5.94 KB
/
api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# TODO: Fix up get get history so that it returns a game state with each guess
""" Creation of the Hangman API. """
import endpoints
from protorpc import remote, messages
from game import guess, random_word
from utils import get_by_urlsafe
from model import (User, Game, Score,
StringMessage, GameForm, GameList, ScoreTable, HistoryMessage)
USER_REQUEST = endpoints.ResourceContainer(
user_name=messages.StringField(1),
email_address=messages.StringField(2)
)
MOVE_REQUEST = endpoints.ResourceContainer(
urlsafe_game_key=messages.StringField(1),
guess=messages.StringField(2)
)
NEW_GAME_REQUEST = endpoints.ResourceContainer(
user_name=messages.StringField(1))
GAME_REQUEST = endpoints.ResourceContainer(key=messages.StringField(1))
SCORE_REQUEST = endpoints.ResourceContainer(
number_of_results=messages.IntegerField(1))
@endpoints.api(name='hangman', version='v1')
class HangmanAPI(remote.Service):
"""Hangman API"""
@endpoints.method(USER_REQUEST, StringMessage, path='user',
http_method='POST', name='create_new_user')
def create_user(self, request):
"""Create a new user for Hangman"""
if User.query(User.user_name == request.user_name).get():
raise endpoints.ConflictException(
"Try again with a new handle, that one is taken.")
user = User(user_name=request.user_name,
email_address=request.email_address)
user.put()
return StringMessage(message="Welcome to Hangman, {}".
format(request.user_name))
@endpoints.method(NEW_GAME_REQUEST, GameForm, path='game',
http_method='POST', name='create_game')
def create_game(self, request):
"""Creates a new game for Hangman users"""
user = User.query(User.user_name == request.user_name).get()
if not user:
raise endpoints.NotFoundException('User does not exist')
game = Game(user_name=user.key, target=random_word())
game.put()
return game.to_form()
@endpoints.method(MOVE_REQUEST, GameForm,
path="game/{urlsafe_game_key}", http_method='PUT',
name="guess_a_letter")
def guess_a_letter(self, request):
"""Allows user to guess at the secret word"""
game = get_by_urlsafe(request.urlsafe_game_key, Game)
if game.over == True:
raise endpoints.BadRequestException("GAME HAS ENDED")
if not request.guess:
raise endpoints.BadRequestException(
"You must guess a letter, word, or phrase")
guess(game, request.guess)
return game.to_form()
@endpoints.method(SCORE_REQUEST, ScoreTable, path="scores",
http_method="GET", name="get_high_scores")
def get_high_scores(self, request):
"""Returns a list of the high scores"""
limit = request.number_of_results
if limit and limit < 0:
raise endpoints.BadRequestException(
"Please request a positive number of results")
if limit and limit > 0:
scores = Score.query().order(-Score.score).fetch(limit=limit)
else:
scores = Score.query().order(-Score.score)
return ScoreTable(items=[score.to_form() for score in scores])
@endpoints.method(USER_REQUEST, ScoreTable,
path="scores/{user_name}", http_method="GET",
name="get_user_scores")
def get_user_scores(self, request):
"""Returns the users top 5 scores"""
user = User.query(User.user_name == request.user_name).get()
if not user:
raise endpoints.NotFoundException("That user doesn't exist")
scores = Score.query(user.key == Score.user_name).order(-Score.score)
return ScoreTable(items=[score.to_form() for score in scores])
@endpoints.method(USER_REQUEST, GameList, path="games/{user_name}",
http_method="GET", name="get_user_games")
def get_user_games(self, request):
"""Retrieves all active games for a given user"""
user = User.query(User.user_name == request.user_name).get()
if not user:
raise endpoints.NotFoundException("That user does not exist")
games = Game.query(user.key == Game.user_name).filter(
Game.over == False)
return GameList(games=[game.to_form() for game in games])
@endpoints.method(GAME_REQUEST, StringMessage,
path="games/delete/{key}", http_method="DELETE",
name="cancel_game")
def cancel_game(self, request):
"""Cancels a given open game"""
game = get_by_urlsafe(request.key, Game)
if not game:
raise endpoints.NotFoundException("Game does not exist")
if game.over:
raise endpoints.ForbiddenException(
"You cannot cancel a completed game")
else:
game.key.delete()
return StringMessage(message="Game deleted!")
@endpoints.method(response_message=ScoreTable, path="rankings",
http_method="GET", name="get_user_rankings")
def get_user_rankings(self, request):
"""Returns an ordered list of users with best win-loss differential"""
games = Game.query(projection=[Game.user_name], distinct=True)
items = [game.to_score() for game in games]
items.sort(key=lambda x: x.score, reverse=True)
return ScoreTable(items=items)
@endpoints.method(GAME_REQUEST, HistoryMessage, path="/games/history/{key}",
http_method="GET", name="get_game_history")
def get_game_history(self, request):
"""Returns a list of the users guesses"""
game = get_by_urlsafe(request.key, Game)
if not game:
raise endpoints.NotFoundException("Game does not exist")
moves = game.history_to_form()
return HistoryMessage(history=[move for move in moves])
api = endpoints.api_server([HangmanAPI])