diff --git a/CMakeLists.txt b/CMakeLists.txt index 1852c76..44cbf2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,12 +10,11 @@ add_executable(o include/sqlite3.h include/sqlite3ext.h include/extern.h - include/myerror.h main.c sqlite3.c - login.c ui.c - signin.c include/ui.h - ) + o.c + calculate.c +) target_link_libraries(o "${LIBRARY_PATH}/${LIBRARY_NAME}") \ No newline at end of file diff --git a/calculate.c b/calculate.c new file mode 100644 index 0000000..3fb7db9 --- /dev/null +++ b/calculate.c @@ -0,0 +1,204 @@ +//参考文章:https://blog.csdn.net/lei20172017/article/details/116404682 + +#include +#include +#include +#include +#include +#define MAX_SIZE 1000 +/*定义一个运算符栈*/ +typedef struct { + char Operator[MAX_SIZE]; + int top; +} OptorStack; +/*定义一个操作数栈*/ +typedef struct { + double Operand[MAX_SIZE]; + int top; +} OpndStack; +/*初始化运算符栈*/ +void InitOptor(OptorStack *S) { + S->top = -1; +} +/*初始化操作数栈*/ +void InitOpnd(OpndStack *S) { + S->top = -1; +} +/*运算符出栈*/ +int PopOptor(OptorStack *S,int *recall,char *errmsg) { + if(S->top==-1) { + *recall=-1; + strcpy(errmsg,"Wrong input."); + return -1; + } + S->top--; + return 1; +} +/*操作数出栈*/ +int PopOpnd(OpndStack *S,int *recall,char *errmsg) { + if(S->top==-1) { + *recall=-1; + strcpy(errmsg,"Wrong input."); + return -1; + } + S->top--; + return 1; +} + +/*运算符入栈*/ +int PushOptor(OptorStack *S,char ch,int *recall,char *errmsg) { + if(S->top==MAX_SIZE-1) { + *recall=-1; + strcpy(errmsg,"Wrong input."); + return -1; + } + S->top++; + S->Operator[S->top]=ch; + return 1; +} +/*操作数入栈*/ +int PushOpnd(OpndStack *S,double ch,int *recall,char *errmsg) { + if(S->top==MAX_SIZE-1) { + *recall=-1; + strcpy(errmsg,"Wrong input."); + return -1; + } + S->top++; + S->Operand[S->top]=ch; + return 1; +} +/*取运算符栈栈顶元素*/ +char GetOptor(OptorStack *S,int *recall,char *errmsg) { + if(S->top==-1) { + *recall=-1; + strcpy(errmsg,"Wrong input."); + return -1; + } + return S->Operator[S->top]; +} +/*取操作数栈栈顶元素*/ +double GetOpnd(OpndStack *S,int *recall,char *errmsg) { + if(S->top==-1) { + *recall=-1; + strcpy(errmsg,"Wrong input."); + return -1; + } + return S->Operand[S->top]; +} +/*表达式运算函数*/ +double Calculate(double a,double b,char op,int *recall,char *errmsg) { + double result; + if(op=='+') result=a+b; + if(op=='-') result=a-b; + if(op=='*') result=a*b; + if(op=='/') { //要防止除数为0 + if(b==0) { + *recall=-1; + strcpy(errmsg,"Wrong input.The divisor is not 0"); + return -1; + } + result=a/b; + } + return result; //返回结果result +} + +int change(char ch) { + switch(ch) { + case '+': + return 0; + case '-': + return 1; + case '*': + return 2; + case '/': + return 3; + case '(': + return 4; + case ')': + return 5; + case '#': + return 6; + } +} +/*定义一个算符优先关系矩阵*/ +char cmp[7][8]= {">><<<>>",">><<<>>",">>>><>>",">>>><>>","<<<<<=?",">>>>?>>","<<<<或<或=*/ +int Compare(char ch1,char ch2,int *recall,char *errmsg) { + if(cmp[change(ch1)][change(ch2)]=='?') { + *recall=-1; + strcpy(errmsg,"Wrong input."); + return -1; + } + return cmp[change(ch1)][change(ch2)]; +} +/*检查函数,用来检查输入的表达式的操作数和运算符的合法性*/ +int Check(char *S,int len) { + int i; + for(i=0; i='0'&&S[i]<='9')continue; + if(S[i]=='('||S[i]==')'||S[i]=='*'||S[i]=='/'||S[i]=='+'||S[i]=='-'||S[i]=='.')continue; + return 0; + } + return 1; +} + +void calculate(char *expre,int *recall,char *errmsg,double *answer) { + SetConsoleOutputCP(65001); + char opd[9999]; //opd用来存操作数 + int len; + OptorStack Optor; + OpndStack Opnd; + InitOptor(&Optor); + InitOpnd(&Opnd); + PushOptor(&Optor,'#',recall,errmsg); + len = strlen(expre); + int kk=0; + for(int i=0;i='0'&&expre[len]<='9')continue; + else kk=1; + } + if(kk==0){ + *recall=-1; + strcpy(errmsg,"you should make sure this is a expression."); + return; + } + if (Check(expre,len) == 0) { + *recall=-1; + strcpy(errmsg,"Wrong input."); + return; + } + int i,j=0,k=0; + double x,y; + expre[len] = '#'; //在expre数组后加个#结尾标志 + for (i=0; i<=len; i++) { + if ((expre[i]>='0' && expre[i]<='9') || expre[i] == '.') { + opd[k++] = expre[i]; //将数字字符存入操作数数组opd中 + j = 1; + continue; + } + if(j) { + opd[k] = '\0'; + PushOpnd(&Opnd,atof(opd),recall,errmsg); + j=0; + k=0; + } + switch (Compare(GetOptor(&Optor,recall,errmsg),expre[i],recall,errmsg)) { //比较运算符栈的栈顶运算符和运算符expre[i]的优先级 + case '<': + PushOptor(&Optor,expre[i],recall,errmsg); + break; + case '=': + PopOptor(&Optor,recall,errmsg); + break; + case '>': + y = GetOpnd(&Opnd,recall,errmsg),PopOpnd(&Opnd,recall,errmsg); + x = GetOpnd(&Opnd,recall,errmsg),PopOpnd(&Opnd,recall,errmsg); + PushOpnd(&Opnd,Calculate(x,y,GetOptor(&Optor,recall,errmsg),recall,errmsg),recall,errmsg); + PopOptor(&Optor,recall,errmsg); + i--; + break; + default:break; + } + } + if(recall==-1)return; + *answer = GetOpnd(&Opnd,recall,errmsg); +} diff --git a/include/extern.h b/include/extern.h index 98b1003..4430b4c 100644 --- a/include/extern.h +++ b/include/extern.h @@ -4,5 +4,14 @@ #ifndef EXTERN_H #define EXTERN_H -extern char *Username; +#define WELCOME_UI 1 +#define LOGIN_UI 2 +#define SIGNIN_UI 3 +#define STUDENT_UI 4 +#define TEACHER_UI 5 +#define STU_TEST_UI 6 +#define STU_HIS_SC_UI 7 +#define STU_EXC 8 +#define T_PROBLEM_UI 9 +#define ADD_UI 10 #endif //EXTERN_H diff --git a/include/function.h b/include/function.h index e2ac257..8f832b0 100644 --- a/include/function.h +++ b/include/function.h @@ -14,4 +14,14 @@ void Login(char *username,char*password,int *recall,char *errmsg); void Signin(const char *username,const char*password,int *recall,char *errmsg); void myexit(); + +void db_create(int *recall,char *errmsg); + +int stu_type_check(); + +void stu_type_insert(char *name,char *class,char *majority,int *recall,char *errmsg); + +void add(char* test,int *recall,char* errmsg); + +void calculate(char *expre,int *recall,char *errmsg,double *answer); #endif //FUNCTION_H diff --git a/include/myerror.h b/include/myerror.h deleted file mode 100644 index de991cc..0000000 --- a/include/myerror.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Created by zhang on 2024/12/25. -// - -#include - -#include "function.h" - -#ifndef MYERROR_H -#define MYERROR_H - -void Error_Invalid_input(); -void Error_Invalid_input(){ - fprintf(stdout,"Error:不合法的输入!输入'0'以继续"); - while(getchar() != '0'); - clear(); - return; -} - -#endif diff --git a/include/ui.h b/include/ui.h index 3295fc8..94f0d6e 100644 --- a/include/ui.h +++ b/include/ui.h @@ -14,5 +14,15 @@ int TeachersDesktop_ui(); int Welcome_ui(); +void stu_test_ui(int *recall,char *errmsg,char *class); +void stu_his_sc_ui(); + +void stu_exercise_ui(); + +int t_problem_ui(); + +void create_ui(); + +int add_ui(); #endif //O_UI_H diff --git a/login.c b/login.c deleted file mode 100644 index 15b7a5b..0000000 --- a/login.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include "./include/function.h" -#include "./include/ui.h" -void Login(char *username,char*password,int *recall,char *errmsg){ - sqlite3 *db; - int rc; - - // 打开数据库 - rc = sqlite3_open("./data/msg.db", &db); - if (rc) { - strcpy(errmsg,"Error:database error."); - *recall=-1; - return; - } - - // SQL 查询语句:查找用户及其密码 - const char *sql = "SELECT user, password FROM users WHERE user = ?;"; - - sqlite3_stmt *stmt; - - // 编译 SQL 语句 - rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - strcpy(errmsg,"Error:database error."); - *recall=-1; - sqlite3_close(db); - return; - } - - // 绑定查询参数 - sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); - - rc = sqlite3_step(stmt); - if (rc == SQLITE_ROW) { - // 查找到用户,获取密码 - const char *db_password = (const char *)sqlite3_column_text(stmt, 1); - - // 如果密码匹配 - if (db_password && strcmp(db_password, password) == 0) { - *recall=0; - } else { - strcpy(errmsg,"Incorrect username or password."); - *recall=-1; - } - } else { - strcpy(errmsg,"Incorrect username or password."); - *recall=-1; - } - // 绑定查询参数 - // 清理资源 - sqlite3_finalize(stmt); - sqlite3_close(db); - - return; -} diff --git a/main.c b/main.c index cceb357..77710e9 100644 --- a/main.c +++ b/main.c @@ -6,68 +6,71 @@ #include #include "./include/function.h" #include "./include/ui.h" -#include "./include/myerror.h" #include "./include/extern.h" #include "./include/curses.h" -#define WELCOME_UI 1 -#define LOGIN_UI 2 -#define SIGNIN_UI 3 -void myexit() { - endwin(); - exit(0); -} - -//void test() { -// // 初始化 ncurses -// initscr(); -// cbreak(); // 禁用行缓冲 -// noecho(); // 不显示输入字符 -// curs_set(0); // 隐藏光标 -// -// // 启用所有鼠标事件 -// mousemask(ALL_MOUSE_EVENTS, NULL); -// -// // 创建一个新的窗口 -// WINDOW *win = newwin(10, 30, 5, 5); -// box(win, 0, 0); // 为窗口添加边框 -// mvwprintw(win, 1, 1, "Click inside this window."); -// keypad(win,TRUE); -// wrefresh(win); // 刷新窗口以显示内容 -// -// MEVENT event; // 用于存储鼠标事件 -// -// while (1) { -// int ch = wgetch(win); // 从指定窗口获取输入 -// -// if (ch == KEY_MOUSE) { -// if (nc_getmouse(&event) == OK) { -// // 打印鼠标事件的信息 -// mvwprintw(win, 3, 1, "Mouse at (%d, %d), button %d", event.x, event.y, event.bstate); -// wrefresh(win); // 刷新窗口以显示鼠标点击位置 -// } -// } else { -// mvwprintw(win, 4, 1, "You pressed a key: %c", ch); -// wrefresh(win); // 刷新窗口以显示按键信息 -// break; // 按键退出循环 -// } -// } -// -// // 等待用户按键后退出 -// getch(); -// -// // 清理和结束程序 -// endwin(); -// return; -//} - +char Username[15]; +char class[15]; +void mytest(); int main() { + initscr(); // 初始化curses + cbreak(); // 禁用行缓冲 + noecho(); // 不显示输入字符 + curs_set(0); // 隐藏光标 + keypad(stdscr, TRUE); // 启用键盘按键的特殊处理 + mousemask(ALL_MOUSE_EVENTS, NULL); // 启用鼠标事件 + timeout(100); // 设置输入超时,防止程序卡死 + int recall; + char *errmsg[100]; + db_create(&recall,errmsg); + if(recall!=0){ + fprintf(stderr,"%s\ninput any key to exit.",errmsg); + getchar(); + exit(0); + } + //int code=TEACHER_UI; int code=Welcome_ui(); while(1){ switch(code){ case WELCOME_UI:code=Welcome_ui();break; case LOGIN_UI:code=Login_ui();break; case SIGNIN_UI:code=Signin_ui();break; - case 0:myexit(); + case STUDENT_UI:code=StudentsDesktop_ui();break; + case TEACHER_UI:code=TeachersDesktop_ui();break; + case T_PROBLEM_UI:code=t_problem_ui();break; + case ADD_UI:code=add_ui();break; + case 0:myexit();return 0; } } -} \ No newline at end of file +} +//void mytest(){ +// sqlite3 *db; +// char *errMsg = 0; +// int rc; +// // 打开数据库,如果数据库文件不存在则创建它 +// rc = sqlite3_open("./data/msg.db", &db); +// for(int i=1;i<=100;i++){ +// char *sql_insert="INSERT INTO tests (test_name,Creater) VALUES (?, 'xianya');"; +// sqlite3_stmt *insert; +// char test[10]; +// snprintf(test,7,"test%d",i); +// rc = sqlite3_prepare_v2(db, sql_insert, -1, &insert, 0); +// if (rc != SQLITE_OK) { +// sqlite3_close(db); +// return; +// } +// +// // 将第一个参数 (username) 绑定到 SQL 语句中的第一个 "?" +// sqlite3_bind_text(insert, 1, test, -1, SQLITE_STATIC); +// +// rc = sqlite3_step(insert); +// if (rc != SQLITE_DONE) { +// sqlite3_free(errMsg); +// sqlite3_finalize(insert); +// sqlite3_close(db); +// return; +// } +// } +// printf("OK"); +// sqlite3_close(db); +// return; +//} \ No newline at end of file diff --git a/o.c b/o.c new file mode 100644 index 0000000..81d6253 --- /dev/null +++ b/o.c @@ -0,0 +1,506 @@ +// +// Created by zhang on 2024/12/29. +// +#include +#include +#include +#include "./include/function.h" +#include "./include/extern.h" +#include "./include/curses.h" +#include "./include/sqlite3.h" +extern char Username[15]; +extern char class[15]; +void myexit() { + endwin(); + exit(0); +} + +void Login(char *username,char*password,int *recall,char *errmsg){ + if(!username[0]){ + strcpy(errmsg,"The username is empty!"); + *recall=-1; + return; + } + if(!password[0]){ + strcpy(errmsg,"The password is empty!"); + *recall=-1; + return; + } + sqlite3 *db; + int rc; + + // 打开数据库 + rc = sqlite3_open("./data/msg.db", &db); + if (rc) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + return; + } + + // SQL 查询语句:查找用户及其密码 + const char *sql = "SELECT password, type FROM users WHERE user = ?;"; + + sqlite3_stmt *stmt; + + // 编译 SQL 语句 + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + sqlite3_close(db); + return; + } + + // 绑定查询参数 + sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); + + rc = sqlite3_step(stmt); + if (rc == SQLITE_ROW) { + // 查找到用户,获取密码 + const char *db_password = (const char *)sqlite3_column_text(stmt, 0); + + // 如果密码匹配 + if (db_password && strcmp(db_password, password) == 0) { + const char *db_type = (const char *)sqlite3_column_text(stmt, 1); + strcpy(Username,username); + *recall = db_type[0]-'0'; + } else { + strcpy(errmsg,"Incorrect username or password."); + *recall=-1; + } + } else { + strcpy(errmsg,"Incorrect username or password."); + *recall=-1; + } + // 绑定查询参数 + // 清理资源 + sqlite3_finalize(stmt); + sqlite3_close(db); + + return; +} + +void Signin(const char *username,const char*password,int *recall,char *errmsg){ + if(!username[0]){ + strcpy(errmsg,"The username is empty!"); + *recall=-1; + return; + } + if(!password[0]){ + strcpy(errmsg,"The password is empty!"); + *recall=-1; + return; + } + sqlite3 *db; + char *errMsg = 0; + int rc; + // 打开数据库,如果数据库文件不存在则创建它 + rc = sqlite3_open("./data/msg.db", &db); + if (rc) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + return; + } + const char *sql = "SELECT user FROM users WHERE user = ?;"; + + sqlite3_stmt *stmt; + + // 编译 SQL 语句 + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + sqlite3_close(db); + return; + } + + // 绑定查询参数 + sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); + + rc = sqlite3_step(stmt); + if (rc == SQLITE_ROW) { + // 查找到用户 + strcpy(errmsg,"Username has been used."); + *recall=-1; + sqlite3_finalize(stmt); + sqlite3_close(db); + return; + } + else sqlite3_finalize(stmt); + char *sql_insert="INSERT INTO users (user,password,type) VALUES (?, ? ,'4');"; + sqlite3_stmt *insert; + rc = sqlite3_prepare_v2(db, sql_insert, -1, &insert, 0); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + sqlite3_close(db); + return; + } + + // 将第一个参数 (username) 绑定到 SQL 语句中的第一个 "?" + sqlite3_bind_text(insert, 1, username, -1, SQLITE_STATIC); + + // 将第二个参数 (password) 绑定到 SQL 语句中的第二个 "?" + sqlite3_bind_text(insert, 2, password, -1, SQLITE_STATIC); + + rc = sqlite3_step(insert); + if (rc != SQLITE_DONE) { + strcpy(errmsg,"Error:database error"); + sqlite3_free(errMsg); + sqlite3_finalize(insert); + sqlite3_close(db); + *recall=-1;return; + } + sqlite3_free(errMsg); + sqlite3_finalize(insert); + sqlite3_close(db); + *recall=0; + return; +} + +void db_create(int *recall,char *errmsg){ + sqlite3 *db; + char *errMsg = 0; + int rc; + // 打开数据库,如果数据库文件不存在则创建它 + rc = sqlite3_open("./data/msg.db", &db); + if (rc) { + strcpy(errmsg,"database error."); + *recall=-1; + return; + } + + + const char *sql_create_table = + "CREATE TABLE IF NOT EXISTS users " + "(" + "ID INTEGER PRIMARY KEY AUTOINCREMENT," + "user TEXT UNIQUE," + "password TEXT," + "type TEXT" + ");"; + + // 执行 SQL 语句 + rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_free(errMsg); + sqlite3_close(db); + *recall=-1;return; + } + + + sql_create_table="CREATE TABLE IF NOT EXISTS tests " + "(" + "ID INTEGER PRIMARY KEY AUTOINCREMENT," + "test_name TEXT," + "Creater TEXT," + "class TEXT," + "problems_count INTEGER" + ");"; + rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_free(errMsg); + sqlite3_close(db); + *recall=-1;return; + } + + + sql_create_table="CREATE TABLE IF NOT EXISTS timu " + "(" + "ID INTEGER PRIMARY KEY AUTOINCREMENT," + "text TEXT UNIQUE," + "answer INTEGER" + ");"; + rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_free(errMsg); + sqlite3_close(db); + *recall=-1;return; + } + + + sql_create_table="CREATE TABLE IF NOT EXISTS stu" + "(" + "ID INTEGER PRIMARY KEY AUTOINCREMENT," + "majority TEXT," + "class TEXT," + "name TEXT," + "test_index INTEGER," + "test_name TEXT," + "user TEXT," + "score INTEGER" + ");"; + rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_free(errMsg); + sqlite3_close(db); + *recall=-1;return; + } + + + sql_create_table="CREATE TABLE IF NOT EXISTS students " + "(" + "ID INTEGER PRIMARY KEY AUTOINCREMENT," + "user TEXT UNIQUE," + "name TEXT," + "class TEXT," + "majority TEXT" + ");"; + rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_free(errMsg); + sqlite3_close(db); + *recall=-1;return; + } + + sql_create_table="CREATE TABLE IF NOT EXISTS class " + "(" + "ID INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT" + ");"; + rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_free(errMsg); + sqlite3_close(db); + *recall=-1;return; + } + + + sql_create_table="CREATE TABLE IF NOT EXISTS majority " + "(" + "ID INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT" + ");"; + rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_free(errMsg); + sqlite3_close(db); + *recall=-1;return; + } + sql_create_table="CREATE TABLE IF NOT EXISTS test_include " + "(" + "ID INTEGER PRIMARY KEY AUTOINCREMENT," + "text TEXT ," + "answer INTEGER," + "test_index INTEGER" + ");"; + rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_free(errMsg); + sqlite3_close(db); + *recall=-1;return; + } + sqlite3_free(errMsg); + sqlite3_close(db); +} + +int stu_type_check(){ + sqlite3 *db; + char *errMsg = 0; + int rc; + // 打开数据库,如果数据库文件不存在则创建它 + rc = sqlite3_open("./data/msg.db", &db); + if (rc) { + sqlite3_close(db); + return -1; + } + const char *sql = "SELECT class FROM students WHERE user = ?;"; + + sqlite3_stmt *stmt; + + // 编译 SQL 语句 + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + sqlite3_finalize(stmt); + sqlite3_close(db); + return -1; + } + + // 绑定查询参数 + sqlite3_bind_text(stmt, 1, Username, -1, SQLITE_STATIC); + + rc = sqlite3_step(stmt); + + if(rc==SQLITE_ROW){ + char *cl=(const char *)sqlite3_column_text(stmt, 0); + strcpy(class,cl); + sqlite3_finalize(stmt); + sqlite3_close(db); + return 1; + } + else{ + sqlite3_finalize(stmt); + sqlite3_close(db); + return 0; + } +} + +void stu_type_insert(char *name,char *class,char *majority,int *recall,char *errmsg) { + if(!name[0]){ + strcpy(errmsg,"The name is empty!"); + *recall=-1; + return; + } + if(!class[0]){ + strcpy(errmsg,"The class is empty!"); + *recall=-1; + return; + } + if(!majority[0]){ + strcpy(errmsg,"The majority is empty!"); + *recall=-1; + return; + } + + sqlite3 *db; + char *errMsg = 0; + int rc; + // 打开数据库,如果数据库文件不存在则创建它 + rc = sqlite3_open("./data/msg.db", &db); + if (rc) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + return; + } + const char *sql = "SELECT name FROM class WHERE name = ?;"; + + sqlite3_stmt *stmt; + + // 编译 SQL 语句 + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + sqlite3_free(errMsg); + sqlite3_finalize(stmt); + sqlite3_close(db); + return; + } + + // 绑定查询参数 + sqlite3_bind_text(stmt, 1, class, -1, SQLITE_STATIC); + + rc = sqlite3_step(stmt); + + if(rc!=SQLITE_ROW){ + strcpy(errmsg,"Unaccepted class."); + sqlite3_free(errMsg); + sqlite3_finalize(stmt); + sqlite3_close(db); + *recall=-1; + return; + } + sql = "SELECT name FROM majority WHERE name = ?;"; + + // 编译 SQL 语句 + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + sqlite3_free(errMsg); + sqlite3_finalize(stmt); + sqlite3_close(db); + return; + } + + // 绑定查询参数 + sqlite3_bind_text(stmt, 1, majority, -1, SQLITE_STATIC); + + rc = sqlite3_step(stmt); + + if(rc!=SQLITE_ROW){ + strcpy(errmsg,"Unaccepted majority."); + sqlite3_free(errMsg); + sqlite3_finalize(stmt); + sqlite3_close(db); + *recall=-1; + return; + } + + sql="INSERT INTO students (user,name,class,majority) VALUES(?,?,?,?)"; + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + sqlite3_free(errMsg); + sqlite3_finalize(stmt); + sqlite3_close(db); + return; + } + sqlite3_bind_text(stmt, 1, Username, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 3, class, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 4, majority, -1, SQLITE_STATIC); + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + strcpy(errmsg,"Error:database error"); + sqlite3_free(errMsg); + sqlite3_finalize(stmt); + sqlite3_close(db); + *recall=-1;return; + } + sqlite3_free(errMsg); + sqlite3_finalize(stmt); + sqlite3_close(db); + *recall=0; + return; +} + +void add(char* test,int *recall,char* errmsg){ + if(!test[0]){ + *recall=1; + return; + } + double ans; + char *test2[9999]; + strcpy(test2,test); + calculate(test2,recall,errmsg,&ans); + if(*recall==-1)return; + sqlite3 *db; + char *errMsg = 0; + int rc; + // 打开数据库,如果数据库文件不存在则创建它 + rc = sqlite3_open("./data/msg.db", &db); + if (rc) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + return; + } + char *sql_insert="INSERT INTO timu (text,answer) VALUES (?, ?);"; + sqlite3_stmt *insert; + rc = sqlite3_prepare_v2(db, sql_insert, -1, &insert, 0); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + *recall=-1; + sqlite3_close(db); + return; + } + + // 将第一个参数 (username) 绑定到 SQL 语句中的第一个 "?" + sqlite3_bind_text(insert, 1, test, -1, SQLITE_STATIC); + + // 将第二个参数 (password) 绑定到 SQL 语句中的第二个 "?" + sqlite3_bind_double(insert, 2, ans); + + rc = sqlite3_step(insert); + if (rc != SQLITE_DONE) { + strcpy(errmsg,"Error:database error"); + sqlite3_free(errMsg); + sqlite3_finalize(insert); + sqlite3_close(db); + *recall=-1;return; + } + sqlite3_free(errMsg); + sqlite3_finalize(insert); + sqlite3_close(db); + *recall=0; + return; +} \ No newline at end of file diff --git a/signin.c b/signin.c deleted file mode 100644 index 108e4c3..0000000 --- a/signin.c +++ /dev/null @@ -1,63 +0,0 @@ -// -// Created by zhang on 2024/12/29. -// -#include -#include -#include "./include/function.h" -#include "./include/sqlite3.h" - -void Signin(const char *username,const char*password,int *recall,char *errmsg){ - sqlite3 *db; - char *errMsg = 0; - int rc; - // 打开数据库,如果数据库文件不存在则创建它 - rc = sqlite3_open("./data/msg.db", &db); - if (rc) { - strcpy(errmsg,"Error:database error."); - *recall=-1; - return; - } - const char *sql_create_table = - "CREATE TABLE IF NOT EXISTS users " - "(" - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "user TEXT UNIQUE," - "password TEXT" - ");"; - - // 执行 SQL 语句 - rc = sqlite3_exec(db, sql_create_table, 0, 0, &errMsg); - if (rc != SQLITE_OK) { - strcpy(errmsg,"Error:database error."); - sqlite3_free(errMsg); - sqlite3_close(db); - *recall=-1;return; - } - const char *sql_insert="INSERT INTO users (user, password) VALUES (?, ?);"; - sqlite3_stmt *insert; - rc = sqlite3_prepare_v2(db, sql_insert, -1, &insert, 0); - if (rc != SQLITE_OK) { - strcpy(errmsg,"Error:database error."); - *recall=-1; - sqlite3_close(db); - return; - } - - // 将第一个参数 (name) 绑定到 SQL 语句中的第一个 "?" - sqlite3_bind_text(insert, 1, username, -1, SQLITE_STATIC); - - // 将第二个参数 (email) 绑定到 SQL 语句中的第二个 "?" - sqlite3_bind_text(insert, 2, password, -1, SQLITE_STATIC); - - rc = sqlite3_exec(db,insert,0,0,&errMsg); - if (rc != SQLITE_OK) { - strcpy(errmsg,errMsg); - sqlite3_free(errMsg); - sqlite3_finalize(insert); - sqlite3_close(db); - *recall=-1;return; - } - sqlite3_close(db); - *recall=0; - return; -} \ No newline at end of file diff --git a/ui.c b/ui.c index 1171fdd..ea465b1 100644 --- a/ui.c +++ b/ui.c @@ -3,23 +3,90 @@ // #include #include +#include +#include +#include #include "./include/function.h" #include "./include/curses.h" #include "./include/ui.h" -#include - +#include "./include/extern.h" +#include "./include/sqlite3.h" // 定义窗口宽度和高度 -#define WIN_HEIGHT 15 -#define WIN_WIDTH 40 +#define WIN_HEIGHT 30 +#define WIN_WIDTH 60 +//定义每一行最多显示多少列数据 +#define PAGE_SIZE 10 + +extern char Username[15]; +extern char class[15]; struct bottom { int x, y; int width, height; - char *test[30]; + char test[30]; int private; }; +typedef struct Node { + char *str1; // 存储第一个字符串 + char *str2; // 存储第二个字符串 + int num; // 存储整数 + struct Node *next; // 指向下一个节点的指针 +} Node; + +void free_list(Node *head) { + Node *temp; + while (head != NULL) { + temp = head; + head = head->next; + free(temp->str1); // 释放第一个字符串 + free(temp->str2); // 释放第二个字符串 + free(temp); // 释放节点本身 + } +} + +bool list_search(Node *head,int x) { + Node *temp = head; + while (temp != NULL) { + if(temp->num==x)return 1; + temp = temp->next; + } + return 0; +} + +Node* create_node(const char *str1, const char *str2, int num) { + Node *new_node = (Node *)malloc(sizeof(Node)); // 分配内存 + if (new_node == NULL) { + printf("Memory allocation failed\n"); + return NULL; + } + + new_node->str1 = strdup(str1); // 复制第一个字符串 + new_node->str2 = strdup(str2); // 复制第二个字符串 + new_node->num = num; // 设置整数 + new_node->next = NULL; // 初始化 next 为 NULL + + return new_node; +} + +void insert_node(Node **head, const char *str1, const char *str2, int num) { + Node *new_node = create_node(str1, str2, num); // 创建新节点 + if (new_node == NULL) { + return; // 如果创建节点失败,直接返回 + } + + if (*head == NULL) { + *head = new_node; // 如果链表为空,将新节点作为头节点 + } else { + Node *temp = *head; + while (temp->next != NULL) { + temp = temp->next; // 找到链表的最后一个节点 + } + temp->next = new_node; // 将新节点插入到链表末尾 + } +} + void draw_bottom(WINDOW *win, struct bottom *bot) { mvwprintw(win, bot->y, bot->x, "%s", bot->test); } @@ -49,6 +116,7 @@ int Welcome_ui() { curs_set(0); // 隐藏光标 keypad(stdscr, TRUE); // 启用键盘按键的特殊处理 mousemask(ALL_MOUSE_EVENTS, NULL); // 启用鼠标事件 + timeout(100); // 设置输入超时,防止程序卡死 // 获取屏幕的尺寸 // 计算按钮的显示位置 int start_y = (LINES - WIN_HEIGHT) / 2; @@ -120,9 +188,35 @@ draw_login_window(WINDOW *win, struct bottom *login, struct bottom *signin, stru wrefresh(win); // 刷新窗口 } +void +draw_stu_type_window(WINDOW *win, struct bottom *ok, struct bottom *name_b, struct bottom *class_b, + struct bottom *majority_b, struct bottom *exit) { + // 清空窗口并绘制边框 + wclear(win); + box(win, 0, 0); + + // 标题 + mvwprintw(win, 1, (WIN_WIDTH - 10) / 2, "Please input your message."); + + // 用户名输入框 + mvwprintw(win, 3, 4, "Name:"); + + // 密码输入框 + mvwprintw(win, 6, 4, "Class:"); + //绘制剩余内容 + mvwprintw(win, 9, 4, "Majority:"); + draw_bottom(win, ok); + draw_bottom(win, name_b); + draw_bottom(win, exit); + draw_bottom(win, class_b); + draw_bottom(win, majority_b); + wrefresh(win); // 刷新窗口 +} + + void draw_signin_window(WINDOW *win, struct bottom *signin, struct bottom *user, struct bottom *psword, - struct bottom *exit) { + struct bottom *exit) { // 清空窗口并绘制边框 wclear(win); box(win, 0, 0); @@ -143,6 +237,46 @@ draw_signin_window(WINDOW *win, struct bottom *signin, struct bottom *user, stru wrefresh(win); // 刷新窗口 } +void +draw_StudentDesktop_window(WINDOW *win, struct bottom *bt1, struct bottom *bt2, struct bottom *bt3, + struct bottom *bt4) { + // 清空窗口并绘制边框 + wclear(win); + box(win, 0, 0); + + // 标题 + mvwprintw(win, 1, 1, "Welcome! dear %s", Username); + + //绘制剩余内容 + + draw_bottom(win, bt1); + draw_bottom(win, bt2); + draw_bottom(win, bt3); + draw_bottom(win, bt4); + + wrefresh(win); // 刷新窗口 +} + +void +draw_TeacherDesktop_window(WINDOW *win, struct bottom *bt1, struct bottom *bt2, struct bottom *bt3, + struct bottom *bt4) { + // 清空窗口并绘制边框 + wclear(win); + box(win, 0, 0); + + // 标题 + mvwprintw(win, 1, 1, "Welcome! Doctor %s", Username); + + //绘制剩余内容 + + draw_bottom(win, bt1); + draw_bottom(win, bt2); + draw_bottom(win, bt3); + draw_bottom(win, bt4); + + wrefresh(win); // 刷新窗口 +} + void get_input(WINDOW *win, int y, int x, char *buffer, int max_len, struct bottom *bot, int sx, int sy) { MEVENT event; int ch, pos = 0; @@ -154,26 +288,203 @@ void get_input(WINDOW *win, int y, int x, char *buffer, int max_len, struct bott if (pos > 0) { pos--; buffer[pos] = '\0'; - test[pos + 1] = '_'; + if(bot->private!=2)test[pos + 1] = '_'; + else test[pos]='\0'; + mvwprintw(win,1,8," "); draw_bottom(win, bot); wrefresh(win); } - } else if (pos < max_len - 1 && ch >= 32 && ch <= 126) { // 可打印字符 - buffer[pos++] = ch; - if (bot->private == 0)test[pos] = ch; - else test[pos] = '*'; - draw_bottom(win, bot); - wrefresh(win); } else if (ch == KEY_MOUSE) { if (nc_getmouse(&event) == OK) { if (!click_bottom(event, *bot, sx, sy)) { return; } } + } else if (pos < max_len - 1) { + if (bot->private == 1) { + if (ch >= 33 && ch <= 126) {} + else { + mvwprintw(win, 12, 5, "Incorrect input"); + wrefresh(win); + continue; + } + } else if (bot->private == 0) { + if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9') {} + else { + mvwprintw(win, 12, 5, "Incorrect input"); + wrefresh(win); + continue; + } + } else if (bot->private == 2) { + if (ch >= '0' && ch <= '9' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' ||ch == ')') {} + else { + mvwprintw(win, 12, 5, "Incorrect input"); + wrefresh(win); + continue; + } + } + buffer[pos++] = ch; + if (bot->private == 0)test[pos] = ch; + else if(bot->private == 1)test[pos] = '*'; + else if(bot->private == 2)test[pos-1]=ch; + draw_bottom(win, bot); + wrefresh(win); + } + if(ch=='\n')return; + } +} + +void get_input_ez(WINDOW *win, int y, int x, char *buffer, int max_len) { + mvwprintw(win,y,x,"input here:"); + int ch, pos = 0; + memset(buffer, 0, max_len); // 清空缓冲区 + + while ((ch = wgetch(win)) != '\n') { // 按回车结束输入 + if (ch == 8 || ch == 127) { // 处理退格键 + if (pos > 0) { + pos--; // 移动到前一个字符位置 + buffer[pos] = '\0'; // 删除字符 + mvwprintw(win,y, x+11, "%s ", buffer); + wrefresh(win); + mvwprintw(win,y, x+11, "%s", buffer); + } + } else if (pos < max_len - 1 && ch >= 32 && ch <= 126) { // 可打印字符 + buffer[pos++] = ch; // 将字符加入输入内容 + buffer[pos] = '\0'; // 添加字符串结束符 + mvwprintw(win,y, x+11, "%s", buffer); // 在窗口中实时显示输入 } } } +int *display_t_test_page(WINDOW *win, sqlite3 *db, int offset, struct bottom *left, + struct bottom *right, struct bottom *exit,struct bottom *create) { + wclear(win); + box(win, 0, 0); + sqlite3_stmt *stmt; + int rc; + int row_count = 0; + char *sql_query="select test_name,Creater,problems_count,ID from tests"; + // 准备 SQL 语句 + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + mvwprintw(win, 0, 0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + wrefresh(win); + return 0; + } + int *id=malloc(PAGE_SIZE*sizeof(int)); + // 计算总行数 + int total_rows = 0; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + total_rows++; + } + sqlite3_reset(stmt); // 重置stmt以便重新执行查询 + + // 设置窗口的高度和宽度 + // 显示表格的头部 + mvwprintw(win, 3, 1, "Name Creater problem_count operate "); + mvwprintw(win, 4, 1, "----------------------------------------------------------"); + + // 跳到指定的偏移位置 + for (int i = 0; i < offset; i++) { + sqlite3_step(stmt); // 跳过前面的行 + } + // 从指定的偏移位置开始,显示10行 + int current_row = 5; // 数据开始显示的位置 + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW && row_count < PAGE_SIZE) { + const char *name = (const char *) sqlite3_column_text(stmt, 0); + const char *creater = (const char *) sqlite3_column_text(stmt, 1); + int problem_c = sqlite3_column_int(stmt, 2); + int now_id= sqlite3_column_int(stmt,3); + *(id+row_count)=now_id; + // 输出当前行 + mvwprintw(win, (current_row * 2) - 5, 1, "%-11s %-16s %-24d", name, creater, problem_c); + start_color(); + init_pair(1, COLOR_BLACK, COLOR_WHITE); + wattron(win, COLOR_PAIR(1)); + mvwprintw(win, (current_row * 2) - 5, 49, "delete"); + wattroff(win, COLOR_PAIR(1)); + row_count++; + current_row++; + } + + // 打印分页信息 + mvwprintw(win, WIN_HEIGHT - 3, (WIN_WIDTH - 9) / 2, "Page: %d/%d", (offset / PAGE_SIZE) + 1, + max(1,(total_rows + PAGE_SIZE - 1) / PAGE_SIZE)); + draw_bottom(win, left); + draw_bottom(win, right); + draw_bottom(win, exit); + draw_bottom(win,create); + // 刷新窗口 + wrefresh(win); + + sqlite3_finalize(stmt); + return id; +} + +int *display_stu_test_page(WINDOW *win, sqlite3 *db, int offset, struct bottom *left, + struct bottom *right, struct bottom *exit,int *t_l) { + wclear(win); + box(win, 0, 0); + sqlite3_stmt *stmt; + int rc; + int row_count = 0; + char *sql_query="select test_name,Creater,problems_count,ID from tests"; + // 准备 SQL 语句 + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + mvwprintw(win, 0, 0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + wrefresh(win); + return 0; + } + int *id=malloc(PAGE_SIZE*sizeof(int)); + // 计算总行数 + int total_rows = 0; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + total_rows++; + } + *t_l=total_rows; + sqlite3_reset(stmt); // 重置stmt以便重新执行查询 + + // 设置窗口的高度和宽度 + // 显示表格的头部 + mvwprintw(win, 3, 1, "Name Creater problem_count operate "); + mvwprintw(win, 4, 1, "----------------------------------------------------------"); + + // 跳到指定的偏移位置 + for (int i = 0; i < offset; i++) { + sqlite3_step(stmt); // 跳过前面的行 + } + // 从指定的偏移位置开始,显示10行 + int current_row = 5; // 数据开始显示的位置 + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW && row_count < PAGE_SIZE) { + const char *name = (const char *) sqlite3_column_text(stmt, 0); + const char *creater = (const char *) sqlite3_column_text(stmt, 1); + int problem_c = sqlite3_column_int(stmt, 2); + int now_id= sqlite3_column_int(stmt,3); + *(id+row_count)=now_id; + // 输出当前行 + mvwprintw(win, (current_row * 2) - 5, 1, "%-11s %-16s %-24d", name, creater, problem_c); + start_color(); + init_pair(1, COLOR_BLACK, COLOR_WHITE); + wattron(win, COLOR_PAIR(1)); + mvwprintw(win, (current_row * 2) - 5, 49, "enter"); + wattroff(win, COLOR_PAIR(1)); + row_count++; + current_row++; + } + + // 打印分页信息 + mvwprintw(win, WIN_HEIGHT - 3, (WIN_WIDTH - 9) / 2, "Page: %d/%d", (offset / PAGE_SIZE) + 1, + max(1,(total_rows + PAGE_SIZE - 1) / PAGE_SIZE)); + draw_bottom(win, left); + draw_bottom(win, right); + draw_bottom(win, exit); + // 刷新窗口 + wrefresh(win); + + sqlite3_finalize(stmt); + return id; +} int Login_ui() { MEVENT event; char *errmsg[30]; @@ -183,9 +494,9 @@ int Login_ui() { WINDOW *login_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); keypad(login_win, TRUE); char *username[15]; //储存用户名 - memset(username, 0, 15); // 清空缓冲区 + memset(username, '\0', 15); // 清空缓冲区 char *password[15]; //储存密码 - memset(password, 0, 15); // 清空缓冲区 + memset(password, '\0', 15); // 清空缓冲区 struct bottom *login = creat_bottom(login_win, 10, 4, 5, 1, "Login"); struct bottom *signin = creat_bottom(login_win, 10, 14, 5, 1, "Signin"); struct bottom *exit = creat_bottom(login_win, 10, 25, 5, 1, "Exit"); @@ -204,14 +515,23 @@ int Login_ui() { if (click_bottom(event, *login, start_x, start_y)) { int recall; Login(username, password, &recall, errmsg); - if (recall != 0) { + if (recall == -1) { wclear(login_win); mvwprintw(login_win, 5, 5, "%s", errmsg); - exit->x=5;exit->y=8; + exit->x = 5; + exit->y = 8; draw_bottom(login_win, exit); wrefresh(login_win); - willdraw=0; + willdraw = 0; continue; + } else { + free(login); + free(signin); + free(exit); + free(users); + free(psword); + endwin(); + return recall; } } if (willdraw) @@ -222,7 +542,7 @@ int Login_ui() { free(users); free(psword); endwin(); - return 3; + return SIGNIN_UI; } if (click_bottom(event, *exit, start_x, start_y)) { free(login); @@ -231,7 +551,7 @@ int Login_ui() { free(users); free(psword); endwin(); - return willdraw==1?1:2; + return willdraw == 1 ? WELCOME_UI : LOGIN_UI; } if (willdraw) if (click_bottom(event, *users, start_x, start_y)) { @@ -257,9 +577,9 @@ int Signin_ui() { WINDOW *signin_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); keypad(signin_win, TRUE); char *username[15]; //储存用户名 - memset(username, 0, 15); // 清空缓冲区 + memset(username, '\0', 15); // 清空缓冲区 char *password[15]; //储存密码 - memset(password, 0, 15); // 清空缓冲区 + memset(password, '\0', 15); // 清空缓冲区 struct bottom *signin = creat_bottom(signin_win, 10, 4, 5, 1, "Signin"); struct bottom *exit = creat_bottom(signin_win, 10, 25, 5, 1, "Exit"); struct bottom *users = creat_bottom(signin_win, 4, 4, 16, 1, "[______________]"); @@ -268,31 +588,32 @@ int Signin_ui() { users->private = 0; int willdraw = 1; while (1) { - if (willdraw)draw_signin_window(signin_win, signin, users, psword, exit); + if (willdraw == 1)draw_signin_window(signin_win, signin, users, psword, exit); int rc = wgetch(signin_win); if (rc == KEY_MOUSE) { if (nc_getmouse(&event) == OK) { //mvwprintw(welcome_win, 3, 1, "Mouse at (%d, %d), button %d", event.x-start_x, event.y-start_y, event.bstate); - if (willdraw) + if (willdraw == 1) if (click_bottom(event, *signin, start_x, start_y)) { int recall; - Signin(username,password,&recall,errmsg); + Signin(username, password, &recall, errmsg); if (recall != 0) { wclear(signin_win); mvwprintw(signin_win, 5, 5, "%s", errmsg); - exit->x=5;exit->y=8; + exit->x = 5; + exit->y = 8; draw_bottom(signin_win, exit); wrefresh(signin_win); - willdraw=0; + willdraw = 2; continue; - } - else{ + } else { wclear(signin_win); mvwprintw(signin_win, 5, 5, "Accepted"); - exit->x=5;exit->y=8; + exit->x = 5; + exit->y = 8; draw_bottom(signin_win, exit); wrefresh(signin_win); - willdraw=0; + willdraw = 0; continue; } } @@ -302,14 +623,14 @@ int Signin_ui() { free(users); free(psword); endwin(); - return willdraw==1?1:3; + return willdraw == 2 ? SIGNIN_UI : WELCOME_UI; } - if (willdraw) + if (willdraw == 1) if (click_bottom(event, *users, start_x, start_y)) { get_input(signin_win, 4, 6, username, 15, users, start_x, start_y); continue; } - if (willdraw) + if (willdraw == 1) if (click_bottom(event, *psword, start_x, start_y)) { get_input(signin_win, 7, 6, password, 15, psword, start_x, start_y); continue; @@ -319,5 +640,1307 @@ int Signin_ui() { } } +int stu_type_ui() { + int recall = stu_type_check(); + if (recall == -1)myexit(); + if (recall == 1)return 0; + MEVENT event; + char *errmsg[30]; + memset(errmsg, 0, 30); + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *stu_type_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(stu_type_win, TRUE); + char *name[15]; //储存用户名 + memset(name, '\0', 15); // 清空缓冲区 + char *majority[15]; //储存用户名 + memset(majority, '\0', 15); // 清空缓冲区 + char *class[15]; //储存密码 + memset(class, '\0', 15); // 清空缓冲区 + struct bottom *ok = creat_bottom(stu_type_win, 13, 4, 5, 1, "OK"); + struct bottom *exit = creat_bottom(stu_type_win, 13, 25, 5, 1, "Exit"); + struct bottom *name_b = creat_bottom(stu_type_win, 4, 4, 16, 1, "[______________]"); + struct bottom *class_b = creat_bottom(stu_type_win, 7, 4, 16, 1, "[______________]"); + struct bottom *majority_b = creat_bottom(stu_type_win, 10, 4, 16, 1, "[______________]"); + name_b->private = 0; + class_b->private = 0; + majority_b->private = 0; + int willdraw = 1; + while (1) { + if (willdraw)draw_stu_type_window(stu_type_win, ok, name_b, class_b, majority_b, exit); + int rc = wgetch(stu_type_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + //mvwprintw(welcome_win, 3, 1, "Mouse at (%d, %d), button %d", event.x-start_x, event.y-start_y, event.bstate); + if (willdraw) + if (click_bottom(event, *ok, start_x, start_y)) { + int recall; + stu_type_insert(name, class, majority, &recall, errmsg); + if (recall == -1) { + wclear(stu_type_win); + mvwprintw(stu_type_win, 5, 5, "%s", errmsg); + exit->x = 5; + exit->y = 8; + draw_bottom(stu_type_win, exit); + wrefresh(stu_type_win); + willdraw = 0; + continue; + } else { + free(ok); + free(name_b); + free(exit); + free(class_b); + free(majority_b); + endwin(); + return 0; + } + } + if (click_bottom(event, *exit, start_x, start_y)) { + free(ok); + free(exit); + free(name_b); + free(class_b); + free(majority_b); + endwin(); + return -1; + } + if (willdraw) + if (click_bottom(event, *name_b, start_x, start_y)) { + get_input(stu_type_win, 4, 6, name, 15, name_b, start_x, start_y); + continue; + } + if (willdraw) + if (click_bottom(event, *class_b, start_x, start_y)) { + get_input(stu_type_win, 7, 6, class, 15, class_b, start_x, start_y); + continue; + } + if (willdraw) + if (click_bottom(event, *majority_b, start_x, start_y)) { + get_input(stu_type_win, 4, 6, majority, 15, majority_b, start_x, start_y); + continue; + } + } + } + } + +} + +int StudentsDesktop_ui() { + int recall = stu_type_ui(); + if (recall == -1) { + memset(Username, 0, 15); + return WELCOME_UI; + } + MEVENT event; + char *errmsg[30]; + memset(errmsg, 0, 30); + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *StudentsDesktop_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(StudentsDesktop_win, TRUE); + struct bottom *test = creat_bottom(StudentsDesktop_win, 3, 4, 6, 1, "1.Test"); + struct bottom *hissc = creat_bottom(StudentsDesktop_win, 6, 4, 15, 1, "2.History Score"); + struct bottom *exercise = creat_bottom(StudentsDesktop_win, 9, 4, 10, 1, "3.Exercise"); + struct bottom *exit = creat_bottom(StudentsDesktop_win, 12, 4, 6, 1, "4.Exit"); + while (1) { + draw_StudentDesktop_window(StudentsDesktop_win, test, hissc, exercise, exit); + int rc = wgetch(StudentsDesktop_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *test, start_x, start_y)) { + int recall; + + stu_test_ui(&recall, errmsg, class); + if (recall != 0) { + wclear(StudentsDesktop_win); + mvwprintw(StudentsDesktop_win, 1, 1, errmsg); + sqlite3_sleep(2000); + } + continue; + } + if (click_bottom(event, *hissc, start_x, start_y)) { + stu_his_sc_ui(); + continue; + } + if (click_bottom(event, *exercise, start_x, start_y)) { + stu_exercise_ui(); + continue; + } + if (click_bottom(event, *exit, start_x, start_y)) { + free(test); + free(hissc); + free(exit); + free(exercise); + endwin(); + memset(Username, 0, 15); + return WELCOME_UI; + } + } + } + } +} + +void stu_exercise_ui() { + +} + +void display_stu_score_page(WINDOW *win, sqlite3 *db, int offset, struct bottom *left,struct bottom *right, struct bottom *exit, struct bottom *search,int *row_count){ + char *sql_query="select majority,class,name,test_name,score from stu where user=? and test_name like ?"; + int *id=malloc(PAGE_SIZE*sizeof(int)); + wclear(win); + box(win, 0, 0); + sqlite3_stmt *stmt; + int rc; + + // 准备 SQL 语句 + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + mvwprintw(win, 0, 0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + wrefresh(win); + return; + } + char query[100]; + memset(query,0,sizeof(query)); + snprintf(query, sizeof(query), "%%%s%%", search->test); // 构造 LIKE 查询参数 + sqlite3_bind_text(stmt, 1, Username, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, query, -1, SQLITE_STATIC); + // 计算总行数 + int total_rows = 0; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + total_rows++; + } + *row_count=total_rows; + sqlite3_reset(stmt); // 重置stmt以便重新执行查询 + + // 设置窗口的高度和宽度 + // 显示表格的头部 + mvwprintw(win, 1, 1, "Search:"); + mvwprintw(win, 3, 1, "majority class name test_name score "); + mvwprintw(win, 4, 1, "----------------------------------------------------------"); + + // 跳到指定的偏移位置 + for (int i = 0; i < offset; i++) { + sqlite3_step(stmt); // 跳过前面的行 + } + int row_c=0; + // 从指定的偏移位置开始,显示10行 + int current_row = 5; // 数据开始显示的位置 + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW && row_c < PAGE_SIZE) { + const char *majority = (const char *) sqlite3_column_text(stmt, 0); + const char *class = (const char *) sqlite3_column_text(stmt, 1); + const char *name = (const char *) sqlite3_column_text(stmt, 2); + const char *test_name = (const char *) sqlite3_column_text(stmt, 3); + int score = sqlite3_column_int(stmt, 4); + // 输出当前行 + mvwprintw(win, (current_row * 2) - 5, 1, "%-13s %-10s %-10s %-15s %-5d",majority,class,name,test_name,score); + row_c++; + current_row++; + } + + // 打印分页信息 + mvwprintw(win, WIN_HEIGHT - 3, (WIN_WIDTH - 9) / 2, "Page: %d/%d", (offset / PAGE_SIZE) + 1, + max(1,(total_rows + PAGE_SIZE - 1) / PAGE_SIZE)); + draw_bottom(win, left); + draw_bottom(win, right); + draw_bottom(win, exit); + draw_bottom(win, search); + draw_bottom(win, add); + // 刷新窗口 + wrefresh(win); + + sqlite3_finalize(stmt); + return; +} + +void display_t_score_page(WINDOW *win, sqlite3 *db, int offset, struct bottom *left,struct bottom *right, struct bottom *exit, struct bottom *search,int *row_count){ + char *sql_query="select majority,class,name,test_name,score from stu where test_name like ?"; + int *id=malloc(PAGE_SIZE*sizeof(int)); + wclear(win); + box(win, 0, 0); + sqlite3_stmt *stmt; + int rc; + + // 准备 SQL 语句 + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + mvwprintw(win, 0, 0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + wrefresh(win); + return; + } + char query[100]; + memset(query,0,sizeof(query)); + snprintf(query, sizeof(query), "%%%s%%", search->test); // 构造 LIKE 查询参数 + sqlite3_bind_text(stmt, 1, query, -1, SQLITE_STATIC); + // 计算总行数 + int total_rows = 0; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + total_rows++; + } + *row_count=total_rows; + sqlite3_reset(stmt); // 重置stmt以便重新执行查询 + + // 设置窗口的高度和宽度 + // 显示表格的头部 + mvwprintw(win, 1, 1, "Search:"); + mvwprintw(win, 3, 1, "majority class name test_name score "); + mvwprintw(win, 4, 1, "----------------------------------------------------------"); + + // 跳到指定的偏移位置 + for (int i = 0; i < offset; i++) { + sqlite3_step(stmt); // 跳过前面的行 + } + int row_c=0; + // 从指定的偏移位置开始,显示10行 + int current_row = 5; // 数据开始显示的位置 + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW && row_c < PAGE_SIZE) { + const char *majority = (const char *) sqlite3_column_text(stmt, 0); + const char *class = (const char *) sqlite3_column_text(stmt, 1); + const char *name = (const char *) sqlite3_column_text(stmt, 2); + const char *test_name = (const char *) sqlite3_column_text(stmt, 3); + int score = sqlite3_column_int(stmt, 4); + // 输出当前行 + mvwprintw(win, (current_row * 2) - 5, 1, "%-13s %-10s %-10s %-15s %-5d",majority,class,name,test_name,score); + row_c++; + current_row++; + } + + // 打印分页信息 + mvwprintw(win, WIN_HEIGHT - 3, (WIN_WIDTH - 9) / 2, "Page: %d/%d", (offset / PAGE_SIZE) + 1, + max(1,(total_rows + PAGE_SIZE - 1) / PAGE_SIZE)); + draw_bottom(win, left); + draw_bottom(win, right); + draw_bottom(win, exit); + draw_bottom(win, search); + draw_bottom(win, add); + // 刷新窗口 + wrefresh(win); + + sqlite3_finalize(stmt); + return; +} + +void stu_his_sc_ui() { + MEVENT event; + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *stu_score_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(stu_score_win, TRUE); + int offset = 0; + sqlite3 *db; + const char *db_filename = "./data/msg.db"; // SQLite 数据库文件名 + const char *sql_query; // 查询 SQL + struct bottom *left = creat_bottom(stu_score_win, WIN_HEIGHT - 3, 20, 2, 1, "<-"); + struct bottom *right = creat_bottom(stu_score_win, WIN_HEIGHT - 3, 40, 2, 1, "->"); + struct bottom *exit = creat_bottom(stu_score_win, WIN_HEIGHT - 3, 52, 4, 1, "Exit"); + struct bottom *search = creat_bottom(stu_score_win, 1, 8, 20, 1, ""); + memset(search->test,0,30); + search->private = 2; + char searchq[100]; + memset(searchq, 0, 100); + // 打开数据库 + if (sqlite3_open(db_filename, &db) != SQLITE_OK) { + return; + } + int *id; + sqlite3_stmt *stmt; + int row_count = 0; + while (1) { + // 清空窗口内容 + werase(stu_score_win); + box(stu_score_win, 0, 0); + // 调用函数输出当前的滚动窗口内容 + display_stu_score_page(stu_score_win, db, offset, left, right, exit, search,&row_count); + + int rc = wgetch(stu_score_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *left, start_x, start_y)) { + if (offset >= PAGE_SIZE) { + offset -= PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *right, start_x, start_y)) { + if (offset + PAGE_SIZE < row_count) { // 总共有100条数据可以调整 + offset += PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *exit, start_x, start_y)) { + free(left); + free(right); + free(exit); + delwin(stu_score_win); + return; + } + if (click_bottom(event, *search, start_x, start_y)) { + get_input(stu_score_win, 4, 6, searchq, 15, search, start_x, start_y); + offset = 0; + continue; + } + } + } + } +} + +void t_his_sc_ui() { + MEVENT event; + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *t_score_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(t_score_win, TRUE); + int offset = 0; + sqlite3 *db; + const char *db_filename = "./data/msg.db"; // SQLite 数据库文件名 + const char *sql_query; // 查询 SQL + struct bottom *left = creat_bottom(t_score_win, WIN_HEIGHT - 3, 20, 2, 1, "<-"); + struct bottom *right = creat_bottom(t_score_win, WIN_HEIGHT - 3, 40, 2, 1, "->"); + struct bottom *exit = creat_bottom(t_score_win, WIN_HEIGHT - 3, 52, 4, 1, "Exit"); + struct bottom *search = creat_bottom(t_score_win, 1, 8, 20, 1, ""); + memset(search->test,0,30); + search->private = 2; + char searchq[100]; + memset(searchq, 0, 100); + // 打开数据库 + if (sqlite3_open(db_filename, &db) != SQLITE_OK) { + return; + } + int *id; + sqlite3_stmt *stmt; + int row_count = 0; + while (1) { + // 清空窗口内容 + werase(t_score_win); + box(t_score_win, 0, 0); + // 调用函数输出当前的滚动窗口内容 + display_t_score_page(t_score_win, db, offset, left, right, exit, search,&row_count); + + int rc = wgetch(t_score_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *left, start_x, start_y)) { + if (offset >= PAGE_SIZE) { + offset -= PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *right, start_x, start_y)) { + if (offset + PAGE_SIZE < row_count) { // 总共有100条数据可以调整 + offset += PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *exit, start_x, start_y)) { + free(left); + free(right); + free(exit); + delwin(t_score_win); + return; + } + if (click_bottom(event, *search, start_x, start_y)) { + get_input(t_score_win, 4, 6, searchq, 15, search, start_x, start_y); + offset = 0; + continue; + } + } + } + } +} + +void enter(WINDOW *win,sqlite3 *db,int id,int start_x,int start_y){ + int offset=0; + int correct_conuts=0; + int total_rows = 0; + double answer; + struct bottom *exit = creat_bottom(win, WIN_HEIGHT - 3, 52, 4, 1, "Exit"); + while(1){ + wclear(win); + box(win, 0, 0); + sqlite3_stmt *stmt; + int rc; + char *sql_query="select text,answer from test_include where test_index=?"; + // 准备 SQL 语句 + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + mvwprintw(win, 0, 0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + wrefresh(win); + return; + } + sqlite3_bind_int(stmt,1,id); + // 计算总行数 + total_rows=0; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + total_rows++; + } + sqlite3_reset(stmt); // 重置stmt以便重新执行查询 + // 跳到指定的偏移位置 + for (int i = 0; i < offset; i++) { + sqlite3_step(stmt); // 跳过前面的行 + } + // 从指定的偏移位置开始,显示10行 + if((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + const char *name = (const char *) sqlite3_column_text(stmt, 0); + answer = sqlite3_column_double(stmt, 1); + int now_id= sqlite3_column_int(stmt,2); + // 输出当前行 + mvwprintw(win, 15, 15, "%-22s", name); + } + + // 打印分页信息 + mvwprintw(win, WIN_HEIGHT - 3, (WIN_WIDTH - 9) / 2, "Problem: %d/%d", offset + 1,total_rows); + draw_bottom(win, exit); + mvwprintw(win, 17, 15, "Please input your answer:", offset + 1,total_rows); + // 刷新窗口 + wrefresh(win); + + double ans; + cbreak(); // 禁用行缓冲 + noecho(); // 禁用自动回显 + curs_set(1); // 显示光标 + mvwscanw(win,18,15,"%lf",&ans); + + mvwprintw(win,18,15,"Your answer:%.3lf",ans); + mvwprintw(win,19,15,"standard answer:%.3lf",answer); + + if(abs(ans-answer)<0.01){ + mvwprintw(win,20,15,"Accepted"); + correct_conuts++; + } + else{ + mvwprintw(win,20,15,"Wrong answer"); + } + wrefresh(win); + sqlite3_finalize(stmt); + sqlite3_sleep(2000); + offset++; + if(offset==total_rows)break; + } + wclear(win); + mvwprintw(win,15,15,"The text has finished."); + int score=(double)correct_conuts/(double)total_rows*100; + mvwprintw(win,16,15,"Your Score is:%d",score);wrefresh(win); + sqlite3_sleep(5000); + sqlite3_stmt *stmt; + int rc; + char *sql_select="select test_name from tests where ID=?;"; + rc = sqlite3_prepare_v2(db, sql_select, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return; + } + char *db_test_name; + // 绑定查询参数 + sqlite3_bind_int(stmt, 1, id); + rc = sqlite3_step(stmt); + if (rc == SQLITE_ROW) { + + db_test_name = sqlite3_column_text(stmt, 0); + } + else{ + sqlite3_finalize(stmt); + free(exit); + return; + } + char *sql_query = "insert into stu (majority,class,name,test_name,test_index,score,user) select majority,class,name,?,?,?,user from students where user=?;"; + // 编译 SQL 语句 + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + sqlite3_finalize(stmt); + sqlite3_close(db); + return; + } + + sqlite3_bind_text(stmt,1,db_test_name,-1,SQLITE_STATIC); + sqlite3_bind_int(stmt,2,id); + sqlite3_bind_int(stmt,3,score); + sqlite3_bind_text(stmt,4,Username,-1,SQLITE_STATIC); + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + sqlite3_finalize(stmt); + free(exit); + return; + } + sqlite3_finalize(stmt); + while(1) { + MEVENT event; + draw_bottom(win,exit); + wrefresh(win); + int rc = wgetch(win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *exit, start_x, start_y)) { + free(exit); + return; + } + } + } + } +} + +void stu_test_ui(int *recall, char *errmsg, char *class) { + MEVENT event; + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *stu_problem_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(stu_problem_win, TRUE); + int offset = 0; + sqlite3 *db; + const char *db_filename = "./data/msg.db"; // SQLite 数据库文件名 + const char *sql_query; // 查询 SQL + struct bottom *left = creat_bottom(stu_problem_win, WIN_HEIGHT - 3, 20, 2, 1, "<-"); + struct bottom *right = creat_bottom(stu_problem_win, WIN_HEIGHT - 3, 40, 2, 1, "->"); + struct bottom *exit = creat_bottom(stu_problem_win, WIN_HEIGHT - 3, 52, 4, 1, "Exit"); + // 打开数据库 + if (sqlite3_open(db_filename, &db) != SQLITE_OK) { + *recall = -1; + return; + } + int *id; + sqlite3_stmt *stmt; + int row_count = 0; + while (1) { + // 清空窗口内容 + werase(stu_problem_win); + box(stu_problem_win, 0, 0); + // 调用函数输出当前的滚动窗口内容 + id = display_stu_test_page(stu_problem_win, db, offset, left, right, exit,&row_count); + + int rc = wgetch(stu_problem_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *left, start_x, start_y)) { + if (offset >= PAGE_SIZE) { + offset -= PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *right, start_x, start_y)) { + if (offset + PAGE_SIZE < row_count) { // 总共有100条数据可以调整 + offset += PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *exit, start_x, start_y)) { + free(left); + free(right); + free(exit); + free(id); + sqlite3_close(db); + delwin(stu_problem_win); + return; + } + if (event.x - start_x >= 49 && event.x - start_x <= 53) { //enter + int test_id=*(id+(((event.y-start_y)+5)/2-5)); + enter(stu_problem_win,db,test_id,start_x,start_y); + } + } + } + } +} + +void t_test_ui(int *recall, char *errmsg) { + MEVENT event; + memset(errmsg, 0, 30); + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *t_test_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(t_test_win, TRUE); + int offset = 0; + sqlite3 *db; + const char *db_filename = "./data/msg.db"; // SQLite 数据库文件名 + const char *sql_query; // 查询 SQL + struct bottom *left = creat_bottom(t_test_win, WIN_HEIGHT - 3, 20, 2, 1, "<-"); + struct bottom *right = creat_bottom(t_test_win, WIN_HEIGHT - 3, 40, 2, 1, "->"); + struct bottom *exit = creat_bottom(t_test_win, WIN_HEIGHT - 3, 52, 2, 1, "Exit"); + struct bottom *create = creat_bottom(t_test_win,1,52,6,1,"Create"); + // 打开数据库 + if (sqlite3_open(db_filename, &db) != SQLITE_OK) { + strcpy(errmsg, "Error:database error"); + *recall = -1; + return; + } + + sqlite3_stmt *stmt; + const char *sql = "SELECT COUNT(*) FROM tests;"; + int row_count = 0; + + // 准备 SQL 查询 + int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + if (rc != SQLITE_OK) { + strcpy(errmsg, "Error:database error"); + sqlite3_close(db); + sqlite3_finalize(stmt); + *recall = -1; + return; + } + rc = sqlite3_step(stmt); + if (rc == SQLITE_ROW) { + // 获取 COUNT(*) 的值,列索引是 0 + row_count = sqlite3_column_int(stmt, 0); + } else { + strcpy(errmsg, "Error:database error"); + sqlite3_close(db); + sqlite3_finalize(stmt); + *recall = -1; + return; + } + sqlite3_finalize(stmt); + while (1) { + // 清空窗口内容 + werase(t_test_win); + box(t_test_win, 0, 0); + + // 调用函数输出当前的滚动窗口内容 + int *id=display_t_test_page(t_test_win, db, offset, left, right, exit,create); + if(id==NULL){ + sqlite3_close(db); + sqlite3_finalize(stmt); + return; + } + int rc = wgetch(t_test_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *left, start_x, start_y)) { + if (offset >= PAGE_SIZE) { + offset -= PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *right, start_x, start_y)) { + if (offset + PAGE_SIZE < row_count) { // 总共有100条数据可以调整 + offset += PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *exit, start_x, start_y)) { + free(left); + free(right); + free(exit); + sqlite3_close(db); + *recall = 0; + return; + } + if(click_bottom(event,*create,start_x,start_y)){ + create_ui(); + continue; + } + if (event.x-start_x >= 49 && event.x-start_x <= 54) { //delete + sql_query="delete from tests where ID=?"; + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + sqlite3_finalize(stmt); + continue; + } + sqlite3_bind_int(stmt, 1, *(id+(((event.y-start_y)+5)/2-5))); + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + sqlite3_finalize(stmt); + return; + } + sql_query="delete from test_include where test_index=?"; + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + sqlite3_finalize(stmt); + continue; + } + sqlite3_bind_int(stmt, 1, *(id+(((event.y-start_y)+5)/2-5))); + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + sqlite3_finalize(stmt); + return; + } + sqlite3_finalize(stmt); + continue; + } + } + } + } +} +int *display_t_problem_page(WINDOW *win, sqlite3 *db, int offset, struct bottom *left, + struct bottom *right, struct bottom *exit, struct bottom *search, struct bottom *add,int *row_count) { + char *sql_query="select text,answer,ID from timu where text like ?"; + int *id=malloc(PAGE_SIZE*sizeof(int)); + wclear(win); + box(win, 0, 0); + sqlite3_stmt *stmt; + int rc; + + // 准备 SQL 语句 + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + mvwprintw(win, 0, 0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + wrefresh(win); + return 0; + } + char query[100]; + memset(query,0,sizeof(query)); + snprintf(query, sizeof(query), "%%%s%%", search->test); // 构造 LIKE 查询参数 + sqlite3_bind_text(stmt, 1, query, -1, SQLITE_STATIC); + // 计算总行数 + int total_rows = 0; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + total_rows++; + } + *row_count=total_rows; + sqlite3_reset(stmt); // 重置stmt以便重新执行查询 + + // 设置窗口的高度和宽度 + // 显示表格的头部 + mvwprintw(win, 1, 1, "Search:"); + mvwprintw(win, 3, 1, "timu answer operate "); + mvwprintw(win, 4, 1, "----------------------------------------------------------"); + + // 跳到指定的偏移位置 + for (int i = 0; i < offset; i++) { + sqlite3_step(stmt); // 跳过前面的行 + } + int row_c=0; + // 从指定的偏移位置开始,显示10行 + int current_row = 5; // 数据开始显示的位置 + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW && row_c < PAGE_SIZE) { + const char *name = (const char *) sqlite3_column_text(stmt, 0); + double answer = sqlite3_column_double(stmt, 1); + int now_id= sqlite3_column_int(stmt,2); + *(id+row_c)=now_id; + // 输出当前行 + if(floor(answer)==answer)mvwprintw(win, (current_row * 2) - 5, 1, "%-22s %d", name, (int)answer); + else mvwprintw(win, (current_row * 2) - 5, 1, "%-22s %lf", name, answer); + start_color(); + init_pair(1, COLOR_BLACK, COLOR_WHITE); + wattron(win, COLOR_PAIR(1)); + mvwprintw(win, (current_row * 2) - 5, 42, "update"); + mvwprintw(win, (current_row * 2) - 5, 52, "delete"); + wattroff(win, COLOR_PAIR(1)); + row_c++; + current_row++; + } + + // 打印分页信息 + mvwprintw(win, WIN_HEIGHT - 3, (WIN_WIDTH - 9) / 2, "Page: %d/%d", (offset / PAGE_SIZE) + 1, + max(1,(total_rows + PAGE_SIZE - 1) / PAGE_SIZE)); + draw_bottom(win, left); + draw_bottom(win, right); + draw_bottom(win, exit); + draw_bottom(win, search); + draw_bottom(win, add); + // 刷新窗口 + wrefresh(win); + + sqlite3_finalize(stmt); + return id; +} + +int add_ui(){ + keypad(stdscr, FALSE); // 启用功能键(如退格键) + curs_set(1); // 显示光标 + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *add_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + char test[9999]; + memset(test,0,9999); + int pos = 0; + char ch; + while (1) { // 按下 Ctrl+G 结束输入 + mvwprintw(add_win,1,1,"input the text,enter means next row.Ctrl+G to exit.\n"); + wrefresh(add_win); + ch= wgetch(add_win); + if(ch==7) { + delwin(add_win); + break; + } + if(ch=='\n'){ + int recall; + char *errmsg[100]; + add(test,&recall,errmsg); + memset(test,0,sizeof(test)); + pos=0; + if(recall==-1){ + wclear(add_win); + mvwprintw(add_win,1,1,"Error:%s",errmsg); + wrefresh(add_win); + sqlite3_sleep(2000); + continue; + } + else if(recall==1){ + wclear(add_win);continue; + } + else{ + wclear(add_win); + mvwprintw(add_win,1,1,"Accept."); + wrefresh(add_win); + sqlite3_sleep(2000); + continue; + } + } + if (ch == 8 || ch == 127) { // 处理退格键 + if (pos > 0) { + pos--; // 移动到前一个字符位置 + test[pos] = '\0'; // 删除字符 + mvwprintw(add_win,3, 0, "%s ", test); // 用空格清除多余字符 + wrefresh(add_win); + mvwprintw(add_win,3, 0, "%s", test); // 用空格清除多余字符 + } + } else if ((ch >= 32 && ch <= 126||ch=='\n')) { // 处理可显示字符 + if (pos < 9999 - 1) { + test[pos++] = ch; // 将字符加入输入内容 + test[pos] = '\0'; // 添加字符串结束符 + mvwprintw(add_win,3, 0, "%s", test); // 在窗口中实时显示输入 + } + } + wrefresh(add_win); // 更新窗口显示 + } + curs_set(0); + endwin(); + return T_PROBLEM_UI; +} + +int t_problem_ui() { + MEVENT event; + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *t_problem_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(t_problem_win, TRUE); + int offset = 0; + sqlite3 *db; + const char *db_filename = "./data/msg.db"; // SQLite 数据库文件名 + const char *sql_query; // 查询 SQL + struct bottom *left = creat_bottom(t_problem_win, WIN_HEIGHT - 3, 20, 2, 1, "<-"); + struct bottom *right = creat_bottom(t_problem_win, WIN_HEIGHT - 3, 40, 2, 1, "->"); + struct bottom *exit = creat_bottom(t_problem_win, WIN_HEIGHT - 3, 52, 4, 1, "Exit"); + struct bottom *add = creat_bottom(t_problem_win, 1, 54, 3, 1, "Add"); + struct bottom *search = creat_bottom(t_problem_win, 1, 8, 20, 1, ""); + memset(search->test,0,30); + search->private = 2; + char searchq[100]; + memset(searchq, 0, 100); + // 打开数据库 + if (sqlite3_open(db_filename, &db) != SQLITE_OK) { + return TEACHER_UI; + } + int *id; + sqlite3_stmt *stmt; + int row_count = 0; + while (1) { + // 清空窗口内容 + werase(t_problem_win); + box(t_problem_win, 0, 0); + // 调用函数输出当前的滚动窗口内容 + id=display_t_problem_page(t_problem_win, db, offset, left, right, exit, search, add,&row_count); + + int rc = wgetch(t_problem_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *left, start_x, start_y)) { + if (offset >= PAGE_SIZE) { + offset -= PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *right, start_x, start_y)) { + if (offset + PAGE_SIZE < row_count) { // 总共有100条数据可以调整 + offset += PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *exit, start_x, start_y)) { + free(left); + free(right); + free(exit); + free(id); + sqlite3_close(db); + delwin(t_problem_win); + return TEACHER_UI; + } + if (click_bottom(event, *add, start_x, start_y)) { + free(left); + free(right); + free(exit); + free(id); + sqlite3_close(db); + delwin(t_problem_win); + return ADD_UI; + } + if (click_bottom(event, *search, start_x, start_y)) { + get_input(t_problem_win, 4, 6, searchq, 15, search, start_x, start_y); + offset=0; + continue; + } + if (event.x-start_x >= 52 && event.x-start_x <= 57) { //delete + sql_query="delete from timu where ID=?"; + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + sqlite3_finalize(stmt); + continue; + } + sqlite3_bind_int(stmt, 1, *(id+(((event.y-start_y)+5)/2-5))); + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + sqlite3_finalize(stmt); + continue; + } + sqlite3_finalize(stmt); + continue; + } + if (event.x-start_x >= 42 && event.x-start_x <= 47) { //update + + sql_query="update timu set text=? ,answer=? where ID=?"; + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + sqlite3_finalize(stmt); + continue; + } + char input[9999]; + memset(input,0,sizeof(input)); + get_input_ez(t_problem_win, WIN_HEIGHT-2,1, input, 15); + double ans; + int recall=0; + sqlite3_bind_text(stmt, 1, input,-1,SQLITE_STATIC); + char errmsg[100]; + calculate(input,&recall,errmsg,&ans); + if(recall==-1){ + mvwprintw(t_problem_win,WIN_HEIGHT-2,1,"Incorrect input!"); + sqlite3_sleep(1000); + sqlite3_finalize(stmt); + continue; + } + sqlite3_bind_double(stmt, 2, ans); + sqlite3_bind_int(stmt, 3, *(id+(((event.y-start_y)+5)/2-5))); + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + sqlite3_finalize(stmt); + continue; + } + sqlite3_finalize(stmt); + continue; + } + } + } + } +} + +int TeachersDesktop_ui() { + MEVENT event; + char *errmsg[30]; + memset(errmsg, 0, 30); + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *TeacherDesktop_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(TeacherDesktop_win, TRUE); + struct bottom *test = creat_bottom(TeacherDesktop_win, 3, 4, 14, 1, "1.Test desktop"); + struct bottom *problem = creat_bottom(TeacherDesktop_win, 6, 4, 17, 1, "2.Problem desktop"); + struct bottom *score = creat_bottom(TeacherDesktop_win, 9, 4, 13, 1, "3.Score check"); + struct bottom *exit = creat_bottom(TeacherDesktop_win, 12, 4, 6, 1, "4.Exit"); + while (1) { + draw_TeacherDesktop_window(TeacherDesktop_win, test, problem, score, exit); + int rc = wgetch(TeacherDesktop_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *test, start_x, start_y)) { + int recall=0; + t_test_ui(&recall,errmsg); + } + if (click_bottom(event, *score, start_x, start_y)) { + t_his_sc_ui(); + continue; + } + if (click_bottom(event, *problem, start_x, start_y)) { + int recall; + return T_PROBLEM_UI; + } + if (click_bottom(event, *exit, start_x, start_y)) { + free(test); + free(score); + free(exit); + free(problem); + endwin(); + memset(Username, 0, 15); + return WELCOME_UI; + } + } + } + } +} + +int *display_t_problem_page_2(WINDOW *win, sqlite3 *db, int offset, struct bottom *left,struct bottom *right, struct bottom *ok, struct bottom *search,int *row_count,Node *head){ + char *sql_query="select text,answer,ID from timu where text like ?"; + int *id=malloc(PAGE_SIZE*sizeof(int)); + wclear(win); + box(win, 0, 0); + sqlite3_stmt *stmt; + int rc; + + // 准备 SQL 语句 + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + mvwprintw(win, 0, 0, "Failed to prepare statement: %s", sqlite3_errmsg(db)); + wrefresh(win); + return 0; + } + char query[100]; + memset(query,0,sizeof(query)); + snprintf(query, sizeof(query), "%%%s%%", search->test); // 构造 LIKE 查询参数 + sqlite3_bind_text(stmt, 1, query, -1, SQLITE_STATIC); + // 计算总行数 + int total_rows = 0; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + total_rows++; + } + *row_count=total_rows; + sqlite3_reset(stmt); // 重置stmt以便重新执行查询 + + // 设置窗口的高度和宽度 + // 显示表格的头部 + mvwprintw(win, 1, 1, "Search:"); + mvwprintw(win, 3, 1, "timu answer operate "); + mvwprintw(win, 4, 1, "----------------------------------------------------------"); + + // 跳到指定的偏移位置 + for (int i = 0; i < offset; i++) { + sqlite3_step(stmt); // 跳过前面的行 + } + int row_c=0; + // 从指定的偏移位置开始,显示10行 + int current_row = 5; // 数据开始显示的位置 + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW && row_c < PAGE_SIZE) { + const char *name = (const char *) sqlite3_column_text(stmt, 0); + double answer = sqlite3_column_double(stmt, 1); + int now_id= sqlite3_column_int(stmt,2); + *(id+row_c)=now_id; + // 输出当前行 + if(floor(answer)==answer)mvwprintw(win, (current_row * 2) - 5, 1, "%-22s %d", name, (int)answer); + else mvwprintw(win, (current_row * 2) - 5, 1, "%-22s %lf", name, answer); + start_color(); + init_pair(1, COLOR_BLACK, COLOR_WHITE); + if(!list_search(head,now_id)) + { + wattron(win, COLOR_PAIR(1)); + mvwprintw(win, (current_row * 2) - 5, 45, "select"); + wattroff(win, COLOR_PAIR(1)); + } + else mvwprintw(win, (current_row * 2) - 5, 45, "selected"); + row_c++; + current_row++; + } + + // 打印分页信息 + mvwprintw(win, WIN_HEIGHT - 3, (WIN_WIDTH - 9) / 2, "Page: %d/%d", (offset / PAGE_SIZE) + 1, + max(1,(total_rows + PAGE_SIZE - 1) / PAGE_SIZE)); + draw_bottom(win, left); + draw_bottom(win, right); + draw_bottom(win, ok); + draw_bottom(win, search); + // 刷新窗口 + wrefresh(win); + + sqlite3_finalize(stmt); + return id; +} + +// 插入节点到链表末尾 + + + +void create_ui(){ + MEVENT event; + char *errmsg[30]; + memset(errmsg, 0, 30); + int start_y = (LINES - WIN_HEIGHT) / 2; + int start_x = (COLS - WIN_WIDTH) / 2; + WINDOW *create_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); + keypad(create_win, TRUE); + + box(create_win,0,0); + mvwprintw(create_win,1,1,"Please input your test name:"); + char testname[300]; + get_input_ez(create_win,1,28,testname,300); + wclear(create_win); + int offset = 0; + sqlite3 *db; + const char *db_filename = "./data/msg.db"; // SQLite 数据库文件名 + // 打开数据库 + if (sqlite3_open(db_filename, &db) != SQLITE_OK) { + return; + } + const char *sql_query; // 查询 SQL + int rc; + + sql_query="select * from tests where test_name=?"; + sqlite3_stmt *sqlsearch; + rc = sqlite3_prepare_v2(db, sql_query, -1, &sqlsearch, 0); + if (rc != SQLITE_OK) { + strcpy(errmsg,"Error:database error."); + sqlite3_close(db); + return; + } + sqlite3_bind_text(sqlsearch, 1, testname, -1, SQLITE_STATIC); + + rc = sqlite3_step(sqlsearch); + + if(rc==SQLITE_ROW){ + wclear(create_win); + mvwprintw(create_win,1,1,"Error:test name has been existed"); + sqlite3_sleep(1000); + sqlite3_finalize(sqlsearch); + sqlite3_close(db); + delwin(create_win); + return; + } + sqlite3_finalize(sqlsearch); + + struct bottom *left = creat_bottom(create_win, WIN_HEIGHT - 3, 20, 2, 1, "<-"); + struct bottom *right = creat_bottom(create_win, WIN_HEIGHT - 3, 40, 2, 1, "->"); + struct bottom *ok = creat_bottom(create_win, WIN_HEIGHT - 3, 52, 2, 1, "OK"); + struct bottom *search = creat_bottom(create_win, 1, 8, 20, 1, ""); + memset(search->test,0,30); + search->private = 2; + char searchq[100]; + memset(searchq, 0, 100); + int *id; + sqlite3_stmt *stmt; + int row_count = 0; + Node *head = NULL; // 初始化链表为空 + while (1) { + // 清空窗口内容 + werase(create_win); + box(create_win, 0, 0); + // 调用函数输出当前的滚动窗口内容 + id=display_t_problem_page_2(create_win, db, offset, left, right, ok, search,&row_count,head); + int rc = wgetch(create_win); + if (rc == KEY_MOUSE) { + if (nc_getmouse(&event) == OK) { + if (click_bottom(event, *left, start_x, start_y)) { + if (offset >= PAGE_SIZE) { + offset -= PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *right, start_x, start_y)) { + if (offset + PAGE_SIZE < row_count) { // 总共有100条数据可以调整 + offset += PAGE_SIZE; + } + continue; + } + if (click_bottom(event, *ok, start_x, start_y)) { + sql_query="insert into tests (test_name,Creater) values (?,?)"; + sqlite3_stmt *insert; + rc = sqlite3_prepare_v2(db, sql_query, -1, &insert, 0); + if (rc != SQLITE_OK) { + wclear(create_win); + mvwprintw(create_win,1,1,"Error:data base error."); + sqlite3_finalize(insert); + sqlite3_close(db); + delwin(create_win); + return; + } + sqlite3_bind_text(insert, 1, testname, -1, SQLITE_STATIC); + + sqlite3_bind_text(insert, 2, Username, -1, SQLITE_STATIC); + + rc = sqlite3_step(insert); + if (rc != SQLITE_DONE) { + wclear(create_win); + sqlite3_finalize(insert); + sqlite3_close(db);return; + } + sql_query="select ID from tests where test_name=?"; + rc = sqlite3_prepare_v2(db, sql_query, -1, &insert, 0); + if (rc != SQLITE_OK) { + wclear(create_win); + sqlite3_finalize(insert); + sqlite3_close(db);return; + } + sqlite3_bind_text(insert, 1, testname, -1, SQLITE_STATIC); + + rc = sqlite3_step(insert); + + if(rc!=SQLITE_ROW){ + free_list(head); + free(left); + free(right); + free(ok); + free(id); + sqlite3_finalize(insert); + sqlite3_close(db); + delwin(create_win); + return; + } + int test_id = sqlite3_column_int(insert,0); + sql_query="insert into test_include (text,answer,test_index) values(?,?,?);"; + Node *temp = head; + int problem_counts=0; + while (temp != NULL) { + problem_counts++; + sqlite3_stmt *insert; + rc = sqlite3_prepare_v2(db, sql_query, -1, &insert, 0); + if (rc != SQLITE_OK) { + wclear(create_win); + sqlite3_finalize(insert); + sqlite3_close(db);return; + } + sqlite3_bind_text(insert, 1, temp->str1, -1, SQLITE_STATIC); + sqlite3_bind_text(insert, 2, temp->str2, -1, SQLITE_STATIC); + sqlite3_bind_int(insert, 3, test_id); + rc = sqlite3_step(insert); + if(rc!=SQLITE_DONE){ + wclear(create_win); + sqlite3_finalize(insert); + sqlite3_close(db);return; + } + temp = temp->next; + } + sql_query="update tests set problems_count =? where ID=?"; + rc = sqlite3_prepare_v2(db, sql_query, -1, &insert, 0); + if (rc != SQLITE_OK) { + wclear(create_win); + sqlite3_finalize(insert); + sqlite3_close(db);return; + } + sqlite3_bind_int(insert, 1, problem_counts); + sqlite3_bind_int(insert, 2, test_id); + rc = sqlite3_step(insert); + if(rc!=SQLITE_DONE){ + wclear(create_win); + sqlite3_finalize(insert); + sqlite3_close(db);return; + } + sqlite3_finalize(insert); + free_list(head); + free(left); + free(right); + free(ok); + free(id); + sqlite3_close(db); + delwin(create_win); + return; + } + if (click_bottom(event, *search, start_x, start_y)) { + get_input(create_win, 4, 6, searchq, 15, search, start_x, start_y); + offset=0; + continue; + } + if (event.x-start_x >= 45 && event.x-start_x <= 50) { //select + sql_query="select text,answer from timu where ID =?"; + rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, 0); + if (rc != SQLITE_OK) { + sqlite3_finalize(stmt); + continue; + } + sqlite3_bind_int(stmt, 1, *(id+(((event.y-start_y)+5)/2-5))); + rc = sqlite3_step(stmt); + if (rc != SQLITE_ROW) { + sqlite3_finalize(stmt); + continue; + } + char *text1 = sqlite3_column_text(stmt, 0); + char *answer1 = sqlite3_column_text(stmt,1); + if(list_search(head,*(id+(((event.y-start_y)+5)/2-5))))continue; + insert_node(&head,text1,answer1,*(id+(((event.y-start_y)+5)/2-5))); + continue; + } + } + } + } +} +