Skip to content

Instantly share code, notes, and snippets.

@RyanHendricks
Created January 3, 2019 18:33
Show Gist options
  • Save RyanHendricks/9dbc2fb648de284f723010e1c8b5b998 to your computer and use it in GitHub Desktop.
Save RyanHendricks/9dbc2fb648de284f723010e1c8b5b998 to your computer and use it in GitHub Desktop.
Union Poker
pragma solidity ^0.5.0;
contract UnionPoker {
struct UnionPokerGame {
bool started; /// has the game started
bool ended; /// has the game ended
uint256 totalBuyIns; /// total of all buy ins
uint256 totalCashOuts; /// total of all cash outs
uint256 totalBalance; /// total amount in play (buyins minus cashouts)
mapping(address => uint256) playerTotalBalance; /// balance of each player
mapping(address => uint256) playerBuyIns; /// buy in total for each player
mapping(address => uint256) playerCashOuts; /// cash out total for each player
}
struct UnionPokerPlayer {
uint256 playerTotalBalance; /// balance of player if player is in the positive
uint256 playerTotalOwed; /// negative balance of player if in the negative
uint256 playerTotalBuyIns; /// total of all buyins made by the player for all games
uint256 playerTotalCashOuts; /// total of all cashouts made by the player for all games
}
/// mapping if player has registered in the contract via bool mapped to address
mapping(address => bool) public isPlayer;
/// mapping UnionPokerPlayer to their address
mapping(address => UnionPokerPlayer) public playerStats;
/// array of gameHistory
UnionPokerGame[] public gameHistory;
/// array of UnionPokerPlayers
UnionPokerPlayer[] public unionPokerPlayers;
/// current game in progress
bool public gameInProgress;
/// struct with state of current game
UnionPokerGame public currentGame;
/// constructor setting game in progress to false
constructor () public {
gameInProgress = false;
}
/**
* @dev newPlayer adds a new player to the contract
* @param _newPlayer address of the new Union Poker Player
*/
function newPlayer(address _newPlayer) public {
require(isPlayer[_newPlayer] == false, "player not new"); /// make sure player is new
/// create a new player struct
UnionPokerPlayer memory player;
/// set balances to 0
player.playerTotalBalance = 0;
player.playerTotalOwed = 0;
player.playerTotalBuyIns = 0;
player.playerTotalCashOuts = 0;
/// register the player
isPlayer[_newPlayer] = true;
/// push player struct to the unionPokerPlayers array
unionPokerPlayers.push(player);
/// map the player stat struct to the new player's address
playerStats[_newPlayer] = player;
}
/**
* @dev newPokerGame creates and starts a new poker game
* @dev can only be started if no game in progress
* @dev can be started by anyone but only registered players can buy in
*/
function newPokerGame() public {
require(gameInProgress == false, "game in progress");
// new UnionPokerGame();
UnionPokerGame memory newGame;
newGame.started = true;
newGame.ended = false;
newGame.totalBuyIns = 0;
newGame.totalCashOuts = 0;
newGame.totalBalance = 0;
currentGame = newGame;
gameInProgress = true;
}
/**
* @dev buyIn allows a registered player to buy in to the current game
* @param _amount uint256 buy in amount
*/
function buyIn(uint256 _amount) public {
require(gameInProgress == true, "create a game first");
require(isPlayer[msg.sender] == true, "not a registered player");
currentGame.totalBuyIns += _amount;
currentGame.totalBalance += _amount;
currentGame.playerTotalBalance[msg.sender] += _amount;
currentGame.playerBuyIns[msg.sender] += _amount;
playerStats[msg.sender].playerTotalOwed += _amount;
playerStats[msg.sender].playerTotalBuyIns += _amount;
rebalancePlayerFunds(msg.sender);
}
/**
* @dev cashOut allows player to cash out
* @param _amount uint256 amount to cash out
*/
function cashOut(uint256 _amount) public {
uint256 deposits = currentGame.totalBuyIns;
uint256 withdraws = currentGame.totalCashOuts;
uint256 gameBalance = currentGame.totalBalance;
require(gameBalance == (deposits - withdraws), "error");
require((_amount <= deposits + withdraws) && (_amount <= gameBalance), "error");
currentGame.totalCashOuts += _amount;
currentGame.totalBalance -= _amount;
currentGame.playerTotalBalance[msg.sender] -= _amount;
currentGame.playerCashOuts[msg.sender] += _amount;
playerStats[msg.sender].playerTotalBalance += _amount;
playerStats[msg.sender].playerTotalCashOuts += _amount;
rebalancePlayerFunds(msg.sender);
if (currentGame.totalBalance == 0 && currentGame.totalCashOuts == currentGame.totalBuyIns) {
gameInProgress = false;
currentGame.ended = true;
gameHistory.push(currentGame);
}
}
/**
* @dev rebalancePlayerFunds reconciles player balance vs player owed amount
* @dev this function is called internally following a buy in or cash out
* @param _player address of the player
*/
function rebalancePlayerFunds(address _player) internal {
if(playerStats[_player].playerTotalBalance >= playerStats[_player].playerTotalOwed) {
playerStats[_player].playerTotalBalance -= playerStats[_player].playerTotalOwed;
playerStats[_player].playerTotalOwed = 0;
} else {
playerStats[_player].playerTotalOwed -= playerStats[_player].playerTotalBalance;
playerStats[_player].playerTotalBalance = 0;
}
}
function playerCurrentGameStats() public view returns(uint256, uint256, uint256) {
return(currentGame.playerTotalBalance[msg.sender], currentGame.playerCashOuts[msg.sender], currentGame.playerBuyIns[msg.sender]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment