Skip to content

Commit

Permalink
Merge pull request #174 from Emik03/search-alg-opt
Browse files Browse the repository at this point in the history
Optimize search algorithms
  • Loading branch information
Illuminati-CRAZ authored Aug 27, 2024
2 parents 05ab6e2 + c4a6ecb commit 08b4345
Show file tree
Hide file tree
Showing 16 changed files with 828 additions and 361 deletions.
205 changes: 205 additions & 0 deletions Quaver.API.Tests/Quaver/Resources/stable-sorting.qua
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
AudioFile: ''
SongPreviewTime: 0
BackgroundFile: ''
MapId: -1
MapSetId: -1
Mode: Keys4
Title: ''
Artist: ''
Source: ''
Tags: ''
DifficultyName: ''
EditorLayers: []
Bookmarks:
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'first'
- StartTime: 0
Note: 'second'
- StartTime: 0
Note: 'third'
- StartTime: 1000
Note: 'fourth'
- StartTime: 1000
Note: 'fifth'
- StartTime: 1000
Note: 'sixth'
CustomAudioSamples: []
SoundEffects: []
TimingPoints:
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 6
Signature: 13646
- StartTime: 0
Bpm: 4
Signature: 3
- StartTime: 0
Bpm: 12
Signature: 4
- StartTime: 1000
Bpm: 27
Signature: 246
- StartTime: 1000
Bpm: 1
Signature: 12
- StartTime: 1000
Bpm: 136
Signature: 3785
SliderVelocities:
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 1253
- StartTime: 0
Multiplier: 8.4
- StartTime: 0
Multiplier: -1345
- StartTime: 1000
Multiplier: 675
- StartTime: 1000
Multiplier: 0
- StartTime: 1000
Multiplier: -13548
HitObjects:
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 4
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 3
KeySounds: []
HitSound: Normal
- StartTime: 0
Lane: 2
KeySounds: []
HitSound: Normal
- StartTime: 1000
Lane: 7
KeySounds: []
HitSound: Normal
- StartTime: 1000
Lane: 1
KeySounds: []
HitSound: Normal
- StartTime: 1000
Lane: 5
KeySounds: []
HitSound: Normal
28 changes: 23 additions & 5 deletions Quaver.API.Tests/Quaver/TestCaseQua.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
using System.IO;
using System.Linq;
using System.Text;
using Force.DeepCloner;
using Quaver.API.Enums;
using Quaver.API.Maps;
using Quaver.API.Maps.Structures;
using Xunit;
using YamlDotNet.Serialization;

namespace Quaver.API.Tests.Quaver
{
Expand Down Expand Up @@ -249,6 +251,22 @@ public void InvalidKeySoundIndex()
Assert.False(qua.IsValid());
}

[Fact]
public void StableSorting()
{
const string Q = "./Quaver/Resources/stable-sorting.qua";
var unsorted = new Deserializer().Deserialize<Qua>(File.ReadAllText(Q));
var sorted = unsorted.DeepClone();
sorted.Sort();

Assert.Equal(unsorted.TimingPoints, sorted.TimingPoints, TimingPointInfo.ByValueComparer);
Assert.Equal(unsorted.SliderVelocities, sorted.SliderVelocities, SliderVelocityInfo.ByValueComparer);
Assert.Equal(unsorted.HitObjects, sorted.HitObjects, HitObjectInfo.ByValueComparer);
Assert.Equal(unsorted.CustomAudioSamples, sorted.CustomAudioSamples, CustomAudioSampleInfo.ByValueComparer);
Assert.Equal(unsorted.EditorLayers, sorted.EditorLayers, EditorLayerInfo.ByValueComparer);
Assert.Equal(unsorted.Bookmarks, sorted.Bookmarks, BookmarkInfo.ByValueComparer);
}

[Fact]
public void SVNormalization()
{
Expand Down Expand Up @@ -282,22 +300,22 @@ public void SVNormalization()

// Check that the normalization gives the correct result.
var quaDenormalizedNormalized = quaDenormalized.WithNormalizedSVs();
Assert.True(quaDenormalizedNormalized.EqualByValue(quaNormalized));
Assert.True(quaDenormalizedNormalized.EqualByValue(quaNormalized), $"Expected {test} to normalize correctly.");

// Denormalization can move the first SV (it doesn't matter where to put the InitialScrollVelocity SV).
// So check back-and-forth instead of just denormalization.
var quaNormalizedDenormalizedNormalized = quaNormalized.WithDenormalizedSVs().WithNormalizedSVs();
Assert.True(quaNormalizedDenormalizedNormalized.EqualByValue(quaNormalized));
Assert.True(quaNormalizedDenormalizedNormalized.EqualByValue(quaNormalized), $"Expected {test} to remain the same after denormalization and subsequent normalization.");

// Check that serializing and parsing the result does not change it.
var bufferDenormalized = Encoding.UTF8.GetBytes(quaDenormalized.Serialize());
var quaDenormalized2 = Qua.Parse(bufferDenormalized, false);
Assert.True(quaDenormalized.EqualByValue(quaDenormalized2));
Assert.True(quaDenormalized.EqualByValue(quaDenormalized2), $"Expected {test} denormalized to remain the same after serialization and parsing.");

var bufferNormalized = Encoding.UTF8.GetBytes(quaNormalized.Serialize());
var quaNormalized2 = Qua.Parse(bufferNormalized, false);
Assert.True(quaNormalized.EqualByValue(quaNormalized2));
Assert.True(quaNormalized.EqualByValue(quaNormalized2), $"Expected {test} to normalized to remain the same after serialization and parsing.");
}
}
}
}
}
50 changes: 50 additions & 0 deletions Quaver.API/Helpers/ListHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* Copyright (c) 2017-2018 Swan & The Quaver Team <[email protected]>.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

namespace Quaver.API.Helpers
{
public static class ListHelper
{
private static class Cache<T>
{
public static Converter<List<T>, T[]> Converter { get; } = typeof(List<T>)
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(x => x.FieldType == typeof(T[])) is { } method
? CreateGetter(method)
: x => x.ToArray();

private static Converter<List<T>, T[]> CreateGetter(FieldInfo field)
{
var name = $"{field.DeclaringType?.FullName}.get_{field.Name}";
var getter = new DynamicMethod(name, typeof(T[]), new[] { typeof(List<T>) }, true);
var il = getter.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, field);
il.Emit(OpCodes.Ret);
return (Converter<List<T>, T[]>)getter.CreateDelegate(typeof(Converter<List<T>, T[]>));
}
}

/// <summary>
/// Gets the underlying <see cref="Array"/> of the <see cref="List{T}"/>.
/// </summary>
/// <remarks><para>
/// Be careful when using this method as the <see cref="List{T}"/> cannot safeguard
/// against underlying mutations or out-of-bounds reading within its capacity.
/// </para></remarks>
/// <param name="list"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T[] GetUnderlyingArray<T>(List<T> list) => Cache<T>.Converter(list);
}
}
Loading

0 comments on commit 08b4345

Please sign in to comment.