Files
BH-Bookstore-2023/backend/src/database.cpp
2023-12-14 04:44:37 +00:00

279 lines
8.4 KiB
C++

#include "database.h"
#include "bs-utility.h"
#include "lexer.h"
void UserDataBase::Open(std::string file_name) {
full_user_data.OpenFile(file_name + ".full");
user_name2index.OpenFile(file_name + ".n2i");
}
void BookDataBase::Open(std::string file_name) {
full_book_data.OpenFile(file_name + ".full");
ISBN2index.OpenFile(file_name + ".isbn");
name2index.OpenFile(file_name + ".name");
author2index.OpenFile(file_name + ".author");
keyword2index.OpenFile(file_name + ".keyword");
}
void LogDataBase::Open(std::string file_name) {
finance_data.OpenFile(file_name + ".finance");
finance_data.get_info(finance_operation_count, 1);
operation_log_data.OpenFile(file_name + ".log");
}
bool UserDataBase::PAM(const std::string &user_id,
const std::string &password) {
// debugPrint("PAM ", user_id, " ", password);
auto ret = user_name2index.Find(user_id);
if (ret.size() != 1) return false;
UserItemClass tmp;
full_user_data.read(tmp, ret[0]);
// debugPrint("Correct password: ", tmp.password, " Input password: ",
// password);
return tmp.password == password;
}
int UserDataBase::GetPrevilege(const std::string &user_id) {
auto ret = user_name2index.Find(user_id);
// debugPrint("size=", ret.size());
if (ret.size() != 1) return -1;
UserItemClass tmp;
full_user_data.read(tmp, ret[0]);
return tmp.privilege;
}
void UserDataBase::AddUser(const std::string &user_id,
const std::string &password,
const std::string &user_name, int privilege) {
UserItemClass tmp;
strcpy(tmp.user_id, user_id.c_str());
strcpy(tmp.password, password.c_str());
strcpy(tmp.user_name, user_name.c_str());
tmp.privilege = privilege;
int idx = full_user_data.write(tmp);
user_name2index.Insert(user_id, idx);
// debugPrint("Add user: ", user_id, " ", password, " ", user_name, " ",
// privilege);
// debugPrint("idx: ", idx);
}
void UserDataBase::DeleteUser(const std::string &user_id) {
auto ret = user_name2index.Find(user_id);
if (ret.size() != 1) return;
full_user_data.Delete(ret[0]);
user_name2index.Delete(user_id, ret[0]);
}
void UserDataBase::ChangePassword(const std::string &user_id,
const std::string &password) {
auto ret = user_name2index.Find(user_id);
if (ret.size() != 1) return;
UserItemClass tmp;
full_user_data.read(tmp, ret[0]);
strcpy(tmp.password, password.c_str());
full_user_data.update(tmp, ret[0]);
}
bool BookDataBase::HaveISBN(const std::string &ISBN) {
auto ret = ISBN2index.Find(ISBN);
return ret.size() == 1;
}
bool BookDataBase::HaveISBN(const std::string &ISBN, BookItemClass &ans) {
auto ret = ISBN2index.Find(ISBN);
if (ret.size() == 1) {
full_book_data.read(ans, ret[0]);
return true;
}
return false;
}
void BookDataBase::CreateEmptyBook(const std::string &ISBN) {
BookItemClass tmp;
strcpy(tmp.ISBN, ISBN.c_str());
tmp.quantity_remain = tmp.price = 0;
tmp.name[0] = 0;
tmp.author[0] = 0;
tmp.keyword[0] = 0;
int idx = full_book_data.write(tmp);
tmp.bid = idx;
// debugPrint("CreateEmptyBook: ", ISBN, " ", idx);
full_book_data.update(tmp, idx);
ISBN2index.Insert(ISBN, idx);
name2index.Insert("", idx);
author2index.Insert("", idx);
keyword2index.Insert("", idx);
}
void BookDataBase::ModifyInfo(const std::string &ISBN,
const std::string &new_ISBN,
const std::string &name,
const std::string &author,
const std::string &keyword, double price,
int quantity_remain) {
auto ret = ISBN2index.Find(ISBN);
if (ret.size() != 1) return;
BookItemClass tmp;
full_book_data.read(tmp, ret[0]);
if (new_ISBN != "") {
ISBN2index.Delete(ISBN, ret[0]);
ISBN2index.Insert(new_ISBN, ret[0]);
strcpy(tmp.ISBN, new_ISBN.c_str());
}
if (name != "") {
name2index.Delete(tmp.name, ret[0]);
name2index.Insert(name, ret[0]);
strcpy(tmp.name, name.c_str());
}
if (author != "") {
author2index.Delete(tmp.author, ret[0]);
author2index.Insert(author, ret[0]);
strcpy(tmp.author, author.c_str());
}
if (keyword != "") {
std::vector<std::string> keyword_vec;
KeyWordSpliter(tmp.keyword, keyword_vec, true);
for (auto &i : keyword_vec) {
keyword2index.Delete(i, ret[0]);
}
KeyWordSpliter(keyword, keyword_vec);
for (auto &i : keyword_vec) {
keyword2index.Insert(i, ret[0]);
}
strcpy(tmp.keyword, keyword.c_str());
}
if (price >= 0) tmp.price = price;
if (quantity_remain >= 0) tmp.quantity_remain = quantity_remain;
full_book_data.update(tmp, ret[0]);
}
void BookDataBase::QueryBook(const std::string &ISBN, const std::string &name,
const std::string &author,
const std::string &keyword,
std::vector<BookItemClass> &ret) {
ret.clear();
std::vector<BookItemClass> cache;
std::vector<unsigned char> valid;
if (ISBN == "" && name == "" && author == "" && keyword == "") {
full_book_data.FetchAll(ret);
/* sort by ISBN */
sort(ret.begin(), ret.end(),
[](const BookItemClass &a, const BookItemClass &b) {
return strcmp(a.ISBN, b.ISBN) < 0;
});
return;
}
bool first_ristrict = true;
if (ISBN != "") {
first_ristrict = false;
auto tmp = ISBN2index.Find(ISBN);
if (tmp.size() == 1) {
BookItemClass tmp_book;
full_book_data.read(tmp_book, tmp[0]);
cache.push_back(tmp_book);
valid.push_back(1);
}
if (tmp.size() > 1) throw FatalError("ISBN not unique", 7);
}
if (name != "") {
if (first_ristrict) {
first_ristrict = false;
auto tmp = name2index.Find(name);
for (auto &i : tmp) {
BookItemClass tmp_book;
full_book_data.read(tmp_book, i);
cache.push_back(tmp_book);
valid.push_back(1);
}
} else {
for (int i = 0; i < cache.size(); i++) {
if (!valid[i]) continue;
if (strcmp(cache[i].name, name.c_str()) != 0) {
valid[i] = 0;
}
}
}
}
if (author != "") {
if (first_ristrict) {
first_ristrict = false;
auto tmp = author2index.Find(author);
for (auto &i : tmp) {
BookItemClass tmp_book;
full_book_data.read(tmp_book, i);
cache.push_back(tmp_book);
valid.push_back(1);
}
} else {
for (int i = 0; i < cache.size(); i++) {
if (!valid[i]) continue;
if (strcmp(cache[i].author, author.c_str()) != 0) {
valid[i] = 0;
}
}
}
}
if (keyword != "") {
if (first_ristrict) {
first_ristrict = false;
auto tmp = keyword2index.Find(keyword);
for (auto &j : tmp) {
BookItemClass tmp_book;
full_book_data.read(tmp_book, j);
cache.push_back(tmp_book);
valid.push_back(1);
}
} else {
for (int i = 0; i < cache.size(); i++) {
if (!valid[i]) continue;
if (strcmp(cache[i].keyword, keyword.c_str()) != 0) {
valid[i] = 0;
}
}
}
}
for (int i = 0; i < cache.size(); i++) {
if (valid[i]) ret.push_back(cache[i]);
}
sort(ret.begin(), ret.end(),
[](const BookItemClass &a, const BookItemClass &b) {
return strcmp(a.ISBN, b.ISBN) < 0;
});
}
void LogDataBase::AddImport(int book_id, int quantity, double total_price) {
FinanceItemClass tmp;
tmp.book_id = book_id;
tmp.quantity = quantity;
tmp.total_price = -total_price;
finance_data.write(tmp);
finance_operation_count++;
}
void LogDataBase::AddSell(int book_id, int quantity, double total_price) {
FinanceItemClass tmp;
tmp.book_id = book_id;
tmp.quantity = quantity;
tmp.total_price = total_price;
finance_data.write(tmp);
finance_operation_count++;
}
std::pair<double, double> LogDataBase::QueryFinance(int count) {
double total_sell = 0, total_import = 0;
if (count == -1) count = finance_operation_count;
for (int i = 1; i <= count; i++) {
FinanceItemClass tmp;
finance_data.read(tmp, finance_operation_count + 1 - i);
if (tmp.total_price > 0)
total_sell += tmp.total_price;
else
total_import -= tmp.total_price;
}
return std::make_pair(total_sell, total_import);
}
std::string BookDataBase::GetISBN(int bid) {
BookItemClass tmp;
full_book_data.read(tmp, bid);
return std::string(tmp.ISBN);
}