Beispiel #1
0
def cacheMap(mapFile, _beatmap):
    # Check if we have to download the .osu file
    download = False
    if not os.path.isfile(mapFile):
        # .osu file doesn't exist. We must download it
        download = True
    else:
        # File exists, check md5
        if generalUtils.fileMd5(mapFile) != _beatmap.fileMD5 or not isBeatmap(
                mapFile):
            # MD5 don't match, redownload .osu file
            download = True

    # Download .osu file if needed
    if download:
        log.debug("maps ~> Downloading {} osu file".format(_beatmap.beatmapID))

        # Get .osu file from osu servers
        fileContent = osuapiHelper.getOsuFileFromID(_beatmap.beatmapID)

        # Make sure osu servers returned something
        if fileContent is None or not isBeatmap(content=fileContent):
            raise exceptions.osuApiFailException("maps")

        # Delete old .osu file if it exists
        if os.path.isfile(mapFile):
            os.remove(mapFile)

        # Save .osu file
        with open(mapFile, "wb+") as f:
            f.write(fileContent)
    else:
        # Map file is already in folder
        log.debug("maps ~> Beatmap found in cache!")
Beispiel #2
0
def shouldDownloadMap(mapFile, _beatmap):
    # Check if we have to download the .osu file
    if not os.path.isfile(mapFile):
        # .osu file doesn't exist. We must download it
        return True
    else:
        # File exists, check md5
        if generalUtils.fileMd5(mapFile) != _beatmap.checksum or not isBeatmap(
                mapFile):
            # MD5 don't match, redownload .osu file
            return True

    # File exists and md5 matches. There's no need to download it again.
    return False
Beispiel #3
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)

            try:
                # Check if we have to download the .osu file
                download = False
                if not os.path.isfile(mapFile):
                    # .osu file doesn't exist. We must download it
                    if glob.debug:
                        consoleHelper.printColored(
                            "[!] {} doesn't exist".format(mapFile),
                            bcolors.YELLOW)
                    download = True
                else:
                    # File exists, check md5
                    if generalUtils.fileMd5(mapFile) != self.beatmap.fileMD5:
                        # MD5 don't match, redownload .osu file
                        if glob.debug:
                            consoleHelper.printColored(
                                "[!] Beatmaps md5 don't match", bcolors.YELLOW)
                        download = True

                # Download .osu file if needed
                if download:
                    if glob.debug:
                        consoleHelper.printRippoppaiMessage(
                            "Downloading {} from osu! servers...".format(
                                self.beatmap.beatmapID))

                    # Get .osu file from osu servers
                    fileContent = osuapiHelper.getOsuFileFromID(
                        self.beatmap.beatmapID)

                    # Make sure osu servers returned something
                    if fileContent is None:
                        raise exceptions.osuApiFailException(MODULE_NAME)

                    # Delete old .osu file if it exists
                    if os.path.isfile(mapFile):
                        os.remove(mapFile)

                    # Save .osu file
                    with open(mapFile, "wb+") as f:
                        f.write(fileContent.encode("latin-1"))
                else:
                    # Map file is already in folder
                    if glob.debug:
                        consoleHelper.printRippoppaiMessage(
                            "Found beatmap file {}".format(mapFile))
            except exceptions.osuApiFailException:
                pass

            # Base command
            command = fixPath("{path}/oppai {mapFile}".format(
                path=self.OPPAI_FOLDER, mapFile=mapFile))

            # Use only mods supported by oppai.
            modsFixed = self.mods & 5979

            # Add params if needed
            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 tillerino:
                command += " tillerino"
            if stars:
                command += " stars"

            # 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
            if glob.debug:
                consoleHelper.printRippoppaiMessage("Calculated pp: {}".format(
                    self.pp))
        finally:
            return self.pp
Beispiel #4
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 = "{path}/maps/{map}".format(path=self.OPPAI_FOLDER, map=self.map)
			log.debug("oppai ~> Map file: {}".format(mapFile))

			try:
				# Check if we have to download the .osu file
				download = False
				if not os.path.isfile(mapFile):
					# .osu file doesn't exist. We must download it
					if glob.debug:
						consoleHelper.printColored("[!] {} doesn't exist".format(mapFile), bcolors.YELLOW)
					download = True
				else:
					# File exists, check md5
					if generalUtils.fileMd5(mapFile) != self.beatmap.fileMD5:
						# MD5 don't match, redownload .osu file
						if glob.debug:
							consoleHelper.printColored("[!] Beatmaps md5 don't match", bcolors.YELLOW)
						download = True

				# Download .osu file if needed
				if download:
					log.debug("oppai ~> Downloading {} osu file".format(self.beatmap.beatmapID))

					# Get .osu file from osu servers
					fileContent = osuapiHelper.getOsuFileFromID(self.beatmap.beatmapID)

					# Make sure osu servers returned something
					if fileContent is None:
						raise exceptions.osuApiFailException(MODULE_NAME)

					# Delete old .osu file if it exists
					if os.path.isfile(mapFile):
						os.remove(mapFile)

					# Save .osu file
					with open(mapFile, "wb+") as f:
						f.write(fileContent.encode("utf-8"))
				else:
					# Map file is already in folder
					log.debug("oppai ~> Beatmap found in cache!")
			except exceptions.osuApiFailException:
				log.error("oppai ~> osu!api error!")
				pass

			# Parse beatmap
			log.debug("oppai ~> About to parse beatmap")
			pyoppai.parse(
				mapFile,
				self._oppai_beatmap,
				self._oppai_buffer,
				self.BUFSIZE,
				False,
				self.OPPAI_FOLDER # /oppai_cache
			)
			self.checkOppaiErrors()
			log.debug("oppai ~> Beatmap parsed with no errors")

			# Create diffcalc context and calculate difficulty
			log.debug("oppai ~> About to calculate difficulty")

			# Use only mods supported by oppai
			modsFixed = self.mods & 5979
			if modsFixed > 0:
				pyoppai.apply_mods(self._oppai_beatmap, modsFixed)
			self._oppai_diffcalc_ctx = pyoppai.new_d_calc_ctx(self._oppai_ctx)
			diff_stars, diff_aim, diff_speed, _, _, _, _ = pyoppai.d_calc(self._oppai_diffcalc_ctx, self._oppai_beatmap)
			self.checkOppaiErrors()
			log.debug("oppai ~> Difficulty calculated with no errors. {}*, {} aim, {} speed".format(diff_stars, diff_aim, diff_speed))

			# Calculate pp
			log.debug("oppai ~> About to calculate PP")
			if not self.tillerino:
				_, total_pp, aim_pp, speed_pp, acc_pp =  pyoppai.pp_calc_acc(self._oppai_ctx, diff_aim, diff_speed, self._oppai_beatmap,
													                   self.acc if self.acc > 0 else 100,
													                   modsFixed,
													                   self.combo if self.combo > 0 else 0xFFFF,
													                   self.misses)
				self.checkOppaiErrors()
				log.debug("oppai ~> PP Calculated with no errors. {}pp, {} aim pp, {} speed pp, {} acc pp".format(
					total_pp, aim_pp, speed_pp, acc_pp
				))
				self.pp = total_pp
			else:
				pp_list = []
				for acc in [100, 99, 98, 95]:
					log.debug("oppai ~> Calculating PP with acc {}%".format(acc))
					_, total_pp, aim_pp, speed_pp, acc_pp = pyoppai.pp_calc_acc(self._oppai_ctx, diff_aim, diff_speed,
					                                                      self._oppai_beatmap, acc, modsFixed)
					self.checkOppaiErrors()
					pp_list.append(total_pp)
					log.debug("oppai ~> PP Calculated with no errors. {}pp, {} aim pp, {} speed pp, {} acc pp".format(
						total_pp, aim_pp, speed_pp, acc_pp
					))
					self.pp = pp_list
			self.stars = diff_stars

			log.debug("oppai ~> Calculated PP: {}".format(self.pp))
		except OppaiError:
			log.error("oppai ~> pyoppai error!")
			self.pp = 0
		except Exception as e:
			log.error("oppai ~> Unhandled exception: {}".format(str(e)))
			raise e
		finally:
			log.debug("oppai ~> Shutting down and returning {}pp".format(self.pp))
			return self.pp