Skip to content

Commit 1a17703

Browse files
committed
cleanup
1 parent 77d6638 commit 1a17703

File tree

4 files changed

+67
-130
lines changed

4 files changed

+67
-130
lines changed

src/dsstats.maui/dsstats.builder/dsstats.builder.tests/FenSharedTests.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,29 @@ public void CanApplyFenString()
5959
new() { Unit = new() { Name = "Marine" }, Poss = "160,160,161,160,163,160,165,159,167,154" },
6060
}
6161
};
62-
var positions = spawn.Units.First().Poss.Split(',').Select(int.Parse).OrderBy(o => o).ToList();
62+
var points = DsFen.GetPoints(spawn.Units.First().Poss).OrderBy(o => o.X).ThenBy(o => o.Y).ToList();
63+
var polygon = DsFen.polygon1;
64+
foreach (var point in points)
65+
{
66+
Assert.IsTrue(polygon.IsPointInside(point), $"Point {point} is not inside the polygon.");
67+
}
68+
6369
string fen = DsFen.GetFen(spawn, cmdr, team);
6470
Assert.IsNotNull(fen);
6571
Assert.IsTrue(fen.Length > 10);
6672

67-
var reSpawn = new SpawnDto();
73+
SpawnDto reSpawn = new SpawnDto();
6874
DsFen.ApplyFen(fen, reSpawn, out cmdr, out team);
6975
Assert.AreEqual(Commander.Terran, cmdr);
7076
Assert.AreEqual(1, team);
7177
Assert.IsNotNull(reSpawn.Units);
7278
Assert.IsTrue(reSpawn.Units.Count > 0);
73-
var rePositions = reSpawn.Units.First().Poss.Split(',').Select(int.Parse).OrderBy(o => o).ToList();
74-
Assert.AreEqual(positions.Count, rePositions.Count);
75-
// for (int i = 0; i < positions.Count; i++)
76-
// {
77-
// Assert.AreEqual(positions[i], rePositions[i]);
78-
// }
79+
var rePoints = DsFen.GetPoints(reSpawn.Units.First().Poss).OrderBy(o => o.X).ThenBy(o => o.Y).ToList();
80+
Assert.AreEqual(points.Count, rePoints.Count);
81+
for (int i = 0; i < points.Count; i++)
82+
{
83+
Assert.AreEqual(points[i], rePoints[i]);
84+
}
7985
}
8086

8187
}

src/dsstats.maui/dsstats.builder/dsstats.builder.tests/Polygon.Tests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using dsstats.shared.DsFen;
2+
13
namespace dsstats.builder.tests;
24

35
[TestClass]
@@ -65,5 +67,33 @@ public void CanGetAllPoint()
6567
var points = polygon.GetAllPointsInsideOrOnEdge();
6668
Assert.AreEqual(403, points.Count());
6769
}
70+
71+
[TestMethod]
72+
public void Team2CanNormalizePoint()
73+
{
74+
var polygon = new Polygon(new(84, 93), new(101, 76), new(90, 65), new(73, 82));
75+
DsPoint point = new(73, 82);
76+
var normalizedPoint = polygon.GetNormalizedPoint(point);
77+
Assert.AreEqual(0, normalizedPoint.X);
78+
Assert.AreEqual(0, normalizedPoint.Y);
79+
}
80+
81+
[TestMethod]
82+
public void Team2CanDeNormalizePoint()
83+
{
84+
var polygon = new Polygon(new(84, 93), new(101, 76), new(90, 65), new(73, 82));
85+
DsPoint normalizedPoint = new(0, 0);
86+
var point = polygon.GetDeNormalizedPoint(normalizedPoint);
87+
Assert.AreEqual(73, point.X, $"({normalizedPoint.X},{normalizedPoint.Y}) => ({point.X},{point.Y})");
88+
Assert.AreEqual(82, point.Y, $"({normalizedPoint.X},{normalizedPoint.Y}) => ({point.X},{point.Y})");
89+
}
90+
91+
[TestMethod]
92+
public void Team2CanGetAllPoint()
93+
{
94+
var polygon = new Polygon(new(84, 93), new(101, 76), new(90, 65), new(73, 82));
95+
var points = polygon.GetAllPointsInsideOrOnEdge();
96+
Assert.AreEqual(403, points.Count());
97+
}
6898
}
6999

src/dsstats.shared/DsFen/DsFen.cs

Lines changed: 21 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,18 @@
22

33
public static partial class DsFen
44
{
5-
private static readonly List<(int x, int y)> polygon2 =
6-
[
7-
new (73, 82), // Left
8-
new (84, 93), // Top
9-
new (101, 76), // Right
10-
new (90, 65), // Bottom
11-
];
12-
private static readonly List<(int x, int y)> polygon1 =
13-
[
14-
new (154, 163), // Left
15-
new (165, 174), // Top
16-
new (182, 157), // Right
17-
new (171, 146), // Bottom
18-
];
19-
private const double CenterX = 128.0;
20-
private const double CenterY = 120.0;
5+
public static readonly Polygon polygon2 = new Polygon(new(84, 93), new(101, 76), new(90, 65), new(73, 82));
6+
public static readonly Polygon polygon1 = new Polygon(new(165, 174), new(182, 157), new(171, 146), new(154, 163));
217

228
public static string GetFen(SpawnDto spawn, Commander cmdr, int team)
239
{
2410
var build = CmdrBuildFactory.Create(cmdr);
2511
if (build == null) return string.Empty;
2612

2713
var polygon = team == 1 ? polygon1 : polygon2;
28-
var origin = polygon[3]; // Bottom point is origin
2914

30-
var groundUnits = new Dictionary<(int x, int y), char>();
31-
var airUnits = new Dictionary<(int x, int y), char>();
15+
var groundUnits = new Dictionary<DsPoint, char>();
16+
var airUnits = new Dictionary<DsPoint, char>();
3217

3318
foreach (var unit in spawn.Units)
3419
{
@@ -42,26 +27,26 @@ public static string GetFen(SpawnDto spawn, Commander cmdr, int team)
4227
var points = GetPoints(unit.Poss);
4328
foreach (var p in points)
4429
{
45-
if (!IsPointInsideOrOnEdge(p, team))
30+
if (!polygon.IsPointInside(p))
4631
{
4732
continue;
4833
}
49-
var grid = RotateNeg45Int(p);
34+
var grid = polygon.GetNormalizedPoint(p);
5035
if (buildOption.IsAir)
5136
airUnits[grid] = key;
5237
else
5338
groundUnits[grid] = key;
5439
}
5540
}
5641

57-
string EncodeLayer(Dictionary<(int x, int y), char> layer)
42+
string EncodeLayer(Dictionary<DsPoint, char> layer)
5843
{
5944
if (layer.Count == 0) return "";
6045

61-
int minX = layer.Keys.Min(p => p.x);
62-
int maxX = layer.Keys.Max(p => p.x);
63-
int minY = layer.Keys.Min(p => p.y);
64-
int maxY = layer.Keys.Max(p => p.y);
46+
int minX = layer.Keys.Min(p => p.X);
47+
int maxX = layer.Keys.Max(p => p.X);
48+
int minY = layer.Keys.Min(p => p.Y);
49+
int maxY = layer.Keys.Max(p => p.Y);
6550

6651
var rows = new List<string>();
6752
for (int y = minY; y <= maxY; y++)
@@ -70,7 +55,7 @@ string EncodeLayer(Dictionary<(int x, int y), char> layer)
7055
int empty = 0;
7156
for (int x = minX; x <= maxX; x++)
7257
{
73-
if (layer.TryGetValue((x, y), out char key))
58+
if (layer.TryGetValue(new(x, y), out char key))
7459
{
7560
if (empty > 0)
7661
{
@@ -117,17 +102,16 @@ public static void ApplyFen(string fen, SpawnDto spawn, out Commander cmdr, out
117102
if (build == null) return;
118103

119104
var polygon = team == 1 ? polygon1 : polygon2;
120-
var origin = polygon[3];
121105

122106
var layers = parts[1].Split('|');
123107
string groundLayer = layers.Length > 0 ? layers[0] : "";
124108
string airLayer = layers.Length > 1 ? layers[1] : "";
125109

126-
ParseLayer(groundLayer, build, false, spawn, origin);
127-
ParseLayer(airLayer, build, true, spawn, origin);
110+
ParseLayer(groundLayer, build, false, spawn, polygon);
111+
ParseLayer(airLayer, build, true, spawn, polygon);
128112
}
129113

130-
private static void ParseLayer(string layer, CmdrBuild build, bool isAir, SpawnDto spawn, (int x, int y) origin)
114+
private static void ParseLayer(string layer, CmdrBuild build, bool isAir, SpawnDto spawn, Polygon polygon)
131115
{
132116
if (string.IsNullOrWhiteSpace(layer)) return;
133117

@@ -155,8 +139,8 @@ private static void ParseLayer(string layer, CmdrBuild build, bool isAir, SpawnD
155139
var name = build.GetUnitNameFromKey(key, isAir, isUpper);
156140
if (name != null)
157141
{
158-
var gridPos = (x, y);
159-
var world = RotatePos45Int(gridPos);
142+
var gridPos = new DsPoint(x, y);
143+
var world = polygon.GetDeNormalizedPoint(gridPos);
160144

161145
var unit = spawn.Units.FirstOrDefault(u => u.Unit.Name == name);
162146
if (unit == null)
@@ -167,7 +151,7 @@ private static void ParseLayer(string layer, CmdrBuild build, bool isAir, SpawnD
167151

168152
if (!string.IsNullOrEmpty(unit.Poss))
169153
unit.Poss += ",";
170-
unit.Poss += $"{world.x},{world.y}";
154+
unit.Poss += $"{world.X},{world.Y}";
171155
unit.Count++;
172156
}
173157

@@ -177,102 +161,19 @@ private static void ParseLayer(string layer, CmdrBuild build, bool isAir, SpawnD
177161
}
178162
}
179163

180-
private static (double x, double y) Rotate((int x, int y) pt, double angleDeg)
181-
{
182-
double angleRad = angleDeg * Math.PI / 180.0;
183-
double cos = Math.Cos(angleRad);
184-
double sin = Math.Sin(angleRad);
185-
186-
double dx = pt.x - CenterX;
187-
double dy = pt.y - CenterY;
188-
189-
double x = cos * dx - sin * dy + CenterX;
190-
double y = sin * dx + cos * dy + CenterY;
191-
192-
return (x, y);
193-
}
194-
195-
private static (int x, int y) RotateNeg45Int((int x, int y) pt)
196-
{
197-
var rotated = Rotate(pt, -45);
198-
return ((int)Math.Round(rotated.x), (int)Math.Round(rotated.y));
199-
}
200-
201-
private static (int x, int y) RotatePos45Int((int x, int y) pt)
202-
{
203-
var rotated = Rotate(pt, +45);
204-
return ((int)Math.Round(rotated.x), (int)Math.Round(rotated.y));
205-
}
206-
207-
private static List<(int x, int y)> GetPoints(string possString)
164+
public static List<DsPoint> GetPoints(string possString)
208165
{
209166
if (string.IsNullOrEmpty(possString))
210167
{
211168
return [];
212169
}
213170
var stringPoints = possString.Split(',', StringSplitOptions.RemoveEmptyEntries);
214-
List<(int x, int y)> points = [];
171+
List<DsPoint> points = [];
215172
for (int i = 0; i < stringPoints.Length; i += 2)
216173
{
217-
points.Add((int.Parse(stringPoints[i]), int.Parse(stringPoints[i + 1])));
174+
points.Add(new(int.Parse(stringPoints[i]), int.Parse(stringPoints[i + 1])));
218175
}
219176
return points;
220177
}
221178

222-
private static bool IsPointInsideOrOnEdge((int x, int y) p, int team)
223-
{
224-
var polygon = team == 1 ? polygon1 : polygon2;
225-
if (IsPointInPolygon(p, polygon))
226-
return true;
227-
228-
for (int i = 0; i < polygon.Count; i++)
229-
{
230-
if (IsOnEdge(p, polygon[i], polygon[(i + 1) % polygon.Count]))
231-
return true;
232-
}
233-
234-
return false;
235-
}
236-
237-
private static bool IsPointInPolygon((int x, int y) p, List<(int x, int y)> polygon)
238-
{
239-
int wn = 0; // winding number
240-
int n = polygon.Count;
241-
242-
for (int i = 0; i < n; i++)
243-
{
244-
(int x, int y) pi = polygon[i];
245-
(int x, int y) pj = polygon[(i + 1) % n];
246-
247-
if (pi.y <= p.y)
248-
{
249-
if (pj.y > p.y && IsLeft(pi, pj, p) > 0)
250-
wn++;
251-
}
252-
else
253-
{
254-
if (pj.y <= p.y && IsLeft(pi, pj, p) < 0)
255-
wn--;
256-
}
257-
}
258-
259-
return wn != 0;
260-
}
261-
262-
private static double IsLeft((int x, int y) p0, (int x, int y) p1, (int x, int y) p2)
263-
{
264-
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
265-
}
266-
267-
private static bool IsOnEdge((int x, int y) p, (int x, int y) a, (int x, int y) b)
268-
{
269-
double cross = (p.y - a.y) * (b.x - a.x) - (p.x - a.x) * (b.y - a.y);
270-
if (Math.Abs(cross) > 1e-6) return false;
271-
272-
double dot = (p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y);
273-
if (dot < 0) return false;
274-
275-
double lenSq = (b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y);
276-
return dot <= lenSq;
277-
}
278179
}

src/dsstats.maui/dsstats.builder/dsstats.builder/Polygon.cs renamed to src/dsstats.shared/DsFen/Polygon.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
2-
namespace dsstats.builder;
1+

2+
namespace dsstats.shared.DsFen;
33

44
/// <summary>
55
/// representing a 45° rotated rectangle as build area

0 commit comments

Comments
 (0)