Typo
This commit is contained in:
268
CS1527/assessment-1/assessment1.py
Normal file
268
CS1527/assessment-1/assessment1.py
Normal file
@@ -0,0 +1,268 @@
|
||||
# The following is a template of the design.
|
||||
# you will need to complete the definition of each class, including class attributes,
|
||||
# instance attributes, and instance methods. However, please do not change the class
|
||||
# names provided below.
|
||||
|
||||
# IMPORTANT: In order to get your program pass the test, make sure your class constructors
|
||||
# use exactly the same parameter names as in the test examples provided at the end of this template.
|
||||
|
||||
# ================Your codes start here=============
|
||||
# Notes:
|
||||
# - Should a motorboat (or eboat) really *be* an engine?
|
||||
# - Why are the keyword arguments abbreviated?
|
||||
|
||||
|
||||
def class_bases(cls):
|
||||
"""Generator of the base classes of a class (including the given class).
|
||||
|
||||
Depth-first, post-order, may yield duplicates
|
||||
"""
|
||||
for cls_ in cls.__bases__:
|
||||
yield from class_bases(cls_)
|
||||
yield cls
|
||||
|
||||
|
||||
def field_repr(obj) -> str:
|
||||
"""String representation of an object
|
||||
|
||||
Lists fields with type annotations in object's class and superclasses"""
|
||||
classes = class_bases(obj.__class__)
|
||||
attrs = (
|
||||
attr for cls in classes for attr in getattr(cls, "__annotations__", {}).keys()
|
||||
)
|
||||
attrs_vals = ",".join(f"{attr}={getattr(obj, attr, None)!r}" for attr in attrs)
|
||||
return f"{obj.__class__.__name__}({attrs_vals})"
|
||||
|
||||
|
||||
class Boat:
|
||||
"""A boat
|
||||
|
||||
Attributes:
|
||||
- `color`: color of boat
|
||||
- `brand`: boat brand
|
||||
- `year`: manufacture year
|
||||
|
||||
Class Attributes:
|
||||
- `all_boats`: a list of all boats ever constructed
|
||||
"""
|
||||
|
||||
all_boats = []
|
||||
|
||||
color: str
|
||||
brand: str
|
||||
year: int
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
co: str,
|
||||
br: str,
|
||||
yr: int,
|
||||
**kwargs,
|
||||
):
|
||||
"""Initialize a `Boat`.
|
||||
|
||||
Takes keyword-only arguments `co` (color), `br` (brand), and `yr` (year)
|
||||
as described in class docstring
|
||||
"""
|
||||
Boat.all_boats.append(self)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.color = co
|
||||
self.brand = br
|
||||
self.year = yr
|
||||
|
||||
def __str__(self):
|
||||
return field_repr(self)
|
||||
|
||||
def get_boat_age(self, current_year: int) -> int:
|
||||
"""Get the age of this boat given the current year"""
|
||||
return current_year - self.year
|
||||
|
||||
|
||||
class Engine:
|
||||
"""An Engine
|
||||
|
||||
Attributes:
|
||||
- `tech`: Technology used by the engine.
|
||||
Either 'gas' or 'electric'
|
||||
- `engine_speed`: maximum speed in miles per hour
|
||||
determined by `tech` - gas engines have speed 80mph, electric 20mph
|
||||
|
||||
Class Attributes:
|
||||
- `speeds`: mapping of engine tech to speed
|
||||
"""
|
||||
|
||||
speeds = {"gas": 80, "electric": 20}
|
||||
|
||||
engine_speed: float
|
||||
tech: str
|
||||
|
||||
def __init__(self, *, tech: str, **kwargs):
|
||||
"""Initialize an `Engine`
|
||||
|
||||
Takes keyword-only argument `tech` (see class docstring)
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.tech = tech
|
||||
self.engine_speed = Engine.speeds[tech]
|
||||
|
||||
def __str__(self):
|
||||
return field_repr(self)
|
||||
|
||||
def get_engine_speed(self) -> float:
|
||||
"""Get the engine speed for this engine in miles per hour"""
|
||||
return self.engine_speed
|
||||
|
||||
|
||||
class Motorboat(Boat, Engine):
|
||||
"""A Motorboat
|
||||
|
||||
Always uses 'gas' engine tech
|
||||
Attributes:
|
||||
- `fuel_level`: remaining level of fuel in gallons
|
||||
- `fuel_efficiency`: range with a certain amount of fuel in miles per gallon
|
||||
"""
|
||||
|
||||
fuel_level: float
|
||||
fuel_efficiency: float
|
||||
|
||||
def __init__(self, *, fl: float, fe: float, **kwargs):
|
||||
"""Initialize a `Motorboat`
|
||||
|
||||
Takes keyword-only arguments `fl` (fuel level) and `fe` (fuel efficiency)
|
||||
as described in class docstring, in addition to the arguments described in `Boat`
|
||||
"""
|
||||
super().__init__(**kwargs, tech="gas")
|
||||
|
||||
self.fuel_level = fl
|
||||
self.fuel_efficiency = fe
|
||||
|
||||
def get_max_speed(self) -> float:
|
||||
"""Get the max speed of the motorboat"""
|
||||
return self.engine_speed
|
||||
|
||||
def cal_travel_time(self, distance: float) -> float:
|
||||
"""Calculate the time to travel `distance` miles
|
||||
|
||||
Prints a message and returns max engine runtime
|
||||
if the engine would run out of fuel before the destination
|
||||
"""
|
||||
range = self.fuel_level * self.fuel_efficiency
|
||||
if range < distance:
|
||||
print(
|
||||
f"This motorboat runs out of fuel {distance - range} miles away from the destination."
|
||||
)
|
||||
return min(range, distance) / self.engine_speed
|
||||
|
||||
|
||||
class Pedalboat(Boat):
|
||||
"""A Pedalboat
|
||||
|
||||
Attributes:
|
||||
- `pedal_speed`: speed attainable by pedalling in miles per hour
|
||||
Generally in range [10, 20]
|
||||
"""
|
||||
|
||||
pedal_speed: float
|
||||
|
||||
def __init__(self, *, ps: float, **kwargs):
|
||||
"""Initialize a `Pedalboat`
|
||||
|
||||
Clamps `pedal_speed` to `10 <= pedal_speed <= 20`
|
||||
|
||||
Takes keyword-only argument `ps` (pedal speed), as described in the class docstring,
|
||||
in addition to the arguments described in `Boat`
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.pedal_speed = ps
|
||||
self.check_speed()
|
||||
|
||||
def get_pedal_speed(self) -> float:
|
||||
"""Get the pedalling speed of the boat in miles per hour"""
|
||||
return self.pedal_speed
|
||||
|
||||
def cal_travel_time(self, distance: float) -> float:
|
||||
"""Calculate the time to travel `distance` miles
|
||||
"""
|
||||
return distance / self.pedal_speed
|
||||
|
||||
def check_speed(self):
|
||||
"""Clamps `pedal_speed` to `10 <= pedal_speed <= 20`
|
||||
Returns whether the speed was already in this range
|
||||
"""
|
||||
if 10 <= self.pedal_speed <= 20:
|
||||
return True
|
||||
self.pedal_speed = min(20, max(self.pedal_speed, 10))
|
||||
return False
|
||||
|
||||
|
||||
class Eboat(Pedalboat, Engine):
|
||||
"""An `Eboat`
|
||||
|
||||
Always has engine tech 'electric'
|
||||
Attributes:
|
||||
- `battery_time`: remaining battery running time in hours
|
||||
"""
|
||||
|
||||
battery_time: float
|
||||
|
||||
def __init__(self, *, bt: float, **kwargs):
|
||||
"""Initialize an `Eboat`
|
||||
|
||||
Takes keyword-only argument `bt` (battery time), as described in the class docstring,
|
||||
in addition to the arguments described in `Pedalboat`
|
||||
"""
|
||||
super().__init__(**kwargs, tech="electric")
|
||||
|
||||
self.battery_time = bt
|
||||
|
||||
def get_max_speed(self) -> float:
|
||||
"""The maximum speed attainable in this boat by running the engine and pedalling"""
|
||||
return self.pedal_speed + self.engine_speed
|
||||
|
||||
def cal_travel_time(self, distance: float) -> float:
|
||||
"""Calculate the time to travel `distance` miles
|
||||
"""
|
||||
battery_range = self.get_max_speed() * self.battery_time
|
||||
return (
|
||||
min(distance, battery_range) / self.get_max_speed()
|
||||
+ max(distance - battery_range, 0) / self.pedal_speed
|
||||
)
|
||||
|
||||
|
||||
# ============ End of your codes here ==================
|
||||
|
||||
|
||||
# ============No modification beyond here =============
|
||||
# the following is a list of test instances, please do not modify them
|
||||
if __name__ == "__main__":
|
||||
# arguments: co - color, br - brand, yr - year, tech - technology used in engine
|
||||
boat1 = Boat(co="Black", br="Trek", yr=2012)
|
||||
engine1 = Engine(tech="gas")
|
||||
print(engine1.get_engine_speed())
|
||||
|
||||
# arguments: co - color, br - brand, yr - year, ps - pedal speed
|
||||
pedalboat1 = Pedalboat(co="Red", br="GIANT", yr=2015, ps=15)
|
||||
pedalboat2 = Pedalboat(co="Red", br="GIANT", yr=2015, ps=30)
|
||||
print(pedalboat1.get_pedal_speed())
|
||||
print(pedalboat2.get_pedal_speed())
|
||||
print(pedalboat1.cal_travel_time(300))
|
||||
|
||||
# arguments: co - color, br - brand, yr - year, ps - pedal speed, bt - battery time
|
||||
eboat1 = Eboat(co="Blue", br="Basis", yr=2018, ps=15, bt=10)
|
||||
print(eboat1.get_max_speed())
|
||||
print(eboat1.cal_travel_time(350))
|
||||
print(eboat1.cal_travel_time(650))
|
||||
|
||||
# arguments: co - color, br - brand, yr - year, fl - fuel level, fe - fuel efficiency
|
||||
motorboat1 = Motorboat(co="Silver", br="YAMAHA", yr=2013, fl=40, fe=12)
|
||||
print(motorboat1.get_max_speed())
|
||||
print(motorboat1.cal_travel_time(300))
|
||||
print(motorboat1.cal_travel_time(600))
|
||||
|
||||
# get the age of all bikes created
|
||||
for b in Boat.all_boats:
|
||||
print(b.get_boat_age(2023))
|
||||
Reference in New Issue
Block a user