computer mouse problems
This commit is contained in:
@@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'
|
||||
import Gameboard from './components/Gameboard/Gameboard'
|
||||
import GameConstructor from './components/GameConstructor';
|
||||
import './App.css'
|
||||
import ResumeGame from './components/ResumeGame';
|
||||
|
||||
function App() {
|
||||
const [state, setState] = useState(initialState);
|
||||
@@ -18,9 +19,11 @@ function App() {
|
||||
<h1>SPLENDOR</h1>
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
{/* @ts-ignore */}a
|
||||
{/* @ts-ignore */}
|
||||
<Route path="/" element={<GameConstructor state={state} setState={setState} />} />
|
||||
{/* @ts-ignore */}
|
||||
<Route path="/resume-game" element={<ResumeGame state={state} setState={setState} /> } />
|
||||
{/* @ts-ignore */}
|
||||
<Route path="/game" element={<Gameboard state={state} setState={setState} />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { useNavigate } from "react-router-dom"
|
||||
import { Link, useNavigate } from "react-router-dom"
|
||||
import { CardData, NobleData, PlayerData } from "../util/types";
|
||||
import { StateProps } from '../util/propTypes';
|
||||
|
||||
@@ -103,7 +103,9 @@ export default function GameConstructor({ state, setState }: StateProps) {
|
||||
|
||||
return (
|
||||
<div className="game-constructor App">
|
||||
<h1>Configure a new game:</h1>
|
||||
<strong>Start a new game</strong>
|
||||
<h2>OR</h2>
|
||||
<strong>Enter your previous game data <Link to={'/resume-game'}>here</Link> to pick up where you left off.</strong>
|
||||
|
||||
<div>
|
||||
<label htmlFor="P1-NAME">Player 1 Name:</label>
|
||||
@@ -162,7 +164,7 @@ export default function GameConstructor({ state, setState }: StateProps) {
|
||||
</input>
|
||||
<input
|
||||
type="radio"
|
||||
id="P1-START"
|
||||
id="P4-START"
|
||||
onChange={() => handleRadio(4)}
|
||||
checked={starter === 3 && input.playerFour.name.length > 0}>
|
||||
</input>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { AppState, ResourceCost } from '../../util/types';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { getChipsActions } from '../Player/ActionMethods';
|
||||
import { StateProps } from '../../util/propTypes';
|
||||
const { validateChips } = getChipsActions;
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// components
|
||||
import Nobles from './Nobles';
|
||||
@@ -12,6 +12,7 @@ import AvailableChips from '../Resources/AvailableChips';
|
||||
import AllPlayers from '../Player/AllPlayers';
|
||||
import CardRow from '../Card/CardRow';
|
||||
import SelectionView from '../Resources/SelectionView';
|
||||
const { validateChips } = getChipsActions;
|
||||
|
||||
export default function Gameboard({ state, setState }: StateProps) {
|
||||
const [view, setView] = useState(<p>Loading...</p>);
|
||||
@@ -50,17 +51,13 @@ export default function Gameboard({ state, setState }: StateProps) {
|
||||
setCardRows(state);
|
||||
}, [state])
|
||||
|
||||
useEffect(() => {
|
||||
console.log(state)
|
||||
}, [state])
|
||||
|
||||
// displays state of board if data is populated
|
||||
// displays state of board if data is populated, otherwise points to game constructor
|
||||
useEffect(() => {
|
||||
if (!state.players.length) {
|
||||
setView(
|
||||
<div className="error-page">
|
||||
<strong>Sorry! It appears we've lost track of your game data.</strong>
|
||||
<p>Please head back to the <a href="/">home page</a> to start a fresh game.</p>
|
||||
<p>Please head back to the <Link to="/">home page</Link> to start a fresh game.</p>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
|
||||
144
src/components/Gameboard/Nobles.test.ts
Normal file
144
src/components/Gameboard/Nobles.test.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { describe, test } from "vitest";
|
||||
import { CardData, NobleData, PlayerData } from "../../util/types";
|
||||
|
||||
export const firstNoble: NobleData = {
|
||||
points: 3,
|
||||
resourceCost: {
|
||||
ruby: 0,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 3
|
||||
}
|
||||
}
|
||||
|
||||
export const secondNoble: NobleData = {
|
||||
points: 3,
|
||||
resourceCost: {
|
||||
ruby: 3,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 0
|
||||
}
|
||||
}
|
||||
|
||||
const exampleOneCards: CardData[] = [
|
||||
{
|
||||
gemValue: "diamond",
|
||||
tier: 3,
|
||||
points: 0,
|
||||
resourceCost: {
|
||||
ruby: 0,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 3
|
||||
}
|
||||
},
|
||||
{
|
||||
gemValue: "diamond",
|
||||
tier: 3,
|
||||
points: 1,
|
||||
resourceCost: {
|
||||
ruby: 0,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 4
|
||||
}
|
||||
},
|
||||
{
|
||||
gemValue: "diamond",
|
||||
tier: 2,
|
||||
points: 2,
|
||||
resourceCost: {
|
||||
ruby: 0,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 5
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export const legalPlayer: PlayerData = {
|
||||
name: "First example",
|
||||
id: 1,
|
||||
starter: true,
|
||||
turnActive: true,
|
||||
points: 5,
|
||||
nobles: [],
|
||||
cards: exampleOneCards,
|
||||
reservedCards: [],
|
||||
inventory: {
|
||||
ruby: 0,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 0
|
||||
}
|
||||
}
|
||||
|
||||
const exampleTwoCards: CardData[] = [
|
||||
{
|
||||
gemValue: "ruby",
|
||||
tier: 2,
|
||||
points: 2,
|
||||
resourceCost: {
|
||||
ruby: 5,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
gemValue: "ruby",
|
||||
tier: 3,
|
||||
points: 1,
|
||||
resourceCost: {
|
||||
ruby: 4,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
gemValue: "ruby",
|
||||
tier: 3,
|
||||
points: 0,
|
||||
resourceCost: {
|
||||
ruby: 3,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
onyx: 0,
|
||||
diamond: 0
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
export const doesNotIncludeInventory: PlayerData = {
|
||||
name: "second example",
|
||||
id: 2,
|
||||
starter: true,
|
||||
turnActive: true,
|
||||
points: 5,
|
||||
nobles: [],
|
||||
cards: exampleTwoCards,
|
||||
reservedCards: [],
|
||||
inventory: {
|
||||
ruby: 3,
|
||||
sapphire: 3,
|
||||
emerald: 3,
|
||||
onyx: 3,
|
||||
diamond: 3,
|
||||
}
|
||||
}
|
||||
|
||||
describe('canPickUpNoble', () => {
|
||||
test('detects noble eligibility by card count', () => {
|
||||
|
||||
})
|
||||
})
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useEffect } from "react";
|
||||
import { v4 } from "uuid";
|
||||
import { NobleData, ResourceCost } from "../../util/types";
|
||||
import { NobleData, PlayerData, ResourceCost } from "../../util/types";
|
||||
import { StateProps } from "../../util/propTypes";
|
||||
import "./Nobles.css"
|
||||
import getTotalBuyingPower from "../../util/getTotalBuyingPower";
|
||||
import { useCurrentPlayer } from "../../util/useCurrentPlayer";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function Nobles({ state, setState }: StateProps) {
|
||||
const removeNoble = (noble: NobleData) => {
|
||||
@@ -18,6 +20,38 @@ export default function Nobles({ state, setState }: StateProps) {
|
||||
})
|
||||
}
|
||||
|
||||
const canPickUpNoble = (player: PlayerData, noble: NobleData): boolean => {
|
||||
const nobleCost = noble.resourceCost;
|
||||
|
||||
const totalBuyingPower = getTotalBuyingPower(player);
|
||||
const playerInventory = player.inventory;
|
||||
|
||||
|
||||
for (let key of Object.keys(totalBuyingPower)) {
|
||||
const typedKey = key as keyof ResourceCost;
|
||||
let coinValue = playerInventory[typedKey] || 0;
|
||||
|
||||
if (!noble.resourceCost[typedKey]) continue;
|
||||
// @ts-ignore
|
||||
if ((totalBuyingPower[typedKey] - coinValue) >= noble.resourceCost[typedKey]) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const currentPlayer = useCurrentPlayer(state);
|
||||
if (!currentPlayer) return;
|
||||
|
||||
for (let each of state.gameboard.nobles) {
|
||||
console.log(`${currentPlayer.name} can pick up noble ${state.gameboard.nobles.indexOf(each) + 1}? ${canPickUpNoble(currentPlayer, each) ? "yes" : "no"}`)
|
||||
}
|
||||
}, [state])
|
||||
|
||||
return (
|
||||
<div className="nobles-panel">
|
||||
<strong>NOBLES</strong>
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
import cardTierToKey from "../../../util/cardTierToKey";
|
||||
import { initialActions } from "../../../util/stateSetters";
|
||||
import { turnOrderUtil } from "../../../util/turnOrderUtil";
|
||||
import { AppState, CardData, PlayerData, ResourceCost, setStateType } from "../../../util/types";
|
||||
import { useCurrentPlayer } from "../../../util/useCurrentPlayer";
|
||||
import { getTotalBuyingPower } from "./buyCardActions";
|
||||
|
||||
export const buyCard = (card: CardData, state: AppState, setState: setStateType) => {
|
||||
/**
|
||||
* functionality: adds target card's data to current player's collection of cards,
|
||||
* removes the card from the active state of the gameboard, replaces it with
|
||||
* a new card in the correct tier, and runs turn order utility
|
||||
*
|
||||
* @param card -> the target card, @param state -> current app state
|
||||
*/
|
||||
|
||||
let currentPlayer = useCurrentPlayer(state);
|
||||
|
||||
setState((prev: AppState) => {
|
||||
if (!currentPlayer) return prev;
|
||||
|
||||
const { newPlayers, roundIncrement } = turnOrderUtil(prev, currentPlayer);
|
||||
let newPlayerInventory = currentPlayer.inventory;
|
||||
let newResourcePool = prev.gameboard.tradingResources;
|
||||
const totalBuyingPower = getTotalBuyingPower(state);
|
||||
|
||||
// iterate through cost values of card to purchase
|
||||
for (let [gem, cost] of Object.entries(card.resourceCost)) {
|
||||
if (cost < 1) continue;
|
||||
let inventoryValue = newPlayerInventory[gem as keyof ResourceCost];
|
||||
let globalResource = newResourcePool[gem as keyof ResourceCost];
|
||||
|
||||
if (!inventoryValue || !globalResource) {
|
||||
continue;
|
||||
} else {
|
||||
let i = cost;
|
||||
|
||||
// prevents duplication of resources when purchasing a card using permanent resources from cards
|
||||
if (totalBuyingPower[gem as keyof ResourceCost] !== inventoryValue) {
|
||||
console.log('caught');
|
||||
}
|
||||
|
||||
while (i > 0) {
|
||||
inventoryValue -= 1;
|
||||
globalResource += 1;
|
||||
i--;
|
||||
}
|
||||
|
||||
newResourcePool[gem as keyof ResourceCost] = globalResource;
|
||||
newPlayerInventory[gem as keyof ResourceCost] = inventoryValue;
|
||||
}
|
||||
}
|
||||
|
||||
let updatedPlayer: PlayerData = {
|
||||
...currentPlayer,
|
||||
cards: [...currentPlayer.cards, card],
|
||||
inventory: newPlayerInventory
|
||||
}
|
||||
|
||||
let newScore = 0;
|
||||
for (let each of updatedPlayer.cards) {
|
||||
newScore += each.points || 0;
|
||||
}
|
||||
|
||||
updatedPlayer.points = newScore;
|
||||
const idx = newPlayers.findIndex((one: PlayerData) => one.id === currentPlayer?.id);
|
||||
newPlayers[idx] = updatedPlayer;
|
||||
let updatedRows = prev.gameboard.cardRows;
|
||||
|
||||
if (card.tier) {
|
||||
const tierKey = cardTierToKey(card.tier);
|
||||
updatedRows[tierKey] = prev.gameboard.cardRows[tierKey].filter((found: CardData) => found.resourceCost !== card.resourceCost);
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
round: (roundIncrement ? prev.round + 1 : prev.round),
|
||||
players: newPlayers,
|
||||
gameboard: {
|
||||
...prev.gameboard,
|
||||
tradingResources: prev.gameboard.tradingResources,
|
||||
cardRows: updatedRows
|
||||
},
|
||||
actions: initialActions
|
||||
}
|
||||
})
|
||||
}
|
||||
12
src/components/ResumeGame.tsx
Normal file
12
src/components/ResumeGame.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Link } from "react-router-dom";
|
||||
import { StateProps } from "../util/propTypes";
|
||||
|
||||
export default function ResumeGame({ state, setState }: StateProps) {
|
||||
return (
|
||||
<div className="resume-game App">
|
||||
<h2>Congrats! You've found an in-progress feature.</h2>
|
||||
<p>Check back in here later to enter a save game token to pick up a game from where you left off.</p>
|
||||
<p>In the meantime, click <Link to="/">here</Link> to head back home.</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user