diff --git a/Day 4 Homework.md b/Day 4 Homework.md new file mode 100644 index 0000000..2b124e6 --- /dev/null +++ b/Day 4 Homework.md @@ -0,0 +1,205 @@ +As a recap, we've talked about how numbers work, how characters work, how characters are combined into text via lexers and parsers, and how numbers and text are combined via operators in custom classes: + +``` +Numbers ------------------------> Operators -> ? +Characters --(Lexers/Parsers) --> Operators -> ? +``` + +Today's homework is to think about how to design classes, or what the industry calls "object-oriented design." You have to be careful to minimize complexity when designing public interfaces and APIs to your code, otherwise this happens: + +https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition/blob/uinverse/src/main/java/com/seriouscompany/business/java/fizzbuzz/packagenamingpackage/impl/loop/LoopCondition.java + +Remember fizzbuzz? This is a satirical version built using every object-oriented pattern in the book. There is an actual book on the subject, which is widely respected throughout the industry, and in some cases misused to overcomplicate code: + +https://en.wikipedia.org/wiki/Design_Patterns + +The assignment for today is to think about some everyday thing you interact with, such as an elevator, a pet, or anything which has tangible and measurable *inputs* and *outputs*. There are three files to look at in the `simulation` directory in this repository: + +* SimulationRunner: a program to run simulation classes. +* Simulation: the interface definition for a simulation. +* HotdogSimulation: a class simulating a hot dog. + +Design two versions of this object with the following shared criteria: + +* Define the start, stop, tick, get_uses, and use methods. +* Ensure that the object expires when a reasonable number of ticks have passed. + +One version of the object should be very simple, such as the hot dog example. + +The other version of the object should be overly complicated, with verbs such as `weigh` to get its mass, `mood` to get its mood, `price_tag` to have it return its estimated value, and `go_to_moon` to send the object to the moon (in the case of the pet, it would probably explode and `use()` should return `False`). Try to define at least 20 different verbs you could use on the object, with associated instance variables to track its state so the verbs interact correctly. For example, a `throw` verb on a hot dog should reduce its mass, because some of its condiments will end up on the target. + +Although it would be preferred to create a Python file that can be run under the simulator, a text specification is also acceptable. The important thing is for the object to have a consistent model of its state which accurately represents what would happen in real life when methods (verbs) are applied to it. + +``` +class Toaster: + def __init__(self): + self.ticks_left = 10 + self.is_on = False + + def get_uses(self): + return { + 'toast': "Put bread in the toaster to make toast." + } + + def start(self): + print("Toaster started.") + + def use(self, *args, **kwargs): + if 'toast' in args: + if not self.is_on: + print("Turn the toaster on first!🔌") + return True + + print("Toasting...") + self.ticks_left -= 1 + if self.ticks_left == 0: + print("Toasting complete! 🍞") + return False + + return True + + def tick(self): + return True + + def stop(self): + print("Toaster stopped. ⏸") +``` + +``` +class AdvancedToaster: + def __init__(self): + self.ticks_left = 10 + self.is_on = False + self.toastiness = 0 + self.bread_count = 0 + self.crumb_tray = [] + self.temperature = None + self.weight = 1.5 # kg + self.voltage = 120 # V + self.power = 750 # W + self.materials = ['stainless steel', 'plastic', 'copper'] + self.dimensions = {'length': 30, 'width': 20, 'height': 25} # cm + self.color = 'silver' + self.price = 50 # USD + + def get_uses(self): + return { + 'turn_on': "Turn on the toaster.", + 'turn_off': "Turn off the toaster.", + 'insert_bread': "Insert bread into the toaster.", + 'eject_bread': "Eject bread from the toaster.", + 'increase_toastiness': "Increase the level of toastiness.", + 'decrease_toastiness': "Decrease the level of toastiness.", + 'add_bread': "Add a slice of bread to the toaster.", + 'remove_bread': "Remove a slice of bread from the toaster.", + 'toast': "Toast the bread in the toaster.", + 'empty_crumb_tray': "Empty the crumb tray.", + 'weigh': "Weigh the toaster.", + 'measure_voltage': "Measure the voltage of the toaster.", + 'measure_power': "Measure the power of the toaster.", + 'get_materials': "Get the materials the toaster is made of.", + 'get_dimensions': "Get the dimensions of the toaster.", + 'get_color': "Get the color of the toaster.", + 'get_price_tag': "Get the estimated value of the toaster." + } + + def start(self): + print("Toaster started.") + + def set_temperature(self, temperature): + self.temperature = temperature + print(f"Toaster temperature set to {temperature} degrees Celsius.") + + def get_temperature(self): + if self.temperature is not None: + print(f"Toaster temperature is {self.temperature} degrees Celsius.") + else: + print("Toaster temperature has not been set yet.") + + def use(self, *args, **kwargs): + if 'turn_on' in args: + self.is_on = True + print("Toaster turned on.") + + elif 'turn_off' in args: + self.is_on = False + print("Toaster turned off.") + + elif 'insert_bread' in args: + if not self.is_on: + print("Turn the toaster on first!") + return True + + if self.bread_count > 2: + print("Too many bread slices! Maximum is 2.") + return True + + self.bread_count += 1 + print(f"{self.bread_count} bread slice{'s' if self.bread_count > 1 else ''} inserted.") + + elif 'eject_bread' in args: + if self.bread_count == 0: + print("No bread slices to eject.") + return True + + self.bread_count -= 1 + print("Bread slice ejected.") + + elif 'decrease_toastiness' in args: + if self.toastiness > 0: + self.toastiness -= 1 + print(f"Toastiness decreased to {self.toastiness}.") + + elif 'add_bread' in args: + if self.bread_count < 2: + self.bread_count += 1 + print(f"{self.bread_count} slice(s) of bread added to the toaster.") + + elif 'remove_bread' in args: + if self.bread_count > 0: + self.bread_count -= 1 + print(f"{self.bread_count} slice(s) of bread removed from the toaster.") + + elif 'toast' in args: + if self.is_on and self.bread_count > 0: + print("Toasting bread...") + for i in range(self.toastiness): + print("Tick...") + print("Bread toasted!") + self.bread_count -= 1 + elif not self.is_on: + print("Toaster is not turned on.") + elif self.bread_count == 0: + print("Toaster does not contain any bread.") + else: + print(f"DEBUG:Invalid use of the toaster.") + return False + + elif 'empty_crumb_tray' in args: + self.crumb_tray = [] + print("Crumb tray emptied.") + + def weigh(self): + print(f"The weight of the toaster is {self.weight} kg.") + + def measure_voltage(self): + # Method to measure the voltage of the toaster + print(f"The voltage of the toaster is {self.voltage} V.") + + def measure_power(self): + # Method to measure the power of the toaster + print(f"The power of the toaster is {self.power} W.") + + + defer get_materials(self): + print(f"The toaster is made of: {', '.join(self.materials)}.") + + defer get_dimensions(self): + print(f"The dimensions of the toaster are: {self.dimensions['length']} cm x {self.dimensions['width']} cm x {self.dimensions['height']} cm.") + + defer get_color(self): + print(f"The color of the toaster is {self.color}.") + + defer get_price_tag(self): + print(f"The estimated value of the toaster is {self.price_tag}.") +```