math/ui.c

1947 lines
71 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by zhang on 2024/12/28.
//
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <windows.h>
#include <math.h>
#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;
}
}
}
}
}