Skip to content

Commit

Permalink
Merge pull request #30 from flightlex/master
Browse files Browse the repository at this point in the history
level length
  • Loading branch information
Folleach authored Oct 21, 2023
2 parents 21ed109 + 90b16cf commit f9fb419
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 6 deletions.
24 changes: 24 additions & 0 deletions GeometryDashAPI.Tests/LevelLengthTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.IO;
using System.Net;
using FluentAssertions;
using GeometryDashAPI.Levels;
using GeometryDashAPI.Server;
using GeometryDashAPI.Server.Responses;
using NUnit.Framework;

namespace GeometryDashAPI.Tests;

[TestFixture]
public class LevelLengthTests
{
[TestCase("12034598_Conclusion", 57)]
[TestCase("28755513_TheFinalLair", 154)]
[TestCase("116631_XmasParty", 87)]
public void Test(string fileName, int expectedSeconds)
{
var responseBody = File.ReadAllText(Path.Combine("data", "levels", fileName));
var response = new ServerResponse<LevelResponse>(HttpStatusCode.OK, responseBody);
var level = new Level(response.GetResultOrDefault().Level.LevelString, compressed: true);
level.LevelLength.TotalSeconds.Should().BeApproximately(expectedSeconds, precision: 1);
}
}
50 changes: 44 additions & 6 deletions GeometryDashAPI/Levels/GameObjects/Specific/SpeedBlock.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
using GeometryDashAPI.Attributes;
using System;
using GeometryDashAPI.Attributes;
using GeometryDashAPI.Levels.Enums;
using GeometryDashAPI.Levels.GameObjects.Default;

namespace GeometryDashAPI.Levels.GameObjects.Specific
{
/// <summary>
/// Represents the id of the speed block.<br/><br/>
/// Not to be confused with <see cref="SpeedType"/>.<br/>
/// Because it is responsible for a specific speed, instead of a specific block id
/// </summary>
public enum SpeedBlockId
{
Orange = 200,
Expand All @@ -14,26 +19,59 @@ public enum SpeedBlockId
}

[GameBlock(200, 201, 202, 203, 1334)]
public class SpeedBlock : Block
public class SpeedBlock : Portal
{
[GameProperty("24", (short)Layer.B2)] protected override short zLayer { get; set; } = (short)Layer.B2;
[GameProperty("25", -6)] public override int ZOrder { get; set; } = -6;

[GameProperty("13", true, true)]
public bool Using { get; set; } = true;

public SpeedBlockId BlockType
{
get => (SpeedBlockId)Id;
set => Id = (int)value;
}

public SpeedType SpeedType
{
get => FromBlockIdToSpeedType(BlockType);
set => BlockType = FromSpeedTypeToBlockId(value);
}

public SpeedBlock() : base(201)
{
}

public SpeedBlock(SpeedBlockId type) : base((int)type)
{
}

public SpeedBlock(SpeedType type) : base((int)FromSpeedTypeToBlockId(type))
{
}

public static SpeedType FromBlockIdToSpeedType(SpeedBlockId id)
{
return id switch
{
SpeedBlockId.Orange => SpeedType.Half,
SpeedBlockId.Default => SpeedType.Default,
SpeedBlockId.Green => SpeedType.X2,
SpeedBlockId.Purple => SpeedType.X3,
SpeedBlockId.Red => SpeedType.X4,
_ => throw new ArgumentOutOfRangeException(nameof(id), id, null)
};
}

public static SpeedBlockId FromSpeedTypeToBlockId(SpeedType speedType)
{
return speedType switch
{
SpeedType.Half => SpeedBlockId.Orange,
SpeedType.Default => SpeedBlockId.Default,
SpeedType.X2 => SpeedBlockId.Green,
SpeedType.X3 => SpeedBlockId.Purple,
SpeedType.X4 => SpeedBlockId.Red,
_ => throw new ArgumentOutOfRangeException(nameof(speedType), speedType, null)
};
}
}
}
2 changes: 2 additions & 0 deletions GeometryDashAPI/Levels/Level.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public Guidelines Guidelines
set => Options.Guidelines = value;
}

public TimeSpan LevelLength => Levels.LevelLength.Measure(this);

public int CountBlock => Blocks.Count;
public int CountColor => Options.Colors.Count;

Expand Down
34 changes: 34 additions & 0 deletions GeometryDashAPI/Levels/LevelLength.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Linq;
using GeometryDashAPI.Levels.GameObjects.Specific;

namespace GeometryDashAPI.Levels
{
public static class LevelLength
{
public static TimeSpan Measure(Level level)
{
var maxX = level.Blocks.Max(x => x.PositionX);
var portals = GetSpeedBlocks(level);

var seconds = 0d;
var i = 1;
for (; i < portals.Length; i++)
seconds += (portals[i].PositionX - portals[i - 1].PositionX) / portals[i - 1].SpeedType.GetSpeed();

var final = Math.Min(i, portals.Length - 1);
var total = seconds + (maxX - portals[final].PositionX) / portals[final].SpeedType.GetSpeed();

return TimeSpan.FromSeconds(total);
}

private static SpeedBlock[] GetSpeedBlocks(Level level)
{
return new[] { new SpeedBlock(level.Options.PlayerSpeed) }
.Concat(level.Blocks.OfType<SpeedBlock>()
.Where(x => x.Checked)
.OrderBy(x => x.PositionX)
).ToArray();
}
}
}
25 changes: 25 additions & 0 deletions GeometryDashAPI/Levels/LevelSpeed.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using GeometryDashAPI.Levels.Enums;

namespace GeometryDashAPI.Levels
{
public static class LevelSpeed
{
public const double Half = 251.16;
public const double Default = 311.58;
public const double X2 = 387.42;
public const double X3 = 468;
public const double X4 = 576;

public static double GetSpeed(this SpeedType speedType)
{
return speedType switch
{
SpeedType.Half => Half,
SpeedType.Default => Default,
SpeedType.X2 => X2,
SpeedType.X3 => X3,
SpeedType.X4 => X4
};
}
}
}
18 changes: 18 additions & 0 deletions GeometryDashAPI/Levels/Portal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using GeometryDashAPI.Attributes;
using GeometryDashAPI.Levels.GameObjects.Default;

namespace GeometryDashAPI.Levels
{
public class Portal : Block
{
[GameProperty("13", true, true)] public bool Checked { get; set; }

public Portal()
{
}

public Portal(int id) : base(id)
{
}
}
}

0 comments on commit f9fb419

Please sign in to comment.