#include #include #include #include #include #include #include #include #include // ÆÛÆ÷ ÃøÁ¤ Ŭ·¡½º class CheckPerformance { #define HOUR(Tick) ((int)((Tick) / 1000 / 60 / 60)) #define MIN(Tick) ((int)((Tick) / 1000 / 60) - HOUR(Tick) * 60) #define SEC(Tick) ((int)((Tick) / 1000) - HOUR(Tick) * 60 * 60 - MIN(Tick) * 60) private: FILE* m_pFile; DWORD m_Start; public: CheckPerformance(FILE* pFile) : m_pFile(pFile) { m_Start = GetTickCount(); } ~CheckPerformance() { DWORD Total = GetTickCount() - m_Start; fprintf(m_pFile, "\nÃÑ ½Ã°£ %2d½Ã°£ %2dºÐ %2dÃÊ\n", HOUR(Total), MIN(Total), SEC(Total)); } }; const char* GetGradeString(Item::EquipType::Grade eGrade) { const char* szResult = "Unknown Grade"; switch(eGrade) { case Item::EquipType::AAA_GRADE: szResult = "AAA"; break; case Item::EquipType::AA_GRADE: szResult = "AA"; break; case Item::EquipType::A_GRADE: szResult = "A"; break; case Item::EquipType::B_GRADE: szResult = "B"; break; case Item::EquipType::C_GRADE: szResult = "C"; break; case Item::EquipType::D_GRADE: szResult = "D"; break; case Item::EquipType::F_GRADE: szResult = "E"; break; case Item::EquipType::MAX_GRADE: szResult = "F"; break; } return szResult; } #pragma pack(1) typedef struct ItemMapInfo* LPItemMapInfo; struct ItemMapInfo { unsigned __int64 m_dwUID; int m_nProtoTypeID; int m_nCount; }; struct ItemGradeMapInfo { unsigned __int64 m_dwUID; int m_nProtoTypeID; int m_nGrade; int m_nGradeNum; }; struct ItemGradeInfo { unsigned char m_nGrade; int m_nGradeNum; }; typedef struct OwnerInfo* LPOwnerInfo; struct OwnerInfo { unsigned long m_dwUID; unsigned long m_dwCID; unsigned long m_dwCount; }; #pragma pack() const unsigned long MAX_ITEMMAP_INFO = 2000; const unsigned long MAX_OWNER_INFO = 1000; // ÇÔ¼ö bool DupMapAnalyzer(FILE* pOutStd, FILE* pOutFile, char* szTableName); bool UpgMapAnalyzer(FILE* pOutStd, FILE* pOutFile, char* szTableName); bool PrintItem(FILE* pOutFile, ItemGradeMapInfo& MapInfo, char* Param); bool PrintItem(FILE* pOutFile, ItemMapInfo& MapInfo, char* Param); // º¯¼ö/»ó¼ö const char ScriptFileName[MAX_PATH] = "ItemScript.txt"; static ItemMapInfo g_ItemMapInfo[MAX_ITEMMAP_INFO]; static ItemGradeMapInfo g_ItemGradeMapInfo[MAX_ITEMMAP_INFO]; static OwnerInfo g_OwnerInfo[MAX_OWNER_INFO]; typedef std::map ItemList; // Key == Serial typedef std::map ItemGradeList; // Key == Serial typedef std::multimap OwnerList; // Key == Serial ItemGradeList g_DupItemList; ItemList g_AskOwnerList; OwnerList g_OwnerList; int main(int argc, char *argv[]) { // ÆÄÀÏ ¿ÀÇ FILE *pOutStd = stdout; char szTableName[MAX_PATH] = ""; if(argc == 6) { // DB ¿¬°á if(!CDBSingleObject::GetInstance().Connect(argv[1], argv[2], argv[4], argv[5])) { fprintf(pOutStd, "\n[DB ¿¬°á ½ÇÆÐ]\n"); return -1; } sprintf(szTableName, argv[3]); } else { printf("Using Like this : NewItemMapAnalyzer DBServerName DBName TableName Account Password"); return -1; } std::string dupFileName = "DupLog"; std::string upgFileName = "UpgLog"; dupFileName += szTableName; dupFileName += ".txt"; upgFileName += szTableName; upgFileName += ".txt"; FILE* pDupOutFile = fopen(dupFileName.c_str(), "wt"); FILE* pUpgOutFile = fopen(upgFileName.c_str(), "wt"); if(NULL == pDupOutFile || NULL == pUpgOutFile) { if(NULL != pDupOutFile) { fclose(pDupOutFile); } if(NULL != pUpgOutFile) { fclose(pUpgOutFile); } return -1; } fprintf(pOutStd, "\n[DB ¿¬°á ¼º°ø]\n"); // ½ºÅ©¸³Æ® Àбâ if(!Item::CItemMgr::GetInstance().LoadItemProtoType(ScriptFileName)) { fprintf(pOutStd, "\n[½ºÅ©¸³Æ® ·Îµå ½ÇÆÐ]\n"); fclose(pDupOutFile); fclose(pUpgOutFile); return -1; } fprintf(pOutStd, "\n[½ºÅ©¸³Æ® ·Îµå ¼º°ø]\n\n[¸Ê ºÐ¼® ½ÃÀÛ]\n"); DupMapAnalyzer(pOutStd, pDupOutFile, szTableName); // º¹»ç °Ë»ç UpgMapAnalyzer(pOutStd, pUpgOutFile, szTableName); // ¾÷±Û °Ë»ç fprintf(pOutStd, "\n[¸Ê ºÐ¼® ¿Ï·á]\n"); fclose(pDupOutFile); fclose(pUpgOutFile); getchar(); return 0; } // º¹»ç ¾ÆÀÌÅÛ ºÐ¼® bool DupMapAnalyzer(FILE* pOutStd, FILE* pOutFile, char* szTableName) { CheckPerformance CheckPerformance(pOutFile); char Query[MAX_PATH] = ""; int Rows = 0; fprintf(pOutFile, "[Áߺ¹ ¾ÆÀÌÅÛ °Ë»ç + _+]\n\n"); CDBSingleObject& DBSingleObject = CDBSingleObject::GetInstance(); DWORD TotalNum = 0; sprintf(Query, "SELECT COUNT(ITEM_SERIAL) FROM %s", szTableName); if(!DBSingleObject.Select(Query, (void**)&TotalNum, sizeof(DWORD), 0, 1, &Rows)) { fprintf(pOutFile, "¾ÆÀÌÅÛ ÃÑ ¼ö ¾ò±â ½ÇÆÐ : ErrorString:%s\n", DBSingleObject.GetErrorString()); return false; } int DuplicatedSerial = 0; std::vector itemMaps; itemMaps.reserve(10000); sprintf(Query, "SELECT ITEM_SERIAL, CAST(PROTOTYPE_ID AS INT), CAST(COUNT(ITEM_SERIAL) AS INT) FROM %s " "GROUP BY ITEM_SERIAL, PROTOTYPE_ID HAVING COUNT(ITEM_SERIAL) > 1 ORDER BY COUNT(ITEM_SERIAL) DESC", szTableName); for(int StartRow = 0;; StartRow += MAX_ITEMMAP_INFO) { if(DBSingleObject.Select(Query, (void**)&g_ItemMapInfo, sizeof(ItemMapInfo), StartRow, MAX_ITEMMAP_INFO, &Rows)) { for(int RowCounter = 0; RowCounter < Rows; ++RowCounter) { ++DuplicatedSerial; g_AskOwnerList.insert( std::make_pair(g_ItemMapInfo[RowCounter].m_dwUID, g_ItemMapInfo[RowCounter])); itemMaps.push_back(g_ItemMapInfo[RowCounter]); } } else { fprintf(pOutFile, "µ¥ÀÌÅÍ ·ÎµùÁß ¿¡·¯ ¹ß»ý : ErrorCode:%s\n", DBSingleObject.GetErrorString()); break; } fprintf(pOutStd, "%d\n", StartRow + Rows); if(Rows < MAX_ITEMMAP_INFO) { break; } } std::vector::iterator begin = itemMaps.begin(); std::vector::iterator end = itemMaps.end(); char szSerial[MAX_PATH]; unsigned __int64 dwSerial = 0; ItemMapInfo itemInfo; int nCount = 0; for(;begin != end; ++begin) { dwSerial = begin->m_dwUID; itemInfo = *begin; sprintf(Query, "SELECT OWNER_UID, OWNER_CID, COUNT(ITEM_SERIAL) FROM %s" " WHERE ITEM_SERIAL = %s GROUP BY OWNER_UID, OWNER_CID" " ORDER BY OWNER_UID ASC, OWNER_CID ASC, COUNT(ITEM_SERIAL) DESC", szTableName, _ui64toa(dwSerial, szSerial, 10)); for(int StartRow = 0;; StartRow += MAX_OWNER_INFO) { if(CDBSingleObject::GetInstance().Select(Query, (void**)&g_OwnerInfo, sizeof(OwnerInfo), StartRow, MAX_OWNER_INFO, &Rows)) { PrintItem(pOutFile, itemInfo, ""); for(int RowCounter = 0; RowCounter < Rows; ++RowCounter) { fprintf(pOutFile, "\tUID:%10d CID:%10d ¼ÒÀ¯°³¼ö:%4d\n", g_OwnerInfo[RowCounter].m_dwUID, g_OwnerInfo[RowCounter].m_dwCID, g_OwnerInfo[RowCounter].m_dwCount); g_OwnerList.insert(std::make_pair(dwSerial, g_OwnerInfo[RowCounter])); } } else { fprintf(pOutFile, "µ¥ÀÌÅÍ ·ÎµùÁß ¿¡·¯ ¹ß»ý : ErrorCode:%s\n", CDBSingleObject::GetInstance().GetErrorString()); break; } if(Rows < MAX_ITEMMAP_INFO) break; } ++nCount; if(0 == nCount % 2000) { fprintf(pOutStd, "%d\n", nCount); } } fprintf(pOutStd, "%d\n", nCount); fprintf(pOutFile, "\nÁߺ¹ ¾ÆÀÌÅÛ: %d/%d [ %2.2f% ] \n\n\n", DuplicatedSerial, TotalNum, (float)DuplicatedSerial / TotalNum * 100); return true; } // ¾÷±×·¹ÀÌµå ¾ÆÀÌÅÛ ºÐ¼® bool UpgMapAnalyzer(FILE* pOutStd, FILE* pOutFile, char* szTableName) { CheckPerformance CheckPerformance(pOutFile); char Query[MAX_PATH] = ""; int Rows = 0; CDBSingleObject& DBSingleObject = CDBSingleObject::GetInstance(); const Item::EquipType::Grade eMinFindGrade = Item::EquipType::A_GRADE; fprintf(pOutFile, "[µî±Þ ¾ÆÀÌÅÛ °Ë»ç(%s µî±Þ ÀÌ»ó) + _+]" "\nSerial\tProtoTypeID\tItemName(Grade(+)))\n", GetGradeString(eMinFindGrade)); DWORD TotalNum = 0; sprintf(Query, "SELECT COUNT(ITEM_SERIAL) FROM %s WHERE ITEM_GRADE <= %d", szTableName, eMinFindGrade); if(!DBSingleObject.Select(Query, (void**)&TotalNum, sizeof(DWORD), 0, 1, &Rows)) { fprintf(pOutFile, "¾ÆÀÌÅÛ ÃÑ ¼ö ¾ò±â ½ÇÆÐ : ErrorString:%s\n", DBSingleObject.GetErrorString()); return false; } int DuplicatedSerial = 0; sprintf(Query, "SELECT ITEM_SERIAL, CAST(PROTOTYPE_ID AS INT), " "CAST(ITEM_GRADE AS INT), CAST(ITEM_GRADE_PLUS AS INT) FROM %s " "WHERE ITEM_GRADE <= %d ORDER BY ITEM_GRADE ASC, PROTOTYPE_ID ASC, ITEM_SERIAL ASC", szTableName, eMinFindGrade); for(int StartRow = 0;; StartRow += MAX_ITEMMAP_INFO) { if(DBSingleObject.Select(Query, (void**)&g_ItemGradeMapInfo, sizeof(ItemGradeMapInfo), StartRow, MAX_ITEMMAP_INFO, &Rows)) { for(int RowCounter = 0; RowCounter < Rows; ++RowCounter) { ItemGradeList::iterator find = g_DupItemList.find(g_ItemGradeMapInfo[RowCounter].m_dwUID); if(find != g_DupItemList.end()) { ++DuplicatedSerial; PrintItem(pOutFile, g_ItemGradeMapInfo[RowCounter], "[º¹»ç] "); } else { PrintItem(pOutFile, g_ItemGradeMapInfo[RowCounter], ""); } fprintf(pOutStd, "#"); } } else { fprintf(pOutFile, "µ¥ÀÌÅÍ ·ÎµùÁß ¿¡·¯ ¹ß»ý : ErrorCode:%s\n", CDBSingleObject::GetInstance().GetErrorString()); } if(Rows < MAX_ITEMMAP_INFO) break; } fprintf(pOutFile, "\n[µî±Þº° ¾ÆÀÌÅÛ ¼ö]\n"); ItemGradeInfo gradeInfo[Item::EquipType::MAX_GRADE + 1]; memset(&gradeInfo, 0, sizeof(ItemGradeInfo) * (Item::EquipType::MAX_GRADE + 1)); sprintf(Query, "SELECT ITEM_GRADE, CAST(COUNT(ITEM_GRADE) AS INT) FROM %s " "GROUP BY ITEM_GRADE ORDER BY ITEM_GRADE ASC", szTableName); if(!DBSingleObject.ExecuteQuery(Query)) { fprintf(pOutFile, "µ¥ÀÌÅÍ ·ÎµùÁß ¿¡·¯ ¹ß»ý : ErrorCode:%s\n", CDBSingleObject::GetInstance().GetErrorString()); } else { int nGetNum = 0; while(DBSingleObject.GetData((void**)&gradeInfo, sizeof(ItemGradeInfo), Item::EquipType::MAX_GRADE + 1, &nGetNum)) { if(0 == nGetNum) { break; } for(int nCount = 0; nCount < Item::EquipType::MAX_GRADE + 1; ++nCount) { fprintf(pOutFile, "%5s µî±Þ ¾ÆÀÌÅÛ ¼ö : %d\n", GetGradeString(static_cast(gradeInfo[nCount].m_nGrade)), gradeInfo[nCount].m_nGradeNum); } } } fprintf(pOutFile, "\n%s µî±Þ ÀÌ»ó Áߺ¹ ¾ÆÀÌÅÛ: %d/%d [ %2.2f% ] \n\n\n", GetGradeString(eMinFindGrade), DuplicatedSerial, TotalNum, (float)DuplicatedSerial / TotalNum * 100); return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////// // ¾ÆÀÌÅÛ Ãâ·Â bool PrintItem(FILE* pOutFile, ItemGradeMapInfo& MapInfo, char* Param) { static char Query[2000] = ""; char strUID[256] = ""; if(0 == MapInfo.m_nProtoTypeID) return false; Item::CItem* lpItem = Item::CItemFactory::GetInstance().CreateItem(MapInfo.m_nProtoTypeID); if(NULL == lpItem) { fprintf(pOutFile, "[ERROR] ¾ÆÀÌÅÛ »ý¼º ½ÇÆÐ ProtoTypeID: %d\n", MapInfo.m_nProtoTypeID); return false; } Item::ItemInfo ItemInfo = lpItem->GetItemInfo(); Math::Convert::Hex64ToStr(strUID, MapInfo.m_dwUID); fprintf(pOutFile, "%s0x%s\t%4d\t%s(%s(%d))\n", Param, strUID, MapInfo.m_nProtoTypeID, ItemInfo.m_SpriteData.m_szName, GetGradeString(static_cast(MapInfo.m_nGrade)), MapInfo.m_nGradeNum); return true; } bool PrintItem(FILE* pOutFile, ItemMapInfo& MapInfo, char* Param) { static char Query[2000] = ""; char strUID[256] = ""; if(0 == MapInfo.m_nProtoTypeID) return false; Item::CItem* lpItem = Item::CItemFactory::GetInstance().CreateItem(MapInfo.m_nProtoTypeID); if(NULL == lpItem) { fprintf(pOutFile, "[ERROR] ¾ÆÀÌÅÛ »ý¼º ½ÇÆÐ ProtoTypeID: %d\n", MapInfo.m_nProtoTypeID); return false; } Item::ItemInfo ItemInfo = lpItem->GetItemInfo(); Math::Convert::Hex64ToStr(strUID, MapInfo.m_dwUID); fprintf(pOutFile, "%s0x%s\t%4d\t%s(%d)\n", Param, strUID, MapInfo.m_nProtoTypeID, ItemInfo.m_SpriteData.m_szName, MapInfo.m_nCount); return true; }