Files
winapp/BacDPThread.cpp
2026-06-12 22:37:02 +08:00

496 lines
14 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#include <time.h>
#pragma hdrstop
#include "BacDPThread.h"
#include "GlobalUnit.h"
#include "GameUnit.h"
#include "UtilityUnit.h"
#include "TableUnit.h"
//#include "ActiveFormUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//软件过期时间
#define TM_ABORT 125000
void __fastcall WriteData( char* msg )
{
SYSTEMTIME st;
GetLocalTime(&st);
char szDataFile[256];
sprintf( szDataFile, "%s/data/%04d%02d%02d.txt", g_AppPath, st.wYear, st.wMonth, st.wDay);
// FILE* fp = NULL;
// if(!FileExists(szDataFile)){
// fp = fopen(szDataFile, "w");
// if(fp)
// fprintf( fp, "时间,台桌,手数,结果\n" );
// }
// else{
// fp = fopen(szDataFile, "a");
// }
FILE* fp = fopen(szDataFile, "r+");
if(!fp){
fp = fopen(szDataFile, "w");
if(fp)
fprintf( fp, "时间,台桌,手数,结果\n" );
}
else
fseek(fp, 0, SEEK_END);
if( fp ){
fprintf( fp, "%02d:%02d:%02d,%s\n", st.wHour, st.wMinute, st.wSecond, msg );
fclose( fp );
}
else{
g_bBacData = false;
ShowMessage("导出数据失败! errno=" + IntToStr((int)GetLastError()));
}
}
//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// TBetWayThread
__fastcall TDataParseThread::TDataParseThread()
{
m_hDataEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
// m_tmGST = 0;
// m_tmExpire = GetCompileTime() + 30 * 86400; //编译时间后30天过期
}
//---------------------------------------------------------------------------
__fastcall TDataParseThread::~TDataParseThread()
{
CloseHandle( m_hDataEvent );
}
//---------------------------------------------------------------------------
void __fastcall TDataParseThread::Reset()
{
WaitForSingleObject(m_hDataEvent, 5000);
m_aData.clear();
SetEvent(m_hDataEvent);
}
//---------------------------------------------------------------------------
void __fastcall TDataParseThread::ParseData(String sData)
{
WaitForSingleObject(m_hDataEvent, 5000);
m_aData.push_back(sData);
SetEvent(m_hDataEvent);
Suspended = false;
}
//---------------------------------------------------------------------------
void __fastcall TDataParseThread::Execute()
{
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); //关闭系统休眠
while( !Terminated ){
while(m_aData.size()>0){
String sData = m_aData[0];
// if(sData.Length()<3){
// WaitForSingleObject(m_hDataEvent, 5000);
// m_aData.erase(m_aData.begin());
// SetEvent(m_hDataEvent);
// continue;
// }
// DebugPrint(((AnsiString)sData).c_str());
TStringDynArray arr = SplitString( sData, "|" );
if(arr.Length<2){
WaitForSingleObject(m_hDataEvent, 5000);
m_aData.erase(m_aData.begin());
SetEvent(m_hDataEvent);
continue;
}
int iType = arr[0].ToInt();
if( iType==0 ){ //连接异常断开
DebugPrint("连接异常断开");
int reason = arr[1].ToInt();
PostMessage( Application->MainFormHandle, UM_WEBDEAD, reason, 0 );
}
else if( iType==1 ){ //初始化所有台桌
DebugPrint("!!! init all tables");
g_aGames.Init(arr[1]);
PostMessage( Application->MainFormHandle, UM_ADDTABLE, 0, 0 );
}
else if( iType==2 ){ //台桌Roadmap
if(!g_aGames.empty() && arr[1].Length()){
int iG = Vid2Gid(arr[1]);
TGame* pGame = NULL;
int ind = g_aGames.FindGame(iG, pGame);
if(!pGame && iG>0){
pGame = g_aGames.NewGame(iG, arr[g_iPlatform==PF_PA ? 1 : 2], ind);
PostMessage( Application->MainFormHandle, UM_ADDTABLE, ind, (long)pGame );
}
if(pGame){
int oldSize = pGame->aRes.size(),
newSize = arr[3].Length();
if(oldSize!=newSize && oldSize!=newSize+1){
#ifdef _DEBUG
if(newSize && oldSize && (oldSize>newSize || oldSize<newSize-1)){
char res[128];
for(int i=0; i<oldSize; i++){
res[i] = pGame->aRes[i] + '0';
}
res[oldSize] = 0;
DebugPrint("!!! %s road size %d -> %d with map: %s -> %s",
((AnsiString)pGame->vid).c_str(),
// ((AnsiString)arr[1]).c_str(),
oldSize, newSize, res,
((AnsiString)arr[3]).c_str());
}
#endif
if(g_bGameOn && pGame->bRun)
pGame->AutoBetOff();
if(newSize==oldSize+1){
int wt = arr[3][newSize]-'0';
if(wt==0) wt = 3;
pGame->aRes.push_back(wt);
pGame->winCount[wt-1]++;
pGame->BuildRoadmap(wt);
}
else{
pGame->ClearResults();
for(int i=1; i<=newSize; i++){
int wt = arr[3][i]-'0';
if(wt==0) wt = 3;
pGame->aRes.push_back(wt);
pGame->winCount[wt-1]++;
pGame->BuildRoadmap(wt);
}
}
bool bUpdateRoad = true;
if(pGame->gmstatus==12){ //维护台桌
if(oldSize && !newSize) //新局
pGame->AutoBetOn(); //台桌维护中无法正常处理shuffle状态,调用该接口显示和处理新局
}
else{ //正常台桌
pGame->gmstatus = 0; //设置结算状态,避免重复计算
// pGame->gmcode = "";
if(oldSize<newSize){
pGame->HandleResult(oldSize+1==newSize ? 0 : 1); //0=正常处理 1=异常处理
bUpdateRoad = false;
}
}
if(bUpdateRoad && pGame->hTable)
PostMessage(pGame->hTable, UM_TAB_UPDATE, UPDATE_ROAD, 0);
}
}
}
}
else if( iType==3 ){ //台桌状态
// 3 | vid | gmcode | wintype(timeout)
if(!g_aGames.empty() && arr.Length>=4){
int iG = Vid2Gid(arr[1]);
TGame* pGame = NULL;
int ind = g_aGames.FindGame(iG, pGame);
if(!pGame && iG>0){
pGame = g_aGames.NewGame(iG, arr[g_iPlatform==PF_PA ? 1 : 2], ind);
PostMessage( Application->MainFormHandle, UM_ADDTABLE, ind, (long)pGame );
}
if( pGame ){
String gmcode = arr[3];
int status = arr[4].ToInt();
bool bNewStatus = pGame->gmstatus != status,
bNewCode = pGame->gmcode != gmcode;
if(!bNewCode && bNewStatus || bNewCode && (g_iPlatform!=PF_PA
|| gmcode=="" || gmcode > pGame->gmcode)){
#ifdef _DEBUG
if( bNewCode && status!=1 && status<11 && (g_iPlatform!=PF_AB || status!=0) && pGame->gmcode.Length()){
DebugPrint("!!! %s gmcode %s -> %s with status: %d",
((AnsiString)pGame->vid).c_str(),
// ((AnsiString)arr[1]).c_str(),
((AnsiString)pGame->gmcode).c_str(),
((AnsiString)gmcode).c_str(),
status);
}
#endif
if(bNewCode)
pGame->gmcode = gmcode;
// pGame->timeout = 0;
if(bNewStatus && pGame->gmstatus==1){
pGame->ManualBetOff();
if(g_bGameOn && pGame->bRun)
pGame->AutoBetOff();
}
if(status==0 && !bNewCode){ //结算
#ifdef _DEBUG
if(pGame->gmstatus!=2 && (g_iPlatform!=PF_AB || pGame->gmstatus!=11))
DebugPrint("!!! %s status %d -> %d",
((AnsiString)pGame->vid).c_str(),
// ((AnsiString)arr[1]).c_str(),
pGame->gmstatus, status);
#endif
pGame->gmstatus = status;
if(arr.Length>=8){ //DB特殊处理
if(arr[6].Length()){
pGame->bcard = UnifyCard(arr[6]);
pGame->pcard = UnifyCard(arr[7]);
}
else
pGame->bcard = pGame->pcard = "";
}
int wt = 0;
if(arr.Length>=6 && arr[5].Length()){
wt = arr[5][1]-'0';
if(wt==0) wt = 3;
}
if(wt>0){
pGame->aRes.push_back(wt);
pGame->winCount[wt-1]++;
pGame->BuildRoadmap(wt);
pGame->HandleResult();
if(g_bBacData){
char data[128];
sprintf(data, "%s,%d,%s",
((AnsiString)arr[g_iPlatform==PF_PA ? 1 : 2]).c_str(),
pGame->aRes.size(), wt==1 ? "庄" : wt==2 ? "闲" : "和");
WriteData( data );
}
}
}
else if(status==1 && bNewStatus){// && pGame->gmstatus!=2){ //开始下注
#ifdef _DEBUG
if(pGame->gmstatus!=0 && pGame->gmstatus<11)
DebugPrint("!!! %s status %d -> %d",
((AnsiString)pGame->vid).c_str(),
// ((AnsiString)arr[1]).c_str(),
pGame->gmstatus, status);
#endif
if(bNewStatus && bNewCode && pGame->iState==ST_BETTED){
DebugPrint("!!! %s status %d -> %d with betted",
((AnsiString)pGame->vid).c_str(),
// ((AnsiString)arr[1]).c_str(),
pGame->gmstatus, status);
pGame->HandleResult(2);
}
pGame->gmstatus = status;
pGame->timeout = g_iPlatform==PF_AB ? pGame->countdown
: g_iPlatform==PF_DB ? arr[5].ToInt() / 1000
: arr[5].ToInt();
pGame->AutoBetOn();
}
else if(status==2 && !bNewCode){// && pGame->gmstatus==1 ){ //开牌中
#ifdef _DEBUG
if(pGame->gmstatus!=1)
DebugPrint("!!! %s status %d -> %d",
((AnsiString)pGame->vid).c_str(),
// ((AnsiString)arr[1]).c_str(),
pGame->gmstatus, status);
#endif
pGame->gmstatus = status;
if(pGame->iState==ST_BETTED)
pGame->timeout = -1; //开始计算超时
pGame->bcard = pGame->pcard = "";
}
else if((status==11 || status==12) && bNewStatus){ //洗牌/维护
if(pGame->iState==ST_BETTED || pGame->iState==ST_EXPIRED){ //超时
DebugPrint("!!! %s status %d -> %d with betted",
((AnsiString)pGame->vid).c_str(),
// ((AnsiString)arr[1]).c_str(),
pGame->gmstatus, status);
pGame->HandleResult(status==12 ? 3 : 2);
}
pGame->gmstatus = status;
if(status==11){
pGame->Shuffle();
if(g_bBacData){
char data[128];
sprintf(data, "%s,,%s",
((AnsiString)arr[g_iPlatform==PF_PA ? 1 : 2]).c_str(),
"洗牌");
WriteData( data );
}
}
else{
pGame->iState = ST_INIT;
#ifdef _DEBUG
DebugPrint("!!! %s 台桌维护中", ((AnsiString)pGame->vid).c_str());//, ((AnsiString)arr[1]).c_str());
SendMessage( Application->MainFormHandle, UM_RESTORE, 0, 0 );
#endif
}
}
if(pGame->hTable)
PostMessage(pGame->hTable, UM_TAB_UPDATE, UPDATE_STATUS, 0);
}
}
}
}
else if(iType==4){ //多台状态
//4 | e.payload.vid
DebugPrint("Enter HALL: %s", ((AnsiString)arr[1]).c_str());
int tab = 2;
if(g_iPlatform==PF_PA){
tab = arr[1]=="LINK" ? 1 : arr[1]=="LOBB" ? 0 : 2;
}
else if(g_iPlatform==PF_AB){
int hId = arr[1].ToInt();
tab = hId==102 ? 1 : hId==100 ? 0 : 2;
}
else if(g_iPlatform==PF_DB){
int hId = arr[1].ToInt();
tab = hId==2 ? 1 : hId==0 ? 0 : 2;
}
PostMessage(Application->MainFormHandle, UM_ENTER_TABLE, tab, 0);
}
else if(iType==5){ //账户余额
//5 | e.val
double amo;
if(TryStrToFloat(arr[1], amo)){
if(!(g_bTesting && g_settings.bSimAccOn)){
g_fBalance = amo;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_BALANCE, 0);
}
}
}
else if(iType==6){ //下注反馈
//6 | vid | retCode | gmcode | 庄 | 闲 | 平
if(!g_aGames.empty() && arr[1].Length()){
int iG = Vid2Gid(arr[1]);
TGame* pGame = NULL;
int ind = g_aGames.FindGame(iG, pGame);
if(pGame && pGame->gmcode==arr[3]){
int chips[3] = {0};
chips[0] = arr[4].ToInt();
chips[1] = arr[5].ToInt();
chips[2] = arr[6].ToInt();
int retCode = arr[2].ToInt();
if(retCode!=0){
if(g_iPlatform==PF_AB) //欧博错误码转换
retCode = retCode==101 ? 10 //限红低
: retCode==102 ? 11 //限红高
: retCode==103 || retCode==100015 || retCode==6044 ? 25 //超时
: retCode==10101 || retCode==6035 || retCode==6042 ? 26 //余额不足
: -1;
else if(g_iPlatform==PF_DB) //多宝错误码转换
retCode = retCode==210010 ? 10 //限红低
: retCode==220030 ? 11 //限红高
: retCode==220004 || retCode==220006 || retCode==110041 ? 25 //超时
: retCode==10469 || retCode==20126 ? 26 //余额不足
: retCode;
}
pGame->BetResp(retCode, chips);
}
}
}
else if(iType==7){ //限额
//7 | min | max
int minBet, maxBet;
if(TryStrToInt(arr[1], minBet) && TryStrToInt(arr[2], maxBet)){
if(minBet!=g_MinOnBet || maxBet!=g_MaxOnBet){
g_MinOnBet = minBet;
g_MaxOnBet = maxBet;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_LIMIT, 0);
}
}
}
else if(iType==8){ //倒计时
//8 | countdownList ABG专用
if(!g_aGames.empty() && arr[1].Length()){
g_aGames.SetCountDown(arr[1]);
}
}
else if(iType==9){ //翻牌
//9 | gid | gmcode | bcard | pcard
if(!g_aGames.empty() && !arr[1].IsEmpty() && (!arr[3].IsEmpty() || !arr[4].IsEmpty())){
int iG = Vid2Gid(arr[1]);
TGame* pGame = NULL;
int ind = g_aGames.FindGame(iG, pGame);
if(pGame && pGame->gmstatus==2 && pGame->gmcode==arr[2]){
pGame->bcard = UnifyCard(arr[3]);
pGame->pcard = UnifyCard(arr[4]);
if(pGame->hTable)
PostMessage(pGame->hTable, UM_TAB_UPDATE, UPDATE_STATUS, 0);
if(pGame->iState==ST_BETTED)
pGame->timeout = -1; //重新计算超时
}
}
}
// else if(iType==10){ //撤销注单
// //10 | gid | gmcode
// if(!g_aGames.empty() && arr[1].Length()){
// int iG = Vid2Gid(arr[1]);
// TGame* pGame = NULL;
// int ind = g_aGames.FindGame(iG, pGame);
//
// if(pGame && pGame->gmcode==arr[2]){
// DebugPrint("!!! %s 撤销注单 with status: %d",
// ((AnsiString)pGame->vid).c_str(),
//// ((AnsiString)arr[1]).c_str(),
// pGame->gmstatus);
// pGame->gmstatus = 0;
// pGame->HandleResult(3);
// }
// }
// }
m_aData[0] = "";
if( Terminated )
break;
WaitForSingleObject(m_hDataEvent, 5000);
m_aData.erase(m_aData.begin());
SetEvent(m_hDataEvent);
}
// 等待数据
if( !Terminated )
Suspended = true;
};
SetThreadExecutionState( ES_CONTINUOUS );//打开系统休眠
}
//---------------------------------------------------------------------------