Ejemplo n.º 1
0
	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
Ejemplo n.º 2
0
    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))
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
	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))
Ejemplo n.º 6
0
    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))
Ejemplo n.º 7
0
    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))
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
    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))
Ejemplo n.º 11
0
    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))