카카오톡 특정 인물 대화 내역 보기 - 개발 #3
이전 과정
https://push-back.tistory.com/11?category=1004907
CFind.cpp
데이터를 추출하여 큐에 담는다.
SetFile(CString arg_filePath, CString arg_Imposter)
메인 다이얼로그로부터 파일 경로와 임포스터 이름을 받는다.
void CFind::SetFile(CString arg_filePath, CString arg_Imposter)
{
m_FilePath = arg_filePath;
m_Imposter = arg_Imposter;
OpenFile();
}
OpenFile()
유니코드 형식의 파일을 읽는다
void CFind::OpenFile()
{
FILE* fStream;
fStream = NULL;
errno_t err = _wfopen_s(&fStream, m_FilePath, _T("rb,ccs=UNICODE"));
if (err != 0)
{
// error
}
else
{
CStdioFile file(fStream);
CString str;
while (file.ReadString(str))
{
int nLen = str.GetLength();
Find(str, nLen);
}
file.Close(); // Close File
}
}
Find(CString arg_str, int str_len)
isChat으로 TYPE_CHAT인지 판별하고
TYPE_CHAT이 아니면 TYPE_DATE인지 판별하고
TYPE_CHAT도, TYPE_DATE도 아니면 TYPE_IN, TYPE_OUT, TYPE_KICK, TYPE_ANN인지 판별한다.
함수 이름에서도 알 수 있듯이 TYPE_IN OUT KICK ANN 은 함께 처리했다.
왜냐하면 일일이 함수 나누기도 귀찮았고 네 개의 타입은 같은 과정으로 추출할 것이기 때문이다.
void CFind::Find(CString arg_str, int str_len)
{
int isChat, isDate, isIn_Out_Kick_Ann = 0;
// Date
isChat = Find_Chat(arg_str, str_len); // 채팅인지 판별
if (isChat != TYPE_CHAT) // 채팅 아니면
{
isDate = Find_Date(arg_str, str_len); // 날짜인지
isIn_Out_Kick_Ann = (isDate != TYPE_DATE) ? Find_In_Out_Kick_Ann(arg_str, str_len) : isDate;
if (isIn_Out_Kick_Ann > 0)
{
Push_Data(arg_str, isIn_Out_Kick_Ann);
}
}
else
{
Find_Chat_1(arg_str, str_len);
}
}
Find_Chat(CString arg_str, int str_len)
채팅 타입인지 판별한다.
1. 대괄호 두 개 있으면 채팅 타입
1.1. 채팅 내용에 줄바꿈 하고 대괄호 두 개를 쓰면 채팅으로 간주할 것이기 때문에 신뢰성을 위해 2번 추가
2. " ] [오" 라는 글자가 있으면 채팅 타입
2.1. [이름] [오후 시각] 채팅 내용
또는
[이름] [오전 시각] 채팅 내용
의 형태로 돼있기 때문
// 타입이 채팅인지 판별
int CFind::Find_Chat(CString arg_str, int str_len)
{
int nChat_Count = 0;
int nType = 0;
CString buf;
CString strImposter;
buf.Format(_T("%s"), L"]");
for (int i = 0; i < str_len; i++)
{
if (arg_str[i] == buf)
{
nChat_Count++;
}
}
nType = (nChat_Count == 2) ? TYPE_CHAT : nType; // 대괄호 두개 있으면 채팅 타입
bChatting = (nChat_Count == 2) ? true : false;
// 한번 더 검사 for 신뢰성
int isChat = arg_str.Find(L"] [오"); // [ ] [오후] [ ] [오전]
nType = (isChat != -1) ? TYPE_CHAT : nType;
bChatting = (isChat != -1) ? true : false;
return nType;
}
Find_Chat_1(CString arg_str, int str_len)
임포스터가 한 채팅이 맞으면
채팅 타입인 이상 무조건 대괄호 이후는 채팅이라고 가정하여
대괄호 이후의 글자들을 추출하여 큐에 넣는다.
void CFind::Find_Chat_1(CString arg_str, int str_len)
{
int isImposter = arg_str.Find(m_Imposter);
// 임포스터의 이름이 맞으면
if (isImposter != -1)
{
IsExist = true;
bIsImposter = true;
// 채팅만 추출
CString strChat = L"";
AfxExtractSubString(strChat, arg_str, 2, ']'); // 2번째 대괄호 이후 채팅임
Push_Data(strChat, TYPE_CHAT); // Push Data
}
// 임포스터의 이름이 아니면
else
{
bIsImposter = false;
}
}
Find_Date(CString arg_str, int str_len)
날짜를 찾는다.
하이픈이 정확히 15개이면 날짜라고 간주
int CFind::Find_Date(CString arg_str, int str_len)
{
int nType = 0;
CString strHyphen = L"";
strHyphen.Format(_T("%s"), L"-");
bool isHypen = false;
// 날짜 : 하이픈이 연속으로 15개 나와야함
// Find는 하이픈 인식 못해서 15번 돌리는걸로 코딩했지만 추후 수정 예정
for (int i = 0; i < 15; i++)
{
if (arg_str[i] == strHyphen)
{
isHypen = true;
}
else
{
isHypen = false;
break;
}
}
// 날짜를 나타내는 텍스트가 맞으면
if (isHypen)
{
nDate = Find_Data_1(arg_str); // 날짜 저장
nType = (nDate > 0) ? TYPE_DATE : 0;
}
return nType;
}
Find_Data_1(CString arg_str)
날짜 추출해서
int 형태로 집어넣을 것이기 때문에 int로 변환한다.
int CFind::Find_Data_1(CString arg_str) // 날짜 추출
{
int nYearIndex, nMonthIndex, nDayIndex = 0;
nYearIndex = arg_str.Find(_T("년"));
nMonthIndex = arg_str.Find(_T("월"));
nDayIndex = arg_str.Find(_T("일"));
CString strYear, strMonth, strDay;
for (int i = 0; i < 4; i++)
{
strYear = strYear + arg_str[nYearIndex - 4 + i];
}
for (int i = 0; i < 2; i++)
{
strMonth = strMonth + arg_str[nMonthIndex - 2 + i];
}
for (int i = 0; i < 2; i++)
{
strDay = strDay + arg_str[nDayIndex - 2 + i];
}
int nYear, nMonth, nDay = 0;
nYear = _ttoi(strYear);
nMonth = _ttoi(strMonth);
nDay = _ttoi(strDay);
int nDate_final = nYear * 10000 + nMonth * 100 + nDay;
return nDate_final;
}
Find_In_Out_Kick_Ann(CString arg_str, int str_len)
입장, 퇴장, 강퇴, 시스템 안내 타입인지 판별하고
위 타입 모두 아니면 줄바꿈 한 채팅으로 간주한다.
int CFind::Find_In_Out_Kick_Ann(CString arg_str, int str_len)
{
int nType = 0;
CString strIn, strOut, strKick, strAnn1, strAnn2;
strIn.Format(_T("%s"), L"님이 들어왔습니다.");
strOut.Format(_T("%s"), L"님이 나갔습니다.");
strKick.Format(_T("%s"), L"님을 내보냈습니다.");
strAnn1.Format(_T("%s"), L"불법촬영물 등 식별 및 게재제한 조치 안내");
strAnn2.Format(_T("%s"), L"불법촬영물등을 전송할 경우 관련 법령에 따라 처벌받을 수 있사오니 서비스 이용 시 유의하여 주시기 바랍니다.");
// To Do : 반복자 사용
int nTypeIn = arg_str.Find(strIn);
int nTypeOut = arg_str.Find(strOut);
int nTypeKick = arg_str.Find(strKick);
int nTypeAnn1 = arg_str.Find(strAnn1);
int nTypeAnn2 = arg_str.Find(strAnn2);
int IsImposter = 0;
if (nTypeIn != -1)
{
IsImposter = arg_str.Find(m_Imposter);
nType = (IsImposter!=-1)?TYPE_IN:nType;
}
else if (nTypeOut != -1)
{
IsImposter = arg_str.Find(m_Imposter);
nType = (IsImposter!=-1)?TYPE_OUT:nType;
}
else if (nTypeKick != -1)
{
IsImposter = arg_str.Find(m_Imposter);
nType = (IsImposter!=-1)?TYPE_KICK:nType;
}
else if (nTypeAnn1 != -1)
{
nType = 0;
}
else if (nTypeAnn2 != -1)
{
nType = 0;
}
else // 모두 해당 안되면 줄바꿈 된 채팅임.
{
nType = (bIsImposter)? TYPE_CHAT : nType;
}
return nType;
}
Push_Data(CString arg_str, int arg_Type)
큐에 구조체를 넣는다.
void CFind::Push_Data(CString arg_str, int arg_Type)
{
stImposterInfo stImpo;
stImpo.nDate = nDate; // 날짜
strcpy_s(stImpo.cTalk, CT2A(arg_str)); // 내용(채팅)
stImpo.nType = arg_Type;
qData_Imposter.push(stImpo);
}