fixed bug

This commit is contained in:
wzdwc
2020-06-29 08:41:36 +08:00
parent caa8669417
commit 78fabec1c8
25 changed files with 597 additions and 542 deletions
+24 -26
View File
@@ -2,32 +2,26 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="f9039135-aa11-4abd-ad74-f40c84e4fdb2" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/client/src/interface/IRoom.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/client/src/components/Action.vue" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/components/Action.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/client/src/components/BuyIn.vue" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/components/BuyIn.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/client/src/components/SitList.vue" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/components/SitList.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/client/src/components/range.vue" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/components/range.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/client/src/service/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/service/index.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/client/src/utils/PokerStyle.ts" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/utils/PokerStyle.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/client/src/views/Home.vue" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/views/Home.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/client/src/views/game.vue" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/views/game.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/controller/room.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/controller/room.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/core/Poker.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/core/Poker.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src.zip" beforeDir="false" afterPath="$PROJECT_DIR$/server/src.zip" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/controller/account.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/controller/account.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/controller/user.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/controller/user.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/core/Player.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/core/Player.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/core/PokerGame.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/core/PokerGame.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/core/PokerStyle.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/core/PokerStyle.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/extend/context.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/extend/context.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/io/controller/game.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/io/controller/game.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/io/middleware/join.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/io/middleware/join.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/interface/ICommandRecord.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/interface/ICommandRecord.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/interface/IGame.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/interface/IGame.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/interface/IGameRecord.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/interface/IGameRoom.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/interface/IGameRoom.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/middleware/elkLogger.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/middleware/elkLogger.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/app/middleware/notFound.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/app/middleware/notFound.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/config/config.default.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/config/config.default.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/config/config.prod.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/config/config.prod.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/config/config.test.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/config/config.test.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/interface/IAccountService.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/interface/IRoom.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/interface/IRoom.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/interface/IUser.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/interface/IUser.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/interface/IUserService.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/lib/baseSocketController.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/lib/baseSocketController.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/service/account.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/service/account.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/service/commandRecord.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/service/commandRecord.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/service/game.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/service/game.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/service/gameRecord.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/service/room.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/service/room.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/src/service/user.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/src/service/user.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/server/test/app/core/pokerGame.test.ts" beforeDir="false" afterPath="$PROJECT_DIR$/server/test/app/core/pokerGame.test.ts" afterDir="false" />
@@ -66,7 +60,7 @@
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="js.linters.configure.manually.selectedtslint" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/server/src/service" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/client/src/interface" />
<property name="list.type.of.created.stylesheet" value="Less" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.standard" value="true" />
@@ -83,6 +77,7 @@
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/client/src/interface" />
<recent name="$PROJECT_DIR$/server/src/service" />
<recent name="$PROJECT_DIR$/client/src/utils" />
<recent name="$PROJECT_DIR$/client/src/assets" />
@@ -108,7 +103,7 @@
<workItem from="1589475961634" duration="559000" />
<workItem from="1589732800789" duration="13203000" />
<workItem from="1590767628109" duration="39193000" />
<workItem from="1593066389745" duration="5258000" />
<workItem from="1593066389745" duration="10749000" />
</task>
<servers />
</component>
@@ -128,19 +123,22 @@
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="533" y="173" key="#com.intellij.ide.util.MemberChooser/0.0.1440.900@0.0.1440.900" timestamp="1587206645912" />
<state x="100" y="100" width="1240" height="700" key="DiffContextDialog" timestamp="1593070402308">
<screen x="0" y="0" width="1440" height="900" />
<state x="100" y="100" width="1240" height="700" key="DiffContextDialog" timestamp="1593348545499">
<screen x="0" y="23" width="1440" height="828" />
</state>
<state x="100" y="100" width="1240" height="700" key="DiffContextDialog/0.0.1440.900@0.0.1440.900" timestamp="1593070402308" />
<state x="100" y="100" width="1240" height="700" key="DiffContextDialog/0.23.1440.828@0.23.1440.828" timestamp="1593348545499" />
<state x="221" y="89" key="SettingsEditor" timestamp="1588864041632">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="221" y="89" key="SettingsEditor/0.0.1440.900@0.0.1440.900" timestamp="1588864041632" />
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog" timestamp="1590853061364">
<screen x="0" y="23" width="1440" height="823" />
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog" timestamp="1593358666478">
<screen x="0" y="23" width="1440" height="827" />
</state>
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.0.1440.900@0.0.1440.900" timestamp="1590851703228" />
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.0.1440.900@0.0.1440.900" timestamp="1593351376798" />
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.23.1440.823@0.23.1440.823" timestamp="1590853061364" />
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.23.1440.827@0.23.1440.827" timestamp="1593358666478" />
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.23.1440.828@0.23.1440.828" timestamp="1593348545500" />
<state x="513" y="145" key="com.intellij.openapi.editor.actions.MultiplePasteAction$ClipboardContentChooser" timestamp="1590828749947">
<screen x="0" y="0" width="1440" height="900" />
</state>
+2 -2
View File
@@ -3,9 +3,9 @@
<div class="action"
v-show="isAction">
<div class="action-type action-btn">
<span @click="action('check')"
v-show="showActionBtn('check')">check</span>
<span @click="action('fold')">fold</span>
<span @click="action('check')"
v-show="showActionBtn('check')">check</span>
<span @click="action('call')"
v-show="showActionBtn('call')">call</span>
<span @click="otherSizeHandle()"
+2 -1
View File
@@ -125,8 +125,9 @@
private buyIn(size: number) {
console.log('ccc');
this.showBuyIn = false;
this.currPlayer.counter += size;
this.$emit('buyIn', Number(size));
// this.sitDown(this.currSit);
this.sitDown(this.currSit);
}
private showHandCard(sit: ISit) {
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
import BaseController from '../../lib/baseController';
import { controller, inject, post, provide } from 'midway';
import { IAccountService } from '../../interface/IAccountService';
import { IAccountService } from '../../interface/service/IAccountService';
import { IAccountInfo } from '../../interface/IAccountInfo';
@provide()
+1 -1
View File
@@ -1,6 +1,6 @@
import { Context, inject, controller, post, provide, plugin } from 'midway';
import BaseController from '../../lib/baseController';
import { IUserService } from '../../interface/IUserService';
import { IUserService } from '../../interface/service/IUserService';
@provide()
@controller('/node/user')
+6 -6
View File
@@ -45,9 +45,8 @@ export class Player {
evPot: number = Infinity;
inPot: number = 0;
income: number = 0;
pokeStyle: string = '';
pokerStyle: string = '';
// commandRecord: Array<string> = [];
constructor(config: IPlayer) {
this.counter = config.counter;
this.position = config.position || 0;
@@ -75,8 +74,8 @@ export class Player {
/**
* player action
* @param {string} commandString
* @param {number} prevSize
* @param {string} commandString - player action command string
* @param {number} prevSize - prev player action size
* @example action('command:raise:10')
*/
action(commandString: string, prevSize: number = 0) {
@@ -88,7 +87,7 @@ export class Player {
&& (prevSize > (this.counter + this.actionSize) || raiseSize > this.counter)) {
throw 'player: error action, overflow action size';
} else {
this.actionCommand = (command === 'sb' || command === 'bb') ? '' : command;
this.actionCommand = (command === ECommand.SMALL_BLIND || command === ECommand.BIG_BLIND) ? '' : command;
}
// BLIND
@@ -122,7 +121,8 @@ export class Player {
if (command === ECommand.CALL) {
console.log('player: call----------------', prevSize, this.actionSize);
size = prevSize - this.actionSize;
const actionSize = this.actionSize >= 0 ? this.actionSize : 0;
size = prevSize - actionSize;
}
if (command === ECommand.CHECK) {
+304 -241
View File
@@ -7,6 +7,9 @@ import { PokerStyle } from './PokerStyle';
import { ILinkNode, Link } from '../../utils/Link';
import Timeout = NodeJS.Timeout;
/**
* Poker game class interface
*/
interface IPokerGame {
users: IPlayer[];
smallBlind: number;
@@ -16,11 +19,17 @@ interface IPokerGame {
autoActionCallBack: (actionType: string, userId: string) => void;
}
/**
* Game over enum
*/
export enum EGameOverType {
GAME_SHOWDOWN = 1,
GAME_OVER = 2,
}
/**
* Game state enum
*/
export enum EGameStatus {
GAME_READY,
GAME_START,
@@ -32,34 +41,41 @@ export enum EGameStatus {
GAME_OVER,
}
/**
* Action time
* @type {number}
*/
const ACTION_TIME = 30 * 1000;
/**
* Class representing a poker game
*/
export class PokerGame {
commonCard: string[] = [];
fireCards: string[] = [];
playerLink: Link<Player>;
allPlayer: Player[] = [];
SBPlayer: Player;
BBPlayer: Player;
poker: IPoker;
isShort: boolean;
pot: number;
slidePots: number [] = [];
status: EGameStatus;
gameOverType: EGameOverType;
currPlayer: ILinkNode<Player>;
smallBlind: number;
playerSize: number;
prevSize: number;
prevPot: number = 0;
actionTimeOut: Timeout;
allInPlayers: Player[] = [];
currActionAllinPlayer: Player[] = [];
actionRoundComplete: () => void;
gameOverCallBack: () => void;
autoActionCallBack: (actionType: string, userId: string) => void;
hasStraddle = false;
winner: Player[][] = [];
private playerLink: Link<Player>;
private poker: IPoker;
private prevPot: number = 0;
private actionTimeOut: Timeout;
private currActionAllinPlayer: Player[] = [];
// It's a short poker game
private readonly isShort: boolean;
private readonly smallBlind: number;
private readonly actionRoundComplete: () => void;
private readonly gameOverCallBack: () => void;
private readonly autoActionCallBack: (actionType: string, userId: string) => void;
// hasStraddle = false;
public slidePots: number [] = [];
public prevSize: number;
public currPlayer: ILinkNode<Player>;
public allInPlayers: Player[] = [];
public playerSize: number;
public pot: number;
public status: EGameStatus;
public commonCard: string[] = [];
public winner: Player[][] = [];
public allPlayer: Player[] = [];
public SBPlayer: Player;
public BBPlayer: Player;
public gameOverType: EGameOverType;
constructor(config: IPokerGame) {
this.smallBlind = config.smallBlind;
@@ -81,12 +97,15 @@ export class PokerGame {
this.playerLink = this.setPlayer(users);
this.playerSize = users.length;
// set SB, BB,Straddle
this.getBlind();
this.setBlind();
// UTG
this.currPlayer = this.playerLink.getNode(3);
}
getBlind() {
/**
* game init blind (SB,BB)
*/
private setBlind() {
// sb blind
const SBPlayerNode = this.playerLink.getNode(1);
this.SBPlayer = SBPlayerNode.node;
@@ -104,11 +123,205 @@ export class PokerGame {
}
}
/**
* Get game winner
*/
getWinner() {
// only one winner, other players fold
if (this.allInPlayers.length === 0 && this.playerSize === 1
|| this.allInPlayers.length === 1 && this.playerSize === 0) {
console.log('only one player');
this.gameOverType = EGameOverType.GAME_OVER;
const winner = this.allInPlayers[0] || this.currPlayer.node;
this.status = EGameStatus.GAME_OVER;
this.winner.push([ winner ]);
return;
}
// game show down
while (this.status !== EGameStatus.GAME_SHOWDOWN) {
this.sendCard();
this.setSate();
}
this.status = EGameStatus.GAME_OVER;
this.gameOverType = EGameOverType.GAME_SHOWDOWN;
this.getPlayerPokerStyle();
/**
* The max player can't win all of pot, get the largest of the remaining players
* @param {Player[]} excludePlayers - exclude players
*/
const getOtherWinner = (excludePlayers: Player[]) => {
// all player allin, winner can't get all pot
const allPlayer = this.getPlayers('all', excludePlayers);
// all player are exclude
if (allPlayer.length === 0) {
return;
}
const maxLastPlayer = this.getMaxPlayers(allPlayer);
this.winner.push(maxLastPlayer);
if (this.getLeftoverPot() > 0) {
getOtherWinner([ ...excludePlayers, ...maxLastPlayer ]);
}
};
getOtherWinner([]);
}
/**
* Set players
* @param {IPlayer[]} users
* @returns {Link<Player>}
*/
setPlayer(users: IPlayer[]) {
console.log('init player ======================================================', users);
users.forEach((u, position) => {
const player = new Player({
...u,
position,
});
this.allPlayer.push(player);
});
return new Link<Player>(this.allPlayer);
}
/**
* Get in the game players
* @param {string} type - 'all': include allin players
* @param {Player[]} excludePlayers - exclude player
* @returns {any[]}
*/
getPlayers(type= 'all', excludePlayers?: Player[]) {
let players = [];
let nextPlayer: ILinkNode<Player> = this.playerLink.link;
let i = 0;
while (i < this.playerSize) {
players.push(nextPlayer.node);
if (nextPlayer.next) {
nextPlayer = nextPlayer.next;
}
i++;
}
players = type === 'all' ? [ ...players, ...this.allInPlayers ] : players;
return excludePlayers ? players.filter(p => {
const isNotPlayer = excludePlayers.filter(excludePlayer => excludePlayer.userId === p.userId
|| excludePlayer.evPot >= p.evPot);
return isNotPlayer.length === 0;
}) : players;
}
/**
* Get player poker max poker style
*/
getPlayerPokerStyle() {
this.allPlayer.map(p => {
p.pokerStyle = new PokerStyle([ ...p.getHandCard(), ...this.commonCard ], this.isShort).getPokerWeight();
return p;
});
}
/**
* Counting allin player slide pot
* @returns {number}
*/
getLeftoverPot() {
if (this.winner.length === 0) {
return this.pot;
}
return this.pot - this.winner[this.winner.length - 1][0].evPot;
}
/**
* Get max players with player poker style weight
* @param {Player[]} lastPlayers
* @returns {Player[]}
*/
getMaxPlayers(lastPlayers: Player[]) {
const _maxPlayers: Player[] = [];
const maxPlayer = lastPlayers.reduce((acc, cur) => {
return this.compareCard(acc, cur) === 1 ? acc : cur;
});
// has many winner equal max player
lastPlayers.forEach(p => {
if (this.compareCard(p, maxPlayer) === 0) {
_maxPlayers.push(p);
}
});
return _maxPlayers;
}
/**
* Find next round first action player,
* if small blind is already fold, then next in the game player
* @returns {ILinkNode<Player>}
*/
getFirstActionPlayer() {
const player = this.allPlayer.filter(p => p.counter > 0
&& p.position !== 0 && p.actionCommand !== 'fold')[0];
console.log('getFirstActionPlayer-------player', player);
let link: ILinkNode<Player> | null = this.playerLink.link;
for (let i = 0; i < this.playerSize; i++) {
if (link?.node.userId === player?.userId) {
return link;
}
link = link?.next as ILinkNode<Player>;
}
return link;
}
/**
* Set game state
*/
setSate() {
if (this.status === EGameStatus.GAME_ACTION) {
if (this.commonCard.length === 0) {
this.status = EGameStatus.GAME_FLOP;
}
if (this.commonCard.length === 3) {
this.status = EGameStatus.GAME_TURN;
}
if (this.commonCard.length === 4) {
this.status = EGameStatus.GAME_RIVER;
}
if (this.commonCard.length === 5) {
this.status = EGameStatus.GAME_SHOWDOWN;
}
} else {
this.status = EGameStatus.GAME_ACTION;
}
}
/**
* Set hand cards
*/
setHandCard() {
// send card start by small blind
let playerLink = this.playerLink.link;
let player: Player;
for (let i = 0; i < 2; i++) {
let j = 0;
while (j < this.playerSize) {
player = playerLink.node;
player.setHandCard(this.poker.getCard());
if (playerLink.next) {
playerLink = playerLink.next;
}
j++;
}
}
}
/**
* Play game
*/
play() {
this.status = EGameStatus.GAME_START;
this.sendCard();
}
/**
* Start next action round
*/
startActionRound() {
this.actionTimeOut = setTimeout(async () => {
const userId = this.currPlayer.node.userId || '';
@@ -118,49 +331,52 @@ export class PokerGame {
}, ACTION_TIME);
}
/**
* player action
* @param {string} commandString - player action command string, include 'call', 'fold', 'raise:xxx(size)', 'allin', 'check'
*/
action(commandString: string) {
if (this.status === EGameStatus.GAME_ACTION && this.currPlayer.next) {
const commandArr = commandString.split(':');
const command = commandArr[0];
let size = Number(commandArr[1]);
const commands = commandString.split(':');
const command = commands[0];
let size = Number(commands[1]);
if (command === ECommand.ALL_IN) {
// Counting player action size, if player's counter less than prevSize then use prevSize
size = this.currPlayer.node.counter > this.prevSize ?
this.currPlayer.node.counter : this.prevSize;
this.allIn();
console.log('allin: -----------', this.currPlayer);
this.currActionAllinPlayer.push(this.currPlayer.node);
this.removePlayer(this.currPlayer.node);
this.pot += this.currPlayer.node.counter;
// other pot
// only one playeror none playergame is over
}
if (command === ECommand.CALL) {
size = this.prevSize;
this.pot += size - this.currPlayer.node.actionSize;
const actionSize = this.currPlayer.node.actionSize >= 0 ? this.currPlayer.node.actionSize : 0;
console.log('call----------', actionSize);
this.pot += size - actionSize;
}
if (command === ECommand.FOLD) {
// size = this.prevSize;
this.removePlayer(this.currPlayer.node);
// only one playeror none playergame is over
}
if (command === ECommand.CHECK) {
console.log(this.currPlayer.node.type === EPlayerType.BIG_BLIND
&& this.prevSize === this.smallBlind * 2, 'big blind', this.currPlayer);
size = -1;
// prev player must be check
if (!(this.prevSize <= 0 ||
((this.currPlayer.node.type === EPlayerType.BIG_BLIND
|| this.playerSize === 2 && this.currPlayer.node.type === EPlayerType.DEALER)
&& this.prevSize === this.smallBlind * 2))) {
&& this.prevSize === this.smallBlind * 2))) {
throw 'incorrect action: check';
}
console.log(this.currPlayer.node.type === EPlayerType.BIG_BLIND
&& this.prevSize === this.smallBlind * 2, 'big blind', this.currPlayer);
size = -1;
}
if (command === ECommand.RAISE) {
this.pot += size;
// 3 bet
size += this.currPlayer.node.actionSize;
// counter not enough raise
if ((size + this.currPlayer.node.actionSize) < this.prevSize * 2) {
throw `incorrect action: raise ========= action size: ${this.currPlayer.node.actionSize}, prevSize: ${this.prevSize}`;
}
this.pot += size;
// 3 bet
size += this.currPlayer.node.actionSize;
}
try {
clearTimeout(this.actionTimeOut);
@@ -168,23 +384,10 @@ export class PokerGame {
const nextPlayer = this.currPlayer.next.node;
// all check actionSize === -1
// all player allin
// only 2 player, curr player fold, next player already action
// only 2 player, curr player fold, next player alrecommand add errorady action
// only one player ,one player fold,other player allin
// pre flop big blind check and other player call
// pre flop big blind fold and other player call
console.log('this.currPlayer----------', this.currPlayer, nextPlayer, command);
console.log('this.currPlayer----------', this.playerSize);
console.log('this.currPlayer---------- test play', this.allInPlayers);
console.log('this.currPlayer---------- this.prevSize', this.prevSize);
console.log('this.currPlayer---------- complete',
nextPlayer.actionSize === this.prevSize,
this.prevSize !== this.smallBlind * 2,
(this.commonCard.length === 0
&& nextPlayer.actionSize === this.smallBlind * 2
&& (this.currPlayer.node.type === EPlayerType.BIG_BLIND
|| (this.allPlayer.length === 2 && this.currPlayer.node.type === EPlayerType.DEALER))
&& (command === ECommand.CHECK || command === ECommand.FOLD)));
if (this.playerSize === 0
|| (this.playerSize === 1 && this.currActionAllinPlayer.length === 0)
|| (this.commonCard.length !== 0 && nextPlayer.actionSize === this.smallBlind * 2 && nextPlayer.actionSize === size)
@@ -196,15 +399,13 @@ export class PokerGame {
&& (this.currPlayer.node.type === EPlayerType.BIG_BLIND
|| (this.allPlayer.length === 2 && this.currPlayer.node.type === EPlayerType.DEALER))
&& (command === ECommand.CHECK || command === ECommand.FOLD))) {
// console.log('ccc------', this.currPlayer, nextPlayer, command, this.playerSize);
console.log('actionComplete');
this.actionComplete();
return;
}
this.prevSize = command === ECommand.FOLD ? this.prevSize : size;
this.currPlayer = this.currPlayer.next;
// action time is 60s
console.log('action auto');
// action time out, auto action fold
this.actionTimeOut = setTimeout(() => {
const actionType = 'fold';
const userId = this.currPlayer.node.userId;
@@ -218,32 +419,11 @@ export class PokerGame {
throw 'incorrect action flow';
}
}
allIn() {
this.currActionAllinPlayer.push(this.currPlayer.node);
this.removePlayer(this.currPlayer.node);
}
/**
* Action is complete, collet allin player, clear player action, enter the next round
*/
private actionComplete() {
// // pre flop
// if (this.commonCard.length === 0
// && this.currPlayer.node.actionSize === this.smallBlind * 2
// && this.currPlayer.node.type !== EPlayerType.BIG_BLIND) {
// if (this.currPlayer.next) {
// this.currPlayer = this.currPlayer.next;
// } else {
// throw 'currPlayer.next is null';
// }
// console.log('come in test---------ets');
// if (this.playerSize > 1) {
// this.actionTimeOut = setTimeout(() => {
// const actionType = 'fold';
// const userId = this.currPlayer.node.userId;
// this.action(actionType);
// this.autoActionCallBack(actionType, userId);
// }, ACTION_TIME);
// return;
// }
// }
// action has allin, sum the allin player ev_pot
if (this.currActionAllinPlayer.length !== 0) {
let currAllinPlayerPot = 0;
@@ -287,38 +467,10 @@ export class PokerGame {
}
this.actionRoundComplete();
}
getFirstActionPlayer() {
const player = this.allPlayer.filter(p => p.counter > 0
&& p.position !== 0 && p.actionCommand !== 'fold')[0];
console.log('getFirstActionPlayer-------player', player);
let link: ILinkNode<Player> | null = this.playerLink.link;
for (let i = 0; i < this.playerSize; i++) {
if (link?.node.userId === player?.userId) {
return link;
}
link = link?.next as ILinkNode<Player>;
}
return link;
}
setSate() {
if (this.status === EGameStatus.GAME_ACTION) {
if (this.commonCard.length === 0) {
this.status = EGameStatus.GAME_FLOP;
}
if (this.commonCard.length === 3) {
this.status = EGameStatus.GAME_TURN;
}
if (this.commonCard.length === 4) {
this.status = EGameStatus.GAME_RIVER;
}
if (this.commonCard.length === 5) {
this.status = EGameStatus.GAME_SHOWDOWN;
}
} else {
this.status = EGameStatus.GAME_ACTION;
}
}
/**
* Send common card or hand card
*/
sendCard() {
if (this.status === EGameStatus.GAME_START) {
this.setHandCard();
@@ -326,13 +478,17 @@ export class PokerGame {
return;
}
if (this.status === EGameStatus.GAME_FLOP) {
this.fireCards.push(this.poker.getCard());
this.flop();
// fire card
this.poker.getCard();
for (let i = 0; i < 3; i++) {
this.commonCard.push(this.poker.getCard());
}
this.setSate();
return;
}
if (this.status === EGameStatus.GAME_TURN || this.status === EGameStatus.GAME_RIVER) {
this.fireCards.push(this.poker.getCard());
// fire card
this.poker.getCard();
this.commonCard.push(this.poker.getCard());
this.setSate();
return;
@@ -340,15 +496,15 @@ export class PokerGame {
throw 'error flow sendCard';
}
flop() {
for (let i = 0; i < 3; i++) {
this.commonCard.push(this.poker.getCard());
}
}
compareCard(player: Player, otherPlayer: Player) {
const firstWeight = player.pokeStyle;
const lastWeight = otherPlayer.pokeStyle;
/**
* Comparison player cards style, base on poker style weight
* @param {Player} player - first player
* @param {Player} targetPlayer - second player
* @returns {number} - target player, bigger: -1, equal: 0, less than: 1
*/
compareCard(player: Player, targetPlayer: Player) {
const firstWeight = player.pokerStyle;
const lastWeight = targetPlayer.pokerStyle;
let flag = -1;
if (firstWeight > lastWeight) {
flag = 1;
@@ -362,44 +518,19 @@ export class PokerGame {
return flag;
}
setPlayer(users: IPlayer[]) {
console.log('init player ======================================================', users);
users.forEach((u, position) => {
const player = new Player({
...u,
position,
});
this.allPlayer.push(player);
});
return new Link<Player>(this.allPlayer);
}
getPlayers(type= 'all', withoutPlayers?: Player[]) {
let players = [];
let nextPlayer: ILinkNode<Player> = this.playerLink.link;
let i = 0;
while (i < this.playerSize) {
players.push(nextPlayer.node);
if (nextPlayer.next) {
nextPlayer = nextPlayer.next;
}
i++;
}
players = type === 'all' ? [ ...players, ...this.allInPlayers ] : players;
return withoutPlayers ? players.filter(p => {
const isNotPlayer = withoutPlayers.filter(withoutPlayer => withoutPlayer.userId === p.userId
|| withoutPlayer.evPot >= p.evPot);
return isNotPlayer.length === 0;
}) : players;
}
/**
* Clear all player action size and action command
*/
private clearPlayerAction() {
this.allPlayer.forEach(player => {
player.clearActionSize();
});
}
public clearPlayer() {
/**
* Game over, init player
*/
public initPlayer() {
this.allPlayer.forEach(player => {
player.type = '';
player.actionSize = 0;
@@ -407,6 +538,10 @@ export class PokerGame {
});
}
/**
* remove player from player link
* @param {Player} currPlayer
*/
removePlayer(currPlayer: Player) {
let playerLink = this.playerLink.link;
let player: ILinkNode<Player>;
@@ -424,85 +559,9 @@ export class PokerGame {
}
}
getWinner() {
if (this.allInPlayers.length === 0 && this.playerSize === 1
|| this.allInPlayers.length === 1 && this.playerSize === 0) {
console.log('only one player');
this.gameOverType = EGameOverType.GAME_OVER;
const winner = this.allInPlayers[0] || this.currPlayer.node;
this.status = EGameStatus.GAME_OVER;
this.winner.push([ winner ]);
return;
}
while (this.status !== EGameStatus.GAME_SHOWDOWN) {
this.sendCard();
this.setSate();
}
this.status = EGameStatus.GAME_OVER;
this.gameOverType = EGameOverType.GAME_SHOWDOWN;
this.getPlayerPokeStyle();
const getOtherWinner = (withoutPlayers: Player[]) => {
// all player allin, winner can't get all pot
const allPlayer = this.getPlayers('all', withoutPlayers);
// withoutPlayer is allPlayer
if (allPlayer.length === 0) {
return;
}
const maxLastPlayer = this.getMaxPlayers(allPlayer);
this.winner.push(maxLastPlayer);
if (this.getLeftoverPot() > 0) {
getOtherWinner([ ...withoutPlayers, ...maxLastPlayer ]);
}
};
getOtherWinner([]);
}
getPlayerPokeStyle() {
this.allPlayer.map(p => {
p.pokeStyle = new PokerStyle([ ...p.getHandCard(), ...this.commonCard ], this.isShort).getPokerWeight();
return p;
});
}
getLeftoverPot() {
if (this.winner.length === 0) {
return this.pot;
}
return this.pot - this.winner[this.winner.length - 1][0].evPot;
}
getMaxPlayers(lastPlayers: Player[]) {
const _maxPlayers: Player[] = [];
const maxPlayer = lastPlayers.reduce((acc, cur) => {
return this.compareCard(acc, cur) === 1 ? acc : cur;
});
// has many winner equal max player
lastPlayers.forEach(p => {
if (this.compareCard(p, maxPlayer) === 0) {
_maxPlayers.push(p);
}
});
return _maxPlayers;
}
setHandCard() {
// send card start by small blind
let playerLink = this.playerLink.link;
let player: Player;
for (let i = 0; i < 2; i++) {
let j = 0;
while (j < this.playerSize) {
player = playerLink.node;
player.setHandCard(this.poker.getCard());
if (playerLink.next) {
playerLink = playerLink.next;
}
j++;
}
}
}
/**
* Counting winner Pot
*/
counting() {
let prevEvPot = 0;
this.winner.forEach((winnerList, key) => {
@@ -515,13 +574,17 @@ export class PokerGame {
});
});
}
/**
* Game over
*/
gameOver() {
console.log('game over------------------');
// only one player,other fold
this.getWinner();
// todo counting
this.counting();
this.clearPlayer();
this.initPlayer();
this.gameOverCallBack();
}
}
+2 -2
View File
@@ -4,7 +4,7 @@ const LOG_COLLECTION = Symbol('Context#logCollection');
export default {
context: this,
/**
*
* Get log
* @returns {any}
*/
getLogs(this: Context) {
@@ -15,7 +15,7 @@ export default {
return result;
},
/**
*
* Collect log info
* @param {string} key
* @param {string} value
*/
+105 -154
View File
@@ -9,38 +9,67 @@ import { ICommandRecord } from '../../../interface/ICommandRecord';
import { IPlayerDTO } from '../../../interface/IPlayer';
class GameController extends BaseSocketController {
private async getSitDownPlayer(roomInfo: IRoomInfo): Promise<IPlayer []> {
let sitDownPlayer: IPlayer[] = [];
// first game sitLink is null
if (roomInfo.sitLink) {
let currNode: ILinkNode<IPlayer> | null = roomInfo.sitLink;
const currPlayer = currNode.node;
sitDownPlayer.push(currNode.node);
while (currNode && currPlayer.userId !== currNode.next?.node.userId) {
const next: ILinkNode<IPlayer> | null = currNode.next;
if (next) {
sitDownPlayer.push(next.node);
}
currNode = next;
}
} else {
sitDownPlayer = roomInfo.sit.filter(
s => s.player && s.player.counter > 0).map(sit => sit.player);
if (sitDownPlayer.length < 2) {
throw 'player not enough';
}
roomInfo.sitLink = new Link<IPlayer>(sitDownPlayer).link;
}
if (sitDownPlayer.length < 2) {
throw 'player not enough';
}
return sitDownPlayer;
}
private async sendHandCard(roomInfo: IRoomInfo) {
const playerRecordService = await this.app.applicationContext.getAsync('PlayerRecordService');
for (const p of roomInfo.players) {
const player = roomInfo.game?.allPlayer.find(
player => player.userId === p.userId);
const msg = this.ctx.helper.parseMsg('handCard', {
handCard: player?.getHandCard(),
}, { client: p.socketId });
this.nsp.emit(p.socketId, msg);
if (player) {
const playerRecord: IPlayerDTO = {
roomNumber: this.roomNumber,
gameId: roomInfo.gameId || 0,
userId: player.userId || '',
buyIn: p.buyIn,
counter: p.counter,
handCard: player.getHandCard().join(',') || '',
};
await playerRecordService.add(playerRecord);
}
}
}
/**
* Play game
* @returns {Promise<void>}
*/
async playGame() {
try {
const roomInfo = await this.getRoomInfo();
const gameService = await this.app.applicationContext.getAsync('GameService');
const playerRecordService = await this.app.applicationContext.getAsync('PlayerRecordService');
console.log('players===============sit11111111111', roomInfo.sit);
let sitDownPlayer: IPlayer[] = [];
if (roomInfo.sitLink) {
let currNode: ILinkNode<IPlayer> | null = roomInfo.sitLink;
const currPlayer = currNode.node;
sitDownPlayer.push(currNode.node);
while (currNode && currPlayer.userId !== currNode.next?.node.userId) {
const next: ILinkNode<IPlayer> | null = currNode.next;
if (next) {
sitDownPlayer.push(next.node);
}
currNode = next;
}
} else {
sitDownPlayer = roomInfo.sit.filter(
s => s.player && s.player.counter > 0).map(sit => sit.player);
if (sitDownPlayer.length < 2) {
throw 'player not enough';
}
roomInfo.sitLink = new Link<IPlayer>(sitDownPlayer).link;
}
console.log('sitDownPlayer===============sit11111111111', sitDownPlayer);
console.log('roomInfo.sitLink===============sit11111111111',
roomInfo.sitLink);
if (sitDownPlayer.length < 2) {
throw 'player not enough';
}
const sitDownPlayer = await this.getSitDownPlayer(roomInfo);
console.log('roomConfig-------------------', roomInfo.config);
if (!roomInfo.game) {
roomInfo.game = null;
@@ -48,7 +77,7 @@ class GameController extends BaseSocketController {
users: sitDownPlayer,
isShort: roomInfo.config.isShort,
smallBlind: 1,
actionRoundComplete: () => {
actionRoundComplete: async () => {
let slidePots: number [] = [];
if (roomInfo.game) {
console.log('come in', roomInfo.game.status);
@@ -59,21 +88,10 @@ class GameController extends BaseSocketController {
if (roomInfo.game.allInPlayers.length > 0) {
slidePots = roomInfo.game.slidePots;
}
this.nsp.adapter.clients([ this.roomNumber ],
(err: any, clients: any) => {
if (roomInfo.game) {
// 更新common card
this.nsp.to(this.roomNumber).emit('online', {
clients,
action: 'actionComplete',
target: 'participator',
data: {
slidePots,
commonCard: roomInfo.game.commonCard,
},
});
}
});
await this.adapter('online', 'actionComplete', {
slidePots,
commonCard: roomInfo.game.commonCard,
});
}
}
},
@@ -98,41 +116,28 @@ class GameController extends BaseSocketController {
}
});
console.log('allPlayer =================== game over', roomInfo.game.allPlayer);
}
this.nsp.adapter.clients([ this.roomNumber ],
(err: any, clients: any) => {
if (roomInfo.game) {
// game over show winner
if (roomInfo.game.status === 7) {
let winner: any = [
[
{
...roomInfo.game.winner[0][0],
handCard: [],
}]];
let allPlayers = winner[0];
// only player, other fold
if (roomInfo.game.getPlayers().length !== 1) {
winner = roomInfo.game.winner;
allPlayers = roomInfo.game.getPlayers();
}
this.nsp.to(this.roomNumber).emit('online', {
clients,
action: 'gameOver',
target: 'participator',
data: {
winner,
allPlayers,
commonCard: roomInfo.game.commonCard,
},
});
}
// new game
setTimeout(() => {
this.reStart();
}, 10000);
if (roomInfo.game.status === EGameStatus.GAME_OVER) {
let winner: any = [[{
...roomInfo.game.winner[0][0],
handCard: [],
}]];
let allPlayers = winner[0];
// only player, other fold
if (roomInfo.game.getPlayers().length !== 1) {
winner = roomInfo.game.winner;
allPlayers = roomInfo.game.getPlayers();
}
});
await this.adapter('online', 'gameOver', {
winner,
allPlayers,
commonCard: roomInfo.game.commonCard,
});
// new game
setTimeout(() => {
this.reStart();
}, 10000);
}
}
// update game info
const gameRecord: IGame = {
id: roomInfo.gameId,
@@ -149,8 +154,6 @@ class GameController extends BaseSocketController {
autoActionCallBack: async (command, userId) => {
// fold change status: -1
if (command === 'fold') {
console.log('cccc', command, userId);
console.log('roomInfo', roomInfo.players);
roomInfo.players.forEach(p => {
if (p.userId === userId) {
p.status = -1;
@@ -163,35 +166,17 @@ class GameController extends BaseSocketController {
}
});
}
// todo notice next player action
await this.updateGameInfo();
console.log('auto Action');
},
});
roomInfo.game.play();
roomInfo.game.startActionRound();
console.log('hand card', roomInfo.game.allPlayer);
// update counter, pot, status
await this.updateGameInfo();
for (const p of roomInfo.players) {
const player = roomInfo.game?.allPlayer.find(
player => player.userId === p.userId);
const msg = this.ctx.helper.parseMsg('handCard', {
handCard: player?.getHandCard(),
}, { client: p.socketId });
this.nsp.emit(p.socketId, msg);
const playerRecord: IPlayerDTO = {
roomNumber: this.roomNumber,
gameId: roomInfo.gameId || 0,
userId: player?.userId || '',
buyIn: p.buyIn,
counter: p.counter,
handCard: player?.getHandCard().join(',') || '',
};
await playerRecordService.add(playerRecord);
}
await this.sendHandCard(roomInfo);
// add game record
const gameRecord: IGame = {
roomNumber: this.roomNumber,
@@ -231,8 +216,12 @@ class GameController extends BaseSocketController {
counter: SB.counter,
};
const commandRecordService = await this.app.applicationContext.getAsync('CommandRecordService');
await commandRecordService.add(SBCommandRecord);
await commandRecordService.add(BBCommandRecord);
const sbRecordResult = await commandRecordService.add(SBCommandRecord);
const bbRecordResult = await commandRecordService.add(BBCommandRecord);
console.log(bbRecordResult, sbRecordResult);
if (!sbRecordResult.succeed || !bbRecordResult.succeed) {
throw 'command add error';
}
} else {
throw 'game already paling';
}
@@ -289,34 +278,16 @@ class GameController extends BaseSocketController {
roomInfo.sitLink = link;
console.log('dealer ===================', dealer, link);
// new game
this.nsp.adapter.clients([ this.roomNumber ],
async (err: any, clients: any) => {
// 广播信息
this.nsp.to(this.roomNumber).emit('online', {
clients,
action: 'newGame',
target: 'participator',
data: {},
});
await this.playGame();
});
await this.adapter('online', 'newGame', {});
await this.playGame();
} else {
roomInfo.sitLink = null;
console.log('come in only one player');
// player not enough
this.nsp.adapter.clients([ this.roomNumber ],
async (err: any, clients: any) => {
// 广播信息
this.nsp.to(this.roomNumber).emit('online', {
clients,
action: 'pause',
target: 'participator',
data: {
players: roomInfo.players,
sitList: roomInfo.sit,
},
});
});
await this.adapter('online', 'pause', {
players: roomInfo.players,
sitList: roomInfo.sit,
});
}
} catch (e) {
console.log(e + 'restart ex');
@@ -343,6 +314,9 @@ class GameController extends BaseSocketController {
player.reBuy += Number(buyInSize);
player.buyIn += Number(buyInSize);
console.log('come in');
} else {
player.buyIn += Number(buyInSize);
player.counter += Number(buyInSize);
}
} else {
player.buyIn += Number(buyInSize);
@@ -358,18 +332,9 @@ class GameController extends BaseSocketController {
}
console.log(player, 'buy in player', roomInfo.players);
if (!isGaming) {
this.nsp.adapter.clients([ this.roomNumber ],
(err: any, clients: any) => {
// 广播信息
this.nsp.to(this.roomNumber).emit('online', {
clients,
action: 'players',
target: 'participator',
data: {
players: roomInfo.players,
},
});
});
await this.adapter('online', 'players', {
players: roomInfo.players,
});
}
} catch (e) {
console.log(e);
@@ -406,23 +371,9 @@ class GameController extends BaseSocketController {
const { payload } = this.message;
const sitList = payload.sitList;
const roomInfo = await this.getRoomInfo();
console.log('sitList===========', sitList);
// update player isSit
// roomInfo.players.forEach(p => {
// const sit = sitList.find((s: ISit) => s.player?.userId === p.userId);
// p.isSit = !!sit;
// });
roomInfo.sit = sitList;
this.nsp.adapter.clients([ this.roomNumber ], (err: any, clients: any) => {
// 广播信息
this.nsp.to(this.roomNumber).emit('online', {
clients,
action: 'sitList',
target: 'participator',
data: {
sitList,
},
});
await this.adapter('online', 'sitList', {
sitList,
});
} catch (e) {
console.log(e);
+4 -4
View File
@@ -1,15 +1,15 @@
import { Context, EggAppConfig } from 'egg';
/**
* elk
* @description ,config的环境配置prod默认开启
* @param {EggAppConfig["elkLogger"]} options config elkLogger
* elk
* @description request intercept,log report,prod default open
* @param {EggAppConfig["elkLogger"]} options config elkLogger
* @returns {any}
*/
export default function elkLogger(options: EggAppConfig['elkLogger']): any {
return async (ctx: Context, next: () => Promise<any>) => {
const { match, enable } = options;
// 是否符合配置规则
// match
if (match(ctx) && enable) {
ctx.setLogCollection('fetchStart', Date.now());
ctx.setLogCollection('url', ctx.url);
+2 -2
View File
@@ -1,7 +1,7 @@
import { Context } from 'egg';
/**
* 404
* 404
* @returns {any}
*/
export default function notFound(): any {
@@ -12,7 +12,7 @@ export default function notFound(): any {
ctx.body = {
code: '404',
data: {},
msg: '页面坐火箭去了',
msg: 'page not found',
};
} else {
ctx.body = '<h1>Page Not Found</h1>';
+7 -11
View File
@@ -8,14 +8,13 @@ export default (appInfo: EggAppInfo) => {
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_{{keys}}';
// elk日志中间件,404处理中间件
// elk log404
config.middleware = [ 'elkLogger', 'notFound' ];
// 合成配置
const bizConfig = {
sourceUrl: '',
elkLogger: {
// 请求url匹配规则
// request url match
match(ctx: Context) {
const reg = /.*/;
return reg.test(ctx.url);
@@ -24,7 +23,7 @@ export default (appInfo: EggAppInfo) => {
enable: true,
},
};
// 安全处理
// security
config.security = {
csrf: {
enable: false,
@@ -33,7 +32,7 @@ export default (appInfo: EggAppInfo) => {
enable: false,
},
};
// CORS 跨域处理
// CORS
config.cors = {
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
credentials: true,
@@ -50,7 +49,7 @@ export default (appInfo: EggAppInfo) => {
},
};
// 日志配置
// logger
config.logger = {
outputJSON: false,
appLogName: 'app.log',
@@ -59,10 +58,10 @@ export default (appInfo: EggAppInfo) => {
errorLogName: 'error.log',
};
// 业务接口domain
// business domain
config.apiDomain = {};
// jsonwebtoken 插件配置
// jsonwebtoken
config.jwt = {
secret: '123456',
enable: true,
@@ -95,7 +94,6 @@ export default (appInfo: EggAppInfo) => {
},
};
config.mysql = {
// 单数据库信息配置
client: {
// host
host: '47.104.172.100',
@@ -108,9 +106,7 @@ export default (appInfo: EggAppInfo) => {
// 数据库名
database: 'poker',
},
// 是否加载到 app 上,默认开启
app: true,
// 是否加载到 agent 上,默认关闭
agent: false,
};
+2 -2
View File
@@ -3,10 +3,10 @@ import { Context } from 'midway';
export default () => {
const config: PowerPartial<EggAppConfig> = {};
// 业务接口domain
// business domain
config.apiDomain = {
};
// CORS 跨域处理
// CORS
config.cors = {
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
credentials: true,
+1 -1
View File
@@ -2,7 +2,7 @@ import { EggAppConfig, PowerPartial } from 'egg';
export default () => {
const config: PowerPartial<EggAppConfig> = {};
// 业务接口domain
// business domain
config.apiDomain = {
};
return config;
-8
View File
@@ -1,8 +0,0 @@
import { IAccountInfo } from './IAccountInfo';
import { ILoginResult } from './ILoginResult';
export interface IAccountService {
login(accountInfo: IAccountInfo): Promise<ILoginResult>;
authUser(userInfo: IAccountInfo): Promise<boolean>;
register(accountInfo: IAccountInfo): Promise<string>;
}
+2 -2
View File
@@ -7,8 +7,8 @@ export interface IRoom {
export interface IRoomService {
findById(uid: string): Promise<IRoom>;
findRoomNumber(roomNumber: number): Promise<IRoom>;
findByRoomNumber(roomNumber: number): Promise<boolean>;
findRoomNumber(roomNumber: string): Promise<IRoom>;
findByRoomNumber(roomNumber: string): Promise<boolean>;
add(isShort: boolean, smallBlind: number, time?: number): Promise<any>;
// join(roomNumber: string, userName: string): void;
// leave(roomNumber: string, message: string): void;
@@ -0,0 +1,25 @@
import { IAccountInfo } from '../IAccountInfo';
import { ILoginResult } from '../ILoginResult';
export interface IAccountService {
/**
* User login
* @param {IAccountInfo} accountInfo - account information
* @returns {Promise<ILoginResult>}
*/
login(accountInfo: IAccountInfo): Promise<ILoginResult>;
/**
* Check user exists
* @param {IAccountInfo} userInfo - user info
* @returns {Promise<boolean>}
*/
authUser(userInfo: IAccountInfo): Promise<boolean>;
/**
* User register
* @param {IAccountInfo} accountInfo - account information
* @returns {Promise<string>}
*/
register(accountInfo: IAccountInfo): Promise<string>;
}
@@ -1,5 +1,5 @@
import { IAccountInfo } from './IAccountInfo';
import { IUser } from './IUser';
import { IAccountInfo } from '../IAccountInfo';
import { IUser } from '../IUser';
export interface IUserService {
findById(uid: string): Promise<IUser>;
+51 -43
View File
@@ -13,62 +13,70 @@ export default class BaseSocketController extends Controller {
public jwt: any = this.app.jwt;
public message = this.ctx.args[0] || {};
async getUserInfo() {
protected async getUserInfo() {
const { token } = this.query;
const user: IPlayer = this.jwt.verify(token) && this.jwt.verify(token).user;
return user;
}
async getRoomInfo(): Promise<IRoomInfo> {
protected async getRoomInfo(): Promise<IRoomInfo> {
const { room } = this.query;
const roomInfo = this.gameRooms.find((gr: IGameRoom) => gr.number === room);
return roomInfo.roomInfo;
}
async updateGameInfo() {
const roomInfo = await this.getRoomInfo();
console.log(roomInfo, 'roomInfo ===============================');
this.nsp.adapter.clients([ this.roomNumber ], (err: any, clients: any) => {
if (roomInfo.game && roomInfo.game.status < 6 || (roomInfo.game?.status === 6 && roomInfo.game.playerSize === 1)) {
roomInfo.players.forEach(p => {
const currPlayer = roomInfo.game &&
roomInfo.game.getPlayers().find(player => player.userId === p.userId);
p.counter = currPlayer?.counter || p.counter;
p.type = currPlayer?.type || '';
p.status = currPlayer ? 1 : p.status === -1 ? -1 : 0;
p.actionCommand = currPlayer && currPlayer.actionCommand || '';
p.actionSize = currPlayer && currPlayer.actionSize || 0;
});
console.log(roomInfo.players, 'roomInfo.players ===============================333');
const gameInfo = {
players: roomInfo.players.map(p => {
const currPlayer = roomInfo.game?.allPlayer.find(player => player.userId === p.userId);
return Object.assign({}, {
counter: currPlayer?.counter || p.counter,
actionSize: currPlayer?.actionSize || 0,
actionCommand: currPlayer?.actionCommand || '',
nickName: p.nickName,
type: currPlayer?.type || '',
status: p.status || 0,
userId: p.userId,
buyIn: p.buyIn || 0,
}, {});
}),
pot: roomInfo.game.pot,
prevSize: roomInfo.game.prevSize,
sitList: roomInfo.sit,
currPlayer: {
userId: roomInfo.game.currPlayer.node.userId,
},
};
// 广播信息
this.nsp.to(this.roomNumber).emit('online', {
protected adapter(type: string, actionName: string, data: any) {
return new Promise(resolve => {
this.nsp.adapter.clients([ this.roomNumber ], (err: any, clients: any) => {
this.nsp.to(this.roomNumber).emit(type, {
clients,
action: 'gameInfo',
action: actionName,
target: 'participator',
data: gameInfo,
data,
});
}
resolve();
});
});
}
protected async updateGameInfo() {
const roomInfo = await this.getRoomInfo();
console.log(roomInfo, 'roomInfo ===============================');
if (roomInfo.game && roomInfo.game.status < 6 || (roomInfo.game?.status === 6 && roomInfo.game.playerSize === 1)) {
roomInfo.players.forEach(p => {
const currPlayer = roomInfo.game &&
roomInfo.game.getPlayers().find(player => player.userId === p.userId);
p.counter = currPlayer?.counter || p.counter;
p.type = currPlayer?.type || '';
p.status = currPlayer ? 1 : p.status === -1 ? -1 : 0;
p.actionCommand = currPlayer && currPlayer.actionCommand || '';
p.actionSize = currPlayer && currPlayer.actionSize || 0;
});
console.log(roomInfo.players,
'roomInfo.players ===============================333');
const gameInfo = {
players: roomInfo.players.map(p => {
const currPlayer = roomInfo.game?.allPlayer.find(
player => player.userId === p.userId);
return Object.assign({}, {
counter: currPlayer?.counter || p.counter,
actionSize: currPlayer?.actionSize || 0,
actionCommand: currPlayer?.actionCommand || '',
nickName: p.nickName,
type: currPlayer?.type || '',
status: p.status || 0,
userId: p.userId,
buyIn: p.buyIn || 0,
}, {});
}),
pot: roomInfo.game.pot,
prevSize: roomInfo.game.prevSize,
sitList: roomInfo.sit,
currPlayer: {
userId: roomInfo.game.currPlayer.node.userId,
},
};
await this.adapter('online', 'gameInfo', gameInfo);
}
}
}
+2 -2
View File
@@ -1,9 +1,9 @@
import BaseService from '../lib/baseService';
import { Context, inject, provide, plugin, config } from 'midway';
import { IAccountInfo } from '../interface/IAccountInfo';
import { IAccountService } from '../interface/IAccountService';
import { IAccountService } from '../interface/service/IAccountService';
import { ILoginResult } from '../interface/ILoginResult';
import { IUserService } from '../interface/IUserService';
import { IUserService } from '../interface/service/IUserService';
import { IUser } from '../interface/IUser';
@provide('AccountService')
+2 -3
View File
@@ -1,9 +1,8 @@
import BaseService from '../lib/baseService';
import { Context, inject, provide, plugin } from 'midway';
import { IRoom } from '../interface/IRoom';
import { IRoom, IRoomService } from '../interface/IRoom';
@provide('RoomService')
export class RoomService extends BaseService {
export default class RoomService implements IRoomService {
@inject()
ctx: Context;
+1 -1
View File
@@ -1,6 +1,6 @@
import { Context, inject, provide, plugin } from 'midway';
import { IUser } from '../interface/IUser';
import { IUserService } from '../interface/IUserService';
import { IUserService } from '../interface/service/IUserService';
import { IAccountInfo } from '../interface/IAccountInfo';
@provide('UserService')
+47 -25
View File
@@ -7,7 +7,7 @@ describe('test/app/core/pokerGame.test.ts', () => {
const users: IPlayer[] = [
{
userId: '1',
counter: 1000,
counter: 380,
nickName: '1',
account: '1',
socketId: '1',
@@ -20,7 +20,7 @@ describe('test/app/core/pokerGame.test.ts', () => {
},
{
userId: '2',
counter: 200,
counter: 597,
nickName: '2',
account: '2',
socketId: '2',
@@ -33,7 +33,7 @@ describe('test/app/core/pokerGame.test.ts', () => {
},
{
userId: '3',
counter: 1000,
counter: 414,
nickName: '3',
account: '3',
socketId: '3',
@@ -44,19 +44,32 @@ describe('test/app/core/pokerGame.test.ts', () => {
status: 0,
type: '',
},
{
userId: '4',
counter: 1000,
nickName: '4',
account: '4',
socketId: '4',
buyIn: 0,
reBuy: 0,
actionSize: 0,
actionCommand: '',
status: 0,
type: '',
},
// {
// userId: '4',
// counter: 342,
// nickName: '4',
// account: '4',
// socketId: '4',
// buyIn: 0,
// reBuy: 0,
// actionSize: 0,
// actionCommand: '',
// status: 0,
// type: '',
// },
// {
// userId: '5',
// counter: 556,
// nickName: '5',
// account: '5',
// socketId: '5',
// buyIn: 0,
// reBuy: 0,
// actionSize: 0,
// actionCommand: '',
// status: 0,
// type: '',
// },
];
/**
@@ -211,8 +224,8 @@ describe('test/app/core/pokerGame.test.ts', () => {
it('one player allin', async () => {
const game = new PokerGame({
smallBlind: 1,
users,
isShort: false,
users,
actionRoundComplete: () => {
if (game.status < 6) {
game.startActionRound();
@@ -225,16 +238,25 @@ describe('test/app/core/pokerGame.test.ts', () => {
game.play();
// pre flop
console.log('curr----------------------------1', game.currPlayer);
game.action('call'); // utg 1000
console.log('curr----------------------------2', game.currPlayer);
game.action('call'); // d 100
// game.action('fold'); // utg
// console.log('curr----------------------------2', game.currPlayer);
game.action('raise:6'); // co
game.action('call'); // D
game.action('call'); // sb
game.action('check'); // bb
// game.action('call'); // bb
game.action('check'); // sb
game.action('raise:10'); // utg
game.action('call'); // d
game.action('call'); // sb
game.action('fold'); // bb
game.action('check'); // bb
// game.action('check'); // bb
game.action('raise:13'); // d
game.action('fold'); // sb
// game.action('fold'); // bb
game.action('call'); // bb
game.action('check'); // bb
game.action('raise:45'); // bb
console.log(game.pot, 'pot');
game.action('call'); // bb
console.log(game.commonCard);
console.log(game.pot, 'pot');
// // console.log('curr----------------------------3', game.currPlayer);
// game.action('check'); // BB 200
// game.action('check'); // utg
+2 -2
View File
@@ -61,8 +61,8 @@ describe('test/app/core/pokerStyle.test.ts', () => {
assert.strictEqual(pokerStyle.getPokerWeight() , '000000000miged')
});
it('compare card', async () => {
let pokerStyle: PokerStyle = new PokerStyle(['k2','g3','i2','h4','j3', 'm1', 'l1'], true)
let pokerStyle2: PokerStyle = new PokerStyle(['k2','g3','i2','h4','j3','h1', 'h2'], true)
let pokerStyle: PokerStyle = new PokerStyle(['g4','g2', 'l3', 'l2', 'c1', 'i2', 'm3'])
let pokerStyle2: PokerStyle = new PokerStyle(['g4','g2', 'l3', 'l2', 'c1', 'c2', 'm3'])
console.log('getPokerValueCard', pokerStyle.getPokerValueCard())
assert.strictEqual(pokerStyle.getPokerWeight() , pokerStyle2.getPokerWeight())
});