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_runlist_for_runner_put( self, params ): user = params[ 'user' ] game = params[ 'game' ] game_code = params[ 'game_code' ] category = params[ 'category' ] time = params[ 'time' ] video = params[ 'video' ] version = params[ 'version' ] notes = params[ 'notes' ] date = params[ 'date' ] datetime_created = params[ 'datetime_created' ] run_id = params[ 'run_id' ] # Update runlist for runner in memcache runlist = self.get_runlist_for_runner( user.username, no_refresh=True ) if runlist is not None: runlist.insert( 0, dict( run_id = run_id, game = game, game_code = game_code, category = category, time = time, date = date, datetime_created = datetime_created, video = video, version = version, notes = notes ) ) runlist.sort( key=lambda x: util.get_valid_date( x['date'] ), reverse=True ) self.update_cache_runlist_for_runner( user.username, runlist )
def update_runlist_for_runner_put(self, params): user = params['user'] game = params['game'] game_code = params['game_code'] category = params['category'] time = params['time'] video = params['video'] version = params['version'] notes = params['notes'] date = params['date'] datetime_created = params['datetime_created'] run_id = params['run_id'] # Update runlist for runner in memcache runlist = self.get_runlist_for_runner(user.username, no_refresh=True) if runlist == self.OVER_QUOTA_ERROR: self.update_cache_runlist_for_runner(user.username, None) elif runlist is not None: runlist.insert( 0, dict(run_id=run_id, game=game, game_code=game_code, category=category, category_code=util.get_code(category), time=time, date=date, datetime_created=datetime_created, video=video, version=version, notes=notes)) runlist.sort(key=lambda x: util.get_valid_date(x['date']), reverse=True) self.update_cache_runlist_for_runner(user.username, runlist)
def update_runlist_for_runner_put(self, params): user = params["user"] game = params["game"] game_code = params["game_code"] category = params["category"] time = params["time"] video = params["video"] version = params["version"] notes = params["notes"] date = params["date"] datetime_created = params["datetime_created"] run_id = params["run_id"] # Update runlist for runner in memcache cached_runlists = self.get_cached_runlists_for_runner(user.username) if cached_runlists is not None: res = cached_runlists.get(1) if res is not None: res["runlist"].insert( 0, dict( run_id=run_id, game=game, game_code=game_code, category=category, category_code=util.get_code(category), time=time, date=date, datetime_created=datetime_created, video=video, version=version, notes=notes, ), ) res["runlist"].sort(key=lambda x: util.get_valid_date(x["date"]), reverse=True) self.update_cache_runlist_for_runner(user.username, cached_runlists)
def put_existing_run( self, params ): user = params[ 'user' ] game = params[ 'game' ] game_code = params[ 'game_code' ] category = params[ 'category' ] seconds = params[ 'seconds' ] time = params[ 'time' ] video = params[ 'video' ] version = params[ 'version' ] notes = params[ 'notes' ] valid = params[ 'valid' ] run_id = params[ 'run_id' ] # Grab the old run, which we will update to be the new run new_run = self.get_run_by_id( run_id ) if ( new_run is None or ( not user.is_mod and new_run.username != user.username ) ): return False # Get the owner of this run if new_run.username != user.username: runner = self.get_runner( util.get_code( new_run.username ) ) params['user'] = runner else: runner = user # Store the contents of the old run old_run = dict( game = new_run.game, category = new_run.category, seconds = new_run.seconds ) # Update the run try: new_run.game = game new_run.category = category new_run.seconds = seconds new_run.date = params['date'] new_run.version = version new_run.notes = notes except db.BadValueError: valid = False if video: try: new_run.video = video except db.BadValueError: params['video_error'] = "Invalid video URL" valid = False elif new_run.video: new_run.video = None if not valid: return False new_run.put( ) logging.debug( "Put updated run for runner " + runner.username + ", game = " + game + ", category = " + category + ", time= " + time + ", run_id = " + run_id ) # Figure out the change in num_pbs for the old and new game, as well # as the runner delta_num_pbs_old = 0 delta_num_pbs_new = 0 if game != old_run['game'] or category != old_run['category']: num_runs = self.num_runs( runner.username, old_run[ 'game' ], old_run[ 'category' ], 1 ) if num_runs == 0: delta_num_pbs_old = -1 num_runs = self.num_runs( runner.username, game, category, 2 ) if num_runs == 1: delta_num_pbs_new = 1 # Update games.Games and runners.Runners self.update_runner( runner, delta_num_pbs_old + delta_num_pbs_new ) if game == old_run['game']: self.update_games_delete( params['game_model'], delta_num_pbs_old ) else: self.update_games_delete( self.get_game_model( util.get_code( old_run['game'] ) ), delta_num_pbs_old ) self.update_games_put( params, delta_num_pbs_new ) # Update memcache with the removal of the old run and addition of the # new run. self.update_cache_run_by_id( run_id, new_run ) # Must update runinfo before pblist and gamepage as in put_new_run() self.update_runinfo_delete( runner, old_run ) self.update_runinfo_put( params ) self.update_pblist_delete( runner, old_run ) self.update_pblist_put( params ) self.update_gamepage_delete( runner, old_run ) self.update_gamepage_put( params ) self.update_user_has_run_delete( runner, old_run ) self.update_cache_user_has_run( runner.username, game, True ) # Update gamelist and runnerlist in memcache if delta_num_pbs_old == -1: self.update_gamelist_delete( old_run ) self.update_runnerlist_delete( runner ) if delta_num_pbs_new == 1: self.update_gamelist_put( params ) self.update_runnerlist_put( params ) # Replace the old run in the runlist for runner in memcache runlist = self.get_runlist_for_runner( runner.username, no_refresh=True ) if runlist: for run in runlist: if run[ 'run_id' ] == run_id: run[ 'game' ] = game run[ 'game_code' ] = game_code run[ 'category' ] = category run[ 'time' ] = time run[ 'date' ] = new_run.date run[ 'video' ] = video run[ 'version' ] = version run[ 'notes' ] = notes runlist.sort( key=lambda x: util.get_valid_date( x['date'] ), reverse=True ) self.update_cache_runlist_for_runner( runner.username, runlist ) break # Check to see if we need to replace the last run for this user last_run = self.get_last_run( runner.username, no_refresh=True ) if( last_run is not None and new_run.key().id() == last_run.key().id() ): self.update_cache_last_run( runner.username, new_run ) return True
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 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 put_existing_run(self, params): user = params['user'] game = params['game'] game_code = params['game_code'] category = params['category'] seconds = params['seconds'] time = params['time'] video = params['video'] version = params['version'] notes = params['notes'] valid = params['valid'] run_id = params['run_id'] # Grab the old run, which we will update to be the new run new_run = self.get_run_by_id(run_id) if new_run == self.OVER_QUOTA_ERROR: return False if (new_run is None or (not user.is_mod and new_run.username != user.username)): return False # Get the owner of this run if new_run.username != user.username: runner = self.get_runner(util.get_code(new_run.username)) if runner == self.OVER_QUOTA_ERROR: return False params['user'] = runner else: runner = user # Store the contents of the old run old_run = dict(game=new_run.game, category=new_run.category, seconds=new_run.seconds) old_game_model = self.get_game_model(util.get_code(old_run['game'])) if old_game_model == self.OVER_QUOTA_ERROR: return False # Update the run try: new_run.game = game new_run.category = category new_run.seconds = seconds new_run.date = params['date'] new_run.version = version new_run.notes = notes except db.BadValueError: valid = False if video: try: new_run.video = video except db.BadValueError: params['video_error'] = "Invalid video URL" valid = False elif new_run.video: new_run.video = None if not valid: return False new_run.put() logging.debug("Put updated run for runner " + runner.username + ", game = " + game + ", category = " + category + ", time= " + time + ", run_id = " + run_id) # Figure out the change in num_pbs for the old and new game, as well # as the runner delta_num_pbs_old = 0 delta_num_pbs_new = 0 if game != old_run['game'] or category != old_run['category']: num_runs = self.num_runs(runner.username, old_run['game'], old_run['category'], 1) if num_runs == 0: delta_num_pbs_old = -1 num_runs = self.num_runs(runner.username, game, category, 2) if num_runs == 1: delta_num_pbs_new = 1 # Update games.Games and runners.Runners self.update_runner(runner, delta_num_pbs_old + delta_num_pbs_new) if game == old_run['game']: self.update_games_delete(params['game_model'], delta_num_pbs_old) else: self.update_games_delete(old_game_model, delta_num_pbs_old) self.update_games_put(params, delta_num_pbs_new) # Update memcache with the removal of the old run and addition of the # new run. self.update_cache_run_by_id(run_id, new_run) # Must update runinfo before pblist and gamepage as in put_new_run() self.update_runinfo_delete(runner, old_run) self.update_runinfo_put(params) self.update_pblist_delete(runner, old_run) self.update_pblist_put(params) self.update_gamepage_delete(runner, old_run) self.update_gamepage_put(params) self.update_user_has_run_delete(runner, old_run) self.update_cache_user_has_run(runner.username, game, True) # Update gamelist and runnerlist in memcache if delta_num_pbs_old == -1: self.update_gamelist_delete(old_run) self.update_runnerlist_delete(runner) if delta_num_pbs_new == 1: self.update_gamelist_put(params) self.update_runnerlist_put(params) # Replace the old run in the runlist for runner in memcache runlist = self.get_runlist_for_runner(runner.username, no_refresh=True) if runlist == self.OVER_QUOTA_ERROR: self.update_cache_runlist_for_runner(runner.username, None) elif runlist is not None: for run in runlist: if run['run_id'] == run_id: run['game'] = game run['game_code'] = game_code run['category'] = category run['category_code'] = util.get_code(category) run['time'] = time run['date'] = new_run.date run['video'] = video run['version'] = version run['notes'] = notes runlist.sort(key=lambda x: util.get_valid_date(x['date']), reverse=True) self.update_cache_runlist_for_runner( runner.username, runlist) break # Check to see if we need to replace the last run for this user last_run = self.get_last_run(runner.username, no_refresh=True) if last_run == self.OVER_QUOTA_ERROR: self.update_cache_last_run(runner.username, None) elif (last_run is not None and new_run.key().id() == last_run.key().id()): self.update_cache_last_run(runner.username, new_run) return True
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 put_existing_run(self, params): user = params["user"] game = params["game"] game_code = params["game_code"] category = params["category"] seconds = params["seconds"] time = params["time"] video = params["video"] version = params["version"] notes = params["notes"] valid = params["valid"] run_id = params["run_id"] # Grab the old run, which we will update to be the new run new_run = self.get_run_by_id(run_id) if new_run == self.OVER_QUOTA_ERROR: return False if new_run is None or (not user.is_mod and new_run.username != user.username): return False # Get the owner of this run if new_run.username != user.username: runner = self.get_runner(util.get_code(new_run.username)) if runner == self.OVER_QUOTA_ERROR: return False params["user"] = runner else: runner = user # Store the contents of the old run old_run = dict(game=new_run.game, category=new_run.category, seconds=new_run.seconds) old_game_model = self.get_game_model(util.get_code(old_run["game"])) if old_game_model == self.OVER_QUOTA_ERROR: return False # Update the run try: new_run.game = game new_run.category = category new_run.seconds = seconds new_run.date = params["date"] new_run.version = version new_run.notes = notes except db.BadValueError: valid = False if video: try: new_run.video = video except db.BadValueError: params["video_error"] = "Invalid video URL" valid = False elif new_run.video: new_run.video = None if not valid: return False new_run.put() logging.debug( "Put updated run for runner " + runner.username + ", game = " + game + ", category = " + category + ", time= " + time + ", run_id = " + run_id ) # Figure out the change in num_pbs for the old and new game, as well # as the runner delta_num_pbs_old = 0 delta_num_pbs_new = 0 if game != old_run["game"] or category != old_run["category"]: num_runs = self.num_runs(runner.username, old_run["game"], old_run["category"], 1) if num_runs == 0: delta_num_pbs_old = -1 num_runs = self.num_runs(runner.username, game, category, 2) if num_runs == 1: delta_num_pbs_new = 1 # Update games.Games and runners.Runners self.update_runner(runner, delta_num_pbs_old + delta_num_pbs_new) if game == old_run["game"]: self.update_games_delete(params["game_model"], old_run["category"], delta_num_pbs_old) else: self.update_games_delete(old_game_model, old_run["category"], delta_num_pbs_old) self.update_games_put(params, delta_num_pbs_new) # Update memcache with the removal of the old run and addition of the # new run. self.update_cache_run_by_id(run_id, new_run) self.update_pblist_delete(runner, old_run) self.update_pblist_put(params) self.update_gamepage_delete(runner, old_run) self.update_gamepage_put(params) self.update_user_has_run_delete(runner, old_run) self.update_cache_user_has_run(runner.username, game, True) # Update gamelist and runnerlist in memcache if delta_num_pbs_old == -1: self.update_gamelist_delete(old_run) self.update_runnerlist_delete(runner) if delta_num_pbs_new == 1: self.update_gamelist_put(params) self.update_runnerlist_put(params) # Replace the old run in the runlist for runner in memcache cached_runlists = self.get_cached_runlists_for_runner(runner.username) if cached_runlists is not None: found_run = False for page_num, res in cached_runlists.iteritems(): if found_run: break for run in res["runlist"]: if run["run_id"] == run_id: run["game"] = game run["game_code"] = game_code run["category"] = category run["category_code"] = util.get_code(category) run["time"] = time run["date"] = new_run.date run["video"] = video run["version"] = version run["notes"] = notes res["runlist"].sort(key=lambda x: util.get_valid_date(x["date"]), reverse=True) self.update_cache_runlist_for_runner(runner.username, cached_runlists) found_run = True break # Check to see if we need to replace the last run for this user last_run = self.get_last_run(runner.username, no_refresh=True) if last_run == self.OVER_QUOTA_ERROR: self.update_cache_last_run(runner.username, None) elif last_run is not None and new_run.key().id() == last_run.key().id(): self.update_cache_last_run(runner.username, new_run) return True