1+ from dataclasses import dataclass
2+ from enum import Enum
3+ from typing import List , Dict
4+ import sys
5+
6+ class OperatingSystem (Enum ):
7+ MACOS = "macOS"
8+ ARCH = "Arch Linux"
9+ UBUNTU = "Ubuntu"
10+
11+
12+ @dataclass (frozen = True )
13+ class Person :
14+ name : str
15+ age : int
16+ # Sorted in order of preference, most preferred is first.
17+ preferred_operating_system : List [OperatingSystem ]
18+
19+
20+ @dataclass (frozen = True )
21+ class Laptop :
22+ id : int
23+ manufacturer : str
24+ model : str
25+ screen_size_in_inches : float
26+ operating_system : OperatingSystem
27+
28+
29+ #add new person with preferences
30+ def create_a_new_person () -> Person :
31+ add_name = input ("What is your name? \n " ).title ()
32+ if not add_name or add_name == "" or len (add_name ) > 50 :
33+ print ("Enter a valid name." , file = sys .stderr )
34+ sys .exit (1 )
35+
36+ add_age = int (input ("What is your age? \n " ))
37+ if add_age < 0 or add_age > 100 :
38+ print ("Enter a valid age." , file = sys .stderr )
39+ sys .exit (1 )
40+
41+ #get strings to rank
42+ print ("Select your 3 favourite operating systems. Type 'macOS', 'Arch Linux' or 'Ubuntu'." )
43+ os1_str = input ("What is your fav os?: \n " )
44+ os2_str = input ("What is your second fav os?: \n " )
45+ os3_str = input ("What is your third fav os?: \n " )
46+
47+ #chamnge here to enums by using constructor from enums os
48+ # choice1 = OperatingSystem(os1_str)
49+ # choice2 = OperatingSystem(os2_str)
50+ # choice3 = OperatingSystem(os3_str)
51+ # user_oss_ranked_as_enums = [choice1, choice2, choice3]
52+ # or shorter
53+ #here i have strings converted to enums so can compare
54+ user_oss_ranked_as_enums = [
55+ OperatingSystem (os1_str ),
56+ OperatingSystem (os2_str ),
57+ OperatingSystem (os3_str )
58+ ]
59+
60+ # grab by value of enum str not whole obj like compared in logic[0]
61+ print (
62+ f"Hi { add_name } , your choices were saved and your favourite os is { user_oss_ranked_as_enums [0 ].value } " )
63+
64+ return Person (name = add_name , age = add_age , preferred_operating_system = user_oss_ranked_as_enums )
65+
66+
67+ laptops = [
68+ Laptop (id = 1 , manufacturer = "Dell" , model = "XPS" , screen_size_in_inches = 13 , operating_system = OperatingSystem .ARCH ),
69+ Laptop (id = 2 , manufacturer = "Dell" , model = "XPS" , screen_size_in_inches = 15 , operating_system = OperatingSystem .UBUNTU ),
70+ Laptop (id = 3 , manufacturer = "Dell" , model = "XPS" , screen_size_in_inches = 15 , operating_system = OperatingSystem .UBUNTU ),
71+ Laptop (id = 4 , manufacturer = "Apple" , model = "macBook" , screen_size_in_inches = 13 , operating_system = OperatingSystem .MACOS ),
72+ ]
73+
74+ #here i need to refactor i was changing logic from coursework
75+ #return laptop obj and happiness value
76+ def link_laptops_and_happiness (laptops : List [Laptop ], person : Person ):
77+
78+ for laptop in laptops :
79+ #to comapre to if selected fav sanes 0 = first choice
80+ if laptop .operating_system == person .preferred_operating_system [0 ]:
81+ return laptop , 0
82+
83+ for laptop in laptops :
84+ if laptop .operating_system == person .preferred_operating_system [1 ]:
85+ return laptop , 1
86+
87+ for laptop in laptops :
88+ if laptop .operating_system == person .preferred_operating_system [2 ]:
89+ return laptop , 2
90+
91+ #in case laptop not on list
92+ non_existent_laptop = Laptop (
93+ id = 100 ,
94+ manufacturer = "Does not exist" ,
95+ model = "no laptop" ,
96+ screen_size_in_inches = 0.0 ,
97+ operating_system = OperatingSystem .MACOS
98+ )
99+ return non_existent_laptop , 100
100+
101+ #this is to sort people
102+ def compare_count_of_choices_and_os (person : Person , available_laptops : List [Laptop ]) -> int :
103+ #from enum for fav
104+ fav = person .preferred_operating_system [0 ]
105+
106+ count_of_available = 0
107+ for laptop in available_laptops :
108+ if laptop .operating_system == fav :
109+ count_of_available += 1
110+
111+ return count_of_available
112+
113+
114+ def allocate_laptops (people : List [Person ], laptops : List [Laptop ]) -> Dict [Person , Laptop ]:
115+ print (f"Welcome to the laptop allocator" )
116+
117+ #store final
118+ students_with_laptops_assigned = {}
119+ available_laptops = list (laptops )
120+
121+ #minimise unhappiness so ones with least available laptops go first
122+ people .sort (key = lambda p : compare_count_of_choices_and_os (p , available_laptops ))
123+
124+ for person_being_checked in people :
125+
126+ laptop , sadness = link_laptops_and_happiness (available_laptops , person_being_checked )
127+ #non listed os
128+ if laptop .id != 100 :
129+ students_with_laptops_assigned [person_being_checked ] = laptop
130+ #remove from available to allocate
131+ available_laptops .remove (laptop )
132+ print (f"Allocated { laptop .model } to { person_being_checked .name } with a sadness score of { sadness } ." )
133+ else :
134+ #if no laptop on list give them popped one
135+ remaining = available_laptops .pop (0 )
136+ students_with_laptops_assigned [person_being_checked ] = remaining
137+ print (f"Allocated non-matching { remaining .model } to { person_being_checked .name } with a sadness score of 100)" )
138+
139+ return students_with_laptops_assigned
140+
141+
142+
143+ def main ():
144+ # add people
145+ people = []
146+ for i in range (4 ):
147+ people .append (create_a_new_person ())
148+
149+ final_dict = allocate_laptops (people , laptops )
150+
151+ print ("All people have been assigned laptops." )
152+
153+ main ()
0 commit comments