示例#1
0
        private static string ObjectsAsString(HitObject hitObject, HitObject otherHitObject)
        {
            string type      = hitObject.GetObjectType();
            string otherType = otherHitObject.GetObjectType();

            return
                (type == otherType ?
                 type + "s" :
                 type + " and " + otherType);
        }
        public override IEnumerable <DiffInstance> Translate(IEnumerable <DiffInstance> aDiffs)
        {
            List <Tuple <DiffInstance, HitObject> > addedHitObjects   = new List <Tuple <DiffInstance, HitObject> >();
            List <Tuple <DiffInstance, HitObject> > removedHitObjects = new List <Tuple <DiffInstance, HitObject> >();

            foreach (DiffInstance diff in aDiffs)
            {
                HitObject hitObject = null;
                try
                { hitObject = new HitObject(diff.difference.Split(','), beatmap: null); }
                catch
                {
                    // Cannot yield in a catch clause, so checks for null in the following statement instead.
                }

                if (hitObject != null)
                {
                    if (diff.diffType == DiffType.Added)
                    {
                        addedHitObjects.Add(new Tuple <DiffInstance, HitObject>(diff, hitObject));
                    }
                    else
                    {
                        removedHitObjects.Add(new Tuple <DiffInstance, HitObject>(diff, hitObject));
                    }
                }
                else
                {
                    // Failing to parse a changed line shouldn't stop it from showing.
                    yield return(diff);
                }
            }

            foreach (var(addedDiff, addedObject) in addedHitObjects)
            {
                string stamp = Timestamp.Get(addedObject.time);
                string type  = addedObject.GetObjectType();

                bool             found          = false;
                List <HitObject> removedObjects = removedHitObjects.Select(aTuple => aTuple.Item2).ToList();
                foreach (var removedObject in removedObjects)
                {
                    if (addedObject.time.AlmostEqual(removedObject.time))
                    {
                        string removedType = removedObject.GetObjectType();

                        if (type != removedType)
                        {
                            continue;
                        }

                        List <string> changes = GetChanges(addedObject, removedObject).ToList();

                        if (changes.Count == 1)
                        {
                            yield return(new DiffInstance(stamp + changes[0],
                                                          Section, DiffType.Changed, new List <string>(), addedDiff.snapshotCreationDate));
                        }
                        else if (changes.Count > 1)
                        {
                            yield return(new DiffInstance(stamp + type + " changed.",
                                                          Section, DiffType.Changed, changes, addedDiff.snapshotCreationDate));
                        }

                        found = true;
                        var o = removedObject;
                        removedHitObjects.RemoveAll(aTuple => aTuple.Item2.code == o.code);
                    }
                    else
                    {
                        // First check all following objects and see what happened to them. Once we get to a point where
                        // time and properties match up again, we can go back here and check these until that point.

                        // If the only difference is time, the object was most likely just offset.
                    }
                }

                if (!found)
                {
                    yield return(new DiffInstance(stamp + type + " added.",
                                                  Section, DiffType.Added, new List <string>(), addedDiff.snapshotCreationDate));
                }
            }

            foreach (Tuple <DiffInstance, HitObject> removedTuple in removedHitObjects)
            {
                DiffInstance removedDiff   = removedTuple.Item1;
                HitObject    removedObject = removedTuple.Item2;

                string stamp = Timestamp.Get(removedObject.time);
                string type  = removedObject.GetObjectType();

                yield return(new DiffInstance(stamp + type + " removed.",
                                              Section, DiffType.Removed, new List <string>(), removedDiff.snapshotCreationDate));
            }
        }
        private IEnumerable <string> GetChanges(HitObject addedObject, HitObject removedObject)
        {
            if (addedObject.Position != removedObject.Position)
            {
                yield return("Moved from " + removedObject.Position.X + "; " + removedObject.Position.Y +
                             " to " + addedObject.Position.X + "; " + addedObject.Position.Y + ".");
            }

            if (addedObject.hitSound != removedObject.hitSound)
            {
                foreach (HitObject.HitSound hitSound in Enum.GetValues(typeof(HitObject.HitSound)))
                {
                    if (addedObject.HasHitSound(hitSound) && !removedObject.HasHitSound(hitSound))
                    {
                        yield return("Added " + Enum.GetName(typeof(HitObject.HitSound), hitSound)?.ToLower() + ".");
                    }

                    if (!addedObject.HasHitSound(hitSound) && removedObject.HasHitSound(hitSound))
                    {
                        yield return("Removed " + Enum.GetName(typeof(HitObject.HitSound), hitSound)?.ToLower() + ".");
                    }
                }
            }

            if (addedObject.sampleset != removedObject.sampleset)
            {
                yield return("Sampleset changed from " +
                             removedObject.sampleset.ToString().ToLower() + " to " +
                             addedObject.sampleset.ToString().ToLower() + ".");
            }

            if (addedObject.addition != removedObject.addition)
            {
                yield return("Addition changed from " +
                             removedObject.addition.ToString().ToLower() + " to " +
                             addedObject.addition.ToString().ToLower() + ".");
            }

            if ((addedObject.customIndex ?? 0) != (removedObject.customIndex ?? 0))
            {
                yield return("Custom sampleset index override changed from " +
                             (removedObject.customIndex?.ToString() ?? "default") + " to " +
                             (addedObject.customIndex?.ToString() ?? "default") + ".");
            }

            if (addedObject.type.HasFlag(HitObject.Type.NewCombo) && !removedObject.type.HasFlag(HitObject.Type.NewCombo))
            {
                yield return("Added new combo.");
            }

            if (!addedObject.type.HasFlag(HitObject.Type.NewCombo) && removedObject.type.HasFlag(HitObject.Type.NewCombo))
            {
                yield return("Removed new combo.");
            }

            int addedComboSkip = 0;

            if (addedObject.type.HasFlag(HitObject.Type.ComboSkip1))
            {
                addedComboSkip += 1;
            }
            if (addedObject.type.HasFlag(HitObject.Type.ComboSkip2))
            {
                addedComboSkip += 2;
            }
            if (addedObject.type.HasFlag(HitObject.Type.ComboSkip3))
            {
                addedComboSkip += 4;
            }

            int removedComboSkip = 0;

            if (removedObject.type.HasFlag(HitObject.Type.ComboSkip1))
            {
                removedComboSkip += 1;
            }
            if (removedObject.type.HasFlag(HitObject.Type.ComboSkip2))
            {
                removedComboSkip += 2;
            }
            if (removedObject.type.HasFlag(HitObject.Type.ComboSkip3))
            {
                removedComboSkip += 4;
            }

            if (addedComboSkip != removedComboSkip)
            {
                yield return("Changed skipped combo amount from " + removedComboSkip + " to " +
                             addedComboSkip + ".");
            }

            if (addedObject.filename != removedObject.filename)
            {
                yield return("Hit sound filename changed from " + removedObject.filename + " to " +
                             addedObject.filename + ".");
            }

            if (addedObject.volume != removedObject.volume)
            {
                yield return("Hit sound volume changed from " + (removedObject.volume?.ToString() ?? "inherited") + " to " +
                             (addedObject.volume?.ToString() ?? "inherited") + ".");
            }

            string type = addedObject.GetObjectType();

            if (type == "Slider")
            {
                Slider addedSlider   = new Slider(addedObject.code.Split(','), null);
                Slider removedSlider = new Slider(removedObject.code.Split(','), null);

                if (addedSlider.curveType != removedSlider.curveType)
                {
                    yield return("Curve type changed from " + removedSlider.curveType + " to " +
                                 addedSlider.curveType + ".");
                }

                if (addedSlider.edgeAmount != removedSlider.edgeAmount)
                {
                    yield return("Reverse amount changed from " + (removedSlider.edgeAmount - 1) + " to " +
                                 (addedSlider.edgeAmount - 1) + ".");
                }

                if (addedSlider.endSampleset != removedSlider.endSampleset)
                {
                    yield return("Tail sampleset changed from " +
                                 removedSlider.endSampleset.ToString().ToLower() + " to " +
                                 addedSlider.endSampleset.ToString().ToLower() + ".");
                }

                if (addedSlider.endAddition != removedSlider.endAddition)
                {
                    yield return("Tail addition changed from " +
                                 removedSlider.endAddition.ToString().ToLower() + " to " +
                                 addedSlider.endAddition.ToString().ToLower() + ".");
                }

                if (addedSlider.endHitSound != removedSlider.endHitSound)
                {
                    foreach (HitObject.HitSound hitSound in Enum.GetValues(typeof(HitObject.HitSound)))
                    {
                        if (addedSlider.HasHitSound(hitSound) && !removedSlider.HasHitSound(hitSound))
                        {
                            yield return("Added " + Enum.GetName(typeof(HitObject.HitSound), hitSound)?.ToLower() +
                                         " to tail.");
                        }

                        if (!addedSlider.HasHitSound(hitSound) && removedSlider.HasHitSound(hitSound))
                        {
                            yield return("Removed " + Enum.GetName(typeof(HitObject.HitSound), hitSound)?.ToLower() +
                                         " from tail.");
                        }
                    }
                }

                if (addedSlider.pixelLength.AlmostEqual(removedSlider.pixelLength))
                {
                    yield return("Pixel length changed from " + removedSlider.pixelLength +
                                 " to " + addedSlider.pixelLength + ".");
                }

                if (addedSlider.nodePositions.Count == removedSlider.nodePositions.Count)
                {
                    // The first node is the start, which we already checked.
                    for (int i = 1; i < addedSlider.nodePositions.Count; ++i)
                    {
                        if (addedSlider.nodePositions[i] != removedSlider.nodePositions[i])
                        {
                            yield return("Node " + (i + 1) + " moved from " +
                                         removedSlider.nodePositions[i].X + "; " + removedSlider.nodePositions[i].Y + " to " +
                                         addedSlider.nodePositions[i].X + "; " + addedSlider.nodePositions[i].Y + ".");
                        }
                    }
                }
                else
                {
                    yield return("Node count changed from " + removedSlider.nodePositions.Count +
                                 " to " + addedSlider.nodePositions.Count + " (possibly positions as well).");
                }

                if (addedSlider.edgeAmount == removedSlider.edgeAmount)
                {
                    for (int i = 0; i < addedSlider.reverseSamplesets.Count; ++i)
                    {
                        if (addedSlider.reverseSamplesets.ElementAtOrDefault(i) !=
                            removedSlider.reverseSamplesets.ElementAtOrDefault(i))
                        {
                            yield return("Reverse #" + (i + 1) + " sampleset changed from " +
                                         removedSlider.reverseSamplesets.ElementAtOrDefault(i).ToString().ToLower() + " to " +
                                         addedSlider.reverseSamplesets.ElementAtOrDefault(i).ToString().ToLower() + ".");
                        }
                    }

                    for (int i = 0; i < addedSlider.reverseAdditions.Count; ++i)
                    {
                        if (addedSlider.reverseAdditions.ElementAtOrDefault(i) !=
                            removedSlider.reverseAdditions.ElementAtOrDefault(i))
                        {
                            yield return("Reverse #" + (i + 1) + " addition changed from " +
                                         removedSlider.reverseAdditions.ElementAtOrDefault(i).ToString().ToLower() + " to " +
                                         addedSlider.reverseAdditions.ElementAtOrDefault(i).ToString().ToLower() + ".");
                        }
                    }

                    for (int i = 0; i < addedSlider.reverseAdditions.Count; ++i)
                    {
                        if (addedSlider.reverseHitSounds.ElementAtOrDefault(i) !=
                            removedSlider.reverseHitSounds.ElementAtOrDefault(i))
                        {
                            foreach (HitObject.HitSound hitSound in Enum.GetValues(typeof(HitObject.HitSound)))
                            {
                                if (addedSlider.reverseHitSounds.ElementAtOrDefault(i).HasFlag(hitSound) &&
                                    !removedSlider.reverseHitSounds.ElementAtOrDefault(i).HasFlag(hitSound))
                                {
                                    yield return("Added " +
                                                 Enum.GetName(typeof(HitObject.HitSound), hitSound).ToLower() +
                                                 " to reverse #" + (i + 1) + ".");
                                }

                                if (!addedSlider.reverseHitSounds.ElementAtOrDefault(i).HasFlag(hitSound) &&
                                    removedSlider.reverseHitSounds.ElementAtOrDefault(i).HasFlag(hitSound))
                                {
                                    yield return("Removed " + Enum.GetName(typeof(HitObject.HitSound), hitSound).ToLower() +
                                                 " from reverse #" + (i + 1) + ".");
                                }
                            }
                        }
                    }
                }

                if (addedSlider.startHitSound != removedSlider.startHitSound)
                {
                    foreach (HitObject.HitSound hitSound in Enum.GetValues(typeof(HitObject.HitSound)))
                    {
                        if (addedSlider.startHitSound.HasFlag(hitSound) &&
                            !removedSlider.startHitSound.HasFlag(hitSound))
                        {
                            yield return("Added " + Enum.GetName(typeof(HitObject.HitSound), hitSound).ToLower() +
                                         " to head.");
                        }

                        if (!addedSlider.startHitSound.HasFlag(hitSound) &&
                            removedSlider.startHitSound.HasFlag(hitSound))
                        {
                            yield return("Removed " + Enum.GetName(typeof(HitObject.HitSound), hitSound).ToLower() +
                                         " from head.");
                        }
                    }
                }

                if (addedSlider.startSampleset != removedSlider.startSampleset)
                {
                    yield return("Head sampleset changed from " +
                                 removedSlider.startSampleset.ToString().ToLower() + " to " +
                                 addedSlider.startSampleset.ToString().ToLower() + ".");
                }

                if (addedSlider.startAddition != removedSlider.startAddition)
                {
                    yield return("Head addition changed from " +
                                 removedSlider.startAddition.ToString().ToLower() + " to " +
                                 addedSlider.startAddition.ToString().ToLower() + ".");
                }
            }

            if (type == "Spinner")
            {
                Spinner addedSpinner   = new Spinner(addedObject.code.Split(','), null);
                Spinner removedSpinner = new Spinner(removedObject.code.Split(','), null);

                if (addedSpinner.endTime.AlmostEqual(removedSpinner.endTime))
                {
                    yield return("End time changed from " + removedSpinner.endTime + " to " +
                                 addedSpinner.endTime + ".");
                }
            }

            if (type == "Hold note")
            {
                HoldNote addedNote   = new HoldNote(addedObject.code.Split(','), null);
                HoldNote removedNote = new HoldNote(removedObject.code.Split(','), null);

                if (addedNote.endTime.AlmostEqual(removedNote.endTime))
                {
                    yield return("End time changed from " + removedNote.endTime + " to " +
                                 addedNote.endTime + ".");
                }
            }
        }