initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__pycache__
|
||||||
85
classes.py
Normal file
85
classes.py
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
from enum import Enum
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
class ParsingMode(Enum):
|
||||||
|
LOCATIONS = 1
|
||||||
|
FLIGHTSCHEDULE = 2
|
||||||
|
FINDCONNECTION = 3
|
||||||
|
|
||||||
|
|
||||||
|
class LocationType(Enum):
|
||||||
|
LOCATION = 1
|
||||||
|
HALTESTELLE = 2
|
||||||
|
FLUGHAFEN = 3
|
||||||
|
|
||||||
|
|
||||||
|
class TransportData():
|
||||||
|
def __init__(self, co2: float, speed: float, distance_penalty: float):
|
||||||
|
self.co2 = co2
|
||||||
|
self.speed = speed
|
||||||
|
self.distance_penalty = distance_penalty
|
||||||
|
|
||||||
|
|
||||||
|
class TransportMethod(Enum):
|
||||||
|
"""
|
||||||
|
(co2 emission, speed, distance_penalty)
|
||||||
|
"""
|
||||||
|
WALK = TransportData(0, 4, 0.2)
|
||||||
|
CITY = TransportData(0.189, 30, 0.2)
|
||||||
|
AUTOBAHN = TransportData(0.189, 100, 0.2)
|
||||||
|
OEPNV = TransportData(0.055, 30, 0.1)
|
||||||
|
ICE = TransportData(0.055, 100, 0.1)
|
||||||
|
AIRPLANE = TransportData(0.2113, 900, 0.02)
|
||||||
|
|
||||||
|
|
||||||
|
class Coordinate:
|
||||||
|
def __init__(self, lat: float, long: float):
|
||||||
|
self.lat = lat
|
||||||
|
self.long = long
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Lat: {self.lat}, Long: {self.long}"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
|
||||||
|
class Location:
|
||||||
|
def __init__(self, coord: Coordinate, continent: int, name: str, type: LocationType):
|
||||||
|
self.coord = coord
|
||||||
|
self.continent = continent
|
||||||
|
self.name = name
|
||||||
|
self.type = type
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{{Location: {self.coord}, continent: {self.continent}, name: {self.name}, type: {self.type}}}"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
def distance(self, loc2) -> float:
|
||||||
|
"""
|
||||||
|
Calculate the distance im km between two locations with the help of the
|
||||||
|
Seitenkosinussatz
|
||||||
|
"""
|
||||||
|
rErde = 6378.388
|
||||||
|
lat1 = float(self.coord.lat)
|
||||||
|
long1 = float(self.coord.long)
|
||||||
|
lat2 = float(loc2.coord.lat)
|
||||||
|
long2 = float(loc2.coord.long)
|
||||||
|
inner = math.sin(lat1) * math.sin(lat2) + math.cos(lat1) * math.cos(lat2) * math.cos(long2 - long1)
|
||||||
|
return rErde * math.acos(inner)
|
||||||
|
|
||||||
|
|
||||||
|
class DataSet:
|
||||||
|
def __init__(self, locations: dict, flights: dict, connection: tuple):
|
||||||
|
self.locations = locations
|
||||||
|
self.flights = flights
|
||||||
|
self.connection = connection
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"locations: {self.locations}, flights: {self.flights}, connection: {self.connection}"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.__str__()
|
||||||
77
dijkstra.py
Normal file
77
dijkstra.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
"""
|
||||||
|
Module, which holds the logic for the solving algorithms
|
||||||
|
"""
|
||||||
|
|
||||||
|
from classes import DataSet, LocationType, Location, TransportMethod
|
||||||
|
|
||||||
|
|
||||||
|
def calc_co2(distance: float, method: TransportMethod) -> float:
|
||||||
|
"""
|
||||||
|
Return co2 emission in kg
|
||||||
|
"""
|
||||||
|
return (distance * method.value.distance_penalty) * method.value.co2
|
||||||
|
|
||||||
|
|
||||||
|
def calc_time(distance: float, method: TransportMethod) -> float:
|
||||||
|
"""
|
||||||
|
Return time taking in h
|
||||||
|
"""
|
||||||
|
return (distance * method.value.distance_penalty) / method.value.speed
|
||||||
|
|
||||||
|
|
||||||
|
def add_node(graph: dict, frm: str, to: str, locs: dict, method: TransportMethod):
|
||||||
|
"""
|
||||||
|
Add a node into the graph
|
||||||
|
"""
|
||||||
|
distance = locs[frm].distance(locs[to])
|
||||||
|
co2 = calc_co2(distance, method)
|
||||||
|
time = calc_time(distance, method)
|
||||||
|
new_connection: dict = {to: {"type": method, "co2": co2, "time": time}}
|
||||||
|
graph[frm].append(new_connection)
|
||||||
|
print(f"Added node from {frm} to {to} with type {method}.")
|
||||||
|
|
||||||
|
|
||||||
|
def create_graph(dataset: DataSet) -> dict:
|
||||||
|
"""
|
||||||
|
Creates the initial graph, with all edges
|
||||||
|
"""
|
||||||
|
locations = dataset.locations
|
||||||
|
graph: dict = {}
|
||||||
|
|
||||||
|
# add nodes with no edges
|
||||||
|
for start in locations:
|
||||||
|
graph.update({start: []})
|
||||||
|
|
||||||
|
# add edges
|
||||||
|
for start in locations:
|
||||||
|
for dest in locations:
|
||||||
|
# skip, if we wouldnt go anywhere
|
||||||
|
if start == dest:
|
||||||
|
continue
|
||||||
|
print(f"Searching for nodes from {start} to {dest}...")
|
||||||
|
distance = locations[start].distance(locations[dest])
|
||||||
|
|
||||||
|
# Individualtransport
|
||||||
|
if distance <= 1:
|
||||||
|
add_node(graph, start, dest, locations, TransportMethod.WALK)
|
||||||
|
if distance <= 10 + 1:
|
||||||
|
add_node(graph, start, dest, locations, TransportMethod.CITY)
|
||||||
|
if distance <= 2000 + 10 + 1:
|
||||||
|
add_node(graph, start, dest, locations, TransportMethod.AUTOBAHN)
|
||||||
|
|
||||||
|
# Train
|
||||||
|
if locations[start].type == LocationType.HALTESTELLE:
|
||||||
|
dest_type = locations[dest].type
|
||||||
|
# there are only trains between haltestellen or airports
|
||||||
|
if dest_type == LocationType.HALTESTELLE or dest_type == LocationType.FLUGHAFEN:
|
||||||
|
if distance <= 25:
|
||||||
|
add_node(graph, start, dest, locations, TransportMethod.OEPNV)
|
||||||
|
else:
|
||||||
|
add_node(graph, start, dest, locations, TransportMethod.ICE)
|
||||||
|
|
||||||
|
# Flying
|
||||||
|
flights = dataset.flights
|
||||||
|
for flight in flights:
|
||||||
|
add_node(graph, start, dest, locations, TransportMethod.AIRPLANE)
|
||||||
|
|
||||||
|
return graph
|
||||||
13
file.txt
Normal file
13
file.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Locations:
|
||||||
|
csu_zen ; Location; 48.176971; 11.5895754; 1; CSU-Zentrale
|
||||||
|
mun_hbf ; PublicTransportStop; 48.140235; 11.559417; 1; Muenchen Hbf.
|
||||||
|
mun_flugh; Airport; 48.140235; 11.770723; 1; Muenchen Flughafen
|
||||||
|
reichstag; Location; 52.518191; 13.3751725; 1; Reichstags Gebaeude
|
||||||
|
ber_flugh; Airport; 52.553625; 13.2901544; 1; Berlin Flughafen Tegel
|
||||||
|
ber_hbf ; PublicTransportStop; 52.524195; 13.3693013; 1; Berlin Hbf
|
||||||
|
|
||||||
|
FlightSchedule:
|
||||||
|
mun_flugh; ber_flugh; 0; True
|
||||||
|
|
||||||
|
FindBestConnections:
|
||||||
|
csu_zen; muc
|
||||||
21
main.py
Normal file
21
main.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
"""
|
||||||
|
Run program from here.
|
||||||
|
Requires: python > 3.10.x
|
||||||
|
"""
|
||||||
|
|
||||||
|
from parser import parse
|
||||||
|
from dijkstra import create_graph
|
||||||
|
|
||||||
|
|
||||||
|
INPUTFILE = "file.txt"
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
dataset: dict = parse(INPUTFILE)
|
||||||
|
print(dataset)
|
||||||
|
graph: dict = create_graph(dataset)
|
||||||
|
print(graph)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
78
parser.py
Normal file
78
parser.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
"""
|
||||||
|
Parse the input file
|
||||||
|
"""
|
||||||
|
|
||||||
|
from classes import ParsingMode, Coordinate, LocationType, Location, DataSet
|
||||||
|
|
||||||
|
|
||||||
|
def parse(filename: str) -> DataSet:
|
||||||
|
"""
|
||||||
|
Parse a given file with given format and return a DataSet containing the
|
||||||
|
parsed locations, flightschedules and wanted connection
|
||||||
|
"""
|
||||||
|
locations: dict = {}
|
||||||
|
flights: dict = {}
|
||||||
|
connection: tuple = ()
|
||||||
|
with open(filename, "r") as file:
|
||||||
|
for line in file.readlines():
|
||||||
|
line = line.replace("\n", "") # strip newline
|
||||||
|
line = line.replace(" ", "") # strip whitespaces
|
||||||
|
|
||||||
|
# skip empty lines
|
||||||
|
if line == "":
|
||||||
|
continue
|
||||||
|
|
||||||
|
# meta parsing
|
||||||
|
match line:
|
||||||
|
case "Locations:":
|
||||||
|
print("Parsing `Locations`...")
|
||||||
|
current_parsing = ParsingMode.LOCATIONS
|
||||||
|
continue
|
||||||
|
case "FlightSchedule:":
|
||||||
|
print("Parsing `FlightSchedule`...")
|
||||||
|
current_parsing = ParsingMode.FLIGHTSCHEDULE
|
||||||
|
continue
|
||||||
|
case "FindBestConnections:":
|
||||||
|
print("Parsing `FindBestConnections`...")
|
||||||
|
current_parsing = ParsingMode.FINDCONNECTION
|
||||||
|
continue
|
||||||
|
|
||||||
|
match current_parsing:
|
||||||
|
case ParsingMode.LOCATIONS:
|
||||||
|
print("Parsing location...")
|
||||||
|
splitted = line.split(";")
|
||||||
|
assert(len(splitted) == 6) # make sure we have a location
|
||||||
|
id = splitted[0]
|
||||||
|
type = splitted[1]
|
||||||
|
match type:
|
||||||
|
case "Location":
|
||||||
|
type = LocationType.LOCATION
|
||||||
|
case "PublicTransportStop":
|
||||||
|
type = LocationType.HALTESTELLE
|
||||||
|
case "Airport":
|
||||||
|
type = LocationType.FLUGHAFEN
|
||||||
|
lat = splitted[2]
|
||||||
|
long = splitted[3]
|
||||||
|
continent = splitted[4]
|
||||||
|
name = splitted[5]
|
||||||
|
coord = Coordinate(lat, long)
|
||||||
|
location = Location(coord, continent, name, type)
|
||||||
|
locations.update({id: location})
|
||||||
|
case ParsingMode.FLIGHTSCHEDULE:
|
||||||
|
print("Parsing flight schedule...")
|
||||||
|
splitted = line.split(";")
|
||||||
|
assert(len(splitted) >= 2)
|
||||||
|
id1 = splitted[0]
|
||||||
|
id2 = splitted[1]
|
||||||
|
if len(splitted) == 3:
|
||||||
|
stops = splitted[2]
|
||||||
|
else:
|
||||||
|
stops = 0
|
||||||
|
flights.update({id1: {"to": id2, "stops": stops}})
|
||||||
|
continue
|
||||||
|
case ParsingMode.FINDCONNECTION:
|
||||||
|
print("Parsing connection...")
|
||||||
|
splitted = line.split(";")
|
||||||
|
assert(len(splitted) == 2)
|
||||||
|
connection = (splitted[0], splitted[1])
|
||||||
|
return DataSet(locations, flights, connection)
|
||||||
Reference in New Issue
Block a user