試題模塊用於保存試題信息(編號,題目,保存路徑,難度),提供接口用於server端調用。
保存題目的數據結構我們採用unordered_map,因爲其底層採用hash結構,所以我們在查找題目的時候更快
<k, v> 對應 <題目id, 整個題目信息(question類)>
先介紹下一個具體的題目包含哪幾個部分
- desc.txt:題目描述
- header.cpp:給出的頭文件及函數入口
- tail.cpp:主函數和測試函數
在server模塊我們需要獲取desc和header
在運行編譯模塊我們就需要獲取header和tail並組成新的cpp文件
bool LoadQuestions(const std::string& configfile_path);//用於加載所有題目的基本信息
bool GetAllQuestions(std::vector<Question>* ques);//用於獲取所有試題的基本信息
bool GetOneQuestion(const std::string& id, std::string* desc, std::string* header, Question* ques); //用於獲取單個題目的詳細信息,包括題目描述(desc), 給出的頭文件(header)
#pragma once
#include "oj_log.hpp"
#include "tools.hpp"
#include <fstream>
#include <unordered_map>
#include <string>
#include <iostream>
#include <algorithm>
typedef struct Question
{
std::string _id;
std::string _name;
std::string _path;
std::string _star;
}Ques;
class OjModel
{
public:
OjModel()
{
LoadQuestions("./config_oj.cfg");
}
bool GetAllQuestions(std::vector<Question>* ques) {
//將獲取的試題信息保存在一個vector數組中
for (const auto& kv : _model_map) {
ques->push_back(kv.second);
}
//獲取試題信息後,按照id編號排序
std::sort(ques->begin(), ques->end(), [](const Question& le, const Question& ri){
return std::atoi(le._id.c_str()) < std::atoi(ri._id.c_str());
});
return true;
}
bool GetOneQuestion(const std::string& id, std::string* desc, std::string* header, Question* ques)
{
//1.根據id去查找對應題目信息,在哪裏加載
auto iter = _model_map.find(id);
if (iter == _model_map.end()) {
LOG(ERROR, "Not Found Question id is") << " " << id << std::endl;
return false;
}
*ques = iter->second;
//iter->second._path;
//加載具體的單個題目信息,從保存的路徑上面去加載
//從具體的題目文件當中去獲取兩部分信息,描述,header
int ret = FileOpen::ReadDataFromFile(DescPath(iter->second._path), desc);
if (ret == -1) {
LOG(ERROR, "Read desc failed") << std::endl;
}
ret = FileOpen::ReadDataFromFile(HeaderPath(iter->second._path), header);
if (ret == -1) {
LOG(ERROR, "Header desc failed") << std::endl;
}
return true;
}
bool SplitingCode(std::string user_code, std::string ques_id, std::string* code)
{
//1.查找以下對應id的題目是否存在
auto iter = _model_map.find(ques_id);
if (iter == _model_map.end()) {
LOG(ERROR, "can not find questions id is") << ques_id << std::endl;
return false;
}
std::string tail_code;
int ret = FileOpen::ReadDataFromFile(TailPath(iter->second._path), &tail_code);
if (ret < 0) {
LOG(ERROR, "Open tail.cpp failed") << std::endl;
return false;
}
*code = user_code + tail_code;
return true;
}
private:
//傳的參數是路徑,用於到具體的路徑下尋找對應文件
std::string DescPath(const std::string& que_path)
{
return que_path + "desc.txt";
}
std::string HeaderPath(const std::string& que_path)
{
return que_path + "header.cpp";
}
std::string TailPath(const std::string& que_path)
{
return que_path + "tail.cpp";
}
bool LoadQuestions(const std::string& configfile_path)
{
//使用C++當中的文件流來加載文件
//iostream:處理控制檯
//fstream:處理命名文件
//stringstream:處理string
//ostream:output文件流
//istream:input文件流,從文件當中讀
std::ifstream file(configfile_path.c_str());
if(!file.is_open()){
return false;
}
std::string line;
while(std::getline(file, line)) {
//切割字符串
std::vector<std::string> vec;
StringTools::Split(line, " ", &vec);
if (vec.size() != 4) {
continue;
}
//將切割後的字符放到unordered_map
Question ques;
ques._id = vec[0];
ques._name = vec[1];
ques._path = vec[2];
ques._star = vec[3];
_model_map[ques._id] = ques;
}
file.close();
return true;
}
private:
//試題id,名稱,路徑,難度
std::unordered_map<std::string, Question> _model_map;
};