📄 logplayer.cpp
字号:
#include "StdAfx.h"
#include "logplayer.h"
#include "MainFrm.h"
#include "CycleSlider.h"
/************************************************************************/
/* CParserThread Class */
/************************************************************************/
int CParserThread::Run()
{
_bAlive = true;
_pParser->parseLog(*_pLogFile);
_bAlive = false;
_pLogFile->Close();
return 0;
}
BOOL CParserThread::InitInstance()
{
// do nothing
return TRUE;
}
CParserThread::~CParserThread()
{
if( _bAlive) {
::TerminateThread(m_hThread,0);
}
}
/************************************************************************/
/* CLogPlayer Class */
/************************************************************************/
CLogPlayer::CLogPlayer(void) : m_cycle_infos(8000),_pParserThread(NULL),_pGZFile(NULL)
{
_LogParserFactory.init(this);
_DispinfoParserFactory.init(this);
init();
}
CLogPlayer::~CLogPlayer(void)
{
if( _pParserThread ){
delete _pParserThread;
_pParserThread = NULL;
}
if( _pGZFile ){
delete _pGZFile;
}
}
void CLogPlayer::init()
{
m_player_types.clear();
m_cycle_infos.clear();
m_dFreq = 100.0;
m_nCurrent = 0;
m_bTimerAlive = false;
m_bReverse = false;
}
bool CLogPlayer::addDispInfo(const dispinfo_t2* pInfo)
{
CDispinfoParser* pParser = _DispinfoParserFactory.getParser(2); // fix me
if( pParser)
return pParser->parseDispinfo((BYTE *)pInfo);
else
return false;
}
bool CLogPlayer::DoCommand(LogPlayerCommand cmd,CString strValue)
{
switch(cmd){
case CmdLoad:
return LoadLog();
break;
case CmdOpen:
return OpenLog(strValue);
break;
case CmdPlay:
PlayLog();
break;
case CmdReverse:
ReverseLog();
break;
case CmdStop:
StopPlay();
break;
case CmdAccelerate:
Accelerate();
break;
case CmdDecelerate:
Decelerate();
break;
case CmdRewind:
RewindLog();
break;
case CmdForward:
Forward();
break;
case CmdBackward:
Backward();
break;
case CmdJump:
JumpTo();
break;
case CmdClean:
init();
break;
case CmdSaveLog:
SaveLog();
break;
default:
break;
}
return true;
}
void CLogPlayer::Decelerate()
{
if(!m_bTimerAlive)
return;
if(m_dFreq < 1000){
m_dFreq *= 2.0;
TimerStop();
TimerStart();
}
}
void CLogPlayer::Accelerate()
{
if(!m_bTimerAlive)
return;
if(m_dFreq > 10){
m_dFreq /= 2.0;
TimerStop();
TimerStart();
}
}
bool CLogPlayer::LoadLog( )
{
CFileDialog openDlg(TRUE,NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, NULL, NULL,0);
if(openDlg.DoModal()!=IDOK){
return false;
}
return OpenLog(openDlg.GetPathName());
}
bool CLogPlayer::OpenLog(CString logFileName)
{
/* close previous opened file before opening new one */
TimerStop();
if( _pParserThread ){
delete _pParserThread;
_pParserThread = NULL;
}
if( _pGZFile ){
delete _pGZFile;
_pGZFile = NULL;
}
_pGZFile = new CGZFile(logFileName);
if( _pGZFile->Good() ){
ParseLog(_pGZFile);
}
return true ;
}
bool CLogPlayer::ParseLog(CGZFile *pLogFile)
{
m_cycle_infos.clear();
m_player_types.clear();
CLogParser* pParser = _LogParserFactory.getParser(*pLogFile);
if( pParser != NULL ) {
_pParserThread = new CParserThread(pLogFile,pParser);
_pParserThread->CreateThread(); // 读文件线程开始
}
return false; // 没有东西能这个分析此文件
}
void CLogPlayer::PlayLog()
{
TimerStart();
m_bReverse = false;
}
void CLogPlayer::ReverseLog()
{
TimerStart();
m_bReverse = true;
}
void CLogPlayer::StopPlay()
{
TimerStop();
}
void CLogPlayer::TimerStart()
{
if(!m_bTimerAlive){
_pMainFrame->SetTimer(IDT_LOGPLAYER,(UINT)m_dFreq,NULL);
m_bTimerAlive = true;
}
}
void CLogPlayer::TimerStop()
{
if(m_bTimerAlive){
_pMainFrame->KillTimer(IDT_LOGPLAYER);
m_bTimerAlive = false;
}
}
void CLogPlayer::WriteStatus(CString str)
{
_pMainFrame->WriteStatus(str);
}
const cycle_info_t* CLogPlayer::GetDisplayInfo()
{
_Mutex.Lock();
if( m_cycle_infos.empty() ){
_Mutex.Unlock();
return NULL;
}
if( m_bTimerAlive ){
if( m_bReverse ){
if( m_nCurrent > 0 )
m_nCurrent--;
else
TimerStop();
} else {
if( m_nCurrent < m_cycle_infos.size() - 1)
m_nCurrent++;
else
TimerStop();
}
}
_CurrentCycle = m_cycle_infos[m_nCurrent];
_Mutex.Unlock();
return &_CurrentCycle;
}
const cycle_info_t* CLogPlayer::GetLastDispInfo()
{
if( m_cycle_infos.empty() ) {
return NULL;
}
return &m_cycle_infos[m_cycle_infos.size()-1];
}
bool CLogPlayer::getCommandStatus(LogPlayerCommand cmd)
{
if( cmd == CmdLoad ) {
return true; // 打开文件随时可以
}
if( m_cycle_infos.empty() ) {
return false; // 没有记录,不能播放
}
switch(cmd){
case CmdPlay:
return !m_bTimerAlive || ( m_bTimerAlive && m_bReverse);
break;
case CmdReverse:
return !m_bTimerAlive || (m_bTimerAlive && !m_bReverse);
break;
case CmdStop:
return m_bTimerAlive;
break;
case CmdAccelerate:
return m_dFreq > MIN_FREQ;
break;
case CmdDecelerate:
return m_dFreq < MAX_FREQ;
break;
case CmdRewind:
return m_nCurrent != 0;
break;
default:
break;
}
return true;
}
void CLogPlayer::RewindLog()
{
TimerStop();
m_nCurrent = 0;
}
void CLogPlayer::Backward()
{
TimerStop();
if(m_nCurrent >0)
m_nCurrent--;
}
void CLogPlayer::Forward()
{
TimerStop();
if(m_nCurrent < m_cycle_infos.size() - 1)
m_nCurrent++;
}
short CLogPlayer::GetMaxCycle()
{
if(m_cycle_infos.empty())
return 0;
else
return m_cycle_infos[m_cycle_infos.size()-1].cycle;
}
short CLogPlayer::GetMinCycle()
{
if(m_cycle_infos.empty())
return 0;
else
return m_cycle_infos[0].cycle;
}
short CLogPlayer::GetCurrentCycle()
{
if(m_cycle_infos.empty())
return 0;
else
return m_cycle_infos[m_nCurrent].cycle;
}
void CLogPlayer::JumpTo()
{
bool bRestorTimer = m_bTimerAlive;
TimerStop();
CCycleSlider cycleSlider(this,GetMinCycle(),GetMaxCycle(),GetCurrentCycle());
if( cycleSlider.DoModal() == IDOK )
m_nCurrent = FindCyclePos(cycleSlider.GetPos());
if( bRestorTimer ){
TimerStart();
}
}
int CLogPlayer::FindCyclePos(short nCycle)
{
// 二分查找
short nMin = 0;
short nMax = m_cycle_infos.size() - 1;
short nMid = (nMin + nMax)/2; // 中点
while(true){
if( m_cycle_infos[nMid].cycle == nCycle ){
return nMid;
}
if( m_cycle_infos[nMid].cycle < nCycle ){ // 目标在右边
nMin = nMid;
}else{ // 目标在左边
nMax = nMid;
}
nMid = (nMax + nMin)/2;
if( nMid == nMax || nMid == nMin ){ // 目标已找到,或者已不可能找到
return nMid;
}
}
return nMid;
}
void CLogPlayer::DisplayCycle(UINT nCycle)
{
if( m_cycle_infos.empty() )
return ;
int nPos = FindCyclePos(nCycle);
if( nPos >= 0 ){
_pMainFrame->DisplayCycle(&m_cycle_infos[nPos]);
}
}
const player_type_t* CLogPlayer::getPlayerType(UINT nType)
{
for(UINT i = 0; i < m_player_types.size() ;i++){
if(ntohs(m_player_types[i].id) == nType)
return &m_player_types[i];
}
return NULL;
}
void CLogPlayer::addOneCycle(const cycle_info_t& cInfo)
{
_Mutex.Lock();
m_cycle_infos.push_back(cInfo) ;
_pMainFrame->analyzeCycle(cInfo.show);
if( m_cycle_infos.size() == 1 ){ // 第一帧
_CurrentCycle = cInfo;
_pMainFrame->DisplayCycle(&_CurrentCycle);
}
_Mutex.Unlock();
}
bool CLogPlayer::SaveLog(void)
{
bool bRestorTimer = m_bTimerAlive;
TimerStop();
CFileDialog saveDlg(FALSE,NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, NULL, NULL,0);
if(saveDlg.DoModal()!=IDOK){
return false;
}
CGZFile saveFile(saveDlg.GetPathName(),CGZFile::ModeSave);
saveFile.Write("ULG",3);
BYTE iVersion = 3;
saveFile.Write(&iVersion,sizeof(iVersion));
CString TeamNameLeft,TeamNameRight;
short ScoreLeft=0,ScoreRight=0;
char PlayMode = 0;
short_showinfo_t2 info;
saveFile.Write(htons(PARAM_MODE));
saveFile.Write(&m_ServerParams,sizeof(server_params_t));
saveFile.Write(htons(PPARAM_MODE));
saveFile.Write(&m_PlayerParams,sizeof(player_params_t));
for( int i=0; i<m_player_types.size(); i++ ){
saveFile.Write(htons(PT_MODE));
saveFile.Write(&m_player_types[i],sizeof(player_type_t));
}
for( int i=0; i<m_cycle_infos.size(); i++ ){
if(!m_cycle_infos[i].bSight){
if( PlayMode != m_cycle_infos[i].show.pmode ){
PlayMode = m_cycle_infos[i].show.pmode;
saveFile.Write(htons(PM_MODE));
saveFile.Write(&PlayMode,sizeof(PlayMode));
}
if( TeamNameLeft != m_cycle_infos[i].show.team[0].name || TeamNameRight != m_cycle_infos[i].show.team[1].name ||
ScoreLeft != m_cycle_infos[i].show.team[0].score || ScoreRight != m_cycle_infos[i].show.team[1].score ){
saveFile.Write(htons(TEAM_MODE));
TeamNameLeft = m_cycle_infos[i].show.team[0].name;
TeamNameRight = m_cycle_infos[i].show.team[1].name;
ScoreLeft = m_cycle_infos[i].show.team[0].score;
ScoreRight = m_cycle_infos[i].show.team[1].score;
saveFile.Write(m_cycle_infos[i].show.team,sizeof(m_cycle_infos[i].show.team));
}
if( strlen(m_cycle_infos[i].msg) > 0 ){
const char* p1=m_cycle_infos[i].msg;
const char* p2;
short len;
while( *p1 && (p2 = strstr(p1,MSG_FOOTER)) ){ // MSG_FOOTER是每一行的结尾
saveFile.Write(htons(MSG_MODE));
saveFile.Write(htons(MSG_BOARD));
len = p2 - p1;
saveFile.Write(htons(len)); // 不用写入MSG_FOOTER
saveFile.Write((const voidp)p1,len);
p1 = p2 + strlen(MSG_FOOTER); // skip MSG_FOOTER
}
}
saveFile.Write(htons(SHOW_MODE));
info.ball = m_cycle_infos[i].show.ball;
memcpy(info.pos,m_cycle_infos[i].show.pos,sizeof(info.pos));
info.time = m_cycle_infos[i].show.time;
saveFile.Write(&info,sizeof(info));
}
}
if( bRestorTimer ){
TimerStart();
}
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -