Remove some hacks.

This commit is contained in:
AnduinXue
2024-01-13 11:11:06 +00:00
parent 7453a05b98
commit 5e9bde7e51
9 changed files with 118 additions and 83 deletions
@@ -1,41 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace Aiursoft.ChessServer.Controllers;
[Route("challenges")]
public class ChallengeController : ControllerBase
{
[HttpPost]
[Route("create")]
public IActionResult Create(Guid userId)
{
// Create a new challenge. Add to database.
return Ok();
}
[HttpGet]
[Route("list")]
public IActionResult List()
{
// Show all public challenges.
return Ok();
}
[HttpPost]
[Route("accept/{id:int}")]
public IActionResult Accept(int id, Guid userId)
{
// Accept a challenge. Remove the challenge from database.
// Create a new game. Redirect both players to the game.
return Ok();
}
[HttpPost]
[Route("reject/{id:int}")]
public IActionResult Edit(int id, Guid userId)
{
// If challenge owner is the same as user id,
// Edit a challenge in database.
return Ok();
}
}
@@ -21,7 +21,10 @@ public class HomeController : Controller
[HttpGet]
public IActionResult Index()
{
var model = new IndexViewModel(_database.Challenges);
var model = new IndexViewModel
{
Challenges = _database.GetPublicChallenges()
};
return View(model);
}
@@ -29,17 +32,17 @@ public class HomeController : Controller
public IActionResult Auto(Guid playerId)
{
// I created a challenge. Go to my challenge.
var iHaveAChallenge = _database.Challenges.FirstOrDefault(t => t.Value.Creator.Id == playerId);
if (iHaveAChallenge.Value != null)
var myChallengeKey = _database.GetMyChallengeKey(playerId);
if (myChallengeKey != null)
{
return RedirectToAction(nameof(Challenge), new { id = iHaveAChallenge.Key, playerId });
return RedirectToAction(nameof(Challenge), new { id = (int)myChallengeKey, playerId });
}
// Exists a public challenge. Go to that challenge.
var otherChallenge = _database.Challenges.FirstOrDefault(t => t.Value.Permission == ChallengePermission.Public);
if (otherChallenge.Value != null)
var otherChallenge = _database.GetFirstPublicChallengeKey();
if (otherChallenge != null)
{
return RedirectToAction(nameof(Challenge), new { id = otherChallenge.Key, playerId });
return RedirectToAction(nameof(Challenge), new { id = (int)otherChallenge, playerId });
}
// Create a new challenge.
@@ -49,10 +52,10 @@ public class HomeController : Controller
[HttpGet]
public IActionResult Create(Guid playerId)
{
var iHaveAChallenge = _database.Challenges.FirstOrDefault(t => t.Value.Creator.Id == playerId);
if (iHaveAChallenge.Value != null)
var myChallengeKey = _database.GetMyChallengeKey(playerId);
if (myChallengeKey != null)
{
return RedirectToAction(nameof(Challenge), new { id = iHaveAChallenge.Key, playerId });
return RedirectToAction(nameof(Challenge), new { id = myChallengeKey, playerId });
}
var model = new CreateChallengeViewModel();
return View(model);
@@ -75,20 +78,21 @@ public class HomeController : Controller
TimeLimit = model.TimeLimit,
};
var roomId = _counter.GetUniqueNo();
_database.Challenges.TryAdd(roomId, challenge);
return RedirectToAction(nameof(Challenge), new { id = roomId, playerId = model.CreatorId });
_database.CreateChallenge(roomId, challenge);
return RedirectToAction(nameof(Challenge), new { id = roomId });
}
[HttpGet]
public IActionResult Challenge(int id, Guid playerId)
public IActionResult Challenge(int id)
{
var player = _database.GetOrAddPlayer(playerId);
var challenge = _database.GetOrAddChallenge(id, player);
var model = new ChallengeViewModel()
var challenge = _database.GetChallenge(id);
if (challenge == null)
{
return RedirectToAction(nameof(Index));
}
var model = new ChallengeViewModel
{
RoomId = id,
PlayerId = playerId,
IsCreator = challenge.Creator.Id == playerId,
};
return View(model);
}
@@ -100,11 +104,10 @@ public class HomeController : Controller
{
return RedirectToAction(nameof(Challenge), new { id = model.Id, playerId = model.PlayerId });
}
var player = _database.GetOrAddPlayer(model.PlayerId);
var challenge = _database.GetOrAddChallenge(model.Id, player);
if (challenge.Creator.Id == model.PlayerId)
var challenge = _database.GetChallenge(model.Id);
if (challenge != null && challenge.Creator.Id == model.PlayerId)
{
_database.Challenges.TryRemove(model.Id, out _);
_database.DeleteChallenge(model.Id);
}
return RedirectToAction(nameof(Index));
}
@@ -10,7 +10,7 @@ public class InMemoryDatabase : ISingletonDependency
private ConcurrentDictionary<Guid, Player> Players { get; } = new();
public ConcurrentDictionary<int, Challenge> Challenges { get; } = new();
private ConcurrentDictionary<int, Challenge> Challenges { get; } = new();
public GameContext[] GetActiveGames()
{
@@ -36,11 +36,66 @@ public class InMemoryDatabase : ISingletonDependency
}
}
public Challenge GetOrAddChallenge(int id, Player creator)
public IReadOnlyCollection<KeyValuePair<int, Challenge>> GetPublicChallenges()
{
lock (Challenges)
{
return Challenges.GetOrAdd(id, _ => new Challenge(creator));
return Challenges
.Where(t => t.Value.Permission == ChallengePermission.Public)
.ToArray();
}
}
public Challenge? GetChallenge(int id)
{
lock (Challenges)
{
return Challenges.GetValueOrDefault(id);
}
}
public int? GetMyChallengeKey(Guid playerId)
{
lock (Challenges)
{
if (Challenges.All(t => t.Value.Creator.Id != playerId))
{
return null;
}
return Challenges
.FirstOrDefault(t => t.Value.Creator.Id == playerId)
.Key;
}
}
public int? GetFirstPublicChallengeKey()
{
lock (Challenges)
{
return Challenges
.FirstOrDefault(t => t.Value.Permission == ChallengePermission.Public)
.Key;
}
}
public void DeleteChallenge(int id)
{
lock (Challenges)
{
Challenges.TryRemove(id, out _);
}
}
public void CreateChallenge(int id, Challenge challenge)
{
lock (Challenges)
{
var result = Challenges.TryAdd(id, challenge);
if (!result)
{
throw new InvalidOperationException("Challenge already exists!");
}
}
}
}
+9
View File
@@ -44,4 +44,13 @@ public class Challenge
public TimeSpan TimeLimit { get; set; } = TimeSpan.FromMinutes(10);
public ChallengePermission Permission { get; set; } = ChallengePermission.Public;
// Possible messages:
// Player joined: p-joined-{player-nick-name}
// Player left: p-left-{player-nick-name}
// Room dropped: room-dropped
// Game started: game-started
// Creator transferred: creator-transferred-{new-owner-player-nick-name}
// Settings changed: settings-changed
public AsyncObservable<string> ChallengeChangedChannel { get; } = new();
}
@@ -2,9 +2,5 @@
public class ChallengeViewModel
{
public int RoomId { get; set; }
public Guid PlayerId { get; set; }
public bool IsCreator { get; set; }
public int RoomId { get; init; }
}
@@ -4,10 +4,5 @@ namespace Aiursoft.ChessServer.Models;
public class IndexViewModel
{
public ConcurrentDictionary<int, Challenge> Challenges { get; }
public IndexViewModel(ConcurrentDictionary<int, Challenge> challenges)
{
Challenges = challenges;
}
public required IReadOnlyCollection<KeyValuePair<int, Challenge>> Challenges { get; init; }
}
@@ -1,15 +1,16 @@
@model Aiursoft.ChessServer.Models.ChallengeViewModel
@using Aiursoft.ChessServer.Controllers
@model Aiursoft.ChessServer.Models.ChallengeViewModel
<div class="jumbotron">
<div class="container">
<h1 class="display-4">Waiting for joining...</h1>
<p class="lead">Please share the link of this room to your friend!</p>
@{
var link = $"{Context.Request.Scheme}://{Context.Request.Host}/Home/Room/{Model.RoomId}";
var link = $"{Context.Request.Scheme}://{Context.Request.Host}/Home/{nameof(HomeController.Challenge)}/{Model.RoomId}";
}
<form asp-controller="Home" asp-action="DropChallenge" asp-route-id="@Model.RoomId" method="post" class="d-inline" asp-antiforgery="false">
<div asp-validation-summary="All" class="text-danger"></div>
<input type="hidden" name="playerId" value="@Model.PlayerId"/>
<input type="hidden" name="playerId" value=""/>
<input type="text" class="form-control" value="@link" readonly>
<a class="btn btn-secondary btn-lg mt-4" data-clipboard-text="@link" role="button" data-toggle="tooltip" data-placement="top" title="Copied!">
@@ -24,6 +25,12 @@
@section scripts
{
<script type="module">
import { getUserId } from "/scripts/player.js";
const playerId = getUserId();
const playerIdControl = document.querySelector('input[name="playerId"]');
playerIdControl.value = playerId;
</script>
<script src="/node_modules/clipboard/dist/clipboard.min.js"></script>
<script>
// Initialize clipboard.
@@ -0,0 +1,10 @@
@{
Layout = null;
}
<script type="module">
import { getUserId } from "/scripts/player.js";
const playerId = getUserId();
if (playerId) {
window.location.href = window.location.href.toLowerCase().replace("challengenoid", "Challenge") + `?playerId=${playerId}`;
}
</script>
@@ -1,4 +1,5 @@
@model Aiursoft.ChessServer.Models.IndexViewModel
@using Aiursoft.ChessServer.Models
@model Aiursoft.ChessServer.Models.IndexViewModel
<div class="jumbotron">
<div class="container">
@@ -24,7 +25,7 @@
<th>Creator</th>
<th>Action</th>
</tr>
@foreach (var item in Model.Challenges)
@foreach (var item in Model.Challenges.Where(t => t.Value.Permission == ChallengePermission.Public))
{
<tr>
<td>@item.Value.Message</td>