📄 raindoc.cpp
字号:
// rainDoc.cpp : implementation of the CRainDoc class
//
#include "stdafx.h"
#include "rain.h"
#include "rainDoc.h"
#include "rainView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CRainDoc *PDocument;
/////////////////////////////////////////////////////////////////////////////
// CRainDoc
IMPLEMENT_DYNCREATE(CRainDoc, CDocument)
BEGIN_MESSAGE_MAP(CRainDoc, CDocument)
//{{AFX_MSG_MAP(CRainDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRainDoc construction/destruction
CRainDoc::CRainDoc()
{
// TODO: add one-time construction code here
CString tmpStr;
PDocument=this;
stepBetweenStr=0;
maxStrlen=0;
stepTime=DFT_TIMER;
allStr=50;
localUsrName="";
fileName="";
rainType=RT_LOCAL;
rainSource=RS_RANDOM;
rainLevel=RL_0;
rainState=RS_STOPPED;
rainMsg=STOPPED_MSG;
isFileOpened=0;
initRain();
if(!recordFile.Open(RECORD_FILE,CFile::modeRead,NULL))
{
#if DEBUG_RAIN
TRACE("\nno record file\n");
#endif
recordSpeed=0;
recordUsrName="*";
recordCreateTime="*";
}
else
{
recordFile.ReadString(tmpStr);
recordSpeed=atoi(tmpStr);
recordFile.ReadString(tmpStr);
int i=tmpStr.GetLength();
recordUsrName=tmpStr.Left(i-1);
recordFile.ReadString(tmpStr);
i=tmpStr.GetLength();
recordCreateTime=tmpStr.Left(i-1);
recordFile.Close();
}
}
CRainDoc::~CRainDoc()
{
char buffer[]={13,10};
CString tmpStr;
if(recordFile.Open(RECORD_FILE,CFile::modeCreate|CFile::modeWrite,NULL))
{
tmpStr.Format("%d",recordSpeed);
recordFile.WriteString(tmpStr);
recordFile.Write(buffer,2);
recordFile.WriteString(recordUsrName);
recordFile.Write(buffer,2);
recordFile.WriteString(recordCreateTime);
recordFile.Write(buffer,2);
recordFile.Close();
}
}
void CRainDoc::initRain()
{
for (int i=0;i<RAIN_Y;i++)
{
rainStr[i].state=STR_FREE;
rainStr[i].strlen=0;
rainStr[i].timer=0;
}
totalStr=0;
stepBeforeNewStr=0;
usrRightLen=0;
rightStr=0;
maxFitStrAddr=-1;
rightChar=0;
totalTime=0;
tmpTime=0;
lastNumber=-1;
StrSequence=0;
tick_timer=0;
demoStep=0;
demoTick=0;
demoState=0;
currentSpeed=0;
closeFile();
server.init();
client.init();
}
int CRainDoc::strNew()
{
int find;
int len,i,j;
int returnVaule;
int ret;
find=0;
for (i=0;i<RAIN_Y;i++)
{
if (rainStr[i].state==STR_FREE)
{
find=1;
break;
}
}
if (!find)
{
return 0;
}
returnVaule=0;
switch(rainType)
{
case RT_SERVER:
case RT_LOCAL:
if(rainSource==RS_RANDOM)
{
if(totalStr<allStr)
{
len=MapRand(maxStrlen-1)+1;// len < RAIN_X
for (j=0;j<len;j++)
{
rainStr[i].string[j]='a'+MapRand(25);
}
rainStr[i].string[len]=0;
rainStr[i].strlen=len;
if(rainType==RT_SERVER)
{
rainStr[i].whereX=STATE_WIDE+MapRand(RAIN_X-STATE_WIDE-len);//
}
else//rainType==RT_LOCAL
{
rainStr[i].whereX=MapRand(RAIN_X-len);
}
rainStr[i].whereY=0;
stepBeforeNewStr=stepBetweenStr;
totalStr++;
rainStr[i].state=STR_USE;
}
else
{
returnVaule=1;
}
}
else//rainSource==RS_FILE
{
if(rainType==RT_SERVER)
{
ret=readFileStr(rainStr[i].string,RAIN_X-STATE_WIDE);
}
else//rainType==RT_LOCAL
{
ret=readFileStr(rainStr[i].string,RAIN_X);
}
if(ret)
{
rainStr[i].strlen=strlen(rainStr[i].string);//
if(rainType==RT_SERVER)
{
rainStr[i].whereX=STATE_WIDE+MapRand(RAIN_X-STATE_WIDE-rainStr[i].strlen);//
}
else//rainType==RT_LOCAL
{
rainStr[i].whereX=MapRand(RAIN_X-rainStr[i].strlen);//
}
rainStr[i].whereY=0;
totalStr++;
stepBeforeNewStr=stepBetweenStr;
rainStr[i].state=STR_USE;
}
else
{
returnVaule=1;
}
}
// as server,must dispatch new string to clients
if((rainType==RT_SERVER)&&(!returnVaule))
{
rainStr[i].sequence=StrSequence;
server.dispatchStr(rainStr[i].string,
rainStr[i].strlen,
rainStr[i].whereX,
StrSequence);
StrSequence++;
}
break;
}
return returnVaule;
}
void CRainDoc::insertStr(char *str,int strlen,int whereX,ULONG seq)
{
int i,j;
for (i=0;i<RAIN_Y;i++)
{
if (rainStr[i].state==STR_FREE)
{
for(j=0;j<strlen;j++)
{
rainStr[i].string[j]=str[j];
}
rainStr[i].string[strlen]=0;
rainStr[i].strlen=strlen;
rainStr[i].sequence=seq;
rainStr[i].whereX=whereX;
rainStr[i].whereY=0;
rainStr[i].state=STR_USE;
break;
}
}
}
int CRainDoc::rainStep()
{
int returnVaule;
returnVaule=0;
for (int i=0;i<RAIN_Y;i++)
{
//process USE string
if (rainStr[i].state==STR_USE)
{
rainStr[i].whereY++;
if (rainStr[i].whereY==RAIN_Y) // the string is fall!
{
strFree(i,STR_FREE);
}
}
//process FREEING string
if ((rainStr[i].state==STR_FREEING)
||(rainStr[i].state==STR_FREEING2))
{
strFree(i,STR_FREE);
}
//process WAITING string
if (rainStr[i].state==STR_WAITING)
{
rainStr[i].whereY++;//
}
}
//check lastNumber if flag is set
if(lastNumber==-1)
{
if (stepBeforeNewStr==0)
{
if(strNew())//end of rain source
{
lastNumber=findUseStr();//set this flag now,later it will down to 0
#if DEBUG_RAIN
TRACE("\nlastNumber %d\n",lastNumber);
#endif
}
}
else
{
stepBeforeNewStr--;
}
}
else
{
if (lastNumber==0)
{
returnVaule=1;
}
}
return returnVaule;
}
void CRainDoc::rainDemo()
{
/*
* demoState==0 : need re paint
* demoState==1 : need not
* demoState==2 : slient state
*/
if(demoState==2)
{
return;
}
demoTick++;
if(demoTick==5)
{
demoStep=1;
demoState=0;
}
if(demoTick==15)
{
demoStep=0;
demoTick=0;
}
}
int CRainDoc::charInput(char aChar)
{
int tmpUsrRightLen=0;
int tmpMaxFitStrAddr=-1;
int returnVaule;
int i;
// put a new char to the end,usrRightLen+1==input string len
if ((aChar==8)||(aChar==32)) //backspace or blank
{
if (usrRightLen>0)
{
usrRightLen=0;
maxFitStrAddr=-1;
}
return 0;
}
usrPressed[usrRightLen]=aChar;
returnVaule=0;
// check the user input
for (i=0;i<RAIN_Y;i++)
{
if (rainStr[i].state==STR_USE)
{
for (int j=0;j<usrRightLen+1;j++)
{
if (usrPressed[j]!=rainStr[i].string[j])
break;
}
if (j>tmpUsrRightLen)
{
// I'm the fittest at this time
tmpUsrRightLen=j;
tmpMaxFitStrAddr=i;
}
if ((j==tmpUsrRightLen)&&(rainStr[i].whereY>rainStr[tmpMaxFitStrAddr].whereY))
{
tmpMaxFitStrAddr=i;
}
}
}
// find the fittest string
maxFitStrAddr=tmpMaxFitStrAddr;
usrRightLen=tmpUsrRightLen;
if(maxFitStrAddr>=0)
{
// the user input hit the string!
if(usrRightLen==rainStr[maxFitStrAddr].strlen)
{
returnVaule=1;
}
}
return returnVaule;
}
void CRainDoc::setRainMsg(CString msg)
{
rainMsg=msg;
}
CString CRainDoc::getRainMsg()
{
return rainMsg;
}
void CRainDoc::strHit()
{
CString tmpStr;
ULONG tmpTickTimer;
switch(rainType)
{
case RT_SERVER:
usrPressed[usrRightLen]=0;
tmpTickTimer=tick_timer;
#if DEBUG_RAIN
TRACE("server tick_timer:0x%x\n",tick_timer);
#endif
if(server.checkUsrHit(rainStr[maxFitStrAddr].sequence,tmpTickTimer))
{
//insert this string into server hit list
server.insertUsrHit(rainStr[maxFitStrAddr].sequence,tmpTickTimer,usrRightLen);
}
strFree(maxFitStrAddr,STR_WAITING);
/* if user press fast,then rain fast */
if (!findUseStr())
{
stepBeforeNewStr=0;
}
break;
//maybe some msg
case RT_LOCAL:
usrPressed[usrRightLen]=0;
rightStr++;
rightChar+=usrRightLen;
strFree(maxFitStrAddr,STR_FREEING);
/* if user press fast,then rain fast */
if (!findUseStr())
{
stepBeforeNewStr=0;
}
tmpStr.Format("' %s '",usrPressed);
tmpStr+=" OK";
setRainMsg(tmpStr);
break;
case RT_CLIENT:
usrPressed[usrRightLen]=0;
client.hit(rainStr[maxFitStrAddr].sequence,tick_timer,usrRightLen);
strFree(maxFitStrAddr,STR_WAITING);
break;
}
}
void CRainDoc::strHitAck(ULONG seq,CString usrName,int flag)
{
int i;
CString tmpStr;
for(i=0;i<RAIN_Y;i++)
{
if(rainStr[i].sequence==seq)//&&(rainStr[i].state!=STR_FREEING))
{
if(!flag)
{
strFree(i,STR_FREEING);
}
else
{
strFree(i,STR_FREEING2);
}
tmpStr.Format("' %s '",rainStr[i].string);
tmpStr+=" hitted by ";
tmpStr+="' ";
tmpStr+=usrName;
tmpStr+=" '";
setRainMsg(tmpStr);
break;
}
}
}
int CRainDoc::findUseStr()
{
int i,count=0;
for (i=0;i<RAIN_Y;i++)
{
if((rainStr[i].state==STR_USE)
||(rainStr[i].state==STR_FREEING)
||(rainStr[i].state==STR_FREEING2))//
{
count++;
}
}
return count;
}
void CRainDoc::strFree(int i,int state)
{
switch(state)
{
case STR_FREE:
// if from USE to FREE
if(rainStr[i].state==STR_USE)
{
//this show user not hit this string
rainStr[i].state=STR_FREE;
rainStr[i].timer=0;
if (i==maxFitStrAddr)
{
usrRightLen=0;
maxFitStrAddr=-1;
}
if (lastNumber!=-1)
{
lastNumber--;
}
}
// if from FREEING to FREE
if((rainStr[i].state==STR_FREEING)
||(rainStr[i].state==STR_FREEING2))
{
//wait some step before free
if (rainStr[i].timer==1)
{
rainStr[i].state=STR_FREE;
rainStr[i].timer=0;
if (lastNumber!=-1)
{
lastNumber--;
}
}
else// not this time
{
rainStr[i].timer++;
}
}
break;
case STR_FREEING:
case STR_FREEING2:
if(rainStr[i].state!=STR_WAITING)
{
usrRightLen=0;
maxFitStrAddr=-1;
}
rainStr[i].state=state;
break;
case STR_WAITING: //this not use for local
rainStr[i].state=STR_WAITING;
usrRightLen=0;
maxFitStrAddr=-1;
break;
}
}
int CRainDoc::getRainState()
{
return rainState;
}
int CRainDoc::getStrState(int i)
{
int j=rainStr[i].state;
return j;
}
int CRainDoc::getStrWhereX(int i)
{
return rainStr[i].whereX;
}
int CRainDoc::getStrWhereY(int i)
{
return rainStr[i].whereY;
}
CString CRainDoc::getStr(int i)
{
char tmpBuffer[RAIN_X];
CString tmpString;
for(int j=0;j<rainStr[i].strlen;j++)
{
tmpBuffer[j]=rainStr[i].string[j];
}
tmpBuffer[rainStr[i].strlen]=0;
tmpString.Format("%s",tmpBuffer);
return tmpString;
}
BOOL CRainDoc::isFittestStr(int i)
{
if(i==maxFitStrAddr)
{
return 1;
}
return 0;
}
CString CRainDoc::getFittestStr()
{
char tmpBuffer[RAIN_X];
CString tmpString;
for(int i=0;i<usrRightLen;i++)
{
tmpBuffer[i]=rainStr[maxFitStrAddr].string[i];
}
tmpBuffer[usrRightLen]=0;
tmpString.Format("%s",tmpBuffer);
return tmpString;
}
int CRainDoc::openFile(CString filename)
{
int ret;
if(isFileOpened)
{
return 0;
}
ret=file.Open(fileName,CFile::modeRead,NULL);
if(ret)
{
isFileOpened=1;
}
return ret;
}
void CRainDoc::closeFile()
{
if(isFileOpened)
{
file.Close();
isFileOpened=0;
}
}
int CRainDoc::readFileStr(char *buffer,int max)
{
char tmp;
int index,ret;
if(!isFileOpened)
{
return 0;
}
//get first char
tmp=0;
ret=file.Read(&tmp,1);
while((tmp==13)||(tmp==10)||(tmp==32))
{
ret=file.Read(&tmp,1);
if(ret==0) /* ret==0 ,reach file end */
{
break;
}
}
index=0;
for(;;)
{
if(ret==1)
{
if((tmp==13)||(tmp==10)||(tmp==32))
{
if(index>0)//may be needn't check here
{
buffer[index]=0;
}
break;
}
else
{
buffer[index++]=tmp;
if(index==max)
{
buffer[index]=0;
break;
}
}
}
else /* ret==0 ,reach file end */
{
if(index>0)
{
buffer[index]=0;
}
break;
}
ret=file.Read(&tmp,1); //get a new char
}
return index;
}
void CRainDoc::setRainState(int state)
{
rainState=state;
}
void CRainDoc::countTime()
{
tmpTime+=stepTime;
totalTime+=tmpTime/1000;
tmpTime%=1000;
}
int CRainDoc::getTotalTime()
{
return totalTime;
}
int CRainDoc::getTotalStrNum()
{
return totalStr;
}
int CRainDoc::getRightStrNum()
{
return rightStr;
}
int CRainDoc::getRightCharNum()
{
return rightChar;
}
int CRainDoc::getDemoStep()
{
return demoStep;
}
void CRainDoc::setDemoState(int state)
{
demoState=state;
if(state==0)
{
demoStep=0;
demoTick=0;
}
}
int CRainDoc::getDemoState()
{
return demoState;
}
///////////////////////////////////////////////////////////////
// CRainDoc diagnostics
#ifdef _DEBUG
void CRainDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CRainDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -