def getPP(self, tillerino=False, stars=False): """ Calculate total pp value with oppai and return it return -- total pp """ # Set variables self.pp = 0 self.stars = 0 try: # Build .osu map file path mapFile = "/data/oppai/maps/{map}".format(map=self.map) mapsHelper.cacheMap(mapFile, self.beatmap) # Base command if tillerino == True: pp_list = [] for acc in [100, 99, 98, 95]: calc = omppc.Calculator(mapFile, score=1000000, mods=self.mods, accuracy=acc) pp = calc.calculate_pp()[0] pp_list.append(round(pp, 2)) else: calc = omppc.Calculator(mapFile, score=(self.score.score if self.score is not None else 1000000), mods=self.mods, accuracy=self.acc) pp = calc.calculate_pp()[0] if stars == True: self.stars = round(calc.calculate_stars(),5) consoleHelper.printRippoppaiMessage("calculated pp {}".format(pp)) if(tillerino == True): self.pp = pp_list else: self.pp = round(pp,2) finally: return self.pp
def calculate_pp(self): try: # Cache beatmap mapFile = mapsHelper.cachedMapPath(self.beatmap.beatmapID) mapsHelper.cacheMap(mapFile, self.beatmap) # TODO: Sanizite mods # Gamemode check if self.score and self.score.gameMode != gameModes.CTB: raise exceptions.unsupportedGameModeException() # Accuracy check if self.accuracy > 1: raise ValueError("Accuracy must be between 0 and 1") # Calculate difficulty calcBeatmap = CalcBeatmap(mapFile) difficulty = Difficulty(beatmap=calcBeatmap, mods=self.mods) # Calculate pp if self.tillerino: results = [] for acc in [1, 0.99, 0.98, 0.95]: results.append(ppCalc.calculate_pp( diff=difficulty, accuracy=acc, combo=self.combo if self.combo >= 0 else calcBeatmap.max_combo, miss=self.misses )) self.pp = results else: self.pp = ppCalc.calculate_pp( diff=difficulty, accuracy=self.accuracy, combo=self.combo if self.combo >= 0 else calcBeatmap.max_combo, miss=self.misses ) except exceptions.osuApiFailException: log.error("cicciobello ~> osu!api error!") self.pp = 0 except exceptions.unsupportedGameModeException: log.error("cicciobello ~> Unsupported gamemode") self.pp = 0 except Exception as e: log.error("cicciobello ~> Unhandled exception: {}".format(str(e))) self.pp = 0 raise finally: log.debug("cicciobello ~> Shutting down, pp = {}".format(self.pp))
def getPP(self): try: # Reset pp self.pp = 0 # Cache map mapsHelper.cacheMap(self.mapPath, self.beatmap) # Calculate pp self.pp = self._runProcess() except PianoError: log.warning("Invalid beatmap {}".format(self.beatmap.beatmapID)) self.pp = 0 finally: return self.pp
def _getPP(self): try: # Reset pp self.pp = 0 if self.score.mods & PlayMods.SCOREV2 > 0: return 0 # Cache map mapsHelper.cacheMap(self.mapPath, self.beatmap) # Calculate pp self.pp = self._runProcess() except OsuPerfomanceCalculationsError: log.warning("Invalid beatmap {}".format(self.beatmap.beatmapID)) self.pp = 0 except Exception as e1: print(e1) finally: return self.pp
def calculatePP(self): """ Calculate total pp value with oppai and return it return -- total pp """ # Set variables self.pp = None try: # Build .osu map file path mapFile = mapsHelper.cachedMapPath(self.beatmap.beatmapID) log.debug("oppai ~> Map file: {}".format(mapFile)) mapsHelper.cacheMap(mapFile, self.beatmap) # Use only mods supported by oppai modsFixed = self.mods & 5983 # Check gamemode if self.gameMode != gameModes.STD and self.gameMode != gameModes.TAIKO: raise exceptions.unsupportedGameModeException() command = "./pp/oppai-ng/oppai {}".format(mapFile) if not self.tillerino: # force acc only for non-tillerino calculation # acc is set for each subprocess if calculating tillerino-like pp sets if self.acc > 0: command += " {acc:.2f}%".format(acc=self.acc) if self.mods > 0: command += " +{mods}".format(mods=scoreUtils.readableMods(modsFixed)) if self.combo >= 0: command += " {combo}x".format(combo=self.combo) if self.misses > 0: command += " {misses}xm".format(misses=self.misses) if self.gameMode == gameModes.TAIKO: command += " -taiko" command += " -ojson" # Calculate pp if not self.tillerino: # self.pp, self.stars = self._runOppaiProcess(command) temp_pp, self.stars = self._runOppaiProcess(command) if (self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and temp_pp > 800) or \ self.stars > 50: # Invalidate pp for bugged taiko converteds and bugged inf pp std maps self.pp = 0 else: self.pp = temp_pp else: pp_list = [] for acc in [100, 99, 98, 95]: temp_command = command temp_command += " {acc:.2f}%".format(acc=acc) pp, self.stars = self._runOppaiProcess(temp_command) # If this is a broken converted, set all pp to 0 and break the loop if self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and pp > 800: pp_list = [0, 0, 0, 0] break pp_list.append(pp) self.pp = pp_list log.debug("oppai ~> Calculated PP: {}, stars: {}".format(self.pp, self.stars)) except OppaiError: log.error("oppai ~> oppai-ng error!") self.pp = 0 except exceptions.osuApiFailException: log.error("oppai ~> osu!api error!") self.pp = 0 except exceptions.unsupportedGameModeException: log.error("oppai ~> Unsupported gamemode") self.pp = 0 except Exception as e: log.error("oppai ~> Unhandled exception: {}".format(str(e))) self.pp = 0 raise finally: log.debug("oppai ~> Shutting down, pp = {}".format(self.pp))
def calculatePP(self): """ Calculate total pp value with oppai and return it return -- total pp """ # Set variables self.pp = None ez = None try: # Build .osu map file path mapFile = mapsHelper.cachedMapPath(self.beatmap.beatmapID) mapsHelper.cacheMap(mapFile, self.beatmap) # Use only mods supported by oppai modsFixed = self.mods & 5983 # Check gamemode if self.gameMode not in (gameModes.STD, gameModes.TAIKO): raise exceptions.unsupportedGameModeException() ez = oppai.ezpp_new() if self.misses > 0: oppai.ezpp_set_nmiss(ez, self.misses) if self.combo >= 0: oppai.ezpp_set_combo(ez, self.combo) if self.gameMode == gameModes.TAIKO: oppai.ezpp_set_mode_override(ez, gameModes.TAIKO) if not self.tillerino: if self.acc > 0: oppai.ezpp_set_accuracy_percent(ez, self.acc) if self.mods > mods.NOMOD: oppai.ezpp_set_mods(ez, modsFixed) relax = (self.mods & mods.RELAX) > 0 autopilot = (self.mods & mods.RELAX2) > 0 if relax or autopilot: oppai.ezpp_set_relax_version(ez, 1) if relax: oppai.ezpp_set_relax(ez, 1) elif autopilot: oppai.ezpp_set_autopilot(ez, 1) if not self.tillerino: oppai.ezpp_dup(ez, mapFile) temp_pp = oppai.ezpp_pp(ez) self.stars = oppai.ezpp_stars(ez) if (self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and temp_pp > 800) or \ self.stars > 50: # Invalidate pp for bugged taiko converteds and bugged inf pp std maps self.pp = 0 else: self.pp = temp_pp else: with open(mapFile, "r") as f: data = f.read() oppai.ezpp_data_dup(ez, data, len(data.encode())) pp_list = [] self.stars = oppai.ezpp_stars(ez) oppai.ezpp_set_autocalc(ez, 1) for acc in (100, 99, 98, 95): oppai.ezpp_set_accuracy_percent(ez, acc) pp = oppai.ezpp_pp(ez) # If this is a broken converted, set all pp to 0 and break the loop if self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and pp > 800: pp_list = [0, 0, 0, 0] break pp_list.append(pp) self.pp = pp_list log.debug("oppai ~> Calculated PP: {}, stars: {}".format( self.pp, self.stars)) except exceptions.osuApiFailException: log.error("oppai ~> osu!api error!") self.pp = 0 except exceptions.unsupportedGameModeException: log.error("oppai ~> Unsupported gamemode") self.pp = 0 except Exception as e: log.error("oppai ~> Unhandled exception: {}".format(str(e))) self.pp = 0 raise finally: if ez is not None: oppai.ezpp_free(ez) log.debug("oppai ~> Shutting down, pp = {}".format(self.pp))
def getPP(self, tillerino=False, stars=False): """ Calculate total pp value with oppai and return it return -- total pp """ # Set variables self.pp = 0 try: # Build .osu map file path mapFile = "{path}/maps/{map}".format(path=self.OPPAI_FOLDER, map=self.map) mapsHelper.cacheMap(mapFile, self.beatmap) # Base command command = fixPath("{path}/oppai {mapFile}".format( path=self.OPPAI_FOLDER, mapFile=mapFile)) # Use only mods supported by oppai. modsFixed = self.mods & 14303 command += " scorev{ver}".format( ver=scoreUtils.scoreType(self.mods)) # Add params if needed if not self.tillerino: if self.acc > 0: command += " {acc:.2f}%".format(acc=self.acc) if self.mods > 0: command += " +{mods}".format( mods=scoreUtils.readableMods(modsFixed)) if self.combo > 0: command += " {combo}x".format(combo=self.combo) if self.misses > 0: command += " {misses}xm".format(misses=self.misses) if self.gameMode == gameModes.TAIKO: command += " -taiko" command += " -ojson" # Calculate pp if not self.tillerino: # self.pp, self.stars = self._runOppaiProcess(command) temp_pp, self.stars = self._runOppaiProcess(command) if (self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and temp_pp > 800) or self.stars > 50: # Invalidate pp for bugged taiko converteds and bugged inf pp std maps self.pp = 0 else: self.pp = round(temp_pp, 2) else: pp_list = [] for acc in [100, 99, 98, 95]: temp_command = command temp_command += " {acc:.2f}%".format(acc=acc) pp, self.stars = self._runOppaiProcess(temp_command) # If this is a broken converted, set all pp to 0 and break the loop if self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and pp > 800: pp_list = [0, 0, 0, 0] break pp_list.append(round(pp, 2)) self.pp = pp_list # Debug output if glob.debug: consoleHelper.printRippoppaiMessage( "Executing {}".format(command)) # oppai output """process = subprocess.run(command, shell=True, stdout=subprocess.PIPE) output = process.stdout.decode("utf-8") # Get standard or tillerino output sep = "\n" if UNIX else "\r\n" if output == ['']: # This happens if mode not supported or something self.pp = 0 self.stars = None return self.pp output = output.split(sep) # get rid of pesky warnings!!! try: float(output[0]) except ValueError: del output[0] if tillerino: # Get tillerino output (multiple lines) if stars: self.pp = output[:-2] self.stars = float(output[-2]) else: self.pp = output.split(sep)[:-1] # -1 because there's an empty line at the end else: # Get standard output (:l to remove (/r)/n at the end) l = -1 if UNIX else -2 if stars: self.pp = float(output[len(output)-2][:l-1]) else: self.pp = float(output[len(output)-2][:l]) """ # Debug output consoleHelper.printRippoppaiMessage("Calculated pp: {}".format( self.pp)) except OppaiError: log.error("oppai ~> oppai-ng error!") self.pp = 0 except exceptions.osuApiFailException: log.error("oppai ~> osu!api error!") self.pp = 0 except exceptions.unsupportedGameModeException: log.error("oppai ~> Unsupported gamemode") self.pp = 0 except Exception as e: log.error("oppai ~> Unhandled exception: {}".format(str(e))) self.pp = 0 raise finally: log.debug("oppai ~> Shutting down, pp = {}".format(self.pp))
def update_beatmaps(args): beatmaps = glob.db.fetchAll( 'select beatmapset_id as sid, beatmap_id as id, beatmap_md5 as md5 from beatmaps' ) for bm in beatmaps: b = beatmap.beatmap() b.beatmapID, b.fileMD5 = bm['id'], bm['md5'] if bm['id'] > 100000000: continue fn = mapsHelper.cachedMapPath(bm['id']) if mapsHelper.os.path.isfile(fn) and mapsHelper.generalUtils.fileMd5( fn) == bm['md5']: continue try: if args.download_update: if mapsHelper.os.path.isfile(fn): if mapsHelper.generalUtils.fileMd5(fn) != bm['md5']: log.info("BID {}: Hash difference ({}) expected ({})". format( bm['id'], mapsHelper.generalUtils.fileMd5(fn)[:8], bm['md5'][:8])) else: log.info("BID {}: Not exists, downloading...".format( bm['id'])) mapsHelper.cacheMap(fn, b) if mapsHelper.os.path.isfile( fn) and mapsHelper.generalUtils.fileMd5(fn) != bm['md5']: bm['update.md5'] = mapsHelper.generalUtils.fileMd5(fn) else: bm['delete.file'] = True except Exception as e: log.warning('BID {}: ({}) {}'.format(bm['id'], type(e).__name__, e)) pass if args.download_update: time.sleep(2.5) stmts = [] bmgroup = [] def destructor(query): nonlocal bmgroup query += " end where beatmap_id in ({})".format(','.join( str(bm) for bm in bmgroup)) del bmgroup[:] return query stmt = QueryBuilder("update beatmaps set beatmap_md5=case ", '', " ") stmt.finisher = destructor for bm in beatmaps: if 'delete.file' in bm: continue if 'update.md5' not in bm: continue bmgroup.append(bm['id']) stmtline = "when beatmap_id={} then '{}'".format( bm['id'], bm['update.md5']) newQuery = stmt.appendAndBuild(stmtline) if newQuery: stmts.append(newQuery) if stmt.query: stmts.append(stmt.build()) for s in stmts: # print(s) glob.db.execute(s)
def getPP(self): try: stars = self.beatmap.starsMania if stars == 0: # This beatmap can't be converted to mania raise exceptions.invalidBeatmapException() # Cache beatmap for cono mapFile = mapsHelper.cachedMapPath(self.beatmap.beatmapID) mapsHelper.cacheMap(mapFile, self.beatmap) od = self.beatmap.OD objects = self.score.c50 + self.score.c100 + self.score.c300 + self.score.cKatu + self.score.cGeki + self.score.cMiss score = self.score.score accuracy = self.score.accuracy scoreMods = self.score.mods log.debug( "[WIFIPIANO2] SCORE DATA: Stars: {stars}, OD: {od}, obj: {objects}, score: {score}, acc: {acc}, mods: {mods}" .format(stars=stars, od=od, objects=objects, score=score, acc=accuracy, mods=scoreMods)) # ---------- STRAIN PP # Scale score to mods multiplier scoreMultiplier = 1.0 # Doubles score if EZ/HT if scoreMods & mods.EASY != 0: scoreMultiplier *= 0.50 #if scoreMods & mods.HALFTIME != 0: # scoreMultiplier *= 0.50 # Calculate strain PP if scoreMultiplier <= 0: strainPP = 0 else: score *= int(1.0 / scoreMultiplier) strainPP = pow(5.0 * max(1.0, stars / 0.0825) - 4.0, 3.0) / 110000.0 strainPP *= 1 + 0.1 * min(1.0, float(objects) / 1500.0) if score <= 500000: strainPP *= (float(score) / 500000.0) * 0.1 elif score <= 600000: strainPP *= 0.1 + float(score - 500000) / 100000.0 * 0.2 elif score <= 700000: strainPP *= 0.3 + float(score - 600000) / 100000.0 * 0.35 elif score <= 800000: strainPP *= 0.65 + float(score - 700000) / 100000.0 * 0.20 elif score <= 900000: strainPP *= 0.85 + float(score - 800000) / 100000.0 * 0.1 else: strainPP *= 0.95 + float(score - 900000) / 100000.0 * 0.05 # ---------- ACC PP # Makes sure OD is in range 0-10. If this is done elsewhere, remove this. scrubbedOD = min(10.0, max(0, 10.0 - od)) # Old formula but done backwards. hitWindow300 = (34 + 3 * scrubbedOD) # Increases hitWindow if EZ is on if scoreMods & mods.EASY != 0: hitWindow300 *= 1.4 # Fiddles with DT and HT to make them match hitWindow300's ingame. if scoreMods & mods.DOUBLETIME != 0: hitWindow300 *= 1.5 elif scoreMods & mods.HALFTIME != 0: hitWindow300 *= 0.75 # makes hit window match what it is ingame. hitWindow300 = int(hitWindow300) + 0.5 if scoreMods & mods.DOUBLETIME != 0: hitWindow300 /= 1.5 elif scoreMods & mods.HALFTIME != 0: hitWindow300 /= 0.75 # Calculate accuracy PP accPP = pow((150.0 / hitWindow300) * pow(accuracy, 16), 1.8) * 2.5 accPP *= min(1.15, pow(float(objects) / 1500.0, 0.3)) # ---------- TOTAL PP multiplier = 1.1 if scoreMods & mods.NOFAIL != 0: multiplier *= 0.90 if scoreMods & mods.SPUNOUT != 0: multiplier *= 0.95 if scoreMods & mods.EASY != 0: multiplier *= 0.50 if scoreMods & mods.HARDROCK != 0: multiplier *= 1.20 if scoreMods & mods.DOUBLETIME != 0: multiplier *= 1.45 if scoreMods & mods.NIGHTCORE != 0: multiplier *= 1.45 pp = pow(pow(strainPP, 1.1) + pow(accPP, 1.1), 1.0 / 1.1) * multiplier log.debug("[WIFIPIANO2] Calculated PP: {}".format(pp)) self.pp = pp except exceptions.invalidBeatmapException: log.warning("Invalid beatmap {}".format(self.beatmap.beatmapID)) self.pp = 0 finally: return self.pp
def _calculatePP(self): log.debug(f"ezPeace ~> object dict: {self.__dict__}") """ Calculate total pp value with peace and return it return -- total pp """ # Set variables self.pp = None peace = None try: # Check gamemode if self.gameMode not in (gameModes.STD, gameModes.TAIKO, gameModes.CTB, gameModes.MANIA): raise exceptions.unsupportedGameModeException() # Build .osu map file path mapFile = "{path}/{map}".format( path=self.GAME_FOLDER[self.gameMode], map=self.map) mapsHelper.cacheMap(mapFile, self.beatmap) beatmap = Beatmap(mapFile) peace = Calculator() # Not so readeable part starts here... peace.set_mode(self.gameMode) if self.misses > 0: peace.set_miss(self.misses) if self.combo >= 0: peace.set_combo(self.combo) if not self.tillerino: if self.acc > 0: peace.set_acc(self.acc) if self.score and self.gameMode == gameModes.MANIA: peace.set_score(self.score.score) if self.mods > mods.NOMOD: peace.set_mods(self.mods) if not self.tillerino: peace_calculations = peace.calculate(beatmap) temp_pp = round(peace_calculations.pp, 5) self.stars = peace_calculations.attrs_dict['stars'] if (self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and temp_pp > 800) or \ self.stars > 50 or \ self.gameMode == gameModes.MANIA and self.mods & mods.SCOREV2 > 0: # Invalidate pp for bugged taiko converteds and bugged inf pp std maps self.pp = 0 else: self.pp = temp_pp else: pp_list = [] peace_calculations = peace.calculate(beatmap) self.stars = peace_calculations.attrs_dict['stars'] if self.acc and self.acc > 0: peace.set_acc(self.acc) peace_calculations = peace.calculate(beatmap) self.pp = peace_calculations.pp else: for acc in (100, 99, 98, 95): peace.set_acc(acc) peace_calculations = peace.calculate(beatmap) pp = round(peace_calculations.pp, 5) # If this is a broken converted, set all pp to 0 and break the loop if self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and pp > 800 or \ self.gameMode == gameModes.MANIA and self.mods & mods.SCOREV2 > 0: pp_list = [0, 0, 0, 0] break pp_list.append(pp) self.pp = pp_list log.debug("peace ~> Calculated PP: {}, stars: {}".format( self.pp, self.stars)) except exceptions.osuApiFailException: log.error("peace ~> osu!api error!") self.pp = 0 except exceptions.unsupportedGameModeException: log.error("peace ~> Unsupported gamemode") self.pp = 0 except Exception as e: log.error("peace ~> Unhandled exception: {}".format(str(e))) self.pp = 0 raise finally: log.debug("peace ~> Shutting down, pp = {}".format(self.pp))
def _calculatePP(self): """ Calculate total pp value with peace and return it return -- total pp """ # Set variables self.pp = None peace = None try: # Check gamemode if self.gameMode not in (gameModes.STD, gameModes.TAIKO, gameModes.CTB, gameModes.MANIA): raise exceptions.unsupportedGameModeException() # Build .osu map file path mapFile = "{path}/maps/{map}".format( path=self.GAME_FOLDER[self.gameMode], map=self.map) mapsHelper.cacheMap(mapFile, self.beatmap) rosu = Calculator(mapFile) score_params = ScoreParams() # Not so readeable part starts here... if self.misses > 0: score_params.nMisses = self.misses if self.combo >= 0: score_params.combo = self.combo if not self.tillerino: if self.acc > 0: score_params.acc = self.acc if self.score and self.gameMode == gameModes.MANIA: score_params.score = self.score.score if self.mods > mods.NOMOD: score_params.mods = self.mods [rosu_calculations] = rosu.calculate(score_params) if not self.tillerino: if rosu_calculations.mode != self.score.gameMode: self.pp = 0 else: temp_pp = round(rosu_calculations.pp, 5) self.stars = rosu_calculations.stars if (self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and temp_pp > 800) or \ self.stars > 50 or \ self.gameMode == gameModes.MANIA and self.mods & mods.SCOREV2 > 0: # Invalidate pp for bugged taiko converteds and bugged inf pp std maps self.pp = 0 else: self.pp = temp_pp else: if rosu_calculations.mode != self.score.gameMode: self.pp = [0, 0, 0, 0] else: pp_list = [] self.stars = rosu_calculations.stars if self.acc and self.acc > 0: score_params.acc = self.acc [rosu_calculations] = rosu.calculate(score_params) self.pp = rosu_calculations.pp else: # ik that can be a better way, but i don't wanna do something "NICE" to this odd code for acc in (100, 99, 98, 95): score_params.acc = self.acc [rosu_calculations] = rosu.calculate(score_params) pp = round(rosu_calculations.pp, 5) # If this is a broken converted, set all pp to 0 and break the loop if self.gameMode == gameModes.TAIKO and self.beatmap.starsStd > 0 and pp > 800 or \ self.gameMode == gameModes.MANIA and self.mods & mods.SCOREV2 > 0: pp_list = [0, 0, 0, 0] break pp_list.append(pp) self.pp = pp_list log.debug("rosu ~> Calculated PP: {}, stars: {}".format( self.pp, self.stars)) except exceptions.osuApiFailException: log.error("rosu ~> osu!api error!") self.pp = 0 except exceptions.unsupportedGameModeException: log.error("rosu ~> Unsupported gamemode") self.pp = 0 except Exception as e: log.error("rosu ~> Unhandled exception: {}".format(str(e))) self.pp = 0 raise finally: log.debug("rosu ~> Shutting down, pp = {}".format(self.pp))