DBBackup.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:26k
源码类别:

模拟服务器

开发平台:

C/C++

  1. // DBBackup.cpp: implementation of the CDBBackup class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "DBTABLE.H"
  6. #include "DBBackup.h"
  7. #include "DBDumpLoad.h"
  8. #include <FSTREAM>
  9. #include <direct.h>
  10. #include "Macro.h"
  11. #include "CRC32.h"
  12. using namespace std;
  13. #define IS_OUTPUT_LOG true
  14. #define ROLE_FILTER_FILE "RoleFilter.ini"
  15. #define ROLE_FILTER_COUNT 300
  16. static char DBPath[32] = {0}; //数据库目录
  17. static char DBName[32] = {0}; //数据库名
  18. static ZDBTable* RunTable = NULL;
  19. static bool IsBackupWorking = false; //是否正在备份
  20. static bool IsThreadWorking = false; //线程是否在工作
  21. static bool IsSuspended = false; //线程是否挂起
  22. static WORD BackupTime = 0; //备份间隔时间
  23. static bool IsTimeToBackup = true;
  24. static CDBBackup::TStatData oldGameStatData;//旧的游戏统计数据
  25. static CDBBackup::TStatData newGameStatData;//新的游戏统计数据
  26. static TGAME_STAT_DATA SendStatData; //取得发送给客户端的统计数据结构
  27. int CDBBackup::GetIndexByName(char* aName, TRoleList* aList, int aListSize)
  28. {
  29. if(aList[0].Name[0] == '') return -1;
  30. for(int i=0;i<aListSize;++i)
  31. {
  32. if(aList[i].Name[0] == '') return -1;
  33. if (strcmp(aName, aList[i].Name) == 0)
  34. return i;
  35. }
  36. return -1;
  37. }
  38. CDBBackup::TRoleList* CDBBackup::GetMin(
  39. TRoleList* const aRoleList,
  40. const int n,
  41. const StatType aType)
  42. {//查找出列表中钱/级别(或其他)最少的一个元素
  43. TRoleList* tmpData;
  44. tmpData = &aRoleList[0];
  45. while(true)
  46. {
  47. for(int i=0;i<n;++i)
  48. {
  49. if(aRoleList[i].Name[0] == '')
  50. return &aRoleList[i];
  51. int aSourse, aDest;
  52. switch(aType)
  53. {
  54. case stMoney:
  55. aDest = tmpData->Money;
  56. aSourse = aRoleList[i].Money;
  57. break;
  58. case stLevel:
  59. aDest = tmpData->Level;
  60. aSourse = aRoleList[i].Level;
  61. break;
  62. case stKiller:
  63. aDest = tmpData->KillNum;
  64. aSourse = aRoleList[i].KillNum;
  65. break;
  66. }
  67. if(aDest > aSourse)
  68. {
  69. tmpData = &aRoleList[i];
  70. break;
  71. }
  72. }
  73. if(i==n)break;
  74. }
  75. return tmpData;
  76. }
  77. void CDBBackup::ListSort(
  78. TRoleList* const aRoleList,
  79. const int n,
  80. const StatType aType)
  81. {//对列表做特定的排序
  82. int i,j;
  83. for(i=0;i<n;++i)
  84. {
  85. TRoleList* tmpData = &aRoleList[i];
  86. for(j=i+1;j<n;++j)
  87. {
  88. __int64 aSourse, aDest;
  89. switch(aType)
  90. {
  91. case stMoney:
  92. aDest = tmpData->Money;
  93. aSourse = aRoleList[j].Money;
  94. break;
  95. case stLevel:
  96. aDest = (__int64)tmpData->Level * 0xffffffff + (__int64)tmpData->FightExp;
  97. aSourse = (__int64)aRoleList[j].Level * 0xffffffff + (__int64)aRoleList[j].FightExp;
  98. break;
  99. case stKiller:
  100. aDest = tmpData->KillNum;
  101. aSourse = aRoleList[j].KillNum;
  102. break;
  103. }
  104. if( aSourse > aDest )
  105. swap(*tmpData, aRoleList[j]);
  106. }
  107. }
  108. }
  109. void CDBBackup::RoleDataCopy(TRoleList* Desc, TRoleData* Source)
  110. {//把RoleData有用的结构复制到RoleList结构中
  111. //strcpy(Desc->Account, Source->BaseInfo.caccname);
  112. strcpy(Desc->Name, Source->BaseInfo.szName);
  113. Desc->Sect = Source->BaseInfo.nSect;
  114. Desc->Money = Source->BaseInfo.imoney + Source->BaseInfo.isavemoney;
  115. Desc->Level = Source->BaseInfo.ifightlevel;
  116. Desc->KillNum = Source->BaseInfo.nKillPeopleNumber;
  117. Desc->FightExp = Source->BaseInfo.fightexp;
  118. }
  119. char* CDBBackup::LoadFilterName()
  120. {//取得要过滤的用户名列表 二维数组 [最大名字长度20][数目]
  121. char* aRoleList = new char[ROLE_FILTER_COUNT * 20];
  122. char aBuffer[20];
  123. char aAppPath[MAX_PATH] = {0};
  124. getcwd(aAppPath,MAX_PATH);
  125. strcat(aAppPath,"\");
  126. strcat(aAppPath,ROLE_FILTER_FILE);
  127. fstream aFile(aAppPath,ios::in);
  128. if(!aFile.is_open())
  129. {
  130. SAFE_DELETE_ARRAY(aRoleList);
  131. return NULL;
  132. }
  133. for(int i=0;i<ROLE_FILTER_COUNT;++i)
  134. {
  135. aFile.getline(aBuffer, 20);
  136. if(!aBuffer[0])break;
  137. int aLen = strlen(aBuffer);
  138. strcpy(&aRoleList[i * 20],aBuffer);
  139. aRoleList[i *20 + 19] = '';
  140. }
  141. aFile.close();
  142. return aRoleList;
  143. }
  144. bool CDBBackup::IsRoleFilter(char* aName, char* aList)
  145. {//过滤某些角色
  146. if(!aList) return false;
  147. for(int i=0;i<ROLE_FILTER_COUNT;++i)
  148. {
  149. if(aList[i * 20] == '') return false;
  150. if (strcmp(aName, &aList[i * 20]) == 0)
  151. return true;
  152. }
  153. return false;
  154. }
  155. CDBBackup::CDBBackup(char* aPath, char* aName, ZDBTable* aRunTable)
  156. {
  157. memset(DBPath,0,32);
  158. memset(DBName,0,32);
  159. strcpy(DBPath, aPath);
  160. strcpy(DBName, aName);
  161. BackupTime = 0;
  162. m_hThread = NULL;
  163. m_hManualThread = NULL;
  164. RunTable = aRunTable;
  165. memset(&oldGameStatData, 0, sizeof(TStatData));
  166. memset(&newGameStatData, 0, sizeof(TStatData));
  167. memset(&SendStatData, 0, sizeof(TGAME_STAT_DATA));
  168. }
  169. bool CDBBackup::Open(int aTime)
  170. {
  171. aTime = aTime % 24;
  172. if((DBPath[0] == '')||(DBName[0] == ''))
  173. return false;//初始化有问题就退出
  174. BackupTime = aTime;
  175. DWORD dwThreadId, dwThrdParam = 1;
  176. m_hThread = CreateThread(
  177. NULL,                        // no security attributes 
  178.         0,                           // use default stack size  
  179.         TimerThreadFunc,             // thread function 
  180.         &dwThrdParam,                // argument to thread function 
  181.         0,                           // use default creation flags 
  182.         &dwThreadId);                // returns the thread identifier 
  183. if(!m_hThread)
  184. {
  185. BackupTime = 0;
  186. return false;//创建线程失败
  187. }
  188. char aAppPath[MAX_PATH] = {0};
  189. getcwd(aAppPath,MAX_PATH);
  190. strcat(aAppPath,"\StatData.dat");
  191. //读取旧排名
  192. memset(&newGameStatData,0,sizeof(CDBBackup::TStatData));
  193. FILE* aStatFile = fopen(aAppPath,"rb");
  194. if(aStatFile)
  195. {
  196. int a = fread(&newGameStatData, 1, sizeof(CDBBackup::TStatData), aStatFile);
  197. fclose(aStatFile);
  198. }
  199. MakeSendStatData();
  200. return true;
  201. }
  202. bool CDBBackup::Close()
  203. {
  204. BackupTime = 0;
  205. if(m_hManualThread) CloseHandle( m_hManualThread );
  206. return (CloseHandle( m_hThread ) == TRUE);
  207. }
  208. bool CDBBackup::Suspend()
  209. {
  210. if(!m_hThread) return false; //如果线程没有初始化好就不能挂起
  211. if(!IsThreadWorking) return false; //如果线程没有开始就不能挂起
  212. if(IsBackupWorking) return false; //如果正在备份就中止挂起
  213. if(IsSuspended) return false; //如果正在备份就中止挂起
  214. if(SuspendThread(m_hThread) == -1)return false;
  215. IsSuspended = true;
  216. return true;
  217. }
  218. bool CDBBackup::Resume()
  219. {//继续执行线程
  220. if(!m_hThread) return false; //如果线程没有初始化好就不能挂起
  221. if(!IsSuspended) return false; //如果正在备份就中止挂起
  222. if(!IsThreadWorking) return false; //如果线程没有开始就不能继续执行线程
  223. if(ResumeThread(m_hThread) == -1)return false;
  224. IsSuspended = false;
  225. return true;
  226. }
  227. TGAME_STAT_DATA CDBBackup::GetSendStatData()
  228. {//取得发送给客户端的统计数据结构
  229. return SendStatData;
  230. }
  231. bool CDBBackup::IsWorking()
  232. {//线程是否在工作
  233. return IsThreadWorking;
  234. }
  235. bool CDBBackup::IsBackuping()
  236. {//备份是否在工作
  237. return IsBackupWorking;
  238. }
  239. bool CDBBackup::ManualBackup()
  240. {//手工备份
  241. if(!m_hThread) return false; //如果线程没有初始化好就不能挂起
  242. if(!IsThreadWorking) return false; //如果线程没有开始就不能继续执行线程
  243. DWORD dwThreadId, dwThrdParam = 1;
  244. m_hManualThread = CreateThread(
  245. NULL,                        // no security attributes 
  246.         0,                           // use default stack size  
  247.         ManualThreadFunc,             // thread function 
  248.         &dwThrdParam,                // argument to thread function 
  249.         0,                           // use default creation flags 
  250.         &dwThreadId);                // returns the thread identifier 
  251. if(!m_hManualThread)
  252. {
  253. BackupTime = 0;
  254. return false;//创建线程失败
  255. }
  256. return true;
  257. }
  258. DWORD WINAPI CDBBackup::TimerThreadFunc( LPVOID lpParam )
  259. {//备份计时线程
  260. IsThreadWorking = true;
  261. while(true)
  262. {
  263. SYSTEMTIME aSysTime;
  264. GetLocalTime(&aSysTime);
  265. if(aSysTime.wHour == BackupTime)
  266. {
  267. if(IsTimeToBackup) Backup();
  268. IsTimeToBackup = false;
  269. }
  270. else
  271. {
  272. IsTimeToBackup = true;
  273. }
  274. Sleep(1000 * 60 * 30);
  275. //Sleep(BackupTime);
  276. }
  277. IsThreadWorking = false;
  278. return 0;
  279. }
  280. DWORD WINAPI CDBBackup::ManualThreadFunc( LPVOID lpParam )
  281. {//手工备份线程
  282. Backup();
  283. return 0;
  284. }
  285. void CDBBackup::Backup()
  286. {
  287. IsBackupWorking = true;
  288. //打开备份状态log文件
  289. char aLogPath[MAX_PATH] = {0};
  290. getcwd(aLogPath,MAX_PATH);
  291. strcat(aLogPath,"\Backup.log");
  292. fstream aLogFile(aLogPath,ios::out);
  293. SYSTEMTIME aSysTime;
  294. GetSystemTime(&aSysTime);
  295. string aBackupDir;
  296. char aIntStr[10];
  297. itoa(aSysTime.wYear,aIntStr,10);
  298. aBackupDir = aIntStr;
  299. itoa(aSysTime.wMonth,aIntStr,10);
  300. aBackupDir += aIntStr;
  301. itoa(aSysTime.wDay,aIntStr,10);
  302. aBackupDir += aIntStr;
  303. aBackupDir += "_";
  304. itoa(aSysTime.wHour,aIntStr,10);
  305. aBackupDir += aIntStr;
  306. itoa(aSysTime.wMinute,aIntStr,10);
  307. aBackupDir += aIntStr;
  308. itoa(aSysTime.wSecond,aIntStr,10);
  309. aBackupDir += aIntStr;
  310. itoa(aSysTime.wMilliseconds,aIntStr,10);
  311. aBackupDir += aIntStr;
  312. aLogFile<<"Backup Log File Open Time:"<<aSysTime.wYear<<"."<<
  313. aSysTime.wMonth<<"."<<aSysTime.wDay<<" "<<
  314. aSysTime.wHour<<":"<<aSysTime.wMinute<<":"<<aSysTime.wSecond<<endl;
  315. int i,j;
  316. char aSavePath[MAX_PATH] = {0};
  317. getcwd(aSavePath, MAX_PATH);
  318. strcat(aSavePath,"\");
  319. strcat(aSavePath,DBPath);
  320. strcat(aSavePath,"\");
  321. #ifdef WIN32
  322. mkdir(aSavePath);
  323. #else
  324.         mkdir(aSavePath, 0);
  325. #endif
  326. strcat(aSavePath,aBackupDir.c_str());
  327. strcat(aSavePath,"\");
  328. #ifdef WIN32
  329. mkdir(aSavePath);
  330. #else
  331.         mkdir(aSavePath, 0);
  332. #endif
  333. strcat(aSavePath,aBackupDir.c_str());
  334. //数据库记录统计(维护查看用)==========Add by Fellow,2003.08.26
  335. char aDBSFullPath[MAX_PATH] = {0};
  336. strcpy(aDBSFullPath, aSavePath);
  337. strcat(aDBSFullPath,".txt");
  338. fstream aDBSOutput(aDBSFullPath,ios::out);
  339. aDBSOutput<<"账号名t角色名t门派t等级t金钱"<<endl;
  340. int aDBSPlayerCount=0;
  341. int aDBSSectPlayerCount[12] = {0};
  342. double aDBSMoneyCount=0;
  343. double aDBSSectMoneyCount[12] = {0};
  344. int aDBSLevelPlayerCount[200] = {0};
  345. //==================
  346. strcat(aSavePath,".bak");
  347. CDBDump DBDump;
  348. DBDump.Open(aSavePath);
  349. if(!RunTable)
  350. {
  351. aLogFile<<"RunTable NULL Error."<<endl;
  352. return;
  353. }
  354. char* RoleFilterList = LoadFilterName(); //取得要过滤的用户名列表
  355. TStatData aStatData;//实时备份后产生的游戏统计数据
  356. memset(&aStatData, 0, sizeof(TStatData));
  357. ZCursor *cursor = RunTable->first();
  358. aLogFile<<"RunTable cursor Opened. Backup begin."<<endl;
  359. while(cursor)
  360. {
  361. if(!DBDump.AddData(cursor->key,cursor->key_size,cursor->data,cursor->size))
  362. {
  363. aLogFile<<"Role["<<cursor->key<<"] Dump Error."<<endl;
  364. }
  365. TRoleList* tmpData;
  366. TRoleData* pRoleData = (TRoleData*)cursor->data;
  367. //数据库记录统计(维护查看用)==========Add by Fellow,2003.08.26
  368. char aDBSSect[32] = {0};
  369. int aDBSSectIndex = (int)pRoleData->BaseInfo.nSect;
  370. switch(aDBSSectIndex)
  371. {
  372. case 0:strcpy(aDBSSect,"少林派");break;
  373. case 1:strcpy(aDBSSect,"天王帮");break;
  374. case 2:strcpy(aDBSSect,"唐门");break;
  375. case 3:strcpy(aDBSSect,"五毒教");break;
  376. case 4:strcpy(aDBSSect,"峨嵋派");break;
  377. case 5:strcpy(aDBSSect,"翠烟门");break;
  378. case 6:strcpy(aDBSSect,"丐帮");break;
  379. case 7:strcpy(aDBSSect,"天忍教");break;
  380. case 8:strcpy(aDBSSect,"武当派");break;
  381. case 9:strcpy(aDBSSect,"昆仑派");break;
  382. default:
  383. if(pRoleData->BaseInfo.ijoincount == 0)
  384. {strcpy(aDBSSect,"新手");break;}
  385. else
  386. {strcpy(aDBSSect,"出师");break;}
  387. }
  388. if(aDBSSectIndex == 255)
  389. {
  390. if(pRoleData->BaseInfo.ijoincount == 0)
  391. {
  392. ++aDBSSectPlayerCount[10];
  393. aDBSSectMoneyCount[10] += pRoleData->BaseInfo.isavemoney + pRoleData->BaseInfo.imoney;
  394. }
  395. else
  396. {
  397. ++aDBSSectPlayerCount[11];
  398. aDBSSectMoneyCount[11] += pRoleData->BaseInfo.isavemoney + pRoleData->BaseInfo.imoney;
  399. }
  400. }
  401. else
  402. {
  403. ++aDBSSectPlayerCount[aDBSSectIndex];
  404. aDBSSectMoneyCount[aDBSSectIndex] += pRoleData->BaseInfo.isavemoney + pRoleData->BaseInfo.imoney;
  405. }
  406. aDBSMoneyCount += pRoleData->BaseInfo.isavemoney + pRoleData->BaseInfo.imoney;
  407. ++aDBSPlayerCount;
  408. if(((pRoleData->BaseInfo.ifightlevel >0))&&(pRoleData->BaseInfo.ifightlevel < 200))
  409. aDBSLevelPlayerCount[pRoleData->BaseInfo.ifightlevel]++;
  410. else
  411. {
  412. aDBSOutput<<"***级别问题*** ";
  413. aDBSLevelPlayerCount[0]++;
  414. }
  415. aDBSOutput<<pRoleData->BaseInfo.caccname<<"t"<<
  416. pRoleData->BaseInfo.szName<<"t"<<
  417. aDBSSect<<"t"<<
  418. pRoleData->BaseInfo.ifightlevel<<"t"<<
  419. pRoleData->BaseInfo.isavemoney + pRoleData->BaseInfo.imoney<<endl;
  420. //=======================================
  421. if(IsRoleFilter(pRoleData->BaseInfo.szName, RoleFilterList))
  422. {//过滤某些角色
  423. if(!RunTable->next(cursor))break;
  424. continue;
  425. }
  426. //////////////////////////////玩家统计////////////////////////////////////
  427. //对金钱排序
  428. tmpData = GetMin(aStatData.MoneyStat, MONEYSTATNUM, stMoney);
  429. if( tmpData->Money < pRoleData->BaseInfo.imoney + pRoleData->BaseInfo.isavemoney)
  430. {//如果当前数据较大就把当前数据代替列表中最小的
  431. RoleDataCopy(tmpData, pRoleData);
  432. }
  433. //对级别排序
  434. tmpData = GetMin(aStatData.LevelStat, LEVELSTATNUM, stLevel);
  435. if( tmpData->Level < pRoleData->BaseInfo.ifightlevel)
  436. {//如果当前数据较大就把当前数据代替列表中最小的
  437. RoleDataCopy(tmpData, pRoleData);
  438. }
  439. //对杀人数排序
  440. tmpData = GetMin(aStatData.KillerStat, KILLERSTATNUM, stKiller);
  441. if( tmpData->KillNum < pRoleData->BaseInfo.nKillPeopleNumber)
  442. {//如果当前数据较大就把当前数据代替列表中最小的
  443. RoleDataCopy(tmpData, pRoleData);
  444. }
  445. //各门派对金钱排序
  446. if( (pRoleData->BaseInfo.nSect <=10) && (pRoleData->BaseInfo.nSect >= 1) )
  447. {
  448. tmpData = GetMin(aStatData.MoneyStatBySect[pRoleData->BaseInfo.nSect + 1], SECTMAXSTATNUM, stMoney);
  449. }
  450. else
  451. {
  452. tmpData = GetMin(aStatData.MoneyStatBySect[0], SECTMAXSTATNUM, stMoney);
  453. }
  454. if( tmpData->Money < pRoleData->BaseInfo.imoney  + pRoleData->BaseInfo.isavemoney)
  455. {//如果当前数据较大就把当前数据代替列表中最小的
  456. RoleDataCopy(tmpData, pRoleData);
  457. }
  458. //各门派对级别排序
  459. if( (pRoleData->BaseInfo.nSect <=10) && (pRoleData->BaseInfo.nSect >= 1) )
  460. {
  461. tmpData = GetMin(aStatData.LevelStatBySect[pRoleData->BaseInfo.nSect + 1], SECTMAXSTATNUM, stMoney);
  462. }
  463. else
  464. {
  465. tmpData = GetMin(aStatData.LevelStatBySect[0], SECTMAXSTATNUM, stMoney);
  466. }
  467. if( tmpData->Level < pRoleData->BaseInfo.ifightlevel)
  468. {//如果当前数据较大就把当前数据代替列表中最小的
  469. RoleDataCopy(tmpData, pRoleData);
  470. }
  471. //////////////////////////////门派统计////////////////////////////////////
  472. //各个门派的玩家数统计
  473. if( (pRoleData->BaseInfo.nSect <=10) && (pRoleData->BaseInfo.nSect >= 1) )
  474. {
  475. ++aStatData.SectPlayerNum[pRoleData->BaseInfo.nSect + 1];
  476. }
  477. else
  478. {
  479. ++aStatData.SectPlayerNum[0];
  480. }
  481. if(!RunTable->next(cursor))break;
  482. }
  483. DBDump.Close(); //关闭备份数据库
  484. aLogFile<<"DB Dump Finished."<<endl;
  485. aLogFile<<"RunTable cursor closed."<<endl;
  486. //数据库记录统计(维护查看用)==========Add by Fellow,2003.08.26
  487. aDBSOutput<<"==记录结束=="<<endl<<endl;
  488. aDBSOutput<<"==统计=="<<endl;
  489. aDBSOutput<<"总人数:"<<aDBSPlayerCount<<endl;
  490. for(i=0;i<12;++i)
  491. {
  492. char aDBSSect[32] = {0};
  493. switch(i)
  494. {
  495. case 0:strcpy(aDBSSect,"少林派");break;
  496. case 1:strcpy(aDBSSect,"天王帮");break;
  497. case 2:strcpy(aDBSSect,"唐门");break;
  498. case 3:strcpy(aDBSSect,"五毒教");break;
  499. case 4:strcpy(aDBSSect,"峨嵋派");break;
  500. case 5:strcpy(aDBSSect,"翠烟门");break;
  501. case 6:strcpy(aDBSSect,"丐帮");break;
  502. case 7:strcpy(aDBSSect,"天忍教");break;
  503. case 8:strcpy(aDBSSect,"武当派");break;
  504. case 9:strcpy(aDBSSect,"昆仑派");break;
  505. case 10:strcpy(aDBSSect,"新手");break;
  506. case 11:strcpy(aDBSSect,"出师");break;
  507. }
  508. aDBSOutput<<aDBSSect<<"人数:"<<aDBSSectPlayerCount[i]<<endl;
  509. }
  510. aDBSOutput<<"------------------------------------------------"<<endl;
  511. aDBSOutput<<"总金钱数:"<<aDBSMoneyCount<<endl;
  512. for(i=0;i<12;++i)
  513. {
  514. char aDBSSect[32] = {0};
  515. switch(i)
  516. {
  517. case 0:strcpy(aDBSSect,"少林派");break;
  518. case 1:strcpy(aDBSSect,"天王帮");break;
  519. case 2:strcpy(aDBSSect,"唐门");break;
  520. case 3:strcpy(aDBSSect,"五毒教");break;
  521. case 4:strcpy(aDBSSect,"峨嵋派");break;
  522. case 5:strcpy(aDBSSect,"翠烟门");break;
  523. case 6:strcpy(aDBSSect,"丐帮");break;
  524. case 7:strcpy(aDBSSect,"天忍教");break;
  525. case 8:strcpy(aDBSSect,"武当派");break;
  526. case 9:strcpy(aDBSSect,"昆仑派");break;
  527. case 10:strcpy(aDBSSect,"新手");break;
  528. case 11:strcpy(aDBSSect,"出师");break;
  529. }
  530. aDBSOutput<<aDBSSect<<"金钱数:"<<aDBSSectMoneyCount[i]<<endl;
  531. }
  532. aDBSOutput<<"------------------------------------------------"<<endl;
  533. aDBSOutput<<"角色级别分布[1-200级]:"<<endl;
  534. for(i=1;i<200;++i)
  535. if(aDBSLevelPlayerCount[i] != 0)
  536. aDBSOutput<<i<<"级人数:"<<aDBSLevelPlayerCount[i]<<endl;
  537. aDBSOutput<<"级别异常人数:"<<aDBSLevelPlayerCount[0]<<endl;
  538. //======================================
  539. for(i=0;i<MONEYSTATNUM;++i)
  540. { //财富排名前一百玩家中各门派所占比例数
  541. if( (aStatData.MoneyStat[i].Sect <=10) && (aStatData.MoneyStat[i].Sect >= 1) )
  542. {
  543. ++aStatData.SectMoneyMost[aStatData.MoneyStat[i].Sect + 1];
  544. }
  545. else
  546. {
  547. ++aStatData.SectMoneyMost[0];
  548. }
  549. }
  550. for(i=0;i<LEVELSTATNUM;++i)
  551. {//级别排名前一百玩家中各门派所占比例数
  552. if( (aStatData.LevelStat[i].Sect <=10) && (aStatData.LevelStat[i].Sect >= 1) )
  553. {
  554. ++aStatData.SectLevelMost[aStatData.LevelStat[i].Sect + 1];
  555. }
  556. else
  557. {
  558. ++aStatData.SectLevelMost[0];
  559. }
  560. }
  561. //////////////////////////////排序////////////////////////////////////
  562. ListSort(aStatData.MoneyStat, MONEYSTATNUM, stMoney);
  563. ListSort(aStatData.LevelStat, LEVELSTATNUM, stLevel);
  564. ListSort(aStatData.KillerStat, KILLERSTATNUM, stKiller);
  565. for(i=0;i<11;++i)
  566. {//各门派金钱排序
  567. ListSort(aStatData.MoneyStatBySect[i], SECTMAXSTATNUM, stMoney);
  568. }
  569. for(i=0;i<11;++i)
  570. {//各门派级别排序
  571. ListSort(aStatData.LevelStatBySect[i], SECTMAXSTATNUM, stLevel);
  572. }
  573. SAFE_DELETE_ARRAY(RoleFilterList);
  574. ///////////////以下为对统计数据的处理//////////////////////////////////////////////////////
  575. char aAppPath[MAX_PATH] = {0};
  576. getcwd(aAppPath,MAX_PATH);
  577. strcat(aAppPath,"\StatData.dat");
  578. //读取旧排名
  579. memset(&oldGameStatData,0,sizeof(CDBBackup::TStatData));
  580. FILE* aStatFile = fopen(aAppPath,"rb");
  581. if(aStatFile)
  582. {
  583. int a = fread(&oldGameStatData, 1, sizeof(CDBBackup::TStatData), aStatFile);
  584. fclose(aStatFile);
  585. }
  586. newGameStatData = aStatData;
  587. //找出前十名的oldGameStatData中的排名(或名次上升还是下降)
  588. for(i=0;i<10;++i)
  589. {
  590. int aIndex;
  591. //等级
  592. aIndex = CDBBackup::GetIndexByName(
  593. newGameStatData.LevelStat[i].Name,oldGameStatData.LevelStat, LEVELSTATNUM);
  594. if(aIndex != -1)
  595. {
  596. if(i < aIndex)
  597. newGameStatData.LevelStat[i].Sort = 1;
  598. else if(i > aIndex)
  599. newGameStatData.LevelStat[i].Sort = 255;
  600. else
  601. newGameStatData.LevelStat[i].Sort = 0;
  602. }
  603. else
  604. newGameStatData.LevelStat[i].Sort = 1;
  605. //金钱
  606. aIndex = CDBBackup::GetIndexByName(
  607. newGameStatData.MoneyStat[i].Name,oldGameStatData.MoneyStat, MONEYSTATNUM);
  608. if(aIndex != -1)
  609. {
  610. if(i < aIndex)
  611. newGameStatData.MoneyStat[i].Sort = 1;
  612. else if(i > aIndex)
  613. newGameStatData.MoneyStat[i].Sort = 255;
  614. else
  615. newGameStatData.MoneyStat[i].Sort = 0;
  616. }
  617. else
  618. newGameStatData.MoneyStat[i].Sort = 1;
  619. //杀人数
  620. aIndex = CDBBackup::GetIndexByName(
  621. newGameStatData.KillerStat[i].Name,oldGameStatData.KillerStat, KILLERSTATNUM);
  622. if(aIndex != -1)
  623. {
  624. if(i < aIndex)
  625. newGameStatData.KillerStat[i].Sort = 1;
  626. else if(i > aIndex)
  627. newGameStatData.KillerStat[i].Sort = 255;
  628. else
  629. newGameStatData.KillerStat[i].Sort = 0;
  630. }
  631. else
  632. newGameStatData.KillerStat[i].Sort = 1;
  633. for(j=0;j<11;++j)
  634. {//各个门派
  635. //等级
  636. aIndex = CDBBackup::GetIndexByName(
  637. newGameStatData.LevelStatBySect[j][i].Name,oldGameStatData.LevelStatBySect[j], SECTMAXSTATNUM);
  638. if(aIndex != -1)
  639. {
  640. if(i < aIndex)
  641. newGameStatData.LevelStatBySect[j][i].Sort = 1;
  642. else if(i > aIndex)
  643. newGameStatData.LevelStatBySect[j][i].Sort = 255;
  644. else
  645. newGameStatData.LevelStatBySect[j][i].Sort = 0;
  646. }
  647. else
  648. newGameStatData.LevelStatBySect[j][i].Sort = 1;
  649. //金钱
  650. aIndex = CDBBackup::GetIndexByName(
  651. newGameStatData.MoneyStatBySect[j][i].Name,oldGameStatData.MoneyStatBySect[j], SECTMAXSTATNUM);
  652. if(aIndex != -1)
  653. {
  654. if(i < aIndex)
  655. newGameStatData.MoneyStatBySect[j][i].Sort = 1;
  656. else if(i > aIndex)
  657. newGameStatData.MoneyStatBySect[j][i].Sort = 255;
  658. else
  659. newGameStatData.MoneyStatBySect[j][i].Sort = 0;
  660. }
  661. else
  662. newGameStatData.MoneyStatBySect[j][i].Sort = 1;
  663. }
  664. }
  665. //储存新排名
  666. aStatFile = fopen(aAppPath,"wb");
  667. if(aStatFile)
  668. {
  669. int a = fwrite(&newGameStatData, 1, sizeof(CDBBackup::TStatData), aStatFile);
  670. fclose(aStatFile);
  671. }
  672. MakeSendStatData();//把统计数据写到发送给客户端的统计数据结构中
  673. //test===========
  674. if(IS_OUTPUT_LOG){//是否输出统计数据
  675. aLogFile<<"DB Statistic Log:"<<endl;
  676. aLogFile<<"--------------Level--------------"<<endl;
  677. for(i=0;i<10;++i)
  678. {
  679. aLogFile<<SendStatData.LevelStat[i].Name<<"t"<<
  680. SendStatData.LevelStat[i].nValue<<"t"<<
  681. (int)SendStatData.LevelStat[i].bySort<<endl;
  682. }
  683. aLogFile<<"--------------Money--------------"<<endl;
  684. for(i=0;i<10;++i)
  685. {
  686. aLogFile<<SendStatData.MoneyStat[i].Name<<"t"<<
  687. SendStatData.MoneyStat[i].nValue<<"t"<<
  688. (int)SendStatData.MoneyStat[i].bySort<<endl;
  689. }
  690. aLogFile<<"--------------Killer--------------"<<endl;
  691. for(i=0;i<10;++i)
  692. {
  693. aLogFile<<SendStatData.KillerStat[i].Name<<"t"<<
  694. SendStatData.KillerStat[i].nValue<<"t"<<
  695. (int)SendStatData.KillerStat[i].bySort<<endl;
  696. }
  697. for(i=0;i<11;++i)
  698. {
  699. aLogFile<<"--------------Sect "<<i<<" Level--------------"<<endl;
  700. for(j=0;j<10;++j)
  701. {
  702. aLogFile<<SendStatData.LevelStatBySect[i][j].Name<<"t"<<
  703. SendStatData.LevelStatBySect[i][j].nValue<<"t"<<
  704. (int)SendStatData.LevelStatBySect[i][j].bySort<<endl;
  705. }
  706. aLogFile<<"-------------Sect "<<i<<" Money---------------"<<endl;
  707. for(j=0;j<10;++j)
  708. {
  709. aLogFile<<SendStatData.MoneyStatBySect[i][j].Name<<"t"<<
  710. SendStatData.MoneyStatBySect[i][j].nValue<<"t"<<
  711. (int)SendStatData.MoneyStatBySect[i][j].bySort<<endl;
  712. }
  713. }
  714. aLogFile<<"各个门派的玩家数"<<endl;
  715. for(i=0;i<11;++i)
  716. {
  717. aLogFile<<"Sect "<<i<<" :"<<SendStatData.SectPlayerNum[i]<<endl;
  718. }
  719. aLogFile<<"财富排名前 "<<MONEYSTATNUM<<" 玩家中各门派所占比例数"<<endl;
  720. for(i=0;i<11;++i)
  721. {
  722. aLogFile<<"Sect "<<i<<" :"<<SendStatData.SectMoneyMost[i]<<endl;
  723. }
  724. aLogFile<<"级别排名前 "<<MONEYSTATNUM<<" 玩家中各门派所占比例数"<<endl;
  725. for(i=0;i<11;++i)
  726. {
  727. aLogFile<<"Sect "<<i<<" :"<<SendStatData.SectLevelMost[i]<<endl;
  728. }
  729. }
  730. //================
  731. IsBackupWorking = false;
  732. }
  733. void CDBBackup::MakeSendStatData()
  734. {//生成发送给客户端的统计数据结构
  735. int i,j;
  736. memset(&SendStatData,0,sizeof(TGAME_STAT_DATA));
  737. for(i=0;i<10;++i)
  738. {
  739. strcpy(SendStatData.LevelStat[i].Name, newGameStatData.LevelStat[i].Name);
  740. SendStatData.LevelStat[i].nValue = newGameStatData.LevelStat[i].Level;
  741. SendStatData.LevelStat[i].bySort = newGameStatData.LevelStat[i].Sort;
  742. strcpy(SendStatData.MoneyStat[i].Name, newGameStatData.MoneyStat[i].Name);
  743. SendStatData.MoneyStat[i].nValue = newGameStatData.MoneyStat[i].Money;
  744. SendStatData.MoneyStat[i].bySort = newGameStatData.MoneyStat[i].Sort;
  745. strcpy(SendStatData.KillerStat[i].Name, newGameStatData.KillerStat[i].Name);
  746. SendStatData.KillerStat[i].nValue = newGameStatData.KillerStat[i].KillNum;
  747. SendStatData.KillerStat[i].bySort = newGameStatData.KillerStat[i].Sort;
  748. for(j=0;j<11;++j)
  749. {//各个门派
  750. strcpy(SendStatData.LevelStatBySect[j][i].Name, newGameStatData.LevelStatBySect[j][i].Name);
  751. SendStatData.LevelStatBySect[j][i].nValue = newGameStatData.LevelStatBySect[j][i].Level;
  752. SendStatData.LevelStatBySect[j][i].bySort = newGameStatData.LevelStatBySect[j][i].Sort;
  753. strcpy(SendStatData.MoneyStatBySect[j][i].Name, newGameStatData.MoneyStatBySect[j][i].Name);
  754. SendStatData.MoneyStatBySect[j][i].nValue = newGameStatData.MoneyStatBySect[j][i].Money;
  755. SendStatData.MoneyStatBySect[j][i].bySort = newGameStatData.MoneyStatBySect[j][i].Sort;
  756. SendStatData.SectLevelMost[j] = newGameStatData.SectLevelMost[j];
  757. SendStatData.SectMoneyMost[j] = newGameStatData.SectMoneyMost[j];
  758. SendStatData.SectPlayerNum[j] = newGameStatData.SectPlayerNum[j];
  759. }
  760. }
  761. }
  762. void CDBBackup::SaveStatInfo()
  763. {//把游戏世界等级排名写到指定玩家角色中
  764. TStatData aStatData;
  765. char aAppPath[MAX_PATH] = {0};
  766. getcwd(aAppPath,MAX_PATH);
  767. strcat(aAppPath,"\StatData.dat");
  768. //读取排名
  769. memset(&aStatData,0,sizeof(TStatData));
  770. FILE* aStatFile = fopen(aAppPath,"rb");
  771. if(aStatFile)
  772. {
  773. int aRead = fread(&aStatData, sizeof(TStatData), 1, aStatFile);
  774. if(aRead != 1) return;
  775. fclose(aStatFile);
  776. }
  777. else
  778. {
  779. return;
  780. }
  781. int i,j;
  782. for(i=0;i<LEVELSTATNUM;++i)
  783. {
  784. if(aStatData.LevelStat[i].Name[0] == '')continue;
  785. ZCursor *cursor = RunTable->search(aStatData.LevelStat[i].Name, strlen(aStatData.LevelStat[i].Name) +1);
  786. // char* aBuffer = RunTable->search(aStatData.LevelStat[i].Name, strlen(aStatData.LevelStat[i].Name) +1,size);
  787. if(!cursor)
  788. {
  789. continue;
  790. }
  791. TRoleData* pRoleData = (TRoleData*)cursor->data;
  792. pRoleData->BaseInfo.nWorldStat = i+1;
  793. if (pRoleData->dwDataLen - 4 == pRoleData->dwFriendOffset)
  794. {
  795. DWORD dwCRC = 0;
  796. dwCRC = CRC32(dwCRC, pRoleData, pRoleData->dwDataLen - 4);
  797. memcpy(cursor->data + pRoleData->dwDataLen - 4, &dwCRC, 4);
  798. }
  799. RunTable->add(aStatData.LevelStat[i].Name, strlen(aStatData.LevelStat[i].Name) +1, cursor->data, cursor->size);
  800. RunTable->closeCursor(cursor);
  801. }
  802. //把门派等级排名写到指定玩家角色中
  803. for(i=0;i<11;++i)
  804. {
  805. for(j=0;j<SECTMAXSTATNUM;++j)
  806. {
  807. if(aStatData.LevelStatBySect[i][j].Name[0] == '')continue;
  808. ZCursor *cursor = RunTable->search( aStatData.LevelStatBySect[i][j].Name, strlen(aStatData.LevelStatBySect[i][j].Name) +1 );
  809. // char* aBuffer = RunTable->search(aStatData.LevelStatBySect[i][j].Name, strlen(aStatData.LevelStatBySect[i][j].Name) +1,size);
  810. if(!cursor)
  811. {
  812. continue;
  813. }
  814. TRoleData* pRoleData = (TRoleData*)cursor->data;
  815. pRoleData->BaseInfo.nSectStat = j+1;
  816. if (pRoleData->dwDataLen - 4 == pRoleData->dwFriendOffset)
  817. {
  818. DWORD dwCRC = 0;
  819. dwCRC = CRC32(dwCRC, pRoleData, pRoleData->dwDataLen - 4);
  820. memcpy(cursor->data + pRoleData->dwDataLen - 4, &dwCRC, 4);
  821. }
  822. RunTable->add(aStatData.LevelStatBySect[i][j].Name, strlen(aStatData.LevelStatBySect[i][j].Name) +1, cursor->data, cursor->size);
  823. RunTable->closeCursor(cursor);
  824. }
  825. }
  826. }