Rename folder from Shogi.Sockets to Shogi.Api
This commit is contained in:
49
Shogi.Api/Repositories/CouchModels/BoardStateDocument.cs
Normal file
49
Shogi.Api/Repositories/CouchModels/BoardStateDocument.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Shogi.Domain;
|
||||
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
public class BoardStateDocument : CouchDocument
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A dictionary where the key is a board-notation position, like D3.
|
||||
/// </summary>
|
||||
public Dictionary<string, Piece?> Board { get; set; }
|
||||
|
||||
public Piece[] Player1Hand { get; set; }
|
||||
|
||||
public Piece[] Player2Hand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Move is null for first BoardState of a session - before anybody has made moves.
|
||||
/// </summary>
|
||||
public Move? Move { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor and setters are for deserialization.
|
||||
/// </summary>
|
||||
public BoardStateDocument() : base(WhichDocumentType.BoardState)
|
||||
{
|
||||
Name = string.Empty;
|
||||
Board = new Dictionary<string, Piece?>(81, StringComparer.OrdinalIgnoreCase);
|
||||
Player1Hand = Array.Empty<Piece>();
|
||||
Player2Hand = Array.Empty<Piece>();
|
||||
}
|
||||
|
||||
public BoardStateDocument(string sessionName, Session shogi)
|
||||
: base($"{sessionName}-{DateTime.Now:O}", WhichDocumentType.BoardState)
|
||||
{
|
||||
static Piece MapPiece(Domain.ValueObjects.Piece piece)
|
||||
{
|
||||
return new Piece { IsPromoted = piece.IsPromoted, Owner = piece.Owner, WhichPiece = piece.WhichPiece };
|
||||
}
|
||||
|
||||
Name = sessionName;
|
||||
Board = shogi.BoardState.State.ToDictionary(kvp => kvp.Key, kvp => kvp.Value == null ? null : MapPiece(kvp.Value));
|
||||
|
||||
Player1Hand = shogi.BoardState.Player1Hand.Select(piece => MapPiece(piece)).ToArray();
|
||||
Player2Hand = shogi.BoardState.Player2Hand.Select(piece => MapPiece(piece)).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Shogi.Api/Repositories/CouchModels/CouchCreatedResult.cs
Normal file
15
Shogi.Api/Repositories/CouchModels/CouchCreatedResult.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
public class CouchCreateResult
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public bool Ok { get; set; }
|
||||
public string Rev { get; set; }
|
||||
|
||||
public CouchCreateResult()
|
||||
{
|
||||
Id = string.Empty;
|
||||
Rev = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Shogi.Api/Repositories/CouchModels/CouchDocument.cs
Normal file
27
Shogi.Api/Repositories/CouchModels/CouchDocument.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
[Obsolete]
|
||||
public abstract class CouchDocument
|
||||
{
|
||||
[JsonProperty("_id")] public string Id { get; set; }
|
||||
[JsonProperty("_rev")] public string? RevisionId { get; set; }
|
||||
public WhichDocumentType DocumentType { get; }
|
||||
public DateTimeOffset CreatedDate { get; set; }
|
||||
|
||||
public CouchDocument(WhichDocumentType documentType)
|
||||
: this(string.Empty, documentType, DateTimeOffset.UtcNow) { }
|
||||
|
||||
public CouchDocument(string id, WhichDocumentType documentType)
|
||||
: this(id, documentType, DateTimeOffset.UtcNow) { }
|
||||
|
||||
public CouchDocument(string id, WhichDocumentType documentType, DateTimeOffset createdDate)
|
||||
{
|
||||
Id = id;
|
||||
DocumentType = documentType;
|
||||
CreatedDate = createdDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Shogi.Api/Repositories/CouchModels/CouchFindResult.cs
Normal file
16
Shogi.Api/Repositories/CouchModels/CouchFindResult.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
internal class CouchFindResult<T>
|
||||
{
|
||||
public T[] docs;
|
||||
public string warning;
|
||||
|
||||
public CouchFindResult()
|
||||
{
|
||||
docs = Array.Empty<T>();
|
||||
warning = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Shogi.Api/Repositories/CouchModels/CouchViewResult.cs
Normal file
28
Shogi.Api/Repositories/CouchModels/CouchViewResult.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
public class CouchViewResult<T> where T : class
|
||||
{
|
||||
public int total_rows;
|
||||
public int offset;
|
||||
public CouchViewResultRow<T>[] rows;
|
||||
|
||||
public CouchViewResult()
|
||||
{
|
||||
rows = Array.Empty<CouchViewResultRow<T>>();
|
||||
}
|
||||
}
|
||||
|
||||
public class CouchViewResultRow<T>
|
||||
{
|
||||
public string id;
|
||||
public T doc;
|
||||
|
||||
public CouchViewResultRow()
|
||||
{
|
||||
id = string.Empty;
|
||||
doc = default!;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Shogi.Api/Repositories/CouchModels/Move.cs
Normal file
32
Shogi.Api/Repositories/CouchModels/Move.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Shogi.Domain;
|
||||
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
public class Move
|
||||
{
|
||||
/// <summary>
|
||||
/// A board coordinate, like A3 or G6. When null, look for PieceFromHand to exist.
|
||||
/// </summary>
|
||||
public string? From { get; set; }
|
||||
|
||||
public bool IsPromotion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The piece placed from the player's hand.
|
||||
/// </summary>
|
||||
public WhichPiece? PieceFromHand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A board coordinate, like A3 or G6.
|
||||
/// </summary>
|
||||
public string To { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor and setters are for deserialization.
|
||||
/// </summary>
|
||||
public Move()
|
||||
{
|
||||
To = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Shogi.Api/Repositories/CouchModels/Piece.cs
Normal file
11
Shogi.Api/Repositories/CouchModels/Piece.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Shogi.Domain;
|
||||
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
public class Piece
|
||||
{
|
||||
public bool IsPromoted { get; set; }
|
||||
public WhichPlayer Owner { get; set; }
|
||||
public WhichPiece WhichPiece { get; set; }
|
||||
}
|
||||
}
|
||||
28
Shogi.Api/Repositories/CouchModels/SessionDocument.cs
Normal file
28
Shogi.Api/Repositories/CouchModels/SessionDocument.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Shogi.Contracts.Types;
|
||||
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
public class SessionDocument : CouchDocument
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Player1Id { get; set; }
|
||||
public string? Player2Id { get; set; }
|
||||
public bool IsPrivate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor and setters are for deserialization.
|
||||
/// </summary>
|
||||
public SessionDocument() : base(WhichDocumentType.Session)
|
||||
{
|
||||
Name = string.Empty;
|
||||
Player1Id = string.Empty;
|
||||
Player2Id = string.Empty;
|
||||
}
|
||||
|
||||
public SessionDocument(SessionMetadata sessionMetaData)
|
||||
: base(sessionMetaData.Name, WhichDocumentType.Session)
|
||||
{
|
||||
Name = sessionMetaData.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Shogi.Api/Repositories/CouchModels/UserDocument.cs
Normal file
27
Shogi.Api/Repositories/CouchModels/UserDocument.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Shogi.Api.Models;
|
||||
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
public class UserDocument : CouchDocument
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public WhichLoginPlatform Platform { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for JSON deserializing.
|
||||
/// </summary>
|
||||
public UserDocument() : base(WhichDocumentType.User)
|
||||
{
|
||||
DisplayName = string.Empty;
|
||||
}
|
||||
|
||||
public UserDocument(
|
||||
string id,
|
||||
string displayName,
|
||||
WhichLoginPlatform platform) : base(id, WhichDocumentType.User)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Platform = platform;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Shogi.Api/Repositories/CouchModels/WhichDocumentType.cs
Normal file
9
Shogi.Api/Repositories/CouchModels/WhichDocumentType.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Shogi.Api.Repositories.CouchModels
|
||||
{
|
||||
public enum WhichDocumentType
|
||||
{
|
||||
User,
|
||||
Session,
|
||||
BoardState
|
||||
}
|
||||
}
|
||||
22
Shogi.Api/Repositories/Dto/BoardStateDto.cs
Normal file
22
Shogi.Api/Repositories/Dto/BoardStateDto.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Shogi.Domain;
|
||||
using Shogi.Domain.ValueObjects;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Shogi.Api.Repositories.Dto;
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
public class BoardStateDto
|
||||
{
|
||||
public ReadOnlyDictionary<string, Piece?> State { get; set; }
|
||||
|
||||
public List<Piece> Player1Hand { get; set; }
|
||||
|
||||
public List<Piece> Player2Hand { get; set; }
|
||||
|
||||
public Move PreviousMove { get; }
|
||||
|
||||
public WhichPlayer WhoseTurn { get; set; }
|
||||
public WhichPlayer? InCheck { get; set; }
|
||||
public bool IsCheckmate { get; set; }
|
||||
}
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
14
Shogi.Api/Repositories/Dto/SessionDto.cs
Normal file
14
Shogi.Api/Repositories/Dto/SessionDto.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Shogi.Api.Repositories.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// Useful with Dapper to read from database.
|
||||
/// </summary>
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
public class SessionDto
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Player1 { get; set; }
|
||||
public string Player2 { get; set; }
|
||||
public BoardStateDto BoardState { get; set; }
|
||||
}
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
232
Shogi.Api/Repositories/GameboardRepository.cs
Normal file
232
Shogi.Api/Repositories/GameboardRepository.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Shogi.Contracts.Types;
|
||||
using Shogi.Api.Repositories.CouchModels;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using Session = Shogi.Domain.Session;
|
||||
|
||||
namespace Shogi.Api.Repositories
|
||||
{
|
||||
public interface IGameboardRepository
|
||||
{
|
||||
Task CreateBoardState(Session session);
|
||||
Task CreateUser(Models.User user);
|
||||
Task<Collection<SessionMetadata>> ReadSessionMetadatas();
|
||||
Task<Session?> ReadSession(string name);
|
||||
Task UpdateSession(SessionMetadata session);
|
||||
Task<SessionMetadata?> ReadSessionMetaData(string name);
|
||||
Task<Models.User?> ReadUser(string userName);
|
||||
}
|
||||
|
||||
public class GameboardRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns session, board state, and user documents, grouped by session.
|
||||
/// </summary>
|
||||
private static readonly string View_SessionWithBoardState = "_design/session/_view/session-with-boardstate";
|
||||
/// <summary>
|
||||
/// Returns session and user documents, grouped by session.
|
||||
/// </summary>
|
||||
private static readonly string View_SessionMetadata = "_design/session/_view/session-metadata";
|
||||
private static readonly string View_User = "_design/user/_view/user";
|
||||
private const string ApplicationJson = "application/json";
|
||||
private readonly HttpClient client;
|
||||
private readonly ILogger<GameboardRepository> logger;
|
||||
|
||||
public GameboardRepository(IHttpClientFactory clientFactory, ILogger<GameboardRepository> logger)
|
||||
{
|
||||
client = clientFactory.CreateClient("couchdb");
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
//public async Task<Collection<SessionMetadata>> ReadSessionMetadatas()
|
||||
//{
|
||||
// var queryParams = new QueryBuilder { { "include_docs", "true" } }.ToQueryString();
|
||||
// var response = await client.GetAsync($"{View_SessionMetadata}{queryParams}");
|
||||
// var responseContent = await response.Content.ReadAsStringAsync();
|
||||
// var result = JsonConvert.DeserializeObject<CouchViewResult<JObject>>(responseContent);
|
||||
// if (result != null)
|
||||
// {
|
||||
// var groupedBySession = result.rows.GroupBy(row => row.id);
|
||||
// var sessions = new List<SessionMetadata>(result.total_rows / 3);
|
||||
// foreach (var group in groupedBySession)
|
||||
// {
|
||||
// /**
|
||||
// * A group contains 3 elements.
|
||||
// * 1) The session metadata.
|
||||
// * 2) User document of Player1.
|
||||
// * 3) User document of Player2.
|
||||
// */
|
||||
// var session = group.FirstOrDefault()?.doc.ToObject<SessionDocument>();
|
||||
// var player1 = group.Skip(1).FirstOrDefault()?.doc.ToObject<UserDocument>();
|
||||
// var player2Doc = group.Skip(2).FirstOrDefault()?.doc;
|
||||
// if (session != null && player1 != null && player2Doc != null)
|
||||
// {
|
||||
// var player2 = IsUserDocument(player2Doc)
|
||||
// ? new Models.User(player2Doc.ToObject<UserDocument>()!)
|
||||
// : null;
|
||||
// //sessions.Add(new SessionMetadata(session.Name, session.IsPrivate, player1.Id, player2?.Id));
|
||||
// }
|
||||
// }
|
||||
// return new Collection<SessionMetadata>(sessions);
|
||||
// }
|
||||
// return new Collection<SessionMetadata>(Array.Empty<SessionMetadata>());
|
||||
//}
|
||||
|
||||
private static bool IsUserDocument(JObject player2Doc)
|
||||
{
|
||||
return player2Doc?.SelectToken(nameof(CouchDocument.DocumentType))?.Value<WhichDocumentType>() == WhichDocumentType.User;
|
||||
}
|
||||
|
||||
//public async Task<Session?> ReadSession(string name)
|
||||
//{
|
||||
// static Domain.ValueObjects.Piece? MapPiece(Piece? piece)
|
||||
// {
|
||||
// return piece == null
|
||||
// ? null
|
||||
// : Domain.ValueObjects.Piece.Create(piece.WhichPiece, piece.Owner, piece.IsPromoted);
|
||||
// }
|
||||
|
||||
// var queryParams = new QueryBuilder
|
||||
// {
|
||||
// { "include_docs", "true" },
|
||||
// { "startkey", JsonConvert.SerializeObject(new [] {name}) },
|
||||
// { "endkey", JsonConvert.SerializeObject(new object [] {name, int.MaxValue}) }
|
||||
// }.ToQueryString();
|
||||
// var query = $"{View_SessionWithBoardState}{queryParams}";
|
||||
// logger.LogInformation("ReadSession() query: {query}", query);
|
||||
// var response = await client.GetAsync(query);
|
||||
// var responseContent = await response.Content.ReadAsStringAsync();
|
||||
// var result = JsonConvert.DeserializeObject<CouchViewResult<JObject>>(responseContent);
|
||||
// if (result != null && result.rows.Length > 2)
|
||||
// {
|
||||
// var group = result.rows;
|
||||
// /**
|
||||
// * A group contains multiple elements.
|
||||
// * 0) The session metadata.
|
||||
// * 1) User documents of Player1.
|
||||
// * 2) User documents of Player1.
|
||||
// * 2.a) If the Player2 document doesn't exist, CouchDB will return the SessionDocument instead :(
|
||||
// * Everything Else) Snapshots of the boardstate after every player move.
|
||||
// */
|
||||
// var session = group[0].doc.ToObject<SessionDocument>();
|
||||
// var player1 = group[1].doc.ToObject<UserDocument>();
|
||||
// var player2Doc = group[2].doc;
|
||||
// var boardState = group.Last().doc.ToObject<BoardStateDocument>();
|
||||
|
||||
// if (session != null && player1 != null && boardState != null)
|
||||
// {
|
||||
// var player2 = IsUserDocument(player2Doc)
|
||||
// ? new Models.User(player2Doc.ToObject<UserDocument>()!)
|
||||
// : null;
|
||||
// var metaData = new SessionMetadata(session.Name, session.IsPrivate, player1.Id, player2?.Id);
|
||||
// var shogiBoardState = new BoardState(boardState.Board.ToDictionary(kvp => kvp.Key, kvp => MapPiece(kvp.Value)));
|
||||
// //return new Session(shogiBoardState, metaData);
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//public async Task<SessionMetadata?> ReadSessionMetaData(string name)
|
||||
//{
|
||||
// var queryParams = new QueryBuilder
|
||||
// {
|
||||
// { "include_docs", "true" },
|
||||
// { "startkey", JsonConvert.SerializeObject(new [] {name}) },
|
||||
// { "endkey", JsonConvert.SerializeObject(new object [] {name, int.MaxValue}) }
|
||||
// }.ToQueryString();
|
||||
// var response = await client.GetAsync($"{View_SessionMetadata}{queryParams}");
|
||||
// var responseContent = await response.Content.ReadAsStringAsync();
|
||||
// var result = JsonConvert.DeserializeObject<CouchViewResult<JObject>>(responseContent);
|
||||
// if (result != null && result.rows.Length > 2)
|
||||
// {
|
||||
// var group = result.rows;
|
||||
// /**
|
||||
// * A group contains 3 elements.
|
||||
// * 1) The session metadata.
|
||||
// * 2) User document of Player1.
|
||||
// * 3) User document of Player2.
|
||||
// */
|
||||
// var session = group[0].doc.ToObject<SessionDocument>();
|
||||
// var player1 = group[1].doc.ToObject<UserDocument>();
|
||||
// var player2Doc = group[2].doc;
|
||||
// if (session != null && player1 != null)
|
||||
// {
|
||||
// var player2 = IsUserDocument(player2Doc)
|
||||
// ? new Models.User(player2Doc.ToObject<UserDocument>()!)
|
||||
// : null;
|
||||
// return new SessionMetadata(session.Name, session.IsPrivate, player1.Id, player2?.Id);
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a snapshot of board state and the most recent move.
|
||||
/// </summary>
|
||||
public async Task CreateBoardState(Session session)
|
||||
{
|
||||
var boardStateDocument = new BoardStateDocument(session.Name, session);
|
||||
var content = new StringContent(JsonConvert.SerializeObject(boardStateDocument), Encoding.UTF8, ApplicationJson);
|
||||
var response = await client.PostAsync(string.Empty, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
//public async Task<bool> CreateSession(SessionMetadata session)
|
||||
//{
|
||||
// var sessionDocument = new SessionDocument(session);
|
||||
// var sessionContent = new StringContent(JsonConvert.SerializeObject(sessionDocument), Encoding.UTF8, ApplicationJson);
|
||||
// var postSessionDocumentTask = client.PostAsync(string.Empty, sessionContent);
|
||||
|
||||
// var boardStateDocument = new BoardStateDocument(session.Name, new Session());
|
||||
// var boardStateContent = new StringContent(JsonConvert.SerializeObject(boardStateDocument), Encoding.UTF8, ApplicationJson);
|
||||
|
||||
// if ((await postSessionDocumentTask).IsSuccessStatusCode)
|
||||
// {
|
||||
// var response = await client.PostAsync(string.Empty, boardStateContent);
|
||||
// return response.IsSuccessStatusCode;
|
||||
// }
|
||||
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//public async Task UpdateSession(SessionMetadata session)
|
||||
//{
|
||||
// // GET existing session to get revisionId.
|
||||
// var readResponse = await client.GetAsync(session.Name);
|
||||
// readResponse.EnsureSuccessStatusCode();
|
||||
// var sessionDocument = JsonConvert.DeserializeObject<SessionDocument>(await readResponse.Content.ReadAsStringAsync());
|
||||
|
||||
// // PUT the document with the revisionId.
|
||||
// var couchModel = new SessionDocument(session)
|
||||
// {
|
||||
// RevisionId = sessionDocument?.RevisionId
|
||||
// };
|
||||
// var content = new StringContent(JsonConvert.SerializeObject(couchModel), Encoding.UTF8, ApplicationJson);
|
||||
// var response = await client.PutAsync(couchModel.Id, content);
|
||||
// response.EnsureSuccessStatusCode();
|
||||
//}
|
||||
|
||||
//public async Task<bool> PutJoinPublicSession(PutJoinPublicSession request)
|
||||
//{
|
||||
// var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, MediaType);
|
||||
// var response = await client.PutAsync(JoinSessionRoute, content);
|
||||
// var json = await response.Content.ReadAsStringAsync();
|
||||
// return JsonConvert.DeserializeObject<PutJoinPublicSessionResponse>(json).JoinSucceeded;
|
||||
//}
|
||||
|
||||
//public async Task<string> PostJoinPrivateSession(PostJoinPrivateSession request)
|
||||
//{
|
||||
// var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, MediaType);
|
||||
// var response = await client.PostAsync(JoinSessionRoute, content);
|
||||
// var json = await response.Content.ReadAsStringAsync();
|
||||
// var deserialized = JsonConvert.DeserializeObject<PostJoinPrivateSessionResponse>(json);
|
||||
// if (deserialized.JoinSucceeded)
|
||||
// {
|
||||
// return deserialized.SessionName;
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
}
|
||||
}
|
||||
29
Shogi.Api/Repositories/QueryRepository.cs
Normal file
29
Shogi.Api/Repositories/QueryRepository.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Dapper;
|
||||
using Shogi.Api.Repositories.Dto;
|
||||
using Shogi.Contracts.Types;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace Shogi.Api.Repositories;
|
||||
|
||||
public class QueryRepository : IQueryRespository
|
||||
{
|
||||
private readonly string connectionString;
|
||||
|
||||
public QueryRepository(IConfiguration configuration)
|
||||
{
|
||||
connectionString = configuration.GetConnectionString("ShogiDatabase");
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SessionMetadata>> ReadAllSessionsMetadata()
|
||||
{
|
||||
using var connection = new SqlConnection(connectionString);
|
||||
return await connection.QueryAsync<SessionMetadata>(
|
||||
"session.ReadAllSessionsMetadata",
|
||||
commandType: System.Data.CommandType.StoredProcedure);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IQueryRespository
|
||||
{
|
||||
Task<IEnumerable<SessionMetadata>> ReadAllSessionsMetadata();
|
||||
}
|
||||
70
Shogi.Api/Repositories/SessionRepository.cs
Normal file
70
Shogi.Api/Repositories/SessionRepository.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using Dapper;
|
||||
using Shogi.Api.Repositories.Dto;
|
||||
using Shogi.Domain;
|
||||
using Shogi.Domain.Aggregates;
|
||||
using Shogi.Domain.ValueObjects;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Shogi.Api.Repositories;
|
||||
|
||||
public class SessionRepository : ISessionRepository
|
||||
{
|
||||
private readonly string connectionString;
|
||||
|
||||
public SessionRepository(IConfiguration configuration)
|
||||
{
|
||||
connectionString = configuration.GetConnectionString("ShogiDatabase");
|
||||
}
|
||||
|
||||
public async Task CreateSession(Session session)
|
||||
{
|
||||
var boardStateDto = new BoardStateDto
|
||||
{
|
||||
InCheck = session.BoardState.InCheck,
|
||||
IsCheckmate = session.BoardState.IsCheckmate,
|
||||
Player1Hand = session.BoardState.Player1Hand,
|
||||
Player2Hand = session.BoardState.Player2Hand,
|
||||
State = session.BoardState.State,
|
||||
WhoseTurn = session.BoardState.WhoseTurn,
|
||||
};
|
||||
|
||||
using var connection = new SqlConnection(connectionString);
|
||||
await connection.ExecuteAsync(
|
||||
"session.CreateSession",
|
||||
new
|
||||
{
|
||||
Name = sessionName,
|
||||
InitialBoardStateDocument = JsonSerializer.Serialize(boardStateDto),
|
||||
Player1Name = player1,
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<ShogiBoard?> ReadShogiBoard(string name)
|
||||
{
|
||||
using var connection = new SqlConnection(connectionString);
|
||||
var results = await connection.QueryAsync<SessionDto>(
|
||||
"session.ReadSession",
|
||||
commandType: CommandType.StoredProcedure);
|
||||
var dto = results.SingleOrDefault();
|
||||
if (dto == null) return null;
|
||||
|
||||
var boardState = new BoardState(
|
||||
state: new(dto.BoardState.State),
|
||||
player1Hand: dto.BoardState.Player1Hand,
|
||||
player2Hand: dto.BoardState.Player2Hand,
|
||||
whoseTurn: dto.BoardState.WhoseTurn,
|
||||
playerInCheck: dto.BoardState.InCheck,
|
||||
previousMove: dto.BoardState.PreviousMove);
|
||||
var session = new ShogiBoard(boardState);
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ISessionRepository
|
||||
{
|
||||
Task CreateSession(Session session);
|
||||
Task<ShogiBoard?> ReadShogiBoard(string name);
|
||||
}
|
||||
47
Shogi.Api/Repositories/UserRepository.cs
Normal file
47
Shogi.Api/Repositories/UserRepository.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Dapper;
|
||||
using Shogi.Api.Models;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace Shogi.Api.Repositories;
|
||||
|
||||
public class UserRepository : IUserRepository
|
||||
{
|
||||
private readonly string connectionString;
|
||||
|
||||
public UserRepository(IConfiguration configuration)
|
||||
{
|
||||
connectionString = configuration.GetConnectionString("ShogiDatabase");
|
||||
}
|
||||
|
||||
public async Task CreateUser(User user)
|
||||
{
|
||||
using var connection = new SqlConnection(connectionString);
|
||||
await connection.ExecuteAsync(
|
||||
"user.CreateUser",
|
||||
new
|
||||
{
|
||||
Name = user.Id,
|
||||
DisplayName = user.DisplayName,
|
||||
Platform = user.LoginPlatform.ToString()
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<User?> ReadUser(string id)
|
||||
{
|
||||
using var connection = new SqlConnection(connectionString);
|
||||
var results = await connection.QueryAsync<User>(
|
||||
"user.ReadUser",
|
||||
new { Name = id },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return results.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public interface IUserRepository
|
||||
{
|
||||
Task CreateUser(User user);
|
||||
Task<User?> ReadUser(string id);
|
||||
}
|
||||
Reference in New Issue
Block a user