diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..cf0f4e0 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,4 @@ +[report] +omit= + *tests/* + */python?.?/* \ No newline at end of file diff --git a/.gitignore b/.gitignore index 72364f9..ef8bde7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,11 @@ __pycache__/ *.py[cod] *$py.class - +*.pyc # C extensions *.so + # Distribution / packaging .Python env/ @@ -44,6 +45,7 @@ nosetests.xml coverage.xml *,cover .hypothesis/ +cover/ # Translations *.mo @@ -87,3 +89,105 @@ ENV/ # Rope project settings .ropeproject + + +# Created by https://www.gitignore.io/api/python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so +*.db + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# 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/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +# End of https://www.gitignore.io/api/python \ No newline at end of file diff --git a/FETCH_HEAD b/FETCH_HEAD new file mode 100644 index 0000000..e69de29 diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app.py b/app.py new file mode 100644 index 0000000..1c68fe9 --- /dev/null +++ b/app.py @@ -0,0 +1,193 @@ + +""" +Usage: + amity create_room (O|L) ... + amity delete_rooms(args['']) + amity add_person (F | S) [--wants_accomodation=value] + amity delete_employee(int(args[''])) + amity print_allocations [-output=] + amity reallocate_person + amity print_room + amity print_unallocated [-output=] + amity load_people + amity delete_rooms(args['']) + amity save_state (--database=) + amity load_state + amity (-i | --interactive) + amity (-h | --help | --version) +Options: + -i, --interactive Interactive Mode + -h, --help Show this screen and exit. + -a, --wants_accomodation= Person wants accomodation [default: N] + -d, --database= Save state to specified database [default: amity_db] +""" +import cmd, os, sys +from docopt import docopt, DocoptExit +from pyfiglet import figlet_format +from termcolor import cprint +from views import Amity + + +amity = Amity() + +def docopt_cmd(func): + """ + This decorator is used to simplify the try/except block and pass the result + of the docopt parsing to the called action. + """ + def fn(self, arg): + try: + opt = docopt(fn.__doc__,arg) + except DocoptExit as e: + # The DocoptExit is thrown when the args do not match. + # We print a message to the user and the usage block. + + print('Invalid command!') + print(e) + return + + except SystemExit: + # The SystemExit exception prints the usage for --help + # We do not need to do the print here. + return + return func(self, opt) + + fn.__name__ = func.__name__ + fn.__doc__ = func.__doc__ + fn.__dict__.update(func.__dict__) + return fn + +def intro(): + cprint(figlet_format('Space Allocator', font='slant'), + 'blue', attrs=['bold']) + print("Welcome to Amity! Here is a list of commands to get you started." + + " Type 'help' anytime to access documented commands") + print("\n\n") + cprint(__doc__, 'magenta') + + +class AmitySystem(cmd.Cmd): + prompt = '(Amity) ' + file = None + + @docopt_cmd + def do_create_room(self, args): + """Usage: create_room (O|L) ...""" + room_type = None + if args["O"].upper() == 'O': + room_type = "O" + else: + room_type = "L" + amity.create_room(room_type, args[""]) + + + @docopt_cmd + def do_add_person(self, args): + """ + Usage: add_person (F | S) [--wants_accomodation=value] + """ + if args["F"].upper() == 'F': + category = "F" + else: + category = "S" + first_name = args[""] + last_name = args[""] + amity.add_person(first_name, last_name, category, args["--wants_accomodation"]) + + @docopt_cmd + def do_reallocate_person(self, args): + """Usage: reallocate_person """ + if args[""].isalpha(): + print("person id cannot be string") + return + else: + (amity.reallocate_person(int(args['']), + args[''])) + + @docopt_cmd + def do_save_state(self, args): + """Persists app data into the given db + Usage: save_state (--db_name=sqlite_db) + """ + db = args['--db_name'] + amity.save_state(db) + + @docopt_cmd + def do_print_unallocated(self, args): + """Usage: print_unallocated [--file=text_file]""" + amity.print_unallocated(args['--file']) + + @docopt_cmd + def do_print_allocations(self, args): + """ + Prints all rooms and the people in them. + Usage: print_allocations [--o=filename] + """ + filename = args["--o"] or "" + amity.print_allocations(filename) + + @docopt_cmd + def do_delete_employee(self, args): + """Usage: delete_employee """ + if args[""].isalpha(): + print("person id cannot be string") + return + else: + (amity.delete_employee(int(args['']))) + + @docopt_cmd + def do_delete_rooms(self, args): + """Usage: delete_room """ + amity.delete_rooms(args['']) + + + @docopt_cmd + def do_load_state(self, arg): + """ + Loads data from the specified db into the app. + Usage: load_state + """ + amity.load_state(arg[""]) + + @docopt_cmd + def do_load_people(self, args): + """Usage: load_state """ + amity.load_people(args[""]) + + + @docopt_cmd + def do_print_room(self, args): + """Usage: print_room """ + + room_name = args[""] + amity.print_room(room_name) + @docopt_cmd + def do_clear(self, arg): + """Clears screen""" + + os.system('clear') + + @docopt_cmd + def do_load_people(self, args): + """Usage: load_state """ + amity.load_people(args[""]) + + + + def do_quit(self, arg): + """Quits out of Interactive Mode.""" + + print('Thank you for using Amity. Adios!') + exit() + + +opt = docopt(__doc__, sys.argv[1:]) + +if opt['--interactive']: + os.system('clear') + intro() + AmitySystem().cmdloop() + +print(opt) + + diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/models/model.py b/models/model.py new file mode 100644 index 0000000..045ea7d --- /dev/null +++ b/models/model.py @@ -0,0 +1,53 @@ +import os +import sys +import sqlalchemy + +from sqlalchemy import Column, Integer, String, ForeignKey, Text, Boolean +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship, sessionmaker + +from sqlalchemy import create_engine + + + + +Base = declarative_base() + + +class Person(Base): + """creates a people's table""" + __tablename__ = "People" + + id = Column(Integer, primary_key=True, autoincrement=True, nullable=False) + first_name = Column(String, nullable=False) + last_name = Column(String, nullable=False) + category = Column(String, nullable=False) + wants_accomodation = Column(Boolean) + + def __repr__(self): + return 'first name{} last name{}'.format(self.first_name,self.last_name) + + +class Room(Base): + """creates rooms tables""" + __tablename__ = "Rooms" + + id = Column(Integer, primary_key=True, autoincrement=True) + name = Column(String, nullable=False) + room_type = Column(String, nullable=False) + room_capacity = Column(Integer, nullable=False) + occupants = Column(String,nullable=True) + + +class DatabaseCreator(object): + """creating database connection to object""" + def __init__(self, db_name=None): + self.db_name = db_name + '.db' + self.engine = create_engine('sqlite:///' + self.db_name) + Base.metadata.create_all(self.engine) + session_maker = sessionmaker(bind=self.engine) + self.session = session_maker() + + + + diff --git a/models/persons.py b/models/persons.py new file mode 100644 index 0000000..09142ca --- /dev/null +++ b/models/persons.py @@ -0,0 +1,34 @@ +class Person(object): + def __init__(self, first_name, last_name, wants_accomodation): + self.person_id = id(self) + self.first_name = first_name + self.last_name = last_name + self.wants_accomodation = wants_accomodation + + @property + def full_name(self): + return self.first_name + " " + self.last_name + + def __str__(self): + """To make Staff human readable.""" + return "{} {}".format(self.first_name.upper(), self.last_name.upper()) + + def __repr__(self): + return 'first_name:{}, last_name:{}'.format(self.first_name.upper(),self.last_name.upper()) +class Staff(Person): + + category = "STAFF" + + def __init__(self, first_name, last_name, wants_accomodation): + """Override the init method of Person superclass.""" + super(Staff, self).__init__(first_name, last_name, wants_accomodation) + + +class Fellow(Person): + + category = "FELLOW" + + def __init__(self, first_name, last_name, wants_accomodation): + """Override the init method of Person superclass.""" + super(Fellow, self).__init__(first_name, last_name, wants_accomodation) + diff --git a/models/rooms.py b/models/rooms.py new file mode 100644 index 0000000..c4b77e8 --- /dev/null +++ b/models/rooms.py @@ -0,0 +1,33 @@ +class Room(object): + def __init__(self, room_name): + self.room_id = id(self) + self.room_name = room_name + self.members = [] + self.room_capacity = 0 + + def __str__(self): + """To make the class human readable.""" + return "{}".format(self.room_name.upper()) + +class Office(Room): + + room_type = "OFFICE" + room_capacity = 6 + + def __init__(self, room_name): + """Override the init method of Person superclass.""" + super(Office, self).__init__(room_name) + + +class LivingSpace(Room): + + room_type = "LIVING_SPACE" + room_capacity = 4 + + def __init__(self, room_name): + """Override the init method of Person superclass.""" + super(LivingSpace, self).__init__(room_name) + + + + diff --git a/people.txt b/people.txt new file mode 100644 index 0000000..cf52e4b --- /dev/null +++ b/people.txt @@ -0,0 +1,11 @@ +JONATHAN NGONDI S Y +AHMED YUSUB F N +EPRAHIM KIMANI F N +FAITH DEDE S N +OLUWAFEMI SULE F Y +DOMINIC WALTERS S N +SIMON PATTERSON F Y +MARI LAWRENCE F Y +LEIGH RILEY S N +TANA LOPEZ F Y +KELLY McGUIRE S N diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c8da736 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,24 @@ +appdirs==1.4.3 +appnope==0.1.0 +colorama==0.3.7 +coverage==4.3.4 +decorator==4.0.11 +docopt==0.6.2 +ipdb==0.10.2 +ipython==5.3.0 +ipython-genutils==0.2.0 +nose==1.3.7 +packaging==16.8 +pexpect==4.2.1 +pickleshare==0.7.4 +prompt-toolkit==1.0.14 +ptyprocess==0.5.1 +pyfiglet==0.7.5 +Pygments==2.2.0 +pyparsing==2.2.0 +simplegeneric==0.8.1 +six==1.10.0 +SQLAlchemy==1.1.9 +termcolor==1.1.0 +traitlets==4.3.2 +wcwidth==0.1.7 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/context.py b/tests/context.py new file mode 100644 index 0000000..6e0c72b --- /dev/null +++ b/tests/context.py @@ -0,0 +1,5 @@ +import os +import sys +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + +from views import Amity \ No newline at end of file diff --git a/tests/test_amity.py b/tests/test_amity.py new file mode 100644 index 0000000..476e543 --- /dev/null +++ b/tests/test_amity.py @@ -0,0 +1,151 @@ +import os +import unittest +from .context import Amity +from ..views import Amity +from ..models.rooms import Office +from ..models.rooms import LivingSpace + +class Amitytest(unittest.TestCase): + + def setUp(self): + """To set up test variables.""" + self.amity = Amity() + self.db_name = "faha" + + def tearDown(self): + """To free variables for fresh use in other tests.""" + if os.path.exists(self.db_name + ".db"): + os.remove(self.db_name + ".db") + del self.amity + + def test_create_room(self): + """To test if create_room adds office(s) successfully.""" + self.amity.create_room('O', ['Krypton']) + self.assertIn('KRYPTON', [room.room_name.upper() for room in self.amity.all_rooms]) + + + def test_add_person_adds_fellow_to_list(self): + """To test if fellow is added to fellow list""" + all_fellows = len(self.amity.all_fellows) + 1 + self.amity.add_person('dede','faith','F','N') + self.assertEqual(len(self.amity.all_fellows), all_fellows, msg = "fellow not added") + + def test_add_person_adds_staff_to_list(self): + """To test if staff is added to staff list""" + all_staff = len(self.amity.all_staff) + 1 + self.amity.add_person('ded','fai','S','N') + self.assertEqual(len(self.amity.all_staff), all_staff, msg = "staff not added") + + def test_staff_not_in_accomodation_list(self): + """test that fellow is not entitled to living space""" + self.amity.create_room('L', ['bonivile']) + new_staff = len(self.amity.living_space_allocations['bonivile']) + 1 + self.amity.add_person('ded','fai','S','Y') + self.assertNotEqual(len(self.amity.living_space_allocations['bonivile']), new_staff, msg = "staff cannot be allocated to living space") + + + def test_office_is_created(self): + """Tests offices are created""" + self.amity.create_room('O', ['Krypto']) + self.assertTrue('Krypto' in self.amity.office_allocations.keys()) + + def test_living_space_is_created(self): + """Tests living space are created""" + self.amity.create_room('L', ['Krpto']) + self.assertTrue('Krpto' in self.amity.living_space_allocations.keys()) + + + def test_reallocate_person_to_office(self): + """Test if person reallocated succesfully to office""" + self.amity.create_room('O', ['oculus']) + self.amity.create_room('O', ['Krypto']) + self.amity.reallocate_person('','krypto') + self.assertFalse('dede' in self.amity.office_allocations['oculus'], msg = "person not reallocated succesfully to office") + + + def test_if_person_is_added_to_livingspace(self): + """ Test if person has been added to a living space""" + living_spaces = len(self.amity.living_space_allocations) + 1 + self.amity.create_room('L', ['ruby']) + self.amity.add_person('dedS','gath','F', 'Y') + self.assertEqual(len(self.amity.living_space_allocations), living_spaces, msg = "livingroom is not added succesfully") + + def test_if_person_is_added_to_livingspace(self): + """ Test if person has been added to a living space""" + living_spaces = len(self.amity.living_space_allocations) + 1 + self.amity.create_room('L', ['ruby']) + self.amity.add_person('dedS','gath','F', 'Y') + self.assertEqual(len(self.amity.living_space_allocations), living_spaces, msg = "livingroom is not added succesfully") + + + def test_fellow_does_not_want_accomodation(self): + """To test if fellow does not want accomodation""" + self.amity.add_person('dedeh', 'fagh', 'F', 'N') + self.assertFalse('dedeh' in self.amity.living_space_allocations, msg = 'fellow does not want accomodation') + + def test_add_person_adds_people_to_waiting_list(self): + """To test if add_person caters for excess people. + Adds fellow/staff to office waiting list when offices are full. + """ + self.amity.add_person("Daniel", "Maina","F", "N") + self.amity.add_person("Dan", "Wachira", "F") + self.amity.add_person("Larry", "W", "F", "N") + self.amity.add_person("David", "White", "S", "N") + self.amity.add_person("Xie", "Yuen", "S", "N") + self.amity.add_person("Stella", "Storl", "S", "N") + self.assertFalse('stella' in self.amity.office_allocations, msg = "person not allocated succesfully to office") + + def test_add_person_adds_fellows(self): + """To test if add_person caters for excess people. + Adds fellow to living space waiting list when offices are full. + """ + self.amity.add_person("Daniel", "Maina","F", "Y") + self.amity.add_person("Dan", "Wachira", "F","Y") + self.amity.add_person("Larry", "W", "F", "Y") + self.amity.add_person("David", "White", "Y", "Y") + self.amity.add_person("Xie", "Yuen", "S", "Y") + # self.amity.add_person("Stella", "Storl", "S", "Y") + self.assertFalse('stella' in self.amity.living_space_allocations, msg = "person not reallocated succesfully to living space") + + def test_print_room_does_not_print(self): + """To test if method prints rooms and occupants successfully.""" + room_name = "I don't exist!!!" + self.assertEqual(self.amity.print_room(room_name),None) + + def test_print_unallocated(self): + """"To test print unallocated works""" + self.amity.print_unallocated('') + self.assertFalse('Dan' in self.amity.office_allocations, msg = "person not in accomodation list") + + + def test_print_allocations_prints(self): + """To test if method prints allocations to screen.""" + self.amity.create_room("O", ["Narnia"]) + self.amity.create_room("living_space", ["Python"]) + # create people + self.amity.add_person("Fell", "Dl", "S", "Y") + self.amity.add_person("Fell", "Dl", "S", "Y") + self.amity.add_person("Fello", "Dl", "S", "Y") + + self.assertEqual(self.amity.print_allocations(),"office allocations printed successfully") + + def test_save_state(self): + """ Test that save state , saves people successfully""" + self.amity.create_room("O", ["Narnia"]) + self.amity.create_room("L", ["Python"]) + self.amity.add_person("Fell", "Dl", "S", "Y") + self.amity.add_person("Fell", "Dl", "S", "Y") + self.assertEqual(self.amity.save_state(self.db_name), "successfully saved people") + + def test_load_state(self): + """ Test that the method loads people to the app succesfully""" + self.amity.create_room("O", ["Narnia"]) + self.amity.create_room("L", ["Python"]) + self.amity.add_person("Fell", "Dl", "S", "Y") + self.amity.add_person("Fell", "Dl", "S", "Y") + self.amity.save_state(self.db_name) + self.assertEqual(self.amity.load_state(self.db_name), "Successfully loaded people to the app") + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/views.py b/views.py new file mode 100644 index 0000000..44941bf --- /dev/null +++ b/views.py @@ -0,0 +1,438 @@ +import random +import os.path +from sqlalchemy import create_engine +from sqlalchemy.orm import mapper, sessionmaker +from models.rooms import Office, LivingSpace +from models.persons import Fellow, Staff +from models.model import (Base, Room, Person, DatabaseCreator) +from models.model import Base +from colorama import init +init(autoreset=True) +from termcolor import colored +from colorama import Fore, Back, Style + + +class Amity(object): + """all_staff - is a list of staff objects names + + all_fellows - list of fellows object names + + office_allocations - dictionary with room names as keys and occupants list as It's value + + living_spaces_allocations - dictionary with room names as keys and occupants list as It's value + + all_people - has people's names + + living_spaces_waiting_list - Has people with no office spaces + + office_spaces_waiting_list - Has people with no living space spaces""" + def __init__(self): + """initialize the class objects""" + self.all_staff = [] + self.all_fellows = [] + self.all_rooms = [] + self.office_allocations = {} + self.living_space_allocations = {} + self.all_people = [] + self.living_spaces_waiting_list = [] + self.office_spaces_waiting_list = [] + + def create_room(self, room_type, list_of_rooms): + + """creates a specified room""" + for name in list_of_rooms: + if name.upper() in [room.room_name.upper() for room in self.all_rooms]: + print(Fore.RED + "sorry! the room {} already exist.".format(name.upper())) + else: + if room_type.upper() == 'O': + office = Office(name) + self.all_rooms.append(office) + self.office_allocations[office.room_name] = [] + print(Fore.GREEN + "Office {} successfully created.".format(office.room_name.upper())) + elif room_type.upper() == 'L': + living_space = LivingSpace(name) + self.all_rooms.append(living_space) + self.living_space_allocations[living_space.room_name] = [] + print(Fore.GREEN + "Living space {} successfully created.".format(living_space.room_name.upper())) + else: + print(Fore.YELLOW + "please specify the room_type you would like to create.") + + def generate_random_office_spaces(self): + """Generates random office""" + offices = [room for room in self.all_rooms if room.room_type == "OFFICE"] + available_offices = [] + for office in offices: + if len(self.office_allocations[office.room_name]) < 6: + available_offices.append(office) + if available_offices: + selected_room = random.choice(available_offices) + else: + selected_room = None + return selected_room + + def generate_random_living_spaces(self): + """Generates random living spaces""" + living_spaces = [room for room in self.all_rooms if room.room_type == "LIVING_SPACE"] + available_living_space = [] + for living_space in living_spaces: + if len(self.living_space_allocations[living_space.room_name]) < 4: + available_living_space.append(living_space) + if available_living_space: + selected_room = random.choice(available_living_space) + else: + selected_room = None + return selected_room + + + def add_person(self, first_name, last_name, category, wants_accomodation='N'): + """Adds person to self and randomly allocates the person""" + if category == "F" : + # create fellow object and adds them to fellow list + fellow = Fellow(first_name, last_name, wants_accomodation) + self.all_people.append(fellow) + self.all_fellows.append(fellow) + allocated_office = self.generate_random_office_spaces() + print(fellow.person_id) + if allocated_office: + allocated_office.members.append(fellow) + # if random room selected + self.office_allocations[allocated_office.room_name] = allocated_office.members + print(Fore.GREEN +"You have allocated {} successfully to office {}".format(fellow.first_name,allocated_office.room_name)) + else: + self.office_spaces_waiting_list.append(fellow) + print(Fore.YELLOW + "Sorry, no space available {} has been added to the office waiting list".format(fellow.first_name)) + + if wants_accomodation == 'Y': + # add living space + allocated_living_space = self.generate_random_living_spaces() + if allocated_living_space: + allocated_living_space.members.append(fellow) + self.living_space_allocations[allocated_living_space.room_name] = allocated_living_space.members + print(Fore.GREEN+"You have allocated {} successfully to living space {} ".format(fellow.first_name, allocated_living_space.room_name)) + else: + self.living_spaces_waiting_list.append(fellow) + print(Fore.YELLOW+"Sorry, no space available {} has been added to the living space waiting list".format(fellow.first_name)) + + elif category == "S" : + + # create fellow object and adds them to fellow list + # create staff object and adds them to list + staff = Staff(first_name, last_name, wants_accomodation) + self.all_staff.append(staff) + self.all_people.append(staff) + allocated_office = self.generate_random_office_spaces() + print(staff.person_id) + if allocated_office: + allocated_office.members.append(staff) + # if random room selected + self.office_allocations[allocated_office.room_name] = allocated_office.members + print(Fore.GREEN+"You have allocated {} successfully to office {}.".format(staff.first_name,allocated_office.room_name)) + else: + self.office_spaces_waiting_list.append(staff) + print(Fore.YELLOW+"Sorry, no space available {} has been added to the waiting list".format(staff.first_name)) + + if wants_accomodation == 'Y': + print(Fore.RED + "Sorry! staff is not entitled to a living space") + return "staff cannot be allocated to living space" + + + def get_person(self, person_id): + """To return person object given person id.""" + person_object = None + + if self.all_people: + for person in self.all_people: + if person_id == person.person_id: + person_object = person + if person_object: + return person_object + else: + return "Invalid person id" + else: + # if all_people has no object + return "There are no people in the system." + + def get_room(self, room_name): + """To return room object given room name""" + if self.all_rooms: + for room in self.all_rooms: + if room.room_name.upper() == room_name.upper(): + return room + return ("Room does not exist") + + def delete_from_allocations(self, id, allocation_obj): + for room in allocation_obj: + for person in allocation_obj[room]: + if person.person_id == id: + allocation_obj[room].remove(person) + + def check_in_allocations(self, id, allocation_obj): + for room in allocation_obj: + for person in allocation_obj[room]: + if person.person_id == id: + return True + return False + + def get_person_room(self, person_id, room_type): + """To return currently allocated room given a valid person id""" + result = None + if room_type is "O": + for room in self.office_allocations.keys(): + if (person_id in [person.person_id for person in self.office_allocations[room]]): + # returns room object if person_id match is found + result = room + elif room_type is "L": + for room in list(self.living_space_allocations.keys()): + if (person_id in [person.person_id for person in self.living_space_allocations[room]]): + result = room + + if result: + return result + else: + return "Person not allocated to room" + + def reallocate_person(self, person_id, new_room_name): + """ moves person from one room to another room""" + # gets person object from person id + person_object = self.get_person(person_id) + if person_object == "Invalid person id": + # prints id does not exist + print(person_object) + return person_object + elif person_object == "There are no people in the system.": + print(Fore.RED + "Sorry!There are no people in the system. Add person(s) first to the system, then reallocate") + return person_object + else: + new_room_object = self.get_room(new_room_name) + if new_room_object == "Room does not exist": + print(Fore.RED + "Room name does not exist") + return "Room name does not exist" + else: + if person_object.category == "STAFF" and new_room_object.room_type == "LIVING_SPACE": + print(Fore.YELLOW + "Cannot reallocate staff to living space.") + return "Cannot reallocate staff to living space." + elif new_room_object.room_type == "OFFICE": + current_room = self.get_person_room(person_id, "O") + if current_room == new_room_object.room_name: + # if person has no office + print(Fore.YELLOW + "{} is already allocated to {}".format(person_object.first_name, new_room_object.room_name)) + return "person ca not be reallocated to a room the person is allocated to" + elif current_room == "Person not allocated to room": + # if person has no office + print(Fore.YELLOW + "{} has no current office space,hence you cannot reallocate".format(person_object.first_name)) + return "person has no current office space, hence canot reallocate" + elif current_room == new_room_object: + print(Fore.YELLOW + "Cannot reallocate a person to the same room.") + return "Cannot reallocate to same room." + else: + # remove from current office + self.office_allocations[current_room].remove(person_object) + # append to new room + if len(self.office_allocations[new_room_object.room_name]) < 6: + self.office_allocations[new_room_object.room_name].append(person_object) + print(Fore.GREEN + "{} {} has been reallocated from office {} to {}".format(person_object.first_name,person_object.last_name, current_room,new_room_object)) + return "Has been reallocated from office" + else: + print(Fore.YELLOW + "Sorry!, the room is full") + + def delete_employee(self, person_id): + person_object = self.get_person(person_id) + if person_object == "Invalid person id": + # prints id does not exist + print(person_object) + return person_object + else: + if person_object in self.all_fellows: + self.all_fellows.remove(person_object) + + if person_object in self.all_staff: + self.all_staff.remove(person_object) + + if person_object in self.all_people: + self.all_people.remove(person_object) + + # delete name name if name exists + if person_object in self.office_spaces_waiting_list: + self.office_spaces_waiting_list.remove(person_object) + print(Fore.GREEN + "{} deleted from unallocated space".format(person_object.first_name,person_object.last_name)) + + if self.check_in_allocations(person_id, self.office_allocations): + self.delete_from_allocations(person_id, self.office_allocations) + print(Fore.GREEN + "{} deleted from office space".format(person_object.first_name,person_object.last_name)) + + if self.check_in_allocations(person_id, self.living_space_allocations): + self.delete_from_allocations(person_id, self.living_space_allocations) + print(Fore.GREEN +"{} {} deleted from living space".format(person_object.first_name, person_object.last_name)) + + if person_object in self.living_spaces_waiting_list: + self.living_spaces_waiting_list.remove(person_object) + print(Fore.GREEN + "{} {} deleted from unallocated living space".format(person_object.first_name, person_object.last_name)) + + print(Fore.GREEN + "Employee {} {} has been deleted from the system".format(person_object.first_name, person_object.last_name)) + return "employee deleted" + + def delete_rooms(self, room_name): + room_name = room_name.upper() + room_object = self.get_room(room_name) + if room_object == "Room does not exist": + print("Room does not exist") + + for room_object in self.all_rooms: + if room_object.room_name == room_name: + self.all_rooms.remove(room_object) + print(Fore.GREEN + "{} has been deleted".format(room_object.room_name)) + + if room_name in self.office_allocations.keys(): + del self.office_allocations[room_name] + + if room_name in self.living_space_allocations.keys(): + del self.living_space_allocations[room_name] + + def load_people(self, filename): + """loads people from a txt file to the app""" + try: + with open (filename, 'r') as people_file: + for person_details in people_file: + details = person_details.rstrip().split() + accomodate = details[3] if len(details) == 4 else "N" + self.add_person(details[0], details[1], details[2], accomodate) + print(Fore.GREEN + "Successfully loaded {} to the app.".format(details[0])) + return "Successfully finished loading people" + except FileNotFoundError: + print(Fore.RED + 'file not found!') + return ('file not found') + + + def print_allocations(self,file_name=None): + """Prints a list of allocations onto the screen""" + print(Fore.MAGENTA + "=" * 30 + "\n" + "Office Allocations\n" + "=" *30) + for room in self.office_allocations.keys(): + if room != "None": + print ("\n" +Fore.BLUE + room.upper()) + for person in self.office_allocations[room]: + print(person.person_id, person) + + print(Fore.MAGENTA + "=" * 30 + "\n" + "Living spaces Allocations\n" + "=" *30) + for room in self.living_space_allocations.keys(): + if room != "None": + print ("\n" + Fore.BLUE +room.upper() ) + for person in self.living_space_allocations[room]: + print(person.person_id, person ) + + if file_name: + nfile = open(file_name + ".txt", "a") + for room in self.office_allocations.keys(): + if room != "None": + nfile.write("\n"+ room.upper() + "\n"+ "-" *30+ "\n") + for person in self.office_allocations[room]: + nfile.write(person.full_name.upper()+"\n") + for room in self.living_space_allocations.keys(): + if room != "None": + nfile.write("\n" + room.upper() + "\n" + "-" * 30+ "\n") + for person in self.living_space_allocations[room]: + nfile.write(person.full_name.upper()+"\n") + print("{}.txt has been written".format(file_name)) + return "Successfully written the file" + return "office allocations printed successfully" + + + + def print_unallocated(self, file_name=None): + """Prints all people not allocated""" + print(Fore.MAGENTA + "=" * 30 + "\n" + "People in office allocation waiting list\n" + "=" * 30) + unallocated_offices = self.office_spaces_waiting_list + unallocated_living_spaces = self.living_spaces_waiting_list + for person in unallocated_offices: + print(person.person_id, person or "None") + print(Fore.MAGENTA + "=" * 30 + "\n" + "People in Living Space waiting list\n" + "=" * 30) + for person in unallocated_living_spaces: + print(person.person_id, person or "None") + # return person or "None" + + if file_name: + file = open(file_name + ".txt", "a") + file.write("=" * 30 + "\n" + "Unallocated people\n" + "=" * 30) + for person in unallocated_offices: + file.write("\n" + person.full_name or "None") + for person in unallocated_living_spaces: + file.write("\n" + person.full_name or "None") + print(Fore.GREEN + "{}.txt written succesfully".format(file_name)) + + + def print_room(self, room_name): + """ Prints the names of all the people in room_name on the + screen.""" + offices = [room for room in self.office_allocations if room != "None"] + living_spaces = [room for room in self.living_space_allocations if room != "None"] + if not offices or not living_spaces: + print(Fore.YELLOW + "There are no rooms existing in the system.") + else: + if room_name not in offices and room_name not in living_spaces: + print(Fore.RED + "sorry! the room does not exist") + return "sorry! the room does not exist" + else: + print(Fore.MAGENTA + "=" * 30 + "\n Members \n" + "=" * 30) + if room_name in offices: + for person in self.office_allocations[room_name]: + print(person) + elif room_name in living_spaces: + for person in self.living_space_allocations[room_name]: + print(person) + + def load_state(self, db_name): + """loads people to the app""" + # connect to the db provided + if os.path.exists(db_name + ".db"): + self.engine = create_engine('sqlite:///' + db_name + ".db") + Base.metadata.bind = self.engine + # query all rooms and people + SessionMaker = sessionmaker(bind=self.engine) + session = SessionMaker() + people = session.query(Person).all() + rooms = session.query(Room).all() + # save them to the current Amity instance + for room in rooms: + self.create_room(room.room_type[0],[room.name]) + for person in people: + self.add_person(person.first_name, person.last_name, person.category[0], 'Y' if person.wants_accomodation else 'N') + print(Fore.GREEN + "Data from {} loaded to the app.".format(db_name)) + return "Successfully loaded people to the app" + else: + print(Fore.RED + "sorry db does not exist") + + def save_state(self, db_name): + """Persists app data into the given db""" + # create a db called db_name + self.db_name = db_name + '.db' + self.engine = create_engine('sqlite:///' + self.db_name) + Base.metadata.bind = self.engine + + # create people and rooms tables. + Base.metadata.create_all() + # create session + SessionMaker = sessionmaker(bind=self.engine) + self.session = SessionMaker() + + # save rooms + rooms = [] + for room in self.all_rooms: + current_occupants = '' + for member in room.members: + current_occupants += member.full_name + new_room = Room(id=room.room_id, name=room.room_name.upper(), room_type=room.room_type, room_capacity=room.room_capacity, occupants=current_occupants) + rooms.append(new_room) + self.session.add_all(rooms) + self.session.commit() + # save people's data + people = [] + for person in self.all_people: + wants_accomodation = True if person.wants_accomodation == "Y" else False + print(person, person.wants_accomodation) + new_person = Person(id=person.person_id, first_name=person.first_name, last_name=person.last_name, category=person.category, wants_accomodation=wants_accomodation) + people.append(new_person) + # self.session.update(new_person) + self.session.add_all(people) + self.session.commit() + print(Fore.GREEN +"Successfully saved people") + return("successfully saved people") +