upd: first version of booksystem
This commit is contained in:
@ -28,6 +28,7 @@ class BookDataBase {
|
|||||||
public:
|
public:
|
||||||
void Open(std::string file_name);
|
void Open(std::string file_name);
|
||||||
bool HaveISBN(const std::string &ISBN);
|
bool HaveISBN(const std::string &ISBN);
|
||||||
|
bool HaveISBN(const std::string &ISBN,BookItemClass &ret);
|
||||||
void CreateEmptyBook(const std::string &ISBN);
|
void CreateEmptyBook(const std::string &ISBN);
|
||||||
void QueryBook(const std::string &ISBN, const std::string &name,
|
void QueryBook(const std::string &ISBN, const std::string &name,
|
||||||
const std::string &author, const std::string &keyword,
|
const std::string &author, const std::string &keyword,
|
||||||
|
@ -226,6 +226,18 @@ class DriveArray {
|
|||||||
first_vacant_data_index;
|
first_vacant_data_index;
|
||||||
first_vacant_data_index = 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
|
#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,
|
bool CommandImportLexer(const std::string &command, int &quantity,
|
||||||
double &total_cost);
|
double &total_cost);
|
||||||
bool CommandShowfinanceLexer(const std::string &command,int &count);
|
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
|
#endif // PROTECTOR_LEXER_H
|
@ -1,6 +1,7 @@
|
|||||||
#include "database.h"
|
#include "database.h"
|
||||||
|
|
||||||
#include "bs-utility.h"
|
#include "bs-utility.h"
|
||||||
|
#include "lexer.h"
|
||||||
void UserDataBase::Open(std::string file_name) {
|
void UserDataBase::Open(std::string file_name) {
|
||||||
full_user_data.OpenFile(file_name + ".full");
|
full_user_data.OpenFile(file_name + ".full");
|
||||||
user_name2index.OpenFile(file_name + ".n2i");
|
user_name2index.OpenFile(file_name + ".n2i");
|
||||||
@ -76,6 +77,14 @@ bool BookDataBase::HaveISBN(const std::string &ISBN) {
|
|||||||
auto ret = ISBN2index.Find(ISBN);
|
auto ret = ISBN2index.Find(ISBN);
|
||||||
return ret.size() == 1;
|
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) {
|
void BookDataBase::CreateEmptyBook(const std::string &ISBN) {
|
||||||
BookItemClass tmp;
|
BookItemClass tmp;
|
||||||
@ -117,8 +126,15 @@ void BookDataBase::ModifyInfo(const std::string &ISBN,
|
|||||||
strcpy(tmp.author, author.c_str());
|
strcpy(tmp.author, author.c_str());
|
||||||
}
|
}
|
||||||
if (keyword != "") {
|
if (keyword != "") {
|
||||||
keyword2index.Delete(tmp.keyword, ret[0]);
|
std::vector<std::string> keyword_vec;
|
||||||
keyword2index.Insert(keyword, ret[0]);
|
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());
|
strcpy(tmp.keyword, keyword.c_str());
|
||||||
}
|
}
|
||||||
if (price >= 0) tmp.price = price;
|
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,
|
const std::string &keyword,
|
||||||
std::vector<BookItemClass> &ret) {
|
std::vector<BookItemClass> &ret) {
|
||||||
ret.clear();
|
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 <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "bs-utility.h"
|
#include "bs-utility.h"
|
||||||
|
|
||||||
@ -135,6 +136,9 @@ std::vector<std::string> BookStoreEngineClass::ExecuteLogout(
|
|||||||
const std::string &cmd,
|
const std::string &cmd,
|
||||||
std::stack<std::pair<std::string, std::string>> &login_stack) {
|
std::stack<std::pair<std::string, std::string>> &login_stack) {
|
||||||
if (login_stack.empty()) return std::vector<std::string>({"Invalid"});
|
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_count[login_stack.top().first]--;
|
||||||
login_stack.pop();
|
login_stack.pop();
|
||||||
return std::vector<std::string>();
|
return std::vector<std::string>();
|
||||||
@ -159,7 +163,7 @@ std::vector<std::string> BookStoreEngineClass::ExecutePasswd(
|
|||||||
if (!CommandPasswdLexer(cmd, user_id, current_password, new_password))
|
if (!CommandPasswdLexer(cmd, user_id, current_password, new_password))
|
||||||
return std::vector<std::string>({"Invalid"});
|
return std::vector<std::string>({"Invalid"});
|
||||||
// debugPrint("sucessfully lexed passwd");
|
// 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"});
|
return std::vector<std::string>({"Invalid"});
|
||||||
// debugPrint("begin checing authority");
|
// debugPrint("begin checing authority");
|
||||||
if (login_stack.size() > 0 &&
|
if (login_stack.size() > 0 &&
|
||||||
@ -215,30 +219,126 @@ std::vector<std::string> BookStoreEngineClass::ExecuteDelete(
|
|||||||
std::vector<std::string> BookStoreEngineClass::ExecuteShow(
|
std::vector<std::string> BookStoreEngineClass::ExecuteShow(
|
||||||
const std::string &cmd,
|
const std::string &cmd,
|
||||||
std::stack<std::pair<std::string, std::string>> &login_stack) {
|
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(
|
std::vector<std::string> BookStoreEngineClass::ExecuteBuy(
|
||||||
const std::string &cmd,
|
const std::string &cmd,
|
||||||
std::stack<std::pair<std::string, std::string>> &login_stack) {
|
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(
|
std::vector<std::string> BookStoreEngineClass::ExecuteSelect(
|
||||||
const std::string &cmd,
|
const std::string &cmd,
|
||||||
std::stack<std::pair<std::string, std::string>> &login_stack) {
|
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>();
|
return std::vector<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> BookStoreEngineClass::ExecuteMOdify(
|
std::vector<std::string> BookStoreEngineClass::ExecuteMOdify(
|
||||||
const std::string &cmd,
|
const std::string &cmd,
|
||||||
std::stack<std::pair<std::string, std::string>> &login_stack) {
|
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>();
|
return std::vector<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> BookStoreEngineClass::ExecuteImport(
|
std::vector<std::string> BookStoreEngineClass::ExecuteImport(
|
||||||
const std::string &cmd,
|
const std::string &cmd,
|
||||||
std::stack<std::pair<std::string, std::string>> &login_stack) {
|
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>();
|
return std::vector<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +346,7 @@ bool CommandModifyLexer(const std::string &command, std::string &ISBN,
|
|||||||
name = "";
|
name = "";
|
||||||
author = "";
|
author = "";
|
||||||
keyword = "";
|
keyword = "";
|
||||||
price = 0;
|
price = -1;
|
||||||
while (ss >> token) {
|
while (ss >> token) {
|
||||||
if (token[1] == 'I') {
|
if (token[1] == 'I') {
|
||||||
ISBN = token.substr(6);
|
ISBN = token.substr(6);
|
||||||
@ -431,7 +431,13 @@ bool CommandShowfinanceLexer(const std::string &command, int &count) {
|
|||||||
return false;
|
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;
|
int current_beg = 0;
|
||||||
for (int i = 0; i < keyword.length(); i++) {
|
for (int i = 0; i < keyword.length(); i++) {
|
||||||
if (keyword[i] == '|') {
|
if (keyword[i] == '|') {
|
||||||
|
Reference in New Issue
Block a user