pyCruiseMapper/src/pycruisemapper/classes/ship.py
2022-09-15 16:54:31 +00:00

200 lines
6.4 KiB
Python

from datetime import datetime, timedelta
from typing import Optional, List, Tuple
from locale import setlocale, LC_ALL
import re
from .location import Location
from .cruise import Cruise
from .flag import Flag
from .shipline import ShipLine
from ..const import IMAGE_BASE_PATH, TEMP_REGEX, HTML_REGEX, DEGREES_REGEX, SPEED_REGEX, GUST_REGEX
class Ship:
id: Optional[int]
name: Optional[str]
url: Optional[str]
url_deckplans: Optional[str]
url_staterooms: Optional[str]
image: Optional[str]
flag: Optional[Flag]
line: Optional[ShipLine]
spec_length: Optional[int] # stored in meters
spec_passengers: Optional[int]
year_built: Optional[int]
last_report: Optional[str]
imo: Optional[int]
mmsi: Optional[int]
latitude: Optional[float]
longitude: Optional[float]
cog: Optional[int] # Course over Ground
sog: Optional[int] # Speed over Ground
heading: Optional[int]
timestamp: Optional[datetime]
icon: Optional[int]
hover: Optional[str]
cruise: Optional[Cruise]
path: Optional[List[Optional[Location]]]
ports: Optional[List[Optional[Tuple[Optional[datetime], Optional[Location]]]]]
destination: Optional[str]
eta: Optional[datetime]
current_temperature: Optional[float] # Celsius
minimum_temperature: Optional[float] # Celsius
maximum_temperature: Optional[float] # Celsius
wind_degrees: Optional[float]
wind_speed: Optional[float] # m/s
wind_gust: Optional[float] # m/s
localtime: Optional[str]
@classmethod
def from_dict(cls, indict: dict):
obj = cls()
obj.id = indict.get("id")
obj.name = indict.get("name", indict.get("ship_name"))
obj.url = indict.get("url")
obj.url_deckplans = indict.get("url_deckplans")
obj.url_staterooms = indict.get("url_staterooms")
if "image" in indict:
obj.image = f"{IMAGE_BASE_PATH}{indict.get('image')}"
if "flag" in indict:
obj.flag = Flag(
code=indict["flag"].get("code"),
name=indict["flag"].get("name")
)
elif "ship_flag" in indict:
obj.flag = Flag(
code=indict.get("ship_flag")
)
if "line" in indict:
obj.line = ShipLine(
id=int(indict["line"]["id"]),
title=indict["line"].get("title"),
url=indict["line"].get("url")
)
elif "ship_line_id" in indict:
obj.line = ShipLine(
id=indict.get("ship_line_id"),
title=indict.get("ship_line_title")
)
if "spec_length" in indict:
parts = indict["spec_length"].split("/")
for part in parts:
if "m" in part:
try:
obj.spec_length = float(part.strip().split()[0])
except:
pass
if "spec_passengers" in indict:
obj.spec_passengers = int(indict["spec_passengers"])
if "year_of_built" in indict: # Those field names... 🤦
obj.year_built = int(indict["year_of_built"])
obj.last_report = indict.get("last_report")
if "imo" in indict:
obj.imo = int(indict["imo"])
if "mmsi" in indict:
obj.mmsi = int(indict["mmsi"])
if "lat" in indict and "lon" in indict:
obj.location = Location(indict["lat"], indict["lon"])
if "cog" in indict:
obj.cog = int(indict["cog"])
if "sog" in indict:
obj.sog = int(indict["sog"])
if "heading" in indict:
obj.heading = int(indict["heading"])
if "ts" in indict:
obj.timestamp = datetime.fromtimestamp(indict[ts])
obj.icon = indict.get("icon")
obj.hover = indict.get("hover")
if "cruise" in indict:
obj.cruise = Cruise.from_dict(indict["cruise"])
if "path" in indict:
if "points" in indict["path"]:
obj.path = list()
for point in indict["path"]["points"]:
lon, lat = point
obj.path.append(Location(lat, lon))
if "ports" in indict["path"]:
obj.ports = list()
for port in indict["path"]["ports"]:
if "dep_datetime" in port:
departure = datetime.strptime(
port["dep_datetime"], "%Y-%m-%d %H:%M:%S")
else:
departure = None
if "lat" in port and "lon" in port:
location = Location(port["lat"], port["lon"])
else:
location = None
obj.ports.append(departure, location)
obj.destination = indict.get("destination")
if "eta" in indict:
try:
previous = setlocale(LC_ALL)
setlocale(LC_ALL, "C")
obj.eta = datetime.strptime(date_string, "%d %B, %H:%M")
setlocale(LC_ALL, previous)
except:
obj.eta = None
if "weather" in indict:
temp_regex = re.compile(TEMP_REGEX)
html_regex = re.compile(HTML_REGEX)
degrees_regex = re.compile(DEGREES_REGEX)
speed_regex = re.compile(SPEED_REGEX)
gust_regex = re.compile(GUST_REGEX)
if "temperature" in indict["weather"]:
obj.current_temperature = float(re.search(temp_regex, re.sub(
html_regex, "", indict["weather"]["temperature"])).groups()[0])
if "wind" in indict["weather"]:
try:
obj.wind_degrees = int(
re.search(degrees_regex, indict["weather"]["wind"]).groups()[0])
except:
pass
try:
obj.wind_speed = float(
re.search(speed_regex, indict["weather"]["wind"]).groups()[0])
except:
pass
try:
obj.wind_gust = float(
re.search(speed_regex, indict["weather"]["wind"]).groups()[0])
except:
pass
obj.localtime = indict["weather"].get("localtime")
return obj
def __repr__(self):
return self.__dict__.__repr__()