public static void Main(string[] args) { Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)); DebugController debugger = new DebugController(); //Load in custom beatmaps if specified args = debugger.LoadCustom(args); //Display a message if no files are specified if (args.Length == 0) { Console.WriteLine("CTB Difficulty Analyzer"); Console.WriteLine("Just drag your beatmap (.osu file) onto this program to measure difficulty"); Console.WriteLine("Press any key to exit..."); } //Otherwise try to run the program, and catch and display any exceptions that arise else { Console.WriteLine("Calculating..."); SortedList <double, string> beatmaps = new SortedList <double, string>(); List <DiffCalc> calculators = new List <DiffCalc>(); Stopwatch timer = new Stopwatch(); try { int count = 0; foreach (string name in args) { timer.Start(); Beatmap map = new Beatmap(name); DiffCalc calc; try { calc = new DiffCalc(map); } catch (InvalidBeatmapException) { //Skip this beatmap if it's not a standard or ctb map, but only if //it was loaded through debug if (debugger.IsLoadCustom()) { continue; } else { throw; } } string title = calc.GetBeatmapTitle() + ": \t"; double difficulty = calc.GetDifficulty(); timer.Stop(); title += timer.ElapsedMilliseconds; beatmaps[difficulty] = title; calculators.Add(calc); timer.Reset(); count++; Console.Write(Math.Round((double)count * 100 / args.Length) + "%\r"); } Console.WriteLine("\n"); for (int i = beatmaps.Count - 1; i >= 0; i--) { string[] titleandtime = beatmaps.Values[i].Split('\t'); Console.WriteLine(titleandtime[0] + beatmaps.Keys[i]); Console.WriteLine("Calculation Time (ms): " + titleandtime[1] + "\n"); } debugger.WriteDebug(calculators.ToArray()); Console.WriteLine("\nDone."); } catch (Exception e) { Console.WriteLine(e); } finally { //Just in case the timer is still running timer.Stop(); } } Console.ReadKey(); }
private void ComputeTotalValue() { // Don't count scores made with supposedly unranked mods if (((int)mods & (int)Modifiers.Relax) > 0 || ((int)mods & (int)Modifiers.Relax2) > 0 || ((int)mods & (int)Modifiers.Autoplay) > 0) { totalvalue = 0; return; } // We are heavily relying on aim in catch the beat totalvalue = Math.Pow(5.0 * Math.Max(1.0, difficulty.GetDifficulty() / 0.0049) - 4.0, 2.0) / 100000.0; // Longer maps are worth more. "Longer" means how many hits there are which can contribute to combo int amountTotalHits = TotalHits(); // Longer maps are worth more double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, amountTotalHits / 3000.0) + (amountTotalHits > 3000 ? Math.Log10(amountTotalHits / 3000.0) * 0.5 : 0.0); // Longer maps are worth more totalvalue *= lengthBonus; // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available totalvalue *= Math.Pow(0.97, amountMiss); // Combo scaling double beatmapMaxCombo = TotalComboHits(); if (beatmapMaxCombo > 0) { totalvalue *= Math.Min(Math.Pow(maxCombo, 0.8) / Math.Pow(beatmapMaxCombo, 0.8), 1.0); } double approachRate = Double.Parse(map.GetTag("Difficulty", "ApproachRate"), CultureInfo.InvariantCulture); double approachRateFactor = 1.0; if (approachRate > 9.0) { approachRateFactor += 0.1 * (approachRate - 9.0); // 10% for each AR above 9 } else if (approachRate < 8.0) { approachRateFactor += 0.025 * (8.0 - approachRate); //2.5% for each AR below 8 } totalvalue *= approachRateFactor; if (((int)mods & (int)Modifiers.Hidden) > 0) { // Hiddens gives nothing on max approach rate, and more the lower it is totalvalue *= 1.05 + 0.075 * (10.0 - Math.Min(10.0, approachRate)); // 7.5% for each AR below 10 } // Scale the aim value with accuracy _slightly_ totalvalue *= Math.Pow(Accuracy(), 5.5); // Custom multipliers for NoFail and SpunOut. if (((int)mods & (int)Modifiers.NoFail) > 0) { totalvalue *= 0.90; } if (((int)mods & (int)Modifiers.SpunOut) > 0) { totalvalue *= 0.95; } }