Esempio n. 1
0
def qEvent_elevation(dPack):
    """ Method caters for recording of change in gradient.
    dPack = {
        "tremb": ccTremb,           # For full DB access.
        "db": cLine,                # Database entries for the line.
        "dEntry": {                 # This parameter will be passed back
            "km":fDist,             # kmilage marker
            "id":iHighest+1,        # Unique reference number
            "item":None,            # We need to fill this with our data
            "type":None,            # We need to fill this with our data
            "xVal":None},           # We need to fill this with our data
    }
    """

    dEntry = dPack["dEntry"]  # Unpack the prototype
    sMenu = ("Please select the elevation event from the list\n")
    sMenu += "Select track event:\n"
    sMenu += "-   [Comments not allowed here. Technical reasons]\n"
    sMenu += "1   Record spot height\n"
    sMenu += ("2   Trapezoidal change (_/TT\_). (!)" +
              " Req. All 4 pts in km seq. (!)\n")

    print(sMenu)
    sInput = input().upper()

    # COMMENT
    if sInput == "0":  # Comment
        print("Comments not allowed for 'elevation events'")
        return None

# SPOT ELEVATION
    if sInput == "1":
        #"dEntry":{"km":fDist,"id":0,"item":None,"type":None,"xVal":None},
        dEntry["item"] = "elev_ft"
        dEntry["type"] = "spot"  # Type of transaction
        sTxt = "Please enter spot elevation, (in ft), as an integer"
        iSpot = misc.get_int(sTxt, bNeg=True)
        dEntry["xVal"] = iSpot
        return dEntry

# TRAPEZIODAL ELEVATION _/TT\_
    if sInput == "2":
        #"dEntry":{"km":fDist,"id":0,"item":None,"type":None,"xVal":None},
        dEntry["item"] = "elev_ft"
        dEntry["type"] = "trapezoid"  # Type of transaction
        sTxt = ("Please enter the local change of elevation, (in ft), " +
                "as an integer.\n(Example '0' or '-20')")
        iSpot = misc.get_int(sTxt, bNeg=True)
        dEntry["xVal"] = iSpot
        return dEntry

    else:
        print("\n\aInvalid selection. Exiting")
        return None
Esempio n. 2
0
def qEvent_crossing(dPack):
    """ This function builds up a piece of station for us.
        dPack = {
            "tremb": ccTremb,           # For full DB access.
            "db": cLine,                # Database entries for the line.
            "dEntry": {                 # This parameter will be passed back
                "km":fDist,             # kmilage marker
                "id":iHighest+1,        # Unique reference number
                "item":None,            # We need to fill this with our data
                "type":None,            # We need to fill this with our data
                "xVal":None},           # We need to fill this with our data
        }
"""

    dEntry = dPack["dEntry"]  # Unpack the prototype
    sMenu = ("Please select the station event from the list")
    sMenu += "Select track event:\n"
    sMenu += "0   Comment (record something unusual)\n"
    sMenu += "1   River (bridge or tunnel)\n"

    print(sMenu)
    sInput = input().upper()

    # COMMENT
    if sInput == "0":  # Comment
        dEntry["item"] = "crossing"
        dEntry["type"] = "comment"  # Type of transaction
        sTxt = "Please enter a comment regarding station"
        print(sTxt)
        dEntry["xVal"] = input()
        return dEntry

# REGISTERED HOST
    if sInput == "1":
        #"dEntry":{"km":fDist,"id":0,"item":None,"type":None,"xVal":None},
        dEntry["item"] = "crossing"
        dEntry["type"] = "river"  # Type of transaction

        sTxt = "Please enter the name of the river being crossed:"
        print(sTxt)
        sName = input()

        sTxt = "Please enter approximate width of the river in integer meters"
        iWidth = misc.get_int(sTxt)
        if iWidth == None: return None

        xVal = {
            "sName": sName,
            "iWidth": iWidth,
        }
        dEntry["xVal"] = xVal
        return dEntry

    else:
        print("\n\aInvalid selection. Exiting")
        return None
Esempio n. 3
0
def remove_sub_comp(ccTremb):
    """ Method prompts the user for data and returns distance on the map for the
        approach to the structure.
    """
    # Request the line identifier
    sTxt = ("You are about to remove a component from a line.\nPlease enter " +
            "the K-code ('K00-001' for example) of the line\n")
    print(sTxt)
    sK_code = input().upper()

    # Verify the line number
    sRte_det = qVerify_line(sK_code, ccTremb)
    if sRte_det == None: return None

    # Ask for the identifier mark
    sTxt = ("Please enter the item identifier (id: 39 for example) as an " +
            "integer")
    iId_req = misc.get_int(sTxt)
    if iId_req == None: return None

    # Pull up the data you are about to delete:
    xParam = {"my_id": sK_code, "dVal.id": iId_req}
    xRestr = {"_id": 0, "dVal": 1}
    cDatabase = db.lines(ccTremb)
    dQuery = cDatabase.find(xParam, xRestr)

    dElement = []
    for query in dQuery:
        dElement.append(query)

    print("\n-----------------------------")
    sTxt = ("You are about to remove\n\n{0}\n\nfrom {1}\n\n" +
            "Do you want to procceed?")
    sTxt = sTxt.format(dElement[0], sRte_det)
    yn_remove = misc.get_binary(sTxt)
    if yn_remove == None: return None
    if yn_remove == "N":
        print("\n\aAborting removal")
        return None

    # Remove the item
    xParam = {"my_id": sK_code, "dVal.id": iId_req}
    xRestr = {}
    dQuery = cDatabase.delete_one(xParam, xRestr)
    print("Specified element deleted")
Esempio n. 4
0
def add_housing(ccTremb):
    """ Adds details of the housing to the database """

    # Obtain the highest "my_id" code that is registered in the database.
    xParam = {}
    xRestr = {"_id": 0, "my_id": 1}
    cHousing = db.housing(ccTremb)
    dId_query = cHousing.find(xParam, xRestr)
    iHighest, aEvery_id = misc.find_highest_id(dId_query)

    if (False):  # Debugging
        sTxt = "\n\nHighest number is {0}(10) < < < < < < < <"
        print(sTxt.format(iHighest))

    # We do have the highest identifier (expressed as a decimal number). Hence,
    # we can incerement the sequence and use it.
    iNext_id = iHighest + 1
    if iNext_id > 36**5:
        print("\n\aMaximum count has been exceeded")
        return None

    # Convert to base36
    sBase36 = misc.base_conv(iNext_id)
    sBase36_5 = sBase36.rjust(5, "0")
    # "0002W" -> "D00-02W"
    sNew_id = "H{0}-{1}".format(sBase36_5[:2], sBase36_5[2:])
    print("\nNext id is {0}".format(sNew_id))

    # START GETTING THE USER TO ENTER THE NEW DATA.
    # Open a blank dictionary, so that the elements are arranged in a certain
    # order.
    dNew_housing = {
        "my_id": sNew_id,
        "host_geo_code": None,
        "aName": {
            "lat": None,
            "cyr": None
        },  # Is the block of flats named?
        "type": None,  # Green(space), Res(idential)
        "sub_type": None,  # house, lin apt, sq apt, x apt, irreg apt,
        "iUnits_per_floor": 0,  # How many apartments in the block
        "iNo_of_floors": 1,  # How tall is the building
        "iNo_of_buildings": 1,  # How many buildings in the 'package'
        "iTot_units": 0,  # Total households in this location
        "sDesc": "",  # Description ex: "9x2x1M; 9 = 7+1S+1SP"
        "demographic": "",  # 'r' to 'p'
        "aParking": {
            "iFloors": 1,  # How many levels is parking offered on.
            "iVeh": 0,  # Vehicles in total
            "map_a": 0,  # sq.mm on the map per floor of the parking area.
        },
        "aMap": {
            "sRegion": None,
            "iYear": None,
            "fScale": None,
            "x": None,
            "y": None,
            "a": None
        },
        "aFpt_bldg": {
            "qty": None,
            "uom": None
        },
        "aArea_plot": {
            "qty": None,
            "uom": None
        },
    }

    # Automatically obtain the geo-code of the last entry. Chances are that we'd
    # like to re-use it.
    xParam = {}
    xRestr = {"_id": 0, "host_geo_code": 1}
    dId_query = cHousing.find(xParam, xRestr).sort("_id", 1)
    dId_query.sort("_id", -1)

    # Pull out the geo-code
    sGeo_code = dId_query[0]["host_geo_code"]
    cDest = db.destinations(ccTremb)
    dGeo_names = misc.verify_geo_code(sGeo_code, cDest)
    if dGeo_names == None: return None  # An error has occured.

    # Names of the settlement.
    sP_lat = dGeo_names["lat"]
    sP_cyr = dGeo_names["cyr"]

    sTxt = "Are you working on {0} ({1} / {2})?"
    sTxt = sTxt.format(sGeo_code, sP_lat, sP_cyr)
    yn_last_host = misc.get_binary(sTxt)
    if yn_last_host == None: return None
    if yn_last_host == "N":
        # HOST
        sTxt = ("\nWho is hosting this residential area OR greenspace?\n" +
                "Please enter host's geo-code.")
        print(sTxt)
        sGeo_code = input().upper()

    dGeo_element = misc.get_geo_element(sGeo_code, cDest)
    if dGeo_element == None: return
    aHost_name = dGeo_element["aName"]

    dNew_housing["host_geo_code"] = sGeo_code
    sTxt = "\nHosted by {0} / {1}".format(aHost_name["lat"], aHost_name["cyr"])
    print(sTxt)

    # TYPE
    sMenu = "\n"
    sMenu += "What type area is it?\n"
    sMenu += "0: Greenspace (Park)\n"
    sMenu += "1: Residential\n"

    iType_option = misc.get_int(sMenu, 1)
    if iType_option == None:
        print("\a")
        return None

    if iType_option == 0:
        dNew_housing["type"] = "Green"
    elif iType_option == 1:
        dNew_housing["type"] = "Res"
    else:
        print("\n\aInvalid choice for area type type")
        return

# SUB-TYPE:
    if dNew_housing["type"] == "Res":  # Residential:
        sMenu = "\n"
        sMenu += "Type of housing is it?\n"
        sMenu += "0: House: Free-standing building for 1 or 2 households\n"
        sMenu += "1: Apartments, Linear: Straight block of appartments\n"
        sMenu += "2: Apartments, Square: Square-edged Doughnut-shaped bldg\n"
        sMenu += "3: Apartments, Cross: Cross-shaped building\n"
        sMenu += "4: Apartments, Irregular: Irregularly-shaped building\n"
        sMenu += "5: Other: Something rare, or that doesn't fit above descr.\n"

        iType_option = misc.get_int(sMenu, 5)
        if iType_option == None:
            print("\a")
            return None

        if iType_option == 0:
            dNew_housing["sub_type"] = "house"
        elif iType_option == 1:
            dNew_housing["sub_type"] = "lin apt"
        elif iType_option == 2:
            dNew_housing["sub_type"] = "sq apt"
        elif iType_option == 3:
            dNew_housing["sub_type"] = "x apt"
        elif iType_option == 4:
            dNew_housing["sub_type"] = "irrg apt"
        elif iType_option == 5:
            dNew_housing["sub_type"] = "other"
        else:
            print("\n\aInvalid choice for port type")
            return
    # Greenspace was selected
    else:
        dNew_housing["sub_type"] == "N/A"

# MAP REFERENCE
    sMap = "plot"
    dData = misc.get_map_input(ccTremb, sMap)  # Asks for user to input stuff.
    if dData in [None, True]:  # No map selected
        print("\n\aInvalid entry from the map. Exiting")
        return None

    # Transfer data through.
    dNew_housing["aMap"] = dData["dMap"]
    dNew_housing["aArea_plot"] = dData["dArea"]

    # BUILDING SIZE
    if dNew_housing["type"] == "Res" and dNew_housing["sub_type"] != "house":
        sTxt = "\nEnter the footprint of the building in sq.mm from map."
        fBldg_ftp = misc.get_float(sTxt)
        if fBldg_ftp == None: return None

        # Calculate area
        fScale = dNew_housing["aMap"]["fScale"]
        dNew_housing["aFpt_bldg"] = misc.calc_area(fBldg_ftp, fScale)

# OPTIONAL NAME
    aName = misc.building_name()
    if aName == None: return None
    if aName != False:  # False: if a name was not chosen
        dNew_housing["aName"] = aName

# DEMOGRAPHICS:
    sMenu = "\n"
    sMenu += "Which demographic is residing here?\n"
    sMenu += "0: Rich           [2500sq.m plot and up]\n"
    sMenu += "1: High-income    [1600sq.m plot]\n"
    sMenu += "2: Mid-income     [ 900sq.m plot]\n"
    sMenu += "3: Low-income     [ 600sq.m plot]\n"
    sMenu += "4: Poor           [ 400sq.m plot]\n"

    iLevel_option = misc.get_int(sMenu, 4)
    if iLevel_option == None:
        print("\a")
        return None

    if iLevel_option == 0:
        dNew_housing["demographic"] = "r"
    elif iLevel_option == 1:
        dNew_housing["demographic"] = "h"
    elif iLevel_option == 2:
        dNew_housing["demographic"] = "m"
    elif iLevel_option == 3:
        dNew_housing["demographic"] = "l"
    elif iLevel_option == 4:
        dNew_housing["demographic"] = "p"
    else:
        print("\n\aInvalid choice for port type")
        return

# DESCRIPTION:
    sTxt = ("\nGive a brief description of the area. For example:\n" +
            "'(9x2)x1M [7+1S+1SP]': Seven units in a row, 1 from the side, " +
            "1 panhandle from\nside with two households sharing this building")
    print(sTxt)
    dNew_housing["sDesc"] = input()

    # BUILDING COUNT
    sTxt = ("\nHow many buildings in the group?")
    iNo_of_buildings = misc.get_int(sTxt)
    if iNo_of_buildings == None: return None
    dNew_housing["iNo_of_buildings"] = iNo_of_buildings

    # FLOOR COUNT
    sTxt = ("\nHow many floors does each building have?")
    iFloor_cnt = misc.get_int(sTxt)
    if iFloor_cnt == None: return None
    dNew_housing["iNo_of_floors"] = iFloor_cnt

    # APPARTMENT COUNT
    sTxt = ("\nHow many appartments per floor in this building?")
    iUnits_per_floor = misc.get_int(sTxt)
    if iUnits_per_floor == None: return None
    dNew_housing["iUnits_per_floor"] = iUnits_per_floor

    # TOTAL UNITS
    fTot_units = iNo_of_buildings * iFloor_cnt * iUnits_per_floor
    iTot_units = int(round(fTot_units, 0))
    dNew_housing["iTot_units"] = iTot_units

    # PARKING:
    sMenu = "\n"
    sMenu += "How do you want to calculate car parking available?\n"
    sMenu += "0: Individual houses, with x number of cars per plot\n"
    sMenu += "1: Square footprint, with x and y known in mm.\n"
    sMenu += "2: Footprint, with area in sq.mm is known\n"

    iParking_option = misc.get_int(sMenu, 2)
    if iParking_option == None: return None

    iVeh = None  # I publish the results of the parking.
    # INDIVIDUAL HOUSES
    if iParking_option == 0:
        sTxt = ("There are {0} plots in this area. Enter number of vehicles " +
                "per plot\nthat can be parked off the street. (Usually 2)")
        sTxt = sTxt.format(iNo_of_buildings)
        iVeh = misc.get_int(sTxt)
        if iVeh == None: return None

        iVeh *= iNo_of_buildings
        dNew_housing["aParking"]["iVeh"] = iVeh

    # SQUARE FOOTPRINT KNOWN SIDES
    elif iParking_option == 1:
        sTxt = ("Enter the first side of the area for parking")
        fParking_x = misc.get_float(sTxt)
        if fParking_x == None: return None

        sTxt = (
            "Enter the second side of the area for parking, perpendicular" +
            " to the first")
        fParking_y = misc.get_float(sTxt)
        if fParking_y == None: return None

        # Calculate the parking area
        fMap_area = fParking_x * fParking_y
        fMap_scale = dNew_housing["aMap"]["fScale"]
        aParking_area = misc.calc_area(fMap_area, fMap_scale)

        if aParking_area == None: return None

        # We know the real-world scale of the parking.
        # In the real world, a parking bay is 5.5m x 2.5m (13.75sq.m). However,
        # each vehicle needs access to that bay. The above calcuation gives
        # 7.27veh/100sq.m. However, each vehilce needs some space to get to the
        # bay. Hence, I'm using the figure of 6 veh / 100sq.m (600veh/ha)

        # Verify the units of measurement
        if aParking_area["uom"] != "sq.m":
            print(
                "\nUnexpected calculation result for residential parking:\n" +
                "Expected 'sq.m', but got {0}\a".format(aParking_area["uom"]))
            return None
        fSqm_P = aParking_area["qty"]

        sTxt = ("On how many levels are cars parked?")
        iFloors = misc.get_int(sTxt)
        if iFloors == None: return None

        if iFloors > 1 and fSqm_P < 90:
            sTxt = ("\n\aInsufficient space for a ramp " +
                    "(1:10 @ h = 3.6m, w = 2.5m). Exiting")
            return None

        if iFloors > 1:
            fSqm_P -= 90  # Take room for the ramp
        fVeh = 6.0 * fSqm_P / 100  # 6 cars per 100 sq.m
        print("fVeh:{0}; fSqm_P:{1}".format(fVeh, fSqm_P))
        iVeh = int(round(fVeh, 0))  # Round off to whole vehicles

        fVeh = iVeh * iFloors  # We need to round off per floor.
        iVeh = int(round(fVeh, 0))  # Round off to whole vehicles

        fVeh = iVeh * iNo_of_buildings  # Parking in each building
        iVeh = int(round(fVeh, 0))  # Round off to whole vehicles

        dNew_housing["aParking"]["iFloors"] = iFloors
        dNew_housing["aParking"]["iVeh"] = iVeh
        dNew_housing["aParking"]["map_a"] = fMap_area

    # BASEMENT PARKING: FOOTPRINT AREA KNOWN
    elif iParking_option == 2:
        sTxt = ("Enter the area of the parking footprint in sq.mm from map.")
        fMap_area = misc.get_float(sTxt)
        if fMap_area == None: return None

        # Calculate the parking area
        fMap_scale = dNew_housing["aMap"]["fScale"]
        aParking_area = misc.calc_area(fMap_area, fMap_scale)
        if aParking_area == None: return None

        # We know the real-world scale of the parking.
        # In the real world, a parking bay is 5.5m x 2.5m (13.75sq.m). However,
        # each vehicle needs access to that bay. The above calcuation gives
        # 7.27veh/100sq.m. However, each vehilce needs some space to get to the
        # bay. Hence, I'm using the figure of 6 veh / 100sq.m (600veh/ha)

        # Verify the units of measurement
        if aParking_area["uom"] != "sq.m":
            print(
                "\nUnexpected calculation result for residential parking:\n" +
                "Expected 'sq.m', but got {0}\a".format(aParking_area["uom"]))
            return None
        fSqm_P = aParking_area["qty"]

        print("Parking is: {0}{1}".format(aParking_area["qty"],
                                          aParking_area["uom"]))

        sTxt = ("On how many levels are cars parked?")
        iFloors = misc.get_int(sTxt)
        if iFloors == None: return None

        if iFloors > 1 and fSqm_P < 90:
            sTxt = ("\n\aInsufficient space for a ramp " +
                    "(1:10 @ h = 3.6m, w = 2.5m). Exiting")
            return None

        if iFloors > 1:
            fSqm_P -= 90  # Take room for the ramp

        fVeh = 6.0 * fSqm_P / 100
        iVeh = int(round(fVeh, 0))  # Round off to whole vehicles

        fVeh = iVeh * iFloors  # We need to round off per floor.
        iVeh = int(round(fVeh, 0))  # Round off to whole vehicles

        fVeh = iVeh * iNo_of_buildings  # Parking in each building
        iVeh = int(round(fVeh, 0))  # Round off to whole vehicles

        dNew_housing["aParking"]["iFloors"] = iFloors
        dNew_housing["aParking"]["iVeh"] = iVeh
        dNew_housing["aParking"]["map_a"] = fMap_area

    # Save the data in the array
    print("\nThese buildings park {0} vehicles".format(iVeh))

    # -- -- -- -- -- -- -- -- -- --
    #   UPDATE THE GEO-OBJECT
    dSup_hhold = dGeo_element["aSupply_hholds"]

    # Get the existing data out
    dTot_sup = dSup_hhold["total"]
    aItemised = dSup_hhold["aItemised"]

    # Update total of this particular demographic
    sGroup = dNew_housing["demographic"]  # 'r' to 'p'
    iTot_units = dNew_housing["iTot_units"]  # Household count.
    dTot_sup[sGroup] += iTot_units  # Add to the grand total

    # Generate the prototype
    dItem = {"sName": None, "r": 0, "h": 0, "m": 0, "l": 0, "p": 0}

    # Update the item
    dItem["sName"] = dNew_housing["my_id"]  # > 36 blocks possible
    dItem[sGroup] += iTot_units  # Build the item
    aItemised.append(dItem)  # Save with suburb

    # UPDATE DATA BASE
    cHousing.insert_one(dNew_housing)  # Housing pushed

    # UPDATE HOST
    xParam = {"geo_code": sGeo_code}
    xNew_data = {"$set": {"aSupply_hholds": dSup_hhold}}
    cDest.update_one(xParam, xNew_data)

    print("\n DATABASE ENTRIES UPDATED ({0})".format(sNew_id))
Esempio n. 5
0
def add_station(ccTremb):
    """ Adds details of a station to the database """

    # Obtain the highest "my_id" code that is registered in the database.

    # Get a list of all the registered base-36 codes
    xParam = {}
    xRestr = {"_id": 0, "my_id": 1}
    cStation = db.stations(ccTremb)
    dId_query = cStation.find(xParam, xRestr)
    iHighest, aEvery_id = misc.find_highest_id(dId_query)

    if (False):  # Debugging
        sTxt = "\n\nHighest number is {0}(10) < < < < < < < <"
        print(sTxt.format(iHighest))

    # We do have the highest identifier (expressed as a decimal number). Hence,
    # we can incerement the sequence and use it.
    iNext_id = iHighest + 1
    if iNext_id > 36**5:
        print("\n\aMaximum count has been exceeded")
        return None

    # Convert to base36
    sBase36 = misc.base_conv(iNext_id)
    sBase36_5 = sBase36.rjust(5, "0")
    # "0002W" -> "D00-02W"
    sNew_id = "S{0}-{1}".format(sBase36_5[:2], sBase36_5[2:])

    # START GETTING THE USER TO ENTER THE NEW DATA.
    # Open a blank dictionary, so that the elements are arranged in a certain
    # order.
    dNew_port = {
        "my_id": sNew_id,
        "host_geo_code": None,
        "aName": {
            "lat": None,
            "cyr": None
        },
        "type": None,
        "sub_type": None,
        "level": None,
        "aMap": {
            "sRegion": None,
            "iYear": None,
            "fScale": None,
            "x": None,
            "y": None,
            "a": None
        },
        "aArea": {
            "qty": None,
            "uom": None
        },
        "lServices": [],
        "lWarehouse": [],
        "iLoading_zones": 0,
    }

    # HOST
    cDest = db.destinations(ccTremb)  # To verify the geocode
    sTxt = ("\nWho is hosting this station/port? Please enter thier geo-code.")
    print(sTxt)
    sGeo_code = input().upper()

    aHost_name = misc.verify_geo_code(sGeo_code, cDest)
    if aHost_name == None: return

    dNew_port["host_geo_code"] = sGeo_code
    sTxt = "\nHosted by {0} / {1}".format(aHost_name["lat"], aHost_name["cyr"])
    print(sTxt)

    # TYPE
    sMenu = "\n"
    sMenu += "What type of a station or port is it?\n"
    sMenu += "0: Rail\n"
    sMenu += "1: Road\n"
    sMenu += "2: Water\n"
    sMenu += "3: Air\n"

    iType_option = misc.get_int(sMenu, 3)
    if iType_option == None:
        print("\a")
        return None

    if iType_option == 0:
        dNew_port["type"] = "Rail"
    elif iType_option == 1:
        dNew_port["type"] = "Road"
    elif iType_option == 2:
        dNew_port["type"] = "Water"
    elif iType_option == 3:
        dNew_port["type"] = "Air"
    else:
        print("\n\aInvalid choice for port type")
        return

# SUB-TYPE
    sMenu = "\n"
    sMenu += "What is transported?\n"
    sMenu += "0: Passangers    (PAX)\n"
    sMenu += "1: Freight       (F)\n"
    sMenu += "2: Livestock     (L/S)\n"

    iType_option = misc.get_int(sMenu, 2)
    if iType_option == None:
        print("\a")
        return None

    if iType_option == 0:
        dNew_port["sub_type"] = "Pax"
    elif iType_option == 1:
        dNew_port["sub_type"] = "Freight"
    elif iType_option == 2:
        dNew_port["sub_type"] = "Livestock"
    else:
        print("\n\aInvalid choice for port type")
        return

# LEVEL
    sMenu = "\n"
    sMenu += "What level is the station or port on?\n"
    sMenu += "0: International                   ['0V9'->'0Q1']\n"
    sMenu += "1: National / Inter-Provincial     ['V'->'L']\n"
    sMenu += "2: Provincial / Inter-District     ['GY'->'VA']\n"
    sMenu += "3: District / Inter-County         ['GYN'->'GY0']\n"
    sMenu += "4: County / Inter-Municipal        ['GYN-2'->GYN-0] \n"
    sMenu += "5: Municipal / Intra-Municipal     ['VAA-0A'->'VAA-0B'])\n"

    iLevel_option = misc.get_int(sMenu, 5)
    if iLevel_option == None:
        print("\a")
        return None

    if iLevel_option == 0:
        dNew_port["level"] = "Int'l"
    elif iLevel_option == 1:
        dNew_port["level"] = "Nat'l"
    elif iLevel_option == 2:
        dNew_port["level"] = "Prov."
    elif iLevel_option == 3:
        dNew_port["level"] = "Dist."
    elif iLevel_option == 4:
        dNew_port["level"] = "Cnty."
    elif iLevel_option == 5:
        dNew_port["level"] = "Muni."
    else:
        print("\n\aInvalid choice for port type")
        return

# MAP REFERENCE
# Obtain the reference to the CAD map. The maps available have their own
# database entry
    cMaps = db.maps_db(ccTremb)
    xParam = {}
    xRestr = {"_id": 0}
    dMap_query = cMaps.find(xParam, xRestr)

    iNo_of_maps = 0
    dMap_copy = []

    for dMap in dMap_query:
        iNo_of_maps += 1
        dMap_copy.append(dMap)

# Setup a menu of the maps available
# Setup an option of entering a region which is not mapped
    print("\nOn which map is this station/port?")

    sMenu = "0: No map\n"
    iCnt = 0

    # Go through all the available maps.
    for one_map in dMap_copy:
        iCnt += 1
        #        xScale = "{:.1e}".format(one_map["fScale"])           # 1.0e6 for 1:1M
        xScale = "{0:,}".format(int(one_map["fScale"]))  # Commas every 1000's
        sTxt = "{0}: {1}, {2} 1:{3}\n"
        sMenu += sTxt.format(iCnt, one_map["sRegion"], one_map["iYear"],
                             xScale)
    sMenu += "x: Invalid choice will exit this sub menu"
    print(sMenu)

    # Get the response from the user, with reference to the menu being offered.
    sInput = input()
    if sInput.isnumeric() == False:
        # An inbuilt 'abort' system where the user can enter 'x' to exit.
        print("\nInput is not a numeric value. Returning to menu")
        return None

    # Get the details from the dictionary and write them into the destinations
    # entry.
    iInput = int(sInput)
    if (iInput == 0):
        dNew_port["aMap"]["sRegion"] = "No Map"
        dNew_port["aMap"]["iYear"] = None
        dNew_port["aMap"]["fScale"] = None
    elif (iInput > iCnt):
        print("\nChoice out of range. Returning to menu")
        return None
    else:
        iIdx = iInput - 1
        dNew_port["aMap"]["sRegion"] = dMap_copy[iIdx]["sRegion"]
        dNew_port["aMap"]["iYear"] = dMap_copy[iIdx]["iYear"]
        dNew_port["aMap"]["fScale"] = dMap_copy[iIdx]["fScale"]

# Map location: Co-ordinates on the speciied CAD map.
    if (dNew_port["aMap"]["fScale"] != None):
        # This only works if the map exists.
        sQuestion = "\nEnter the x-coordinate from the map:"
        fX = misc.get_float(sQuestion, None, True)
        if fX == None: return None
        dNew_port["aMap"]["x"] = fX

        sQuestion = "\nEnter the y-coordinate from the map:"
        fY = misc.get_float(sQuestion, None, True)
        if fY == None: return None
        dNew_port["aMap"]["y"] = fY

        sQuestion = "\nEnter the area in mm2 from the map:"
        fA = misc.get_float(sQuestion)
        if fA == None: return None
        dNew_port["aMap"]["a"] = fA

        # Calcluate the area.
        dArea = misc.calc_area(dNew_port["aMap"]["a"],
                               dNew_port["aMap"]["fScale"])
        if dArea == None: return None
        # Compensate for inconsistency
        dArea_2 = {"val": dArea["qty"], "uom": dArea["uom"]}
        dNew_port["aArea"] = dArea_2
    # End of map location entry

# NAME IT!
    bExit = False
    while bExit == False:
        sMenu = "\nDo you want a to use host's name/a random name?"
        sRand_name_yn = misc.get_binary(sMenu)
        if sRand_name_yn == None: return None

        sName_only_lat = ""
        sName_only_cyr = ""

        # Manual entry:
        if sRand_name_yn == "N":
            print("\nPlease enter the name of the station / port in" +
                  "(Use international Keyboard)")
            sName_only_lat = input()

            # User entered name in Cyrillic
            print("\nНапиш име стацйи люб порту в Цырполюю. " +
                  "(пшэлаьч клавятурэ рэьчне)")
            sName_only_cyr = input()

    # Randomly generated Name
        elif sRand_name_yn == "Y":
            # Operated by an external routine
            import modules.x_random_names as rnd_name

            # We are storing the random names from the various systems here.
            # Hence, we will build up one set of arrays for the user to
            #choose
            aLat = []
            aCyr = []

            # Host name
            aLat.append(aHost_name["lat"])
            aCyr.append(aHost_name["cyr"])

            # Male-static:
            iNo_of_combos = 3
            aName = rnd_name.rnd_male_name(iNo_of_combos)
            aSurname = rnd_name.qRnd_static_surname(iNo_of_combos)

            for iIdx in range(iNo_of_combos):
                sName = aName[iIdx]["lat"]
                sSurname = aSurname[iIdx]["lat"]
                aLat.append("{0} {1}".format(sName, sSurname))

                sName = aName[iIdx]["cyr"]
                sSurname = aSurname[iIdx]["cyr"]
                aCyr.append("{0} {1}".format(sName, sSurname))

        # Male-dynamic:
            iNo_of_combos = 3
            aName = rnd_name.rnd_male_name(iNo_of_combos)
            aSurname = rnd_name.qRnd_dynamic_surname(iNo_of_combos)

            for iIdx in range(iNo_of_combos):
                sName = aName[iIdx]["lat"]
                sSurname = aSurname[iIdx]["lat"]
                aLat.append("{0} {1}".format(sName, sSurname))

                sName = aName[iIdx]["cyr"]
                sSurname = aSurname[iIdx]["cyr"]
                aCyr.append("{0} {1}".format(sName, sSurname))

        # Female-static:
            iNo_of_combos = 3
            aName = rnd_name.rnd_female_name(iNo_of_combos)
            aSurname = rnd_name.qRnd_static_surname(iNo_of_combos)

            for iIdx in range(iNo_of_combos):
                sName = aName[iIdx]["lat"]
                sSurname = aSurname[iIdx]["lat"]
                aLat.append("{0} {1}".format(sName, sSurname))

                sName = aName[iIdx]["cyr"]
                sSurname = aSurname[iIdx]["cyr"]
                aCyr.append("{0} {1}".format(sName, sSurname))

        # Female-dynamic:
            iNo_of_combos = 3
            aName = rnd_name.rnd_female_name(iNo_of_combos)
            aSurname = rnd_name.qRnd_dynamic_surname(iNo_of_combos)

            for iIdx in range(iNo_of_combos):
                sName = aName[iIdx]["lat"]
                sSurname = aSurname[iIdx]["lat"]
                aLat.append("{0} {1}".format(sName, sSurname))

                sName = aName[iIdx]["cyr"]
                sSurname = aSurname[iIdx]["cyr"]
                aCyr.append("{0} {1}".format(sName, sSurname))

        # Display the names
            iNo_of_names = len(aLat)
            sChoices = "0: Choose again\n"  # Don't like the options
            iCnt = 1
            for idx in range(0, iNo_of_names):
                sTxt = "{0}: {1} / {2}\n"
                sChoices += sTxt.format(iCnt, aLat[idx], aCyr[idx])
                iCnt += 1

            iChoice = misc.get_int(sChoices, iNo_of_names)
            if iChoice == None: return None  # Invalid choice
            if iChoice == 0: continue  # Choose again.
            iChoice -= 1

            # Export the final names
            sName_only_lat = aLat[iChoice]
            sName_only_cyr = aCyr[iChoice]
        # Prepare post-fix
        sLat_Intl = ""
        sCyr_Intl = ""
        if dNew_port["level"] == "Int'l":
            sLat_Intl = "International"
            # The joys of Slavic grammar!
            if dNew_port["type"] in ["Rail"]:
                sCyr_Intl = "Меьдзыщнародова"
            elif dNew_port["type"] in ["Water", "Road"]:
                sCyr_Intl = "Меьдзыщнародовы"
            elif dNew_port["type"] in ["Air"]:
                sCyr_Intl = "Меьдзыщнародовэ"

        # Type of transport
        sLat_B = ""
        sCyr_B = ""

        # Rail ####################################################
        if dNew_port["type"] == "Rail":
            if dNew_port["sub_type"] == "Pax":
                sLat_B = "Train Station"
                sCyr_B = "Стаця Колеёва"

            elif dNew_port["sub_type"] == "Freight":
                sLat_B = "Freight Station"
                sCyr_B = "Стаця Товарова"

            elif dNew_port["sub_type"] == "Livestock":
                sLat_B = "Livestock Station"
                sCyr_B = "Стаця Звъежаьт"

        # Road - - - - - - - - - - - - - - - - - - - - - - - - - - -
        elif dNew_port["type"] == "Road":
            if dNew_port["sub_type"] == "Pax":
                sLat_B = "Bus Station"
                sCyr_B = "Двожэс Алтобусовы"

            elif dNew_port["sub_type"] == "Freight":
                sLat_B = "Truck Depot"
                sCyr_B = "Двожэс Товаровы"

            elif dNew_port["sub_type"] == "Livestock":
                sLat_B = "Livestock Depo"
                sCyr_B = "Двожэс Звъежэьтьи"

        # Water ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
        elif dNew_port["type"] == "Water":
            if dNew_port["sub_type"] == "Pax":
                sLat_B = "Passanger Harbour"
                sCyr_B = "Порт Особовы"

            elif dNew_port["sub_type"] == "Freight":
                sLat_B = "Freight Harbour"
                sCyr_B = "Порт Товаровы"

            elif dNew_port["sub_type"] == "Livestock":
                sLat_B = "Livestock Harbour"
                sCyr_B = "Порт Звъежэьтьи"

        # Air > > > -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - < < <
        elif dNew_port["type"] == "Air":
            if dNew_port["sub_type"] == "Pax":
                sLat_B = "Airport"
                sCyr_B = "Лётниско"

            elif dNew_port["sub_type"] == "Freight":
                sLat_B = "Freight Airport"
                sCyr_B = "Лётниско Товаровэ"

            elif dNew_port["sub_type"] == "Livestock":
                sLat_B = "Livestock Airport"
                sCyr_B = "Лётниско Звъежэьцэ"
        else:
            print("Invalid choice. Exiting")
            return None

        # Full Latin name
        if sLat_Intl == "":
            sTxt = "{0} {1}".format(sName_only_lat, sLat_B)
        else:
            sTxt = "{0} {1} {2}".format(sName_only_lat, sLat_Intl, sLat_B)
        dNew_port["aName"]["lat"] = sTxt

        # Cyrillc grammar
        if sCyr_Intl == "":
            sTxt = "{1} о им. {0}".format(sName_only_cyr, sCyr_B)
        else:
            sTxt = "{1} {2} о им. {0}"
            sTxt = sTxt.format(sName_only_cyr, sCyr_Intl, sCyr_B)
        dNew_port["aName"]["cyr"] = sTxt

        # Confirm the name choice
        sNew_lat = dNew_port["aName"]["lat"]
        sNew_cyr = dNew_port["aName"]["cyr"]
        sMenu = "Are the names:\n'{0}'\n'{1}' OK?"
        sMenu = sMenu.format(sNew_lat, sNew_cyr)
        sNames_ok_yn = misc.get_binary(sMenu)
        if sNames_ok_yn == "Y": bExit = True
    # End of 'its named'

# SERVICES: WHICH AREA DOES THIS FACILITY SERVICE
    bDone = False  # Multiple areas.
    while bDone == False:
        sTxt = (
            "\nThis station/port serves the people of ___." +
            "\n(Enter the geo-code of the entity OR Press '.' to exit loop")
        print(sTxt)
        sGeo_code = input().upper()
        if sGeo_code in ["", None, "."]:
            bDone = True
            continue

        # Verify the geo-code
        aName = misc.verify_geo_code(sGeo_code, cDest)
        if aName == None:
            bDone = True
            continue

        # Geocode verified, add the geo code to the list
        dNew_port["lServices"].append(sGeo_code)

        sLat_name = aName["lat"]
        sCyr_name = aName["cyr"]
        print("({0} / {1})".format(sLat_name, sCyr_name))
    # end of while loop

# WAREHOUSE:
    lSta_Whs = dNew_port["lWarehouse"]  # Station warehouse
    for sTown in dNew_port["lServices"]:
        # Passanger or freight?
        if dNew_port["sub_type"] == "Pax":
            aData = {}
            # Travel demand: Why not model on Newton's equation of gravitation:
            # F = G*m1*m2 / r^2. Where, 'm' would be the population.
            xParam = {"geo_code": sTown}
            xRestr = {"_id": 0, "aDemographics": 1}
            dRun_query = cDest.find(xParam, xRestr)
            for query in dRun_query:
                aData = query["aDemographics"]

    # Freight or livestock:
        else:
            # Pull the data from the warehouses.
            dClt_whs = []  # List, client warehouse
            xParam = {"geo_code": sTown}
            xRestr = {"_id": 0, "aWarehouse": 1}
            dRun_query = cDest.find(xParam, xRestr)
            for query in dRun_query:
                dClt_whs = query["aWarehouse"]
            # The could be no data in the warehouse
            if dClt_whs == {}:
                continue

        # Extract the data from the warehouse
            for sShelf in dClt_whs:
                # Pull the data apart: look what is on the 'shelf'
                dContent = dClt_whs[sShelf]
                sResource = dContent["resource"].lower()
                fAmount = dContent["annual_output"]
                xUnits = dContent["units"]

                if xUnits == "t/yr":
                    xUnits = "t/wk"
                elif xUnits == "kg/yr":
                    xUnits = "kg/wk"
                elif xUnits == "kt/yr":
                    xUnits = "kt/wk"
                else:
                    print("Units are not presented as weight per year")

                # We have "shelves" in the warehouse already
                bNot_found = True
                for dSta_whs_shelf in lSta_Whs:
                    # Find the correct shelf to add the contents.
                    if dSta_whs_shelf["resource"] != sResource:
                        continue
                    if dSta_whs_shelf["units"] != xUnits:
                        print("\n\aUnits mismatch at the warehouse. EXITING")
                        return None

                    fWeekly_produce = round(fAmount / 52, 2)
                    fWeekly_total = dSta_whs_shelf["weekly_output"]
                    fSub_tot = round(fWeekly_total + fWeekly_produce, 2)
                    dSta_whs_shelf["weekly_output"] = fSub_tot
                    bNot_found = False

                # We need to add another shelf to the warehouse:
                if bNot_found == True:
                    dEntry = {}
                    dEntry["resource"] = sResource
                    # NOTE: Logistics run on weekly cycles.
                    dEntry["weekly_output"] = round(fAmount / 52, 2)
                    dEntry["units"] = xUnits
                    lSta_Whs.append(dEntry)
                # End of warehouse shelf created
            # end of going through each of the client's shelves
        # end of freight/livestock vs passangers
    # end of going through the towns on the include list.

    fTot_weight = 0.0
    for dEntry in dNew_port["lWarehouse"]:
        sName = dEntry["resource"]
        fAmount = dEntry["weekly_output"]
        sUnits = dEntry["units"]
        if sUnits == "t/wk":
            fTot_weight += fAmount  # Publish total weight
        elif sUnits == "kt/wk":
            fTot_weight += fAmount * 1000
        elif sUnits == "kg/wk":
            fTot_weight += fAmount / 1000
        sTxt = "{0}: {1}{2}".format(sName, fAmount, sUnits)
        print(sTxt)

    if len(dNew_port["lWarehouse"]) > 0:
        fTot_weight = round(fTot_weight, 3)  # Round off .
        fTot_daily = fTot_weight / 5.0  # MON to FRI
        fTot_daily = round(fTot_daily, 3)
        sTxt = "-------------\n"
        sTxt += "TOTAL: {0}t/wk\n".format(fTot_weight)
        sTxt += "TOTAL: {0}t/day\n".format(fTot_daily)
        print(sTxt)

# Number of loading bays
    sTxt = ("\nEnter the number of 'loading zones'. " +
            "Take into account the imports")
    iLoading_zones = misc.get_int(sTxt)
    if iLoading_zones == None: return

    dNew_port["iLoading_zones"] = iLoading_zones

    # ATTACH TO HOST
    if dNew_port["type"] == "Rail":
        if dNew_port["sub_type"] == "Pax":
            sInd_code = "QP1"  # Passanger operations
        else:
            # Freight / livestock operations
            sInd_code = "QF1"

    # ROAD TRANSPORT
    elif dNew_port["type"] == "Road":
        if dNew_port["sub_type"] == "Pax":
            sInd_code = "QB1"  # Bus operations
        else:
            sInd_code = "QT1"  # Truck port. Currently at 20t / trip

    # Air TRANSPORT
    elif dNew_port["type"] == "Air":
        if dNew_port["sub_type"] == "Pax":
            sInd_code = "QA1"  # Passanger air ops
        else:
            sInd_code = "QG1"  # Freight air ops

    dBriefcase = {
        "ccTremb": ccTremb,  # Link to all the databases
        "sGeo_code": dNew_port["host_geo_code"],  # of the host
        "sInd_code": sInd_code,  # Passanger or Freight?
        "sName_lat": dNew_port["aName"]["lat"],  # Don't overkill it.
        "sYour_id": dNew_port["my_id"],  # When constructed in city, link it!
        "aArea": dNew_port["aArea"],  # Footprint
        "iNo_of_builds": 1,  # Number of stations.
        "lServices": dNew_port["lServices"],  # Who makes use of this?
        "fCapacity": None,  # How much is used (schools, ect)
    }

    xFeedback = d_py.add_wkp_auto(dBriefcase)
    if xFeedback == None: return

    cStation.insert_one(dNew_port)
    print("\n>>>\nNew station added")
Esempio n. 6
0
def add_community_services(ccTremb):
    """ Adds the the following items to the database. It takes data from the
    map. The actual number of employees will be determined later. These can be
    placed first; its service region can be edited later. Another method will
    update these and their hosts. The list of items accessed through here is:
            5YP: Community Police station,
            5YF: Community Fire station,
            5YH: Community clinics,
            5YG: Community governance,
            ED0: Pre-school,
            ED1: Primary School,
            ED2: Middle School,
            ED3: High School,
            OAH: Standard Old Age Home,
            5SŠ: Community shop ("Small Šop"),
            5LX: Community Libraries,
            5TH: Community Theatres,
            5PO: Community Post Offices.
    """

    # Obtain the highest "my_id" code that is registered in the database.
    xParam = {}
    xRestr = {"_id": 0, "my_id": 1}
    cCommunity = db.community_services(ccTremb)
    dId_query = cCommunity.find(xParam, xRestr)
    iHighest, aEvery_id = misc.find_highest_id(dId_query)

    # We do have the highest identifier (expressed as a decimal number). Hence,
    # we can incerement the sequence and use it.
    iNext_id = iHighest + 1
    if iNext_id > 36**5:
        print("\n\aMaximum count has been exceeded")
        return None

    # Convert to base36
    sBase36 = misc.base_conv(iNext_id)
    sBase36_5 = sBase36.rjust(5, "0")
    # "0002W" -> "D00-02W"
    sNew_id = "A{0}-{1}".format(sBase36_5[:2], sBase36_5[2:])
    print("\nNext id is {0}".format(sNew_id))

    # START GETTING THE USER TO ENTER THE NEW DATA.
    # Open a blank dictionary, so that the elements are arranged in a certain
    # order.
    dNew_service = {
        "my_id": sNew_id,
        "host_geo_code": None,
        "aName": {
            "lat": None,
            "cyr": None
        },  # Is the block of flats named?
        "type_code": None,  # "5YP" for example
        "type_name": "",  # "Police"
        "iNo_of_units": 1,  # Multiple units operating from one site.
        "sub_type": None,  # RFU
        "aServes": [],  # Geo-codes of commuinties it serves.
        "iClients": 0,  # Quick summary of clients supplied
        "iCapacity": 0,  # Summary of how much we can hold
        "sNotes": "",  # Irregular building
        "aMap": {
            "sRegion": None,
            "iYear": None,
            "fScale": None,
            "x": None,
            "y": None,
            "a": None
        },
        "aFtp_bldg": {
            "qty": None,
            "uom": None
        },
        "aArea_plot": {
            "qty": None,
            "uom": None
        },
    }

    # HOST
    cDest = db.destinations(ccTremb)  # To verify the geocode
    sTxt = ("\nWho is hosting this community service?" +
            " Please enter thier geo-code.")
    print(sTxt)
    sGeo_code = input().upper()

    dHost_element = misc.get_geo_element(sGeo_code, cDest)
    if dHost_element == None: return

    dNew_service["host_geo_code"] = sGeo_code
    aHost_name = dHost_element["aName"]
    sTxt = "\nHosted by {0} / {1}".format(aHost_name["lat"], aHost_name["cyr"])
    print(sTxt)

    # MAKE A LIST OF THE SERVICES
    cCity_services = db.city_services_const(ccTremb)
    xParam = {}
    xRestr = {"_id": 0}
    dCity_query = cCity_services.find(xParam, xRestr)

    # Copy out the query
    dCity_copy = []
    for dItem in dCity_query:
        dCity_copy.append(dItem)

    # Setup the menu
    sMenu = ("\nWhich service are you adding? (Invalid entry will exit)\n")
    iCnt = 0
    for dOne_service in dCity_copy:
        iCnt += 1
        sCode = dOne_service["code"]
        sName = dOne_service["name"]
        sMenu += ("{0}: [{1}] {2}\n".format(iCnt, sCode, sName))

    # Print the menu and get the response
    iChoice = misc.get_int(sMenu, 13)
    if iChoice == None: return None

    # Select the service
    dSvc = dCity_copy[iChoice - 1]  # Count started at one!

    # Record the code
    dNew_service["type_code"] = dSvc["code"]  # 5YP for example
    dNew_service["type_name"] = dSvc["name"]  # Police for example

    # MAP REFERENCE
    sMap = dSvc["name"]
    dData = misc.get_map_input(ccTremb, sMap)  # Asks for user to input stuff.
    if dData in [None, True]:  # No map selected
        print("\n\aInvalid entry from the map. Exiting")
        return None

    # Transfer data through.
    dNew_service["aMap"] = dData["dMap"]
    dNew_service["aArea_plot"] = dData["dArea"]

    # BUILDING:
    sTxt = "Is the size of the actual building(s) known?"
    sYn_bldg = misc.get_binary(sTxt)
    if sYn_bldg == None: return None

    if sYn_bldg == "Y":
        sTxt = "\nEnter the footprint of the building in sq.mm from map."
        fBldg_ftp = misc.get_float(sTxt)
        if fBldg_ftp == None: return None

        # Calculate area
        fScale = dNew_service["aMap"]["fScale"]
        dNew_service["aFpt_bldg"] = misc.calc_area(fBldg_ftp, fScale)

# NAME THE FACILITY
    aName = misc.building_name()
    if aName == None: return None
    if aName != False:  # A name was chosen
        dNew_service["aName"] = aName

# Building count
    sTxt = ("How many units operate from this facility?")
    iNo_of_units = misc.get_int(sTxt)
    if iNo_of_units == None: return None
    dNew_service["iNo_of_units"] = iNo_of_units

    # Calculate total customer capacity:
    fTot_cust = iNo_of_units * dSvc["capacity"]
    iTot_cust = int(round(fTot_cust, 0))  # Just to be sure.
    dNew_service["iCapacity"] = iTot_cust

    # SERVICES: WHICH AREA DOES THIS FACILITY SERVICE
    # While here, show live updates of the service demand.
    sDgfx_code = dSvc["serves"]  # iTOT-PAX for example

    bDone = False  # Multiple areas.
    while bDone == False:
        sTxt = (
            "\nThis facility serves the people of ___." +
            "\n(Enter the geo-code of the entity OR Press '.' to exit loop")
        print(sTxt)
        sGeo_code = input().upper()
        if sGeo_code in ["", None, "."]:
            bDone = True
            continue

        # Verify the geo-code
        dCust_element = misc.get_geo_element(sGeo_code, cDest)
        if dCust_element == None:
            bDone = True
            continue

        # Geocode verified, add the geo code to the list
        dNew_service["aServes"].append(sGeo_code)

        sLat_name = dCust_element["aName"]["lat"]
        sCyr_name = dCust_element["aName"]["cyr"]

        # Sort out the capacity as we go along.
        sTxt = "{0} / {1}:\n".format(sLat_name, sCyr_name)
        sTxt += "{0} is ".format(sDgfx_code)

        aDgfx = dCust_element["aDemographics"]  # Shorter access
        if aDgfx == {}:
            dNew_service["sNotes"] += " {0}*,".format(sGeo_code)
            sTxt += ("N/A")
        else:
            iClients = aDgfx[sDgfx_code]
            sTxt += ("{0}\n".format(iClients))
            dNew_service["iClients"] += iClients
            iNs_clt = dNew_service["iClients"]
            iNs_cap = dNew_service["iCapacity"]
            fPercentage = iNs_clt / iNs_cap
            sPercentage = "{:.3f}".format(fPercentage)  # Hopefully "0.344"
            sTxt_a = ("Total clients: {0} / {2} = ({1} of capacity)")
            sTxt += sTxt_a.format(iNs_clt, sPercentage, iNs_cap)
        print(sTxt)

    # end of while loop, servicing the facilities.
    print("Enter comments (if any)")
    dNew_service["sNotes"] += "| "
    dNew_service["sNotes"] += input()

    # UPDATE THE WORKPLACE SUPPLY.
    # Create the element first. It will either be overridden or a new entry will
    # be created
    fDenominator = dNew_service["iCapacity"] * iNo_of_units
    if fDenominator == 0.00:
        print("\n\aDivide by zero error caught during capacity calc. Exiting")
        return None
    fNumerator = dNew_service["iClients"]
    fCapacity = fNumerator / fDenominator
    sCapacity = "{:.3}".format(fCapacity)

    dThe_item = {
        "iCnt": iNo_of_units,  # How many pre-schools in this facility
        "sCode": dSvc["code"],  # 5YH for example
        "sName": dNew_service["my_id"],  # A00-001 for example (unique)
        "lServices": dNew_service["aServes"],  # Geo-codes within the scope
        "fCapacity": sCapacity,  # Needs to be calculated
    }

    print(dThe_item)  # for aDemand_workforce
    print(dNew_service)  # Own database entry

    # WRITE TO DATABASE
    aSupply_workplace = dGeo_element["aSupply_workplace"]
    aSupply_workplace.append(dThe_item)

    xParam = {"geo_code": dNew_service["host_geo_code"]}
    xNew_data = {
        "$set": {
            "aSupply_workplace": aSupply_workplace,
        }
    }
    cDest.update_one(xParam, xNew_data)
    cCommunity.insert_one(dNew_service)

    print(">>> Databases updated ({0})".format(dNew_service["my_id"]))
Esempio n. 7
0
def qEvent_signage(dPack):
    """ This function sets up a 'trafic sign'.
    dPack = {
        "tremb": ccTremb,           # For full DB access.
        "db": cLine,                # Database entries for the line.
        "dEntry": {                 # This parameter will be passed back
            "km":fDist,             # kmilage marker
            "id":iHighest+1,        # Unique reference number
            "item":None,            # We need to fill this with our data
            "type":None,            # We need to fill this with our data
            "xVal":None},           # We need to fill this with our data
    }
    """

    dEntry = dPack["dEntry"]  # Unpack the prototype
    sMenu = ("Please select the station event from the list")
    sMenu += "Select track event:\n"
    sMenu += "0   Comment (record something unusual)\n"
    sMenu += "1   Speed limit, dir: 'away' (increasing km-count)\n"
    sMenu += "2   Speed limit, dir: 'home' (decreasing km-count)\n"

    print(sMenu)
    sInput = input().upper()

    # COMMENT
    if sInput == "0":  # Comment
        dEntry["item"] = "sign"
        dEntry["type"] = "comment"  # Type of transaction
        sTxt = "Please enter a comment regarding station"
        print(sTxt)
        dEntry["xVal"] = input()
        return dEntry

# SPEED AWAY
    if sInput == "1":
        #"dEntry":{"km":fDist,"id":0,"item":None,"type":None,"xVal":None},
        dEntry["item"] = "sign"
        dEntry["type"] = "speed_away"  # Type of transaction
        sTxt = "Please enter speed limit going away in km/h:"
        iKmh = misc.get_int(sTxt)
        if iKmh == None: return  # Error handling
        xVal = {  # For synchronisation with other signs
            "val": iKmh,
            "dis": None,
            "dur": None
        }
        dEntry["xVal"] = xVal
        return dEntry

# SPEED HOME
    if sInput == "2":
        #"dEntry":{"km":fDist,"id":0,"item":None,"type":None,"xVal":None},
        dEntry["item"] = "sign"
        dEntry["type"] = "speed_home"  # Type of transaction
        sTxt = "Please enter speed limit coming home in km/h:"
        iKmh = misc.get_int(sTxt)
        if iKmh == None: return  # Error handling
        xVal = {  # For synchronisation with other signs
            "val": iKmh,
            "dis": None,
            "dur": None
        }
        dEntry["xVal"] = xVal
        return dEntry

    else:
        print("\n\aInvalid selection. Exiting")
        return None
Esempio n. 8
0
def qEvent_track(dPack):
    """ This function builds up a piece of track for us.
        dPack = {
            "tremb": ccTremb,           # For full DB access.
            "db": cLine,                # Database entries for the line.
            "dEntry": {                 # This parameter will be passed back
                "km":fDist,             # kmilage marker
                "id":iHighest+1,        # Unique reference number
                "item":None,            # We need to fill this with our data
                "type":None,            # We need to fill this with our data
                "xVal":None},           # We need to fill this with our data
        }
"""

    dEntry = dPack["dEntry"]  # Unpack the prototype
    sMenu = (
        "The observer is looking away from the point 'km:0.00'. Hence, " +
        "'start', 'end',\n'merge', 'diverge', 'left', 'right' are biased. " +
        "'track:n' is after the track\nevent. Tracks are numbered '1' to 'n' "
        + "left to right\n\n")
    sMenu += "Select track event:\n"
    sMenu += "0   Comment (record something unusual)\n"
    sMenu += "1   Start tracks (Terminus if at km:0.00)\n"
    sMenu += "2   [RFU]   End tracks (dead-end / Storage)\n"
    sMenu += "3   Merge tracks (4 to 1 for example)\n"
    sMenu += "4   Diverge tracks (1 to 4 for example)\n"
    sMenu += "5   IXI-junction (Simultaneous bi-direct. 'lane change')\n"
    sMenu += "6   [RFU]   Rail-to-rail level crossing\n"
    sMenu += "7   [RFU]   Join two lines head-on (at a border)\n"

    print(sMenu)
    sInput = input().upper()

    # COMMENTS
    if sInput == "0":  # Comment
        dEntry["item"] = "track"
        dEntry["type"] = "comment"  # Type of transaction
        sTxt = "Please enter a comment regarding track"
        print(sTxt)
        dEntry["xVal"] = input()
        return dEntry

# START OF TRACK
    if sInput == "1":  # Start tracks
        #"dEntry":{"km":fDist,"tracks":0,"item":None,"type":None,"xVal":None},

        # Terminus question:
        if dEntry["km"] < 0.001:  # Beginning of the line from a terminus
            sTxt = "Please enter number of tracks that are starting:"
            iNew_tracks = misc.get_int(sTxt)
            if iNew_tracks == None: return None

            dEntry["item"] = "track"
            dEntry["type"] = "start_all"
            dEntry["xVal"] = iNew_tracks
        else:
            print("TODO")
            return None
        return dEntry

    if sInput == "2":  # End tracks
        print("TODO")

    if sInput == "3":  # Merge tracks
        sTxt = "Please confirm number of tracks BEFORE merger:"
        iBef = misc.get_int(sTxt)
        if iBef == None: return None

        sTxt = "Please enter number of tracks AFTER merger:"
        iAft = misc.get_int(sTxt)
        if iAft == None: return None

        dEntry["item"] = "track"
        dEntry["type"] = "merge"
        xVal = {"iBef": iBef, "iAft": iAft}
        dEntry["xVal"] = xVal
        return dEntry

    if sInput == "4":  # Diverge tracks
        sTxt = "Please confirm number of tracks BEFORE divergence:"
        iBef = misc.get_int(sTxt)
        if iBef == None: return None

        sTxt = "Please enter number of tracks AFTER divergence:"
        iAft = misc.get_int(sTxt)
        if iAft == None: return None

        dEntry["item"] = "track"
        dEntry["type"] = "diverge"
        xVal = {"iBef": iBef, "iAft": iAft}
        dEntry["xVal"] = xVal
        return dEntry

    if sInput == "5":  # IXI-junction: Allows for changes between tracks.
        # Simultaneous merge then diverge. Imagine that all the 'legs' of
        # the letters are tracks. They would form the prase "IXI"
        sTxt = "Please confirm number of tracks in 'IXI' junction:"
        iIxi = misc.get_int(sTxt)
        if iIxi == None: return None

        dEntry["item"] = "track"
        dEntry["type"] = "ixi"
        xVal = {"iBef": iIxi, "iAft": iIxi}
        dEntry["xVal"] = xVal
        return dEntry

    if sInput == "6":  # Rail-to-rail level crossing
        print("TODO")

    else:
        print("\n\aInvalid selection. Exiting")
        return None
Esempio n. 9
0
def add_sub_comp(ccTremb):
    """ This method adds to the railway line opened. Items line track switches,
    level crossings, diverges, merges, stations, ect can be added.
    """
    # Get the line input.
    # To avoid annoying the user of having to enter the line segment, lets
    # assume that the user is working on the 'latest' line. So, lets provide
    # the preselected item.
    xParam = {}
    xRestr = {"_id": 0}
    cLine = db.lines(ccTremb)
    dId_query = cLine.find(xParam, xRestr).sort("_id", -1)
    dId_query.sort("_id", -1)  # From latest to earliest

    # Pull the text for the user to know if he is working on the correct object
    sCode = dId_query[0]["my_id"]

    sTxt = ("The last worked on line was '{0}'. Would you like to work on" +
            " it more?").format(sCode)
    yn_prev_code = misc.get_binary(sTxt)
    if yn_prev_code == "N":
        print("Please enter the line code (K00-001) you would like to work on")
        sLast_code = input().upper()

# Verify the existance of the code and return a string verifying identity
    sRte_det = qVerify_line(sCode, ccTremb)
    if sRte_det == None: return None  # Error condition

    # Full confirmation message:
    sTxt = ("Are you are working on {0}".format(sRte_det))
    yn_confirm = misc.get_binary(sTxt)
    if yn_confirm == 'N': return

    # Confirmation completed. Lets get the reference point
    # Run a query on all milestones.
    xParam = {"my_id": sCode, "tag": "val"}
    xRestr = {"_id": 0}
    dQuery = cLine.find(xParam, xRestr)

    dData = []
    for query in dQuery:
        dData.append(query)  # Save data for further processing

    # Pull out the distances already entered
    s1st_line = "Enter the relative distance from the last known point"
    sMenu = "{0}:\n".format(s1st_line)
    sMenu += "0  : -.--km (beginning of the line)\n"
    iNo_of_entries = len(dData)
    iIndex = 0

    # pull out the reference numbers
    iHighest = 0

    # Offer the distances in a menu
    for idx in range(iNo_of_entries):
        iIndex += 1  # This will show up in the menu.
        sLast_item = ""
        dItem = dData[idx]["dVal"]
        sLast_item += "{:.2f}km ".format(dItem["km"])
        sLast_item += "({0}-".format(dItem["item"])
        sLast_item += "{0}-".format(dItem["type"])
        sLast_item += "{0})".format(dItem["xVal"])
        iLoc_high = dItem["id"]
        if iLoc_high > iHighest:
            iHighest = iLoc_high

        sMenu += ("{0:<3}: {1}".format(iIndex, sLast_item))[:78] + "\n"
        # Keep the string less than 78 characters (avoid collumn breaks)

    # Get the user to choose.
    iDist_choice = misc.get_int(sMenu, iIndex)
    if iDist_choice == None:
        return

    # Default option, when there is no other options.
    fDist = 0.00
    if iDist_choice != 0:
        sTxt = "Is the absolute distance known (from 0.00km)?"
        yn_abs_dist = misc.get_binary(sTxt)
        if yn_abs_dist == "Y":
            sTxt = "Please enter the absolute distance in km"
            fAbs_dist = misc.get_float(sTxt)  # Allow negative dist.
            if fAbs_dist == None: return
            fDist = round(fAbs_dist, 2)
        # We want to enter a relative distance
        else:
            sTxt = "Is the relative distance read from the map?"
            yn_rel_map = misc.get_binary(sTxt)
            if yn_rel_map == "N":
                # Relative distance is known in km.
                sTxt = "Please enter the relative distance in km"
                fRel_dist = misc.get_float(sTxt, bNeg=True)
                if fRel_dist == None: return
                fRel_dist = round(fRel_dist, 2)
            # We are reading off the map.
            else:
                # Select a map to work on
                dMap = misc.get_the_map(ccTremb)
                if dMap == None:
                    print("\n\aInvalid map selected. Exiting")
                    return None
                fScale = dMap["fScale"]

                # Ask user to input the distance on the map.
                sTxt = "Please enter the relative distance in mm from the map"
                fRel_mm = misc.get_float(sTxt, bNeg=True)
                if fRel_mm == None: return

                fRel_dist = fRel_mm * (fScale / 1e6)  # Convert map mm to km
                fRel_dist = round(fRel_dist, 2)
                print("km distance: {0}".format(fRel_dist))
            # Relative distane known. Now calculate the absolute distance
            iEntry = iDist_choice - 1  # 1-count to 0-count
            fOld_dist = dData[iEntry]["dVal"]["km"]
            fDist = fOld_dist + fRel_dist
            fDist = round(fDist, 2)
        # Absolute distance is now known.
    # Non-initial condition is being closed here.

    sMenu = "\nPlease select 'event' category:\n"
    sMenu += "1.  Build Track\n"
    sMenu += "2.  Build Junction\n"
    sMenu += "3.  Station\n"
    sMenu += "4.  Non-rail crossing\n"
    sMenu += "5.  [RFU] --- Structure\n"
    sMenu += "6.  Elevation\n"
    sMenu += "7.  [RFU] --- Signal\n"
    sMenu += "8.  Sign (speed / warning / direction)"
    print(sMenu)
    sInput = input().upper()

    dPack = {
        "tremb": ccTremb,  # For full DB access.
        "db": cLine,
        "dEntry": {
            "km": fDist,
            "id": iHighest + 1,  # Unique reference number
            "item": None,
            "type": None,
            "xVal": None
        },
    }

    if sInput == "1":
        dEntry = qEvent_track(dPack)
    elif sInput == "2":
        dEntry = qEvent_junction(dPack)
    elif sInput == "3":
        dEntry = qEvent_station(dPack)
    elif sInput == "4":
        dEntry = qEvent_crossing(dPack)
    elif sInput == "6":
        dEntry = qEvent_elevation(dPack)
    elif sInput == "8":
        dEntry = qEvent_signage(dPack)
    else:
        print("\n\aInvalid selection. Exiting")
        return

    if dEntry == None: return  # We got an error somewhere.

    # Add the item to the database
    dAdd_line = {
        "my_id": sCode,  # K00-001
        "tag": "val",  # Describes that this is the description
        "dVal": dEntry,  # The data generated
    }

    sTxt = "Is this entry OK?: \n{0}\n".format(dAdd_line)
    yn_final = misc.get_binary(sTxt)
    if yn_final == "N":
        print("User confirmation declined. Exiting")
        return

    # Add to the data base.
    cLine.insert_one(dAdd_line)
    print(">>>\nNew item added")