# Modelado de una torre de contral
# con OVs (objetos volantes),
# que pueden colisionar.
import math
class Pos:
"""Pos: x, y, z"""
X = 0
Y = 1
Z = 2
ORG = None
@staticmethod
def org():
"""Devuelve el origen de coordenadas.
:return: el objeto Pos(0, 0, 0)
"""
if not Pos.ORG:
Pos.ORG = Pos(0, 0, 0)
...
return Pos.ORG
...
def __init__(self, x, y, z):
self._pos = [x, y, z]
...
def __len__(self):
return len(self._pos)
...
def __getitem__(self, item):
return self._pos[item]
...
@property
def x(self):
return self._pos[0]
...
@property
def y(self):
return self._pos[1]
...
@property
def z(self):
return self._pos[2]
...
def distancia_a(self, otro):
"""Calcula la distancia entre esta pos. y otra dada.
:param otro: Una pos. dada.
:return: la distancia, como un decimal.
"""
delta__sq_x = (self.x - otro.x) ** 2
delta__sq_y = (self.y - otro.y) ** 2
delta__sq_z = (self.z - otro.z) ** 2
return math.sqrt(delta__sq_x + delta__sq_y + delta__sq_z)
...
def __sub__(self, otro):
return self.distancia_a(otro)
...
def __eq__(self, otro):
return (otro
and self.x == otro.x
and self.y == otro.y
and self.z == otro.z)
...
def __ne__(self, otro):
return not(self == otro)
...
def __str__(self):
return f"({self.x}, {self.y}, {self.z})"
...
...
class OV:
"""Cualquier objecto volante."""
def __init__(self, x, y, z):
self._pos = Pos(x, y, z)
...
@property
def pos(self):
return self._pos
...
def __str__(self):
return f"{self.pos}"
...
...
class OVNI(OV):
"""Cualquier objeto volante no identificado."""
def __init__(self, x, y, z):
super().__init__(x, y, z)
...
def __str__(self):
return "ovni/" + super().__str__()
...
...
class OVI(OV):
"""Cualquier objeto volante con empresa y num. de vuelo."""
def __init__(self, com, num_vuelo, x, y, z):
super().__init__(x, y, z)
self._com = str(com).capitalize()
self._num_vuelo = num_vuelo
...
@property
def com(self):
"""Devuelve el nombre de la empresa."""
return self._com
@property
def num_vuelo(self):
"""Devuelve el num. de vuelo."""
return self._num_vuelo
...
def __str__(self):
return f"{self.com} {str(self.num_vuelo)}/{super().__str__()}"
...
...
class TorreControl:
"""Desde la torre de control se controlan los vuelos."""
def __init__(self):
self._vuelos = []
...
def __add__(self, otro: OV):
self._vuelos += [otro]
return self
...
@property
def vuelos(self):
"""Devuelve una lista con los vuelos actuales."""
return list(self._vuelos)
...
def avisos_colision(self, limite: float):
toret = []
for i in range(len(self.vuelos)):
for j in range(i + 1, len(self._vuelos)):
if (self._vuelos[i].pos - self._vuelos[j].pos) < limite:
toret += [(self._vuelos[i], self._vuelos[j])]
...
...
...
return toret
...
def __str__(self):
return str.join(", ", [str(v) for v in self._vuelos])
...
...
if __name__ == "__main__":
t = TorreControl()
ov1 = OVI("iberia", 1212, 10, 100, 15000)
ov2 = OVI("qantas", 3456, 100, 150, 12000)
ov3 = OVNI(110, 160, 13000)
colisiones = t.avisos_colision(500)
t += ov1
t += ov2
t += ov3
print(f"torre: {t}")
print(f"Avisos colisión:\n{str.join(", ", [str(v1) + " !! " + str(v2) for (v1, v2) in colisiones])}")
...
IyBNb2RlbGFkbyBkZSB1bmEgdG9ycmUgZGUgY29udHJhbAojIGNvbiBPVnMgKG9iamV0b3Mgdm9sYW50ZXMpLAojIHF1ZSBwdWVkZW4gY29saXNpb25hci4KCgppbXBvcnQgbWF0aAoKCmNsYXNzIFBvczoKICAgICIiIlBvczogeCwgeSwgeiIiIgogICAgWCA9IDAKICAgIFkgPSAxCiAgICBaID0gMgogICAgT1JHID0gTm9uZQogICAgCiAgICBAc3RhdGljbWV0aG9kCiAgICBkZWYgb3JnKCk6CiAgICAgICAgIiIiRGV2dWVsdmUgZWwgb3JpZ2VuIGRlIGNvb3JkZW5hZGFzLgogICAgICAgICAgICAgICAgOnJldHVybjogZWwgb2JqZXRvIFBvcygwLCAwLCAwKQogICAgICAgICIiIgogICAgICAgIGlmIG5vdCBQb3MuT1JHOgogICAgICAgICAgICBQb3MuT1JHID0gUG9zKDAsIDAsIDApCiAgICAgICAgLi4uCiAgICAgICAgCiAgICAgICAgcmV0dXJuIFBvcy5PUkcKICAgIC4uLgogICAgCiAgICBkZWYgX19pbml0X18oc2VsZiwgeCwgeSwgeik6CiAgICAgICAgc2VsZi5fcG9zID0gW3gsIHksIHpdCiAgICAuLi4KICAgIAogICAgZGVmIF9fbGVuX18oc2VsZik6CiAgICAgICAgcmV0dXJuIGxlbihzZWxmLl9wb3MpCiAgICAuLi4KICAgIAogICAgZGVmIF9fZ2V0aXRlbV9fKHNlbGYsIGl0ZW0pOgogICAgICAgIHJldHVybiBzZWxmLl9wb3NbaXRlbV0KICAgIC4uLgogICAgCiAgICBAcHJvcGVydHkKICAgIGRlZiB4KHNlbGYpOgogICAgICAgIHJldHVybiBzZWxmLl9wb3NbMF0KICAgIC4uLgogICAgCiAgICBAcHJvcGVydHkKICAgIGRlZiB5KHNlbGYpOgogICAgICAgIHJldHVybiBzZWxmLl9wb3NbMV0KICAgIC4uLgogICAgCiAgICBAcHJvcGVydHkKICAgIGRlZiB6KHNlbGYpOgogICAgICAgIHJldHVybiBzZWxmLl9wb3NbMl0KICAgIC4uLgogICAgCiAgICBkZWYgZGlzdGFuY2lhX2Eoc2VsZiwgb3Rybyk6CiAgICAgICAgIiIiQ2FsY3VsYSBsYSBkaXN0YW5jaWEgZW50cmUgZXN0YSBwb3MuIHkgb3RyYSBkYWRhLgogICAgICAgICAgICAgICAgOnBhcmFtIG90cm86IFVuYSBwb3MuIGRhZGEuCiAgICAgICAgICAgICAgICA6cmV0dXJuOiBsYSBkaXN0YW5jaWEsIGNvbW8gdW4gZGVjaW1hbC4KICAgICAgICAiIiIKICAgICAgICBkZWx0YV9fc3FfeCA9IChzZWxmLnggLSBvdHJvLngpICoqIDIKICAgICAgICBkZWx0YV9fc3FfeSA9IChzZWxmLnkgLSBvdHJvLnkpICoqIDIKICAgICAgICBkZWx0YV9fc3FfeiA9IChzZWxmLnogLSBvdHJvLnopICoqIDIKICAgICAgICByZXR1cm4gbWF0aC5zcXJ0KGRlbHRhX19zcV94ICsgZGVsdGFfX3NxX3kgKyBkZWx0YV9fc3FfeikKICAgIC4uLgogICAgCiAgICBkZWYgX19zdWJfXyhzZWxmLCBvdHJvKToKICAgICAgICByZXR1cm4gc2VsZi5kaXN0YW5jaWFfYShvdHJvKQogICAgLi4uCiAgICAKICAgIGRlZiBfX2VxX18oc2VsZiwgb3Rybyk6CiAgICAgICAgcmV0dXJuIChvdHJvCiAgICAgICAgICAgICAgICBhbmQgc2VsZi54ID09IG90cm8ueAogICAgICAgICAgICAgICAgYW5kIHNlbGYueSA9PSBvdHJvLnkKICAgICAgICAgICAgICAgIGFuZCBzZWxmLnogPT0gb3Ryby56KQogICAgLi4uCiAgICAKICAgIGRlZiBfX25lX18oc2VsZiwgb3Rybyk6CiAgICAgICAgcmV0dXJuIG5vdChzZWxmID09IG90cm8pCiAgICAuLi4KICAgIAogICAgZGVmIF9fc3RyX18oc2VsZik6CiAgICAgICAgcmV0dXJuIGYiKHtzZWxmLnh9LCB7c2VsZi55fSwge3NlbGYuen0pIgogICAgLi4uCi4uLgoKCmNsYXNzIE9WOgogICAgIiIiQ3VhbHF1aWVyIG9iamVjdG8gdm9sYW50ZS4iIiIKICAgIGRlZiBfX2luaXRfXyhzZWxmLCB4LCB5LCB6KToKICAgICAgICBzZWxmLl9wb3MgPSBQb3MoeCwgeSwgeikKICAgIC4uLgogICAgCiAgICBAcHJvcGVydHkKICAgIGRlZiBwb3Moc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX3BvcwogICAgLi4uCiAgICAKICAgIGRlZiBfX3N0cl9fKHNlbGYpOgogICAgICAgIHJldHVybiBmIntzZWxmLnBvc30iCiAgICAuLi4KLi4uCgoKY2xhc3MgT1ZOSShPVik6CiAgICAiIiJDdWFscXVpZXIgb2JqZXRvIHZvbGFudGUgbm8gaWRlbnRpZmljYWRvLiIiIgogICAgZGVmIF9faW5pdF9fKHNlbGYsIHgsIHksIHopOgogICAgICAgIHN1cGVyKCkuX19pbml0X18oeCwgeSwgeikKICAgIC4uLiAgICAKCiAgICBkZWYgX19zdHJfXyhzZWxmKToKICAgICAgICByZXR1cm4gIm92bmkvIiArIHN1cGVyKCkuX19zdHJfXygpCiAgICAuLi4KLi4uCgoKY2xhc3MgT1ZJKE9WKToKICAgICIiIkN1YWxxdWllciBvYmpldG8gdm9sYW50ZSBjb24gZW1wcmVzYSB5IG51bS4gZGUgdnVlbG8uIiIiCiAgICBkZWYgX19pbml0X18oc2VsZiwgY29tLCBudW1fdnVlbG8sIHgsIHksIHopOgogICAgICAgIHN1cGVyKCkuX19pbml0X18oeCwgeSwgeikKICAgICAgICBzZWxmLl9jb20gPSBzdHIoY29tKS5jYXBpdGFsaXplKCkKICAgICAgICBzZWxmLl9udW1fdnVlbG8gPSBudW1fdnVlbG8KICAgIC4uLgogICAgCiAgICBAcHJvcGVydHkKICAgIGRlZiBjb20oc2VsZik6CiAgICAgICAgIiIiRGV2dWVsdmUgZWwgbm9tYnJlIGRlIGxhIGVtcHJlc2EuIiIiCiAgICAgICAgcmV0dXJuIHNlbGYuX2NvbQogICAgCiAgICBAcHJvcGVydHkKICAgIGRlZiBudW1fdnVlbG8oc2VsZik6CiAgICAgICAgIiIiRGV2dWVsdmUgZWwgbnVtLiBkZSB2dWVsby4iIiIKICAgICAgICByZXR1cm4gc2VsZi5fbnVtX3Z1ZWxvCiAgICAuLi4KCiAgICBkZWYgX19zdHJfXyhzZWxmKToKICAgICAgICByZXR1cm4gZiJ7c2VsZi5jb219IHtzdHIoc2VsZi5udW1fdnVlbG8pfS97c3VwZXIoKS5fX3N0cl9fKCl9IgogICAgLi4uCi4uLgoKCmNsYXNzIFRvcnJlQ29udHJvbDoKICAgICIiIkRlc2RlIGxhIHRvcnJlIGRlIGNvbnRyb2wgc2UgY29udHJvbGFuIGxvcyB2dWVsb3MuIiIiCiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgc2VsZi5fdnVlbG9zID0gW10KICAgIC4uLgogICAgCiAgICBkZWYgX19hZGRfXyhzZWxmLCBvdHJvOiBPVik6CiAgICAgICAgc2VsZi5fdnVlbG9zICs9IFtvdHJvXQogICAgICAgIHJldHVybiBzZWxmCiAgICAuLi4KICAgIAogICAgQHByb3BlcnR5CiAgICBkZWYgdnVlbG9zKHNlbGYpOgogICAgICAgICIiIkRldnVlbHZlIHVuYSBsaXN0YSBjb24gbG9zIHZ1ZWxvcyBhY3R1YWxlcy4iIiIKICAgICAgICByZXR1cm4gbGlzdChzZWxmLl92dWVsb3MpCiAgICAuLi4KICAgIAogICAgZGVmIGF2aXNvc19jb2xpc2lvbihzZWxmLCBsaW1pdGU6IGZsb2F0KToKICAgICAgICB0b3JldCA9IFtdCiAgICAgICAgCiAgICAgICAgZm9yIGkgaW4gcmFuZ2UobGVuKHNlbGYudnVlbG9zKSk6CiAgICAgICAgICAgIGZvciBqIGluIHJhbmdlKGkgKyAxLCBsZW4oc2VsZi5fdnVlbG9zKSk6CiAgICAgICAgICAgICAgICBpZiAoc2VsZi5fdnVlbG9zW2ldLnBvcyAtIHNlbGYuX3Z1ZWxvc1tqXS5wb3MpIDwgbGltaXRlOgogICAgICAgICAgICAgICAgICAgICB0b3JldCArPSBbKHNlbGYuX3Z1ZWxvc1tpXSwgc2VsZi5fdnVlbG9zW2pdKV0KICAgICAgICAgICAgICAgIC4uLgogICAgICAgICAgICAuLi4KICAgICAgICAuLi4KICAgIAogICAgICAgIHJldHVybiB0b3JldAogICAgLi4uIAogICAgICAgIAogICAgZGVmIF9fc3RyX18oc2VsZik6CiAgICAgICAgcmV0dXJuIHN0ci5qb2luKCIsICIsIFtzdHIodikgZm9yIHYgaW4gc2VsZi5fdnVlbG9zXSkKICAgIC4uLgouLi4KCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgdCA9IFRvcnJlQ29udHJvbCgpCiAgICBvdjEgPSBPVkkoImliZXJpYSIsIDEyMTIsIDEwLCAxMDAsIDE1MDAwKQogICAgb3YyID0gT1ZJKCJxYW50YXMiLCAzNDU2LCAxMDAsIDE1MCwgMTIwMDApCiAgICBvdjMgPSBPVk5JKDExMCwgMTYwLCAxMzAwMCkKICAgIGNvbGlzaW9uZXMgPSB0LmF2aXNvc19jb2xpc2lvbig1MDApCiAgICAKICAgIHQgKz0gb3YxCiAgICB0ICs9IG92MgogICAgdCArPSBvdjMKICAgIAogICAgcHJpbnQoZiJ0b3JyZToge3R9IikKICAgIHByaW50KGYiQXZpc29zIGNvbGlzacOzbjpcbntzdHIuam9pbigiLCAiLCBbc3RyKHYxKSArICIgISEgIiArIHN0cih2MikgZm9yICh2MSwgdjIpIGluIGNvbGlzaW9uZXNdKX0iKQouLi4K