def get_gamepage(self, game, no_refresh=False): key = self.get_gamepage_memkey(game) gamepage = memcache.get(key) if gamepage is None and not no_refresh: # Not in memcache, so construct the gamepage and store it in # memcache. # Gamepage is a list of dictionaries. These dictionaries have up # to 5 keys, 'category', 'bk_runner', 'bk_time', 'bk_video' and # 'infolist'. gamepage = [] # Grab the game model game_model = self.get_game_model(util.get_code(game)) if game_model is None: logging.error("Could not create " + key + " due to no " + "game model") return None gameinfolist = json.loads(game_model.info) # Use a projection query to get all of the unique # username, category pairs q = db.Query(runs.Runs, projection=("username", "category"), distinct=True) q.ancestor(runs.key()) q.filter("game =", game) q.order("category") cur_category = None for run in q.run(limit=1000): if run.category != cur_category: # New category d = dict(category=run.category, category_code=util.get_code(run.category), infolist=[]) gamepage.append(d) cur_category = run.category # Check for a best known time for this category for gameinfo in gameinfolist: if gameinfo["category"] == run.category: d["bk_runner"] = gameinfo.get("bk_runner") d["bk_time"] = util.seconds_to_timestr(gameinfo.get("bk_seconds")) d["bk_date"] = util.datestr_to_date(gameinfo.get("bk_datestr"))[0] d["bk_video"] = gameinfo.get("bk_video") break # Add the info to the gamepage info = self.get_runinfo(run.username, game, run.category) d["infolist"].append(info) # For each category, sort the runlist by seconds, breaking ties # by date for runlist in gamepage: runlist["infolist"].sort(key=lambda x: util.get_valid_date(x["pb_date"])) runlist["infolist"].sort(key=itemgetter("pb_seconds")) # Sort the categories by number of runners gamepage.sort(key=lambda x: len(x["infolist"]), reverse=True) if memcache.set(key, gamepage): logging.debug("Set " + key + " in memcache") else: logging.warning("Failed to set " + key + " in memcache") elif gamepage is not None: logging.debug("Got " + key + " from memcache") return gamepage
def update_gamepage_put( self, params ): user = params[ 'user' ] game = params[ 'game' ] category = params[ 'category' ] seconds = params[ 'seconds' ] time = params[ 'time' ] date = params[ 'date' ] video = params[ 'video' ] is_bkt = params[ 'is_bkt' ] # Update gamepage in memcache gamepage = self.get_gamepage( game, no_refresh=True ) if gamepage is None: return for d in gamepage: if d[ 'category' ] == category: if is_bkt: # Update best known time for this category d['bk_runner'] = user.username d['bk_time'] = util.seconds_to_timestr( seconds ) d['bk_date'] = date d['bk_video'] = video for i, runinfo in enumerate( d['infolist'] ): if runinfo['username'] == user.username: # User has run this category before d['infolist'][i] = self.get_runinfo( user.username, game, category ) d['infolist'].sort( key=lambda x: util.get_valid_date( x['pb_date'] ) ) d['infolist'].sort( key=itemgetter('pb_seconds') ) self.update_cache_gamepage( game, gamepage ) return # Category found, but user has not prev. run this category runinfo = self.get_runinfo( user.username, game, category ) d['infolist'].append( runinfo ) d['infolist'].sort( key=lambda x: util.get_valid_date( x['pb_date'] ) ) d['infolist'].sort( key=itemgetter('pb_seconds') ) gamepage.sort( key=lambda x: len(x['infolist']), reverse=True ) self.update_cache_gamepage( game, gamepage ) return # This is a new category for this game runinfo = self.get_runinfo( user.username, game, category ) d = dict( category=category, category_code=util.get_code( category ), infolist=[runinfo] ) # Check for best known time. Since we update games.Games before # updating gamepage, this will catch the case for when is_bkt is true. game_model = self.get_game_model( util.get_code( game ) ) if game_model is None: logging.error( "Failed to update gamepage for " + game ) self.update_cache_gamepage( game, None ) return gameinfolist = json.loads( game_model.info ) for gameinfo in gameinfolist: if gameinfo['category'] == category: d['bk_runner'] = gameinfo.get( 'bk_runner' ) d['bk_time'] = util.seconds_to_timestr( gameinfo.get( 'bk_seconds' ) ) d['bk_date'] = util.datestr_to_date( gameinfo.get( 'bk_datestr' ) )[ 0 ] d['bk_video'] = gameinfo.get( 'bk_video' ) break gamepage.append( d ) self.update_cache_gamepage( game, gamepage )
def post( self ): user = self.get_user( ) if not user: self.redirect( "/" ) return game = self.request.get( 'game' ) category = self.request.get( 'category' ) time = self.request.get( 'time' ) datestr = self.request.get( 'date' ) video = self.request.get( 'video' ) version = self.request.get( 'version' ) notes = self.request.get( 'notes' ) is_bkt = self.request.get( 'bkt', default_value="no" ) if is_bkt == "yes": is_bkt = True else: is_bkt = False run_id = self.request.get( 'edit' ) params = dict( user = user, game = game, category = category, time = time, datestr = datestr, video = video, version = version, notes = notes, run_id = run_id, is_bkt = is_bkt ) valid = True # Make sure the game doesn't already exist under a similar name game_code = util.get_code( game ) game_model = self.get_game_model( game_code ) if not game_code: params['game_error'] = "Game cannot be blank" valid = False elif game_model is not None and game != game_model.game: params['game_error'] = ( "Game already exists under [" + game_model.game + "] (case sensitive)." + " Hit submit again to confirm." ) params['game'] = game_model.game valid = False elif not valid_game_or_category( game ): params['game_error'] = ( "Game name must not use any 'funny'" + " characters and can be up to 100 " + "characters long" ) valid = False params[ 'game_code' ] = game_code params[ 'game_model' ] = game_model # Make sure the category doesn't already exist under a similar name category_code = util.get_code( category ) category_found = False if not category_code: params['category_error'] = "Category cannot be blank" valid = False elif game_model is not None: infolist = json.loads( game_model.info ) for info in infolist: if category_code == util.get_code( info['category'] ): category_found = True if category != info['category']: params['category_error'] = ( "Category already exists " + "under [" + info['category'] + "] " + "(case sensitive). " + "Hit submit again to " + "confirm." ) params['category'] = info['category'] valid = False break if not category_found and not valid_game_or_category( category ): params['category_error'] = ( "Category must not use any 'funny'" + " characters and can be up to 100 " + "characters long" ) valid = False params[ 'category_found' ] = category_found # Parse the time into seconds, ensure it is valid ( seconds, time_error ) = util.timestr_to_seconds( time ) if seconds is None: params['time_error'] = "Invalid time: " + time_error params['seconds'] = -1 valid = False else: time = util.seconds_to_timestr( seconds ) # Enforce standard form params[ 'time' ] = time params[ 'seconds' ] = seconds # Parse the date, ensure it is valid ( params['date'], params['date_error'] ) = util.datestr_to_date( datestr ) if params['date_error']: params['date_error'] = "Invalid date: " + params['date_error'] valid = False # Check that if this is a best known time, that it beats the old # best known time if is_bkt and game_model is not None: gameinfolist = json.loads( game_model.info ) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if( gameinfo.get( 'bk_seconds' ) is not None and gameinfo['bk_seconds'] <= seconds ): s = ( "This time does not beat current best known " + "time of " + util.seconds_to_timestr( gameinfo.get( 'bk_seconds' ) ) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)" ) params['bkt_error'] = s params['is_bkt'] = False valid = False break # Make sure that the notes are not too long if len( notes ) > 140: params['notes_error'] = "Notes must be at most 140 characters" valid = False params['valid'] = valid if run_id: success = self.put_existing_run( params ) else: success = self.put_new_run( params ) if success: self.redirect( "/runner/" + util.get_code( user.username ) + "?q=view-all" ) else: # Grab all of the games for autocompleting params['categories'] = self.get_categories( ) params['user'] = user self.render( "submit.html", **params )
def get_gamepage(self, game, no_refresh=False): key = self.get_gamepage_memkey(game) gamepage = memcache.get(key) if gamepage is None and not no_refresh: # Not in memcache, so construct the gamepage and store it in # memcache. # Gamepage is a list of dictionaries. These dictionaries have up # to 5 keys, 'category', 'bk_runner', 'bk_time', 'bk_video' and # 'infolist'. gamepage = [] # Grab the game model game_model = self.get_game_model(util.get_code(game)) if game_model is None: logging.error("Could not create " + key + " due to no " + "game model") return None if game_model == self.OVER_QUOTA_ERROR: return self.OVER_QUOTA_ERROR gameinfolist = json.loads(game_model.info) try: # Use a projection query to get all of the unique # username, category pairs q = db.Query(runs.Runs, projection=('username', 'category'), distinct=True) q.ancestor(runs.key()) q.filter('game =', game) q.order('category') cur_category = None for run in q.run(limit=1000): if run.category != cur_category: # New category d = dict(category=run.category, category_code=util.get_code(run.category), infolist=[]) gamepage.append(d) cur_category = run.category # Check for a best known time for this category for gameinfo in gameinfolist: if gameinfo['category'] == run.category: d['bk_runner'] = gameinfo.get('bk_runner') d['bk_time'] = util.seconds_to_timestr( gameinfo.get('bk_seconds')) d['bk_date'] = util.datestr_to_date( gameinfo.get('bk_datestr'))[0] d['bk_video'] = gameinfo.get('bk_video') break # Add the info to the gamepage info = self.get_runinfo(run.username, game, run.category) if info == self.OVER_QUOTA_ERROR: return self.OVER_QUOTA_ERROR d['infolist'].append(info) except apiproxy_errors.OverQuotaError, msg: logging.error(msg) return self.OVER_QUOTA_ERROR # For each category, sort the runlist by seconds, breaking ties # by date for runlist in gamepage: runlist['infolist'].sort( key=lambda x: util.get_valid_date(x['pb_date'])) runlist['infolist'].sort(key=itemgetter('pb_seconds')) # Sort the categories by number of runners gamepage.sort(key=lambda x: len(x['infolist']), reverse=True) if memcache.set(key, gamepage): logging.debug("Set " + key + " in memcache") else: logging.warning("Failed to set " + key + " in memcache")
def post(self): user = self.get_user() if not user: self.redirect("/") return game = self.request.get('game') category = self.request.get('category') time = self.request.get('time') datestr = self.request.get('date') video = self.request.get('video') version = self.request.get('version') notes = self.request.get('notes') is_bkt = self.request.get('bkt', default_value="no") if is_bkt == "yes": is_bkt = True else: is_bkt = False run_id = self.request.get('edit') params = dict(user=user, game=game, category=category, time=time, datestr=datestr, video=video, version=version, notes=notes, run_id=run_id, is_bkt=is_bkt) valid = True # Make sure the game doesn't already exist under a similar name game_code = util.get_code(game) game_model = self.get_game_model(game_code) if not game_code: params['game_error'] = "Game cannot be blank" valid = False elif game_model is not None and game != game_model.game: params['game_error'] = ("Game already exists under [" + game_model.game + "] (case sensitive)." + " Hit submit again to confirm.") params['game'] = game_model.game valid = False elif not games.valid_game_or_category(game): params['game_error'] = ("Game name must not use any 'funny'" + " characters and can be up to 100 " + "characters long") valid = False params['game_code'] = game_code params['game_model'] = game_model # Make sure the category doesn't already exist under a similar name category_code = util.get_code(category) category_found = False if not category_code: params['category_error'] = "Category cannot be blank" valid = False elif game_model is not None: infolist = json.loads(game_model.info) for info in infolist: if category_code == util.get_code(info['category']): category_found = True if category != info['category']: params['category_error'] = ( "Category already exists " + "under [" + info['category'] + "] " + "(case sensitive). " + "Hit submit again to " + "confirm.") params['category'] = info['category'] valid = False break if not category_found and not games.valid_game_or_category(category): params['category_error'] = ("Category must not use any 'funny'" + " characters and can be up to 100 " + "characters long") valid = False params['category_found'] = category_found # Parse the time into seconds, ensure it is valid (seconds, time_error) = util.timestr_to_seconds(time) if seconds is None: params['time_error'] = "Invalid time: " + time_error params['seconds'] = -1 valid = False else: time = util.seconds_to_timestr(seconds) # Enforce standard form params['time'] = time params['seconds'] = seconds # Parse the date, ensure it is valid (params['date'], params['date_error']) = util.datestr_to_date(datestr) if params['date_error']: params['date_error'] = "Invalid date: " + params['date_error'] valid = False # Check that if this is a best known time, then it beats the old # best known time. if is_bkt and game_model is not None: gameinfolist = json.loads(game_model.info) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if (gameinfo.get('bk_seconds') is not None and gameinfo['bk_seconds'] <= seconds): s = ("This time does not beat current best known " + "time of " + util.seconds_to_timestr( gameinfo.get('bk_seconds')) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)") params['bkt_error'] = s params['is_bkt'] = False valid = False break # Check that if this is not the best known time, then it doesn't beat # the old best known time if not is_bkt and game_model is not None: gameinfolist = json.loads(game_model.info) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if (gameinfo.get('bk_seconds') is not None and seconds < gameinfo['bk_seconds']): s = ( "This time beats the current best known time of " + util.seconds_to_timestr(gameinfo.get('bk_seconds')) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)") params['bkt_error'] = s params['is_bkt'] = True valid = False break # Make sure that the notes are not too long if len(notes) > 140: params['notes_error'] = "Notes must be at most 140 characters" valid = False params['valid'] = valid if run_id: success = self.put_existing_run(params) else: success = self.put_new_run(params) if success: self.redirect("/runner/" + util.get_code(user.username) + "?q=view-all") else: # Grab all of the games for autocompleting params['categories'] = self.get_categories() params['user'] = user self.render("submit.html", **params)
def update_gamepage_put(self, params): user = params['user'] game = params['game'] category = params['category'] seconds = params['seconds'] time = params['time'] date = params['date'] video = params['video'] is_bkt = params['is_bkt'] # Update gamepage in memcache gamepage = self.get_gamepage(game, no_refresh=True) if gamepage is None: return if gamepage == self.OVER_QUOTA_ERROR: self.update_cache_gamepage(game, None) return for d in gamepage: if d['category'] == category: if is_bkt: # Update best known time for this category d['bk_runner'] = user.username d['bk_time'] = util.seconds_to_timestr(seconds) d['bk_date'] = date d['bk_video'] = video for i, runinfo in enumerate(d['infolist']): if runinfo['username'] == user.username: # User has run this category before d['infolist'][i] = self.get_runinfo( user.username, game, category) if d['infolist'][i] == self.OVER_QUOTA_ERROR: gamepage = None else: d['infolist'].sort(key=lambda x: util. get_valid_date(x['pb_date'])) d['infolist'].sort(key=itemgetter('pb_seconds')) self.update_cache_gamepage(game, gamepage) return # Category found, but user has not prev. run this category runinfo = self.get_runinfo(user.username, game, category) if runinfo == self.OVER_QUOTA_ERROR: gamepage = None else: d['infolist'].append(runinfo) d['infolist'].sort( key=lambda x: util.get_valid_date(x['pb_date'])) d['infolist'].sort(key=itemgetter('pb_seconds')) gamepage.sort(key=lambda x: len(x['infolist']), reverse=True) self.update_cache_gamepage(game, gamepage) return # This is a new category for this game runinfo = self.get_runinfo(user.username, game, category) if runinfo == self.OVER_QUOTA_ERROR: self.update_cache_gamepage(game, gamepage) return d = dict(category=category, category_code=util.get_code(category), infolist=[runinfo]) # Check for best known time. Since we update games.Games before # updating gamepage, this will catch the case for when is_bkt is true. game_model = self.get_game_model(util.get_code(game)) if game_model is None: logging.error("Failed to update gamepage for " + game) self.update_cache_gamepage(game, None) return if game_model == self.OVER_QUOTA_ERROR: self.update_cache_gamepage(game, None) return gameinfolist = json.loads(game_model.info) for gameinfo in gameinfolist: if gameinfo['category'] == category: d['bk_runner'] = gameinfo.get('bk_runner') d['bk_time'] = util.seconds_to_timestr( gameinfo.get('bk_seconds')) d['bk_date'] = util.datestr_to_date( gameinfo.get('bk_datestr'))[0] d['bk_video'] = gameinfo.get('bk_video') break gamepage.append(d) self.update_cache_gamepage(game, gamepage)
def post( self, game_code ): user = self.get_user( ) if user == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html" ) return return_url = self.request.get( 'from' ) if not return_url: return_url = "/" # Get the category category_code = self.request.get( 'c' ) if user is None or category_code is None: self.error( 404 ) self.render( "404.html", user=user ) return # Have to take the code of the category code because of percent # encoded plusses category_code = util.get_code( category_code ) # Check to make sure that the user has run this game game_model = self.get_game_model( game_code ) if game_model == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html", user=user ) return user_has_run = self.get_user_has_run( user.username, game_model.game ) if user_has_run == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html", user=user ) return if not user_has_run and not user.is_mod: self.error( 404 ) self.render( "404.html", user=user ) return # Find the corresponding gameinfo for this category gameinfolist = json.loads( game_model.info ) gameinfo = None for g in gameinfolist: if util.get_code( g['category'] ) == category_code: gameinfo = g break if gameinfo is None: self.error( 404 ) self.render( "404.html", user=user ) return # Get the inputs username = self.request.get( 'username' ) time = self.request.get( 'time' ) datestr = self.request.get( 'date' ) video = self.request.get( 'video' ) params = dict( user=user, game=game_model.game, game_code=game_code, category=gameinfo['category'], username=username, time=time, datestr=datestr, video=video, return_url=return_url ) # Are we updating? if gameinfo.get( 'bk_runner' ) is None: params['updating'] = False else: params['updating'] = True valid = True # Check for where we came from if return_url[ 0 : len( '/runner/' ) ] == '/runner/': params['from_runnerpage'] = True else: params['from_runnerpage'] = False if not username and not time and not datestr and not video: gameinfo['bk_runner'] = None gameinfo['bk_seconds'] = None gameinfo['bk_datestr'] = None gameinfo['bk_video'] = None date = None else: # Make sure we got a username if not username: params['username_error'] = "You must enter a runner" valid = False # Parse the time into seconds, ensure it is valid ( seconds, time_error ) = util.timestr_to_seconds( time ) if not seconds: params['time_error'] = "Invalid time: " + time_error valid = False # Parse the date, ensure it is valid ( date, date_error ) = util.datestr_to_date( datestr ) if date_error: params['date_error'] = "Invalid date: " + date_error valid = False if not valid: self.render( "updatebkt.html", **params ) return time = util.seconds_to_timestr( seconds ) # Standard format params['time'] = time # Store the best known time gameinfo['bk_runner'] = username gameinfo['bk_seconds'] = seconds gameinfo['bk_datestr'] = datestr gameinfo['bk_video'] = video gameinfo['bk_updater'] = user.username game_model.info = json.dumps( gameinfolist ) game_model.put( ) # Update game_model in memcache self.update_cache_game_model( game_code, game_model ) # Update gamepage in memcache cached_gamepages = self.get_cached_gamepages( game_model.game, category_code ) if cached_gamepages is not None: for page_num, gamepage in cached_gamepages.iteritems( ): d = gamepage['d'] d['bk_runner'] = gameinfo['bk_runner'] d['bk_time'] = util.seconds_to_timestr( gameinfo['bk_seconds'] ) d['bk_date'] = date d['bk_video'] = gameinfo['bk_video'] self.update_cache_gamepage( game_model.game, category_code, cached_gamepages ) # All dun self.redirect( return_url )
def get_gamepage( self, game, category, page_num ): if category is None: return dict( has_next=False, page_num=0, d=None ) category_code = util.get_code( category ) key = self.get_gamepage_memkey( game, category_code ) cached_gamepages = memcache.get( key ) if cached_gamepages is None: cached_gamepages = dict( ) gamepage = cached_gamepages.get( page_num ) if gamepage is None: # Not in memcache, so construct the gamepage and store it in # memcache. # gamepage['d'] has up to 7 keys: # 'category', 'category_code', 'bk_runner', 'bk_time', # 'bk_date', 'bk_video' and 'infolist'. gamepage = dict( page_num=page_num, has_next=True ) d = dict( category=category, category_code=category_code, infolist=[ ] ) # Grab the game model game_model = self.get_game_model( util.get_code( game ) ) if game_model is None: logging.error( "Could not create " + key + " due to no " + "game model" ) return dict( has_next=False, page_num=0, d=None ) if game_model == self.OVER_QUOTA_ERROR: return self.OVER_QUOTA_ERROR gameinfolist = json.loads( game_model.info ) # Check for a best known time for this category for gameinfo in gameinfolist: if gameinfo['category'] == category: d['bk_runner'] = gameinfo.get( 'bk_runner' ) d['bk_time'] = util.seconds_to_timestr( gameinfo.get( 'bk_seconds' ) ) d['bk_date'] = util.datestr_to_date( gameinfo.get( 'bk_datestr' ) )[ 0 ] d['bk_video'] = gameinfo.get( 'bk_video' ) break try: # Get 1 run per username q = db.Query( runs.Runs, projection=['username', 'seconds', 'date', 'video', 'version'] ) q.ancestor( runs.key() ) q.filter( 'game =', game ) q.filter( 'category =', category ) q.order( 'seconds' ) q.order( 'date' ) usernames_seen = set( ) cached_cursor = memcache.get( self.get_gamepage_cursor_memkey( game, category_code, page_num ) ) if cached_cursor: try: q.with_cursor( start_cursor=cached_cursor['c'] ) usernames_seen = cached_cursor['usernames_seen'] except BadRequestError: gamepage['page_num'] = page_num else: gamepage['page_num'] = 1 num_runs = 0 for run in q.run( limit = self.GAMEPAGE_PAGE_LIMIT ): num_runs += 1 if run.username in usernames_seen: continue # Add the info to the gamepage info = dict( username = run.username, username_code = util.get_code( run.username ), category = category, category_code = category_code, pb_seconds = run.seconds, pb_time = util.seconds_to_timestr( run.seconds ), pb_date = run.date, video = run.video, version = run.version ) d['infolist'].append( info ) usernames_seen.add( run.username ) if num_runs < self.GAMEPAGE_PAGE_LIMIT: gamepage['has_next'] = False else: c = q.cursor( ) cached_cursor = dict( c=c, usernames_seen=usernames_seen ) cursor_key = self.get_gamepage_cursor_memkey( game, category_code, gamepage['page_num'] + 1 ) if memcache.set( cursor_key, cached_cursor ): logging.debug( "Set " + cursor_key + " in memcache" ) else: logging.warning( "Failed to set new " + cursor_key + " in memcache" ) except apiproxy_errors.OverQuotaError, msg: logging.error( msg ) return self.OVER_QUOTA_ERROR gamepage['d'] = d cached_gamepages[ gamepage['page_num'] ] = gamepage if memcache.set( key, cached_gamepages ): logging.debug( "Set " + key + " in memcache" ) else: logging.warning( "Failed to set " + key + " in memcache" )
def post( self, game_code ): user = self.get_user( ) if user == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html" ) return return_url = self.request.get( 'from' ) if not return_url: return_url = "/" # Get the category category_code = self.request.get( 'c' ) if user is None or category_code is None: self.error( 404 ) self.render( "404.html", user=user ) return # Have to take the code of the category code because of percent # encoded plusses category_code = util.get_code( category_code ) # Check to make sure that the user has run this game game_model = self.get_game_model( game_code ) if game_model == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html", user=user ) return user_has_run = self.get_user_has_run( user.username, game_model.game ) if user_has_run == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html", user=user ) return if not user_has_run and not user.is_mod: self.error( 404 ) self.render( "404.html", user=user ) return # Find the corresponding gameinfo for this category gameinfolist = json.loads( game_model.info ) gameinfo = None for g in gameinfolist: if util.get_code( g['category'] ) == category_code: gameinfo = g break if gameinfo is None: self.error( 404 ) self.render( "404.html", user=user ) return # Get the inputs username = self.request.get( 'username' ) time = self.request.get( 'time' ) datestr = self.request.get( 'date' ) video = self.request.get( 'video' ) params = dict( user=user, game=game_model.game, game_code=game_code, category=gameinfo['category'], username=username, time=time, datestr=datestr, video=video, return_url=return_url ) # Are we updating? if gameinfo.get( 'bk_runner' ) is None: params['updating'] = False else: params['updating'] = True valid = True # Check for where we came from if return_url[ 0 : len( '/runner/' ) ] == '/runner/': params['from_runnerpage'] = True else: params['from_runnerpage'] = False if not username and not time and not datestr and not video: gameinfo['bk_runner'] = None gameinfo['bk_seconds'] = None gameinfo['bk_datestr'] = None gameinfo['bk_video'] = None date = None else: # Make sure we got a username if not username: params['username_error'] = "You must enter a runner" valid = False # Parse the time into seconds, ensure it is valid ( seconds, time_error ) = util.timestr_to_seconds( time ) if not seconds: params['time_error'] = "Invalid time: " + time_error valid = False # Parse the date, ensure it is valid ( date, date_error ) = util.datestr_to_date( datestr ) if date_error: params['date_error'] = "Invalid date: " + date_error valid = False if not valid: self.render( "updatebkt.html", **params ) return time = util.seconds_to_timestr( seconds ) # Standard format params['time'] = time # Store the best known time gameinfo['bk_runner'] = username gameinfo['bk_seconds'] = seconds gameinfo['bk_datestr'] = datestr gameinfo['bk_video'] = video gameinfo['bk_updater'] = user.username game_model.info = json.dumps( gameinfolist ) game_model.put( ) # Update game_model in memcache self.update_cache_game_model( game_code, game_model ) # Update gamepage in memcache gamepage = self.get_gamepage( game_model.game, no_refresh=True ) if gamepage == self.OVER_QUOTA_ERROR: self.update_cache_gamepage( game, None ) elif gamepage is not None: for d in gamepage: if d['category'] == gameinfo['category']: d['bk_runner'] = gameinfo['bk_runner'] d['bk_time'] = util.seconds_to_timestr( gameinfo['bk_seconds'] ) d['bk_date'] = date d['bk_video'] = gameinfo['bk_video'] break self.update_cache_gamepage( game_model.game, gamepage ) # All dun self.redirect( return_url )
def post( self, game_code ): user = self.get_user( ) if not user: self.redirect( "/" ) return elif user == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html" ) return category = self.request.get( 'category' ) time = self.request.get( 'time' ) datestr = self.request.get( 'date' ) video = self.request.get( 'video' ) version = self.request.get( 'version' ) notes = self.request.get( 'notes' ) is_bkt = self.request.get( 'bkt', default_value="no" ) if is_bkt == "yes": is_bkt = True else: is_bkt = False run_id = self.request.get( 'edit' ) # Have to take the code of the game code because of percent # encoded plusses game_code = util.get_code( game_code ) params = dict( user = user, game_code = game_code, category = category, time = time, datestr = datestr, video = video, version = version, notes = notes, run_id = run_id, is_bkt = is_bkt ) valid = True # Make sure the game already exists game_model = self.get_game_model( game_code ) game = '' if not game_code: params['game_error'] = "Game cannot be blank" valid = False elif game_model is None: params['game_error'] = ( "That's weird, we could not find any " + "records for that game" ) valid = False elif game_model == self.OVER_QUOTA_ERROR: params['game_error'] = ( "PB Tracker is currently over its quota" + " limit for the day. Please try again " + "tomorrow." ) valid = False else: game = game_model.game params[ 'game' ] = game params[ 'game_model' ] = game_model # Make sure the category doesn't already exist under a similar name category_code = util.get_code( category ) category_found = False if not category_code: params['category_error'] = "Category cannot be blank" valid = False elif game_model is not None: infolist = json.loads( game_model.info ) for info in infolist: if category_code == util.get_code( info['category'] ): category_found = True if category != info['category']: params['category_error'] = ( "Category already exists " + "under [" + info['category'] + "] " + "(case sensitive). " + "Hit submit again to " + "confirm." ) params['category'] = info['category'] valid = False break if not category_found and not games.valid_game_or_category( category ): params['category_error'] = ( "Category must not use any 'funny'" + " characters and can be up to 100 " + "characters long" ) valid = False params[ 'category_found' ] = category_found # Parse the time into seconds, ensure it is valid ( seconds, time_error ) = util.timestr_to_seconds( time ) if seconds is None: params['time_error'] = "Invalid time: " + time_error params['seconds'] = -1 valid = False else: time = util.seconds_to_timestr( seconds ) # Enforce standard form params[ 'time' ] = time params[ 'seconds' ] = seconds # Parse the date, ensure it is valid ( params['date'], params['date_error'] ) = util.datestr_to_date( datestr ) if params['date_error']: params['date_error'] = "Invalid date: " + params['date_error'] valid = False # Check that if this is a best known time, then it beats the old # best known time. if is_bkt and game_model is not None: gameinfolist = json.loads( game_model.info ) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if( gameinfo.get( 'bk_seconds' ) is not None and gameinfo['bk_seconds'] <= seconds ): s = ( "This time does not beat current best known " + "time of " + util.seconds_to_timestr( gameinfo.get( 'bk_seconds' ) ) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)" ) params['bkt_error'] = s params['is_bkt'] = False valid = False break # Check that if this is not the best known time, then it doesn't beat # the old best known time if not is_bkt and game_model is not None: gameinfolist = json.loads( game_model.info ) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if( gameinfo.get( 'bk_seconds' ) is not None and seconds < gameinfo['bk_seconds'] ): s = ( "This time beats the current best known time of " + util.seconds_to_timestr( gameinfo.get( 'bk_seconds' ) ) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)" ) params['bkt_error'] = s params['is_bkt'] = True valid = False break # Make sure that the notes are not too long if len( notes ) > 140: params['notes_error'] = "Notes must be at most 140 characters" valid = False params['valid'] = valid if run_id: success = self.put_existing_run( params ) else: success = self.put_new_run( params ) if success: self.redirect( "/runner/" + util.get_code( user.username ) + "?q=view-all" ) elif game_model is not None: try: # Grab all of the categories for autocompleting params['categories'] = game_model.categories( ) params['user'] = user self.render( "submit.html", **params ) except DeadlineExceededError, msg: logging.error( msg ) self.error( 403 ) self.render( "deadline_exceeded.html", user=user )