def qVerify_line(sK_code, ccTremb): """ Method checks the database for the existance of the K-code header. It then returns the route name details. """ # Access database cLine = db.lines(ccTremb) # Verify that the database exists: cLine = db.lines(ccTremb) xParam = {"my_id": sK_code, "tag": "meta"} xRestr = {"_id": 0} dQuery = cLine.find(xParam, xRestr) # Extract the data dMeta = "" for query in dQuery: dMeta = query # Save data for further processing if dMeta == "": print("\n\aLine {0} couldn't be found".format(sK_code)) return None sTxt = "Route [{0}], Named '{1}'" sTxt = sTxt.format(dMeta["dVal"]["route_no"], dMeta["dVal"]["sRoute_name"]) return sTxt
def pretty_print_all(ccTremb): """ Writes to a file the full line, ordered by km""" import datetime sTxt = "\nEnter the line identifier ('K00-001') to be printed" print(sTxt) sK_code = input().upper() # Verify the existance of the route sRte_det = qVerify_line(sK_code, ccTremb) if sRte_det == None: return None # Error condition # Extract the full data cLine = db.lines(ccTremb) xParam = {"my_id": sK_code, "tag": "val"} xRestr = {"_id": 0} dQuery = cLine.find(xParam, xRestr) dQuery.sort("dVal.km") # Extract the data dData = [] for query in dQuery: dData.append(query) # Save data for further processing sFile_path = "Logs/{0}_full.txt".format(sK_code) eSingle_data = open(sFile_path, "w", encoding="utf-8") sAll = "" # All data in a single string. # Write the title: xNow = datetime.datetime.now() sTxt = "Pretty print information for was generated on {0}\n".format(xNow) sAll += sTxt sAll += sRte_det + "\n" # Populated by the route verification function for dItem in dData: sTxt = "{0:7.2f}km ".format(dItem["dVal"]["km"]) sTxt += "[id:{0:>4}] ".format(dItem["dVal"]["id"]) sTxt += "{0}: ".format(dItem["dVal"]["item"]).upper() sTxt += "{0} ".format(dItem["dVal"]["type"]) sTxt += " --> {0}".format(dItem["dVal"]["xVal"]) sAll += sTxt + "\n" # Write the data to the file eSingle_data.write("{0}\n".format(sAll)) eSingle_data.close()
def pretty_print_meta(ccTremb): """ Writes elements of the meta-data entry to a file """ import datetime sTxt = "\nEnter the line identifier ('K00-001') to be printed" print(sTxt) sK_code = input().upper() # Access database cLine = db.lines(ccTremb) xParam = {"my_id": sK_code, "tag": "meta"} xRestr = {"_id": 0} dQuery = cLine.find(xParam, xRestr) # Extract the data dData = "" for query in dQuery: dData = query # Save data for further processing if dData == "": print("\n\aNo information available") return None sFile_path = "Logs/{0}_meta.txt".format(sK_code) eSingle_data = open(sFile_path, "w", encoding="utf-8") sAll = "" # All data in a single string. # Write the title: xNow = datetime.datetime.now() sTxt = "Pretty print information was generated on {0}\n".format(xNow) sAll += sTxt sAll += "METADATA:\n" dVal = dData["dVal"] sAll += "> Host Geo-code: '{0}'\n".format(dVal["host_geo_code"]) sAll += "> Route number: '{0}'\n".format(dVal["route_no"]) sAll += "> Route name: '{0}'\n".format(dVal["sRoute_name"]) sAll += "> Type of line: '{0}'\n".format(dVal["type"]) sAll += "> Starting point:'{0}'\n".format(dVal["start"]) sAll += "> Ending point: '{0}'\n".format(dVal["end"]) print(dData) # Write the data to the file eSingle_data.write("{0}\n".format(sAll)) eSingle_data.close()
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")
def calc_timetable(ccTremb): """ This method calculates the approximate time for the train to travel between the two specified points. """ # Open the 'lines' database. cLines = db.lines(ccTremb) cDest = db.destinations(ccTremb) sLine = "K00-001" # Obtain the travel durations. dSta_jct = calc_pax(cLines, sLine) if dSta_jct == None: return None if len(dSta_jct) < 1: return None # Process the array aKeys = dSta_jct[0].keys() sAll = "" sSep = ";" sAll += "km{0}type{0}code{0}name{0}s away{0}s home\n".format(sSep) for item in dSta_jct: fKm = item["km"] sType = item["type"] code = item["code"] sLat = " " if sType == "sta" and code != None: aNames = misc.verify_geo_code(code, cDest, bDont_warn=True) if aNames != None: sLat = aNames["lat"] away = item["away"] home = item["home"] sTxt = "{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}{6}\n" sTxt = sTxt.format(sSep, fKm, sType, code, sLat, away, home) sAll += sTxt # Write this data to a .csv file (to be used with excel) sFile_path = "Logs/travel_{0}.csv".format(sLine) eTravel = open(sFile_path, "w", encoding="utf-8") eTravel.write(sAll) eTravel.close() print("Please see {0}".format(sFile_path)) return True
def sub_menu(): """ Provides lines """ ccTremb = db.connect() cLine = db.lines(ccTremb) sSub_menu = """ LINES SUB-MENU (K): .: Exit 1: Open New line (Record its meta-data) 3: Pretty print one line (ordered by distance) 4: Pretty print meta data to a file 5: Add to line (Sub-component as a new entry) 6: Do a gradient (elevation change) report C: Calculate distance on map for gradient _: Remove a sub-component from the line """ # Go through the menu system. bExit = False while bExit == False: # loop until the user exits print(sSub_menu) sInput = input().upper() # Analise the user choice if sInput == ".": # Exit bExit = True elif sInput == "1": # Open new line add_line(ccTremb) elif sInput == "3": # Prints the line ordered by km. pretty_print_all(ccTremb) elif sInput == "4": # Meta-data view pretty_print_meta(ccTremb) elif sInput == "5": # New component of a line add_sub_comp(ccTremb) elif sInput == "6": pretty_gradient(ccTremb) elif sInput == "C": design_gradient(ccTremb) elif sInput == "_": remove_sub_comp(ccTremb)
def mm_star(): """ Tests a concept (This is a scratch pad, or a place to fix mistakes) """ import modules.x_database as db # Delete a single entry if False: xParam = {"dVal.id": 115} xRestr = {} ccTremb = db.connect() cDatabase = db.lines(ccTremb) dQuery = cDatabase.delete_one(xParam, xRestr) print("Specified element deleted") # Delete an entire collection if False: ccTremb = db.connect() cRnd_man = db.rnd_suffix_surname(ccTremb) dQuery = cRnd_man.delete_many({}) print(dQuery.deleted_count, " deleted items!") # Update an array if False: xParam = {"geo_code": "TJV"} # Vaenesston district xNew_data = { "$set": { "aChildren": [ "D00-09I", "D00-09J", "D00-0CM", "D00-0CN", "D00-0CO", ] } } # Prepare the update ccTremb = db.connect() cDest = db.destinations(ccTremb) dParent_query = cDest.update_one(xParam, xNew_data) # Update a bad complex value if False: dNew_data = { 'resource': 'chicken', 'annual_output': 15356, 'units': 't/yr' } xParam = {"my_id": "D00-017"} xNew_data = {"$set": {"aWarehouse.chicken farm 0": dNew_data}} ccTremb = db.connect() cDb = db.destinations(ccTremb) dQuery = cDb.update_one(xParam, xNew_data) # Delete all the geo-codes if False: parent_my_id = "D00-0AL" # Edit me. # Data base connection and selection ccTremb = db.connect() cDb = db.destinations(ccTremb) # Get the parent so we can access the children xParam = {"my_id": parent_my_id} xRestr = {"_id": 0, "aChildren": 1} dQuery = cDb.find(xParam, xRestr) # Analyse the query aChildren = [] for query in dQuery: aChildren = query["aChildren"] # copy out # Erase each child's geo-code for child in aChildren: xParam = {"my_id": child} xNew_data = {"$set": {"geo_code": None}} dQuery = cDb.update_one(xParam, xNew_data) # Global change to the structure if False: dNew_data = { "total": { "rm": 0, "rf": 0, "hm": 0, "hf": 0, "mm": 0, "mf": 0, "lm": 0, "lf": 0, "pm": 0, "pf": 0 }, "aItemised": [], } xParam = {} xNew_data = {"$set": {"aSupply_workforce": dNew_data}} ccTremb = db.connect() cDb = db.destinations(ccTremb) dQuery = cDb.update_many(xParam, xNew_data) # Update a bad simple value if False: dNew_data = "Fusþton" xParam = {'sRegion': 'Loggers Crossing'} # xNew_data = {"$set": {"aVehicles.aItemised.Blàhim" : dNew_data}} xNew_data = {"$set": {'sRegion': dNew_data}} ccTremb = db.connect() cDb = db.maps_db(ccTremb) dQuery = cDb.update_one(xParam, xNew_data) # dQuery = cDb.update_many(xParam, xNew_data) # delete an element if False: xParam = {"geo_code": "GYG"} xNew_data = {"$unset": {"aDemogfx_item": 0, "aWhs_item": 0}} ccTremb = db.connect() cDb = db.destinations(ccTremb) dQuery = cDb.update_one(xParam, xNew_data) # Oblitorate everything except the name, children, area data. # Basically, erase balancing when it was not required. if False: xParam = {"geo_code": "VXA-J"} # Vaenesston district xNew_data = { "$set": { # 'aMap': { # 'sRegion': 'Vænesston', # 'iYear': '2019', # 'fScale': 2000000.0, # 'x': None,'y': None,'a': None}, "aDemand_workforce": { "total": { "rm": 0, "rf": 0, "hm": 0, "hf": 0, "mm": 0, "mf": 0, "lm": 0, "lf": 0, "pm": 0, "pf": 0 }, "aItemised": [] }, "aSupply_workforce": { "total": { "rm": 0, "rf": 0, "hm": 0, "hf": 0, "mm": 0, "mf": 0, "lm": 0, "lf": 0, "pm": 0, "pf": 0 }, "aItemised": [] }, "aDemand_hholds": { "total": { "r": 0, "h": 0, "m": 0, "l": 0, "p": 0 }, "aItemised": [] }, "aSupply_hholds": { "total": { "r": 0, "h": 0, "m": 0, "l": 0, "p": 0 }, "aItemised": [] }, "aDemographics": {}, "aVehicles": {}, "aFootprint": {}, "aWarehouse": {} } } # Prepare the update ccTremb = db.connect() cDest = db.destinations(ccTremb) dParent_query = cDest.update_one(xParam, xNew_data)
def qLine_gradient(sK_code, ccTremb): """ Method takes in the 'K-code' (K00-001) for Vænesston - Fusþton Line. It then extracts the elevation information and computes the grade of the track. """ # Access database cLine = db.lines(ccTremb) # K-CODE EXISTS?: cLine = db.lines(ccTremb) xParam = {"my_id": sK_code, "tag": "meta"} xRestr = {"_id": 0} dQuery = cLine.find(xParam, xRestr) # Extract the data dMeta = "" for query in dQuery: dMeta = query # Save data for further processing if dMeta == "": print("\n\aLine does not exist") return None # EXTRACT THE DATA xParam = { "my_id": sK_code, # Only this line "tag": "val", # Only true data "dVal.item": "elev_ft" # Only elevation data. } xRestr = {"_id": 0} dQuery = cLine.find(xParam, xRestr) dQuery.sort("dVal.km") # Extract the data dRaw = [] for query in dQuery: dRaw.append(query) # Save data for further processing # my_id and tag have been assured by the database query. extract the # 'interesting' stuff. dData = [] for item in dRaw: dItem = { "km": item["dVal"]["km"], "type": item["dVal"]["type"], "elev_ft": item["dVal"]["xVal"] } dData.append(dItem) # misc.write_debug_txt(dData) # See what we found # Prepare for calculation: dGradient = [] iNo_of_items = len(dData) # Working in pairs of values. # TERRAIN: for iCnt in range(1, iNo_of_items): # Process the spot elevation first. if dData[iCnt]["type"] != "spot": # spot elevation, not trapezoidal continue # Loop to the next iteration. # LOOK FOR THE PREVIOUS 'SPOT' HEIGHT. # We are a spot. Lets look back to find the previous spot. iPrev_spot_idx = None # Either next or 5 back... read on # There could be a bridge or tunnel behind us. Also, there could be # an error in its entry. At this stage, we don't care. We just want # to find the last spot height. for iIdx in range(iCnt - 1, -1, -1): # Go backwards if dData[iIdx]["type"] == "spot": iPrev_spot_idx = iIdx break if iPrev_spot_idx == None: print("\n\aERROR: Unable to find previous spot height") return None # DO THE CALCULATION fKm_now = dData[iCnt]["km"] fKm_bef = dData[iPrev_spot_idx]["km"] fFt_now = dData[iCnt]["elev_ft"] fFt_bef = dData[iPrev_spot_idx]["elev_ft"] # Calculation is common to 'terrain' and 'structure' items. dItem = q_grad_calc(fKm_now, fKm_bef, fFt_now, fFt_bef) dItem["type"] = "Terrain" dGradient.append(dItem) # End of the elevation loop loop # BRIDGES AND TUNNELS: # Run the bridges and tunnels as a second pass. for iCnt in range(iNo_of_items): if dData[iCnt]["type"] != "trapezoid": continue # Loop to the next iteration. iExam = iCnt + 0 if dData[iExam]["elev_ft"] == 0: # Beginning or End of a structure # Test for beginning: look at the previous item iExam = iCnt - 1 # Does the previous item exist? if iExam < 0: sError = ("\n\aERROR: Structure needs a preceeding " + "'spot elevation' for correct operation\n") print(sError) return None bBegin = False # Test if this is the first structure after a spot height if dData[iExam]["type"] == "spot": bBegin = True # Test if the previous structure was terminated if (dData[iExam]["type"] == "trapezoid" and dData[iExam]["elev_ft"] == 0): bBegin = bBegin or True # We have a beginning of a structure. if bBegin: # VERIFY ELEMENTS IN SUB-STRUCTURE (0, [+20, +20, 0]) for iOffset in range(1, 4): # There are iExam = iCnt + iOffset # Look forwards at the data if iExam >= iNo_of_items: sError = ("\n\aERROR: Structure has suddenly ended " + "(listing error)\n") print(sError) return None if (dData[iExam]["type"] != "trapezoid"): # Wrong type sError = ( "\n\aERROR: Structure has suddenly ended " + "(non-structural item found as a next element)\n") print(sError) return None if iOffset in [1, 2] and dData[iExam]["elev_ft"] == 0: sError = ( "\n\aERROR: Structure's central 'span' is " + "not elevated or depressed. Expected non-zero number" ) print(sError) return None if iOffset == 3 and dData[iExam]["elev_ft"] != 0: sError = ("\n\aERROR: Structure has no termination") print(sError) return None # End going through the next 3 following points of the structure # CALCULATE THE ACTUAL ELEVATIONS AT ALL THE 4 SPOTS: # Lets use the previous calculations which generated a list # of dictionaries named 'dGradient'. Lets look through it and # try to find the piece of terrain we are working on. iIdx = None # Entry pointer w/ error detect km_tgt = dData[iCnt]["km"] # Our target milepost for dItem in dGradient: if (dItem["km_bef"] < km_tgt < dItem["km_now"] and dItem["type"] == "Terrain"): iIdx = dGradient.index(dItem) break if iIdx == None: sTxt = ("\n\aERROR: Unable to find host terrain section.") return None # Calculate ft/km gradient. This gives us both units. dTerrain = dGradient[iIdx] # Extract the entry fFt_per_km = dTerrain["ft_del"] / dTerrain["km_del"] # distance from beginning of terrain setion to the structure # Initialisation of the loop: afFt = [0, 0, 0, 0] fKm_bef = dTerrain["km_bef"] # Calculate the equivalent 'spot' elevations for iOffset in range(4): # Build up the km iNow = iCnt + iOffset fKm_str = dData[iNow]["km"] # Structure element fLoc_km = round(fKm_str - fKm_bef, 2) # Local km # how much has the terrain changed upto our structure: fFt_del = fLoc_km * fFt_per_km # ft = km * ft/km # What is the absolue elevation at the foot of the bridge? # 1.) Use ratio and proportion to get the base of element. fFt_terrain = dTerrain["ft_bef"] + fFt_del # 2.) Add the relative change of the structure fFt_struct = fFt_terrain + dData[iNow]["elev_ft"] # 3.) Round off and save. afFt[iOffset] = round(fFt_struct, 1) # Calculate the actual gradients of the structure for iCalc in range(1, 4): # DO THE CALCULATION iNow = iCnt + iCalc - 0 fKm_now = dData[iNow - 0]["km"] fKm_bef = dData[iNow - 1]["km"] fFt_now = afFt[iCalc - 0] fFt_bef = afFt[iCalc - 1] # Calculation is common to 'terrain' and 'structure' items. dItem = q_grad_calc(fKm_now, fKm_bef, fFt_now, fFt_bef) dItem["type"] = "Structure" dGradient.append(dItem) # End of finding the beginning of the structure # End of delta elevation is zero # All the bridges and tunnels have been sorted out. Lets sort the list dSorted = sorted(dGradient, key=lambda i: i["km_bef"]) # Debug: to see what the track data actually looks like. return dSorted # Return the array of tracks.
def add_line(ccTremb): """ Creates a new railway line meta-data header in the database. Use the 'append' function to add the details to it. However, those details will be dataase entries themselves. This is the classic debate, few large documents vs lots of small documents.""" # Obtain the highest "my_id" code already registered. # Get a list of all the registered base-36 codes xParam = {} xRestr = {"_id": 0, "my_id": 1} cLine = db.lines(ccTremb) dId_query = cLine.find(xParam, xRestr) iHighest, aEvery_id = misc.find_highest_id(dId_query) if (True): # 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 = "K{0}-{1}".format(sBase36_5[:2], sBase36_5[2:]) # Display the number print("\nCode assigned will be: '{0}'".format(sNew_id)) # PREPARE THE TEMPLATE # Open a blank dictionary. I need to arrange the elements in order dNew_line = { "my_id": sNew_id, # K00-001 "tag": "meta", # Describes that this is the description "dVal": { "host_geo_code": None, # VA "route_no": None, # RFU for road B96 "sRoute_name": "", # "Vænesston-Kændis Beach (VA-FS)" "type": None, # RFU "start": None, # Where is the zero km count "end": None, # Where is the maximum point } # Closes "dVal" for the meta data } # GET THE HOST: sTxt = ( "\n\nPlease note that an unregistered host may be entered. Fill " + "out the known part\nof the geocode. Enter '?' as the final " + "character. Geocode will not be verified.\nIt will be entered as " + "'Unnamed'" + "\n\nPlease enter the geo-code of the Host:") print(sTxt) sGeo_code = input().upper() # Confirm host exists if sGeo_code[-1] != "?": cDest = db.destinations(ccTremb) aHost_name = misc.verify_geo_code(sGeo_code, cDest) if aHost_name == None: print("\n\aUnrecognised host name. Exiting") return sTxt = "\nHosted by {0} / {1}" print(sTxt.format(aHost_name["lat"], aHost_name["cyr"])) # Save the geocode dNew_line["dVal"]["host_geo_code"] = sGeo_code # ROUTE NUMBER sTxt = "Is the route number (Б96 for example) known?" yn_route = misc.get_binary(sTxt) if yn_route == "Y": sTxt = "\nPlease enter the route number:" dNew_line["dVal"]["route_no"] = input().upper() else: dNew_line["dVal"]["route_no"] = None # NAME OF THE STRETCH sTxt = ("\nPlease enter the name of this stretch. For example:\n" + "Vænesston-Kændis Beach (VA-FS)") print(sTxt) dNew_line["dVal"]["sRoute_name"] = input() # TODO: TYPE OF LINE # STARTING POINT sTxt = "\nIs the STARTING point known?" yn_start = misc.get_binary(sTxt) if yn_start == "Y": sTxt = ("\nWhere is the starting point? (Ex: 'VAA-00', " + "'[email protected]')") print(sTxt) dNew_line["dVal"]["start"] = input() else: print("TODO 'AXUZI'") return None # FINISHING POINT sTxt = "\nIs the ENDING point known?" yn_end = misc.get_binary(sTxt) if yn_end == "Y": sTxt = ("\nWhere is the ending point? (Ex: 'FS0', '[email protected]')") print(sTxt) dNew_line["dVal"]["start"] = input() else: print("TODO 'BZHAK'") return None # Meta data captured: cLine.insert_one(dNew_line) print(">>>\nNew line OPENED")
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")