-
Notifications
You must be signed in to change notification settings - Fork 2
/
app.py
253 lines (211 loc) · 8.91 KB
/
app.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
from itertools import islice
from flask import Flask, request, session, render_template, redirect
import requests
import json
import jinja2
import random
import api_utils
import game_utils
import dateutil.parser as parser
from pahmasettings import FLASK_SESSION_SECRET
# import model # for database. not in use yet
# Number of objects to return from search
ROWS = 100
NUM_ARTIFACTS_IN_EXHIBIT = 5
SCORE_SCALE = 1000
app = Flask(__name__)
app.config.update(
SECRET_KEY=FLASK_SESSION_SECRET, # for session cookie
# SESSION_COOKIE_HTTPONLY = False # put this back if things break!
)
app.jinja_env.undefined = jinja2.StrictUndefined
# Data structure to capture results from Hearst API queries
class Artifact_card:
def __init__(self):
name = None
fcp = None
prod_date_begin = None
prod_date_end = None
prod_date_s = None
asso_cult = None
object_id = None
img_id = None
img_URL = None
description = None
obj_file_code = None
museum_num = None
###
# Constructs Hearst API queries and returns results.
# q = search field and type (blob_ss ensures only objects with images)
# fl = filter for returned things from search
# rows = number of objects to return
###
def query_constructor(query_terms='objproddate_begin_dt:[* TO *]' +
'AND objproddate_end_dt:[* TO *]' +
'AND blob_ss:[* TO *]',
search_filter="objname_s, objfcp_s," +
"objproddate_begin_dt, objproddate_end_dt," +
"objproddate_s, objassoccult_ss, id, blob_ss," +
"objdescr_s, objfilecode_ss, objmusno_s",
max_results=100):
return api_utils.query(q=query_terms,
fl=search_filter,
rows=max_results)['response']
# Returns artifact card object instance
def make_artifact_card(result, index):
card = Artifact_card()
card.name = result[u'docs'][index].get(u'objname_s')
card.fcp = result[u'docs'][index].get(u'objfcp_s')
# Process begin and end dates into just the year
prod_date_begin = result[u'docs'][index].get(u'objproddate_begin_dt')
prod_date_end = result[u'docs'][index].get(u'objproddate_end_dt')
card.prod_date_begin = parser.parse(prod_date_begin).year
card.prod_date_end = parser.parse(prod_date_end).year
# Get the rest of the artifact info...
card.prod_date_s = result[u'docs'][index].get(u'objproddate_s')
card.asso_cult = result[u'docs'][index].get(u'objassoccult_ss', [])
card.object_id = result[u'docs'][index].get(u'id')
card.img_id = result[u'docs'][index].get(u'blob_ss')
card.img_URL = api_utils.imagequery(id=result[u'docs'][index][u'blob_ss'][0],
derivative="Medium")
card.description = result[u'docs'][index].get(u'objdescr_s')
card.obj_file_code = result[u'docs'][index].get(u'objfilecode_ss')
card.museum_num = result[u'docs'][index].get(u'objmusno_s')
return card
# Returns a random artifact card
def get_random_artifact():
result = query_constructor(max_results=ROWS)
rand_index = random.randint(0, len(result[u'docs'])-1)
print "NUMBER OF RESULTS: ", len(result[u'docs']) # debug
card = make_artifact_card(result, rand_index)
return card
# Returns a list of random artifact cards
def get_random_artifacts():
result = query_constructor(max_results=ROWS)
#print "NUMBER OF RESULTS: ", len(result[u'docs']) # debug
cards = list()
indexes = list()
for x in range(0,NUM_ARTIFACTS_IN_EXHIBIT):
rand_index = random.randint(0, len(result[u'docs'])-1)
while rand_index in indexes:
rand_index = random.randint(0, len(result[u'docs'])-1)
indexes.append(rand_index)
cards.append(make_artifact_card(result, rand_index))
return cards
# Returns artifact card with specific museum_num
def get_artifact_by_museum_num(museum_num):
result = query_constructor(query_terms=u'objmusno_s:%s' % museum_num)
card = make_artifact_card(result, 0)
return card
# Turns an artifact card object instance into something JSON serializable
# and can be sent in an HTTP response
def art_to_dict(art_obj):
result = {}
result['name'] = art_obj.name
result['fcp'] = art_obj.fcp
result['prod_date_begin'] = art_obj.prod_date_begin
result['prod_date_end'] = art_obj.prod_date_end
result['prod_date_s'] = art_obj.prod_date_s
result['assoccult'] = art_obj.asso_cult
result['object_id'] = art_obj.object_id
result['img_id'] = art_obj.img_id
result['img_URL'] = art_obj.img_URL
result['description'] = art_obj.description
result['obj_file_code'] = art_obj.obj_file_code
result['museum_num'] = art_obj.museum_num
return result
# ==== ROUTES (aka CONTROLLERS / HANDLERS) ===
# oh lookie! a session cookie! (use this to store player info?)
# set up session cookie with some default fields when the user first visits the app.
@app.before_first_request
def setup_session():
session['game'] = {'score': 0, 'player_name': None, 'prev_cards': {}, 'current_card': None}
print "SETTING UP SESSION", session
# TODO: somewhere else in the app, allow user to put their name and record their score.
# Optionally, we can save their final score to a real database and show a leaderboard.
@app.route('/test', methods=['GET'])
def test():
return render_template('game.html')
# Resets the session cookie before starting a new game.
@app.route('/reset_session', methods=['GET'])
def reset():
session['game'] = {'score': 0, 'player_name': None, 'prev_cards': {}, 'current_card': None}
print "RESET", session
return redirect('/')
# The main page
@app.route('/', methods=['GET'])
def hello_world():
session['game'] = session.get('game', {'score': 0, 'player_name': None, 'prev_cards': {}, 'current_card': None})
if session['game'].get('current_card') is None:
card = get_random_artifact()
session['game']['current_card'] = card.museum_num
print "GOT FIRST CARD", session # debug
else:
card = get_artifact_by_museum_num(session['game']['current_card'])
return render_template('game.html', card=card)
# Handles user date guesses
@app.route('/', methods=['POST'])
def handle_guess():
# Grab the value from the form created in the js
guess_val = request.form.get('date_guess')
# print guess_val #debug
guess = int(guess_val)
# Query and create artifact card based on museum number
museum_num = session['game']['current_card']
actual = get_artifact_by_museum_num(museum_num)
# Collect data to sent to frontend.
result = {}
result['guess'] = guess
result['date_begin'] = actual.prod_date_begin
result['date_end'] = actual.prod_date_end
# Update session cookie
# Store user guess and card's museum number
session['game']['prev_cards'][museum_num] = guess
# Set current card to None so we get a new card later
session['game']['current_card'] = None
print len(session['game']['prev_cards']) # debug
if len(session['game']['prev_cards']) >= NUM_ARTIFACTS_IN_EXHIBIT:
result['game_end_flag'] = True
else:
result['game_end_flag'] = False
print session #debug
# Send JSON version of result to frontend
return json.dumps(result)
# Gets data for a new artifact and sends it to the frontend as JSON
@app.route('/get_art', methods=['GET'])
def get_art():
art_card = get_random_artifact()
# Do not use cards that have already been seen
while art_card.museum_num in session['game']['prev_cards']:
art_card = get_random_artifact()
# Add current card to list of seen cards in session cookie
session['game']['current_card'] = art_card.museum_num
print "PROVIDED NEW CARD", session # debug
art_dict = art_to_dict(art_card)
return json.dumps(art_dict)
# Register user name
@app.route('/register', methods=['POST'])
def register_name():
player_name = request.form.get('name')
session['game']['player_name'] = player_name
print "REGISTERED PLAYER AS ", player_name # debug
print session # debug
return "post success"
# Provides the game session information
@app.route('/get_score', methods=['GET'])
def get_score():
template_values = []
game_score = 0
possible_score = 0
for museum_num in session['game']['prev_cards']:
card = get_artifact_by_museum_num(museum_num)
# users guess is stored in the museum_num key
card.guess = session['game']['prev_cards'][museum_num]
card.guess_score, card.score = game_utils.score_card(card.guess, card.prod_date_begin, card.prod_date_end)
game_score += card.guess_score
possible_score += card.score
template_values.append(card)
# print template_values # debug
return render_template('_player_game_data.html', total_score=possible_score, final_score=game_score, cards=template_values)
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=8888)