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> ReadSessionMetadatas(); Task ReadSession(string name); Task UpdateSession(SessionMetadata session); Task ReadSessionMetaData(string name); Task ReadUser(string userName); } public class GameboardRepository { /// /// Returns session, board state, and user documents, grouped by session. /// private static readonly string View_SessionWithBoardState = "_design/session/_view/session-with-boardstate"; /// /// Returns session and user documents, grouped by session. /// 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 logger; public GameboardRepository(IHttpClientFactory clientFactory, ILogger logger) { client = clientFactory.CreateClient("couchdb"); this.logger = logger; } //public async Task> 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>(responseContent); // if (result != null) // { // var groupedBySession = result.rows.GroupBy(row => row.id); // var sessions = new List(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(); // var player1 = group.Skip(1).FirstOrDefault()?.doc.ToObject(); // var player2Doc = group.Skip(2).FirstOrDefault()?.doc; // if (session != null && player1 != null && player2Doc != null) // { // var player2 = IsUserDocument(player2Doc) // ? new Models.User(player2Doc.ToObject()!) // : null; // //sessions.Add(new SessionMetadata(session.Name, session.IsPrivate, player1.Id, player2?.Id)); // } // } // return new Collection(sessions); // } // return new Collection(Array.Empty()); //} private static bool IsUserDocument(JObject player2Doc) { return player2Doc?.SelectToken(nameof(CouchDocument.DocumentType))?.Value() == WhichDocumentType.User; } //public async Task 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>(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(); // var player1 = group[1].doc.ToObject(); // var player2Doc = group[2].doc; // var boardState = group.Last().doc.ToObject(); // if (session != null && player1 != null && boardState != null) // { // var player2 = IsUserDocument(player2Doc) // ? new Models.User(player2Doc.ToObject()!) // : 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 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>(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(); // var player1 = group[1].doc.ToObject(); // var player2Doc = group[2].doc; // if (session != null && player1 != null) // { // var player2 = IsUserDocument(player2Doc) // ? new Models.User(player2Doc.ToObject()!) // : null; // return new SessionMetadata(session.Name, session.IsPrivate, player1.Id, player2?.Id); // } // } // return null; //} /// /// Saves a snapshot of board state and the most recent move. /// 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 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(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 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(json).JoinSucceeded; //} //public async Task 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(json); // if (deserialized.JoinSucceeded) // { // return deserialized.SessionName; // } // return null; //} } }