def getRankInfo(userID, gameMode): """ Get userID's current rank, user above us and pp/score difference :param userID: user :param gameMode: gameMode number :return: {"nextUsername": "", "difference": 0, "currentRank": 0} """ data = {"nextUsername": "", "difference": 0, "currentRank": 0} k = "ripple:leaderboard_relax:{}".format(scoreUtils.readableGameMode(gameMode)) position = userUtils.getGameRankRx(userID, gameMode) - 1 if int(gameMode) == 3: k = "ripple:leaderboard:{}".format(scoreUtils.readableGameMode(gameMode)) position = userUtils.getGameRank(userID, gameMode) - 1 log.debug("Our position is {}".format(position)) if position is not None and position > 0: aboveUs = glob.redis.zrevrange(k, position - 1, position) log.debug("{} is above us".format(aboveUs)) if aboveUs is not None and len(aboveUs) > 0 and aboveUs[0].isdigit(): # Get our rank, next rank username and pp/score difference myScore = glob.redis.zscore(k, userID) otherScore = glob.redis.zscore(k, aboveUs[0]) nextUsername = userUtils.getUsername(aboveUs[0]) if nextUsername is not None and myScore is not None and otherScore is not None: data["nextUsername"] = nextUsername data["difference"] = int(myScore) - int(otherScore) else: position = 0 data["currentRank"] = position + 1 return data
def updateCountry(userID, newScore, gameMode, mode='normal'): """ Update gamemode's country leaderboard. Doesn't do anything if userID is banned/restricted. :param userID: user, country is determined by the user :param newScore: new score or pp :param gameMode: gameMode number :return: """ if userUtils.isAllowed(userID): COUNTRYLESS = 'xx' if features.GLOBAL_COUNTRY_RANKS == 'clan': country = userUtils.getUserCountryClan(userID) else: country = userUtils.getCountry(userID) if country is not None and len( country) > 0 and country.lower() != COUNTRYLESS: log.debug("Updating {} country leaderboard...".format(country)) if features.RANKING_SCOREV2 and mode == 'alternative': k = "ripple:leaderboard_alt:{}:{}" elif mode == 'relax': k = "ripple:leaderboard_relax:{}:{}" else: k = "ripple:leaderboard:{}:{}" k = k.format(scoreUtils.readableGameMode(gameMode), country.lower()) glob.redis.zadd(k, str(userID), str(newScore)) else: log.debug( "Clan leaderboard update for user {} skipped (not allowed)".format( userID))
def updateLevelRX(userID, gameMode=0, totalScore=0): """ Update level in DB for userID relative to gameMode :param userID: user id :param gameMode: game mode number :param totalScore: new total score :return: """ # Make sure the user exists # if not exists(userID): # return # Get total score from db if not passed mode = scoreUtils.readableGameMode(gameMode) if totalScore == 0: totalScore = glob.db.fetch( "SELECT total_score_{m} as total_score FROM rx_stats WHERE id = %s LIMIT 1" .format(m=mode), [userID]) if totalScore: totalScore = totalScore["total_score"] # Calculate level from totalScore level = getLevel(totalScore) # Save new level glob.db.execute( "UPDATE rx_stats SET level_{m} = %s WHERE id = %s LIMIT 1".format( m=mode), [level, userID])
def update(userID, newScore, gameMode): """ Update gamemode's leaderboard. Doesn't do anything if userID is banned/restricted. :param userID: user :param newScore: new score or pp :param gameMode: gameMode number """ if userUtils.isAllowed(userID): log.debug("Updating leaderboard...") glob.redis.zadd("ripple:leaderboard_relax:{}".format(scoreUtils.readableGameMode(gameMode)), str(userID), str(newScore)) if int(gameMode) == 3: glob.redis.zadd("ripple:leaderboard:{}".format(scoreUtils.readableGameMode(gameMode)), str(userID), str(newScore)) else: log.debug("Leaderboard update for user {} skipped (not allowed)".format(userID))
def updateLevel(userID, gameMode=0, totalScore=0, *, relax=False): """ Update level in DB for userID relative to gameMode :param userID: user id :param gameMode: game mode number :param totalScore: new total score :param relax: :return: """ # Make sure the user exists # if not exists(userID): # return # Get total score from db if not passed mode = scoreUtils.readableGameMode(gameMode) table = "users_stats_relax" if relax else "users_stats" if totalScore == 0: totalScore = glob.db.fetch( "SELECT total_score_{m} as total_score FROM {table} WHERE id = %s LIMIT 1" .format(table=table, m=mode), (userID, )) if totalScore: totalScore = totalScore["total_score"] # Calculate level from totalScore level = getLevel(totalScore) # Save new level glob.db.execute( "UPDATE {table} SET level_{m} = %s WHERE id = %s LIMIT 1".format( table=table, m=mode), (level, userID))
def update(userID, newScore, gameMode): """ Update gamemode's leaderboard the leaderboard userID -- newScore -- new score or pp gameMode -- gameMode number """ log.debug("Updating leaderboard...") mode = scoreUtils.readableGameMode(gameMode) newPlayer = False us = glob.db.fetch("SELECT * FROM leaderboard_{} WHERE user=%s LIMIT 1".format(mode), [userID]) if us is None: newPlayer = True # Find player who is right below our score target = glob.db.fetch("SELECT * FROM leaderboard_{} WHERE v <= %s ORDER BY position ASC LIMIT 1".format(mode), [newScore]) plus = 0 if target is None: # Wow, this user completely sucks at this game. target = glob.db.fetch("SELECT * FROM leaderboard_{} ORDER BY position DESC LIMIT 1".format(mode)) plus = 1 # Set newT if target is None: # Okay, nevermind. It's not this user to suck. It's just that no-one has ever entered the leaderboard thus far. # So, the player is now #1. Yay! newT = 1 else: # Otherwise, just give them the position of the target. newT = target["position"] + plus # Make some place for the new "place holder". if newPlayer: glob.db.execute("UPDATE leaderboard_{} SET position = position + 1 WHERE position >= %s ORDER BY position DESC".format(mode), [newT]) else: glob.db.execute("DELETE FROM leaderboard_{} WHERE user = %s".format(mode), [userID]) glob.db.execute("UPDATE leaderboard_{} SET position = position + 1 WHERE position < %s AND position >= %s ORDER BY position DESC".format(mode), [us["position"], newT]) #if newT <= 1: # log.info("{} is now #{} ({})".format(userID, newT, mode), "bunker") # Finally, insert the user back. glob.db.execute("INSERT INTO leaderboard_{} (position, user, v) VALUES (%s, %s, %s);".format(mode), [newT, userID, newScore]) if gameMode == 0: newPlayer = False us = glob.db.fetch("SELECT * FROM users_peak_rank WHERE userid = %s LIMIT 1", [userID]) if us is None: newPlayer = True if newPlayer: glob.db.execute("INSERT INTO users_peak_rank (userid, peak_rank) VALUES (%s, %s);", [userID, newT]) else: if us["peak_rank"] > newT: glob.db.execute("UPDATE users_peak_rank SET peak_rank = %s WHERE userid = %s", [newT,userID])
def updatePP(userID, gameMode): """ Update userID's pp with new value :param userID: user id :param gameMode: game mode number """ glob.db.execute( "UPDATE users_stats SET pp_{}=%s WHERE id = %s LIMIT 1".format( scoreUtils.readableGameMode(gameMode)), (calculatePP(userID, gameMode), userID))
def updateCountry(userID, newScore, gameMode): """ Update gamemode's country leaderboard. Doesn't do anything if userID is banned/restricted. :param userID: user, country is determined by the user :param newScore: new score or pp :param gameMode: gameMode number :return: """ if userUtils.isAllowed(userID): country = userUtils.getCountry(userID) if country is not None and len(country) > 0 and country.lower() != "xx": log.debug("Updating {} country leaderboard...".format(country)) k = "ripple:leaderboard_relax:{}:{}".format(scoreUtils.readableGameMode(gameMode), country.lower()) if int(gameMode) == 3: k = "ripple:leaderboard:{}:{}".format(scoreUtils.readableGameMode(gameMode), country.lower()) glob.redis.zadd(k, str(userID), str(newScore)) else: log.debug("Country leaderboard update for user {} skipped (not allowed)".format(userID))
def updateAccuracy(userID, gameMode): """ Update accuracy value for userID relative to gameMode in DB :param userID: user id :param gameMode: gameMode number :return: """ newAcc = calculateAccuracy(userID, gameMode) mode = scoreUtils.readableGameMode(gameMode) glob.db.execute("UPDATE users_stats SET avg_accuracy_{m} = %s WHERE id = %s LIMIT 1".format(m=mode), [newAcc, userID])
def incrementReplaysWatched(userID, gameMode): """ Increment userID's replays watched by others relative to gameMode :param userID: user id :param gameMode: game mode number :return: """ mode = scoreUtils.readableGameMode(gameMode) glob.db.execute( "UPDATE users_stats SET replays_watched_{mode}=replays_watched_{mode}+1 WHERE id = %s LIMIT 1" .format(mode=mode), [userID])
def updatePP(userID, gameMode, *, relax=False): """ Update userID's pp with new value :param userID: user id :param gameMode: game mode number :param relax: if True, calculate relax pp, otherwise calculate classic pp """ glob.db.execute( "UPDATE {table} SET pp_{m}=%s WHERE id = %s LIMIT 1".format( table="users_stats_relax" if relax else "users_stats", m=scoreUtils.readableGameMode(gameMode)), (calculatePP(userID, gameMode, relax=relax), userID))
def getUserRank(userID, gameMode): """ Get userID's rank in gameMode's Leaderboard userID -- id of the user gameMode -- gameMode number return -- rank number. 0 if unknown """ mode = scoreUtils.readableGameMode(gameMode) result = glob.db.fetch("SELECT position FROM leaderboard_{} WHERE user = %s LIMIT 1".format(mode), [userID]) if result is not None: return int(result["position"]) else: return 0
def getRankedScore(userID, gameMode): """ Get userID's ranked score relative to gameMode :param userID: user id :param gameMode: game mode number :return: ranked score """ mode = scoreUtils.readableGameMode(gameMode) result = glob.db.fetch("SELECT ranked_score_{} FROM users_stats WHERE id = %s LIMIT 1".format(mode), [userID]) if result is not None: return result["ranked_score_{}".format(mode)] else: return 0
def updateStatsRx(userID, score_): """ Update stats (playcount, total score, ranked score, level bla bla) with data relative to a score object :param userID: :param score_: score object :param beatmap_: beatmap object. Optional. If not passed, it'll be determined by score_. """ # Make sure the user exists if not exists(userID): log.warning("User {} doesn't exist.".format(userID)) return # Get gamemode for db mode = scoreUtils.readableGameMode(score_.gameMode) # Update total score, playcount and play time if score_.playTime is not None: realPlayTime = score_.playTime else: realPlayTime = score_.fullPlayTime glob.db.execute( "UPDATE rx_stats SET total_score_{m}=total_score_{m}+%s, playcount_{m}=playcount_{m}+1, " "playtime_{m} = playtime_{m} + %s " "WHERE id = %s LIMIT 1".format( m=mode ), (score_.score, realPlayTime, userID) ) # Calculate new level and update it updateLevelRX(userID, score_.gameMode) # Update level, accuracy and ranked score only if we have passed the song if score_.passed: # Update ranked score glob.db.execute( "UPDATE rx_stats SET ranked_score_{m}=ranked_score_{m}+%s WHERE id = %s LIMIT 1".format(m=mode), (score_.rankedScoreIncrease, userID) ) # Update accuracy updateAccuracyRX(userID, score_.gameMode) # Update pp updatePPRelax(userID, score_.gameMode)
def updatePP(userID, gameMode): """ Update userID's pp with new value :param userID: user id :param gameMode: game mode number """ # Make sure the user exists # if not exists(userID): # return # Get new total PP and update db newPP = calculatePP(userID, gameMode) mode = scoreUtils.readableGameMode(gameMode) glob.db.execute("UPDATE users_stats SET pp_{}=%s WHERE id = %s LIMIT 1".format(mode), [newPP, userID])
def updateAccuracy(userID, gameMode, *, relax=False): """ Update accuracy value for userID relative to gameMode in DB :param userID: user id :param gameMode: gameMode number :param relax: if True, update relax accuracy, otherwise classic accuracy :return: """ newAcc = calculateAccuracy(userID, gameMode, relax=relax) mode = scoreUtils.readableGameMode(gameMode) glob.db.execute( "UPDATE {table} SET avg_accuracy_{m} = %s WHERE id = %s LIMIT 1". format(table="users_stats_relax" if relax else "users_stats", m=mode), (newAcc, userID))
def updateStats(userID, score_, beatmap_=None): """ Update stats (playcount, total score, ranked score, level bla bla) with data relative to a score object :param userID: :param score_: score object :param beatmap_: beatmap object. Optional. If not passed, it'll be determined by score_. """ # Make sure the user exists if not exists(userID): log.warning("User {} doesn't exist.".format(userID)) return if beatmap_ is None: beatmap_ = objects.beatmap.beatmap(score_.fileMd5, 0) # Get gamemode for db mode = scoreUtils.readableGameMode(score_.gameMode) # Update total score, playcount and play time realMapLength = beatmap_.hitLength if (score_.mods & mods.DOUBLETIME) > 0: realMapLength //= 1.5 elif (score_.mods & mods.HALFTIME) > 0: realMapLength //= 0.75 glob.db.execute( "UPDATE users_stats SET total_score_{m}=total_score_{m}+%s, playcount_{m}=playcount_{m}+1, " "playtime_{m} = playtime_{m} + %s " "WHERE id = %s LIMIT 1".format(m=mode), (score_.score, realMapLength, userID)) # Calculate new level and update it updateLevel(userID, score_.gameMode) # Update level, accuracy and ranked score only if we have passed the song if score_.passed: # Update ranked score glob.db.execute( "UPDATE users_stats SET ranked_score_{m}=ranked_score_{m}+%s WHERE id = %s LIMIT 1" .format(m=mode), (score_.rankedScoreIncrease, userID)) # Update accuracy updateAccuracy(userID, score_.gameMode) # Update pp updatePP(userID, score_.gameMode)
def updateStats(userID, score_, *, relax=False): """ Update stats (playcount, total score, ranked score, level bla bla) with data relative to a score object :param userID: :param score_: score object :param relax: if True, update relax stats, otherwise classic stats """ # Make sure the user exists if not exists(userID): log.warning("User {} doesn't exist.".format(userID)) return # Get gamemode for db mode = scoreUtils.readableGameMode(score_.gameMode) table = "users_stats_relax" if relax else "users_stats" # Update total score, playcount and play time if score_.playTime is not None: realPlayTime = score_.playTime else: realPlayTime = score_.fullPlayTime glob.db.execute( "UPDATE {table} SET total_score_{m}=total_score_{m}+%s, " "playcount_{m}=playcount_{m}+1, " "playtime_{m} = playtime_{m} + %s " "WHERE id = %s LIMIT 1".format(table=table, m=mode), (score_.score, realPlayTime, userID)) # Calculate new level and update it updateLevel(userID, score_.gameMode, relax=relax) # Update level, accuracy and ranked score only if we have passed the song if score_.passed: # Update ranked score glob.db.execute( "UPDATE {table} SET ranked_score_{m}=ranked_score_{m}+%s WHERE id = %s LIMIT 1" .format(table=table, m=mode), (score_.rankedScoreIncrease, userID)) # Update accuracy updateAccuracy(userID, score_.gameMode, relax=relax) # Update pp updatePP(userID, score_.gameMode, relax=relax)
def check(mode, beatmap): achievement_ids = [] mode_str = scoreUtils.readableGameMode(mode) mode_2 = mode_str.replace("osu", "std") stars = getattr(beatmap, "stars" + mode_2.title()) indexies = [ x - 1 for x in ACHIEVEMENT_KEYS["index"] if x == math.floor(stars) ] for index in indexies: achievement_ids.append(mode + index * 4) return achievement_ids
def getRankedScore(userID, gameMode, *, relax=False): """ Get userID's ranked score relative to gameMode :param userID: user id :param gameMode: game mode number :param relax: :return: ranked score """ mode = scoreUtils.readableGameMode(gameMode) result = glob.db.fetch( "SELECT ranked_score_{m} FROM {table} WHERE id = %s LIMIT 1".format( table="users_stats_relax" if relax else "users_stats", m=mode), (userID, )) if result is not None: return result["ranked_score_{}".format(mode)] else: return 0
def updateStats(userID, __score): """ Update stats (playcount, total score, ranked score, level bla bla) with data relative to a score object :param userID: :param __score: score object """ # Make sure the user exists if not exists(userID): log.warning("User {} doesn't exist.".format(userID)) return # Get gamemode for db mode = scoreUtils.readableGameMode(__score.gameMode) # Update total score and playcount glob.db.execute( "UPDATE users_stats SET total_score_{m}=total_score_{m}+%s, playcount_{m}=playcount_{m}+1 WHERE id = %s LIMIT 1" .format(m=mode), [__score.score, userID]) # Calculate new level and update it updateLevel(userID, __score.gameMode) # Update level, accuracy and ranked score only if we have passed the song if __score.passed: # Update ranked score glob.db.execute( "UPDATE users_stats SET ranked_score_{m}=ranked_score_{m}+%s WHERE id = %s LIMIT 1" .format(m=mode), [__score.rankedScoreIncrease, userID]) # Update accuracy updateAccuracy(userID, __score.gameMode) # Update pp updatePP(userID, __score.gameMode) # Update clan rating updateUserClanPerformance(userID) updateClanRating(userID, __score.gameMode)
def update(userID, newScore, gameMode, *, relax=False): """ Update gamemode's leaderboard. Doesn't do anything if userID is banned/restricted. :param userID: user :param newScore: new score or pp :param gameMode: gameMode number :param relax: if True, update relax global leaderboard, otherwise update classic global leaderboard """ if userUtils.isAllowed(userID): log.debug("Updating leaderboard...") glob.redis.zadd( "ripple:leaderboard:{}{}".format( scoreUtils.readableGameMode(gameMode), ":relax" if relax else ""), str(userID), str(newScore)) else: log.debug( "Leaderboard update for user {} skipped (not allowed)".format( userID))
def incrementReplaysWatched(scoreID, userID, gameMode, watcher): """ Increment userID's replays watched by others relative to gameMode :param userID: user id :param gameMode: game mode number :return: """ mode = scoreUtils.readableGameMode(gameMode) isWatched = glob.db.fetch( "SELECT id FROM score_views WHERE scoreid = %s AND userid = %s", [scoreID, watcher]) if not isWatched: glob.db.execute( "INSERT INTO score_views (scoreid, userid) VALUES (%s, %s)", [scoreID, watcher]) glob.db.execute( "UPDATE scores SET watched = watched + 1 WHERE id = %s LIMIT 1", [scoreID]) glob.db.execute( "UPDATE users_stats SET replays_watched_{mode}=replays_watched_{mode}+1 WHERE id = %s LIMIT 1" .format(mode=mode), [userID])
def update(userID, newScore, gameMode, mode='normal'): """ Update gamemode's leaderboard. Doesn't do anything if userID is banned/restricted. :param userID: user :param newScore: new score or pp :param gameMode: gameMode number """ if userUtils.isAllowed(userID): log.debug("Updating leaderboard...") if features.RANKING_SCOREV2 and mode == 'alternative': k = "ripple:leaderboard_alt:{}" elif mode == 'relax': k = "ripple:leaderboard_relax:{}" else: k = "ripple:leaderboard:{}" k = k.format(scoreUtils.readableGameMode(gameMode)) glob.redis.zadd(k, str(userID), str(newScore)) else: log.debug( "Leaderboard update for user {} skipped (not allowed)".format( userID))
def getRankInfo(userID, gameMode): """ userID -- gameMode -- gameMode number return -- {"nextusername": string, "difference": int} """ data = {"nextUsername": "", "difference": 0, "currentRank": 0} modeForDB = scoreUtils.readableGameMode(gameMode) v = glob.db.fetch("SELECT v FROM leaderboard_{mode} WHERE user = %s LIMIT 1".format(mode=modeForDB), [userID]) if v is not None: v = v["v"] result = glob.db.fetchAll("SELECT leaderboard_{mode}.*, users.username FROM leaderboard_{mode} LEFT JOIN users ON users.id = leaderboard_{mode}.user WHERE v >= %s ORDER BY v ASC LIMIT 2".format(mode=modeForDB), [v]) if len(result) == 2: # Get us and other us = result[0] other = result[1] # Get our rank, next rank username and pp/score difference data["currentRank"] = us["position"] data["nextUsername"] = other["username"] data["difference"] = int(other["v"])-int(us["v"]) return data
def rxupdate(userID, newScore, gameMode): """ Update gamemode's leaderboard. Doesn't do anything if userID is banned/restricted. :param userID: user :param newScore: new score or pp :param gameMode: gameMode number """ mode = scoreUtils.readableGameMode(gameMode) newPlayer = False us = glob.db.fetch("SELECT * FROM relaxboard_{} WHERE user=%s LIMIT 1".format(mode), [userID]) if us is None: newPlayer = True # Find player who is right below our score target = glob.db.fetch("SELECT * FROM relaxboard_{} WHERE v <= %s ORDER BY position ASC LIMIT 1".format(mode), [newScore]) plus = 0 if target is None: # Wow, this user completely sucks at this game. target = glob.db.fetch("SELECT * FROM relaxboard_{} ORDER BY position DESC LIMIT 1".format(mode)) plus = 1 # Set newT if target is None: # Okay, nevermind. It's not this user to suck. It's just that no-one has ever entered the leaderboard thus far. # So, the player is now #1. Yay! newT = 1 else: # Otherwise, just give them the position of the target. newT = target["position"] + plus # Make some place for the new "place holder". if newPlayer: glob.db.execute("UPDATE relaxboard_{} SET position = position + 1 WHERE position >= %s ORDER BY position DESC".format(mode), [newT]) else: glob.db.execute("DELETE FROM relaxboard_{} WHERE user = %s".format(mode), [userID]) glob.db.execute("UPDATE relaxboard_{} SET position = position + 1 WHERE position < %s AND position >= %s ORDER BY position DESC".format(mode), [us["position"], newT]) #if newT <= 1: # log.info("{} is now #{} ({})".format(userID, newT, mode), "bunker") # Finally, insert the user back. glob.db.execute("INSERT INTO relaxboard_{} (position, user, v) VALUES (%s, %s, %s);".format(mode), [newT, userID, newScore]) if gameMode == 0: newPlayer = False us = glob.db.fetch("SELECT * FROM users_relax_peak_rank WHERE userid = %s LIMIT 1", [userID]) if us is None: newPlayer = True if newPlayer: glob.db.execute("INSERT INTO users_relax_peak_rank (userid, peak_rank) VALUES (%s, %s);", [userID, newT]) else: if us["peak_rank"] > newT: glob.db.execute("UPDATE users_relax_peak_rank SET peak_rank = %s WHERE userid = %s", [newT,userID]) if userUtils.isAllowed(userID): log.debug("Updating relaxboard...") glob.redis.zadd("ripple:relaxboard:{}".format(scoreUtils.readableGameMode(gameMode)), str(userID), str(newScore)) else: log.debug("Relaxboard update for user {} skipped (not allowed)".format(userID))