DragonNest/Server/DNGameServer/LadderStats.cpp
2024-12-20 16:56:44 +08:00

863 lines
51 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.


#include "Stdafx.h"
#include "LadderStats.h"
#include "DNPvPGameRoom.h"
#include "DNUserSession.h"
#include "DnPlayerActor.h"
#include "DNDBConnection.h"
#include "PvPGameMode.h"
#include "DnMonsterActor.h"
#if defined(PRE_ADD_DWC)
#include "DNDBConnectionManager.h"
#endif
using namespace LadderSystem;
//###############################################################################################################################
// FactoryClass
//###############################################################################################################################
CStatsRepository* CStatsFactory::CreateRepository( CDNGameRoom* pGameRoom )
{
_ASSERT( pGameRoom->bIsLadderRoom() );
CStatsRepository* pStats = new CStatsRepository( pGameRoom );
if( pStats->bInitialize() == false )
{
_ASSERT(0);
SAFE_DELETE( pStats );
}
return pStats;
}
#if defined(PRE_ADD_DWC)
CDWCStatsRepository* CStatsFactory::CreateDWCRepository( CDNGameRoom* pGameRoom )
{
_ASSERT( pGameRoom->bIsLadderRoom() );
CDWCStatsRepository* pStats = new CDWCStatsRepository( pGameRoom );
if( pStats->bInitialize() == false )
{
_ASSERT(0);
SAFE_DELETE( pStats );
}
return pStats;
}
#endif
//###############################################################################################################################
// CStats
//###############################################################################################################################
CStats::CStats( CDNUserSession* pSession, MatchType::eCode MatchType )
:m_biCharacterDBID(pSession->GetCharacterDBID()),m_MatchType(MatchType)
{
m_bInit = false;
m_iGradePoint = 0; // 평점
m_iHiddenGradePoint = 0; // 가평점
m_MatchResult = MatchResult::None; // 매치결과
m_iVSJobCode = 0; // MatchType::_1vs1 일경우에만 쓰임
}
void CStats::ConvertKillResult( std::vector<LadderKillResult>& vData )
{
if( m_mKillDeathCount.empty() )
return;
vData.reserve( m_mKillDeathCount.size() );
for( std::map<int,SKillDeathCount>::iterator itor=m_mKillDeathCount.begin() ; itor!=m_mKillDeathCount.end() ; ++itor )
{
LadderKillResult Data;
Data.cJobCode = (*itor).first;
Data.nKillCount = (*itor).second.iKillCount;
Data.nDeathCount = (*itor).second.iDeathCount;
vData.push_back( Data );
}
}
void CStats::OnRecvLadderScore( const TAGetListPvPLadderScore* pPacket )
{
if( pPacket->nRetCode != ERROR_NONE )
{
_ASSERT(0);
return;
}
// 중복초기화들어오면 문제가 있는거다..행여나 발생해도 최신 데이터를 신용한다.
if( m_bInit == true )
_ASSERT(0);
bool bFound = false;
for( int i=0 ; i<pPacket->Data.cLadderTypeCount ; ++i )
{
if( pPacket->Data.LadderScore[i].cPvPLadderCode == m_MatchType )
{
m_iGradePoint = pPacket->Data.LadderScore[i].iPvPLadderGradePoint; // 평점
m_iHiddenGradePoint = pPacket->Data.LadderScore[i].iHiddenPvPLadderGradePoint; // 가평점
bFound = true;
break;
}
}
if( bFound == false )
{
m_iGradePoint = Stats::InitGradePoint;
m_iHiddenGradePoint = Stats::InitGradePoint;
}
#if defined( _WORK )
std::cout << "[Ladder] CharDBID:" << m_biCharacterDBID << " 평점:" << m_iGradePoint << " 가평점:" << m_iHiddenGradePoint << std::endl;
#endif // #if defined( _WORK )
m_bInit = true;
}
void CStats::OnDie( DnActorHandle hActor, DnActorHandle hHitter )
{
if( m_bInit == false )
{
_ASSERT(0);
return;
}
if( !hHitter )
return;
// DeathCount
std::map<int,SKillDeathCount>::iterator itor = m_mKillDeathCount.find( hHitter->OnGetJobClassID() );
if( itor == m_mKillDeathCount.end() )
{
m_mKillDeathCount.insert( std::make_pair(hHitter->OnGetJobClassID(),SKillDeathCount(0,1)) );
}
else
{
++(*itor).second.iDeathCount;
}
}
void CStats::OnKill( DnActorHandle hActor, DnActorHandle hDieActor )
{
if( m_bInit == false )
{
_ASSERT(0);
return;
}
if( !hDieActor )
return;
// KillCount
std::map<int,SKillDeathCount>::iterator itor = m_mKillDeathCount.find( hDieActor->OnGetJobClassID() );
if( itor == m_mKillDeathCount.end() )
{
m_mKillDeathCount.insert( std::make_pair(hDieActor->OnGetJobClassID(),SKillDeathCount(1,0)) );
}
else
{
++(*itor).second.iKillCount;
}
}
//###############################################################################################################################
// CStatsRepository
//###############################################################################################################################
CStatsRepository::CStatsRepository( CDNGameRoom* pGameRoom ):m_pGameRoom(pGameRoom),m_MatchType(MatchType::None)
{
for( int i=0 ; i<_countof(m_iTeamGradePointAvg) ; ++i )
m_iTeamGradePointAvg[i] = 0;
//#############################################
// 평점 계산용
//#############################################
S_Repository[0] = boost::tuple<float,float,float>(1.f,0.4f,0.5f);
S_Repository[1] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
S_Repository[2] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
S_Repository[3] = boost::tuple<float,float,float>(1.f,0.f,0.4f);
S_Repository[4] = boost::tuple<float,float,float>(1.f,0.f,0.3f);
S_Repository[5] = boost::tuple<float,float,float>(1.f,0.f,-0.5f);
HiddenS_Repository[0] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
HiddenS_Repository[1] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
HiddenS_Repository[2] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
HiddenS_Repository[3] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
HiddenS_Repository[4] = boost::tuple<float,float,float>(1.f,-0.2f,0.5f);
HiddenS_Repository[5] = boost::tuple<float,float,float>(1.f,-0.3f,0.5f);
K_Repository[0] = boost::tuple<float,float,float,float>(60.f,60.f,60.f,60.f);
K_Repository[1] = boost::tuple<float,float,float,float>(50.f,50.f,50.f,50.f);
K_Repository[2] = boost::tuple<float,float,float,float>(40.f,40.f,40.f,40.f);
K_Repository[3] = boost::tuple<float,float,float,float>(30.f,30.f,30.f,30.f);
K_Repository[4] = boost::tuple<float,float,float,float>(20.f,20.f,20.f,20.f);
K_Repository[5] = boost::tuple<float,float,float,float>(10.f,10.f,10.f,10.f);
HiddenK_Repository[0] = boost::tuple<float,float,float,float>(120.f,120.f,120.f,120.f);
HiddenK_Repository[1] = boost::tuple<float,float,float,float>(100.f,100.f,100.f,100.f);
HiddenK_Repository[2] = boost::tuple<float,float,float,float>(80.f,80.f,80.f,80.f);
HiddenK_Repository[3] = boost::tuple<float,float,float,float>(60.f,60.f,60.f,60.f);
HiddenK_Repository[4] = boost::tuple<float,float,float,float>(40.f,40.f,40.f,40.f);
HiddenK_Repository[5] = boost::tuple<float,float,float,float>(20.f,20.f,20.f,20.f);
}
CStatsRepository::~CStatsRepository()
{
for( std::map<INT64,CStats*>::iterator itor=m_mRepository.begin() ; itor!=m_mRepository.end() ; ++itor )
SAFE_DELETE( (*itor).second );
}
bool CStatsRepository::bInitialize()
{
CDNPvPGameRoom* pPvPGameRoom = static_cast<CDNPvPGameRoom*>(m_pGameRoom);
m_MatchType = pPvPGameRoom->GetPvPLadderMatchType();
#if defined(PRE_ADD_DWC)
int iNeedTeamPlayer = LadderSystem::GetNeedTeamCount(m_MatchType);
#else
int iNeedTeamPlayer = static_cast<int>(m_MatchType);
#endif
// A 팀 인원수 확인
if( pPvPGameRoom->GetUserCount( PvPCommon::Team::A ) != iNeedTeamPlayer )
{
_ASSERT(0);
return false;
}
// B 팀 인원수 확인
if( pPvPGameRoom->GetUserCount( PvPCommon::Team::B ) != iNeedTeamPlayer )
{
_ASSERT(0);
return false;
}
for( UINT i=0 ; i<m_pGameRoom->GetUserCount() ; ++i )
{
CDNUserSession* pSession = m_pGameRoom->GetUserData(i);
if( (pSession->GetTeam() == PvPCommon::Team::A || pSession->GetTeam() == PvPCommon::Team::B) == false )
continue;
CStats* pStats = new CStats( pSession, m_MatchType );
if( pStats == NULL )
{
_ASSERT(0);
return false;
}
m_mRepository.insert( std::make_pair(pSession->GetCharacterDBID(),pStats) );
}
if( m_mRepository.size() != iNeedTeamPlayer*2 )
return false;
return true;
}
bool CStatsRepository::QueryUpdateResult( CDNUserSession* pSession, UINT uiWinTeam, PvPCommon::QueryUpdatePvPDataType::eCode Type )
{
if( static_cast<CDNPvPGameRoom*>(m_pGameRoom)->GetPvPGameMode()->GetRemainStartTick() > 0 )
{
#if defined( _WORK )
std::cout << "[Ladder] 시작 전에 종료되어서 DB 업뎃안함!!!" << std::endl;
#endif // #if defined( _WORK )
return false;
}
if( bIsValidLadderTeam( pSession->GetTeam() ) == false )
{
_ASSERT(0);
return false;
}
std::map<INT64,CStats*>::iterator itor = m_mRepository.find( pSession->GetCharacterDBID() );
if( itor == m_mRepository.end() )
return false;
CStats* pStats = (*itor).second;
//##############################
// 평균평점
//##############################
float Ra = static_cast<float>((pSession->GetTeam() == PvPCommon::Team::A) ? m_iTeamGradePointAvg[PvPCommon::TeamIndex::A] : m_iTeamGradePointAvg[PvPCommon::TeamIndex::B]);
float Rb = static_cast<float>((pSession->GetTeam() == PvPCommon::Team::A) ? m_iTeamGradePointAvg[PvPCommon::TeamIndex::B] : m_iTeamGradePointAvg[PvPCommon::TeamIndex::A]);
//##############################
// 래더 평점 보정
//##############################
int iAvgGradePoint = static_cast<int>(Ra);
int iTupleIndex = 0;
// 최하유저
if( iAvgGradePoint < 1400 )
iTupleIndex = 0;
// 기본 유저
else if( iAvgGradePoint < 1700 )
iTupleIndex = 1;
// 일반 유저
else if( iAvgGradePoint < 2000 )
iTupleIndex = 2;
// 상위 유저
else if( iAvgGradePoint < 2300 )
iTupleIndex = 3;
// 코어 유저
else if( iAvgGradePoint < 2500 )
iTupleIndex = 4;
// 안드로 유저
else
iTupleIndex = 5;
if( iTupleIndex >= MAX_GRADEPOINT_RANGE )
{
_ASSERT(0);
iTupleIndex = 0;
}
//##############################
// 경기결과
//##############################
float S = 0.f;
float HiddenS = 0.f;
float K = 0.f;
float HiddenK = 0.f;
MatchResult::eCode Result = MatchResult::Lose;
switch( Type )
{
case PvPCommon::QueryUpdatePvPDataType::FinishGameMode:
{
if( uiWinTeam == PvPCommon::Team::Max ) // 무승부
{
Result = MatchResult::Draw;
S = S_Repository[iTupleIndex].get<2>();
HiddenS = HiddenS_Repository[iTupleIndex].get<2>();
}
else if( uiWinTeam == pSession->GetTeam() ) // 승
{
Result = MatchResult::Win;
S = S_Repository[iTupleIndex].get<0>();
HiddenS = HiddenS_Repository[iTupleIndex].get<0>();
}
else // 패
{
Result = MatchResult::Lose;
S = S_Repository[iTupleIndex].get<1>();
HiddenS = HiddenS_Repository[iTupleIndex].get<1>();
}
break;
}
}
switch( m_MatchType )
{
case MatchType::_1vs1:
{
K = K_Repository[iTupleIndex].get<0>();
HiddenK = HiddenK_Repository[iTupleIndex].get<0>();
break;
}
case MatchType::_2vs2:
{
K = K_Repository[iTupleIndex].get<1>();
HiddenK = HiddenK_Repository[iTupleIndex].get<1>();
break;
}
case MatchType::_3vs3:
{
K = K_Repository[iTupleIndex].get<2>();
HiddenK = HiddenK_Repository[iTupleIndex].get<2>();
break;
}
case MatchType::_4vs4:
{
K = K_Repository[iTupleIndex].get<3>();
HiddenK = HiddenK_Repository[iTupleIndex].get<3>();
break;
}
}
//##############################
// 예상승률
//##############################
float Ea = 1/(1.f+pow(10,(Rb-Ra)/400.f));
//##############################
// 평점 변화량
//##############################
float ChangeRa = K*(S-Ea);
float ChangeHiddenRa = HiddenK*(HiddenS-Ea);
//##############################
// flaot 반올림 처리
//##############################
ChangeRa = static_cast<float>(static_cast<int>(ChangeRa + (ChangeRa > 0.f ? .5f : -.5f) )) / 1.f;
ChangeHiddenRa = static_cast<float>(static_cast<int>(ChangeHiddenRa + (ChangeHiddenRa > 0.f ? .5f : -.5f) )) / 1.f;
//##############################
// Query 날리기~
//##############################
CDNDBConnection* pDBCon = pSession->GetDBConnection();
if( pDBCon == NULL )
return false;
int iGradePoint = pStats->GetGradePoint()+static_cast<int>(ChangeRa);
int iHiddenGradePoint = pStats->GetHiddenGradePoint()+static_cast<int>(ChangeHiddenRa);
BYTE cVSJobCode = pStats->GetVSJobCode();
std::vector<LadderKillResult> vData;
pStats->ConvertKillResult( vData );
if( iGradePoint < Stats::MinGradePoint )
iGradePoint = Stats::MinGradePoint;
if( iHiddenGradePoint < Stats::MinGradePoint )
iHiddenGradePoint = Stats::MinGradePoint;
#if defined( _WORK )
std::cout << "[Ladder] CharDBID:" << pSession->GetCharacterDBID() << " 결과:" << Result << std::endl;
std::cout << "[Ladder] 평점변화 " << pStats->GetGradePoint() << "->" << iGradePoint << std::endl;
std::cout << "[Ladder] 가평점변화 " << pStats->GetHiddenGradePoint() << "->" << iHiddenGradePoint << std::endl;
#endif // #if defined( _WORK )
g_Log.Log( LogType::_LADDER, pSession, L"result gradepoint:%d\r\n", iGradePoint );
m_mResult[pSession->GetCharacterDBID()] = SResult(static_cast<int>(ChangeRa),iGradePoint );
return pDBCon->QueryAddPvPLadderResult( pSession, Type, m_MatchType, iGradePoint, iHiddenGradePoint, Result, cVSJobCode, vData );
}
void CStatsRepository::OnDie( DnActorHandle hActor, DnActorHandle hHitter )
{
//소환물이 kill 한 경우
if( hHitter && hHitter->IsMonsterActor() )
{
DnActorHandle hMaster = static_cast<CDnMonsterActor*>(hHitter.GetPointer())->GetSummonerPlayerActor();
if( hMaster && hMaster->IsPlayerActor() )
hHitter = hMaster;
}
// Valid체크
if( !(hActor && hHitter && hActor->IsPlayerActor() && hHitter->IsPlayerActor()) )
return;
CDnPlayerActor* pPlayer = reinterpret_cast<CDnPlayerActor*>(hActor.GetPointer());
std::map<INT64,CStats*>::iterator itor = m_mRepository.find( pPlayer->GetCharacterDBID() );
if( itor != m_mRepository.end() )
(*itor).second->OnDie( hActor, hHitter );
CDnPlayerActor* pHitter = reinterpret_cast<CDnPlayerActor*>(hHitter.GetPointer());
itor = m_mRepository.find( pHitter->GetCharacterDBID() );
if( itor != m_mRepository.end() )
(*itor).second->OnKill( hHitter, hActor );
}
void CStatsRepository::OnRecvLadderScore( INT64 biCharacterDBID, int iTeam, const TAGetListPvPLadderScore* pPacket )
{
std::map<INT64,CStats*>::iterator itor = m_mRepository.find( biCharacterDBID );
if( itor == m_mRepository.end() )
{
_ASSERT(0);
return;
}
if( bIsValidLadderTeam( iTeam ) == false )
_ASSERT(0);
(*itor).second->OnRecvLadderScore( pPacket );
// 팀별 평점 계산
int iGradePoint = (*itor).second->GetGradePoint();
std::map<int,std::vector<int>>::iterator Sumitor = m_mGradePointSum.find( iTeam );
if( Sumitor == m_mGradePointSum.end() )
{
std::vector<int> vTemp;
vTemp.push_back( iGradePoint );
m_mGradePointSum.insert( std::make_pair(iTeam,vTemp) );
}
else
{
(*Sumitor).second.push_back( iGradePoint );
}
// 평균 계산
int iSum = 0;
Sumitor = m_mGradePointSum.find( iTeam );
for( UINT i=0 ; i<(*Sumitor).second.size() ; ++i )
iSum += (*Sumitor).second[i];
if ((*Sumitor).second.size() <= 0)
{
_ASSERT(0);
return;
}
m_iTeamGradePointAvg[iTeam-PvPCommon::Team::A] = static_cast<int>(iSum/(*Sumitor).second.size());
}
void CStatsRepository::OnSetPlayState()
{
// Stats 초기화 검증
for( std::map<INT64,CStats*>::iterator itor=m_mRepository.begin() ; itor!=m_mRepository.end() ; ++itor )
{
CStats* pStats = (*itor).second;
if( pStats->bIsInit() == false )
{
_ASSERT(0);
CDNUserSession* pSession = m_pGameRoom->GetUserSessionByCharDBID( (*itor).first );
if( pSession )
pSession->DetachConnection( L"LadderStats isn't Init" );
}
}
// 1vs1 인 경우 VSJobCode 설정 작업
if( m_MatchType == MatchType::_1vs1 )
{
if( m_pGameRoom->GetUserCount() != 2 )
return;
CDNUserSession* pSession = m_pGameRoom->GetUserData(0);
CDNUserSession* pSession2 = m_pGameRoom->GetUserData(1);
if( pSession && pSession2 )
{
std::map<INT64,CStats*>::iterator itor = m_mRepository.find( pSession->GetCharacterDBID() );
if( itor != m_mRepository.end() )
(*itor).second->SetVSJobCode( pSession2->GetUserJob() );
itor = m_mRepository.find( pSession2->GetCharacterDBID() );
if( itor != m_mRepository.end() )
(*itor).second->SetVSJobCode( pSession->GetUserJob() );
}
}
}
bool CStatsRepository::bIsValidLadderTeam( int iTeam )
{
switch( iTeam )
{
case PvPCommon::Team::A:
case PvPCommon::Team::B:
return true;
}
return false;
}
int CStatsRepository::GetAddGradePoint( INT64 biCharacterDBID )
{
std::map<INT64,SResult>::iterator itor = m_mResult.find( biCharacterDBID );
if( itor != m_mResult.end() )
return (*itor).second.iAddGradePoint;
return 0;
}
int CStatsRepository::GetResultGradePoint( INT64 biCharacterDBID )
{
std::map<INT64,SResult>::iterator itor = m_mResult.find( biCharacterDBID );
if( itor != m_mResult.end() )
return (*itor).second.iResultGradePoint;
return 0;
}
#if defined(PRE_ADD_DWC)
void CDWCStats::SetMatchType(MatchType::eCode MatchType)
{
m_MatchType = MatchType;
}
void CDWCStats::OnRecvDWCScore(UINT nTeamID, TDWCTeam* Info, UINT nOppositeTeamID)
{
// 중복초기화들어오면 문제가 있는거다..행여나 발생해도 최신 데이터를 신용한다.
if( m_bInit == true )
_ASSERT(0);
m_nTeamID = nTeamID;
m_nOppositeTeamID = nOppositeTeamID;
m_iGradePoint = Info->nDWCPoint;
m_iHiddenGradePoint = Info->nHiddenDWCPoint;
if(m_iGradePoint <= 0 )
m_iGradePoint = Stats::InitGradePoint;
if(m_iHiddenGradePoint <= 0 )
m_iHiddenGradePoint = Stats::InitGradePoint;
}
CDWCStatsRepository::CDWCStatsRepository( CDNGameRoom* pGameRoom ) :m_pGameRoom(pGameRoom),m_MatchType(MatchType::None)
{
//#############################################
// 평점 계산용
//#############################################
S_Repository[0] = boost::tuple<float,float,float>(1.f,0.4f,0.5f);
S_Repository[1] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
S_Repository[2] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
S_Repository[3] = boost::tuple<float,float,float>(1.f,0.f,0.4f);
S_Repository[4] = boost::tuple<float,float,float>(1.f,0.f,0.3f);
S_Repository[5] = boost::tuple<float,float,float>(1.f,0.f,-0.5f);
HiddenS_Repository[0] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
HiddenS_Repository[1] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
HiddenS_Repository[2] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
HiddenS_Repository[3] = boost::tuple<float,float,float>(1.f,0.f,0.5f);
HiddenS_Repository[4] = boost::tuple<float,float,float>(1.f,-0.2f,0.5f);
HiddenS_Repository[5] = boost::tuple<float,float,float>(1.f,-0.3f,0.5f);
K_Repository[0] = boost::tuple<float,float,float,float>(60.f,60.f,60.f,60.f);
K_Repository[1] = boost::tuple<float,float,float,float>(50.f,50.f,50.f,50.f);
K_Repository[2] = boost::tuple<float,float,float,float>(40.f,40.f,40.f,40.f);
K_Repository[3] = boost::tuple<float,float,float,float>(30.f,30.f,30.f,30.f);
K_Repository[4] = boost::tuple<float,float,float,float>(20.f,20.f,20.f,20.f);
K_Repository[5] = boost::tuple<float,float,float,float>(10.f,10.f,10.f,10.f);
HiddenK_Repository[0] = boost::tuple<float,float,float,float>(120.f,120.f,120.f,120.f);
HiddenK_Repository[1] = boost::tuple<float,float,float,float>(100.f,100.f,100.f,100.f);
HiddenK_Repository[2] = boost::tuple<float,float,float,float>(80.f,80.f,80.f,80.f);
HiddenK_Repository[3] = boost::tuple<float,float,float,float>(60.f,60.f,60.f,60.f);
HiddenK_Repository[4] = boost::tuple<float,float,float,float>(40.f,40.f,40.f,40.f);
HiddenK_Repository[5] = boost::tuple<float,float,float,float>(20.f,20.f,20.f,20.f);
}
bool CDWCStatsRepository::bInitialize()
{
CDNPvPGameRoom* pPvPGameRoom = static_cast<CDNPvPGameRoom*>(m_pGameRoom);
m_MatchType = pPvPGameRoom->GetPvPLadderMatchType();
int iNeedTeamPlayer = LadderSystem::GetNeedTeamCount(m_MatchType);
#if !defined(_WORK) //워크 버전은 팀원 수 확인 패쓰
// A 팀 인원수 확인
if( pPvPGameRoom->GetUserCount( PvPCommon::Team::A ) != iNeedTeamPlayer )
{
_ASSERT(0);
return false;
}
// B 팀 인원수 확인
if( pPvPGameRoom->GetUserCount( PvPCommon::Team::B ) != iNeedTeamPlayer )
{
_ASSERT(0);
return false;
}
#endif
for( UINT i=0 ; i<m_pGameRoom->GetUserCount() ; ++i )
{
CDNUserSession* pSession = m_pGameRoom->GetUserData(i);
if( (pSession->GetTeam() == PvPCommon::Team::A || pSession->GetTeam() == PvPCommon::Team::B) == false )
continue;
}
m_DWCStat[0].SetMatchType(m_MatchType);
m_DWCStat[1].SetMatchType(m_MatchType);
return true;
}
bool CDWCStatsRepository::bIsValidLadderTeam( int iTeam )
{
switch( iTeam )
{
case PvPCommon::Team::A:
case PvPCommon::Team::B:
return true;
}
return false;
}
int CDWCStatsRepository::GetAddGradePoint( int iTeam )
{
if( iTeam == PvPCommon::Team::A)
return m_Result[0].iAddGradePoint;
if( iTeam == PvPCommon::Team::B)
return m_Result[1].iAddGradePoint;
return 0;
}
int CDWCStatsRepository::GetResultGradePoint( int iTeam )
{
if( iTeam == PvPCommon::Team::A)
return m_Result[0].iResultGradePoint;
if( iTeam == PvPCommon::Team::B)
return m_Result[1].iResultGradePoint;
return 0;
}
void CDWCStatsRepository::OnRecvDWCScore(UINT nATeamID, TDWCTeam* ATeamInfo, UINT nBTeamID, TDWCTeam* BTeamInfo)
{
m_DWCStat[0].OnRecvDWCScore(nATeamID, ATeamInfo, nBTeamID);
m_DWCStat[1].OnRecvDWCScore(nBTeamID, BTeamInfo, nATeamID);
}
bool CDWCStatsRepository::QueryUpdateResult( UINT uiWinTeam, PvPCommon::QueryUpdatePvPDataType::eCode Type )
{
if( static_cast<CDNPvPGameRoom*>(m_pGameRoom)->GetPvPGameMode()->GetRemainStartTick() > 0 )
{
#if defined( _WORK )
std::cout << "[Ladder] 시작 전에 종료되어서 DB 업뎃안함!!!" << std::endl;
#endif // #if defined( _WORK )
return false;
}
int nATeamPoint = 0; // A팀 포인트
int nBTeamPoint = 0; // B팀 포인트
for(int nTeam = PvPCommon::Team::A, i = 0 ; nTeam <= PvPCommon::Team::B ; nTeam++, i++)
{
//##############################
// 래더 평점 보정
//##############################
int Ra = 0; // 현재팀
int Rb = 0; // 상대팀
UINT nTeamID = 0;
UINT nOppositeTeamID = 0;
if( nTeam == PvPCommon::Team::A )
{
Ra = nATeamPoint;
Rb = nBTeamPoint;
}
else
{
Ra = nBTeamPoint;
Rb = nATeamPoint;
}
int iTupleIndex = 0;
// 최하유저
if( Ra < 1400 )
iTupleIndex = 0;
// 기본 유저
else if( Ra < 1700 )
iTupleIndex = 1;
// 일반 유저
else if( Ra < 2000 )
iTupleIndex = 2;
// 상위 유저
else if( Ra < 2300 )
iTupleIndex = 3;
// 코어 유저
else if( Ra < 2500 )
iTupleIndex = 4;
// 안드로 유저
else
iTupleIndex = 5;
if( iTupleIndex >= MAX_GRADEPOINT_RANGE )
{
_ASSERT(0);
iTupleIndex = 0;
}
//##############################
// 경기결과
//##############################
float S = 0.f;
float HiddenS = 0.f;
float K = 0.f;
float HiddenK = 0.f;
MatchResult::eCode Result = MatchResult::Lose;
switch( Type )
{
case PvPCommon::QueryUpdatePvPDataType::FinishGameMode:
{
if( uiWinTeam == PvPCommon::Team::Max ) // 무승부
{
Result = MatchResult::Draw;
S = S_Repository[iTupleIndex].get<2>();
HiddenS = HiddenS_Repository[iTupleIndex].get<2>();
}
else if( uiWinTeam == nTeam ) // 승
{
Result = MatchResult::Win;
S = S_Repository[iTupleIndex].get<0>();
HiddenS = HiddenS_Repository[iTupleIndex].get<0>();
}
else // 패
{
Result = MatchResult::Lose;
S = S_Repository[iTupleIndex].get<1>();
HiddenS = HiddenS_Repository[iTupleIndex].get<1>();
}
break;
}
}
switch( m_MatchType )
{
case MatchType::_3vs3_DWC:
case MatchType::_3vs3_DWC_PRACTICE: // 얘는 포인트 줄건지 말건지 확인
{
K = K_Repository[iTupleIndex].get<2>();
HiddenK = HiddenK_Repository[iTupleIndex].get<2>();
break;
}
}
//##############################
// 예상승률
//##############################
float Ea = 1/(1.f+pow(10,(Rb-Ra)/400.f));
//##############################
// 평점 변화량
//##############################
float ChangeRa = K*(S-Ea);
float ChangeHiddenRa = HiddenK*(HiddenS-Ea);
//##############################
// flaot 반올림 처리
//##############################
ChangeRa = static_cast<float>(static_cast<int>(ChangeRa + (ChangeRa > 0.f ? .5f : -.5f) )) / 1.f;
ChangeHiddenRa = static_cast<float>(static_cast<int>(ChangeHiddenRa + (ChangeHiddenRa > 0.f ? .5f : -.5f) )) / 1.f;
//##############################
// Query 날리기~
//##############################
BYTE cThreadID;
CDNDBConnection* pDBCon = g_pDBConnectionManager->GetDBConnection( cThreadID );
if( pDBCon == NULL )
return false;
int iGradePoint = m_DWCStat[i].GetGradePoint()+static_cast<int>(ChangeRa);
int iHiddenGradePoint = m_DWCStat[i].GetHiddenGradePoint()+static_cast<int>(ChangeHiddenRa);
if( iGradePoint < Stats::MinGradePoint )
iGradePoint = Stats::MinGradePoint;
if( iHiddenGradePoint < Stats::MinGradePoint )
iHiddenGradePoint = Stats::MinGradePoint;
#if defined( _WORK )
std::cout << "[DWC] TeamID:" << m_DWCStat[i].GetTeamID() << " 결과:" << Result << std::endl;
std::cout << "[DWC] 평점변화 " << m_DWCStat[i].GetGradePoint() << "->" << iGradePoint << std::endl;
std::cout << "[DWC] 가평점변화 " << m_DWCStat[i].GetHiddenGradePoint() << "->" << iHiddenGradePoint << std::endl;
#endif // #if defined( _WORK )
g_Log.Log( LogType::_LADDER, L"[TeamID:(%d)] DWC result gradepoint:%d\r\n", m_DWCStat[i].GetTeamID(), iGradePoint );
m_Result[i] = SResult(static_cast<int>(ChangeRa),iGradePoint );
pDBCon->QueryAddPvPDWCResult(cThreadID, m_pGameRoom->GetWorldSetID(), m_pGameRoom->GetRoomID(), 0, m_DWCStat[i].GetTeamID(), m_DWCStat[i].GetOppositeTeamID(), m_MatchType, Result, iGradePoint, iHiddenGradePoint );
}
return true;
}
#endif