뚝딱쓰

카카오톡 특정 인물 대화 내역 보기 - 개발 #3

트럼프 2022. 2. 12. 05:55

이전 과정

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);
}