# Sparsh Pandey
# 15 Jun 2025
# Standard class example (with static variables and methods).
# Finished inheritance example

# Arup Guha 6/8/2026
# Edited to add drive methods to Car, Motorcycle class
# Also added instance variables to Car class.

class Vehicle:
    
    def __init__(self, year, company, model, color, driver = None):
        self.year = year
        self.company = company
        self.model = model
        self.color = color
        self.driver = driver if driver is not None else "N/A"

    def __str__(self): 
        return "Your vehicle is a " + str(self.year) + " " + str(self.company) + " " + str(self.model)
 
    def drive(self, timeItTook, avgSpeed):
        return timeItTook * avgSpeed

    # Getters
    def getYear(self):
        return self.year

    def getCompany(self):
        return self.company

    def getModel(self):
        return self.model

    def getColor(self):
        return self.color

    def getDriver(self):
        return self.driver
 
    # Setters (we can't change the year, make, or model!)
    def setColor(self, newColor):
        self.color = newColor

    def setDriver(self, newDriver):
        self.driver = newDriver


# our car class, but we inherit from the vehicle class
class Car(Vehicle):
    def __init__(self, year, company, model, color, hp, tanksize, driver=None):

        # We are required to call super.
        super().__init__(year, company, model, color, driver)

        # We do this separately since it's not part of Vehicle.
        self.hp = hp

        # Added to original example.
        self.gas = 0
        self.tank = tanksize
        self.odom = 0

    # The only one specific to cars. Getter and Setter for Horsepower (maybe you tuned your car)
    def getHP(self):
        return self.hp

    def setHP(self, newHP):
        self.hp = newHP

    # Note that we can use methods from the class we inherited from
    def __str__(self):
        return super().__str__() + " with " + str(self.hp) + " HP!"+ "odom:"+str(self.odom)+" gas left: "+str(self.gas)

    # Get gas!
    def addGas(self, gallons):
        self.gas += gallons

    # Drive inherits from Vehicle, but uses it to update the Car's odometer and
    # gas tank.
    def drive(self, time, avgspeed):
        distDriven = super().drive(time, avgspeed)
        self.odom += distDriven

        # I am assuming 30 miles per gallon and not doing any error checking!
        self.gas -= distDriven/30

# another class we made  
class Motorcycle(Vehicle):
    def __init__(self, year, company, model, color, cc, driver=None):
        super().__init__(year, company, model, color, driver)
        self.cc = cc

    # Same as car, this is specific only to bikes.
    def getCC(self):
        return self.cc

    def setCC(self, newCC):
        self.cc = newCC

    # I was lazy and did something bizarre: driving shrinks your engine!
    def drive(self, time, avgspeed):
        dist = super().drive(time, avgspeed)
        self.cc -= dist/100
    
    # It's quicker to use the one from vehicle, and then make some tweaks to the __str__ method in the car class!
    def __str__(self):
        return super().__str__() + " with " + str(self.cc) + " CC!"

# Some tests.    
def main():
    
    # make a Car, Motorcycle and Vehicle
    car1 = Car(1992, "Porsche", "964", "Yellow", 320, 20, "Sparsh")
    bike1 = Motorcycle(2022, "Yamaha", "R1", "Blue", 998, "Zen")
    scooter = Vehicle(2026, "Razor", "daRazor", "Purple")
    
    # Add some gas and drive...
    car1.addGas(10)
    print(car1)
    car1.drive(2, 55)
    print(car1)

    # See what happens with a basic Vehicle.
    print(scooter)
    dist = scooter.drive(3, 10)
    print("drove our scooter for",dist,"miles")

    # Now let's look at the bike drive.
    print("bike ",bike1)
    bike1.drive(10, 70)
    print("bike after drive",bike1)

    # Sort of an example of polymorphism.
    items = []
    items.append(car1)
    items.append(scooter)
    items.append(bike1)

    # Each appropriate drive method is called.  
    for x in items:
        x.drive(5, 20)
        print("in loop ",x)

# Run it.
main()
