def stdCalc(bmap, count0: int, count50: int, count100: int, count300: int, combo: int, mods: int, perfect: int, max_combo: int): p = pyt.parser() beatmap = p.map(bmap) objcount = beatmap.ncircles + beatmap.nsliders + beatmap.nspinners totalhits = count50 + count100 + count300 sr = pyt.diff_calc().calc(beatmap, mods) pp, _, _, _, _ = pyt.ppv2(sr.aim, sr.speed, bmap=beatmap, mods=mods, n300=count300, n100=count100, n50=count50, nmiss=count0, combo=combo) pp_fc = 0 if perfect == 0: pp_fc, _, _, _, _ = pyt.ppv2(sr.aim, sr.speed, bmap=beatmap, mods=mods, n300=objcount - totalhits, n100=count100, n50=count50, nmiss=0, combo=max_combo) return round(sr.total, 2), round(pp, 2), round(pp_fc, 2)
def set_embed_pp( self, mods: Mods = None, acc: tuple[Union[float, int]] = (95, 97.5, 100), ) -> None: if self.mode != 0: return if not mods: mods = self.mods self.embed_pp_values = [] stars = pyttanko.diff_calc().calc(self.mapfile, mods._value_) for a in acc: n300, n100, n50 = pyttanko.acc_round(a, len(self.mapfile.hitobjects), 0) pp = pyttanko.ppv2( stars.aim, stars.speed, n100=n100, n50=n50, mods=mods._value_, bmap=self.mapfile, n300=n300, )[0] self.embed_pp_values.append(f'{a}%-{pp:.2f}PP')
def calculate_score_pp(self, beatmap_id, score): p = osu.parser() beatmap_url = "https://osu.ppy.sh/osu/{0}".format(beatmap_id) beatmap_raw = requests.get(beatmap_url).text f = codecs.open(Logic.temp_beatmap_name, "w+", "utf-8") f.write(beatmap_raw) f.close() f = codecs.open(Logic.temp_beatmap_name, encoding="utf-8") clean_beatmap = p.map(f) f.close() os.remove(Logic.temp_beatmap_name) stars = osu.diff_calc().calc( clean_beatmap, osu.mods_from_str(score.get_mods_string())) pp, _, _, _, acc = osu.ppv2(aim_stars=stars.aim, speed_stars=stars.speed, bmap=clean_beatmap, mods=osu.mods_from_str( score.get_mods_string()), combo=score.max_combo, n300=score.number_300s, n100=score.number_100s, n50=score.number_50s, nmiss=score.misses) return pp, acc
def run(): ERROR_MARGIN = 0.02 '''pp can be off by +- 2% margin is actually 3x for < 100pp, 2x for 100-200, 1.5x for 200-300''' p = pyttanko.parser() bmap = pyttanko.beatmap() stars = pyttanko.diff_calc() try: for s in suite.suite: print_score(s) with open("test/test_suite/%d.osu" % (s.id), "r") as f: p.map(f, bmap=bmap) stars.calc(bmap, s.mods) pp, _, _, _, _ = pyttanko.ppv2(stars.aim, stars.speed, bmap=bmap, mods=s.mods, n300=s.n300, n100=s.n100, n50=s.n50, nmiss=s.nmiss, combo=s.max_combo) margin = s.pp * ERROR_MARGIN if s.pp < 100: margin *= 3 elif s.pp < 200: margin *= 2 elif s.pp < 300: margin *= 1.5 if abs(pp - s.pp) >= margin: pyttanko.info("failed test: got %gpp, expected %g\n" % (pp, s.pp)) exit(1) except KeyboardInterrupt: pass except FileNotFoundError: pyttanko.info("please download the test suite by running " + "./download_suite\n") sys.exit(1) except Exception as e: if p.done: raise else: pyttanko.info("%s\n%s\n" % (traceback.format_exc(), str(p))) sys.exit(1)
async def calculate_pp(self, stars, bmap, mods, n50, n100, n300, combo, misses): calc = pyttanko.ppv2(stars['aim'], stars['speed'], max_combo=bmap.max_combo, nsliders=bmap.count_slider, ncircles=bmap.count_normal, nobjects=(bmap.count_slider + bmap.count_normal + bmap.count_spinner), base_ar=bmap.diff_approach, base_od=bmap.diff_overall, mods=mods, n50=n50, n100=n100, n300=n300, combo=combo, nmiss=misses) pp = round(calc[0], 2) return pp
def get_real_pp(self): stars = pyttanko.diff_calc().calc(self.bmap, self.mods) ppv2 = pyttanko.ppv2(aim_stars=stars.aim, speed_stars=stars.speed, mods=self.mods, n100=self.count100, n50=self.count50, n300=self.count300, nmiss=self.misses, combo=self.combo, bmap=self.bmap) return round(ppv2[0], 2)
def calculate_osu_pp(self, osu_file, mods=0): """ 计算pp :param osu_file: file osu后缀名的文件 :param mods: int 模式 HR HD DT NF等,可调用api进行查看 :param n300: int 300 :param n100: int 100 :param n50: int 50 :param nmiss: int miss :param combo: int 最大的连击数 :return: (str stars星级, str pp点) """ p = osu.parser() with open(osu_file, "r", encoding="utf-8") as f: bmap = p.map(f) stars = osu.diff_calc().calc(bmap) if self.is_search_map is True: pp, _, _, _, _ = osu.ppv2(stars.aim, stars.speed, bmap=bmap, mods=mods) else: pp, _, _, _, _ = osu.ppv2(stars.aim, stars.speed, bmap=bmap, mods=self.int_mods, n300=self.count300, n100=self.count100, n50=self.count50, nmiss=self.countmiss, combo=self.maxcombo) # pp, _, _, _, _ = osu.ppv2( # stars.aim, stars.speed, bmap=bmap, mods=mods, # n300=n300, n100=n100, n50=n50, nmiss=nmiss, # combo=combo # ) return "{:.1f}".format(stars.total), "{}".format(int(pp))
def calc_if(osufile, mods_num, c50, c100, mapcb): p = osu.parser() with open(osufile, 'r', encoding='utf-8') as f: bmap = p.map(f) stars = osu.diff_calc().calc(bmap, mods_num) pp = osu.ppv2( stars.aim, stars.speed, mods=mods_num, n100=c100, n50=c50, nmiss=0, max_combo=mapcb, bmap=bmap ) return pp[0]
def get_if_fc_pp(self): # Set miss count to zero self.misses = 0 self.combo = self.bmap.max_combo() stars = pyttanko.diff_calc().calc(self.bmap, self.mods) # max_combo used if combo is not provided => # don't need to set it manually ppv2 = pyttanko.ppv2(stars.aim, stars.speed, n100=self.count100, n50=self.count50, n300=self.count300, mods=self.mods, bmap=self.bmap) return round(ppv2[0], 2)
def ppCalc(mapId, modsInt, n300, n100, n50): bmap = beatmapsDataParser().bmapData(mapId, modsInt) pp, _, _, _, _ = osu.ppv2(aim_stars=bmap["aim"], speed_stars=bmap["speed"], max_combo=bmap["maxcombo"], nsliders=bmap["nsliders"], ncircles=bmap["ncircles"], nobjects=bmap["nobjects"], base_ar=bmap["ar"], base_od=bmap["od"], mods=modsInt, n300=n300, n100=n100, n50=n50) return float("%.2f" % pp)
def pp_if_fc(self) -> tuple[float, float]: if self.mode != 0: return n100 = round(self.n100 / 1.5) n50 = round(self.n50 / 1.5) stars = pyttanko.diff_calc().calc(self.bmap.mapfile, self.mods._value_) data = pyttanko.ppv2(stars.aim, stars.speed, bmap=self.bmap.mapfile, mods=self.mods._value_, n100=n100, n50=n50) return data[0], data[4]
def calc_acc_pp(osufile, mods_num): acc_pp = [] p = osu.parser() with open(osufile, 'r', encoding='utf-8') as f: bmap = p.map(f) stars = osu.diff_calc().calc(bmap, mods_num) for acc in range(95, 101): c300, c100, c50 = osu.acc_round(acc, len(bmap.hitobjects), 0) pp, _, _, _, _ = osu.ppv2( stars.aim, stars.speed, mods=mods_num, n300=c300, n100=c100, n50=c50, bmap=bmap ) acc_pp.append(int(pp)) return acc_pp
def std(map_id, beatmap, mods, combo, n300, n100, n50, nmiss): """Get pp for a Standard play.""" if not beatmap["text"]: return None parser = pyttanko.parser() with io.StringIO(beatmap["text"]) as f: bmap = parser.map(f) stars = pyttanko.diff_calc().calc(bmap, mods) return pyttanko.ppv2( aim_stars=stars.aim, speed_stars=stars.speed, mods=mods, combo=combo, n300=n300, n100=n100, n50=n50, nmiss=nmiss, bmap=bmap, )[0]
def calc_pp(osufile, mods_num, maxcb, c50, c100, c300, miss): p = osu.parser() with open(osufile, 'r', encoding='utf-8') as f: bmap = p.map(f) stars = osu.diff_calc().calc(bmap, mods_num) map_stars = stars.total pp, aim, speed, acc, accuracy = osu.ppv2( stars.aim, stars.speed, mods=mods_num, combo=maxcb, n300=c300, n100=c100, n50=c50, nmiss=miss, bmap=bmap ) cs = bmap.cs ar = bmap.ar od = bmap.od hp = bmap.hp play_pp = int(round(pp, 2)) aim_pp = int(round(aim, 2)) speed_pp = int(round(speed, 2)) acc_pp = int(round(acc, 2)) accuracy = round(accuracy, 2) return map_stars, cs, ar, od, hp, play_pp, aim_pp, speed_pp, acc_pp, accuracy
async def get_pyttanko(self, map_id: str, accs=[100], mods=0, misses=0, combo=None, completion=None, fc=None): url = 'https://osu.ppy.sh/osu/{}'.format(map_id) file_path = os.getcwd() + '/temp/{}.osu'.format(map_id) await self.download_file(url, file_path) bmap = pyttanko.parser().map(open(file_path)) _, ar, od, cs, hp = pyttanko.mods_apply(mods, ar=bmap.ar, od=bmap.od, cs=bmap.cs, hp=bmap.hp) stars = pyttanko.diff_calc().calc(bmap, mods=mods) bmap.stars = stars.total bmap.aim_stars = stars.aim bmap.speed_stars = stars.speed if not combo: combo = bmap.max_combo() bmap.pp = [] bmap.aim_pp = [] bmap.speed_pp = [] bmap.acc_pp = [] bmap.acc = accs for acc in accs: n300, n100, n50 = pyttanko.acc_round(acc, len(bmap.hitobjects), misses) pp, aim_pp, speed_pp, acc_pp, _ = pyttanko.ppv2(bmap.aim_stars, bmap.speed_stars, bmap=bmap, mods=mods, n300=n300, n100=n100, n50=n50, nmiss=misses, combo=combo) bmap.pp.append(pp) bmap.aim_pp.append(aim_pp) bmap.speed_pp.append(speed_pp) bmap.acc_pp.append(acc_pp) if fc: n300, n100, n50 = pyttanko.acc_round(fc, len(bmap.hitobjects), 0) # print("-------------", n300, n100, n50) fc_pp, _, _, _, _ = pyttanko.ppv2(bmap.aim_stars, bmap.speed_stars, bmap=bmap, mods=mods, n300=n300 + misses, n100=n100, n50=n50, nmiss=0, combo=bmap.max_combo()) pyttanko_json = { 'version': bmap.version, 'title': bmap.title, 'artist': bmap.artist, 'creator': bmap.creator, 'combo': combo, 'max_combo': bmap.max_combo(), 'misses': misses, 'mode': bmap.mode, 'stars': bmap.stars, 'aim_stars': bmap.aim_stars, 'speed_stars': bmap.speed_stars, 'pp': bmap.pp, # list 'aim_pp': bmap.aim_pp, 'speed_pp': bmap.speed_pp, 'acc_pp': bmap.acc_pp, 'acc': bmap.acc, # list 'cs': cs, 'od': od, 'ar': ar, 'hp': hp } if completion: try: pyttanko_json['map_completion'] = (completion / len(bmap.hitobjects)) * 100 except: pyttanko_json['map_completion'] = "Error" os.remove(file_path) return pyttanko_json
def calculatePlay(bmap, mode: int = 0, count0: int = 0, count50: int = 0, count100: int = 0, count300: int = 0, countgeki: int = 0, countkatu: int = 0, combo: int = 0, mods: int = 0, perfect: int = 0, calcPP: int = 1): if mode == 0: #Standard modString = pyt.mods_str(mods) accuracy = acc.stdCalc(count0, count50, count100, count300) p = pyt.parser() beatmap = p.map(bmap) objcount = beatmap.ncircles + beatmap.nsliders + beatmap.nspinners totalhits = count50 + count100 + count0 sr = pyt.diff_calc().calc(beatmap, mods) pp = 0 if calcPP == 1: pp, _, _, _, _ = pyt.ppv2(sr.aim, sr.speed, bmap=beatmap, mods=mods, n300=count300, n100=count100, n50=count50, nmiss=count0, combo=combo) pp_fc = 0 if perfect == 0: pp_fc, _, _, _, _ = pyt.ppv2(sr.aim, sr.speed, bmap=beatmap, mods=mods, n300=objcount - totalhits, n100=count100, n50=count50, nmiss=0, combo=beatmap.max_combo()) accuracy_fc = acc.stdCalc(0, count50, count100, objcount - totalhits) beatmapDict = { "title": beatmap.title, "artist": beatmap.artist, "creator": beatmap.creator, "version": beatmap.version, "objcount": objcount, "mode": beatmap.mode, "maxcombo": beatmap.max_combo() } playDict = { "totalhits": totalhits + count0, "pp": round(pp, 2), "pp_fc": round(pp_fc, 2), "accuracy": accuracy, "accuracy_fc": 0 if perfect == 1 else accuracy_fc, "modString": modString if modString != "nomod" else "NM", "rating": round(sr.total, 2), "completion": round(((totalhits + count300) * 100) / objcount, 2), "mode_icon": "https://i.imgur.com/lT2nqls.png", "mode_name": "Standard" } elif mode == 1: #Taiko p = pyt.parser() beatmap = p.map(bmap) beatmapDict = { "title": beatmap.title, "artist": beatmap.artist, "creator": beatmap.creator, "version": beatmap.version, "objcount": 0, "mode": beatmap.mode, "maxcombo": None } playDict = { "totalhits": 0, "pp": "Not implemented.", "pp_fc": 0, "accuracy": acc.taikoCalc(count0, count100, count300), "accuracy_fc": 0 if perfect == 1 else acc.taikoCalc(0, count100, count300 + count0), "modString": modString if modString != "nomod" else "NM", "rating": "N/A", "completion": 100, "mode_icon": "https://i.imgur.com/G6bzM0X.png", "mode_name": "Taiko" } elif mode == 2: #CTB accuracy = acc.ctbCalc(count0, countkatu, count50, count100, count300) beatmap = Beatmap(bmap) p = pyt.parser() beatmapMetadata = p.map(bmap) difficulty = Difficulty(beatmap, mods) pp = 0 if calcPP == 1: pp = round(calculate_pp(difficulty, accuracy, combo, count0), 2) beatmapDict = { "title": beatmapMetadata.title, "artist": beatmapMetadata.artist, "creator": beatmapMetadata.creator, "version": beatmapMetadata.version, "objcount": len(beatmap.hitobjects), "mode": beatmapMetadata.mode, "maxcombo": beatmap.max_combo } playDict = { "totalhits": 0, "pp": pp, "pp_fc": 0, "accuracy": accuracy, "accuracy_fc": 0, "modString": modString if modString != "nomod" else "NM", "rating": round(difficulty.star_rating, 2), "completion": 100, "mode_icon": "https://i.imgur.com/EsanYkH.png", "mode_name": "Catch the Beat" } elif mode == 3: #Mania p = pyt.parser() beatmap = p.map(bmap) beatmapDict = { "title": beatmap.title, "artist": beatmap.artist, "creator": beatmap.creator, "version": beatmap.version, "objcount": 0, "mode": beatmap.mode, "maxcombo": None } playDict = { "totalhits": 0, "pp": "Not implemented.", "pp_fc": 0, "accuracy": acc.maniaCalc(count0, count50, count100, countkatu, count300, countgeki), "accuracy_fc": 0, "modString": modString if modString != "nomod" else "NM", "rating": "N/A", "completion": 100, "mode_icon": "https://i.imgur.com/0uZM1PZ.png", "mode_name": "Mania" } return beatmapDict, playDict
def display_play(api_link, api_key, response, response_number=0, mode=0): try: beatmap_info = requests.get( f'{api_link}get_beatmaps?k={api_key}&b={response.json()[response_number]["beatmap_id"]}&m={mode}' ) beatmap_info.json()[0] except IndexError: beatmap_info = requests.get( f'{api_link}get_beatmaps?k={api_key}&b={response.json()[response_number]["beatmap_id"]}&m={mode}&a=1' ) with open(image_data) as file: data = json.load(file) img = Image.new('RGBA', (900, 500), color=(0, 0, 0, 255)) black = Image.new('RGBA', (900, 500), color=(0, 0, 0, 0)) total_count = int(beatmap_info.json()[0]["count_normal"]) + int( beatmap_info.json()[0]["count_slider"]) + int( beatmap_info.json()[0]["count_spinner"]) accuracy = int(response.json()[response_number]["count300"]) + int( response.json()[response_number]["count100"]) * (1 / 3) + int( response.json()[response_number]["count50"]) * (1 / 6) count_sum = int(response.json()[response_number]["count300"]) + int( response.json()[response_number]["count100"]) + int( response.json()[response_number]["count50"]) + int( response.json()[response_number]["countmiss"]) completion = count_sum / total_count try: beatmap_cover = Image.open( requests.get( f'https://assets.ppy.sh/beatmaps/{beatmap_info.json()[0]["beatmapset_id"]}/covers/cover.jpg', stream=True).raw) except UnidentifiedImageError: beatmap_cover = Image.new('RGBA', (900, 500), color=(0, 0, 0, 0)) mod_list = [ 'NF', 'EZ', 'TD', 'HD', 'HR', 'SD', 'DT', '', 'HT', 'NC', 'FL', '', 'SO', '', 'PF', '', '', '', '', '', 'FI', '', '', '', '', '', '', '', '', '', 'MR' ] rank_colors = { 'F': (242, 56, 56), 'D': (242, 56, 56), 'C': (119, 57, 189), 'B': (57, 111, 244), 'A': (72, 248, 80), 'S': (245, 225, 90), 'X': (255, 223, 6), 'SH': (170, 183, 204), 'XH': (170, 183, 204) } mod_values = {'EZ': 2, 'HR': 16, 'DT': 64, 'NC': 64, 'HT': 256} pt35_light = ImageFont.truetype(lemon_milk_light, 35) pt30_light = ImageFont.truetype(lemon_milk_light, 30) pt25_light = ImageFont.truetype(lemon_milk_light, 25) pt20_light = ImageFont.truetype(lemon_milk_light, 20) pt200_regular = ImageFont.truetype(lemon_milk_regular, 200) pt50_regular = ImageFont.truetype(lemon_milk_regular, 50) pt35_regular = ImageFont.truetype(lemon_milk_regular, 35) special = ImageFont.truetype(special_characters, 25) beatmap_cover = beatmap_cover.resize((900, 250)) beatmap_cover = beatmap_cover.convert('RGBA') black_draw = ImageDraw.Draw(black) black_draw.rectangle(((0, 0), (900, 500)), fill=(0, 0, 0, 127)) img.paste(beatmap_cover, (0, 0)) img = Image.alpha_composite(img, black) draw = ImageDraw.Draw(img) draw.polygon(([0, 100, 900, 200, 900, 500, 0, 500]), fill=(47, 49, 54)) draw.line([(0, 100), (900, 200)], fill=(102, 104, 110), width=6) #-------------------- HEADER --------------------# if len(beatmap_info.json()[0]["version"]) >= 15: version = beatmap_info.json()[0]["version"][:15] + '...' else: version = beatmap_info.json()[0]["version"] if len(beatmap_info.json()[0]["title"]) >= 22: title = beatmap_info.json()[0]["title"][:22] + '...' else: title = beatmap_info.json()[0]["title"] draw.text((28, 18), f'{title}', fill=(255, 255, 255), font=pt35_light) draw.text((30, 55), f'{beatmap_info.json()[0]["creator"]}', fill=(255, 255, 255), font=pt20_light) draw.text((875, 28), f'[{version}]', fill=(255, 255, 255), font=pt30_light, anchor='rt') draw.text((875, 70), '★', fill=(255, 255, 255), font=special, anchor='rt') #-------------------- SCORES LEFT --------------------# draw.text((28, 150), f'{" ".join(response.json()[response_number]["score"])}', fill=(255, 255, 255), font=pt50_regular) draw.rectangle([(30, 220), (135, 260)], fill=(57, 111, 244)) draw.text((85, 227), '300', fill=(47, 49, 54), font=pt35_regular, anchor='mt') draw.text((155, 227), f'{response.json()[response_number]["count300"]}', fill=(255, 255, 255), font=pt35_light, anchor='lt') draw.rectangle([(30, 268), (135, 308)], fill=(72, 248, 80)) draw.text((85, 275), '100', fill=(47, 49, 54), font=pt35_regular, anchor='mt') draw.text((155, 275), f'{response.json()[response_number]["count100"]}', fill=(255, 255, 255), font=pt35_light, anchor='lt') draw.rectangle([(30, 316), (135, 356)], fill=(245, 225, 90)) draw.text((85, 323), '50', fill=(47, 49, 54), font=pt35_regular, anchor='mt') draw.text((155, 323), f'{response.json()[response_number]["count50"]}', fill=(255, 255, 255), font=pt35_light, anchor='lt') draw.rectangle([(30, 364), (135, 404)], fill=(242, 56, 56)) draw.text((85, 371), 'miss', fill=(47, 49, 54), font=pt35_regular, anchor='mt') draw.text((155, 371), f'{response.json()[response_number]["countmiss"]}', fill=(255, 255, 255), font=pt35_light, anchor='lt') #-------------------- SCORES RIGHT --------------------# draw.text((500, 227), 'accuracy:', fill=(255, 255, 255), font=pt35_light, anchor='rt') draw.text((510, 227), f'{round(accuracy/count_sum*100, 2)}%', fill=(142, 142, 142), font=pt35_light, anchor='lt') draw.text((500, 275), 'combo:', fill=(255, 255, 255), font=pt35_light, anchor='rt') draw.text( (520, 275), f'{response.json()[response_number]["maxcombo"]}/{beatmap_info.json()[0]["max_combo"]}', fill=(142, 142, 142), font=pt35_light, anchor='lt') draw.text((505, 290), 'x', fill=(142, 142, 142), font=special, anchor='lt') if 'H' in response.json()[response_number]["rank"]: rank = response.json()[response_number]["rank"][:-1] else: rank = response.json()[response_number]["rank"] if 'X' in response.json()[response_number]["rank"]: rank = 'SS' draw.text((800, 250), f'{rank}', fill=rank_colors[response.json()[response_number]["rank"]], font=pt200_regular, anchor='mt') if count_sum != total_count: draw.text((30, 458), '.', fill=(255, 255, 255), font=pt50_regular, anchor='lt') draw.text((50, 450), f'completion: {round(completion*100, 2)}%', fill=(142, 142, 142), font=pt25_light, anchor='lt') draw.text((870, 458), f'{response.json()[response_number]["date"]}', fill=(142, 142, 142), font=pt25_light, anchor='rt') mod_code = int(response.json()[response_number]['enabled_mods']) mod_code = list(bin(mod_code)[2:]) mod_code.reverse() if len(mod_code) == 1 and mod_code[0] == '0': mods = [Image.fromarray(np.array(data['NM'], dtype=np.uint8))] else: mods = [ Image.fromarray(np.array(data[mod_list[x]], dtype=np.uint8)) for x in range(len(mod_code)) if mod_code[x] == '1' ] mod_request = [ mod_list[x] for x in range(len(mod_code)) if mod_code[x] == '1' ] if ('SD' in mods) and ('PF' in mods): mods.remove(Image.fromarray(np.array(data['SD'], dtype=np.uint8))) if ('DT' in mod_request) and ('NC' in mod_request): mod_request.remove('DT') mods.remove(Image.fromarray(np.array(data['DT'], dtype=np.uint8))) if any(item in ['EZ', 'HR', 'DT', 'NC', 'HT'] for item in mod_request): mod_request = sum([ mod_values[x] for x in mod_request if x in ['EZ', 'HR', 'DT', 'NC', 'HT'] ]) try: beatmap_info = requests.get( f'{api_link}get_beatmaps?k={api_key}&b={response.json()[response_number]["beatmap_id"]}&mods={mod_request}&m={mode}' ) beatmap_info.json()[0] except IndexError: beatmap_info = requests.get( f'{api_link}get_beatmaps?k={api_key}&b={response.json()[response_number]["beatmap_id"]}&mods={mod_request}&m={mode}&a=1' ) draw.text((850, 70), f'{round(float(beatmap_info.json()[0]["difficultyrating"]),2)}', fill=(255, 255, 255), font=pt25_light, anchor='rt') if response_number == 0: try: pp, _, _, _, _ = osu.ppv2( aim_stars=float(beatmap_info.json()[0]["diff_aim"]), speed_stars=float(beatmap_info.json()[0]["diff_speed"]), max_combo=int(beatmap_info.json()[0]["max_combo"]) * completion, nsliders=int(beatmap_info.json()[0]["count_slider"]) * completion, ncircles=int(beatmap_info.json()[0]["count_normal"]) * completion, nobjects=int(beatmap_info.json()[0]["count_spinner"]) * completion, base_ar=float(beatmap_info.json()[0]["diff_approach"]), base_od=float(beatmap_info.json()[0]["diff_overall"]), mode=int(beatmap_info.json()[0]["mode"]), mods=int(response.json()[response_number]["enabled_mods"]), combo=int(response.json()[response_number]["maxcombo"]), n300=int(response.json()[response_number]["count300"]), n100=int(response.json()[response_number]["count100"]), n50=int(response.json()[response_number]["count50"]), nmiss=int(response.json()[response_number]["countmiss"]), score_version=1) pp = round(pp, 2) except TypeError: pp = 'NaN' else: pp = round(float(response.json()[response_number]["pp"]), 2) try: fc_pp, _, _, _, _ = osu.ppv2( aim_stars=float(beatmap_info.json()[0]["diff_aim"]), speed_stars=float(beatmap_info.json()[0]["diff_speed"]), max_combo=int(beatmap_info.json()[0]["max_combo"]), nsliders=int(beatmap_info.json()[0]["count_slider"]), ncircles=int(beatmap_info.json()[0]["count_normal"]), nobjects=int(beatmap_info.json()[0]["count_spinner"]), base_ar=float(beatmap_info.json()[0]["diff_approach"]), base_od=float(beatmap_info.json()[0]["diff_overall"]), mode=int(beatmap_info.json()[0]["mode"]), mods=int(response.json()[response_number]["enabled_mods"]), combo=int(beatmap_info.json()[0]["max_combo"]), n300=int(response.json()[response_number]["count300"]) + int(response.json()[response_number]["countmiss"]), n100=int(response.json()[response_number]["count100"]), n50=int(response.json()[response_number]["count50"]), nmiss=0, score_version=1) fc_pp = round(fc_pp, 2) except TypeError: fc_pp = 'NaN' draw.text((500, 323), 'pp:', fill=(255, 255, 255), font=pt35_light, anchor='rt') draw.text((510, 323), f'{pp}', fill=(142, 142, 142), font=pt35_light, anchor='lt') draw.text((875, 112), 'pp', fill=(255, 255, 255), font=pt25_light, anchor='rt') draw.text((840, 112), f'{fc_pp}', fill=(255, 255, 255), font=pt25_light, anchor='rt') mod_bg = Image.new('RGBA', (len(mods) * 71, 50), color=(47, 49, 54, 255)) a = Image.new('RGBA', (len(mods) * 71, 50), color=(47, 49, 54, 255)) [a.paste(mods[x].resize((71, 50)), (71 * x, 0)) for x in range(len(mods))] a = Image.alpha_composite(mod_bg, a) if len(mods) == 7: img.paste(a, (218, 355)) else: img.paste(a, (290, 355)) return img