School Commit Init
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
@@ -0,0 +1,53 @@
|
||||
# 💻 Assignment 07
|
||||
## Requirements
|
||||
|
||||
- You will be given one of the problems below to solve
|
||||
- The program must provide a menu-driven console user interface.
|
||||
- Use classes to represent the following:
|
||||
- The `UI` class which implements the user interface
|
||||
- A `Services` class that implements the required functionalities
|
||||
- The domain entity (`complex`, `expense`, `student`, `book`) class
|
||||
- A `Repository` class whose job it is to store the domain entity instances. This class will have three implementations: (1) a `MemoryRepository`, which stores domain instances in memory (just like in previous assignments); (2) a `TextFileRepository`, which persists domain entities to a text file, and (3) a `BinaryFileRepository`, which persists domain entities using object serialization with [Pickle](https://docs.python.org/3.10/library/pickle.html). You should be able to switch between which repository is in use by changing the instantiated class. When using a file-backed repository, changes made while running the program must be persisted across runs.
|
||||
- Have 10 programmatically generated entries in the application at start-up. Save these to the text/binary input files.
|
||||
- Unit tests and specifications for non-UI functions related to the first functionality.
|
||||
|
||||
## Problem Statements
|
||||
### 1. Complex numbers
|
||||
Manage a list of complex numbers in `a+bi` form and provide the user the following features:
|
||||
1. Add a number. The number is read from the console.
|
||||
2. Display the list of numbers.
|
||||
3. Filter the list so that it contains only the numbers between indices `start` and `end`, where these values are read from the console.
|
||||
4. Undo the last operation that modified program data. This step can be repeated. The user can undo only those operations made during the current run of the program.
|
||||
|
||||
---
|
||||
### 2. Expenses
|
||||
Manage a list of expenses. Each expense has a `day` (integer between 1 and 30), `amount` of money (positive integer) and expense `type` (string). Provide the following features:
|
||||
1. Add an expense. Expense data is read from the console.
|
||||
2. Display the list of expenses.
|
||||
3. Filter the list so that it contains only expenses above a certain value read from the console.
|
||||
4. Undo the last operation that modified program data. This step can be repeated. The user can undo only those operations made during the current run of the program.
|
||||
|
||||
---
|
||||
### 3. Students
|
||||
Manage a list of students. Each student has an `id` (integer, unique), a `name` (string) and a `group` (positive integer). Provide the following features:
|
||||
1. Add a student. Student data is read from the console.
|
||||
2. Display the list of students.
|
||||
3. Filter the list so that students in a given group (read from the console) are deleted from the list.
|
||||
4. Undo the last operation that modified program data. This step can be repeated. The user can undo only those operations made during the current run of the program.
|
||||
|
||||
---
|
||||
### 4. Books
|
||||
Manage a list of books. Each book has an `isbn` (string, unique), an `author` and a `title` (strings). Provide the following features:
|
||||
1. Add a book. Book data is read from the console.
|
||||
2. Display the list of books.
|
||||
3. Filter the list so that book titles starting with a given word are deleted from the list.
|
||||
4. Undo the last operation that modified program data. This step can be repeated. The user can undo only those operations made during the current run of the program.
|
||||
|
||||
## Bonus possibility (0.1p, deadline week 11)
|
||||
- In addition to the file-based implementations above, implement a repository that uses either a JSON or an XML file for storage (at your choice).
|
||||
|
||||
## Bonus possibility (0.1p, deadline week 11)
|
||||
- Use a `settings.properties` file to decide which of the repository implementations to use. At startup, the program reads this input file and instantiates the correct repository. This allows changing the program's input file format without changing its source code.
|
||||
|
||||
## Bonus possibility (0.1p, deadline week 11)
|
||||
- Implement a database-backed (SQL or NoSQL) repository. Use the database system’s update functionalities properly (don’t rewrite the entire database at each operation).
|
||||
+1
@@ -0,0 +1 @@
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class Expense():
|
||||
def __init__(self,day,money,type_of_expense):
|
||||
self.day=day
|
||||
self.money=money
|
||||
self.type_of_expense=type_of_expense
|
||||
def get_day(self):
|
||||
return self.day
|
||||
def get_money(self):
|
||||
return self.money
|
||||
def get_type_of_expense(self):
|
||||
return self.type_of_expense
|
||||
def set_day(self,day):
|
||||
self.day=day
|
||||
def set_money(self,money):
|
||||
self.money=money
|
||||
def set_type_of_expense(self,type_of_expense):
|
||||
self.type_of_expense=type_of_expense
|
||||
def __str__(self) -> str:
|
||||
return "Day: {} | Money: {} | Type: {} ".format(self.day,self.money,self.type_of_expense)
|
||||
@@ -0,0 +1,25 @@
|
||||
from ui.ui import ui
|
||||
from repositories.textfile import TextFileRepository
|
||||
from repositories.memory import MemoryRepository
|
||||
from repositories.binaryfile import BinaryFileRepository
|
||||
from repositories.jsonfile import JsonFileRepository
|
||||
from repositories.database import DatabaseRepository
|
||||
|
||||
if __name__=="__main__":
|
||||
repos={
|
||||
"textfile":TextFileRepository,
|
||||
"memory":MemoryRepository,
|
||||
"binaryfile":BinaryFileRepository,
|
||||
"jsonfile":JsonFileRepository,
|
||||
"database":DatabaseRepository
|
||||
}
|
||||
repo=None
|
||||
with open("src/settings.properties") as f:
|
||||
for line in f:
|
||||
if line.strip().startswith("repository"):
|
||||
repo=repos.get(line.split("\"",3)[1].strip(),MemoryRepository)()
|
||||
break
|
||||
ui=ui(repo)
|
||||
ui()
|
||||
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
[
|
||||
{
|
||||
"day": 22,
|
||||
"money": 7,
|
||||
"type_of_expense": "Gas"
|
||||
},
|
||||
{
|
||||
"day": 25,
|
||||
"money": 90,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 11,
|
||||
"money": 20,
|
||||
"type_of_expense": "Netflix Subscription"
|
||||
},
|
||||
{
|
||||
"day": 17,
|
||||
"money": 14,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 9,
|
||||
"money": 39,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 27,
|
||||
"money": 4,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 27,
|
||||
"money": 84,
|
||||
"type_of_expense": "Electricity"
|
||||
},
|
||||
{
|
||||
"day": 16,
|
||||
"money": 63,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 20,
|
||||
"money": 69,
|
||||
"type_of_expense": "Electricity"
|
||||
},
|
||||
{
|
||||
"day": 3,
|
||||
"money": 19,
|
||||
"type_of_expense": "Gas"
|
||||
},
|
||||
{
|
||||
"day": 12,
|
||||
"money": 432,
|
||||
"type_of_expense": "gnwrjg"
|
||||
}
|
||||
]
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
25 90 Water
|
||||
11 20 Netflix Subscription
|
||||
9 39 Water
|
||||
27 84 Electricity
|
||||
16 63 Water
|
||||
20 69 Electricity
|
||||
3 19 Gas
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
from repositories.repository import Repository
|
||||
import pickle
|
||||
|
||||
class BinaryFileRepository(Repository):
|
||||
def __init__(self,path="src/memoryfiles/binarymemory.bin"):
|
||||
self.file_path=path
|
||||
self.previous_list_of_expenses=[]
|
||||
with open(self.file_path,"ab") as f:
|
||||
pass
|
||||
def insert_element(self, expense):
|
||||
"""
|
||||
:params:
|
||||
expense - Expense
|
||||
The function appends the current state of the repo to the stack
|
||||
The function takes the expense and dumps it into the file indicated by the file_path as a binary representation
|
||||
"""
|
||||
self.previous_list_of_expenses.append(self.get_elements())
|
||||
with open(self.file_path,"ab") as f:
|
||||
pickle.dump(expense,f)
|
||||
def get_elements(self):
|
||||
list_of_expenses=[]
|
||||
with open(self.file_path,"rb") as f:
|
||||
while True:
|
||||
try:
|
||||
list_of_expenses.append(pickle.load(f))
|
||||
except EOFError:
|
||||
break
|
||||
return list_of_expenses
|
||||
def filter_elements(self, value):
|
||||
self.previous_list_of_expenses.append(self.get_elements())
|
||||
list_of_expenses=[]
|
||||
with open(self.file_path,"rb") as f:
|
||||
while True:
|
||||
try:
|
||||
expense=pickle.load(f)
|
||||
if expense.get_money()<value:
|
||||
continue
|
||||
list_of_expenses.append(expense)
|
||||
except EOFError:
|
||||
break
|
||||
with open(self.file_path,"wb") as f:
|
||||
for expense in list_of_expenses:
|
||||
pickle.dump(expense,f)
|
||||
def undo(self):
|
||||
with open(self.file_path,"wb") as f:
|
||||
for expense in self.previous_list_of_expenses.pop():
|
||||
pickle.dump(expense,f)
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
from pymongo import MongoClient
|
||||
from domain.domain import Expense
|
||||
|
||||
class DatabaseRepository():
|
||||
def __init__(self):
|
||||
self.connection_string="mongodb://DanielCujba:kT99aAmXD2DXXru@ac-72p9ntw-shard-00-00.c6jcmwa.mongodb.net:27017,ac-72p9ntw-shard-00-01.c6jcmwa.mongodb.net:27017,ac-72p9ntw-shard-00-02.c6jcmwa.mongodb.net:27017/?ssl=true&replicaSet=atlas-a0t2fd-shard-0&authSource=admin&retryWrites=true&w=majority"
|
||||
self.client = MongoClient(self.connection_string)
|
||||
self.db = self.client['FP']
|
||||
self.collection=self.db['Expenses']
|
||||
self.undos=[]
|
||||
def insert_element(self,expense):
|
||||
id_inserted=self.collection.insert_one(self.toJson(expense)).inserted_id
|
||||
self.undos.append(id_inserted)
|
||||
def get_elements(self):
|
||||
return [Expense(int(element["day"]),int(element["money"]),element["type_of_expense"]) for element in self.collection.find()]
|
||||
def filter_elements(self,value):
|
||||
self.undos.append([el for el in self.collection.find({"money":{"$lt":value}})])
|
||||
self.collection.delete_many({"money":{"$lt":value}})
|
||||
def undo(self):
|
||||
e=self.undos.pop()
|
||||
if type(e)==list:
|
||||
self.collection.insert_many(e)
|
||||
else:
|
||||
self.collection.delete_one({"_id":e})
|
||||
def toJson(self,expense):
|
||||
return {"day":expense.get_day(),"money":expense.get_money(),"type_of_expense":expense.get_type_of_expense()}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
from repositories.repository import Repository
|
||||
from domain.domain import Expense
|
||||
import json
|
||||
|
||||
class JsonFileRepository(Repository):
|
||||
def __init__(self):
|
||||
self.file_path="src/memoryfiles/jsonmemory.json"
|
||||
self.previous_list_of_expenses=[]
|
||||
with open(self.file_path,"a") as f:
|
||||
pass
|
||||
def insert_element(self, expense):
|
||||
expenses=None
|
||||
with open(self.file_path,"r") as f:
|
||||
expenses=json.load(f)
|
||||
self.previous_list_of_expenses.append(expenses)
|
||||
expenses.append(self.toJson(expense))
|
||||
with open(self.file_path,"w") as f:
|
||||
json.dump(expenses,f,indent=4)
|
||||
def get_elements(self):
|
||||
with open(self.file_path,"r") as f:
|
||||
json_obj=json.load(f)
|
||||
return [Expense(int(expense["day"]),int(expense["money"]),expense["type_of_expense"]) for expense in json_obj]
|
||||
def filter_elements(self, value):
|
||||
expenses=None
|
||||
with open(self.file_path,"r") as f:
|
||||
expenses=json.load(f)
|
||||
self.previous_list_of_expenses.append(expenses)
|
||||
expenses=[expense for expense in expenses if expense["money"]>=value]
|
||||
with open(self.file_path,"w") as f:
|
||||
json.dump(expenses,f,indent=4)
|
||||
def undo(self):
|
||||
with open(self.file_path,"w") as f:
|
||||
json.dump(self.previous_list_of_expenses.pop(),f,indent=4)
|
||||
def toJson(self,expense):
|
||||
return {"day":expense.get_day(),"money":expense.get_money(),"type_of_expense":expense.get_type_of_expense()}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
from repositories.repository import Repository
|
||||
from domain.domain import Expense
|
||||
import random
|
||||
|
||||
class MemoryRepository(Repository):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.list_of_expenses=self.generate_elements(10)
|
||||
self.previous_list_of_expenses=[]
|
||||
def insert_element(self,expense):
|
||||
"""
|
||||
:params:
|
||||
expense - Expense
|
||||
The function takes the current state of the repo and appends it to the stack
|
||||
The function appends the expense to the current list of expenses
|
||||
"""
|
||||
self.previous_list_of_expenses.append(self.list_of_expenses)
|
||||
self.list_of_expenses.append(expense)
|
||||
def get_elements(self):
|
||||
return self.list_of_expenses
|
||||
def filter_elements(self,value):
|
||||
self.previous_list_of_expenses.append(self.list_of_expenses)
|
||||
self.list_of_expenses=list(filter(lambda x:x.get_money()>value,self.list_of_expenses))
|
||||
def generate_elements(self,number)->list:
|
||||
types={1:"Water",2:"Gas",3:"Electricity"}
|
||||
return [Expense(random.randint(1,30),random.randint(1,100),types[random.randint(1,3)]) for _ in range(number)]
|
||||
def undo(self):
|
||||
self.list_of_expenses=self.previous_list_of_expenses.pop()
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
from domain.domain import Expense
|
||||
|
||||
class Repository():
|
||||
def __init__(self):
|
||||
pass
|
||||
def get_elements(self):
|
||||
pass
|
||||
def insert_element(self,expense:Expense):
|
||||
pass
|
||||
def filter_elements(self,value:int):
|
||||
pass
|
||||
def undo():
|
||||
pass
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
from repositories.repository import Repository
|
||||
from domain.domain import Expense
|
||||
|
||||
|
||||
class TextFileRepository(Repository):
|
||||
def __init__(self,path="src/memoryfiles/textmemory.txt"):
|
||||
self.file_path=path
|
||||
self.previous_list_of_expenses=[]
|
||||
with open(self.file_path,"a") as f:
|
||||
pass
|
||||
def insert_element(self, expense):
|
||||
"""
|
||||
:params:
|
||||
expense - Expense
|
||||
The function appends the current state of the repo on the stack
|
||||
The function takes an expense and stores it in the format "{day} {money} {type_of_expense}" in the text file indicated by the file_path
|
||||
"""
|
||||
self.previous_list_of_expenses.append(self.get_elements())
|
||||
with open(self.file_path,"a") as f:
|
||||
f.write("{} {} {}\n".format(expense.get_day(),expense.get_money(),expense.get_type_of_expense()))
|
||||
def get_elements(self):
|
||||
list_of_expenses=[]
|
||||
with open(self.file_path,"r") as f:
|
||||
for line in f:
|
||||
data=line.strip().split(' ',2)
|
||||
list_of_expenses.append(Expense(int(data[0]),int(data[1]),data[2]))
|
||||
return list_of_expenses
|
||||
def filter_elements(self, value):
|
||||
self.previous_list_of_expenses.append(self.get_elements())
|
||||
list_of_expenses=[]
|
||||
with open(self.file_path,'r') as f:
|
||||
for line in f:
|
||||
data=line.strip().split(' ',2)
|
||||
if int(data[1])<value:
|
||||
continue
|
||||
list_of_expenses.append(Expense(int(data[0]),int(data[1]),data[2]))
|
||||
with open(self.file_path,'w') as f:
|
||||
for expense in list_of_expenses:
|
||||
f.write("{} {} {}\n".format(expense.get_day(),expense.get_money(),expense.get_type_of_expense()))
|
||||
def undo(self):
|
||||
with open(self.file_path,'w') as f:
|
||||
for expense in self.previous_list_of_expenses.pop():
|
||||
f.write("{} {} {}\n".format(expense.get_day(),expense.get_money(),expense.get_type_of_expense()))
|
||||
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
from domain.domain import Expense
|
||||
from repositories.repository import Repository
|
||||
|
||||
class Services():
|
||||
def __init__(self,repo:Repository) -> None:
|
||||
self.repo=repo
|
||||
self.undos=0
|
||||
def add_expense(self,day,money,type_of_expense):
|
||||
"""
|
||||
:params:
|
||||
day - integer between 1 and 30
|
||||
money - positive integer
|
||||
type_of_expense - string
|
||||
|
||||
The function creates a new Expense object and call the repository's insert_element method
|
||||
The function increments the undo counter
|
||||
"""
|
||||
expense=Expense(day,money,type_of_expense)
|
||||
self.repo.insert_element(expense)
|
||||
self.undos+=1
|
||||
def display_list(self):
|
||||
return self.repo.get_elements()
|
||||
def filter_list(self,value):
|
||||
self.undos+=1
|
||||
self.repo.filter_elements(value)
|
||||
def undo(self):
|
||||
if self.undos>0:
|
||||
self.undos-=1
|
||||
self.repo.undo()
|
||||
else:
|
||||
raise Exception("No more undos available")
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
repository: "database",
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
[
|
||||
{
|
||||
"day": 22,
|
||||
"money": 7,
|
||||
"type_of_expense": "Gas"
|
||||
},
|
||||
{
|
||||
"day": 25,
|
||||
"money": 90,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 11,
|
||||
"money": 20,
|
||||
"type_of_expense": "Netflix Subscription"
|
||||
},
|
||||
{
|
||||
"day": 17,
|
||||
"money": 14,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 9,
|
||||
"money": 39,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 27,
|
||||
"money": 4,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 27,
|
||||
"money": 84,
|
||||
"type_of_expense": "Electricity"
|
||||
},
|
||||
{
|
||||
"day": 16,
|
||||
"money": 63,
|
||||
"type_of_expense": "Water"
|
||||
},
|
||||
{
|
||||
"day": 20,
|
||||
"money": 69,
|
||||
"type_of_expense": "Electricity"
|
||||
},
|
||||
{
|
||||
"day": 3,
|
||||
"money": 19,
|
||||
"type_of_expense": "Gas"
|
||||
}
|
||||
]
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
22 7 Gas
|
||||
25 90 Water
|
||||
11 20 Netflix Subscription
|
||||
17 14 Water
|
||||
9 39 Water
|
||||
27 4 Water
|
||||
27 84 Electricity
|
||||
16 63 Water
|
||||
20 69 Electricity
|
||||
3 19 Gas
|
||||
@@ -0,0 +1,47 @@
|
||||
from repositories.textfile import TextFileRepository
|
||||
from repositories.memory import MemoryRepository
|
||||
from repositories.binaryfile import BinaryFileRepository
|
||||
from domain.domain import Expense
|
||||
|
||||
import unittest
|
||||
|
||||
class UnitTester(unittest.TestCase):
|
||||
def test_memory_repo(self):
|
||||
repo=MemoryRepository()
|
||||
list_of_expenses=repo.get_elements()
|
||||
e=Expense(10,200,"Gucci")
|
||||
list_of_expenses.append(e)
|
||||
repo.insert_element(e)
|
||||
self.assertEqual(list_of_expenses,repo.get_elements())
|
||||
|
||||
def test_textfile_repo(self):
|
||||
repo=TextFileRepository(path="src/templetes/textmemory.bin")
|
||||
e=Expense(10,200,"Gucci")
|
||||
list_of_expenses=repo.get_elements()
|
||||
repo.insert_element(e)
|
||||
list_of_expenses.append(e)
|
||||
repo_list=repo.get_elements()
|
||||
self.assertEqual(len(list_of_expenses),len(repo_list))
|
||||
for i in range(len(list_of_expenses)):
|
||||
self.assertEqual(list_of_expenses[i].get_day(),repo_list[i].get_day())
|
||||
self.assertEqual(list_of_expenses[i].get_money(),repo_list[i].get_money())
|
||||
self.assertEqual(list_of_expenses[i].get_type_of_expense(),repo_list[i].get_type_of_expense())
|
||||
repo.undo()
|
||||
|
||||
|
||||
def test_binaryfile_repo(self):
|
||||
repo=BinaryFileRepository(path="src/templetes/binarymemory.bin")
|
||||
e=Expense(10,200,"Gucci")
|
||||
list_of_expenses=repo.get_elements()
|
||||
repo.insert_element(e)
|
||||
list_of_expenses.append(e)
|
||||
repo_list=repo.get_elements()
|
||||
self.assertEqual(len(list_of_expenses),len(repo_list))
|
||||
for i in range(len(list_of_expenses)):
|
||||
self.assertEqual(list_of_expenses[i].get_day(),repo_list[i].get_day())
|
||||
self.assertEqual(list_of_expenses[i].get_money(),repo_list[i].get_money())
|
||||
self.assertEqual(list_of_expenses[i].get_type_of_expense(),repo_list[i].get_type_of_expense())
|
||||
repo.undo()
|
||||
|
||||
if __name__=="__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
from services.services import Services
|
||||
import re
|
||||
|
||||
class ui():
|
||||
def __init__(self,repo) -> None:
|
||||
self.repo=repo
|
||||
self.services=Services(self.repo)
|
||||
def __call__(self) -> None:
|
||||
while True:
|
||||
print("""
|
||||
Please select a command:
|
||||
1. Add an expense
|
||||
2. Display the list of expenses
|
||||
3. Filter the list
|
||||
4. Undo
|
||||
0. Exit
|
||||
""")
|
||||
inp=input(">")
|
||||
match inp:
|
||||
case "1":
|
||||
day=input("Please enter the day: ")
|
||||
if not re.fullmatch("\d+",day) or int(day)<1 or int(day)>30:
|
||||
print("Invalid day. Value must be an integer between 1 and 30")
|
||||
continue
|
||||
money=input("Please enter the amount of money: ")
|
||||
if not re.fullmatch("\d+",money):
|
||||
print("Invalid amount of money. Value must be a positive integer")
|
||||
continue
|
||||
type_of_expense=input("Please enter the type of expense: ")
|
||||
self.services.add_expense(int(day),int(money),type_of_expense)
|
||||
case "2":
|
||||
for expense in self.services.display_list():
|
||||
print(expense)
|
||||
case "3":
|
||||
value=input("Please enter a value: ")
|
||||
if not re.fullmatch("\d+",value):
|
||||
print("Invalid number. Value must be a positive integer")
|
||||
continue
|
||||
self.services.filter_list(int(value))
|
||||
print("List filtered")
|
||||
case "4":
|
||||
try:
|
||||
self.services.undo()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
case "0":
|
||||
return
|
||||
case _:
|
||||
print("Invalid Command")
|
||||
Reference in New Issue
Block a user