School Commit Init

This commit is contained in:
2024-08-31 12:07:21 +03:00
commit 0b130ee18c
2801 changed files with 4720552 additions and 0 deletions
@@ -0,0 +1,34 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
.vscode
@@ -0,0 +1,35 @@
# Assignment 07
Observation:
* Requirements **3** and **4** must be implemented using inheritance and polymorphism.
## Bonus possibility (0.2p, deadline week 9)
In addition to the file-based implementation for the repository, implement a true database-backed repository. For this, use inheritance and polymorphism. You are free to choose any type of database management system (e.g. `MySQL`, `SQLite`, `PostgreSQL`, `Couchbase` etc.).
## Problem Statement
For your solution to the previous assignments (Assignments 04-05, 06), add the following features:
1. Store data in a text file. When the program starts, entities are read from the file. Modifications made during program execution are stored in the file. Implement this using the `iostream` library. Create insertion and extraction operators for your entities and use these when reading/writing to files or the console.
2. Use exceptions to signal errors:
- from the repository;
- validation errors validate your entities using Validator classes;
- create your own exception classes.
- validate program input.
3. Depending on your assignment, store your (adoption list, movie watch list, shopping basket or tutorial watch list) in a file. When the application starts, the user should choose the type of file between `CSV` or `HTML`. Depending on the type, the application will save the list in the correct format.
**Indications**\
The CSV file will contain each entity on one line and the attributes will be separated by comma \
The HTML file will contain a table, in which each row holds the data of one entity. The columns of the table will contain the names of the data attributes.\
These are exemplified in the [example.csv](example.csv) and [example.html](example.html) files.
`CSV` and `HTML` files are used to save and display data to the user; they act as program outputs, so data should not be read from them!
4. Add a new command, allowing the user to see the:
* adoption list
* movie watch list
* shopping basket
* tutorial watch list\
Displaying the list means opening the saved file (`CSV` or `HTML`) with the correct application (`CSV` files using Notepad, Notepad++, Microsoft Excel etc. and `HTML` files using a browser)
5. Create a UML class diagram for your entire application. For this, you can use any tool that you like ([StarUML](https://staruml.io/) or [LucidChart](https://www.lucidchart.com/) are only some examples. Many other options exist.
@@ -0,0 +1,10 @@
38,Bej,55,30,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71zZoa1e-xL._AC_UX466_.jpg
40,Bej,55,25,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71zZoa1e-xL._AC_UX466_.jpg
36,Blac",60,5,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/41RBzLubByL._AC_UY550_.jpg
40,Black,60,50,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/41RBzLubByL._AC_UY550_.jpg
38,Army Green,60,40,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/61Qptn0CKQL._AC_UX342_.jpg
42,Army Green,60,40,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/61Qptn0CKQL._AC_UX342_.jpg
40,Black,100,3,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71YLqJCurtL._AC_UY550_.jpg
38,Red,33,20,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/816lGcU-fWL._AC_UX425_.jpg
40,Red,33,33,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/816lGcU-fWL._AC_UX425_.jpg
38,Blue,51,15,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/51zHT88C6zL._AC_UY550_.jpg
Can't render this file because it contains an unexpected character in line 3 and column 8.
@@ -0,0 +1,2 @@
Queen,Bohemian Rhapsody,5:59,https://www.youtube.com/watch?v=fJ9rUzIMcZQ
Louis Armstrong,What A Wonderful World,2:29,https://www.youtube.com/watch?v=VqhCQZaH4Vs
1 Queen Bohemian Rhapsody 5:59 https://www.youtube.com/watch?v=fJ9rUzIMcZQ
2 Louis Armstrong What A Wonderful World 2:29 https://www.youtube.com/watch?v=VqhCQZaH4Vs
@@ -0,0 +1,29 @@
<!DOCTYPE html> <!-- write this exactly as it is here -->
<html> <!-- write this exactly as it is here -->
<head> <!-- write this exactly as it is here -->
<title>Playlist</title> <!-- replace “Playlist” with the title for your HTML -->
</head> <!-- write this exactly as it is here (close head tag) -->
<body> <!-- write this exactly as it is here -->
<table border="1"> <!-- write this exactly as it is here -->
<tr> <!-- tr = table row; 1 row for each entity -->
<td>Artist</td> <!-- td = table data; 1 td for each attribute of the entity -->
<td>Title</td>
<td>Duration</td>
<td>Youtube link</td>
</tr>
<tr>
<td>Queen</td>
<td>Bohemian Rhapsody</td>
<td>5:59</td>
<td><a href="https://www.youtube.com/watch?v=fJ9rUzIMcZQ">Link</a></td>
<!-- a href makes the text “Link” clickable and directs us towards the link written after “=” -->
</tr>
<tr>
<td>Louis Armstrong</td>
<td>What A Wonderful World</td>
<td>2:29</td>
<td><a href="https://www.youtube.com/watch?v=VqhCQZaH4Vs">Link</a></td>
</tr>
</table>
</body>
</html>
@@ -0,0 +1,10 @@
38,Bej,55,2,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71zZoa1e-xL._AC_UX466_.jpg
40,Bej,55,16,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71zZoa1e-xL._AC_UX466_.jpg
36,Black,60,2,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/41RBzLubByL._AC_UY550_.jpg
40,Black,60,47,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/41RBzLubByL._AC_UY550_.jpg
38,Army Green,60,38,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/61Qptn0CKQL._AC_UX342_.jpg
42,Army Green,60,39,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/61Qptn0CKQL._AC_UX342_.jpg
40,Black,100,3,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71YLqJCurtL._AC_UY550_.jpg
38,Red,33,20,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/816lGcU-fWL._AC_UX425_.jpg
40,Red,33,33,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/816lGcU-fWL._AC_UX425_.jpg
38,Blue,51,15,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/51zHT88C6zL._AC_UY550_.jpg
1 38 Bej 55 2 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71zZoa1e-xL._AC_UX466_.jpg
2 40 Bej 55 16 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71zZoa1e-xL._AC_UX466_.jpg
3 36 Black 60 2 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/41RBzLubByL._AC_UY550_.jpg
4 40 Black 60 47 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/41RBzLubByL._AC_UY550_.jpg
5 38 Army Green 60 38 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/61Qptn0CKQL._AC_UX342_.jpg
6 42 Army Green 60 39 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/61Qptn0CKQL._AC_UX342_.jpg
7 40 Black 100 3 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71YLqJCurtL._AC_UY550_.jpg
8 38 Red 33 20 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/816lGcU-fWL._AC_UX425_.jpg
9 40 Red 33 33 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/816lGcU-fWL._AC_UX425_.jpg
10 38 Blue 51 15 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/51zHT88C6zL._AC_UY550_.jpg
@@ -0,0 +1 @@
38,Bej,55,1,https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71zZoa1e-xL._AC_UX466_.jpg
1 38 Bej 55 1 https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T2/images/I/71zZoa1e-xL._AC_UX466_.jpg
@@ -0,0 +1 @@
<!DOCTYPE html><html><head><title>Shopping list</title></head><body><table border="1"><tr><td>Size</td><td>Colour</td><td>Price</td><td>Quantity</td><td>Photograph Link</td><td>Photo</td></tr></table></body></html>
@@ -0,0 +1,57 @@
#include "admin_controller.h"
#include "../../exceptions/exceptions.h"
#include <string>
#include <algorithm>
AdminController::AdminController(std::shared_ptr<FileRepository> repo){
this->_repo = repo;
}
AdminController::~AdminController(){
}
void AdminController::add(int size,std::string colour,int price,int quantity,std::string photograph){
Trench trench(size,colour,price,quantity,photograph);
this->_repo->add(trench);
}
void AdminController::remove(int size,std::string colour,std::string photograph){
Trench trench(size,colour,0,0,photograph);
this->_repo->remove(trench);
}
void AdminController::remove(int index){
this->_repo->remove(index);
}
void AdminController::update(int size,std::string colour,int price,int quantity,std::string photograph){
Trench trench(size,colour,price,quantity,photograph);
int index = this->_repo->get(trench);
if(index==-1){
throw AdminControllerException("Trench does not exist");
}
this->_repo->update(index,price,quantity);
}
int AdminController::get(int size,std::string colour,std::string photograph){
if(size<=0){
throw AdminControllerException("Size must be greater than 0");
}
if(colour.length()==0){
throw AdminControllerException("Colour must not be empty");
}
if(photograph.length()==0){
throw AdminControllerException("Photograph must not be empty");
}
Trench trench(size,colour,0,0,photograph);
int index = this->_repo->get(trench);
return index;
}
int AdminController::size(){
return this->_repo->size();
}
Trench& AdminController::operator[](int index){
return (*this->_repo)[index];
}
std::shared_ptr<FileRepository> AdminController::getAll(){
return this->_repo;
}
@@ -0,0 +1,112 @@
#pragma once
#include "../../repository/FileRepository.h"
#include <string>
#include <memory>
class AdminController {
private:
std::shared_ptr<FileRepository> _repo;
public:
/*
* Constructor for the AdminController class
* Input: repo - Repository object
* Output: adminController object
*/
AdminController(std::shared_ptr<FileRepository> repo);
/*
* Destructor for the AdminController class
* Input: -
* Output: -
*/
~AdminController();
/*
* Adds a trench coat to the repository
* Input: size - integer
* colour - string
* price - integer
* quantity - integer
* photograph - string
* Output: -
* Throws: AdminControllerException if: size<=0
* colour is empty
* price<=0
* quantity<0
* photograph is empty
* trench coat already exists
*/
void add(int size,std::string colour,int price,int quantity,std::string photograph);
/*
* Removes a trench coat from the repository
* Input: size - integer
* colour - string
* photograph - string
* Output: -
* Throws: AdminControllerException if: size<=0
* colour is empty
* photograph is empty
* trench coat does not exist
*/
void remove(int size,std::string colour,std::string photograph);
/*
* Removes a trench coat from the repository
* Input: index - integer
* Output: -
* Throws: RepoException if: index is out of bounds
*/
void remove(int index);
/*
* Updates a trench coat from the repository. If the price or quantity is -1, it will not be updated
* Input: size - integer
* colour - string
* price - integer
* quantity - integer
* photograph - string
* Output: -
* Throws: AdminControllerException if: size<=0
* colour is empty
* price!=-1 and price<=0
* quantity!=-1 and quantity<0
* photograph is empty
* trench coat does not exist
*/
void update(int size,std::string colour,int price,int quantity,std::string photograph);
/*
* Returns the index of a trench coat in the repository. If it does not exist, it returns -1
* Input: size - integer
* colour - string
* photograph - string
* Output: index - integer
*/
int get(int size,std::string colour,std::string photograph);
/*
* Returns the number of trench coats in the repository
* Input: -
* Output: size - integer
*/
int size();
/*
* Returns the trench coat at the given index
* Input: index - integer
* Output: trench coat - Trench object
* Throws: RepoException if: index is out of bounds
*/
Trench& operator[](int index);
/*
* Returns an iterator for all the trench coats in the repository
* Input: -
* Output: iterator
*/
std::shared_ptr<FileRepository> getAll();
};
@@ -0,0 +1,56 @@
#include "../../repository/FileRepository.h"
#include "../../domain/trench.h"
#include "user_controller.h"
#include <stdio.h>
#include <vector>
UserController::UserController(std::shared_ptr<FileRepository> repo,std::shared_ptr<FileRepository> shoppingRepo) {
this->_repo = repo;
this->_shoppingRepository = shoppingRepo;
}
UserController::~UserController() {
}
void UserController::addProductToShoppingList(Trench trench) {
int index = this->_shoppingRepository->get(trench);
int repo_index = this->_repo->get(trench);
if(index==-1) {
Trench trenchCopy = trench;
trenchCopy.quantity(1);
this->_shoppingRepository->add(trenchCopy);
trench.quantity(trench.quantity()-1);
(*this->_repo)[repo_index].quantity((*this->_repo)[repo_index].quantity()-1);
return;
}
trench.quantity(trench.quantity()-1);
this->_shoppingRepository->update(index,trench.price(),(*this->_shoppingRepository)[index].quantity()+1);
(*this->_repo)[repo_index].quantity((*this->_repo)[repo_index].quantity()-1);
}
int UserController::shoppingListTotal() {
int total = 0;
for(Trench i : *this->_shoppingRepository) {
total+=i.quantity()*i.price();
}
return total;
}
std::vector<Trench> UserController::getTrenchCarousel(int size) {
std::vector<Trench> trenchCarousel;
for(Trench i : *this->_repo){
if((size == -1||i.size()==size) && i.quantity()>0){
Trench copy = i;
trenchCarousel.push_back(copy);
}
}
return trenchCarousel;
}
void UserController::openShoppingList() {
this->_shoppingRepository->open();
}
@@ -0,0 +1,53 @@
#pragma once
#include "../../repository/FileRepository.h"
#include "../../domain/trench.h"
#include <vector>
#include <memory>
class UserController {
private:
std::shared_ptr<FileRepository> _repo;
std::shared_ptr<FileRepository> _shoppingRepository;
public:
/*
* Constructor for the UserController class
* Input: repo - Repository object
* Output: userController object
*/
UserController(std::shared_ptr<FileRepository> repo,std::shared_ptr<FileRepository> shoppingRepo);
/*
* Destructor for the UserController class
* Input: -
* Output: -
*/
~UserController();
/*
* Adds a trench coat to the shopping list
* Input: trench - Trench object
* Output: -
*/
void addProductToShoppingList(Trench trench);
/*
* Returns the total price of the shopping list
* Input: -
* Output: total - integer
*/
int shoppingListTotal();
/*
* Returns a vector of trench coats that are in the shopping list
* Input: size - integer
* Output: trenchCarousel - vector<Trench*> object
*/
std::vector<Trench> getTrenchCarousel(int size);
void openShoppingList();
};
@@ -0,0 +1,128 @@
#include "trench.h"
#include <string.h>
#include <string>
#include <exception>
#include <stdio.h>
#include <iostream>
#include <fstream>
Trench::Trench(int size, std::string colour, int price, int quantity, std::string photograph){
this->_size = size;
this->_colour = colour;
this->_price = price;
this->_quantity = quantity;
this->_photograph=photograph;
}
Trench::~Trench(){
}
Trench::Trench(const Trench &trench){
_size = trench.size();
_colour = trench.colour();
_price = trench.price();
_quantity = trench.quantity();
_photograph = trench.photograph();
}
Trench& Trench::operator=(const Trench &trench){
this->_size = trench.size();
this->_colour=trench.colour();
this->_price = trench.price();
this->_quantity = trench.quantity();
this->_photograph = trench.photograph();
return *this;
}
int Trench::size() const {
return this->_size;
}
void Trench::size(int newSize){
this->_size = newSize;
}
std::string Trench::colour() const {
return this->_colour;
}
void Trench::colour(std::string newColour){
this->_colour = newColour;
}
int Trench::price() const {
return this->_price;
}
void Trench::price(int newPrice){
this->_price = newPrice;
}
int Trench::quantity() const{
return this->_quantity;
}
void Trench::quantity(int newQuantity){
this->_quantity = newQuantity;
}
std::string Trench::photograph() const {
return this->_photograph;
}
void Trench::photograph(std::string newPhotograph){
this->_photograph = newPhotograph;
}
bool Trench::operator==(const Trench& t){
if(this->_size==t.size() && this->_colour == t.colour() && this->_photograph == t.photograph()){
return true;
}
return false;
}
std::ostream& operator<<(std::ostream& os, const Trench& trench){
os << "Size: " << trench.size() << " | Colour: " << trench.colour() << " | Price: " << trench.price() << " | Quantity: " << trench.quantity() << " | Photograph Link: " << trench.photograph() << std::endl;
return os;
}
std::ofstream& operator<<(std::ofstream& os, const Trench& trench){
os << trench.size() << "," << trench.colour() << "," << trench.price() << "," << trench.quantity() << "," << trench.photograph() << std::endl;
return os;
}
std::ifstream& operator>>(std::ifstream& is, Trench& trench){
std::string line;
std::getline(is, line);
if(line == ""){
return is;
}
std::string delimiter = ",";
size_t pos = 0;
std::string token;
int i = 0;
while ((pos = line.find(delimiter)) != std::string::npos) {
token = line.substr(0, pos);
switch(i){
case 0:
trench.size(std::stoi(token));
break;
case 1:
trench.colour(token);
break;
case 2:
trench.price(std::stoi(token));
break;
case 3:
trench.quantity(std::stoi(token));
break;
}
line.erase(0, pos + delimiter.length());
i++;
}
trench.photograph(line);
return is;
}
@@ -0,0 +1,135 @@
#pragma once
#include <string>
class Trench {
private:
int _size;
std::string _colour;
int _price;
int _quantity;
std::string _photograph;
public:
Trench()=default;
/*
* Constructor for the Trench class
* Input: size - integer
* colour - string
* price - integer
* quantity - integer
* photograph - string
* Output: trench object
*/
Trench(int size, std::string colour, int price, int quantity, std::string photograph);
/*
* Destructor for the Trench class
* Input: -
* Output: -
*/
~Trench();
/*
* Copy constructor for the Trench class
* Input: trench - trench object
* Output: trench object
*/
Trench(const Trench &trench);
/*
* Overload of the = operator
* Input: trench - trench object
* Output: trench object
*/
Trench& operator=(const Trench &trench);
/*
* Getter for the size attribute
* Input: -
* Output: size - integer
*/
int size() const;
/*
* Setter for the size attribute
* Input: newSize - integer
* Output: -
*/
void size(int newSize);
/*
* Getter for the colour attribute
* Input: -
* Output: colour - string
*/
std::string colour() const;
/*
* Setter for the colour attribute
* Input: newColour - string
* Output: -
*/
void colour(std::string newColour);
/*
* Getter for the price attribute
* Input: -
* Output: price - integer
*/
int price() const;
/*
* Setter for the price attribute
* Input: newPrice - integer
* Output: -
*/
void price(int newPrice);
/*
* Getter for the quantity attribute
* Input: -
* Output: quantity - integer
*/
int quantity() const;
/*
* Setter for the quantity attribute
* Input: newQuantity - integer
* Output: -
*/
void quantity(int newQuantity);
/*
* Getter for the photograph attribute
* Input: -
* Output: photograph - string
*/
std::string photograph() const;
/*
* Setter for the photograph attribute
* Input: newPhotograph - string
* Output: -
*/
void photograph(std::string newPhotograph);
/*
* Overload of the == operator
* Input: trench - trench object
* Output: true - if the trench objects are the same
* false - otherwise
*/
bool operator==(const Trench& t);
friend std::ostream& operator<<(std::ostream& os, const Trench& trench);
friend std::ofstream& operator<<(std::ofstream& os, const Trench& trench);
friend std::ifstream& operator>>(std::ifstream& is, Trench& trench);
};
@@ -0,0 +1,25 @@
#include "exceptions.h"
RepoException::RepoException(const char* message){
this->_message = message;
}
const char* RepoException::what() const noexcept {
return this->_message;
}
AdminControllerException::AdminControllerException(const char* message){
this->_message = message;
}
const char* AdminControllerException::what() const noexcept {
return this->_message;
}
ValidatorException::ValidatorException(const char* message){
this->_message = message;
}
const char* ValidatorException::what() const noexcept {
return this->_message;
}
@@ -0,0 +1,26 @@
#pragma once
#include <exception>
class RepoException : public std::exception {
public:
RepoException(const char* message);
const char* what() const noexcept override;
private:
const char* _message;
};
class AdminControllerException : public std::exception {
public:
AdminControllerException(const char* message);
const char* what() const noexcept override;
private:
const char* _message;
};
class ValidatorException : public std::exception{
public:
ValidatorException(const char* message);
const char* what() const noexcept override;
private:
const char* _message;
};
@@ -0,0 +1,12 @@
#include "repository/MemoryRepository.h"
#include "repository/CSVRepository.h"
#include "repository/HTMLRepository.h"
#include "controllers/admin_controller/admin_controller.h"
#include "ui/ui.h"
int main(){
UI ui;
ui.run();
return 0;
}
@@ -0,0 +1,42 @@
#include "CSVRepository.h"
CSVRepository::CSVRepository(std::string fileName){
this->_fileName = fileName;
}
CSVRepository::~CSVRepository(){
this->saveToFile();
}
void CSVRepository::loadFromFile(){
std::ifstream file(this->_fileName);
if(!file.is_open()){
return;
}
while(true){
Trench trench;
file >> trench;
if(file.eof()){
break;
}
this->_data.push_back(trench);
}
file.close();
}
void CSVRepository::saveToFile(){
std::ofstream file(this->_fileName);
if(!file.is_open()){
return;
}
for(auto trench : this->_data){
file << trench;
}
file.close();
}
void CSVRepository::open(){
std::string command = "notepad-plus-plus " + this->_fileName + " > /dev/null 2>&1";
system(command.c_str());
}
@@ -0,0 +1,19 @@
#pragma once
#include "FileRepository.h"
#include "../exceptions/exceptions.h"
#include "../domain/trench.h"
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
class CSVRepository : public FileRepository {
private:
std::string _fileName;
void saveToFile() override;
public:
void loadFromFile();
CSVRepository(std::string fileName);
~CSVRepository();
void open() override;
};
@@ -0,0 +1,21 @@
#include "FileRepository.h"
void FileRepository::add(Trench trench){
MemoryRepository::add(trench);
this->saveToFile();
}
void FileRepository::remove(int index){
MemoryRepository::remove(index);
this->saveToFile();
}
void FileRepository::remove(Trench trench){
MemoryRepository::remove(trench);
this->saveToFile();
}
void FileRepository::update(int index, int price, int quantity){
MemoryRepository::update(index, price, quantity);
this->saveToFile();
}
@@ -0,0 +1,20 @@
#pragma once
#include "MemoryRepository.h"
#include "../domain/trench.h"
#include <string>
class FileRepository : public MemoryRepository {
protected:
std::string _fileName;
virtual void saveToFile()=0;
public:
FileRepository()=default;
virtual ~FileRepository()=default;
virtual void add(Trench trench) override;
virtual void remove(Trench trench) override;
virtual void remove(int index) override;
virtual void update(int index, int price, int quantity) override;
virtual void open()=0;
};
@@ -0,0 +1,28 @@
#include "HTMLRepository.h"
HTMLRepository::HTMLRepository(std::string fileName){
this->_fileName = fileName;
}
HTMLRepository::~HTMLRepository(){
this->saveToFile();
}
void HTMLRepository::saveToFile(){
std::ofstream file(this->_fileName);
if(!file.is_open()){
return;
}
file << "<!DOCTYPE html><html><head><title>Shopping list</title></head><body><table border=\"1\"><tr><td>Size</td><td>Colour</td><td>Price</td><td>Quantity</td><td>Photograph Link</td><td>Photo</td></tr>";
for(auto trench : this->_data){
file << "<tr><td>" << trench.size() << "</td><td>" << trench.colour() << "</td><td>" << trench.price() << "</td><td>" << trench.quantity() << "</td><td>" << "<a href=\"" << trench.photograph() << "\">Link</a> " << "</td><td>" << "<img src=\"" << trench.photograph() << "\" width=100 height=100>" << "</td></tr>";
}
file << "</table></body></html>";
file.close();
}
void HTMLRepository::open(){
std::string command = "xdg-open " + this->_fileName + " > /dev/null 2>&1";
system(command.c_str());
}
@@ -0,0 +1,23 @@
#pragma once
#include "FileRepository.h"
#include "../exceptions/exceptions.h"
#include "../domain/trench.h"
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
class HTMLRepository : public FileRepository {
private:
std::string _fileName;
void saveToFile() override;
public:
HTMLRepository(std::string fileName);
~HTMLRepository();
void open() override;
};
@@ -0,0 +1,64 @@
#include "MemoryRepository.h"
#include "../exceptions/exceptions.h"
MemoryRepository::MemoryRepository(){
}
MemoryRepository::~MemoryRepository(){
}
void MemoryRepository::add(Trench trench){
if(this->get(trench)!=-1)
throw RepoException("Trench already exists");
this->_data.push_back(trench);
}
void MemoryRepository::remove(Trench trench){
int index = this->get(trench);
if(index==-1)
throw RepoException("Trench does not exists");
this->remove(index);
}
void MemoryRepository::remove(int index){
if(index<0 || index > (int)(this->_data.size())-1)
throw RepoException("Index out of bounds");
this->_data.erase(this->_data.begin()+index);
}
int MemoryRepository::get(Trench trench){
for(int i=0;i<(int)(this->_data.size());i++){
if(trench == this->_data[i])
return i;
}
return -1;
}
Trench& MemoryRepository::operator[](int index){
if(index<0 || index > (int)(this->_data.size())-1)
throw RepoException("Index out of bounds");
return this->_data[index];
}
void MemoryRepository::update(int index, int price, int quantity){
if(index<0 || index > (int)(this->_data.size())-1)
throw RepoException("Index out of bounds");
Trench& trench = this->_data[index];
if(price!=-1 && price<=0)
throw RepoException("Invalid price");
if(quantity!=-1 && quantity<0)
throw RepoException("Invalid quantity");
if(price>0)
trench.price(price);
if(quantity>=0)
trench.quantity(quantity);
}
int MemoryRepository::size(){
return this->_data.size();
}
std::vector<Trench>::iterator MemoryRepository::begin(){
return this->_data.begin();
}
std::vector<Trench>::iterator MemoryRepository::end(){
return this->_data.end();
}
@@ -0,0 +1,94 @@
#pragma once
#include "../domain/trench.h"
#include <vector>
#include "Repository.h"
class MemoryRepository : public Repository {
public:
/*
* Constructor for the Repository class
* Input: -
* Output: repository object
*/
MemoryRepository();
/*
* Destructor for the Repository class
* Input: -
* Output: -
*/
~MemoryRepository();
/*
* Adds a trench to the repository
* Input: trench - trench object
* Output: -
* Throws: RepoException if trench already exists
*/
void add(Trench trench) override;
/*
* Removes a trench from the repository
* Input: trench - trench object
* Output: -
* Throws: RepoException if trench does not exist
*/
void remove(Trench trench) override;
/*
* Removes a trench from the repository
* Input: index - index of the trench
* Output: -
* Throws: RepoException if index is out of bounds
*/
void remove(int index) override;
/*
* Returns the index of a trench in the repository
* Input: trench - trench object
* Output: index of the trench. -1 if trench does not exist
*/
int get(Trench trench) override;
/*
* Returns a trench from the repository
* Input: index - index of the trench
* Output: trench object
* Throws: RepoException if index is out of bounds
*/
Trench& operator[](int index) override;
/*
* Updates a trench from the repository
* Input: index - index of the trench
* price - new price
* quantity - new quantity
* Output: -
* Throws: RepoException if index is out of bounds
*/
void update(int index, int price, int quantity) override;
/*
* Returns the size of the repository
* Input: -
* Output: size of the repository
*/
int size() override;
/*
* Returns an iterator to the beginning of the repository
* Input: -
* Output: iterator to the beginning of the repository
*/
std::vector<Trench>::iterator begin() override;
/*
* Returns an iterator to the end of the repository
* Input: -
* Output: iterator to the end of the repository
*/
std::vector<Trench>::iterator end() override;
};
@@ -0,0 +1,21 @@
#pragma once
#include "../domain/trench.h"
#include <vector>
class Repository {
protected:
std::vector<Trench> _data;
public:
Repository() = default;
~Repository() = default;
virtual void add(Trench trench) = 0;
virtual void remove(Trench trench) = 0;
virtual void remove(int index) = 0;
virtual int get(Trench trench) = 0;
virtual Trench& operator[](int index) = 0;
virtual void update(int index, int price, int quantity) = 0;
virtual int size() = 0;
virtual std::vector<Trench>::iterator begin() = 0;
virtual std::vector<Trench>::iterator end() = 0;
};
@@ -0,0 +1,16 @@
#include<iostream>
#include "tests/domain_tests/domain_tests.h"
#include "tests/repo_tests/repo_tests.h"
#include "tests/admin_controller_tests/admin_controller_tests.h"
#include "tests/user_controller_tests/user_controller_tests.h"
int main(){
test_domain();
test_repo();
test_admin_controller();
test_user_controller();
std::cout<<"All tests passed"<<std::endl;
return 0;
}
@@ -0,0 +1,333 @@
#include "ui.h"
#include "../exceptions/exceptions.h"
#include "../domain/trench.h"
#include "../validator/validator.h"
#include "../repository/Repository.h"
#include "../repository/MemoryRepository.h"
#include "../repository/CSVRepository.h"
#include "../repository/HTMLRepository.h"
#include "../controllers/admin_controller/admin_controller.h"
#include "../controllers/user_controller/user_controller.h"
#include <stdlib.h>
#include <vector>
#include <string>
#include <memory>
#include <iostream>
UI::UI(){
std::shared_ptr<CSVRepository> repo = std::make_shared<CSVRepository>("repo.csv");
repo->loadFromFile();
std::shared_ptr<FileRepository> shoppingRepo;
while(true){
std::cout<<"1. CSV Repository"<<std::endl;
std::cout<<"2. HTML Repository"<<std::endl;
std::cout<<"Option: ";
std::string buffer;
getline(std::cin,buffer);
if(buffer.length()!=1){
std::cout<<"Invalid option!"<<std::endl;
continue;
}
char option = buffer[0];
switch(option){
case '1':
shoppingRepo = std::make_shared<CSVRepository>("shoppingRepo.csv");
break;
case '2':
shoppingRepo = std::make_shared<HTMLRepository>("shoppingRepo.html");
break;
default:
std::cout<<"Invalid option!"<<std::endl;
continue;
}
break;
}
this->_adminController = std::make_unique<AdminController>(repo);
this->_userController = std::make_unique<UserController>(repo,shoppingRepo);
}
UI::~UI(){
}
void UI::run(){
char option = 0;
std::string buffer;
while(1){
std::cout<<"1. Run as admin"<<std::endl;
std::cout<<"2. Run as user"<<std::endl;
std::cout<<"3. Exit"<<std::endl;
std::cout<<"Option: ";
std::getline(std::cin,buffer);
if(buffer.length()!=1){
std::cout<<"Invalid option!"<<std::endl;
continue;
}
option = buffer[0];
switch(option){
case '1':
this->runAsAdmin();
break;
case '2':
this->runAsUser();
break;
case '3':
return;
default:
std::cout<<"Invalid option!"<<std::endl;
break;
}
}
}
void UI::runAsAdmin(){
char option = 0;
std::string buffer;
while(1){
std::cout<<"1. Add trench"<<std::endl;
std::cout<<"2. Remove trench"<<std::endl;
std::cout<<"3. Update trench"<<std::endl;
std::cout<<"4. List all trenches"<<std::endl;
std::cout<<"5. Exit"<<std::endl;
std::cout<<"Option: ";
std::getline(std::cin,buffer);
if(buffer.length()!=1){
std::cout<<"Invalid option!"<<std::endl;
continue;
}
option = buffer[0];
switch(option){
case '1':
{
try{
std::string buffer;
int size;
std::string colour;
int price;
int quantity;
std::string photograph;
std::cout<<"Size: ";
getline(std::cin,buffer);
Validator::validate_size(buffer);
size = std::stoi(buffer);
std::cout<<"Colour: ";
getline(std::cin,colour);
Validator::validate_colour(colour);
std::cout<<"Price: ";
getline(std::cin,buffer);
Validator::validate_price(buffer);
price = std::stoi(buffer);
std::cout<<"Quantity: ";
getline(std::cin,buffer);
Validator::validate_quantity(buffer);
quantity = std::stoi(buffer);
std::cout<<"Photograph: ";
getline(std::cin,photograph);
Validator::validate_photograph(photograph);
this->_adminController->add(size,colour,price,quantity,photograph);
std::cout<<"Trench added!"<<std::endl;
}
catch(ValidatorException& e){
std::cout<<e.what()<<std::endl;
}
catch(RepoException& e){
std::cout<<e.what()<<std::endl;
}
}
break;
case '2':
{
try{
std::string buffer;
int size;
std::string colour;
std::string photograph;
std::cout<<"Size: ";
getline(std::cin,buffer);
Validator::validate_size(buffer);
size = std::stoi(buffer);
std::cout<<"Colour: ";
getline(std::cin,colour);
Validator::validate_colour(colour);
std::cout<<"Photograph: ";
getline(std::cin,photograph);
Validator::validate_photograph(photograph);
this->_adminController->remove(size,colour,photograph);
std::cout<<"Trench removed!"<<std::endl;
}
catch(ValidatorException& e){
std::cout<<e.what()<<std::endl;
}
catch(RepoException& e){
std::cout<<e.what()<<std::endl;
}
}
break;
case '3':
{
try{
std::string buffer;
int size;
std::string colour;
int price;
int quantity;
std::string photograph;
std::cout<<"Size: ";
getline(std::cin,buffer);
Validator::validate_size(buffer);
size = std::stoi(buffer);
std::cout<<"Colour: ";
getline(std::cin,colour);
Validator::validate_colour(colour);
std::cout<<"Price: (type enter to not change it) ";
getline(std::cin,buffer);
if (buffer.length()!=0){
Validator::validate_price(buffer);
price = std::stoi(buffer);
}
else
price = -1;
std::cout<<"Quantity: (type enter to not change it) ";
getline(std::cin,buffer);
if (buffer.length()!=0){
Validator::validate_quantity(buffer);
quantity = std::stoi(buffer);
}
else
quantity = -1;
std::cout<<"Photograph: ";
getline(std::cin,photograph);
Validator::validate_photograph(photograph);
this->_adminController->update(size,colour,price,quantity,photograph);
std::cout<<"Trench updated!"<<std::endl;
}
catch(ValidatorException& e){
std::cout<<e.what()<<std::endl;
}
catch(RepoException& e){
std::cout<<e.what()<<std::endl;
}
catch(AdminControllerException& e){
std::cout<<e.what()<<std::endl;
}
}
break;
case '4':
for(Trench i:*this->_adminController->getAll()){
std::cout<<i;
}
break;
case '5':
return;
default:
std::cout<<"Invalid option!"<<std::endl;
break;
}
}
}
void UI::runAsUser(){
char option;
std::string buffer;
while(1){
std::cout<<"1. Show all trench coats in a given size"<<std::endl;
std::cout<<"2. Show shopping cart"<<std::endl;
std::cout<<"3. Exit"<<std::endl;
std::cout<<"Option: ";
std::getline(std::cin,buffer);
if(buffer.length()!=1){
std::cout<<"Invalid option!"<<std::endl;
continue;
}
option = buffer[0];
switch(option){
case '1':
{
std::string buffer;
int size;
std::cout<<"Size: ";
getline(std::cin,buffer);
if (buffer.length()!=0){
try{
Validator::validate_size(buffer);
}
catch(ValidatorException& e){
std::cout<<e.what()<<std::endl;
continue;
}
size = std::stoi(buffer);
}
else
size = -1;
std::vector<Trench> iterator = this->_userController->getTrenchCarousel(size);
if(iterator.size()==0){
std::cout<<"No trench coats found!"<<std::endl;
continue;
}
int exit = 1;
int index = 0;
while(exit && iterator.size()){
Trench s = iterator[index];
std::cout<< s << std::endl;
std::cout<<"Total price: "<<this->_userController->shoppingListTotal()<<std::endl;
char option;
std::string buffer;
std::cout<<"1. Add to shopping cart"<<std::endl;
std::cout<<"2. Next trench coat"<<std::endl;
std::cout<<"3. Exit"<<std::endl;
std::cout<<"Option: ";
std::getline(std::cin,buffer);
if(buffer.length()!=1){
std::cout<<"Invalid option!"<<std::endl;
continue;
}
option = buffer[0];
switch(option){
case '1':
{
this->_userController->addProductToShoppingList(iterator[index]);
iterator[index].quantity(iterator[index].quantity()-1);
if (iterator[index].quantity() == 0){
iterator.erase(iterator.begin()+index);
if(index==(int)(iterator.size()))
index=0;
}
break;
}
case '2':
{
index++;
if(index==(int)(iterator.size()))
index=0;
break;
}
case '3':
{
exit=0;
break;
}
default:
std::cout<<"Invalid option!"<<std::endl;
break;
}
}
break;
}
case '2':
{
this->_userController->openShoppingList();
}
case '3':
{
return;
}
}
}
}
@@ -0,0 +1,17 @@
#pragma once
#include "../controllers/admin_controller/admin_controller.h"
#include "../controllers/user_controller/user_controller.h"
#include <memory>
class UI {
private:
std::unique_ptr<AdminController> _adminController;
std::unique_ptr<UserController> _userController;
public:
UI();
~UI();
void run();
void runAsAdmin();
void runAsUser();
};
@@ -0,0 +1,59 @@
#include "validator.h"
#include "../exceptions/exceptions.h"
void Validator::validate_size(const std::string& size) {
if (size.length() == 0) {
throw ValidatorException("Invalid size!");
}
for(size_t i=0;i<size.length();i++){
if(size[i]<'0' || size[i]>'9'){
throw ValidatorException("Invalid size!");
break;
}
}
if (std::stoi(size) <= 0) {
throw ValidatorException("Invalid size!");
}
}
void Validator::validate_colour(const std::string& colour) {
if (colour.length() == 0) {
throw ValidatorException("Invalid colour!");
}
}
void Validator::validate_price(const std::string& price) {
if (price.length() == 0) {
throw ValidatorException("Invalid price!");
}
for(size_t i=0;i<price.length();i++){
if(price[i]<'0' || price[i]>'9'){
throw ValidatorException("Invalid price!");
break;
}
}
if (std::stoi(price) <= 0) {
throw ValidatorException("Invalid price!");
}
}
void Validator::validate_quantity(const std::string& quantity) {
if (quantity.length() == 0) {
throw ValidatorException("Invalid quantity!");
}
for(size_t i=0;i<quantity.length();i++){
if(quantity[i]<'0' || quantity[i]>'9'){
throw ValidatorException("Invalid quantity!");
break;
}
}
if (std::stoi(quantity) < 0) {
throw ValidatorException("Invalid quantity!");
}
}
void Validator::validate_photograph(const std::string& photograph) {
if (photograph.length() == 0) {
throw ValidatorException("Invalid photograph!");
}
}
@@ -0,0 +1,14 @@
#pragma once
#include <string>
class Validator {
private:
Validator()=default;
public:
static void validate_size(const std::string& size);
static void validate_colour(const std::string& colour);
static void validate_price(const std::string& price);
static void validate_quantity(const std::string& quantity);
static void validate_photograph(const std::string& photograph);
};