// // Created by zhang on 2024/12/28. // #include #include #include #include #include #include "./include/function.h" #include "./include/curses.h" #include "./include/ui.h" #include "./include/extern.h" #include "./include/sqlite3.h" // 定义窗口宽度和高度 #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]; 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); } struct bottom *creat_bottom(WINDOW *win, int x, int y, int width, int height, char *test[]) { struct bottom *bot = malloc(sizeof(struct bottom)); bot->y = x; bot->x = y; bot->width = width; bot->height = height; strcpy(bot->test, test); //mvwprintw(win,x,y,"%s",test); return bot; } bool click_bottom(MEVENT event, struct bottom bottom, int sx, int sy) { return event.x - sx >= bottom.x && event.x - sx < bottom.x + bottom.width && event.y - sy >= bottom.y && event.y - sy < bottom.y + bottom.height; } int Welcome_ui() { MEVENT event; int startx, starty; initscr(); // 初始化curses cbreak(); // 禁用行缓冲 noecho(); // 不显示输入字符 curs_set(0); // 隐藏光标 keypad(stdscr, TRUE); // 启用键盘按键的特殊处理 mousemask(ALL_MOUSE_EVENTS, NULL); // 启用鼠标事件 timeout(100); // 设置输入超时,防止程序卡死 // 获取屏幕的尺寸 // 计算按钮的显示位置 int start_y = (LINES - WIN_HEIGHT) / 2; int start_x = (COLS - WIN_WIDTH) / 2; WINDOW *welcome_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); keypad(welcome_win, TRUE); wborder(welcome_win, '|', '|', '-', '-', '+', '+', '+', '+'); // 标题 mvwprintw(welcome_win, 1, 1, "Welcome to math calculate system!"); struct bottom *login = creat_bottom(welcome_win, 4, 1, 5, 1, "Login"); draw_bottom(welcome_win, login); struct bottom *signin = creat_bottom(welcome_win, 8, 1, 6, 1, "Signin"); draw_bottom(welcome_win, signin); struct bottom *exit = creat_bottom(welcome_win, 12, 1, 4, 1, "Exit"); draw_bottom(welcome_win, exit); wrefresh(welcome_win); while (1) { int rc = wgetch(welcome_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 (click_bottom(event, *login, start_x, start_y)) { free(login); free(signin); free(exit); endwin(); return 2; } if (click_bottom(event, *signin, start_x, start_y)) { free(login); free(signin); free(exit); endwin(); return 3; } if (click_bottom(event, *exit, start_x, start_y)) { free(login); free(signin); free(exit); endwin(); return 0; } } } } } void draw_login_window(WINDOW *win, struct bottom *login, struct bottom *signin, struct bottom *user, struct bottom *psword, struct bottom *exit) { // 清空窗口并绘制边框 wclear(win); box(win, 0, 0); // 标题 mvwprintw(win, 1, (WIN_WIDTH - 10) / 2, "Login Menu"); // 用户名输入框 mvwprintw(win, 3, 4, "Username:"); // 密码输入框 mvwprintw(win, 6, 4, "Password:"); //绘制剩余内容 draw_bottom(win, login); draw_bottom(win, signin); draw_bottom(win, exit); draw_bottom(win, user); draw_bottom(win, psword); 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) { // 清空窗口并绘制边框 wclear(win); box(win, 0, 0); // 标题 mvwprintw(win, 1, (WIN_WIDTH - 10) / 2, "Signin"); // 用户名输入框 mvwprintw(win, 3, 4, "Username:"); // 密码输入框 mvwprintw(win, 6, 4, "Password:"); //绘制剩余内容 draw_bottom(win, signin); draw_bottom(win, exit); draw_bottom(win, user); draw_bottom(win, psword); 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; char *test = bot->test; while (pos < max_len && buffer[pos] != '\0')pos++; while (1) { ch = wgetch(win); if (ch == KEY_BACKSPACE || ch == 8) { // 处理退格键 if (pos > 0) { pos--; buffer[pos] = '\0'; if(bot->private!=2)test[pos + 1] = '_'; else test[pos]='\0'; mvwprintw(win,1,8," "); 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]; memset(errmsg, 0, 30); int start_y = (LINES - WIN_HEIGHT) / 2; int start_x = (COLS - WIN_WIDTH) / 2; WINDOW *login_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); keypad(login_win, TRUE); char *username[15]; //储存用户名 memset(username, '\0', 15); // 清空缓冲区 char *password[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"); struct bottom *users = creat_bottom(login_win, 4, 4, 16, 1, "[______________]"); struct bottom *psword = creat_bottom(login_win, 7, 4, 16, 1, "[______________]"); psword->private = 1; users->private = 0; int willdraw = 1; while (1) { if (willdraw)draw_login_window(login_win, login, signin, users, psword, exit); int rc = wgetch(login_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, *login, start_x, start_y)) { int recall; Login(username, password, &recall, errmsg); if (recall == -1) { wclear(login_win); mvwprintw(login_win, 5, 5, "%s", errmsg); exit->x = 5; exit->y = 8; draw_bottom(login_win, exit); wrefresh(login_win); willdraw = 0; continue; } else { free(login); free(signin); free(exit); free(users); free(psword); endwin(); return recall; } } if (willdraw) if (click_bottom(event, *signin, start_x, start_y)) { free(login); free(signin); free(exit); free(users); free(psword); endwin(); return SIGNIN_UI; } if (click_bottom(event, *exit, start_x, start_y)) { free(login); free(signin); free(exit); free(users); free(psword); endwin(); return willdraw == 1 ? WELCOME_UI : LOGIN_UI; } if (willdraw) if (click_bottom(event, *users, start_x, start_y)) { get_input(login_win, 4, 6, username, 15, users, start_x, start_y); continue; } if (willdraw) if (click_bottom(event, *psword, start_x, start_y)) { get_input(login_win, 7, 6, password, 15, psword, start_x, start_y); continue; } } } } } int Signin_ui() { MEVENT event; char *errmsg[100]; memset(errmsg, 0, 30); int start_y = (LINES - WIN_HEIGHT) / 2; int start_x = (COLS - WIN_WIDTH) / 2; WINDOW *signin_win = newwin(WIN_HEIGHT, WIN_WIDTH, start_y, start_x); keypad(signin_win, TRUE); char *username[15]; //储存用户名 memset(username, '\0', 15); // 清空缓冲区 char *password[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, "[______________]"); struct bottom *psword = creat_bottom(signin_win, 7, 4, 16, 1, "[______________]"); psword->private = 0; users->private = 0; int willdraw = 1; while (1) { 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 == 1) if (click_bottom(event, *signin, start_x, start_y)) { int recall; Signin(username, password, &recall, errmsg); if (recall != 0) { wclear(signin_win); mvwprintw(signin_win, 5, 5, "%s", errmsg); exit->x = 5; exit->y = 8; draw_bottom(signin_win, exit); wrefresh(signin_win); willdraw = 2; continue; } else { wclear(signin_win); mvwprintw(signin_win, 5, 5, "Accepted"); exit->x = 5; exit->y = 8; draw_bottom(signin_win, exit); wrefresh(signin_win); willdraw = 0; continue; } } if (click_bottom(event, *exit, start_x, start_y)) { free(signin); free(exit); free(users); free(psword); endwin(); return willdraw == 2 ? SIGNIN_UI : WELCOME_UI; } 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 == 1) if (click_bottom(event, *psword, start_x, start_y)) { get_input(signin_win, 7, 6, password, 15, psword, start_x, start_y); continue; } } } } } 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; } } } } }