|
|
|
@ -0,0 +1,514 @@
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include <cctype>
|
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
|
|
|
#include <ctime>
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
//第五版问题:?未知
|
|
|
|
|
|
|
|
#include <set>
|
|
|
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
|
|
#include <direct.h>
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 用户类型枚举
|
|
|
|
|
|
|
|
enum UserType {
|
|
|
|
|
|
|
|
PRIMARY, // 小学
|
|
|
|
|
|
|
|
JUNIOR, // 初中
|
|
|
|
|
|
|
|
SENIOR, // 高中
|
|
|
|
|
|
|
|
UNKNOWN //未知
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 用户结构体
|
|
|
|
|
|
|
|
struct User {
|
|
|
|
|
|
|
|
string username;
|
|
|
|
|
|
|
|
string password;
|
|
|
|
|
|
|
|
UserType type;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//加载所有历史题目,便于查重
|
|
|
|
|
|
|
|
set<string> loadExistingQuestions(const string& userDir) {
|
|
|
|
|
|
|
|
set<string> existingQuestions;//使用集合避免重复
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
|
|
// Windows版本的目录遍历
|
|
|
|
|
|
|
|
WIN32_FIND_DATA findFileData;
|
|
|
|
|
|
|
|
HANDLE hFind = FindFirstFile((userDir + "\\*.txt").c_str(), &findFileData);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (hFind != INVALID_HANDLE_VALUE) {
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
|
|
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
|
|
|
|
|
|
string filename = userDir + "\\" + findFileData.cFileName;
|
|
|
|
|
|
|
|
ifstream file(filename);
|
|
|
|
|
|
|
|
string line;
|
|
|
|
|
|
|
|
while (getline(file, line)) {
|
|
|
|
|
|
|
|
if (!line.empty() && line.find(".") != string::npos) {
|
|
|
|
|
|
|
|
// 提取题目内容(去掉题号)
|
|
|
|
|
|
|
|
size_t dotPos = line.find(".");
|
|
|
|
|
|
|
|
if (dotPos != string::npos) {
|
|
|
|
|
|
|
|
string question = line.substr(dotPos + 2); // 跳过". "
|
|
|
|
|
|
|
|
existingQuestions.insert(question);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (FindNextFile(hFind, &findFileData));
|
|
|
|
|
|
|
|
FindClose(hFind);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return existingQuestions;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//检查题目是否唯一
|
|
|
|
|
|
|
|
bool isQuestionUnique(const string& question, const set<string>& existingQuestions) {
|
|
|
|
|
|
|
|
return existingQuestions.find(question) == existingQuestions.end();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//字符串分割函数
|
|
|
|
|
|
|
|
vector<string> split(const string& str, char delimiter) {
|
|
|
|
|
|
|
|
vector<string> tokens;
|
|
|
|
|
|
|
|
string token;
|
|
|
|
|
|
|
|
istringstream tokenStream(str);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (getline(tokenStream, token, delimiter)) {
|
|
|
|
|
|
|
|
if (!token.empty()) {
|
|
|
|
|
|
|
|
tokens.push_back(token);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return tokens;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 字符串修剪函数 - 去除字符串首尾的空白字符
|
|
|
|
|
|
|
|
string trim(const string& str) {
|
|
|
|
|
|
|
|
size_t start = str.find_first_not_of(" \t\n\r");
|
|
|
|
|
|
|
|
if (start == string::npos) return "";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t end = str.find_last_not_of(" \t\n\r");
|
|
|
|
|
|
|
|
return str.substr(start, end - start + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 字符串转小写函数 - 将字符串转换为小写形式
|
|
|
|
|
|
|
|
string toLower(const string& str) {
|
|
|
|
|
|
|
|
string result = str;
|
|
|
|
|
|
|
|
transform(result.begin(), result.end(), result.begin(), ::tolower);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//数字验证函数
|
|
|
|
|
|
|
|
bool isNumber(const string& str) {
|
|
|
|
|
|
|
|
if (str.empty()) return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (str == "-1") return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < str.length(); i++) {
|
|
|
|
|
|
|
|
if (!isdigit(str[i])) return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前时间字符串 - 生成格式为"年-月-日-时-分-秒"的时间字符串
|
|
|
|
|
|
|
|
string getCurrentTimeString() {
|
|
|
|
|
|
|
|
time_t now = time(0);
|
|
|
|
|
|
|
|
struct tm* localTime = localtime(&now);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char buffer[20];
|
|
|
|
|
|
|
|
strftime(buffer, sizeof(buffer), "%Y-%m-%d-%H-%M-%S", localTime);
|
|
|
|
|
|
|
|
return string(buffer);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//创建目录函数
|
|
|
|
|
|
|
|
bool createDirectory(const string& path) {
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
|
|
return _mkdir(path.c_str()) == 0;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
return mkdir(path.c_str(), 0755) == 0;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//用户类型转中文字符串
|
|
|
|
|
|
|
|
string getUserTypeString(UserType type) {
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
|
|
case PRIMARY: return "小学";
|
|
|
|
|
|
|
|
case JUNIOR: return "初中";
|
|
|
|
|
|
|
|
case SENIOR: return "高中";
|
|
|
|
|
|
|
|
default: return "未知";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//将中文字符串转换为对应枚举
|
|
|
|
|
|
|
|
UserType parseUserType(const string& typeStr) {
|
|
|
|
|
|
|
|
string lowerType = toLower(typeStr);
|
|
|
|
|
|
|
|
if (lowerType == "小学") return PRIMARY;
|
|
|
|
|
|
|
|
if (lowerType == "初中") return JUNIOR;
|
|
|
|
|
|
|
|
if (lowerType == "高中") return SENIOR;
|
|
|
|
|
|
|
|
return UNKNOWN;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 用户管理类
|
|
|
|
|
|
|
|
class UserManager {
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
vector<User> users;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void initializeUsers() {
|
|
|
|
|
|
|
|
// 小学账号
|
|
|
|
|
|
|
|
users.push_back((User){"张三1", "123", PRIMARY});
|
|
|
|
|
|
|
|
users.push_back((User){"张三2", "123", PRIMARY});
|
|
|
|
|
|
|
|
users.push_back((User){"张三3", "123", PRIMARY});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初中账号
|
|
|
|
|
|
|
|
users.push_back((User){"李四1", "123", JUNIOR});
|
|
|
|
|
|
|
|
users.push_back((User){"李四2", "123", JUNIOR});
|
|
|
|
|
|
|
|
users.push_back((User){"李四3", "123", JUNIOR});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 高中账号
|
|
|
|
|
|
|
|
users.push_back((User){"王五1", "123", SENIOR});
|
|
|
|
|
|
|
|
users.push_back((User){"王五2", "123", SENIOR});
|
|
|
|
|
|
|
|
users.push_back((User){"王五3", "123", SENIOR});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
//构造函数初始化
|
|
|
|
|
|
|
|
UserManager() {
|
|
|
|
|
|
|
|
initializeUsers();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//验证用户名密码是否正确
|
|
|
|
|
|
|
|
User* authenticate(const string& username, const string& password) {
|
|
|
|
|
|
|
|
for (size_t i = 0; i < users.size(); i++) {
|
|
|
|
|
|
|
|
if (users[i].username == username && users[i].password == password) {
|
|
|
|
|
|
|
|
return &users[i];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//抽象题目生成器接口类,定义基本操作
|
|
|
|
|
|
|
|
class IQuestionGenerator {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
virtual ~IQuestionGenerator() {}
|
|
|
|
|
|
|
|
virtual void setUserType(UserType type) = 0;
|
|
|
|
|
|
|
|
virtual string generateQuestion() = 0;
|
|
|
|
|
|
|
|
virtual vector<string> generatePaper(int questionCount, const string& username) = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 具体题目生成器实现类,继承接口
|
|
|
|
|
|
|
|
class QuestionGenerator : public IQuestionGenerator {
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
UserType currentType;
|
|
|
|
|
|
|
|
set<string> existingQuestions;//历史题目集合用于查重
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int generateOperand() {
|
|
|
|
|
|
|
|
return rand() % 100 + 1;//操作数范围1-100
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//生成表达式
|
|
|
|
|
|
|
|
string generateExpression(int operandCount) {
|
|
|
|
|
|
|
|
string operators[] = {"+", "-", "*", "/"};
|
|
|
|
|
|
|
|
vector<int> operands;//存放操作数
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
|
|
|
operands.push_back(generateOperand());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stringstream ss;
|
|
|
|
|
|
|
|
ss << operands[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i < operandCount; i++) {
|
|
|
|
|
|
|
|
string op = operators[rand() % 4];//随机运算符
|
|
|
|
|
|
|
|
ss << " " << op << " " << operands[i];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ss.str();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//生成小学题目
|
|
|
|
|
|
|
|
string generatePrimaryQuestion() {
|
|
|
|
|
|
|
|
int operandCount = rand() % 4 + 2; // 小学要求2-5个操作数
|
|
|
|
|
|
|
|
return generateExpression(operandCount);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//生成初中题目
|
|
|
|
|
|
|
|
string generateJuniorQuestion() {
|
|
|
|
|
|
|
|
int operandCount = rand() % 5 + 1;
|
|
|
|
|
|
|
|
string expression = generateExpression(operandCount);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 确保至少有一个平方或开根号
|
|
|
|
|
|
|
|
if (rand() % 2 == 0) {
|
|
|
|
|
|
|
|
return expression +"^2"; // 平方
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return "√" + expression; // 开根号
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//生成高中题目
|
|
|
|
|
|
|
|
string generateSeniorQuestion() {
|
|
|
|
|
|
|
|
int operandCount = rand() % 5 + 1;
|
|
|
|
|
|
|
|
string expression = generateExpression(operandCount);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 确保至少有一个三角函数
|
|
|
|
|
|
|
|
string trigFunctions[] = {"sin", "cos", "tan"};
|
|
|
|
|
|
|
|
string trigFunc = trigFunctions[rand() % 3];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return trigFunc + "(" + expression + ")";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
//构造函数,初始化随机种子
|
|
|
|
|
|
|
|
QuestionGenerator() : currentType(PRIMARY) {
|
|
|
|
|
|
|
|
srand(time(0));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//设置用户类型
|
|
|
|
|
|
|
|
void setUserType(UserType type) override {//重载
|
|
|
|
|
|
|
|
currentType = type;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置历史题目,便于查重
|
|
|
|
|
|
|
|
void setExistingQuestions(const set<string>& questions) {
|
|
|
|
|
|
|
|
existingQuestions = questions;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//生成单个题目
|
|
|
|
|
|
|
|
string generateQuestion() override {
|
|
|
|
|
|
|
|
string question;
|
|
|
|
|
|
|
|
int attempts = 0;
|
|
|
|
|
|
|
|
const int MAX_ATTEMPTS = 100; // 防止无限循环
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 循环生成题目直到生成不重复的题目或达到最大尝试次数
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
|
|
switch (currentType) {
|
|
|
|
|
|
|
|
case PRIMARY:
|
|
|
|
|
|
|
|
question = generatePrimaryQuestion();
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JUNIOR:
|
|
|
|
|
|
|
|
question = generateJuniorQuestion();
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SENIOR:
|
|
|
|
|
|
|
|
question = generateSeniorQuestion();
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
question = generatePrimaryQuestion();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
attempts++;
|
|
|
|
|
|
|
|
} while (!isQuestionUnique(question, existingQuestions) && attempts < MAX_ATTEMPTS);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将新题目添加到历史记录中
|
|
|
|
|
|
|
|
existingQuestions.insert(question);
|
|
|
|
|
|
|
|
return question;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//生成整张试卷(指定数量题目)
|
|
|
|
|
|
|
|
vector<string> generatePaper(int questionCount, const string& username) override {//重载
|
|
|
|
|
|
|
|
vector<string> paper;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= questionCount; i++) {
|
|
|
|
|
|
|
|
string question = generateQuestion();
|
|
|
|
|
|
|
|
stringstream ss;
|
|
|
|
|
|
|
|
ss << i << ". " << question;//题号
|
|
|
|
|
|
|
|
paper.push_back(ss.str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return paper;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 试卷系统主类
|
|
|
|
|
|
|
|
class PaperSystem {
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
UserManager userManager;
|
|
|
|
|
|
|
|
QuestionGenerator questionGenerator;
|
|
|
|
|
|
|
|
User* currentUser;
|
|
|
|
|
|
|
|
string currentDirectory;
|
|
|
|
|
|
|
|
set<string> existingQuestions;//登录时加载历史题目
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//用户登录函数
|
|
|
|
|
|
|
|
bool login() {
|
|
|
|
|
|
|
|
cout << "请输入用户名和密码(用空格隔开):";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string input;
|
|
|
|
|
|
|
|
getline(cin, input);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vector<string> tokens = split(input, ' ');
|
|
|
|
|
|
|
|
if (tokens.size() != 2) {
|
|
|
|
|
|
|
|
cout << "请输入正确的用户名、密码" << endl;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string username = trim(tokens[0]);
|
|
|
|
|
|
|
|
string password = trim(tokens[1]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentUser = userManager.authenticate(username, password);
|
|
|
|
|
|
|
|
if (currentUser == NULL) {
|
|
|
|
|
|
|
|
cout << "请输入正确的用户名、密码" << endl;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
questionGenerator.setUserType(currentUser->type);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 加载历史题目用于查重
|
|
|
|
|
|
|
|
string userDir = currentDirectory + "/" + currentUser->username;
|
|
|
|
|
|
|
|
createDirectory(userDir);
|
|
|
|
|
|
|
|
existingQuestions = loadExistingQuestions(userDir);
|
|
|
|
|
|
|
|
questionGenerator.setExistingQuestions(existingQuestions);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cout << "当前选择为" << getUserTypeString(currentUser->type) << "出题" << endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//处理命令行的"切换为xx"命令
|
|
|
|
|
|
|
|
bool processSwitchCommand(const string& input) {
|
|
|
|
|
|
|
|
if (input.length() < 7) return false; // "切换为XX" 至少7个字符
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string prefix = input.substr(0, 6);
|
|
|
|
|
|
|
|
if (toLower(prefix) != "切换为") return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string typeStr = trim(input.substr(6));
|
|
|
|
|
|
|
|
UserType newType = parseUserType(typeStr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//切换类型不合法
|
|
|
|
|
|
|
|
if (newType == UNKNOWN) {
|
|
|
|
|
|
|
|
cout << "请输入小学、初中和高中三个选项中的一个" << endl;
|
|
|
|
|
|
|
|
return true; // 命令格式正确但内容错误
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 永久切换用户类型
|
|
|
|
|
|
|
|
currentUser->type = newType;
|
|
|
|
|
|
|
|
questionGenerator.setUserType(newType);
|
|
|
|
|
|
|
|
cout << "准备生成" << getUserTypeString(newType) << "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 处理输入并验证题目数量
|
|
|
|
|
|
|
|
int getValidQuestionCount() {
|
|
|
|
|
|
|
|
string input;
|
|
|
|
|
|
|
|
getline(cin, input);
|
|
|
|
|
|
|
|
input = trim(input);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (processSwitchCommand(input)) {
|
|
|
|
|
|
|
|
return -3; // 特殊代码表示切换类型
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (input == "-1") {
|
|
|
|
|
|
|
|
return -1; // 退出代码
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!isNumber(input)) {
|
|
|
|
|
|
|
|
cout << "请输入有效的数字!" << endl;
|
|
|
|
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int questionCount = atoi(input.c_str());
|
|
|
|
|
|
|
|
if (questionCount < 10 || questionCount > 30) {
|
|
|
|
|
|
|
|
cout << "题目数量范围是10-30,请重新输入。" << endl;
|
|
|
|
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return questionCount;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 生成并保存试卷,更新历史题目,便于查重
|
|
|
|
|
|
|
|
void generateAndSavePaper(int questionCount) {
|
|
|
|
|
|
|
|
vector<string> paper = questionGenerator.generatePaper(questionCount, currentUser->username);
|
|
|
|
|
|
|
|
string filename = getCurrentTimeString() + ".txt";
|
|
|
|
|
|
|
|
string userDir = currentDirectory + "/" + currentUser->username;
|
|
|
|
|
|
|
|
createDirectory(userDir);
|
|
|
|
|
|
|
|
string fullPath = userDir + "/" + filename;
|
|
|
|
|
|
|
|
savePaperToFile(paper, fullPath);
|
|
|
|
|
|
|
|
cout << "试卷已生成并保存到: " << fullPath << endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新历史题目记录(从文件中重新加载,确保包含最新题目)
|
|
|
|
|
|
|
|
existingQuestions = loadExistingQuestions(userDir);
|
|
|
|
|
|
|
|
questionGenerator.setExistingQuestions(existingQuestions);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
void generatePaper() {
|
|
|
|
|
|
|
|
cout << "准备生成" << getUserTypeString(currentUser->type)
|
|
|
|
|
|
|
|
<< "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
|
|
|
int questionCount = getValidQuestionCount();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (questionCount == -3) { // 切换类型
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (questionCount == -2) { // 需要重新输入
|
|
|
|
|
|
|
|
cout << "准备生成" << getUserTypeString(currentUser->type)
|
|
|
|
|
|
|
|
<< "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):";
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (questionCount == -1) { // 退出
|
|
|
|
|
|
|
|
currentUser = NULL;
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 有效的题目数量
|
|
|
|
|
|
|
|
generateAndSavePaper(questionCount);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//保存试卷到文件 - 将题目列表写入文件
|
|
|
|
|
|
|
|
void savePaperToFile(const vector<string>& paper, const string& filename) {
|
|
|
|
|
|
|
|
ofstream file(filename.c_str());
|
|
|
|
|
|
|
|
if (file.is_open()) {
|
|
|
|
|
|
|
|
for (size_t i = 0; i < paper.size(); i++) {
|
|
|
|
|
|
|
|
file << paper[i] << endl;
|
|
|
|
|
|
|
|
if (i < paper.size() - 1) {
|
|
|
|
|
|
|
|
file << endl; // 题目之间空一行
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void userSession() {
|
|
|
|
|
|
|
|
while (currentUser != NULL) {
|
|
|
|
|
|
|
|
generatePaper();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
PaperSystem() : currentUser(NULL) {
|
|
|
|
|
|
|
|
currentDirectory = "papers";
|
|
|
|
|
|
|
|
createDirectory(currentDirectory);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//系统主循环-程序入口
|
|
|
|
|
|
|
|
void run() {
|
|
|
|
|
|
|
|
cout << "=== 中小学数学卷子自动生成程序 ===" << endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
|
|
|
if (currentUser == NULL) {
|
|
|
|
|
|
|
|
if (!login()) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
userSession();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
|
|
|
PaperSystem system;
|
|
|
|
|
|
|
|
system.run();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|