private double GetPp(Beatmap beatmap, double acc, Mods mods = Mods.NoMod) { _accCalculator = new Accuracy(acc, beatmap.Objects.Count, 0); _ppCalculator = new PPv2(new PPv2Parameters(beatmap, _accCalculator.Count100, _accCalculator.Count50, _accCalculator.CountMiss, -1, _accCalculator.Count300, mods)); return(Math.Round(_ppCalculator.Total, 2)); }
public Dictionary <string, string> GetMapReplacements(MapSearchResult map) { var ret = new Dictionary <string, string> { { "!MaxCombo!", "" }, { "!SSPP!", "" }, { "!99.9PP!", "" }, { "!99PP!", "" }, { "!98PP!", "" }, { "!95PP!", "" }, { "!90PP!", "" }, { "!mMod!", "" }, { "!mSSPP!", "" }, { "!m99.9PP!", "" }, { "!m99PP!", "" }, { "!m98PP!", "" }, { "!m95PP!", "" }, { "!m90PP!", "" }, }; if (!map.FoundBeatmaps) { return(ret); } if (map.BeatmapsFound[0].PlayMode != PlayMode.Osu) { return(ret); } var mapLocation = map.BeatmapsFound[0].FullOsuFileLocation(BeatmapHelpers.GetFullSongsLocation(_settings)); if (!File.Exists(mapLocation)) { return(ret); } FileInfo file = new FileInfo(mapLocation); Thread.Sleep(50);//If we acquire lock before osu it'll force "soft" beatmap reprocessing(no data loss, but time consuming). while (FileIsLocked(file)) { Thread.Sleep(1); } if (file.Length == 0) { return(ret); } try { using (var stream = new FileStream(mapLocation, FileMode.Open)) { using (var reader = new StreamReader(stream)) { var beatmap = Beatmap.Read(reader); ret["!MaxCombo!"] = beatmap.GetMaxCombo().ToString(CultureInfo.InvariantCulture); ret["!SSPP!"] = GetPp(beatmap, 100d).ToString(CultureInfo.InvariantCulture); ret["!99.9PP!"] = GetPp(beatmap, 99.9d).ToString(CultureInfo.InvariantCulture); ret["!99PP!"] = GetPp(beatmap, 99d).ToString(CultureInfo.InvariantCulture); ret["!98PP!"] = GetPp(beatmap, 98d).ToString(CultureInfo.InvariantCulture); ret["!95PP!"] = GetPp(beatmap, 95d).ToString(CultureInfo.InvariantCulture); ret["!90PP!"] = GetPp(beatmap, 90d).ToString(CultureInfo.InvariantCulture); Mods mods; string modsStr; if (map.Action == OsuStatus.Playing || map.Action == OsuStatus.Watching) { mods = (map.Mods?.Item1 ?? CollectionManager.DataTypes.Mods.Omod).Convert(); modsStr = map.Mods?.Item2 ?? "NM"; _lastMods = mods; _lastModsStr = modsStr; } else { mods = _lastMods; modsStr = _lastModsStr; } ret["!mMod!"] = modsStr; ret["!mSSPP!"] = GetPp(beatmap, 100d, mods).ToString(CultureInfo.InvariantCulture); ret["!m99.9PP!"] = GetPp(beatmap, 99.9d, mods).ToString(CultureInfo.InvariantCulture); ret["!m99PP!"] = GetPp(beatmap, 99d, mods).ToString(CultureInfo.InvariantCulture); ret["!m98PP!"] = GetPp(beatmap, 98d, mods).ToString(CultureInfo.InvariantCulture); ret["!m95PP!"] = GetPp(beatmap, 95d, mods).ToString(CultureInfo.InvariantCulture); ret["!m90PP!"] = GetPp(beatmap, 90d, mods).ToString(CultureInfo.InvariantCulture); } } return(ret); } catch { return(ret); } }
/// <summary> /// Reads a beatmap from a file. /// </summary> /// <returns><see cref="Beatmap"/></returns> public static Beatmap Read(StreamReader reader) { var bm = new Beatmap(); string line, section = null; while ((line = reader.ReadLine()?.Trim()) != null) { //any comments if (line.StartsWith("_") || line.StartsWith("//")) { continue; } whileLoopStart: //don't continue here, the read methods will start reading at the next line if (line.StartsWith("[")) { section = line.Substring(1, line.Length - 2); } if (line.Length <= 0) { continue; } switch (section) { case "Metadata": foreach (var s in ReadSectionPairs(reader, out line)) { var val = s.Value; switch (s.Key) { case "Title": bm.Title = val; break; case "TitleUnicode": bm.TitleUnicode = val; break; case "Artist": bm.Artist = val; break; case "ArtistUnicode": bm.ArtistUnicode = val; break; case "Creator": bm.Creator = val; break; case "Version": bm.Version = val; break; } } break; case "General": foreach (var pair in ReadSectionPairs(reader, out line)) { if (pair.Key == "Mode") { bm.Mode = (GameMode)int.Parse(pair.Value); } } break; case "Difficulty": bool arFound = false; foreach (var s in ReadSectionPairs(reader, out line)) { var val = s.Value; switch (s.Key) { case "CircleSize": bm.CS = float.Parse(val, CultureInfo.InvariantCulture); break; case "OverallDifficulty": bm.OD = float.Parse(val, CultureInfo.InvariantCulture); break; case "ApproachRate": bm.AR = float.Parse(val, CultureInfo.InvariantCulture); arFound = true; break; case "HPDrainRate": bm.HP = float.Parse(val, CultureInfo.InvariantCulture); break; case "SliderMultiplier": bm.SliderVelocity = float.Parse(val, CultureInfo.InvariantCulture); break; case "SliderTickRate": bm.TickRate = float.Parse(val, CultureInfo.InvariantCulture); break; } } if (!arFound) { bm.AR = bm.OD; } break; case "TimingPoints": foreach (var ptLine in ReadSectionLines(reader, out line)) { string[] splitted = ptLine.Split(','); if (splitted.Length > 8) { Warn("timing point with trailing values"); } else if (splitted.Length < 2) { Warn("timing point with too little values"); continue; } var t = new Timing { Time = double.Parse(splitted[0], CultureInfo.InvariantCulture), MsPerBeat = double.Parse(splitted[1], CultureInfo.InvariantCulture) }; if (splitted.Length >= 7) { t.Change = splitted[6].Trim() != "0"; } bm.TimingPoints.Add(t); } break; case "HitObjects": foreach (var objLine in ReadSectionLines(reader, out line)) { string[] s = objLine.Split(','); if (s.Length > 11) { Warn("object with trailing values"); } else if (s.Length < 5) { Warn("object with too little values"); continue; } var obj = new HitObject { Time = double.Parse(s[2], CultureInfo.InvariantCulture), Type = (HitObjectType)int.Parse(s[3]) }; if ((obj.Type & HitObjectType.Circle) != 0) { bm.CountCircles++; obj.Data = new Circle { Position = new Vector2 { X = double.Parse(s[0], CultureInfo.InvariantCulture), Y = double.Parse(s[1], CultureInfo.InvariantCulture) } }; } if ((obj.Type & HitObjectType.Spinner) != 0) { bm.CountSpinners++; } if ((obj.Type & HitObjectType.Slider) != 0) { bm.CountSliders++; obj.Data = new Slider { Position = { X = double.Parse(s[0], CultureInfo.InvariantCulture), Y = double.Parse(s[1], CultureInfo.InvariantCulture) }, Repetitions = int.Parse(s[6]), Distance = double.Parse(s[7], CultureInfo.InvariantCulture) }; } bm.Objects.Add(obj); } break; default: int fmtIndex = line.IndexOf("file format v", StringComparison.Ordinal); if (fmtIndex < 0) { continue; } bm.FormatVersion = int.Parse(line.Substring(fmtIndex + "file format v".Length)); break; } //in hand-edited beatmap, it's possible that the section header doesn't come after a newline //if that is the case, this check stops us from skipping this line if (line?.StartsWith("[") == true) { goto whileLoopStart; } } return(bm); }