Skip to content

Implement Queen Attack generator #393

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion exercises/queen-attack/Example.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public Queen(int row, int column)
public int Column { get; }
}

public static class Queens
public static class QueenAttack
{
public static bool CanAttack(Queen white, Queen black)
{
Expand All @@ -25,4 +25,17 @@ public static bool CanAttack(Queen white, Queen black)
black.Column == white.Column ||
Math.Abs(black.Row - white.Row) == Math.Abs(black.Column - white.Column);
}

public static Queen Create(int row, int column)
{
const int MIN_VALUE = 0;
const int MAX_VALUE = 7;

if (row < MIN_VALUE || column < MIN_VALUE || row > MAX_VALUE || column > MAX_VALUE)
{
throw new ArgumentOutOfRangeException("invalid queen position");
}

return new Queen(row, column);
}
}
7 changes: 6 additions & 1 deletion exercises/queen-attack/QueenAttack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ public Queen(int row, int column)
public int Column { get; }
}

public static class Queens
public static class QueenAttack
{
public static bool CanAttack(Queen white, Queen black)
{
throw new NotImplementedException("You need to implement this function.");
}

public static Queen Create(int row, int column)
{
throw new NotImplementedException("You need to implement this function.");
}
}
76 changes: 57 additions & 19 deletions exercises/queen-attack/QueenAttackTest.cs
Original file line number Diff line number Diff line change
@@ -1,55 +1,93 @@
using System;
// This file was auto-generated based on version 1.0.0 of the canonical data.

using Xunit;
using System;

public class QueenAttackTest
{
[Fact]
public void Cannot_occupy_same_space()
public void Queen_with_a_valid_position_does_not_throw_exception()
{
var actual = QueenAttack.Create(2, 2);
}

[Fact(Skip = "Remove to run test")]
public void Queen_must_have_positive_rank()
{
Assert.Throws<ArgumentOutOfRangeException>(() => QueenAttack.Create(-2, 2));
}

[Fact(Skip = "Remove to run test")]
public void Queen_must_have_rank_on_board()
{
Assert.Throws<ArgumentOutOfRangeException>(() => QueenAttack.Create(8, 4));
}

[Fact(Skip = "Remove to run test")]
public void Queen_must_have_positive_file()
{
Assert.Throws<ArgumentOutOfRangeException>(() => QueenAttack.Create(2, -2));
}

[Fact(Skip = "Remove to run test")]
public void Queen_must_have_file_on_board()
{
var white = new Queen(2, 4);
var black = new Queen(2, 4);
Assert.Throws<ArgumentException>(() => Queens.CanAttack(white, black));
Assert.Throws<ArgumentOutOfRangeException>(() => QueenAttack.Create(4, 8));
}

[Fact(Skip = "Remove to run test")]
public void Cannot_attack()
public void Can_not_attack()
{
Assert.False(Queens.CanAttack(new Queen(2, 3), new Queen(4, 7)));
var whiteQueen = QueenAttack.Create(2,4);
var blackQueen = QueenAttack.Create(6,6);
Assert.False(QueenAttack.CanAttack(whiteQueen, blackQueen));
}

[Fact(Skip = "Remove to run test")]
public void Can_attack_on_same_row()
public void Can_attack_on_same_rank()
{
Assert.True(Queens.CanAttack(new Queen(2, 4), new Queen(2, 7)));
var whiteQueen = QueenAttack.Create(2,4);
var blackQueen = QueenAttack.Create(2,6);
Assert.True(QueenAttack.CanAttack(whiteQueen, blackQueen));
}

[Fact(Skip = "Remove to run test")]
public void Can_attack_on_same_column()
public void Can_attack_on_same_file()
{
Assert.True(Queens.CanAttack(new Queen(5, 4), new Queen(2, 4)));
var whiteQueen = QueenAttack.Create(4,5);
var blackQueen = QueenAttack.Create(2,5);
Assert.True(QueenAttack.CanAttack(whiteQueen, blackQueen));
}

[Fact(Skip = "Remove to run test")]
public void Can_attack_on_diagonal()
public void Can_attack_on_first_diagonal()
{
Assert.True(Queens.CanAttack(new Queen(1, 1), new Queen(6, 6)));
var whiteQueen = QueenAttack.Create(2,2);
var blackQueen = QueenAttack.Create(0,4);
Assert.True(QueenAttack.CanAttack(whiteQueen, blackQueen));
}

[Fact(Skip = "Remove to run test")]
public void Can_attack_on_other_diagonal()
public void Can_attack_on_second_diagonal()
{
Assert.True(Queens.CanAttack(new Queen(0, 6), new Queen(1, 7)));
var whiteQueen = QueenAttack.Create(2,2);
var blackQueen = QueenAttack.Create(3,1);
Assert.True(QueenAttack.CanAttack(whiteQueen, blackQueen));
}

[Fact(Skip = "Remove to run test")]
public void Can_attack_on_yet_another_diagonal()
public void Can_attack_on_third_diagonal()
{
Assert.True(Queens.CanAttack(new Queen(4, 1), new Queen(6, 3)));
var whiteQueen = QueenAttack.Create(2,2);
var blackQueen = QueenAttack.Create(1,1);
Assert.True(QueenAttack.CanAttack(whiteQueen, blackQueen));
}

[Fact(Skip = "Remove to run test")]
public void Can_attack_on_a_diagonal_slanted_the_other_way()
public void Can_attack_on_fourth_diagonal()
{
Assert.True(Queens.CanAttack(new Queen(6, 1), new Queen(1, 6)));
var whiteQueen = QueenAttack.Create(2,2);
var blackQueen = QueenAttack.Create(5,5);
Assert.True(QueenAttack.CanAttack(whiteQueen, blackQueen));
}
}
85 changes: 85 additions & 0 deletions generators/Exercises/QueenAttack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using Generators.Input;
using Generators.Output;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;

namespace Generators.Exercises
{
public class QueenAttack : Exercise
{
protected override void UpdateCanonicalData(CanonicalData canonicalData)
{
foreach (var canonicalDataCase in canonicalData.Cases)
{
if (canonicalDataCase.Property == "create")
{
SetCreatePropertyData(canonicalDataCase);
}
}
}

protected override string RenderTestMethodBodyAssert(TestMethodBody testMethodBody)
{
if (testMethodBody.CanonicalDataCase.Property == "canAttack")
{
return RenderCanAttackAssert(testMethodBody);
}

if (testMethodBody.UseVariableForTested)
{
return string.Empty;
}

return base.RenderTestMethodBodyAssert(testMethodBody);
}

private static string RenderCanAttackAssert(TestMethodBody testMethodBody)
{
const string template =
@"var whiteQueen = QueenAttack.Create({{whiteQueenX}},{{whiteQueenY}});
var blackQueen = QueenAttack.Create({{blackQueenX}},{{blackQueenY}});
Assert.{% if Expected %}True{% else %}False{% endif %}(QueenAttack.CanAttack(whiteQueen, blackQueen));";

var whiteQueenPositions = GetCoordinatesFromPosition(testMethodBody.CanonicalDataCase.Input["white_queen"]);
var blackQueenPositions = GetCoordinatesFromPosition(testMethodBody.CanonicalDataCase.Input["black_queen"]);

var templateParameters = new
{
whiteQueenX = whiteQueenPositions.Item1,
whiteQueenY = whiteQueenPositions.Item2,
blackQueenX = blackQueenPositions.Item1,
blackQueenY = blackQueenPositions.Item2,
Expected = testMethodBody.CanonicalDataCase.Expected
};

return TemplateRenderer.RenderInline(template, templateParameters);
}

private static Tuple<int, int> GetCoordinatesFromPosition(object rawPosition)
{
var coordinates = ((JObject)rawPosition).ToObject<Dictionary<string, string>>()["position"].Split(',');

var positionX = int.Parse(coordinates[0].TrimStart('('));
var positionY = int.Parse(coordinates[1].TrimEnd(')'));

return Tuple.Create(positionX, positionY);
}

private static void SetCreatePropertyData(CanonicalDataCase canonicalDataCase)
{
var validExpected = (long)canonicalDataCase.Expected >= 0;

canonicalDataCase.UseVariableForTested = validExpected;
canonicalDataCase.ExceptionThrown = validExpected ? null : typeof(ArgumentOutOfRangeException);
canonicalDataCase.Description = validExpected ? canonicalDataCase.Description + " does not throw exception" : canonicalDataCase.Description;

var coordinates = GetCoordinatesFromPosition(canonicalDataCase.Input["queen"]);
canonicalDataCase.Input = new Dictionary<string, object>
{
["X"] = coordinates.Item1,
["Y"] = coordinates.Item2
};
}
}
}