-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathvisibility.py
72 lines (62 loc) · 2.16 KB
/
visibility.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import re
from fractions import Fraction
from aviation_weather.components import Component
from aviation_weather.exceptions import VisibilityDecodeError
class Visibility(Component):
def __init__(self, raw):
"""Parse `raw` to create a new Visibility object.
Args:
raw (str): The visibility to be parsed.
Raises:
VisibilityDecodeError: If `raw` could not be parsed.
"""
m = re.search(
r"\b(?:(?P<lt_gt>[MP])?(?P<distance1>\d[ \d/]{,4})(?P<unit>SM)|(?P=lt_gt)?(?P<distance2>\d{4})|(?P<cavok>CAVOK))\b",
raw
)
if not m:
raise VisibilityDecodeError("Visibility(%r) could not be parsed" % raw)
if m.group("cavok"):
self.cavok = True
self.distance = None
self.greater_than = False
self.less_than = False
self.unit = None
else:
self.cavok = None
self.less_than = m.group("lt_gt") == "M"
self.greater_than = m.group("lt_gt") == "P"
distance = m.group("distance1") or m.group("distance2")
self.unit = m.group("unit") or "m"
if "/" in distance:
parts = distance.split(" ", 1)
if len(parts) == 1:
self.distance = float(Fraction(parts[0]))
else:
self.distance = int(parts[0]) + float(Fraction(parts[1]))
else:
self.distance = int(distance)
@property
def raw(self):
if self.cavok:
return "CAVOK"
else:
if self.less_than:
raw = "M"
elif self.greater_than:
raw = "P"
else:
raw = ""
whole = self.distance // 1
fraction = Fraction(self.distance % 1)
if whole and fraction:
raw += "%d %s" % (whole, fraction)
elif whole:
raw += str(whole)
elif fraction:
raw += str(fraction)
else:
raw += "0"
if self.unit != "m":
raw += self.unit
return raw