Skip to content

Commit 7583460

Browse files
Merge pull request #110 from CodebreakerApp/109-analyzer-5x5x4
109 analyzer 5x5x4
2 parents 65e743e + b980d49 commit 7583460

File tree

4 files changed

+123
-61
lines changed

4 files changed

+123
-61
lines changed

src/services/gameapi/Codebreaker.GameAPIs.Analyzers.Tests/Analyzers/ShapeGame5x5x4AnalyzerTests.cs

Lines changed: 105 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,48 @@
55

66
namespace Codebreaker.GameAPIs.Analyzer.Tests;
77

8-
// TODO: add more unit tests
98
public class ShapeGame5x5x4AnalyzerTests
109
{
10+
11+
1112
[Fact]
12-
public void SetMoveShouldReturnThreeBlue()
13+
public void SetMoveShouldReturnTwoBlack()
14+
{
15+
ShapeAndColorResult expectedKeyPegs = new(2, 0, 0);
16+
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
17+
["Rectangle;Green", "Circle;Yellow", "Rectangle;Green", "Circle;Yellow"],
18+
["Rectangle;Green", "Circle;Yellow", "Star;Blue", "Star;Blue"]
19+
);
20+
21+
Assert.Equal(expectedKeyPegs, resultKeyPegs);
22+
}
23+
24+
[Fact]
25+
public void SetMoveShouldReturnOneBlackWithMultipleCorrectCodes()
26+
{
27+
ShapeAndColorResult expectedKeyPegs = new(1, 0, 0);
28+
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
29+
["Rectangle;Green", "Rectangle;Green", "Rectangle;Green", "Rectangle;Green"],
30+
["Rectangle;Green", "Star;Blue", "Star;Blue", "Star;Blue"]
31+
);
32+
33+
Assert.Equal(expectedKeyPegs, resultKeyPegs);
34+
}
35+
36+
[Fact]
37+
public void SetMoveShouldReturnOneBlackWithMultipleCorrectPairGuesses()
38+
{
39+
ShapeAndColorResult expectedKeyPegs = new(1, 0, 0);
40+
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
41+
["Rectangle;Green", "Circle;Yellow", "Circle;Yellow", "Circle;Yellow"],
42+
["Rectangle;Green", "Rectangle;Green", "Rectangle;Green", "Rectangle;Green"]
43+
);
44+
45+
Assert.Equal(expectedKeyPegs, resultKeyPegs);
46+
}
47+
48+
[Fact]
49+
public void SetMoveShouldReturnThreeWhite()
1350
{
1451
ShapeAndColorResult expectedKeyPegs = new(0, 3, 0);
1552
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
@@ -20,48 +57,72 @@ public void SetMoveShouldReturnThreeBlue()
2057
Assert.Equal(expectedKeyPegs, resultKeyPegs);
2158
}
2259

23-
//[InlineData(1, 2, Red, Yellow, Red, Blue)]
24-
//[InlineData(2, 0, White, White, Blue, Red)]
25-
//[Theory]
26-
//public void SetMoveUsingVariousData(int expectedBlack, int expectedWhite, params string[] guessValues)
27-
//{
28-
// string[] code = new[] { Red, Green, Blue, Red };
29-
// ColorResult expectedKeyPegs = new (expectedBlack, expectedWhite);
30-
// ColorResult resultKeyPegs = TestSkeleton(code, guessValues);
31-
// Assert.Equal(expectedKeyPegs, resultKeyPegs);
32-
//}
33-
34-
//[Theory]
35-
//[ClassData(typeof(TestData6x4))]
36-
//public void SetMoveUsingVariousDataUsingDataClass(string[] code, string[] guess, ColorResult expectedKeyPegs)
37-
//{
38-
// ColorResult actualKeyPegs = TestSkeleton(code, guess);
39-
// Assert.Equal(expectedKeyPegs, actualKeyPegs);
40-
//}
41-
42-
//[Fact]
43-
//public void ShouldThrowOnInvalidGuessCount()
44-
//{
45-
// Assert.Throws<ArgumentException>(() =>
46-
// {
47-
// TestSkeleton(
48-
// new[] { "Black", "Black", "Black", "Black" },
49-
// new[] { "Black" }
50-
// );
51-
// });
52-
//}
53-
54-
//[Fact]
55-
//public void ShouldThrowOnInvalidGuessValues()
56-
//{
57-
// Assert.Throws<ArgumentException>(() =>
58-
// {
59-
// TestSkeleton(
60-
// new[] { "Black", "Black", "Black", "Black" },
61-
// new[] { "Black", "Der", "Blue", "Yellow" } // "Der" is the wrong value
62-
// );
63-
// });
64-
//}
60+
[Fact]
61+
public void SetMoveShouldReturnOneWhiteWithMultipleCorrectPairIsGuesses()
62+
{
63+
ShapeAndColorResult expectedKeyPegs = new(0, 1, 0);
64+
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
65+
["Rectangle;Green", "Circle;Yellow", "Circle;Yellow", "Circle;Yellow"],
66+
["Triangle;Blue", "Rectangle;Green", "Rectangle;Green", "Rectangle;Green"]
67+
);
68+
69+
Assert.Equal(expectedKeyPegs, resultKeyPegs);
70+
}
71+
72+
[Fact]
73+
public void SetMoveShouldReturnTwoBlueForMatchingColors()
74+
{
75+
// the second and third guess have a correct color in the correct position
76+
// all the shapes are incorrect
77+
ShapeAndColorResult expectedKeyPegs = new(0, 0, 2);
78+
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
79+
["Rectangle;Green", "Circle;Yellow", "Rectangle;Green", "Circle;Yellow"],
80+
["Star;Blue", "Star;Yellow", "Star;Green", "Star;Blue"]
81+
);
82+
83+
Assert.Equal(expectedKeyPegs, resultKeyPegs);
84+
}
85+
86+
[Fact]
87+
public void SetMoveShouldReturnTwoBlueForMatchingShapesAndColors()
88+
{
89+
// the first guess has a correct shape, and the second guess a correct color. All other guesses are wrong.
90+
ShapeAndColorResult expectedKeyPegs = new(0, 0, 2);
91+
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
92+
["Rectangle;Green", "Circle;Yellow", "Rectangle;Green", "Circle;Yellow"],
93+
["Rectangle;Blue", "Rectangle;Yellow", "Star;Blue", "Star;Blue"]
94+
);
95+
96+
Assert.Equal(expectedKeyPegs, resultKeyPegs);
97+
}
98+
99+
[Fact]
100+
public void SetMoveShouldReturnTwoBlueForMatchingShapes()
101+
{
102+
// the first and second guess have a correct shape, but a wrong color
103+
// all the colors are incorrect
104+
ShapeAndColorResult expectedKeyPegs = new(0, 0, 2);
105+
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
106+
["Rectangle;Green", "Circle;Yellow", "Rectangle;Green", "Circle;Yellow"],
107+
["Rectangle;Blue", "Circle;Blue", "Star;Blue", "Star;Blue"]
108+
);
109+
110+
Assert.Equal(expectedKeyPegs, resultKeyPegs);
111+
}
112+
113+
[Fact]
114+
public void SetMoveShouldReturnOneBlackAndOneWhite()
115+
{
116+
// the first and second guess have a correct shape, but both in the wrong positon
117+
// all the colors are incorrect
118+
ShapeAndColorResult expectedKeyPegs = new(1, 1, 0);
119+
ShapeAndColorResult? resultKeyPegs = TestSkeleton(
120+
["Rectangle;Blue", "Circle;Yellow", "Star;Green", "Circle;Yellow"],
121+
["Rectangle;Blue", "Star;Green", "Triangle;Red", "Triangle;Red"]
122+
);
123+
124+
Assert.Equal(expectedKeyPegs, resultKeyPegs);
125+
}
65126

66127
private static ShapeAndColorResult TestSkeleton(string[] codes, string[] guesses)
67128
{

src/services/gameapi/Codebreaker.GameAPIs.Analyzers/Analyzers/ShapeGameGuessAnalyzer.cs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,25 @@ protected override void ValidateGuessValues()
1919

2020
protected override ShapeAndColorResult GetCoreResult()
2121
{
22-
// Check black and white keyPegs
22+
// Check black, white and blue keyPegs
2323
List<ShapeAndColorField> codesToCheck = new(_game.Codes.ToPegs<ShapeAndColorField>());
2424
List<ShapeAndColorField> guessPegsToCheck = new(Guesses);
2525
List<ShapeAndColorField> remainingCodesToCheck = [];
2626
List<ShapeAndColorField> remainingGuessPegsToCheck = [];
2727

2828
byte black = 0;
29-
byte blue = 0;
3029
byte white = 0;
30+
byte blue = 0;
3131

32-
// check black (correct color and shape)
32+
// check for black (correct color and shape at the correct position)
33+
// add the remaining codes and guess pegs to the remaining lists to check for white and blue keyPegs
3334
for (int i = 0; i < guessPegsToCheck.Count; i++)
3435
{
3536
if (guessPegsToCheck[i] == codesToCheck[i])
3637
{
3738
black++;
3839
}
39-
else
40+
else // the codes and the guess pegs need to be checked again for the blue and white keyPegs
4041
{
4142
remainingCodesToCheck.Add(codesToCheck[i]);
4243
remainingGuessPegsToCheck.Add(guessPegsToCheck[i]);
@@ -48,37 +49,37 @@ protected override ShapeAndColorResult GetCoreResult()
4849
guessPegsToCheck = remainingGuessPegsToCheck;
4950
remainingGuessPegsToCheck = [];
5051

51-
// check blue (correct shape and color on a wrong position)
52+
// check for white (correct pair at a wrong position)
53+
// and add the remaining codes and guess pegs to the remaining lists to check for blue keyPegs
5254
for (int i = 0; i < guessPegsToCheck.Count; i++)
5355
{
5456
ShapeAndColorField? codeField = codesToCheck.FirstOrDefault(c => c == guessPegsToCheck[i]);
5557
if (codeField is not null)
5658
{
57-
blue++;
58-
remainingCodesToCheck.Remove(codeField); // remove for the white check
59+
white++;
60+
codesToCheck.Remove(codeField); // remove for the white check
61+
remainingCodesToCheck.Remove(codeField); // remove for the blue check
5962
}
6063
else
6164
{
62-
remainingGuessPegsToCheck.Add(guessPegsToCheck[i]); // add for the white check
65+
remainingGuessPegsToCheck.Add(guessPegsToCheck[i]); // add for the blue check
6366
}
6467
}
6568

6669
codesToCheck = remainingCodesToCheck;
6770
guessPegsToCheck = remainingGuessPegsToCheck;
6871

69-
// check white (either the shape or the color is correct on a wrong position)
72+
// check blue (either the shape or the color is in the correct position but with a wrong paired element)
7073
for (int i = 0; i < guessPegsToCheck.Count; i++)
7174
{
72-
string[] colorCodes = codesToCheck.Select(c => c.Color).ToArray();
73-
string[] shapeCodes = codesToCheck.Select(c => c.Shape).ToArray();
74-
75-
if (colorCodes.Contains(guessPegsToCheck[i].Color) || shapeCodes.Contains(guessPegsToCheck[i].Shape))
75+
if (guessPegsToCheck[i].Shape == codesToCheck[i].Shape ||
76+
guessPegsToCheck[i].Color == codesToCheck[i].Color)
7677
{
77-
white++;
78+
blue++;
7879
}
7980
}
8081

81-
ShapeAndColorResult resultPegs = new(black, blue, white);
82+
ShapeAndColorResult resultPegs = new(black, white, blue);
8283

8384
if ((resultPegs.Correct + resultPegs.WrongPosition + resultPegs.ColorOrShape) > _game.NumberCodes)
8485
throw new InvalidOperationException("There are more keyPegs than codes"); // Should not be the case

src/services/gameapi/Codebreaker.GameAPIs.Analyzers/Fields/ColorField_Parsable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public static ColorField Parse(string s, IFormatProvider? provider = default)
1212
}
1313
else
1414
{
15-
throw new FormatException($"Cannot parse value {s}");
15+
throw new ArgumentException($"Cannot parse value {s}") { HResult = 4404 };
1616
}
1717
}
1818

src/services/gameapi/Codebreaker.GameAPIs.Analyzers/Fields/ShapeAndColorField_Parsable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public static ShapeAndColorField Parse(string s, IFormatProvider? provider = def
1212
}
1313
else
1414
{
15-
throw new ArgumentException($"Cannot parse value {s}", nameof(s));
15+
throw new ArgumentException($"Cannot parse value {s} - use ';' to separate shape and color", nameof(s)) { HResult = 4404 };
1616
}
1717
}
1818

0 commit comments

Comments
 (0)