upd: first version of booksystem

This commit is contained in:
2023-12-14 03:01:37 +00:00
parent db4830d7d9
commit 7ca2b28548
6 changed files with 230 additions and 9 deletions

View File

@ -28,6 +28,7 @@ class BookDataBase {
public:
void Open(std::string file_name);
bool HaveISBN(const std::string &ISBN);
bool HaveISBN(const std::string &ISBN,BookItemClass &ret);
void CreateEmptyBook(const std::string &ISBN);
void QueryBook(const std::string &ISBN, const std::string &name,
const std::string &author, const std::string &keyword,

View File

@ -226,6 +226,18 @@ class DriveArray {
first_vacant_data_index;
first_vacant_data_index = index;
}
void FetchAll(std::vector<T> &vec) noexcept {
vec.clear();
for (int i = 1; i <= total_block_number; ++i) {
BlockType *blk_ptr = OrderBlock(i);
for (int j = 0; j < kDataPerBlock; ++j) {
if (blk_ptr->data[j].next_vacant_data_index == -1) {
vec.push_back(blk_ptr->data[j].val);
}
}
}
}
};
#endif // PROTECTOR_DRIVEARRAY_HPP

View File

@ -27,5 +27,5 @@ bool CommandModifyLexer(const std::string &command, std::string &ISBN,
bool CommandImportLexer(const std::string &command, int &quantity,
double &total_cost);
bool CommandShowfinanceLexer(const std::string &command,int &count);
bool KeyWordSpliter(const std::string &keyword, std::vector<std::string> &words);
bool KeyWordSpliter(const std::string &keyword, std::vector<std::string> &words,bool allow_empty=false);
#endif // PROTECTOR_LEXER_H

View File

@ -1,6 +1,7 @@
#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");
@ -76,6 +77,14 @@ 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;
@ -117,8 +126,15 @@ void BookDataBase::ModifyInfo(const std::string &ISBN,
strcpy(tmp.author, author.c_str());
}
if (keyword != "") {
keyword2index.Delete(tmp.keyword, ret[0]);
keyword2index.Insert(keyword, ret[0]);
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;
@ -131,5 +147,91 @@ void BookDataBase::QueryBook(const std::string &ISBN, const std::string &name,
const std::string &keyword,
std::vector<BookItemClass> &ret) {
ret.clear();
if (ISBN == "" && name == "" && author == "" && keyword == "") return;
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;
});
}

View File

@ -4,6 +4,7 @@
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include "bs-utility.h"
@ -135,6 +136,9 @@ std::vector<std::string> BookStoreEngineClass::ExecuteLogout(
const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack) {
if (login_stack.empty()) return std::vector<std::string>({"Invalid"});
if (user_data_base.GetPrevilege(login_stack.top().first) < 1) {
return std::vector<std::string>({"Invalid"});
}
login_count[login_stack.top().first]--;
login_stack.pop();
return std::vector<std::string>();
@ -159,7 +163,7 @@ std::vector<std::string> BookStoreEngineClass::ExecutePasswd(
if (!CommandPasswdLexer(cmd, user_id, current_password, new_password))
return std::vector<std::string>({"Invalid"});
// debugPrint("sucessfully lexed passwd");
if (user_data_base.GetPrevilege(user_id) == -1)
if (user_data_base.GetPrevilege(user_id) < 1)
return std::vector<std::string>({"Invalid"});
// debugPrint("begin checing authority");
if (login_stack.size() > 0 &&
@ -215,30 +219,126 @@ std::vector<std::string> BookStoreEngineClass::ExecuteDelete(
std::vector<std::string> BookStoreEngineClass::ExecuteShow(
const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
if (login_stack.empty() ||
user_data_base.GetPrevilege(login_stack.top().first) < 1)
return std::vector<std::string>({"Invalid"});
std::string ISBN, name, author, keyword;
if (!CommandShowLexer(cmd, ISBN, name, author, keyword))
return std::vector<std::string>({"Invalid"});
std::vector<BookItemClass> ret;
book_data_base.QueryBook(ISBN, name, author, keyword, ret);
if (ret.empty()) return std::vector<std::string>({""});
/* output format
* [ISBN]\t[BookName]\t[Author]\t[Keyword]\t[Price]\t[库存数量]\n */
std::vector<std::string> ans;
for (auto &i : ret) {
std::string tmp = i.ISBN;
tmp += '\t';
tmp += i.name;
tmp += '\t';
tmp += i.author;
tmp += '\t';
tmp += i.keyword;
tmp += '\t';
tmp += std::to_string(i.price);
tmp += '\t';
tmp += std::to_string(i.quantity_remain);
ans.push_back(tmp);
}
return ans;
}
std::vector<std::string> BookStoreEngineClass::ExecuteBuy(
const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
std::string ISBN;
int quantity;
if (!CommandBuyLexer(cmd, ISBN, quantity))
return std::vector<std::string>({"Invalid"});
if (login_stack.empty() ||
user_data_base.GetPrevilege(login_stack.top().first) < 1)
return std::vector<std::string>({"Invalid"});
BookItemClass tmp;
if (!book_data_base.HaveISBN(ISBN, tmp))
return std::vector<std::string>({"Invalid"});
if (quantity <= 0) return std::vector<std::string>({"Invalid"});
if (quantity > tmp.quantity_remain)
return std::vector<std::string>({"Invalid"});
book_data_base.ModifyInfo(ISBN, "", "", "", "", -1,
tmp.quantity_remain - quantity);
/*浮点数输出购买图书所需的总金额,小数点后有且仅有两位小数*/
std::vector<std::string> ans;
unsigned long long cost_tmp = tmp.price * quantity * 100 + 0.5;
ans.push_back(std::to_string(cost_tmp / 100) + '.' +
std::to_string(cost_tmp % 100 / 10) +
std::to_string(cost_tmp % 10));
return ans;
}
std::vector<std::string> BookStoreEngineClass::ExecuteSelect(
const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack) {
std::string ISBN;
if (!CommandSelectLexer(cmd, ISBN))
return std::vector<std::string>({"Invalid"});
if (login_stack.empty() ||
user_data_base.GetPrevilege(login_stack.top().first) < 3)
return std::vector<std::string>({"Invalid"});
if (!book_data_base.HaveISBN(ISBN)) book_data_base.CreateEmptyBook(ISBN);
std::pair<std::string, std::string> tmp;
tmp = login_stack.top();
login_stack.pop();
tmp.second = ISBN;
login_stack.push(tmp);
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteMOdify(
const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack) {
std::string new_ISBN, name, author, keyword;
double price;
if (!CommandModifyLexer(cmd, new_ISBN, name, author, keyword, price))
return std::vector<std::string>({"Invalid"});
if (login_stack.empty() ||
user_data_base.GetPrevilege(login_stack.top().first) < 3)
return std::vector<std::string>({"Invalid"});
if (login_stack.top().second == "" || login_stack.top().second == new_ISBN)
return std::vector<std::string>({"Invalid"});
if (keyword != "") {
std::vector<std::string> key_list;
if (!KeyWordSpliter(keyword, key_list, false))
return std::vector<std::string>({"Invalid"});
std::unordered_set<std::string> key_set;
for (auto &i : key_list) {
if (key_set.find(i) != key_set.end())
return std::vector<std::string>({"Invalid"});
key_set.insert(i);
}
}
book_data_base.ModifyInfo(login_stack.top().second, new_ISBN, name, author,
keyword, price, -1);
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteImport(
const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack) {
int quantity;
double total_cost;
if (!CommandImportLexer(cmd, quantity, total_cost))
return std::vector<std::string>({"Invalid"});
if (login_stack.empty() ||
user_data_base.GetPrevilege(login_stack.top().first) < 3)
return std::vector<std::string>({"Invalid"});
if (login_stack.top().second == "")
return std::vector<std::string>({"Invalid"});
if (quantity <= 0) return std::vector<std::string>({"Invalid"});
if (total_cost <= 0) return std::vector<std::string>({"Invalid"});
BookItemClass tmp;
book_data_base.HaveISBN(login_stack.top().second, tmp);
book_data_base.ModifyInfo(login_stack.top().second, "", "", "", "", -1,
tmp.quantity_remain + quantity);
return std::vector<std::string>();
}

View File

@ -346,7 +346,7 @@ bool CommandModifyLexer(const std::string &command, std::string &ISBN,
name = "";
author = "";
keyword = "";
price = 0;
price = -1;
while (ss >> token) {
if (token[1] == 'I') {
ISBN = token.substr(6);
@ -431,7 +431,13 @@ bool CommandShowfinanceLexer(const std::string &command, int &count) {
return false;
}
bool KeyWordSpliter(const std::string &keyword, std::vector<std::string> &words) {
bool KeyWordSpliter(const std::string &keyword, std::vector<std::string> &words,
bool allow_empty) {
words.clear();
if (keyword == "") {
if (!allow_empty) return false;
return true;
}
int current_beg = 0;
for (int i = 0; i < keyword.length(); i++) {
if (keyword[i] == '|') {