328 lines
14 KiB
Plaintext
328 lines
14 KiB
Plaintext
@model YatzyGame.Controllers.HomeViewModel;
|
|
@using YatzyGame.Components;
|
|
|
|
@{
|
|
ViewData["Title"] = "Home Page";
|
|
}
|
|
<script>
|
|
window.gamekey = "@Model.gameID"
|
|
|
|
const ws = new WebSocket("ws://" + document.location.host + "/ws");
|
|
|
|
|
|
ws.addEventListener("message", (event) => {
|
|
const dat = event.data.split("|");
|
|
|
|
if (dat[0] == window.gamekey && dat[1] == "update") {
|
|
ws.close();
|
|
|
|
document.location.reload();
|
|
}
|
|
|
|
if (dat[0] == window.gamekey && dat[1] == "stop") {
|
|
ws.close();
|
|
|
|
document.location.location = document.location.hostname;
|
|
}
|
|
});
|
|
</script>
|
|
<div class="flexbox">
|
|
<div style="flex: 1;">
|
|
<div class="scoreboard">
|
|
@if(Model.GameStarted) {
|
|
<div></div>
|
|
foreach(var enu in Enum.GetValues(typeof(ScoreLine))){
|
|
@if (Model.GameStarted && !enu.ToString().Equals("bonus") && !Model.CurrentPlayer.scores.ContainsKey((ScoreLine)enu) && (Model.CurrentPlayer.name.Equals(Model.player.name) || !Model.onlineMultiplayer))
|
|
{
|
|
<div class="empty-insert-dice">
|
|
<a href="@Url.Action("InsertDice", "Home", new { game = Model.gameID, id = enu })" class="">==></a>
|
|
</div>
|
|
}
|
|
else {
|
|
<div class="empty-insert-dice"></div>
|
|
}
|
|
}
|
|
<div></div>
|
|
}
|
|
<div></div>
|
|
@foreach (var enu in Enum.GetValues(typeof(ScoreLine)))
|
|
{
|
|
<div>
|
|
@GameController.TypeLabel((ScoreLine)enu)
|
|
</div>
|
|
}
|
|
<div>Sum</div>
|
|
@foreach (var player in Model.players)
|
|
{
|
|
if(!Model.GameStarted)
|
|
{
|
|
<a class="deleteuser" href="@Url.Action("DeletePlayer", "Home", new { game = Model.gameID, id = player.name })"><b>@player.name</b></a>
|
|
}
|
|
else
|
|
{
|
|
<div><b>@player.name</b></div>
|
|
}
|
|
@foreach (var test in Enum.GetValues(typeof(ScoreLine)))
|
|
{
|
|
if (player.scores.TryGetValue((ScoreLine)Enum.Parse(typeof(ScoreLine), test.ToString(), true), out var score))
|
|
{
|
|
<div>@score</div>
|
|
}
|
|
else
|
|
{
|
|
<div></div>
|
|
}
|
|
}
|
|
<div>@player.scores.Where(x => x.Key != ScoreLine.top_sum).Select(x => x.Value).Sum()</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="GameArea">
|
|
<!-- Copy Join Link Section -->
|
|
|
|
|
|
@if (Model.GameStarted)
|
|
{
|
|
@if(!Model.onlineMultiplayer || !Model.CurrentPlayer.name.Equals(Model.player.name)) {
|
|
|
|
<p><span><b>Current player:</b> </span><span>@Model.CurrentPlayer.name</span></p>
|
|
}
|
|
else
|
|
{
|
|
<p class="text-success text-bold"><b>Your turn!</b></p>
|
|
}
|
|
<div class="dice-table">
|
|
@foreach (var dice in Model.Dices)
|
|
{
|
|
@if(!Model.onlineMultiplayer || Model.CurrentPlayer.name.Equals(Model.player.name)) {
|
|
<form action="@Url.Action("SelectDice", "Home", new { game = Model.gameID, id = dice.Key })" method="post">
|
|
@* <input type="hidden" name="id" value="@dice.Key" /> *@
|
|
<button type="submit">
|
|
@if (Model.selectedDices.Contains(dice.Key))
|
|
{
|
|
<div class="dice selected">
|
|
@dice.Value
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="dice">
|
|
@dice.Value
|
|
</div>
|
|
}
|
|
</button>
|
|
</form>
|
|
}
|
|
else {
|
|
<button type="submit">
|
|
@if (Model.selectedDices.Contains(dice.Key))
|
|
{
|
|
<div class="dice selected">
|
|
@dice.Value
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="dice">
|
|
@dice.Value
|
|
</div>
|
|
}
|
|
</button>
|
|
}
|
|
}
|
|
</div>
|
|
@if(!Model.onlineMultiplayer || Model.CurrentPlayer.name.Equals(Model.player.name))
|
|
{
|
|
@if(!Model.RerollsBlocked)
|
|
{
|
|
<form action="@Url.Action("RerollSelected", "Home", new {game = Model.gameID})" method="post">
|
|
<input type="submit" class="btn btn-primary mt-4 text-center" value="Reroll" />
|
|
</form>
|
|
}
|
|
else
|
|
{
|
|
<input type="button" value=Reroll class="btn btn-primary disabled mt-4 text-center" />
|
|
}
|
|
}
|
|
<div style="flex:1;"></div>
|
|
@if(Model.player.Owner) {
|
|
<form method="post" action="@Url.Action("StopGame", "Home", new { game = Model.gameID })">
|
|
<input type="submit" class="btn btn-danger mt-4 text-center" value="Stop Game" />
|
|
</form>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
@if (!Model.onlineMultiplayer) {
|
|
<h3>Add player</h3>
|
|
<form method="post" action="@Url.Action("AddPlayer", "Home", new { game = Model.gameID })" class="p-4">
|
|
<label>Name</label>
|
|
<input name="Name" class="form-control" type="text" required />
|
|
|
|
<input type="submit" class="btn btn-primary mt-4 text-center" value="Create" />
|
|
</form>
|
|
}
|
|
else {
|
|
<h3>Online multiplayer</h3>
|
|
<p>Join code: <span>@Model.joinCode</span></p>
|
|
<p>Joined as: <span>@Model.player.name</span></p>
|
|
}
|
|
@if (Model.onlineMultiplayer)
|
|
{
|
|
<div class="mb-3 p-3 bg-light rounded">
|
|
<div class="d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<h6 class="mb-1">🎮 Share this game</h6>
|
|
<small class="text-muted">Send this link to friends to join the game</small>
|
|
</div>
|
|
<div>
|
|
<button id="copyJoinLink" class="btn btn-sm btn-info" onclick="copyJoinLink('@Model.gameID')">
|
|
Copy Join Link
|
|
</button>
|
|
<span id="copySuccess" class="text-success ms-2" style="display: none;">✓ Copied!</span>
|
|
</div>
|
|
</div>
|
|
<div class="mt-2">
|
|
<input type="text" id="joinLinkInput" class="form-control form-control-sm"
|
|
value="@(Context.Request.Scheme)://@(Context.Request.Host)/game/join/@Model.joinCode"
|
|
readonly onclick="this.select()">
|
|
</div>
|
|
</div>
|
|
}
|
|
<div style="flex:1;"></div>
|
|
@if(Model.player.Owner) {
|
|
@if(Model.players.Count <= 0)
|
|
{
|
|
<input type="button" class="btn btn-success disabled" value="Start Game" />
|
|
}
|
|
else
|
|
{
|
|
<form action="@Url.Action("StartGame", "Home", new { game = Model.gameID })" method="post">
|
|
<input type="submit" class="btn btn-success mt-4 text-center" value="Start Game">
|
|
</form>
|
|
}
|
|
}
|
|
else if (Model.onlineMultiplayer) {
|
|
<form action="@Url.Action("LeaveGame", "Home", new {game = Model.gameID, name = Model.player.name})" method="post">
|
|
<input type="submit" class="btn btn-danger mt-4 text-center" value="Leave Game" />
|
|
</form>
|
|
}
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Rules Button -->
|
|
<div style="position: fixed; bottom: 20px; right: 20px;">
|
|
<button type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#rulesModal">
|
|
📋 Rules
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Rules Modal -->
|
|
<div class="modal fade" id="rulesModal" tabindex="-1" aria-labelledby="rulesModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="rulesModalLabel">🎲 Yatzy Rules</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<h5>🎯 Objective</h5>
|
|
<p>Score the most points by rolling five dice to make certain combinations.</p>
|
|
|
|
<h5>🚀 How to Setup the Game</h5>
|
|
<ol>
|
|
<li><strong>Add Players:</strong> Enter player names one by one using the "Add player" form</li>
|
|
<li><strong>Remove Players:</strong> Click on a player's name (before starting) to remove them</li>
|
|
<li><strong>Start Game:</strong> Click "Start Game" when you have at least one player added</li>
|
|
<li><strong>Game Begins:</strong> The first player will automatically be selected to start</li>
|
|
</ol>
|
|
<div class="alert alert-success">
|
|
<strong>🎮 Ready to Play:</strong> You can add 1-6 players for the best experience!
|
|
</div>
|
|
|
|
<h5>🎮 How to Play</h5>
|
|
<ol>
|
|
<li>Each player takes turns rolling 5 dice</li>
|
|
<li>After each roll, you can select which dice to keep and which to reroll</li>
|
|
<li>You get up to 3 rolls per turn (initial roll + 2 rerolls)</li>
|
|
<li>After your final roll, you must choose a scoring category</li>
|
|
<li>Each category can only be used once per game</li>
|
|
</ol>
|
|
|
|
<h5>📊 Scoring Categories</h5>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6><strong>Upper Section:</strong></h6>
|
|
<ul class="list-unstyled">
|
|
<li><strong>Ones:</strong> Sum of all 1s</li>
|
|
<li><strong>Twos:</strong> Sum of all 2s</li>
|
|
<li><strong>Threes:</strong> Sum of all 3s</li>
|
|
<li><strong>Fours:</strong> Sum of all 4s</li>
|
|
<li><strong>Fives:</strong> Sum of all 5s</li>
|
|
<li><strong>Sixes:</strong> Sum of all 6s</li>
|
|
<li><em><strong>Bonus:</strong> 50 points if upper section totals 63+</em></li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6><strong>Lower Section:</strong></h6>
|
|
<ul class="list-unstyled">
|
|
<li><strong>One Pair:</strong> Sum of highest pair</li>
|
|
<li><strong>Two Pair:</strong> Sum of both pairs</li>
|
|
<li><strong>Three of a Kind:</strong> Sum of three matching dice</li>
|
|
<li><strong>Four of a Kind:</strong> Sum of four matching dice</li>
|
|
<li><strong>Small Straight:</strong> 30 points (4 consecutive)</li>
|
|
<li><strong>Large Straight:</strong> 40 points (5 consecutive)</li>
|
|
<li><strong>Full House:</strong> Sum of all dice (3+2 of a kind)</li>
|
|
<li><strong>Chance:</strong> Sum of all dice (any combination)</li>
|
|
<li><strong>Yatzy:</strong> 50 points (all 5 dice the same)</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<h5>💡 Strategy Tips</h5>
|
|
<ul>
|
|
<li><strong>Upper Section Bonus:</strong> Focus early - it's worth 50 points!</li>
|
|
<li><strong>Chance Category:</strong> Use as backup when other categories don't work</li>
|
|
<li><strong>Yatzy Attempts:</strong> Save for when you have 3+ of the same number</li>
|
|
<li><strong>Bad Rolls:</strong> Consider which categories to sacrifice strategically</li>
|
|
</ul>
|
|
|
|
<div class="alert alert-info">
|
|
<strong>💭 Pro Tip:</strong> You need an average of 10.5 points per upper section category to get the bonus!
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function copyJoinLink(gameId) {
|
|
const joinLinkInput = document.getElementById('joinLinkInput');
|
|
const copyButton = document.getElementById('copyJoinLink');
|
|
const successMessage = document.getElementById('copySuccess');
|
|
|
|
// Select and copy the text
|
|
joinLinkInput.select();
|
|
joinLinkInput.setSelectionRange(0, 99999); // For mobile devices
|
|
|
|
try {
|
|
// Use the modern clipboard API if available
|
|
if (navigator.clipboard) {
|
|
navigator.clipboard.writeText(joinLinkInput.value).then(function() {
|
|
});
|
|
} else {
|
|
// Fallback for older browsers
|
|
fallbackCopy(joinLinkInput, copyButton, successMessage);
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to copy: ', err);
|
|
alert('Failed to copy link. Please copy it manually.');
|
|
}
|
|
}
|
|
</script> |