UNPKG

@ledinhhoankhai/bcr-algorithm

Version:

Clean & Optimized Algorithm Logic

2 lines (1 loc) 6.34 kB
"use strict";class Baccarat{static CONSTANTS={MIN_BET:1e4,MAX_BET:2e7,RATE:.1,CHIP_VALUES:[5e3,1e4,25e3,5e4,1e5,5e5],ACTION_TYPES:{CHIPS:"Chips",UNDO:"Undo",X2:"X2",DOUBLE:"Double",REBET:"Rebet"}};constructor(){this.serverBet={},this.userActions=[],this.lastRoundBets={},this.min=Baccarat.CONSTANTS.MIN_BET,this.max=Baccarat.CONSTANTS.MAX_BET,this.rate=Baccarat.CONSTANTS.RATE,this.chipValues=[...Baccarat.CONSTANTS.CHIP_VALUES],this.actionTypes={...Baccarat.CONSTANTS.ACTION_TYPES},this.history=[],this.userBet={},this.historyCleared=[],this._initializeState()}_initializeState(){this.userActions=[],this.serverBet={},this.lastRoundBets={}}onRequestBet(request){this._logRequestStart(request.id);const result=this._processRequest(request);return this._logRequestResult(result),this._logRequestEnd(request.id),result}resetForNewRound(){this._saveLastRoundBets(),this._resetCurrentState()}getDebugInfo(){return{serverBet:{...this.serverBet},userActions:this.userActions.length,lastRoundBets:{...this.lastRoundBets},userBetCalculated:this._calculateUserBetFromActions()}}_processRequest(request){const previousServerBet=this._cloneObject(this.serverBet);if(!this._executeAction(request))return!1;const newServerBet=this._calculateServerBetFromActions();return this._isEqual(previousServerBet,newServerBet)?this._handleNoChange(request):(this.serverBet={...newServerBet},this._handleStateChange(request,previousServerBet,newServerBet))}_executeAction(request){switch(request.args.action.name){case this.actionTypes.CHIPS:return this._executeChipsAction(request.args.action.chips);case this.actionTypes.UNDO:return this._executeUndoAction();case this.actionTypes.X2:case this.actionTypes.DOUBLE:return this._executeDoubleAction();case this.actionTypes.REBET:return this._executeRebetAction();default:return!1}}_executeChipsAction(chips){return!(!chips||"object"!=typeof chips)&&(this.userActions.push({type:"chips",chips:{...chips}}),!0)}_executeUndoAction(){if(0===this.userActions.length)return!1;const lastAction=this.userActions[this.userActions.length-1];return"double_end"===lastAction.type?(this._undoDoubleGroup(lastAction.id),!0):this._isInsideDoubleGroup()?(this._undoToDoubleBegin(),!0):(this.userActions.pop(),!0)}_executeDoubleAction(){if(0===this.userActions.length)return!1;const doubleId=this._generateDoubleId();return this.userActions.push({type:"double_begin",id:doubleId,timestamp:Date.now()}),this._duplicateCurrentActions(),this.userActions.push({type:"double_end",id:doubleId,timestamp:Date.now()}),!0}_executeRebetAction(){return!(!this.lastRoundBets||0===Object.keys(this.lastRoundBets).length)&&(this.userActions.push({type:"chips",chips:{...this.lastRoundBets}}),!0)}_calculateServerBetFromActions(){const userBet=this._calculateUserBetFromActions(),serverBet={};for(const[betType,amount]of Object.entries(userBet))amount>0&&(serverBet[betType]=this._calculateServerBetAmount(amount));return serverBet}_calculateUserBetFromActions(){const userBet={};return this.userActions.forEach(action=>{if("chips"===action.type&&action.chips)for(const[betType,amount]of Object.entries(action.chips))userBet[betType]=(userBet[betType]||0)+(amount||0)}),userBet}_calculateServerBetAmount(userBetAmount){const amountWithRate=userBetAmount*this.rate;return amountWithRate>=this.min?Math.min(amountWithRate,this.max):userBetAmount>=this.min?this.min:userBetAmount}_handleNoChange(request){return!1}_handleStateChange(request,previousServerBet,newServerBet){const actionName=request.args.action.name;return actionName===this.actionTypes.UNDO?{undo:!0}:actionName===this.actionTypes.X2||actionName===this.actionTypes.DOUBLE?this._handleDoubleResponse(previousServerBet,newServerBet):this._calculateBetDifference(previousServerBet,newServerBet)}_handleDoubleResponse(previousServerBet,newServerBet){const userBet=this._calculateUserBetFromActions(),betToSend={};for(const[betType,newAmount]of Object.entries(newServerBet)){const difference=newAmount-(previousServerBet[betType]||0);if(difference>0){(userBet[betType]||0)/2*this.rate<this.min&&(betToSend[betType]=difference)}}return Object.keys(betToSend).length>0&&betToSend}_calculateBetDifference(previousServerBet,newServerBet){const betToSend={};for(const[betType,newAmount]of Object.entries(newServerBet)){const difference=newAmount-(previousServerBet[betType]||0);difference>0&&(betToSend[betType]=difference)}return betToSend}_generateDoubleId(){return`double_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}_isInsideDoubleGroup(){let doubleDepth=0;for(let i=this.userActions.length-1;i>=0;i--){const action=this.userActions[i];if("double_end"===action.type)doubleDepth++;else if("double_begin"===action.type&&(doubleDepth--,doubleDepth<0))return!0}return!1}_undoDoubleGroup(doubleId){const beginIndex=this._findDoubleBeginIndex(doubleId);-1!==beginIndex&&(this.userActions=this.userActions.slice(0,beginIndex))}_undoToDoubleBegin(){for(let i=this.userActions.length-1;i>=0;i--)if("double_begin"===this.userActions[i].type){this.userActions=this.userActions.slice(0,i);break}}_findDoubleBeginIndex(doubleId){for(let i=0;i<this.userActions.length;i++)if("double_begin"===this.userActions[i].type&&this.userActions[i].id===doubleId)return i;return-1}_duplicateCurrentActions(){const actionsToDouble=[];this.userActions.forEach(action=>{"chips"===action.type&&actionsToDouble.push({type:"chips",chips:{...action.chips},duplicated:!0})}),this.userActions.push(...actionsToDouble)}_saveLastRoundBets(){this.lastRoundBets={...this._calculateUserBetFromActions()}}_resetCurrentState(){this.serverBet={},this.userActions=[],this.history=[],this.userBet={}}_cloneObject(obj){return JSON.parse(JSON.stringify(obj))}_isEqual(obj1,obj2){return JSON.stringify(obj1)===JSON.stringify(obj2)}_logRequestStart(requestId){}_logRequestResult(result){!1===result||result&&result.undo}_logRequestEnd(requestId){}handleUserBet(){return this._calculateUserBetFromActions()}calculateServerBetFromActions(){return this._calculateServerBetFromActions()}handleCleanHistory(){return[]}mergeBetToServerBet(bet){for(const[betType,amount]of Object.entries(bet))this.serverBet[betType]=(this.serverBet[betType]||0)+(amount||0);return this.serverBet}_pickChipValue(serverBet){return serverBet||{}}_isWithinBettingLimits(betAmount){return betAmount>=this.min&&betAmount<=this.max}}module.exports=Baccarat;