Skip to content
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

Dotnet version of the workshop as used with Customer #10

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Participants will be guided to install the GitHub Copilot VS Code extension, fol

Depending on the time available, participants will be able to complete the game or just get started, from a simple version all the way to introducing additional logic to make the game more interesting complete, with unit tests and REST API endpoints.


Python is the language of choice for this workshop, but the principles can be applied to any language supported by GitHub Copilot. There is a version of the workshop for C# developers available in the dotnet folder.

## Instructions

Expand Down
14 changes: 14 additions & 0 deletions dotnet/1. setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Setup Instructions

To get started with the Rock Paper Scissors workshop in .NET, you'll need:

1. Visual Studio Code or Visual Studio
2. .NET 7.0 SDK or later installed
3. GitHub Copilot extension installed and authenticated
4. Git installed

### Verify Your Setup

Open a terminal and verify your installation:
```bash
dotnet --version # Should show 7.0.x or later
36 changes: 36 additions & 0 deletions dotnet/2. core exercises.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
### 2. Core exercises

## Workshop Exercises

### Core Exercise - Building Rock Paper Scissors in .NET

1. Clone the starter repository which contains the basic solution structure:
- RockPaperScissors.Core (game logic)
- RockPaperScissors.Api (REST API)
- RockPaperScissors.Tests (unit tests)
- RockPaperScissors.Console (console interface)

2. Test the initial program state:
```bash
cd RockPaperScissors.Console
dotnet run
```
You should see a welcome message, and the program will throw a NotImplementedException since the game logic hasn't been implemented yet. This is expected!

3. Open the `Game.cs` file in RockPaperScissors.Core project
4. Implement the `EvaluateResult` method in the `Game` class:
- Use GitHub Copilot to help implement the basic Rock Paper Scissors logic
- The method should return Win, Lose, or Draw based on the player's move and the computer's move

5. Open the `Program.cs` file in RockPaperScissors.Console project
6. Implement the console game logic:
- Prompt the user to enter their move
- Parse the user's input and validate it
- Generate a random move for the computer
- Call the `EvaluateResult` method to determine the game result
- Display the result to the user

7. Run the console application again to test your implementation:
```bash
dotnet run
```
75 changes: 75 additions & 0 deletions dotnet/3. challenge exercises.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Challenge Exercises

<details>
<summary>Challenge #1 - Adding Lizard and Spock</summary>

### Extending the Game Logic

1. Open `Game.cs` in RockPaperScissors.Core
2. Extend the `Move` enum to include Lizard and Spock
3. Update the game logic to handle the new moves
4. Update the console interface to show all options

Business Logic:
<img width="400" alt="RPSLS Rules" src="../assets/Rock Paper Scissors Lizard Spock image.jpg">
</details>

<details>
<summary>Challenge #2 - Implementing Unit Tests</summary>

### Adding Unit Tests

1. Navigate to RockPaperScissors.Tests project
2. Implement tests for all possible game outcomes
3. Use GitHub Copilot to help generate test cases
4. Aim for 100% code coverage

Example test scenarios:
- Rock crushes Scissors
- Paper covers Rock
- Scissors cuts Paper
- Lizard poisons Spock
- Spock vaporizes Rock

### Running the Tests

1. Open a terminal and navigate to the RockPaperScissors.Tests project directory:
```bash
cd RockPaperScissors.Tests
```

2. Run the tests using the .NET CLI:
```bash
dotnet test
```

3. Verify that all tests pass and review the test results in the terminal output.
</details>

<details>
<summary>Challenge #3 - Implementing the REST API</summary>

### Completing the API

1. Navigate to the RockPaperScissors.Api project
2. Open the `GameController.cs` file
3. Implement the `Play` endpoint in `GameController`:
- Accept a JSON request body with the player's move
- Generate a random move for the computer
- Call the `EvaluateResult` method to determine the game result
- Return the result and the computer's move in the response

### Testing and Debugging the API

1. Open the project in VSCode.
2. Set breakpoints in the `GameController.cs` file.
3. Open the Debug panel in VSCode.
4. Select the ".NET Core Launch (API)" configuration.
5. Start debugging by pressing F5.
6. Use the web browser to navigate to the `/game/play` endpoint with a query parameter for the player's move:
```
http://localhost:5000/game/play?move=Rock
```
7. Verify that the response contains the game result and the computer's move.
8. Trigger the breakpoints to debug the API.
</details>
14 changes: 14 additions & 0 deletions dotnet/4. additional resources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Additional Resources

- [ASP.NET Core Documentation](https://docs.microsoft.com/en-us/aspnet/core)
- [xUnit Testing Framework](https://xunit.net/)
- [GitHub Copilot Documentation](https://docs.github.com/en/copilot)
- [REST API Best Practices](https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design)

## Next Steps

Consider these extensions:
1. Add a database to store game history
2. Implement player authentication
3. Add a web frontend using Blazor
4. Deploy to Azure using GitHub Actions
22 changes: 22 additions & 0 deletions dotnet/RockPaperScissors.Api/Controllers/GameController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Mvc;
using RockPaperScissors.Core;

namespace RockPaperScissors.Api.Controllers;

[ApiController]
[Route("[controller]")]
public class GameController : ControllerBase
{
private readonly IGame _game;

public GameController(IGame game)
{
_game = game;
}

[HttpGet("play")]
public IActionResult Play([FromQuery] Move move)
{
throw new NotImplementedException("Implement the API endpoint here");
}
}
22 changes: 22 additions & 0 deletions dotnet/RockPaperScissors.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using RockPaperScissors.Core;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddScoped<IGame, Game>();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();
41 changes: 41 additions & 0 deletions dotnet/RockPaperScissors.Api/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:14939",
"sslPort": 44330
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5179",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7283;http://localhost:5179",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
18 changes: 18 additions & 0 deletions dotnet/RockPaperScissors.Api/RockPaperScissors.Api.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\RockPaperScissors.Core\RockPaperScissors.Core.csproj" />
</ItemGroup>

</Project>
19 changes: 19 additions & 0 deletions dotnet/RockPaperScissors.Api/RockPaperScissors.Api.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@baseUrl = http://localhost:5179

### Play a game with Rock
POST {{baseUrl}}/game/play
Content-Type: application/json

"Rock"

### Play a game with Paper
POST {{baseUrl}}/game/play
Content-Type: application/json

"Paper"

### Play a game with Scissors
POST {{baseUrl}}/game/play
Content-Type: application/json

"Scissors"
9 changes: 9 additions & 0 deletions dotnet/RockPaperScissors.Api/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
6 changes: 6 additions & 0 deletions dotnet/RockPaperScissors.Console/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using RockPaperScissors.Core;

var game = new Game();

Console.WriteLine("Welcome to Rock, Paper, Scissors!");
Console.WriteLine("Implement the console game logic here");
14 changes: 14 additions & 0 deletions dotnet/RockPaperScissors.Console/RockPaperScissors.Console.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<ProjectReference Include="..\RockPaperScissors.Core\RockPaperScissors.Core.csproj" />
</ItemGroup>

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
28 changes: 28 additions & 0 deletions dotnet/RockPaperScissors.Core/Game.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace RockPaperScissors.Core;

public enum Move
{
Rock,
Paper,
Scissors
}

public enum GameResult
{
Win,
Lose,
Draw
}

public interface IGame
{
GameResult EvaluateResult(Move playerMove, Move computerMove);
}

public class Game : IGame
{
public GameResult EvaluateResult(Move playerMove, Move computerMove)
{
throw new NotImplementedException("Implement the game logic here");
}
}
9 changes: 9 additions & 0 deletions dotnet/RockPaperScissors.Core/RockPaperScissors.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
20 changes: 20 additions & 0 deletions dotnet/RockPaperScissors.Tests/GameTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using RockPaperScissors.Core;
using Xunit;

namespace RockPaperScissors.Tests;

public class GameTests
{
[Fact]
public void WhenPlayerChoosesRock_ShouldReturnValidResult()
{
// Arrange
var game = new Game();

// Act
var result = game.EvaluateResult(Move.Rock, Move.Scissors); // Example computer move

// Assert
Assert.True(result is GameResult.Win or GameResult.Lose or GameResult.Draw);
}
}
Loading