Exemple #1
0
        protected virtual void runSanityRules()
        {
            List <HitObjectBase> hitObjects = hitObjectManager.GetHitObjects();

            for (int i = 0; i < hitObjects.Count; i++)
            {
                bool          isLast = i == hitObjects.Count - 1;
                HitObjectBase h      = hitObjects[i];
                HitObjectBase h1     = isLast ? null : hitObjects[i + 1];
                //Check for hitobjects which share the same startTime...
                if (i > 0 && !isLast)
                {
                    if (hitObjects[i].StartTime != hitObjects[i + 1].StartTime && hitObjects[i].StartTime < hitObjects[i - 1].EndTime + 10)
                    {
                        HitObjectBase last = hitObjects[i - 1];
                        Reports.Add(new AiReportTwoObjects(last, h, delegate { return(Math.Abs(last.StartTime - h.StartTime) > 10); }, Severity.Error, LocalisationManager.GetString(OsuString.AICompose_ObjectsTooClose), -1));
                    }
                }

                //check snap
                if (AiMod.TestBeatSnap(h.StartTime, true))
                {
                    int      index  = i;
                    AiReport report = new AiReportOneObject(h, h.StartTime, delegate { return(AiMod.TestBeatSnap(h.StartTime, true)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_UnsnappedObject), 0);
                    Reports.Add(report);
                }

                if (h.EndTime != h.StartTime)
                {
                    if (AiMod.TestBeatSnap(h.EndTime, true)) //Need to account for slider velocity buffer.
                    {
                        int      index  = i;
                        AiReport report = new AiReportOneObject(h, h.EndTime, delegate { return(AiMod.TestBeatSnap(h.EndTime, true)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_UnsnappedObjectEnd), 0);
                        Reports.Add(report);
                    }
                }
            }
        }
Exemple #2
0
        protected override void runComposeRules()
        {
            HitObjectManager     hom        = hitObjectManager as HitObjectManager;
            List <HitObjectBase> hitObjects = hitObjectManager.GetHitObjects();

            int column = (int)Math.Round(BeatmapManager.Current.DifficultyCircleSize);
            List <Dictionary <int, int> > columns = new List <Dictionary <int, int> >(column);

            int[] pressArr         = new int[column];
            int[] lastNoteInColumn = new int[column]; // used to check distance between notes on the same column
            for (int i = 0; i < column; i++)
            {
                columns.Add(new Dictionary <int, int>());
            }

            for (int i = 0; i < hitObjects.Count; i++)
            {
                HitObjectBase h   = hitObjects[i];
                int           col = hom.ManiaStage.ColumnAt(h.Position);

                //check snap
                if (AiMod.TestBeatSnap(h.StartTime, false))
                {
                    AiReport report = new AiReportOneObject(h, h.StartTime, delegate { return(AiMod.TestBeatSnap(h.StartTime, false)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_UnsnappedObject), 0);
                    Reports.Add(report);
                }

                if (h.IsType(HitObjectType.Hold))
                {
                    if (h.EndTime - h.StartTime < 10)
                    {
                        Reports.Add(new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AIComposeMania_HoldNoteTooShort), 0));
                    }

                    if (AiMod.TestBeatSnap(h.EndTime, false))
                    {
                        AiReport report = new AiReportOneObject(h, h.EndTime, delegate { return(AiMod.TestBeatSnap(h.EndTime, false)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_UnsnappedObjectEnd), 0);
                        Reports.Add(report);
                    }
                }

                if (h.StartTime != lastNoteInColumn[col] && lastNoteInColumn[col] != 0 && h.StartTime < lastNoteInColumn[col] + 10)
                {
                    Reports.Add(new AiReportOneObject(h, h.StartTime, delegate { return(Math.Abs(lastNoteInColumn[col] - h.StartTime) > 10); }, Severity.Error, LocalisationManager.GetString(OsuString.AICompose_ObjectsTooClose), -1));
                }

                //check for 7 notes simultaneously
                int existCount = 1;
                for (int j = 0; j < column; j++)
                {
                    if (pressArr[j] >= h.StartTime)
                    {
                        existCount++;
                    }
                }
                //pressArr[col] = h.EndTime;
                if (h.StartTime == h.EndTime)
                {
                    pressArr[col] = h.StartTime;
                }
                else
                {
                    pressArr[col] = h.EndTime - 2;//hack, holds' end are not counted here.
                }
                if (existCount >= 7)
                {
                    AiReportOneObject report = new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AIComposeMania_TooManyNotes), 0);
                    Reports.Add(report);
                }
                //note stack on another note's startTime
                if (columns[col].ContainsKey(h.StartTime) || columns[col].ContainsKey(h.EndTime))
                {
                    AiReportOneObject report = new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AIComposeMania_StackedObjects), 0);
                    Reports.Add(report);
                    continue;
                }
                bool needReport = false;
                foreach (KeyValuePair <int, int> pair in columns[col])
                {
                    //normal note, already checked above
                    if (pair.Key == pair.Value)
                    {
                        continue;
                    }
                    if (h.StartTime <= pair.Key && h.EndTime >= pair.Key)
                    {
                        needReport = true;
                        break;
                    }
                    if (h.StartTime <= pair.Value && h.EndTime >= pair.Value)
                    {
                        needReport = true;
                        break;
                    }
                    if (h.StartTime >= pair.Key && h.EndTime <= pair.Value)
                    {
                        needReport = true;
                        break;
                    }
                    if (h.StartTime < pair.Key && h.EndTime > pair.Value)
                    {
                        needReport = true;
                        break;
                    }
                }
                if (needReport)
                {
                    AiReportOneObject report = new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AIComposeMania_OverlappingObject), 0);
                    Reports.Add(report);
                    continue;
                }
                else
                {
                    columns[col][h.StartTime] = h.EndTime;
                }

                // we don't want to mark this note as the previous note in the column until it's been processed
                lastNoteInColumn[col] = h.StartTime;
            }
        }
Exemple #3
0
        protected virtual void runTimingRules()
        {
            List <HitObjectBase> hitObjects = hitObjectManager.GetHitObjects();

            int mapEndTime  = 0;
            int drainLength = 0;

            if (hitObjects.Count > 0)
            {
                mapEndTime  = hitObjects[hitObjects.Count - 1].EndTime;
                drainLength = mapEndTime - hitObjects[0].StartTime;

                if (drainLength > 6 * 60 * 1000)
                {
                    Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_BeatmapTooLong), -1, null));
                }
                else if (drainLength < 45000)
                {
                    Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_BeatmapTooShort), -1, null));
                }
                if (drainLength * 1.0 / (AudioEngine.AudioLength - hitObjects[0].StartTime) < 0.8)
                {
                    Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_Mp3LongerThanMap), -1, null));
                }
            }

            List <ControlPoint> points = AudioEngine.ControlPoints;

            int          kiaiToggleCount   = 0;
            int          kiaiLength        = 0;
            List <float> SliderMultipliers = new List <float>();
            bool         kiaiOn            = false;
            double       lastKiaiEndTime   = 0;
            int          lowVolumeCount    = 0;
            int          stackedPointCount = 0;

            for (int i = 0; i < points.Count; i++)
            {
                ControlPoint p = points[i];

                //overlap
                int startOffset = (int)p.Offset;
                int endOffset   = i == points.Count - 1 ? mapEndTime : (int)points[i + 1].Offset;

                int timingLength = endOffset - startOffset;

                if (timingLength > 0)
                {
                    if (p.KiaiMode)
                    {
                        kiaiLength += timingLength;
                        if (i > 0 && !points[i - 1].KiaiMode)
                        {
                            kiaiToggleCount++;
                        }
                    }
                }

                //Check for duplicate control points
                if (i > 0 && startOffset == (int)points[i - 1].Offset)
                {
                    stackedPointCount++;
                    for (int z = 1; z <= stackedPointCount; z++)
                    {
                        if (p.TimingChange == points[i - z].TimingChange)
                        {
                            Reports.Add(new AiReport(startOffset, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_OverlappingTimingPoints), 0, null));
                            break;
                        }
                    }
                }
                else
                {
                    stackedPointCount = 0;
                }

                //snap
                if (p.KiaiMode && !kiaiOn)
                {
                    kiaiOn = true;
                    if (AiMod.TestBeatSnap(startOffset, false))
                    {
                        Reports.Add(new AiReport(startOffset, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_UnsnappedKiai), 0, null));
                    }
                    if (p.Offset - lastKiaiEndTime < 15000 && p.Offset - lastKiaiEndTime > 10)
                    {
                        Reports.Add(new AiReport(startOffset, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_KiaiTooShort), -1, null));
                    }
                }
                else if (!p.KiaiMode && kiaiOn)
                {
                    kiaiOn = false;
                    if (AiMod.TestBeatSnap(startOffset, false))
                    {
                        Reports.Add(new AiReport(startOffset, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_UnsnappedKiaiEnd), 0, null));
                    }
                    lastKiaiEndTime = p.Offset;
                }

                //volume
                if (p.Volume < 5)
                {
                    lowVolumeCount++;
                }
            }

            //zero volume
            if (lowVolumeCount == points.Count)
            {
                Reports.Add(new AiReport(Severity.Error, LocalisationManager.GetString(OsuString.AITiming_AllTimingSectionsQuiet)));
            }
            else if (lowVolumeCount > 0)
            {
                Reports.Add(new AiReport(Severity.Warning, string.Format(LocalisationManager.GetString(OsuString.AITiming_SomeTimingSectionsQuiet), lowVolumeCount, points.Count)));
            }

            //KIAI
            if (drainLength > 3 * 60 * 1000 && kiaiLength > drainLength / 3)
            {
                Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_TooMuchKiai), -1, null));
            }
            else if (drainLength < 90 * 1000 && kiaiLength > drainLength / 2)
            {
                Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_TooMuchKiaiTvSize), -1, null));
            }

            if (BeatmapManager.Current.PreviewTime < 0)
            {
                Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_NoPreviewPoint), -1, null));
            }
            if (kiaiOn)
            {
                Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_NoKiaiEnd), -1, null));
            }

            //audio quality
            TAG_INFO info = AudioEngine.GetAudioTagInfo();

            if (info != null)
            {
                if (info.bitrate < 128)
                {
                    Reports.Add(new AiReport(Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_LowAudioBitrate)));
                }
                else if (info.bitrate > 192)
                {
                    Reports.Add(new AiReport(Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_HighAudioBitrate)));
                }
            }
        }