Skip to content

Commit

Permalink
Removed turns and handcards, added markerMap recovery
Browse files Browse the repository at this point in the history
  • Loading branch information
Frederick Behringer committed Feb 26, 2024
1 parent 22541d8 commit cd870dc
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 156 deletions.
110 changes: 22 additions & 88 deletions backend/src/models/MauMau.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export class MauMau {
history: string[];
startTime: Date|undefined;
endTime: Date|undefined;
turn: number;


constructor (room: Room) {
Expand All @@ -25,7 +24,6 @@ export class MauMau {
this.playedCards = [ ];
this.drawPile = [ ]; // "Nachziehstapel"
this.history = [ ];
this.turn = 0;
}

start() {
Expand All @@ -40,31 +38,17 @@ export class MauMau {
this.room.state = 'inGame';
this.drawPile = [...this.deck]; // copy array
this.shuffleArray(this.drawPile);
// give users some handcards
for (let i = 0; i < 7; i++) {
for (let user of this.room.users) {
user.handcards.unshift(this.drawPile.pop()!);
}
}
// propagate handcards?
for (let user of this.room.users) {
user.ws.send(JSON.stringify({
action: 'dealCards',
data: {
handcards: user.handcards
}
}));
let historyEntry = [ 'dealCards', user.id, user.handcards.join(',')].join(':');
this.history.unshift(historyEntry);
}
this.room.sendMessageToUsers('dealCards', { });
let historyEntry = 'dealCards';
this.history.unshift(historyEntry);
}

end() {
this.endTime = new Date();

const leaderboard: string[] = [ ];

this.notifyUsers('end', {
this.room.sendMessageToUsers('end', {
startTime: this.startTime,
endTime: this.endTime,
leaderboard: leaderboard
Expand All @@ -80,82 +64,40 @@ export class MauMau {
}

drawCard(user: User, message: WsMessage) {
// check if it is the users turn
if (this.room.users[this.turn] !== user) {
user.ws.send(JSON.stringify({ error: 'It is not your turn!' }));
return;
}
// check if we need to shuffle deck
if (this.drawPile.length <= 0) {
this.shuffleDrawPile();
}
const card = this.drawPile.pop()!;
user.handcards.unshift(card);
user.ws.send(JSON.stringify({
action: 'drawCard',
data: {
card: card,
markerId: message.data.markerId,
handcards: user.handcards,
nextActions: [ 'endTurn', 'playCard' ]
const markerId = message.data.markerId;
let card = user.markerMap.get(markerId)
// check if this card is already known
if (!card) {
// check if we need to shuffle deck
if (this.drawPile.length <= 0) {
this.shuffleDrawPile();
}
}));
card = this.drawPile.pop()!;
this.room.addDataToMarker(markerId, card, user);
}
this.room.sendMessageToUsers('drawCard', { card: card, markerId: markerId });
// it might happen that we draw a card again, since we can shuffle
this.history.unshift(`+${user.id}:${card}`);
// do not hand to next user now, wait if he can play now
}

playCard(user: User, message: WsMessage) {
// check if it is the users turn
if (this.room.users[this.turn] !== user) {
user.ws.send(JSON.stringify({ error: 'It is not your turn!' }));
return;
}
// check if user has this card in his hand
const cardIndex = user.handcards.findIndex(card => card === message.data.card);
if (cardIndex < 0) {
user.ws.send(JSON.stringify({ error: 'The Server did not know you own this card. Please play another one' }));
return;
}
// play card
const playedCard = user.handcards.splice(cardIndex, 1)[0];
this.playedCards.unshift(playedCard);
this.history.unshift(`-${user.id}:${playedCard}`)
// check if it was the last card
const wasLast = user.handcards.length <= 0;
this.notifyUsers('playCard', { card: playedCard, wasLast: wasLast });
if (wasLast) {
// we do not check here if he needs to pull another card he can do so if he wants to :)
this.history.unshift(`${user.id}:finished`)
}
// hand to next user
this.endTurn(user, message);
}

endTurn(user: User, _: WsMessage) {
// check if it is the users turn
if (this.room.users[this.turn] !== user) {
user.ws.send(JSON.stringify({ error: 'It is not your turn!' }));
return;
}
// just hand to next user
this.turn = (this.turn) + 1 % this.room.users.length;
this.room.users[this.turn].ws.send(JSON.stringify({
action: 'yourTurn',
data: {
nextActions: [ 'drawCard', 'playCard' ]
}
}));
let card = message.data.card;
this.playedCards.push(card);
this.room.sendMessageToUsers('playedCard', { card: card });
this.history.unshift(`-${user.id}:${card}`);
}

shuffleDrawPile() {
this.drawPile = this.drawPile.concat(this.playedCards);
this.drawPile = this.shuffleArray(this.drawPile);
this.playedCards = [ ];
// notify users
this.notifyUsers('shuffled', { })
this.room.sendMessageToUsers('shuffled', { })
this.history.unshift('shuffle');
}


shuffleArray(array: any[]) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
Expand All @@ -165,12 +107,4 @@ export class MauMau {
}
return array;
}
notifyUsers(action: string, data: any) {
for (let user of this.room.users) {
user.ws.send(JSON.stringify({
action: action,
data: data
}));
}
}
}
97 changes: 45 additions & 52 deletions backend/src/models/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,13 @@ export class Room {
console.log(user.id, connectionAction, this.id);

// notify users
this.users
.filter(u => u.id != user.id)
.forEach(u => {
u.ws.send(JSON.stringify({
action: connectionAction,
data: {
user: {
id: user.id,
name: user.name
}
}
}));
});
this.sendMessageToUsers(connectionAction, { id: user.id, name: user.name }, this.users.filter(u => u.id != user.id));

// listen for actions of normal players
const availableActions = [
'drawCard',
'playCard',
'endTurn'
// 'endTurn'
];
const availableRoomActions = [
'getRoomInfo',
Expand Down Expand Up @@ -109,50 +97,31 @@ export class Room {
}

leave(user: User) {
console.log(user.id, 'left', this.id);
this.users
.filter(u => u != user)
.forEach(u => {
u.ws.send(JSON.stringify({
action: 'disconnected',
data: {
id: user.id,
name: user.name
}
}));
});
console.log(user.id, 'disconnected', this.id);
this.sendMessageToUsers('disconnected', { id: user.id, name: user.name }, this.users.filter(u => u != user));
user.timeout = setTimeout(() => {
console.log('triggered timeout')
this.users = this.users.filter(u => u != user); // remove this user
// notify remaining
this.users.forEach(u => {
u.ws.send(JSON.stringify({
action: 'left',
data: {
id: user.id,
name: user.name
}
}));
});
this.sendMessageToUsers('left', { id: user.id, name: user.name });
// return this.users.length;
}, 5 * 60 * 1000);
}

getRoomInfo(user: User) {
user.ws.send(JSON.stringify({
action: 'gotRoomInfo',
data: {
you: { name: user.name, isOwner: user.isOwner, id: user.id, handcards: user.handcards },
console.log('getting room infos')
this.sendMessageToUsers('gotRoomInfo', {
you: { name: user.name, isOwner: user.isOwner, id: user.id },
room: {
isLocal: false,
isLocal: this.isLocal,
selectedGame: this.selectedGame,
state: this.state,
users: this.getUserInformations(),
id: this.id,
},
game: { ...this.game, room: undefined }
}
}))
game: { ...this.game, room: undefined },
markerMap: Object.fromEntries(user.markerMap.entries()) // convert to plain object
}, [user]);
}

selectGame() {
Expand All @@ -165,18 +134,42 @@ export class Room {
return;
}
this.isLocal = message.data.isLocal || false;
this.users
.forEach(u => {
u.ws.send(JSON.stringify({
action: 'settingsChanged',
data: {
isLocal: this.isLocal
}
}));
});
this.sendMessageToUsers('settingsChanged', { isLocal: this.isLocal })
}

addLocalDataToMarker(user: User, message: WsMessage) {
if (this.isLocal) {
user.ws.send(JSON.stringify({ error: 'This game is a local game!' }));
return;
}
if (message.data.markerId) {
user.ws.send(JSON.stringify({ error: 'markerId is missing!' }));
return;
}
this.addDataToMarker(message.data.markerId, message.data.card, user);
this.sendMessageToUsers('addedLocalDataMarker', message.data, [user]);
}



getUserInformations(): { name: string, isOwner: boolean, id: string, disconnected: boolean }[] {
return this.users.map(user => { return { name: user.name, isOwner: user.isOwner, id: user.id, disconnected: user.timeout !== undefined }})
}

addDataToMarker(markerId: string, data: any, user: User) {
if (this.isLocal) {
for (let user of this.users) {
user.markerMap.set(markerId, data);
}
} else {
user.markerMap.set(markerId, data);
}
}

sendMessageToUsers(action: string, data: any, users: User[] = this.users) {
users = users.filter(user => !user.timeout); // only send to connected users
for (let user of users) {
user.ws.send(JSON.stringify({ action, data }));
}
}
}
4 changes: 2 additions & 2 deletions backend/src/models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ export class User {
ws: WebSocket;
id: string;
name: string;
handcards: string[];
isOwner: boolean;
timeout: NodeJS.Timeout|undefined;
markerMap: Map<string, any>;

constructor(ws: WebSocket, id: string|undefined, name: string|undefined) {
this.ws = ws;
Expand All @@ -21,7 +21,7 @@ export class User {
} else {
this.name = 'name_' + (Math.random() + 1).toString(36).substring(7);
}
this.handcards = [];
this.isOwner = false;
this.markerMap = new Map();
}
}
30 changes: 21 additions & 9 deletions frontend-vue/src/components/ar-component/CardService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ export class CardService {
this.markerMap = new Map<string, Card>();
this.cardCallbacks = new Map<string, Function>();
// conService.onConnection(() => this.numberOfCards = conService.game.value!.deck.length);
conService.onConnection(() => (this.numberOfCards = 40)); // Todo: Marker Anzahl?!
conService.onConnection((data) => {
this.numberOfCards = 40; // Todo: Marker Anzahl?!
if (data.markerMap) {
this.markerMap = new Map(Object.entries<string>(data.markerMap).map(([key, value]): [string, Card] => [key, { name: value, url: this.getCardUrl(value) }]));
console.log('recovered markerMap')
}
});
conService.onCardDrawed((markerId, cardName) => this.registerMarker(markerId, cardName));
}

Expand Down Expand Up @@ -55,15 +61,21 @@ export class CardService {
*/
public registerMarker(markerId: string, cardName: string) {
const card = { name: cardName, url: this.getCardUrl(cardName) };
if (this.markerMap.get(markerId)) {
console.warn('Marker was already known, but was registered twice!');
// if it is a local game, update markerMap and check for waiting callbacks
if (this.conSerivce.room.value?.isLocal) {
if (this.markerMap.get(markerId)) {
console.warn('Marker was already known, but was registered twice!');
}
this.markerMap.set(markerId, card);
const callback = this.cardCallbacks.get(markerId);
// if there was no callback someone else drew this card locally
if (callback) {
callback(card);
}
} else {
// ToDo: What are we doing with not local games?
console.warn('This is not a local Game!');
}
this.markerMap.set(markerId, card);
const callback = this.cardCallbacks.get(markerId);
if (callback) {
callback(card);
}
// if there was no callback someone else drew this card locally
}

public reloadMarkerMap() {}
Expand Down
Loading

0 comments on commit cd870dc

Please sign in to comment.