upd: first version of booksystem
This commit is contained in:
@ -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,
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
});
|
||||
}
|
@ -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>();
|
||||
}
|
||||
|
||||
|
@ -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] == '|') {
|
||||
|
Reference in New Issue
Block a user