diff options
feat(Week07): Add solutions
17 files changed, 1539 insertions, 0 deletions
| -rw-r--r-- | Week07/Exercise01/BankClerk.cpp | 21 | ||||
| -rw-r--r-- | Week07/Exercise01/BankClerk.h | 23 | ||||
| -rw-r--r-- | Week07/Exercise01/Book.cpp | 96 | ||||
| -rw-r--r-- | Week07/Exercise01/Book.h | 39 | ||||
| -rw-r--r-- | Week07/Exercise01/Librarian.cpp | 21 | ||||
| -rw-r--r-- | Week07/Exercise01/Librarian.h | 23 | ||||
| -rw-r--r-- | Week07/Exercise01/LibraryBanking.cpp | 159 | ||||
| -rw-r--r-- | Week07/Exercise01/LibraryBanking.h | 40 | ||||
| -rw-r--r-- | Week07/Exercise01/OnlineLibrary.cpp | 264 | ||||
| -rw-r--r-- | Week07/Exercise01/OnlineLibrary.h | 65 | ||||
| -rw-r--r-- | Week07/Exercise01/String.cpp | 98 | ||||
| -rw-r--r-- | Week07/Exercise01/String.h | 33 | ||||
| -rw-r--r-- | Week07/Exercise01/Transaction.cpp | 56 | ||||
| -rw-r--r-- | Week07/Exercise01/Transaction.h | 46 | ||||
| -rw-r--r-- | Week07/Exercise01/User.cpp | 128 | ||||
| -rw-r--r-- | Week07/Exercise01/User.h | 45 | ||||
| -rw-r--r-- | Week07/Exercise01/main.cpp | 382 |
diff --git a/Week07/Exercise01/BankClerk.cpp b/Week07/Exercise01/BankClerk.cpp new file mode 100644 index 0000000..697894b --- /dev/null +++ b/Week07/Exercise01/BankClerk.cpp @@ -0,0 +1,21 @@ +#include "BankClerk.h" + +BankClerk::BankClerk(unsigned clerkNumber) { + this->clerkNumber = clerkNumber; + this->staticPassword = "password"; +} + +BankClerk::BankClerk() : clerkNumber(0), staticPassword() +{ } + +unsigned BankClerk::GetClerkNumber() const { + return clerkNumber; +} + +void BankClerk::SetPassword(const String& newPassword) { + staticPassword = newPassword; +} + +bool BankClerk::Login(unsigned clerkNumber, unsigned dynamicPassword, const String& staticPassword) { + return (clerkNumber * dynamicPassword) % 8581 == 0 && this->staticPassword.EqualTo(staticPassword); +} diff --git a/Week07/Exercise01/BankClerk.h b/Week07/Exercise01/BankClerk.h new file mode 100644 index 0000000..5692ef8 --- /dev/null +++ b/Week07/Exercise01/BankClerk.h @@ -0,0 +1,23 @@ +#ifndef _BANKCLERK +#define _BANKCLERK + +#include "String.h" + +class BankClerk { + unsigned clerkNumber; + String staticPassword; + +public: + BankClerk(unsigned clerkNumber); + // Ако направим поне един конструктор, то конструктора по подразбиране + // спира да се създава автоматично + BankClerk(); + + unsigned GetClerkNumber() const; + + void SetPassword(const String& newPassword); + + bool Login(unsigned clerkNumber, unsigned dynamicPassword, const String& staticPassword); +}; + +#endif /* _BANKCLERK */ diff --git a/Week07/Exercise01/Book.cpp b/Week07/Exercise01/Book.cpp new file mode 100644 index 0000000..d48e090 --- /dev/null +++ b/Week07/Exercise01/Book.cpp @@ -0,0 +1,96 @@ +#include "Book.h" +#include <iostream> +#include <fstream> + +void Book::SetTitle(const String& newTitle) { + title = newTitle; +} + +const String& Book::GetTitle() const { + return title; +} + +void Book::SetAuthor(const String& newAuthor) { + author = newAuthor; +} + +const String& Book::GetAuthor() const { + return author; +} + +void Book::SetYear(short newYear) { + year = newYear; +} + +short Book::GetYear() const { + return year; +} + +void Book::SetText(const String& newText) { + text = newText; +} + +const String& Book::GetText() const { + return text; +} + +void Book::SetPrice(double newPrice) { + price = newPrice; +} + +double Book::GetPrice() const { + return price; +} + +void Book::SetAvailableForPurchase(bool isAvailableForPurchase) { + availableForPurchase = isAvailableForPurchase; +} + +bool Book::GetAvailableForPurchase() const { + return availableForPurchase; +} + +void Book::PrintBookInfo() const { + std::cout << GetTitle().GetStr() << ", " + << GetAuthor().GetStr() << ' ' + << GetYear() << std::endl; +} + +bool Book::Export(const String& fileName) { + std::ofstream exportFile(fileName.GetStr(), std::ios::binary); + + if (!exportFile.is_open()) { + std::cout << "Couldn't export book to file!" << std::endl; + } + else { + exportFile.write(title.GetStr(), title.GetLength() + 1); + exportFile.write(author.GetStr(), author.GetLength() + 1); + exportFile.write((const char*)&year, sizeof(year)); + exportFile.write(text.GetStr(), text.GetLength() + 1); + } + + return exportFile.is_open(); +} + +void readNullTerminated(String& readInto, std::ifstream& file) { + readInto.Clear(); + for (char buffer = file.get(); buffer != '\0' && !file.eof(); buffer = file.get()) { + readInto.AppendChar(buffer); + } +} + +bool Book::Import(const String& fileName) { + std::ifstream importFile(fileName.GetStr(), std::ios::binary); + + if (!importFile.is_open()) { + std::cout << "Couldn't import book to file!" << std::endl; + } + else { + readNullTerminated(title, importFile); + readNullTerminated(author, importFile); + importFile.read((char*)&year, sizeof(year)); + readNullTerminated(text, importFile); + } + + return importFile.is_open(); +} diff --git a/Week07/Exercise01/Book.h b/Week07/Exercise01/Book.h new file mode 100644 index 0000000..eaddaea --- /dev/null +++ b/Week07/Exercise01/Book.h @@ -0,0 +1,39 @@ +#ifndef _BOOK +#define _BOOK + +#include "String.h" + +class Book { + String title; + String author; + short year; + String text; + double price; + bool availableForPurchase; + +public: + void SetTitle(const String& newTitle); + const String& GetTitle() const; + + void SetAuthor(const String& newAuthor); + const String& GetAuthor() const; + + void SetYear(short newYear); + short GetYear() const; + + void SetText(const String& newText); + const String& GetText() const; + + void SetPrice(double newPrice); + double GetPrice() const; + + void SetAvailableForPurchase(bool isAvailableForPurchase); + bool GetAvailableForPurchase() const; + + void PrintBookInfo() const; + + bool Export(const String& fileName); + bool Import(const String& fileName); +}; + +#endif /* _BOOK */ diff --git a/Week07/Exercise01/Librarian.cpp b/Week07/Exercise01/Librarian.cpp new file mode 100644 index 0000000..0e6179d --- /dev/null +++ b/Week07/Exercise01/Librarian.cpp @@ -0,0 +1,21 @@ +#include "Librarian.h" + +Librarian::Librarian(unsigned librarianNumber) { + this->librarianNumber = librarianNumber; + this->password = "password"; +} + +Librarian::Librarian() : librarianNumber(0), password() +{ } + +unsigned Librarian::GetLibrarianNumber() const { + return librarianNumber; +} + +void Librarian::SetPassword(const String& newPassword) { + this->password = newPassword; +} + +bool Librarian::Login(unsigned librarianNumber, const String& password) { + return this->librarianNumber == librarianNumber && this->password.EqualTo(password); +} diff --git a/Week07/Exercise01/Librarian.h b/Week07/Exercise01/Librarian.h new file mode 100644 index 0000000..839a258 --- /dev/null +++ b/Week07/Exercise01/Librarian.h @@ -0,0 +1,23 @@ +#ifndef _LIBRARIAN +#define _LIBRARIAN + +#include "String.h" + +class Librarian { + unsigned librarianNumber; + String password; + +public: + Librarian(unsigned librarianNumber); + // Ако направим поне един конструктор, то конструктора по подразбиране + // спира да се създава автоматично + Librarian(); + + unsigned GetLibrarianNumber() const; + + void SetPassword(const String& newPassword); + + bool Login(unsigned librarianNumber, const String& password); +}; + +#endif /* _LIBRARIAN */ diff --git a/Week07/Exercise01/LibraryBanking.cpp b/Week07/Exercise01/LibraryBanking.cpp new file mode 100644 index 0000000..66e0959 --- /dev/null +++ b/Week07/Exercise01/LibraryBanking.cpp @@ -0,0 +1,159 @@ +#include "LibraryBanking.h" +#include "Transaction.h" +#include <fstream> +#include <iostream> + +void LibraryBanking::free() { + delete[] clerks; + delete[] transactions; +} + +void LibraryBanking::copyFrom(const LibraryBanking& other) { + clerksAlloc = other.clerksAlloc; + clerksCount = other.clerksCount; + clerks = new BankClerk[clerksAlloc]; + for (unsigned i = 0; i < clerksCount; ++i) + clerks[i] = other.clerks[i]; + + transactionsAlloc = other.transactionsAlloc; + transactionsCount = other.transactionsCount; + transactions = new Transaction[transactionsAlloc]; + for (unsigned i = 0; i < transactionsCount; ++i) + transactions[i] = other.transactions[i]; +} + +void LibraryBanking::resizeClerks() { + clerksAlloc = clerksAlloc == 0 ? 8 : clerksAlloc * 2; + BankClerk* newClerks = new BankClerk[clerksAlloc]; + + for (unsigned i = 0; i < clerksCount; ++i) + newClerks[i] = clerks[i]; + + delete[] clerks; + clerks = newClerks; +} + +void LibraryBanking::resizeTransactions() { + transactionsAlloc = transactionsAlloc == 0 ? 8 : transactionsAlloc * 2; + Transaction* newTransactions = new Transaction[transactionsAlloc]; + + for (unsigned i = 0; i < transactionsCount; ++i) + newTransactions[i] = transactions[i]; + + delete[] transactions; + transactions = newTransactions; +} + +LibraryBanking::LibraryBanking() : clerks(nullptr), clerksCount(0), clerksAlloc(0), transactions(nullptr), transactionsCount(0), transactionsAlloc(0) +{ } + +LibraryBanking::~LibraryBanking() { + free(); +} + +LibraryBanking::LibraryBanking(const LibraryBanking& other) { + copyFrom(other); +} + +LibraryBanking& LibraryBanking::operator=(const LibraryBanking& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +LibraryBanking::LibraryBanking(LibraryBanking&& other) { + clerks = other.clerks; + clerksCount = other.clerksCount; + clerksAlloc = other.clerksAlloc; + + transactions = other.transactions; + transactionsCount = other.transactionsCount; + transactionsAlloc = other.transactionsAlloc; + + other.clerks = nullptr; + other.clerksCount = other.clerksAlloc = 0; + + other.transactions = nullptr; + other.transactionsCount = other.transactionsAlloc = 0; +} + +LibraryBanking& LibraryBanking::operator=(LibraryBanking&& other) { + if (this != &other) { + free(); + + clerks = other.clerks; + clerksCount = other.clerksCount; + clerksAlloc = other.clerksAlloc; + + transactions = other.transactions; + transactionsCount = other.transactionsCount; + transactionsAlloc = other.transactionsAlloc; + + other.clerks = nullptr; + other.clerksCount = other.clerksAlloc = 0; + + other.transactions = nullptr; + other.transactionsCount = other.transactionsAlloc = 0; + } + return *this; +} + +void LibraryBanking::RegisterClerk(const BankClerk& clerk) { + if (clerksCount >= clerksAlloc) + resizeClerks(); + clerks[clerksCount++] = clerk; +} + +BankClerk* LibraryBanking::LoginClerk(unsigned clerkNumber, unsigned dynamicPassword, const String& staticPassword) { + for (unsigned i = 0; i < clerksCount; ++i) { + if (clerks[i].Login(clerkNumber, dynamicPassword, staticPassword)) + // "clerks + i" е същото като "&clerks[i]" + return clerks + i; + } + return nullptr; +} + +void LibraryBanking::ListPendingTransactions() { + for (unsigned i = 0; i < transactionsCount; ++i) { + if (transactions[i].GetStatus() == STATUS_PENDING) { + std::cout << '[' << i << "] "; + transactions[i].PrintTransactionInfo(); + } + } +} + +Transaction* LibraryBanking::GetTransaction(unsigned index) { + if (index >= transactionsCount) + return nullptr; + // "transactions + index" е същото като "&transactions[index]" + return transactions + index; +} + +const Transaction* LibraryBanking::RegisterTransaction(const Transaction& transaction) { + if (transactionsCount >= transactionsAlloc) + resizeTransactions(); + transactions[transactionsCount] = transaction; + + if (transaction.GetSum() == 0.0) + transactions[transactionsCount].SetStatus(0, STATUS_ACCEPTED); + + return transactions + transactionsCount++; +} + +void LibraryBanking::ExportNonPendingTransactions(const String& fileName) { + std::ofstream exportFile(fileName.GetStr(), std::ios::trunc); + + if (!exportFile.is_open()) { + std::cout << "Couldn't open file!" << std::endl; + } + else { + for (unsigned i = 0; i < transactionsCount; ++i) { + if (transactions[i].GetStatus() != STATUS_PENDING) { + exportFile << i << ","; + transactions[i].Export(exportFile); + } + } + } +} diff --git a/Week07/Exercise01/LibraryBanking.h b/Week07/Exercise01/LibraryBanking.h new file mode 100644 index 0000000..08e9d9d --- /dev/null +++ b/Week07/Exercise01/LibraryBanking.h @@ -0,0 +1,40 @@ +#ifndef _LIBRARY_BANKING +#define _LIBRARY_BANKING + +#include "BankClerk.h" +#include "Transaction.h" + +class LibraryBanking { + BankClerk* clerks; + unsigned clerksCount; + unsigned clerksAlloc; + + Transaction* transactions; + unsigned transactionsCount; + unsigned transactionsAlloc; + + void free(); + void copyFrom(const LibraryBanking& other); + + void resizeClerks(); + void resizeTransactions(); + +public: + LibraryBanking(); + ~LibraryBanking(); + LibraryBanking(const LibraryBanking& other); + LibraryBanking& operator=(const LibraryBanking& other); + LibraryBanking(LibraryBanking&& other); + LibraryBanking& operator=(LibraryBanking&& other); + + void RegisterClerk(const BankClerk& clerk); + BankClerk* LoginClerk(unsigned clerkNumber, unsigned dynamicPassword, const String& staticPassword); + + void ListPendingTransactions(); + Transaction* GetTransaction(unsigned index); + const Transaction* RegisterTransaction(const Transaction& transaction); + + void ExportNonPendingTransactions(const String& fileName); +}; + +#endif /* _LIBRARY_BANKING */ diff --git a/Week07/Exercise01/OnlineLibrary.cpp b/Week07/Exercise01/OnlineLibrary.cpp new file mode 100644 index 0000000..495ee95 --- /dev/null +++ b/Week07/Exercise01/OnlineLibrary.cpp @@ -0,0 +1,264 @@ +#include "OnlineLibrary.h" +#include <iostream> + +void OnlineLibrary::free() { + delete[] books; + delete[] users; + delete[] librarians; + delete[] connections; +} + +void OnlineLibrary::copyFrom(const OnlineLibrary& other) { + booksCount = other.booksCount; + booksAlloc = other.booksAlloc; + books = new Book[booksAlloc]; + for (unsigned i = 0; i < booksCount; ++i) + books[i] = other.books[i]; + + usersCount = other.usersCount; + usersAlloc = other.usersAlloc; + users = new User[usersAlloc]; + for (unsigned i = 0; i < usersCount; ++i) + users[i] = other.users[i]; + + librariansCount = other.librariansCount; + librariansAlloc = other.librariansAlloc; + librarians = new Librarian[librariansAlloc]; + for (unsigned i = 0; i < librariansCount; ++i) + librarians[i] = other.librarians[i]; + + connectionsCount = other.connectionsCount; + connectionsAlloc = other.connectionsAlloc; + connections = new TransactionConnection[connectionsAlloc]; + for (unsigned i = 0; i < connectionsCount; ++i) + connections[i] = other.connections[i]; +} + +void OnlineLibrary::resizeBooks() { + booksAlloc = booksAlloc == 0 ? 8 : booksAlloc * 2; + Book* booksLarger = new Book[booksAlloc]; + + for (unsigned i = 0; i < booksCount; ++i) + booksLarger[i] = books[i]; + + delete[] books; + books = booksLarger; +} + +void OnlineLibrary::resizeUsers() { + usersAlloc = usersAlloc == 0 ? 8 : usersAlloc * 2; + User* usersLarger = new User[usersAlloc]; + + for (unsigned i = 0; i < usersCount; ++i) + usersLarger[i] = users[i]; + + delete[] users; + users = usersLarger; +} + +void OnlineLibrary::resizeLibrarians() { + librariansAlloc = librariansAlloc == 0 ? 8 : librariansAlloc * 2; + Librarian* librariansLarger = new Librarian[librariansAlloc]; + + for (unsigned i = 0; i < librariansCount; ++i) + librariansLarger[i] = librarians[i]; + + delete[] librarians; + librarians = librariansLarger; +} + +void OnlineLibrary::resizeConnections() { + connectionsAlloc = connectionsAlloc == 0 ? 8 : connectionsAlloc * 2; + TransactionConnection* connectionsLarger = new TransactionConnection[connectionsAlloc]; + + for (unsigned i = 0; i < connectionsCount; ++i) + connectionsLarger[i] = connections[i]; + + delete[] connections; + connections = connectionsLarger; +} + +OnlineLibrary::OnlineLibrary() { + books = nullptr; + booksCount = booksAlloc = 0; + users = nullptr; + usersCount = usersAlloc = 0; + librarians = nullptr; + librariansCount = librariansAlloc = 0; + connections = nullptr; + connectionsCount = connectionsAlloc = 0; +} + +OnlineLibrary::~OnlineLibrary() { + free(); +} + +OnlineLibrary::OnlineLibrary(const OnlineLibrary& other) { + copyFrom(other); +} + +OnlineLibrary& OnlineLibrary::operator=(const OnlineLibrary& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +OnlineLibrary::OnlineLibrary(OnlineLibrary&& other) { + books = other.books; + booksCount = other.booksCount; + booksAlloc = other.booksAlloc; + + users = other.users; + usersCount = other.usersCount; + usersAlloc = other.usersAlloc; + + librarians = other.librarians; + librariansCount = other.librariansCount; + librariansAlloc = other.librariansAlloc; + + connections = other.connections; + connectionsCount = other.connectionsCount; + connectionsAlloc = other.connectionsAlloc; + + other.books = nullptr; + other.booksCount = other.booksAlloc = 0; + + other.users = nullptr; + other.usersCount = other.usersAlloc = 0; + + other.librarians = nullptr; + other.librariansCount = other.librariansAlloc = 0; + + other.connections = nullptr; + other.connectionsCount = other.connectionsAlloc = 0; +} + +OnlineLibrary& OnlineLibrary::operator=(OnlineLibrary&& other) { + if (this != &other) { + free(); + + books = other.books; + booksCount = other.booksCount; + booksAlloc = other.booksAlloc; + + users = other.users; + usersCount = other.usersCount; + usersAlloc = other.usersAlloc; + + librarians = other.librarians; + librariansCount = other.librariansCount; + librariansAlloc = other.librariansAlloc; + + connections = other.connections; + connectionsCount = other.connectionsCount; + connectionsAlloc = other.connectionsAlloc; + + other.books = nullptr; + other.booksCount = other.booksAlloc = 0; + + other.users = nullptr; + other.usersCount = other.usersAlloc = 0; + + other.librarians = nullptr; + other.librariansCount = other.librariansAlloc = 0; + + other.connections = nullptr; + other.connectionsCount = other.connectionsAlloc = 0; + } + return *this; +} + +void OnlineLibrary::RegisterUser(const User& user) { + if (usersCount >= usersAlloc) + resizeUsers(); + users[usersCount++] = user; +} + +User* OnlineLibrary::LoginUser(const String& email, const String& password) { + for (unsigned i = 0; i < usersCount; ++i) { + if (users[i].Login(email, password)) + // "users + i" е същото като "&users[i]" + return users + i; + } + return nullptr; +} + +void OnlineLibrary::RegisterLibrarian(const Librarian& librarian) { + if (librariansCount >= librariansAlloc) + resizeLibrarians(); + librarians[librariansCount++] = librarian; +} + +Librarian* OnlineLibrary::LoginLibrarian(unsigned librarianNumber, const String& password) { + for (unsigned i = 0; i < librariansCount; ++i) { + if (librarians[i].Login(librarianNumber, password)) + // "librarians + i" е същото като "&librarians[i]" + return librarians + i; + } + return nullptr; +} + +void OnlineLibrary::ListBooks() const { + for (unsigned i = 0; i < booksCount; ++i) { + if (books[i].GetAvailableForPurchase()) { + std::cout << '[' << i << "] "; + books[i].PrintBookInfo(); + } + } +} + +Book* OnlineLibrary::GetBook(unsigned index) { + if (index >= booksCount) + return nullptr; + // "books + index" е същото като "&books[index]" + return books + index; +} + +void OnlineLibrary::AddBook(const Book& book) { + if (booksCount >= booksAlloc) + resizeBooks(); + books[booksCount++] = book; +} + +void OnlineLibrary::PurchaseBook(const Book& book, const User& user, LibraryBanking& banking) { + if (connectionsCount >= connectionsAlloc) + resizeConnections(); + + TransactionConnection tc; + tc.user = &user; + tc.book = &book; + tc.transaction = banking.RegisterTransaction(Transaction(book.GetPrice(), user.GetBankCard())); + + connections[connectionsCount++] = tc; +} + +void OnlineLibrary::ListTransactions(const User& user) const { + for (unsigned i = 0; i < connectionsCount; ++i) { + if (connections[i].user == &user) { + std::cout << connections[i].book->GetTitle().GetStr() << ", " + << connections[i].book->GetAuthor().GetStr() << " Price:" + << connections[i].book->GetPrice() << " Card:" + << connections[i].transaction->GetBankCard() << " Status:" + << connections[i].transaction->GetStatusStr().GetStr() << std::endl; + } + } +} + +void OnlineLibrary::ExportTransactions(const User& user, const String& fileName) const { + std::ofstream exportFile(fileName.GetStr(), std::ios::trunc); + + if (!exportFile.is_open()) { + std::cout << "Couldn't open export file!" << std::endl; + } + else { + for (unsigned i = 0; i < connectionsCount; ++i) { + if (connections[i].user == &user) { + exportFile << i << ',' + << connections[i].book->GetTitle().GetStr() << ','; + connections[i].transaction->Export(exportFile); + } + } + } +} diff --git a/Week07/Exercise01/OnlineLibrary.h b/Week07/Exercise01/OnlineLibrary.h new file mode 100644 index 0000000..4121af0 --- /dev/null +++ b/Week07/Exercise01/OnlineLibrary.h @@ -0,0 +1,65 @@ +#ifndef _ONLINE_LIBRARY +#define _ONLINE_LIBRARY + +#include "Book.h" +#include "LibraryBanking.h" +#include "Transaction.h" +#include "User.h" +#include "Librarian.h" + +class OnlineLibrary { + Book* books; + unsigned booksCount; + unsigned booksAlloc; + + User* users; + unsigned usersCount; + unsigned usersAlloc; + + Librarian* librarians; + unsigned librariansCount; + unsigned librariansAlloc; + + // В методи на OnlineLibrary, тази структура се казва "TransactionConnection" + // Извън методи на OnlineLibrary, тази структура се казва "OnlineLibrary::TransactionConnection" + struct TransactionConnection { + const User* user; + const Book* book; + const Transaction* transaction; + }; + TransactionConnection* connections; + unsigned connectionsCount; + unsigned connectionsAlloc; + + void free(); + void copyFrom(const OnlineLibrary& other); + + void resizeBooks(); + void resizeUsers(); + void resizeLibrarians(); + void resizeConnections(); + +public: + OnlineLibrary(); + ~OnlineLibrary(); + OnlineLibrary(const OnlineLibrary& other); + OnlineLibrary& operator=(const OnlineLibrary& other); + OnlineLibrary(OnlineLibrary&& other); + OnlineLibrary& operator=(OnlineLibrary&& other); + + void RegisterUser(const User& user); + User* LoginUser(const String& email, const String& password); + + void RegisterLibrarian(const Librarian& librarian); + Librarian* LoginLibrarian(unsigned librarianNumber, const String& password); + + void ListBooks() const; + Book* GetBook(unsigned index); + void AddBook(const Book& book); + void PurchaseBook(const Book& book, const User& user, LibraryBanking& banking); + + void ListTransactions(const User& user) const; + void ExportTransactions(const User& user, const String& fileName) const; +}; + +#endif /* _ONLINE_LIBRARY */ diff --git a/Week07/Exercise01/String.cpp b/Week07/Exercise01/String.cpp new file mode 100644 index 0000000..8272658 --- /dev/null +++ b/Week07/Exercise01/String.cpp @@ -0,0 +1,98 @@ +#include "String.h" +#include <cstring> + +void String::free() { + delete[] str; +} + +void String::copyFrom(const String& other) { + length = other.length; + + // Не забравяме за терминиращата нула + str = new char[length + 1]; + strncpy(str, other.str, length + 1); +} + +void String::resize() { + allocated = allocated == 0 ? 8 : allocated * 2; + char* strLarger = new char[allocated]; + + memcpy(strLarger, str, length); + strLarger[length] = '\0'; + + delete[] str; + str = strLarger; +} + +String::String() { + str = nullptr; + allocated = length = 0; +} + +String::~String() { + free(); +} + +String::String(const String& other) { + copyFrom(other); +} + +String& String::operator=(const String& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +String::String(String&& other) { + str = other.str; + length = other.length; + + other.str = nullptr; + other.length = 0; +} + +String& String::operator=(String&& other) { + if (this != &other) { + free(); + + str = other.str; + length = other.length; + + other.str = nullptr; + other.length = 0; + } + return *this; +} + +String::String(const char* str) { + length = strlen(str); + this->str = new char[length + 1]; + strncpy(this->str, str, length + 1); +} + +void String::Clear() { + free(); + str = nullptr; + length = allocated = 0; +} + +void String::AppendChar(char c) { + if (length + 1 >= allocated) + resize(); + str[length++] = c; + str[length] = '\0'; +} + +bool String::EqualTo(const String& other) const { + return strcmp(str, other.str) == 0; +} + +const char* String::GetStr() const { + return str; +} + +unsigned String::GetLength() const { + return length; +} diff --git a/Week07/Exercise01/String.h b/Week07/Exercise01/String.h new file mode 100644 index 0000000..c9cc263 --- /dev/null +++ b/Week07/Exercise01/String.h @@ -0,0 +1,33 @@ +#ifndef _STRING +#define _STRING + +class String { + char* str; + unsigned length; + unsigned allocated; + + void free(); + void copyFrom(const String& other); + + void resize(); + +public: + String(); + ~String(); + String(const String& other); + String& operator=(const String& other); + String(String&& other); + String& operator=(String&& other); + + String(const char* str); + void Clear(); + + void AppendChar(char c); + + bool EqualTo(const String& other) const; + + const char* GetStr() const; + unsigned GetLength() const; +}; + +#endif /* _STRING */ diff --git a/Week07/Exercise01/Transaction.cpp b/Week07/Exercise01/Transaction.cpp new file mode 100644 index 0000000..8978c05 --- /dev/null +++ b/Week07/Exercise01/Transaction.cpp @@ -0,0 +1,56 @@ +#include "Transaction.h" +#include <iostream> + +Transaction::Transaction(double sum, unsigned bankCard) { + this->clerkNumber = 0; + this->sum = sum; + this->bankCard = bankCard; + this->status = STATUS_PENDING; +} + +Transaction::Transaction() : clerkNumber(0), sum(0), bankCard(0), status(0) +{ } + +unsigned Transaction::GetClerkNumber() const { + return clerkNumber; +} + +double Transaction::GetSum() const { + return sum; +} + +unsigned Transaction::GetBankCard() const { + return bankCard; +} + +unsigned Transaction::GetStatus() const { + return status; +} + +String Transaction::GetStatusStr() const { + switch (status) { + case STATUS_PENDING: return "Pending"; + case STATUS_ACCEPTED: return "Accepted"; + case STATUS_REJECTED: return "Rejected"; + } + return ""; +} + +void Transaction::SetStatus(unsigned clerk, unsigned status) { + this->clerkNumber = clerk; + this->status = status; +} + +void Transaction::PrintTransactionInfo() const { + std::cout << clerkNumber << ' ' + << bankCard << ' ' + << sum << ' ' + << GetStatusStr().GetStr() << std::endl; +} + +void Transaction::Export(std::ofstream& exportFile) const { + exportFile << sum << ',' + << bankCard << ',' + << clerkNumber << ',' + << status << std::endl; +} diff --git a/Week07/Exercise01/Transaction.h b/Week07/Exercise01/Transaction.h new file mode 100644 index 0000000..d4941ce --- /dev/null +++ b/Week07/Exercise01/Transaction.h @@ -0,0 +1,46 @@ +#ifndef _TRANSACTION +#define _TRANSACTION + +#include "String.h" +#include <fstream> + +const unsigned STATUS_PENDING = 0; +const unsigned STATUS_ACCEPTED = 1; +const unsigned STATUS_REJECTED = 2; + +// Няма да обвързваме транзакции с потребители директно +// (т.е. няма член-данна която свързва User обект). +// Тази връзка осъществяваме с UserTransaction класа. +// Логически, можем да приемем че не искаме банковия служител +// да знае за акаунтите на купувачите. +class Transaction { + unsigned clerkNumber; + double sum; + unsigned bankCard; + // Уговаряме се, че стойността на status ще бъде равна на една + // от глобалните променливи STATUS_PENDING, STATUS_ACCEPTED и STATUS_REJECTED. + // Тук е добро място за употреба на енумерации (enum). + unsigned status; + +public: + Transaction(double sum, unsigned bankCard); + // Ако направим поне един конструктор, то конструктора по подразбиране + // спира да се създава автоматично + Transaction(); + + // Не искаме транзакции да могат да се променят своеволно. + // Т.е. след като се създаде транзакция, единствено можем да променяме статус + unsigned GetClerkNumber() const; + double GetSum() const; + unsigned GetBankCard() const; + + unsigned GetStatus() const; + String GetStatusStr() const; + void SetStatus(unsigned clerk, unsigned status); + + void PrintTransactionInfo() const; + + void Export(std::ofstream& exportFile) const; +}; + +#endif /* _TRANSACTION */ diff --git a/Week07/Exercise01/User.cpp b/Week07/Exercise01/User.cpp new file mode 100644 index 0000000..be5f76f --- /dev/null +++ b/Week07/Exercise01/User.cpp @@ -0,0 +1,128 @@ +#include "User.h" +#include <iostream> + +void User::copyFrom(const User& other) { + email = other.email; + password = other.password; + bankCard = other.bankCard; + + libraryCount = other.libraryCount; + libraryAlloc = other.libraryAlloc; + library = new const Book*[libraryAlloc]; + for (unsigned i = 0; i < libraryCount; ++i) + library[i] = other.library[i]; +} + +void User::free() { + delete[] library; +} + +void User::resizeLibrary() { + libraryAlloc = libraryAlloc == 0 ? 8 : libraryAlloc * 2; + const Book** libraryLarger = new const Book*[libraryAlloc]; + + for (unsigned i = 0; i < libraryCount; ++i) + libraryLarger[i] = library[i]; + + delete[] library; + library = libraryLarger; +} + +User::User() : email(), password(), bankCard(0), library(nullptr), libraryCount(0), libraryAlloc(0) +{ } + +User::~User() { + free(); +} + +User::User(const User& other) { + copyFrom(other); +} + +User& User::operator=(const User& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +User::User(User&& other) { + email = other.email; + password = other.password; + bankCard = other.bankCard; + + library = other.library; + libraryCount = other.libraryCount; + libraryAlloc = other.libraryAlloc; + + other.email.Clear(); + other.password.Clear(); + other.bankCard = 0; + + other.library = nullptr; + other.libraryCount = other.libraryAlloc = 0; +} + +User& User::operator=(User&& other) { + if (this != &other) { + free(); + + email = other.email; + password = other.password; + bankCard = other.bankCard; + + library = other.library; + libraryCount = other.libraryCount; + libraryAlloc = other.libraryAlloc; + + other.email.Clear(); + other.password.Clear(); + other.bankCard = 0; + + other.library = nullptr; + other.libraryCount = other.libraryAlloc = 0; + } + return *this; +} + +void User::SetEmail(const String& newEmail) { + email = newEmail; +} + +const String& User::GetEmail() const { + return email; +} + +void User::SetPassword(const String& newPassword) { + password = newPassword; +} + +bool User::Login(const String& email, const String& password) { + return this->email.EqualTo(email) && this->password.EqualTo(password); +} + +void User::AddBookToLibrary(const Book* book) { + if (libraryCount >= libraryAlloc) + resizeLibrary(); + library[libraryCount++] = book; +} + +void User::ListLibrary() { + for (unsigned i = 0; i < libraryCount; ++i) { + std::cout << '[' << i << "] "; + library[i]->PrintBookInfo(); + } +} + +const Book* User::GetBook(unsigned index) const { + return library[index]; +} + +void User::SetBankCard(unsigned newBankCard) { + bankCard = newBankCard; +} + +unsigned User::GetBankCard() const { + return bankCard; +} diff --git a/Week07/Exercise01/User.h b/Week07/Exercise01/User.h new file mode 100644 index 0000000..7e04560 --- /dev/null +++ b/Week07/Exercise01/User.h @@ -0,0 +1,45 @@ +#ifndef _USER +#define _USER + +#include "String.h" +#include "Book.h" + +class User { + String email; + String password; + unsigned bankCard; + + // Масив от указатели към книги + const Book** library; + unsigned libraryCount; + unsigned libraryAlloc; + + void copyFrom(const User& other); + void free(); + + void resizeLibrary(); + +public: + User(); + ~User(); + User(const User& other); + User& operator=(const User& other); + User(User&& other); + User& operator=(User&& other); + + void SetEmail(const String& newEmail); + const String& GetEmail() const; + + void SetPassword(const String& newPassword); + + bool Login(const String& email, const String& password); + + void AddBookToLibrary(const Book* book); + void ListLibrary(); + const Book* GetBook(unsigned index) const; + + void SetBankCard(unsigned newBankCard); + unsigned GetBankCard() const; +}; + +#endif /* _USER */ diff --git a/Week07/Exercise01/main.cpp b/Week07/Exercise01/main.cpp new file mode 100644 index 0000000..ca97b15 --- /dev/null +++ b/Week07/Exercise01/main.cpp @@ -0,0 +1,382 @@ +#include "OnlineLibrary.h" +#include "LibraryBanking.h" +#include "Transaction.h" +#include <iostream> + +// Игнорираме всички букви до края на реда вкл. +void ignoreLine() { + while (std::cin.get() != '\n'); +} + +// Тази функция ни позволява да приемем от входа низ с неограничена дължина +String getlineEndless() { + String bufferString; + for (char buffer = std::cin.get(); buffer != '\n'; buffer = std::cin.get()) { + bufferString.AppendChar(buffer); + } + return bufferString; +} + +void RegisterConsole(OnlineLibrary& lib, LibraryBanking& libBank) { + char c; + std::cin >> c; + switch (c) { + case 'u': { + User newUser; + + std::cout << "Username: "; + ignoreLine(); + newUser.SetEmail(getlineEndless()); + + std::cout << "Password: "; + newUser.SetPassword(getlineEndless()); + + std::cout << "Bank card: "; + unsigned bankCard; + std::cin >> bankCard; + newUser.SetBankCard(bankCard); + + lib.RegisterUser(newUser); + } + break; + case 'l': { + std::cout << "Librarian Number: "; + unsigned number; + std::cin >> number; + + Librarian newLib(number); + + std::cout << "Password: "; + ignoreLine(); + newLib.SetPassword(getlineEndless()); + + lib.RegisterLibrarian(newLib); + } + break; + case 'c': { + std::cout << "Clerk Number: "; + unsigned number; + std::cin >> number; + + BankClerk newClerk(number); + + std::cout << "Static password: "; + ignoreLine(); + newClerk.SetPassword(getlineEndless()); + + libBank.RegisterClerk(newClerk); + } + break; + } +} + +void UserConsole(OnlineLibrary& lib, LibraryBanking& libBank) { + std::cout << "Username: "; + ignoreLine(); + String bufferUsername = getlineEndless(); + + std::cout << "Password: "; + String bufferPassword = getlineEndless(); + + User* loggedIn = lib.LoginUser(bufferUsername, bufferPassword); + if (loggedIn == nullptr) { + std::cout << "Invalid username or password!" << std::endl; + return; + } + + while (true) { + char c; + std::cin >> c; + switch (c) { + case 'e': + return; + case 'l': + loggedIn->ListLibrary(); + break; + case 'r': { + std::cout << "User library index: "; + unsigned i; + std::cin >> i; + const Book* book = loggedIn->GetBook(i); + + if (book == nullptr) { + std::cout << "Invalid index!" << std::endl; + } + else { + std::cout << book->GetText().GetStr() << std::endl; + } + } + break; + case 's': + lib.ListBooks(); + break; + case 'p': { + std::cout << "Book index: "; + unsigned i; + std::cin >> i; + const Book* book = lib.GetBook(i); + + if (book == nullptr) { + std::cout << "Invalid index!" << std::endl; + } + else if (loggedIn->GetBankCard() == 0 && book->GetPrice() != 0.0) { + std::cout << "Cannot purchase book with invalid card!" << std::endl; + } + else { + lib.PurchaseBook(*book, *loggedIn, libBank); + loggedIn->AddBookToLibrary(book); + } + } + break; + case 't': + lib.ListTransactions(*loggedIn); + break; + case 'x': { + std::cout << "Output file: "; + ignoreLine(); + String fileName = getlineEndless(); + + lib.ExportTransactions(*loggedIn, fileName); + } + break; + + case 'P': { + std::cout << "New password: "; + ignoreLine(); + String newPassword = getlineEndless(); + + loggedIn->SetPassword(newPassword); + } + break; + case 'C': { + std::cout << "New bank card: "; + unsigned newBankCard; + std::cin >> newBankCard; + + loggedIn->SetBankCard(newBankCard); + } + break; + } + } +} + +void LibrarianConsole(OnlineLibrary& lib) { + std::cout << "Librarian number: "; + unsigned bufferLibrarianNo; + std::cin >> bufferLibrarianNo; + + std::cout << "Password: "; + ignoreLine(); + String bufferPassword = getlineEndless(); + + Librarian* loggedIn = lib.LoginLibrarian(bufferLibrarianNo, bufferPassword); + if (loggedIn == nullptr) { + std::cout << "Invalid librarian number or password!" << std::endl; + return; + } + + while (true) { + char c; + std::cin >> c; + switch (c) { + case 'e': + return; + // Не се изисква по условие, но е удобно + case 's': + lib.ListBooks(); + break; + case 'a': { + Book newBook; + newBook.SetAvailableForPurchase(true); + + std::cout << "Title: "; + ignoreLine(); + newBook.SetTitle(getlineEndless()); + + std::cout << "Author: "; + newBook.SetAuthor(getlineEndless()); + + std::cout << "Year: "; + short year; + std::cin >> year; + newBook.SetYear(year); + + std::cout << "Price: "; + double price; + std::cin >> price; + newBook.SetPrice(price); + + ignoreLine(); + String text; + char prevprev = std::cin.get(), prev = std::cin.get(), curr = std::cin.get(); + while (prevprev != '\n' || prev != '.' || curr != '\n') { + text.AppendChar(prevprev); + std::cout << '[' << (int)prevprev << ',' << (int)prev << ',' << (int)curr << ']' << std::endl; + + prevprev = prev; + prev = curr; + curr = std::cin.get(); + } + text.AppendChar(prevprev); + newBook.SetText(text); + + lib.AddBook(newBook); + } + break; + case 'i': { + Book newBook; + newBook.SetAvailableForPurchase(true); + + std::cout << "File name: "; + ignoreLine(); + if (newBook.Import(getlineEndless())) { + double price; + std::cout << "Price: "; + std::cin >> price; + newBook.SetPrice(price); + + lib.AddBook(newBook); + } + } + break; + case 'x': { + std::cout << "Book index: "; + unsigned i; + std::cin >> i; + Book* book = lib.GetBook(i); + + if (book == nullptr) { + std::cout << "Invalid index!" << std::endl; + } + else { + std::cout << "File name: "; + ignoreLine(); + book->Export(getlineEndless()); + } + } + break; + case 'E': { + std::cout << "Book index: "; + unsigned i; + std::cin >> i; + Book* book = lib.GetBook(i); + + if (book == nullptr) { + std::cout << "Invalid index!" << std::endl; + } + else { + ignoreLine(); + std::cout << "Title: "; + book->SetTitle(getlineEndless()); + + std::cout << "Author: "; + book->SetAuthor(getlineEndless()); + + std::cout << "Price: "; + double price; + std::cin >> price; + book->SetPrice(price); + } + } + break; + case 'A': { + std::cout << "Book index: "; + unsigned i; + std::cin >> i; + Book* book = lib.GetBook(i); + + if (book == nullptr) { + std::cout << "Invalid index!" << std::endl; + } + else { + book->SetAvailableForPurchase(! book->GetAvailableForPurchase()); + if (book->GetAvailableForPurchase()) { + std::cout << "Book is now available!" << std::endl; + } + else { + std::cout << "Book is now not available!" << std::endl; + } + } + } + break; + } + } +} + +void ClerkConsole(LibraryBanking& libBank) { + std::cout << "Clerk number: "; + unsigned bufferClerkNo; + std::cin >> bufferClerkNo; + + std::cout << "Dynamic password: "; + unsigned dynamicPassword; + std::cin >> dynamicPassword; + + ignoreLine(); + std::cout << "Static password: "; + String bufferPassword = getlineEndless(); + + BankClerk* loggedIn = libBank.LoginClerk(bufferClerkNo, dynamicPassword, bufferPassword); + if (loggedIn == nullptr) { + std::cout << "Invalid clerk number or password!" << std::endl; + return; + } + + while (true) { + char c; + std::cin >> c; + switch (c) { + case 'e': + return; + case 'l': + libBank.ListPendingTransactions(); + break; + case 'A': + case 'R': { + std::cout << "Transaction index: "; + unsigned i; + std::cin >> i; + Transaction* transaction = libBank.GetTransaction(i); + + if (transaction == nullptr) { + std::cout << "Invalid index!" << std::endl; + } + else if (transaction->GetStatus() != STATUS_PENDING) { + std::cout << "Transaction not pending!" << std::endl; + } + else { + transaction->SetStatus(loggedIn->GetClerkNumber(), c == 'A' ? STATUS_ACCEPTED : STATUS_REJECTED); + } + } + break; + case 'x': { + std::cout << "File name: "; + ignoreLine(); + libBank.ExportNonPendingTransactions(getlineEndless()); + } + break; + } + } +} + +// Поискано ни е да имплементираме система, +// това да направим конзолен интерфейс се подразбира +int main() { + OnlineLibrary lib; + LibraryBanking libBank; + + while (true) { + char c; + std::cin >> c; + switch (c) { + case 'r': RegisterConsole(lib, libBank); break; + case 'u': UserConsole(lib, libBank); break; + case 'l': LibrarianConsole(lib); break; + case 'c': ClerkConsole(libBank); break; + case 'e': return 0; + default: std::cout << "Invalid!" << std::endl; + } + } + + return 0; +} |
