...
 
Commits (8)
......@@ -53,6 +53,7 @@ These are known problems that we lacked time to address/fix.
If someone does not make any action during his time (30s), the server for some reason is not able to send the updates anymore via the socket.
Therefore the front-end calls /api/game/ every second to keep track of the state of the game in parallel of the websocket. The socket will only reconnect (as a new socket) on page reload.
Maybe SocketIO does not manage to use websockets and falls back to HTTP long-polling, and it times out.
As there is no server-side file/database storage, on a server restart or crash all the games are lost. We choosed to do so for quicker development, but it is obviously not production ready.
......
var server;
var gameId = window.location.href.substring((window.location.origin + window.location.pathname).length + 8);
var players = [];
function catchUp(tableState) {
updateHistory(tableState)
setBoard(tableState.boardCards);
setHoleCards(tableState.holeCards, tableState.players);
setPlayers(tableState.players);
......@@ -13,6 +15,32 @@ function catchUp(tableState) {
setBB(tableState["BB"]);
}
function updateHistory(tableState) {
var state = tableState;
var txt = '';
console.log(players);
if (players.length > 0) {
console.log("test")
for (var i = 0; i < state['players'].length; i++) {
if (players[i]['state'] !== state['players'][i]['state']) {
if (state['players'][i]['state'].length > 0) {
txt = txt + 'Game event ==> ' + state['players'][i]['name'] + ' : ' + state['players'][i]['state'] + ', <br>'
} else {
txt = txt + 'Game event ==> ' + state['players'][i]['name'] + ' : IN HAND, <br>'
}
}
}
for (var i = 0; i < state['players'].length; i++) {
if (players[i]['won'] !== state['players'][i]['won'] && state['players'][i]['won']) {
txt = txt + 'Hand ' + state['handNbr'] + ' ended ==> ' + state['players'][i]['name'] + ' : ' + 'WON <br>'
}
}
var history = document.getElementById('history');
history.innerHTML += txt;
}
players = state.players;
}
function setActionButtons(tableState) {
var state = $('#state');
if (tableState["handNbr"] > 0) {
......@@ -203,7 +231,7 @@ function setCurrentPot(amount) {
function checkClicked() {
var history = document.getElementById('history');
history.innerHTML += 'You clicked CHECK <br>';
history.innerHTML += 'Your action ==> CHECK <br>';
var url = '/api/game/' + gameId + "/action";
console.log(url);
$.ajax({
......@@ -221,7 +249,7 @@ function checkClicked() {
function foldClicked() {
var history = document.getElementById('history');
history.innerHTML += 'You clicked FLOD <br>';
history.innerHTML += 'Your action ==> FLOD <br>';
var url = '/api/game/' + gameId + "/action";
console.log(url);
$.ajax({
......@@ -239,7 +267,7 @@ function foldClicked() {
function callClicked() {
var history = document.getElementById('history');
history.innerHTML += 'You clicked CALL <br>';
history.innerHTML += 'Your action ==> CALL <br>';
var url = '/api/game/' + gameId + "/action";
console.log(url);
$.ajax({
......@@ -257,7 +285,7 @@ function callClicked() {
function raiseClicked() {
var history = document.getElementById('history');
history.innerHTML += 'You clicked RAISE <br>';
history.innerHTML += 'Your action ==> RAISE <br>';
var url = '/api/game/' + gameId + "/action";
console.log(url);
var amount = document.forms[0].amount.value;
......
......@@ -8,7 +8,7 @@
# instatiation, which may fail if the given card list is neither empty nor
# contains exactly 5 cards.
#
# Tests :
# Tests :
# h = hand.Hand([Card(1,3), Card(1, 6), Card(1, 6), Card(1, 8), Card(2, 8)])
# h2 = hand.Hand([Card(1,10), Card(1, 6), Card(1, 6), Card(1, 8), Card(2, 8)])
# h.getHandName()
......@@ -37,8 +37,7 @@ class Hand:
self.__cards = cards[:]
self.__handName = HandName.HIGH_CARD
if len(self.__cards) == 5:
self.__cards.sort()
self.__cards.reverse()
self.__cards.sort(reverse=True)
self.__readHand()
def getHandName(self):
......@@ -153,7 +152,7 @@ class Hand:
else:
isFlush = True
for i in range(4):
if self.__cards[0].color != self.__cards[i + 1].color:
if self.__cards[0].suit != self.__cards[i + 1].suit:
isFlush = False
if isFlush:
self.__handName = HandName.FLUSH
......
......@@ -55,7 +55,7 @@ class Player:
return self.__playerState == PlayerState.ALL_IN
@property
def getChipsOnTable(self):
def chipsOnTable(self):
return self.__chipsOnTable
@property
......@@ -163,11 +163,6 @@ class Player:
self.__hand = newHand
return self.__hand
def endTurn(self):
ans = self.__chipsOnTable
self.__chipsOnTable = 0
return ans
def receiveCards(self, card1, card2):
self.__cards = [card1, card2]
......@@ -221,10 +216,6 @@ class Player:
self.__playerState = PlayerState.FOLDED
return True
def yieldAction(self):
# Timeout, shouldn't be needed (just check/fold called from Table)
self.__hasHadAction = True
def state(self):
# returns player state (all in, playing, folded)
if self.__playerState == PlayerState.FOLDED:
......
......@@ -18,7 +18,7 @@
from enum import Enum
class Color(Enum):
class Suit(Enum):
HEARTS = 1
SPADES = 2
DIAMONDS = 3
......@@ -26,22 +26,22 @@ class Color(Enum):
class Card:
def __init__(self, color, value):
def __init__(self, Suit, value):
## The card must be instanciated with its suit and value, which won't
# change.
assert value >= 2 and value <= 14
self.__color = color
self.__suit = Suit
self.__value = value
self.__json = {}
if self.__color == Color.HEARTS : self.__json["Suit"] = "Hearts"
elif self.__color == Color.SPADES : self.__json["Suit"] = "Spades"
elif self.__color == Color.DIAMONDS : self.__json["Suit"] = "Diamonds"
elif self.__color == Color.CLUBS : self.__json["Suit"] = "Clubs"
if self.__suit == Suit.HEARTS : self.__json["Suit"] = "Hearts"
elif self.__suit == Suit.SPADES : self.__json["Suit"] = "Spades"
elif self.__suit == Suit.DIAMONDS : self.__json["Suit"] = "Diamonds"
elif self.__suit == Suit.CLUBS : self.__json["Suit"] = "Clubs"
self.__json["Rank"] = self.__value
@property
def color(self):
return self.__color
def suit(self):
return self.__suit
@property
def value(self):
......@@ -50,10 +50,10 @@ class Card:
@property
def json(self):
return self.__json
def cardStr(self):
# Debug print
return '({0}:{1})'.format(self.__value, self.__color)
return '({0}:{1})'.format(self.__value, self.__suit)
def valueStr(self):
# Returns the value of a card as astring, for json export.
......@@ -75,4 +75,4 @@ class Card:
def sameAs(self, card):
# Check if both cards are exactly the same (suit and value)
return self.__color == card.color and self.__value == card.value
return self.__suit == card.suit and self.__value == card.value
......@@ -5,7 +5,7 @@
# one.
# The size of the deck is decreased by one for each drawn card, until none are
# left (drawCard will then fail).
#
#
from table import card
import random
......@@ -25,7 +25,7 @@ class Deck:
def reset(self):
self.__cards = []
for c in card.Color:
for c in card.Suit:
for i in range(2, 15):
self.__cards.append(card.Card(c, i))
random.shuffle(self.__cards)
......@@ -135,7 +135,7 @@ class Table(object):
self.__timer.start()
for p in self.__players:
if p.isInHand:
print("Player {} : {} ({} chips)".format(p.name, p.getChipsOnTable, p.remainingChips))
print("Player {} : {} ({} chips)".format(p.name, p.chipsOnTable, p.remainingChips))
else:
print("Player {} : out ({} chips)".format(p.name, p.remainingChips))
self.__bCastCB()
......@@ -232,12 +232,12 @@ class Table(object):
pickUpDone = True
for p in self.__players:
if p.isInHand:
if p.isAllIn and p.getChipsOnTable and (not minAllInValue or p.getChipsOnTable < minAllInValue):
minAllInValue = p.getChipsOnTable
if p.isAllIn and p.chipsOnTable and (not minAllInValue or p.chipsOnTable < minAllInValue):
minAllInValue = p.chipsOnTable
pickUpDone = False
if not pickUpDone:
for p in self.__players:
if p.getChipsOnTable <= minAllInValue:
if p.chipsOnTable <= minAllInValue:
if p.isAllIn:
p.potId = len(self.__pots) - 1
self.__pots[-1] += p.yieldBet()
......@@ -331,7 +331,7 @@ class Table(object):
if nbrInHand <= 1:
return True
for p in self.__players:
if p.isPlaying and (not p.hasHadAction or p.getChipsOnTable != self.__currentBet):
if p.isPlaying and (not p.hasHadAction or p.chipsOnTable != self.__currentBet):
return False
return True
......@@ -377,8 +377,8 @@ class Table(object):
return True
def __check(self, p):
if p.getChipsOnTable != self.__currentBet:
print("Player {} cant check, needs to call ({}/{})".format(p.name, p.getChipsOnTable, self.__currentBet))
if p.chipsOnTable != self.__currentBet:
print("Player {} cant check, needs to call ({}/{})".format(p.name, p.chipsOnTable, self.__currentBet))
return False
if not p.check():
print("Player {} cant check, check failed (unexpected).".format(p.name))
......@@ -395,8 +395,8 @@ class Table(object):
return True
def __bet(self, p, amount):
if amount + p.getChipsOnTable < self.__currentBet + self.__minRaise:
print("Player {} cant bet, not adding enough money (would be {}/{})".format(p.name, amount + p.getChipsOnTable, self.__currentBet + self.__minRaise))
if amount + p.chipsOnTable < self.__currentBet + self.__minRaise:
print("Player {} cant bet, not adding enough money (would be {}/{})".format(p.name, amount + p.chipsOnTable, self.__currentBet + self.__minRaise))
return False
if amount > p.remainingChips:
print("Player {} cant bet, not enough money ({}/{})".format(p.name, amount, p.remainingChips))
......@@ -406,8 +406,8 @@ class Table(object):
return False # Betting could not happen for some reason
if not self.__currentBet:
self.__minRaise = amount
if p.getChipsOnTable > self.__currentBet:
self.__currentBet = p.getChipsOnTable
if p.chipsOnTable > self.__currentBet:
self.__currentBet = p.chipsOnTable
print("Player {} added {}, current bet to {}, minraise at {}.".format(p.name, amount, self.__currentBet, self.__minRaise))
return True
......@@ -430,7 +430,7 @@ class Table(object):
"chips": player.remainingChips,
"isActive": player.isPlaying,
"won": player.won,
"chipsOnTable": player.getChipsOnTable,
"chipsOnTable": player.chipsOnTable,
"state": player.state(),
} for player in self.__players],
"holeCards": self.__getHoleCards(userId),
......@@ -475,7 +475,7 @@ class Table(object):
if userIndex == -1:
return []
p = self.__players[userIndex]
return [self.__currentBet + self.__minRaise - p.getChipsOnTable, p.remainingChips]
return [self.__currentBet + self.__minRaise - p.chipsOnTable, p.remainingChips]
def __availableActions(self, userId):
userIndex = self.getPlayerIndex(userId)
......@@ -487,7 +487,7 @@ class Table(object):
if not p.isPlaying:
return []
rslt = ["fold"]
if self.__currentBet == p.getChipsOnTable:
if self.__currentBet == p.chipsOnTable:
rslt.append("check")
else:
rslt.append("call")
......@@ -499,7 +499,7 @@ class Table(object):
if userIndex == -1:
return 0
p = self.__players[userIndex]
return self.__currentBet - p.getChipsOnTable
return self.__currentBet - p.chipsOnTable
def __defaultActionCallback(self):
activePlayerId = self.__players[self.__activePlayer].uniqueId
......@@ -520,16 +520,3 @@ class Table(object):
val += 1
self.__blind = val
self.__smallBlind = val / 2
# """
# t = Table(3, 0)
# p0 = Player("p0")
# p1 = Player("p1")
# p2 = Player("p2")
# t.addPlayer(p0)
# t.addPlayer(p1)
# t.addPlayer(p2)
#
# t.startHand()
# """