Esempio n. 1
0
        public static double CalcRating(BeatmapInfo map)
        {
            //  Call PatternAnalyzer to find Jacks / Spams.
            var analyzer = new PatternAnalyzer(map.Notes, map.LNs, map.Data.Keys, map.Data.SpecialStyle);
            var jacks    = analyzer.GetJackRatio();
            var spams    = analyzer.GetSpamRatio();

            //  Spam correction.
            //  Deduct 'Corrected Max Density' and 'Corrected Average Density' by exponential function.
            var corMaxDen = map.CorMaxDen * (1 - (Math.Pow(78, spams) - 1) / 100);
            var corAvgDen = map.CorAvgDen * (1 - (Math.Pow(78, spams) - 1) / 100);

            //  Start from 'Corrected Max Density'
            var result = corMaxDen;

            //  Density correction.
            //  If 'Corrected Average Density' is really close with 'Corrected Max Density',
            if (corMaxDen <= corAvgDen * 1.1)
            {
                //  then it means it's quite hard compared with its max density.
                //  Get bonus score.
                result += corAvgDen * 0.1;
            }

            //  If 'Corrected Average Density' is too low than 'Corrected Max Density',
            else if (corMaxDen >= 3 && corMaxDen >= corAvgDen * 1.5)
            {
                //  then it means it's quite easy compared with its max density.
                //  Deduct rating score.
                result -= corMaxDen * 0.1;
            }

            //  General correction for density.
            var correction = Math.Pow(6, Math.Log(corMaxDen, corAvgDen + corMaxDen)) - 1;

            result *= 1 - correction / 10;

            //  Jack correction.
            //  Increase Rating by exponential function.
            result *= 1 + (Math.Pow(101, jacks) - 1) / 100;

            //  Key correction.
            //  Standard: 6k.
            //  Other key modes' rating value is set to 6k like '(key + 1) / 7'.
            //  If it's special style, than key -= 1.
            var specialStyle = map.Data.Keys == 8 && (double)(analyzer.Notes[0].Count + analyzer.LNs[0].Count) / analyzer.Count < 0.06;

            result *= (double)((specialStyle ? map.Data.Keys - 1 : map.Data.Keys) + 1) / 7;

            //  Multiply it only for convenience.
            result *= 1.6;

            return(result);
        }
Esempio n. 2
0
        private static void CalcCorrectedDensityList(ref List <Note> notes, ref List <LongNote> lns, int key, out List <double> density)
        {
            int Key;
            var pat = new PatternAnalyzer(notes, lns, key, false);

            var corNotes = new List <NoteCount>();
            var corLNs   = new List <LongNoteCount>();

            var Notes = new List <Note>();
            var LNs   = new List <LongNote>();

            density = new List <double>();
            var specialStyle = key == 8 && (double)(pat.Notes[0].Count + pat.LNs[0].Count) / pat.Count < 0.06;

            if (!specialStyle)
            {
                Notes = notes;
                LNs   = lns;
                Key   = key;
            }
            else
            {
                Notes.AddRange(notes.Where(cur => cur.Line != 0));
                LNs.AddRange(lns.Where(cur => cur.Line != 0));
                Key = key - 1;
            }

            var(startPeriod, endPeriod) = GetPeriods(ref notes, ref lns);
            for (var i = startPeriod; i < endPeriod - 1000; i += 250)
            {
                corNotes.Clear();
                corLNs.Clear();

                //  Get the notes in current period.
                corNotes.AddRange(from cur in Notes where cur.Time >= i && cur.Time <= i + 1000 select new NoteCount(cur.Time, cur.Line, 0));

                corLNs.AddRange(
                    from cur in LNs where (cur.Time >= i && cur.Time <= i + 1000) ||
                    (cur.Endtime >= i && cur.Endtime <= i + 1000) ||
                    (cur.Time <= i && cur.Endtime >= i + 1000)
                    select new LongNoteCount(cur.Time, cur.Endtime, cur.Line, 0));

                //  Count the LN-count for each notes.
                foreach (var cur in corLNs)
                {
                    foreach (var note in corNotes)
                    {
                        if (note.Time >= cur.Time && note.Time < cur.Endtime)
                        {
                            note.LNs++;
                        }
                    }

                    for (var j = corLNs.IndexOf(cur) + 1; j < corLNs.Count; j++)
                    {
                        if ((corLNs[j].Time >= cur.Time && corLNs[j].Time < cur.Endtime) ||
                            (corLNs[j].Endtime >= cur.Time && corLNs[j].Endtime <= cur.Endtime) ||
                            (corLNs[j].Time <= cur.Time && corLNs[j].Endtime >= cur.Endtime))
                        {
                            corLNs[j].LNs++;
                        }
                    }
                }

                //  Correct the density.
                var den = (corNotes.Sum(cur => (double)Key / (Key - cur.LNs))
                           + corLNs.Sum(cur => (double)Key / (Key - cur.LNs) * 1.1)) / Key;

                density.Add(den);
            }
        }