# Project 2: Environmental Model Program
# File: p2envmodel.py
# By: John Philip McGee
# Login: mcgee21
# By: Andre Woloshuk
# Login: acwolosh
# By: Mitchell Woolever
# Login: mwooleve
# By: Joseph Pejril
# Login: jpejril
# Section: 2
# Team: Team 37
#
# ELECTRONIC SIGNATURES
# John Philip McGee
# Andre Woloshuk
# Mitchell Woolever
# Joseph Pejril  
#
#
# The electronic signature above indicates the program
# team members and that each member of the team was an
# equal participant in its creation.
#
# PROGRAM DESCRIPTION
# This program calculates various types of environmental 
# emissions caused directly and indirectly by a construction project.

#!/usr/bin/env python3

import math

# Outputs Miles Per Gallon hourly array starting from 1 on sunday and covering over 700 days
def TrafficFlow(Population, PercentCars, LanesOpenPerSide, LanesCoefficient, DayStarted, Days, Day, ConstructionSpeedLimit):
    
    # Time of Day vs traffic flow - 
    # Array of 24*7 values for traffic congestion coefficients 
    # (Minutes wasted in congestion):
    TrafficCongestion =\
    [[.8,.8,.9,.8,.7,.6,.5,.5,.5,.6,.8,1.1,1.3,1.3,1.3,1.4,1.4,1.2,1.0,1.0,.9,.8,.7,.6],\
    [.5,.4,.4,.5,.6,1.0,2.8,3.6,2.0,1.5,1.6,1.7,1.7,1.8,2.2,3.1,4.3,2.7,1.2,1.0,.9,.8,.7,.6],\
    [.5,.4,.4,.5,.6,1.2,3.3,4.4,2.5,1.7,1.7,1.8,1.8,1.9,2.4,3.6,5.5,3.5,1.4,1.0,.9,.8,.7,.6],\
    [.5,.4,.4,.5,.6,1.2,3.2,4.3,2.4,1.8,1.8,1.9,2.0,2.1,2.7,4.1,6.0,3.9,1.5,1.2,.9,.8,.7,.6],\
    [.5,.4,.4,.5,.6,1.2,3.2,4.1,2.4,1.8,1.8,2.0,2.0,2.1,2.8,4.3,6.4,4.1,1.6,1.2,.9,.8,.7,.6],\
    [.5,.4,.4,.5,.6,1.0,2.2,2.8,1.9,1.7,1.9,2.2,2.4,2.9,4.1,5.8,6.7,4.3,2.0,1.3,.9,.8,.7,.6],\
    [.5,.4,.4,.5,.7,.6,.6,.7,.9,1.2,1.5,1.8,1.9,1.8,1.7,1.6,1.5,1.4,1.1,1.0,.9,.8,.7,.6]]
    
    BaseMphCoefficient = int((math.log(math.e \
    + ((Population*PercentCars/LanesOpenPerSide-250000)/1000000)*(LanesCoefficient)))) \
    * (ConstructionSpeedLimit+5)

    # ConstructionSpeedLimit+5 is the entirely limiting speed limit
        
    # ln() depicts decrease in mph based on all influences but has a negative second 
    # derivative to show a decreasing influence
    
    # With low enough population*percent cars at 250,000 per lane, the general influence of all other factors
    # but construction speed limit is insignificant

    # As mph decreases, TrafficCongestion decreases in influence (See Natural Log)

    # Assume direct proportion of congestion and vehicle addition, congestion coefficient = k * vehicle addition coefficient
    
    #The full equation will be:
    # int((1/k(t)*(ln(e \
    # + ((Population/LanesOpenPerSide-250000)/1000000)*(LanesCoefficient)))) \
    # * (ConstructionSpeedLimit+5))

    # k(t) is a parametric equation to control the extent of the calculation, as all factors are 
    # approximately correlated correctly, but the underlying mechanics of traffic congestion are very
    # unpredictable, so using given values of mph, population, LanesOpenPerSide, TrafficCongestion at times of day
    # from credible news sources from multiple cities will be used as a metric to predict k(t). 

    # The use of k(t) and ln() are based on the basic decay equation, so if k(t) is found to be within 
    # 25% of itself at any given values, a k constant will be used instead.

    def MilesPerGallonPerMilesPerHour(mph):
        # Independent = Speed (mph), Dependent = Miles per gallon
        MilesPerGallon = [5,11,17,22,25.66,27.66,28.66,29.33,29.66,30,30.33,30,29,27.33,25,23.33]
        MilesPerHour = [0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75]

        def MphToMpg(mph):
            for i in range(len(MilesPerHour)):

                if mph == a[i]:
                    return i
                else:
                    print("Mph is either negative or over 75, which is very dangerous for construction workers.")
                    return 0
        mpg = MilesPerGallon[MphToMpg(mph)]
        return mpg

    MPH_Main = [x * BaseMphCoefficient for x in TrafficCongestion]
    MPG_Main = MilesPerGallonPerMilesPerHour(MPH_Main)
    
    # Elongates MPG_Main to cover 104 weeks, or 2 years, a reasonable
    # maximum
    MPG_Main = 104*MPG_Main

    return MPG_Main

def EmissionsRate(MPG_Main):
    # Defining number of types of vehicle on the road in the US 2009: 
    # PC = Passenger Cars, LDT = Light Duty Trucks, MC = MotorCycles, HDT = Heavy Duty Trucks
    PC = 193979654
    LDT = 40488025 + 8356097
    MC = 7929724
    HDT = 2617118

    # Defining percentages of vehicles out of total
    PC_P = PC / (PC+LDT+MC+HDT)
    LDT_P = LDT / (PC+LDT+MC+HDT)
    MC_P = MC / (PC+LDT+MC+HDT)
    HDT_P = HDT / (PC+LDT+MC+HDT)


    # Defining normal rate of emission for each type of emission for each type of vehicle in grams/hr
    # VOC = Volative Organic Compounds, THC = Total hydrocarbons, 
    # CO = Carbon Monoxide, NOx = Nitrogen Oxides, CO2 = Carbon Dioxide

    # This first number is a coefficient for average grams/mi
    # For non-given values of MC and HDT, a direct proportion with idle emissions was used
    PC_VOC = 1.034
    LDT_VOC = 1.224
    MC_VOC = 7.381 
    HDT_VOC = 2.503 
    PC_THC = 1.077 
    LDT_THC = 1.289 
    MC_THC = 7.190 
    HDT_THC = 2.472 
    PC_CO = 9.400 
    LDT_CO = 11.84 
    MC_CO = 39.7347 
    HDT_CO = 20.047 
    PC_NOx = 0.693 
    LDT_NOx = 0.95 
    MC_NOx = 0.320 
    HDT_NOx = 1.051 
    PC_CO2 = 368.4 
    LDT_CO2 = 513.5 

    # Finding average normal rate of emission for each type of emission for all vehicles
    # Other values for CO2 were not available so Passenger Cars and Light Duty 
    # Trucks will determine the standard.
    VOC = PC_P*PC_VOC+LDT_P*LDT_VOC+MC_P*MC_VOC+HDT_P*HDT_VOC
    THC = PC_P*PC_THC+LDT_P*LDT_THC+MC_P*MC_THC+HDT_P*HDT_THC
    CO = PC_P*PC_CO+LDT_P*LDT_CO+MC_P*MC_CO+HDT_P*HDT_CO
    NOx = PC_P*PC_NOx+LDT_P*LDT_NOx+MC_P*MC_NOx+HDT_P*HDT_NOx
    CO2 = (PC_CO2+LDT_CO2)/2
    
    # There is 20 mph : 25.66 mpg from the MilesPerGallon array
    # Coefficients for MC and HDT are estimated by assuming idling and normal rates are proportional
   
    BaseSpeed = 20
    EmissionConversion = BaseSpeed*25.66/MPG_Main    
   
    # VOC*BaseSpeed converts from grams/mi to grams/hr
    # As there is 25.66 mpg at 20 mph, we use mpg found from the MilesPerGallon array and
    # multiply by 25.66/mpg
    VOCArray = VOC*EmissionConversion
    THCArray = THC*EmissionConversion
    COArray = CO*EmissionConversion
    NOxArray = NOx*EmissionConversion
    CO2Array = CO2*EmissionConversion

    return VOCArray, THCArray, COArray, NOxArray, CO2Array

def CityDecision():
    print('Enter one of the following cities: Boston, Chicago, Dallas, Houston,' +
    ' Los Angeles, Indianapolis, New York City, Philadelphia, Phoenix, San Antonio,' +
    ' San Francisco, San Jose, Washington, D.C.) to model construction: ')
    City = str(input())
    if City == 'Boston':
        Population = 617594
        PercentCars = .6509
    elif City == 'Chicago':
        Population = 2695598
        PercentCars = .6509        
    elif City == 'Dallas':
        Population = 1197816
        PercentCars = .9000
    elif City == 'Houston':
        Population = 2099451
        PercentCars = .9000 
    elif City == 'Los Angeles':
        Population = 3792621
        PercentCars = .8347
    elif City == 'Indianapolis':
        Population = 820445
        PercentCars = .9000
    elif City == 'New York City':
        Population = 8175133
        PercentCars = .4430
    elif City == 'Philadelphia':
        Population = 1526006
        PercentCars = .6426
    elif City == 'Phoenix':
        Population = 1445632
        PercentCars = .9000
    elif City == 'San Antonio':
        Population = 1327407
        PercentCars = .9000
    elif City == 'San Francisco':
        Population = 805235
        PercentCars = .7144
    elif City == 'San Jose':
        Population = 945942
        PercentCars = .9000
    elif City == 'Washington, D.C.':
        Population = 601723
        PercentCars = .6307
    else:
        print('City not recognized. Setting population to default 1 million.')
        Population = 1000000
        PercentCars = .9000        
    Relative_Size = 100 * (Population / 8175133)

    CityConstants = [Population, PercentCars]
    return CityConstants


# The following are all functions used in the Main Input function block
# to convert inputs into usable constants.

# Converts "Sides" into boolean value
def BooleanSides(Sides):
    if Sides == 'Y' or Sides == 'y' or Sides == 'Yes' or Sides == 'yes':
        Boolean = bool(True)
    elif Sides == 'N' or Sides == 'n' or Sides == 'No' or Sides == 'no':
        Boolean = bool(False)
    else:
        print("Input not Y or N, defaulting to one side")
        Boolean = bool(False)

# Figures out how many lanes there are per side
def LanesOpenPerSideCalculation(LanesTotal, LanesClosed, Sides):
    if Sides == True:
        LanesOpenPerSide = (LanesTotal-LanesClosed)/2
    else:
        LanesOpenPerSide = (LanesTotal-LanesClosed)
    return LanesOpenPerSide

# Figures out how many lanes are closed per side
def LanesClosedPerSideCalculation(LanesClosed, Sides):
    if Sides == True:
        LanesClosedPerSide = (LanesClosed)/2
    else:
        LanesClosedPerSide = LanesClosed
    return LanesClosedPerSide

def ConstructionCost(Length, Lanes):
    #Construction_Rate is expressed in USD per lane-mile
    if Expand_Or_Repair == 'Expand':
        Construction_Rate = 4460000
    elif Expand_Or_Repair == 'Repair':
        Construction_Rate = 312500
    else:
        Construction_Rate = 312500

    Construction_Cost = Construction_Rate * Length * Lanes
    return Construction_Cost

#Need to give error messages when invalid values are entered!
def MainInput():
    
    CityConstants = CityDecision()
    Population = CityConstants[0]
    PercentCars = CityConstants[1]

    print(' ')
    print('How many miles of road will the construction encompass?')
    Length = input()
    
    try:
        val = float(Length)
    except ValueError:
        print("That's not a number. Defaulting to 1 mile.")
        Length = 1

    if float(Length) > 0 and float(Length) < 1000:
        Length = float(Length)
    else:
        print('Invalid value for miles. Either less than 0 or greater \
        than 1000. Defaulting to 1 mile.')
        Length = 1


    print(' ')
    print('Will the construction cover both sides of the road? (Y/N)')
    Sides = str(input())
    
    Sides = BooleanSides(Sides)


    print(' ')
    print('How many lanes of road are available normally?')
    LanesTotal = input()

    try:
        val = int(LanesTotal)
    except ValueError:
        print("That's not an integer. Defaulting to 3 lanes.")
        LanesTotal = 3

    if int(LanesTotal) > 0 and int(LanesTotal) < 20:
        LanesTotal = int(LanesTotal)
    else:
        print('Invalid value for lanes. Either less than 0 or greater \
        than 20 lanes. Defaulting to 3.')
        LanesTotal = 3


    print(' ')
    print('How many lanes of road will the construction encompass?')
    LanesClosed = input()

    try:
        val = int(LanesClosed)
    except ValueError:
        print("That's not an integer. Defaulting to 2 lanes.")
        LanesClosed = 2

    if int(LanesClosed) > 0 and int(LanesClosed) < 20:
        LanesClosed = int(LanesClosed)
    else:
        print('Invalid value for lanes. Either less than 0 or greater \
        than 20 lanes. Defaulting to 2.')
        LanesClosed = 2
   
    print(' ')
    print('What is the normal speed limit of the highway in miles per hour?')
    SpeedLimit = input()

    try:
        val = float(SpeedLimit)
    except ValueError:
        print("That's not a number. Defaulting to 65 miles per hour.")
        SpeedLimit = 65

    if float(SpeedLimit) > 0 and float(SpeedLimit) < 90:
        SpeedLimit = float(SpeedLimit)
    else:
        print('Invalid value for speed limit. Either less than 0 or greater \
        than 90 miles per hour. Defaulting to 65 miles per hour.')
        SpeedLimit = 65

    print(' ')
    print('What is the speed limit of the highway in miles per hour' +
    ' while it is under construction?')
    ConstructionSpeedLimit = input()

    try:
        val = float(ConstructionSpeedLimit)
    except ValueError:
        print("That's not a number. Defaulting to 35 miles per hour.")
        ConstructionSpeedLimit = 35

    if float(ConstructionSpeedLimit) > 0 and float(ConstructionSpeedLimit) < 90:
        ConstructionSpeedLimit = float(ConstructionSpeedLimit)
    else:
        print('Invalid value for speed limit. Either less than 0 or greater \
        than 90 miles per hour. Defaulting to 35 miles per hour.')
        ConstructionSpeedLimit = 35

    print(' ')
    print('What day of the week will the construction start?')
    DayStarted = input()

    # Change DayStarted into integer value (Corresponding to
    # the hour value it starts on in the TrafficCongestion array)
    if DayStarted == 'Sunday' or DayStarted == 'sunday':
        Day = 0
    elif DayStarted == 'Monday' or DayStarted == 'monday':
        Day = 24
    elif DayStarted == 'Tuesday' or DayStarted == 'tuesday':
        Day = 48
    elif DayStarted == 'Wednesday' or DayStarted == 'wednesday':
        Day = 72
    elif DayStarted == 'Thursday' or DayStarted == 'thursday':
        Day = 96
    elif DayStarted == 'Friday' or DayStarted == 'friday':
        Day = 120
    elif DayStarted == 'Saturday' or DayStarted == 'saturday':
        Day = 144
    else:
        print(' ')
        print("Invalid value for day, defaulting to Sunday")
        Day = 0

    print(' ')
    print('How many days will the construction project last?')
    Days = input()

    try:
        val = int(Days)
    except ValueError:
        print("That's not an integer. Defaulting to 7 days.")
        Days = 7

    if int(Days) > 0 and int(Days) < 700:        
        Days = int(Days)
    else:
        print('Invalid days value (less than zero or greater than 700), defaulting to 7 days')
        Days = 7

    LanesOpenPerSide = LanesOpenPerSideCalculation(LanesTotal, LanesClosed, Sides)

    LanesClosedPerSide = LanesClosedPerSideCalculation(LanesClosed, Sides)

    LanesPerSide = LanesOpenPerSide + LanesClosedPerSide
    LanesCoefficient = LanesOpenPerSide/LanesPerSide

    MPG_Main = TrafficFlow(Population, PercentCars, LanesOpenPerSide, LanesCoefficient, DayStarted, Days, Day, ConstructionSpeedLimit)

    print (EmissionsRate(MPG_Main))

#def PartsNumber():
#    print(' ')
#    print('Split the job into parts? Yes or No.')
#    Split = str(input())
#    if Split == 'Yes':
#        print(' ')
#        print('How many parts?')
#        Part_Number = int(input())
#        Length_Per_Part = Length / Part_Number
#        Time_Per_Part = Duration / Part_Number
#    elif Split == 'No':
#        print(' ')
#    else:
#        print('Command not recognized. Not splitting.')

#def ExpandOrRepair():
#    print(' ')
#    print('Will this construction job be Expansion or Repair?')
#    Expand_Or_Repair = str(input())
#    if Expand_Or_Repair == 'Expand':
#        print(' ')
#    elif Expand_Or_Repair == 'Repair':
#        print(' ')
#    else:
#        print('Expand/Repair command not recognized. Substituting with Repair.')
#        print(' ')

MainInput()

print(' ')
print(' ')
print(' ')
print('====================================================================')
print(' ')
print(City, 'is', Relative_Size, '% the size of New York City.')

print(' ')
if Split == 'Yes':
    print('This construction job will take up,', \
    Length_Per_Part, ' mile(s) and ', Time_Per_Part, 'day(s) for a total \
of', Length, 'mile(s) and', Duration, 'month(s).')
print('The total cost of this construction project is $', Construction_Cost)

print(' ')
print('====================================================================')
print(' ')
print(' ')
print(' ')

# STATS AREA #

## Daily traffic congestion coefficients - 
    ## These allow for an average traffic congestion per hour per day
    #Sunday = sum(MPH_Main[0]/24)
    #Monday = sum(MPH_Main[1]/24)
    #Tuesday = sum(MPH_Main[2]/24)
    #Wednesday = sum(MPH_Main[3]/24)
    #Thursday = sum(MPH_Main[4]/24)
    #Friday = sum(MPH_Main[5]/24)
    #Saturday = sum(MPH_Main[6]/24)

    #SundayNight = sum(MPH_Main[0][0:3]+ MPH_Main[0][19:23])
    #MondayNight = sum(MPH_Main[1][0:3]+ MPH_Main[1][19:23])
    #TuesdayNight = sum(MPH_Main[2][0:3]+ MPH_Main[2][19:23])
    #WednesdayNight = sum(MPH_Main[3][0:3]+ MPH_Main[3][19:23])
    #ThursdayNight = sum(MPH_Main[4][0:3]+ MPH_Main[4][19:23])
    #FridayNight = sum(MPH_Main[5][0:3]+ MPH_Main[5][19:23])
    #SaturdayNight = sum(MPH_Main[6][0:3]+ MPH_Main[6][19:23])

    #SundayDay = sum(MPH_Main[0][4:18])
    #MondayDay = sum(MPH_Main[1][4:18])
    #TuesdayDay = sum(MPH_Main[2][4:18])
    #WednesdayDay = sum(MPH_Main[3][4:18])
    #ThursdayDay = sum(MPH_Main[4][4:18])
    #FridayDay = sum(MPH_Main[5][4:18])
    #SaturdayDay = sum(MPH_Main[6][4:18])

     #Round to previous 5 mph multiple
   
    #SpeedLimit+5 
    # Speed limit on highway (Assume everyone 
    # goes 5 mph more). SpeedLimit+5 defines the control, 
    # and assuming no other congestion such as accidents,
    # SpeedLimit+5 is the constant emissions-creating speed 
    # on efficient highways.
    # Traffic congestion coefficient only applies to construction
    # Construction-required Speed Limit variable graph 
    # (with everything else constant)
