From b403379b06d9fe1c8a5b7e98ff04a6f35168313e Mon Sep 17 00:00:00 2001
From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com>
Date: Sat, 5 Oct 2024 18:41:36 +0200
Subject: [PATCH 1/7] Save + callsigns + routes
feet : callsigns database, heure sur les routes et meilleur systeme de save xml
---
Python/XML/aircraft.xml | 101 ++++++---
Python/XML/carteSecteur.xml | 139 ++++++++++--
Python/XML/simu.xml | 412 +++++++++++++++++++++++++++++++++++-
Python/client.py | 13 +-
Python/horloge.py | 12 ++
Python/interface.py | 7 +-
Python/paquets_avion.py | 8 +-
Python/player.py | 18 +-
Python/server.py | 45 ++--
Python/server_browser.py | 6 +-
10 files changed, 678 insertions(+), 83 deletions(-)
diff --git a/Python/XML/aircraft.xml b/Python/XML/aircraft.xml
index e434a4f..b8dfd30 100644
--- a/Python/XML/aircraft.xml
+++ b/Python/XML/aircraft.xml
@@ -1,49 +1,26 @@
-
+
+
- 330
+ 280
410
2000
3000
- 220
+ 200
450
1500
2000
-
- 200
- 430
- 1000
- 1500
-
- 330
+ 280
410
2000
2500
-
- 200
- 450
- 1000
- 1500
-
-
- 330
- 450
- 500
- 1000
-
-
- 160
- 370
- 1000
- 1500
-
240
450
@@ -57,7 +34,7 @@
3000
- 400
+ 310
550
2000
2500
@@ -69,16 +46,76 @@
2500
- 330
+ 280
550
1500
2000
- 330
+ 280
550
2500
3000
-
\ No newline at end of file
+
+
+
+ AIGLE AZUR
+ AMERICAN
+ AIR Canada
+ AIR FRANCE
+ AEROFLOT
+ AIR FRANCE
+ AIRBUS INDUSTRIE
+ AIR MALTA
+ AEROMEXICO
+ ARGENTINA
+ AUSTRIAN
+ UKRAINE INTERNATIONAL
+ ALITALIA
+ SPEEDBIRD
+ BEE-LINE
+ AIR BERLIN
+ CONDOR
+ CONTINENTAL
+ C.S.A.
+ AIR ALGERIE
+ LUFTHANSA
+ SHAMROCK
+ EUROWINGS
+ EASY
+ ALPINE
+ FINNAIR
+ FRENCH POST
+ HOP AIR
+ IBERIA
+ SPANAIR
+ KLM
+ KENIYA
+ LIBAIR
+ LOT
+ MALEV
+ CEDAR JET
+ EGYPTAIR
+ OLYMPIC
+ ROYAL AIR MAROC
+ ROYAL AIR MAROC
+ JORDANIAN
+ TAROM
+ RYANAIR
+ SPRINGBOCK
+ SCANDINAVIAN
+ SAUDIA
+ SWISS
+ SYRIANAIR
+ AIR Portugal
+ TUNAIR
+ THOMAS COOK
+ TURKAIR
+ TRANSAVIA
+ FRANCE SOLEIL
+ EMIRATES
+ VIRGIN
+
+
\ No newline at end of file
diff --git a/Python/XML/carteSecteur.xml b/Python/XML/carteSecteur.xml
index c2944ed..ba3c058 100644
--- a/Python/XML/carteSecteur.xml
+++ b/Python/XML/carteSecteur.xml
@@ -86,7 +86,7 @@
709
- 995
+ 1008
1146
@@ -109,6 +109,18 @@
970
328
+
+ 838
+ 412
+
+
+ 739
+ 225
+
+
+ 806
+ 354
+
947
620
@@ -141,10 +153,6 @@
2028
997
-
- 2000
- 980
-
1645
1097
@@ -174,12 +182,12 @@
1644
- 1107
- 1237
+ 1108
+ 1236
- 991
- 1265
+ 993
+ 1266
1108
@@ -190,12 +198,40 @@
1303
- 844
- 1249
+ 840
+ 1253
- 720
- 1339
+ 699
+ 1341
+
+
+ 572
+ 1421
+
+
+ 2094
+ 1968
+
+
+ 2229
+ 944
+
+
+ 1995
+ 533
+
+
+ 1901
+ 463
+
+
+ 1273
+ 446
+
+
+ 1947
+ 1538
@@ -301,6 +337,9 @@
TRANSIT
SO
NE
+
+ FRI
+
MELKA
@@ -338,6 +377,9 @@
TRANSIT
E-SE
N
+
+ ATN
+
BURGO
@@ -368,6 +410,9 @@
TRANSIT
SE
N
+
+ ATN
+
BURGO
@@ -391,6 +436,9 @@
JAMBI
+
+ VAREK
+
I2
@@ -398,6 +446,9 @@
TRANSIT
E
SO
+
+ BIELA
+
JUVEN
@@ -428,12 +479,12 @@
OS
-
+
DEPART
SO
LIML
- LIML
+ BIELA
20
@@ -528,6 +579,9 @@
SEVET
+
+ RAPID
+
250
G2
@@ -556,6 +610,9 @@
SEVET
+
+ RAPID
+
250
G2
@@ -621,6 +678,12 @@
BERNI
+
+ ETAMO
+
+
+ DIRMO
+
N2
N3
@@ -629,6 +692,9 @@
TRANSIT
SE
NO
+
+ MIROS
+
JAMBI
@@ -652,6 +718,12 @@
BERNI
+
+ ETAMO
+
+
+ DIRMO
+
N2
N3
@@ -660,6 +732,9 @@
TRANSIT
SE
NO
+
+ MIROS
+
JAMBI
@@ -749,6 +824,40 @@
JAMBI
+
+ VAREK
+
+ I2
+
+
+
+ DEPART
+ LFVB
+ SE
+
+ BST
+ 20
+
+
+ LSE
+
+
+ AVRIL
+
+
+ WS
+ 240
+
+
+ RETNO
+
+
+ SANTO
+ True
+
+
+ SAMOS
+
I2
diff --git a/Python/XML/simu.xml b/Python/XML/simu.xml
index fb9033f..66365d6 100644
--- a/Python/XML/simu.xml
+++ b/Python/XML/simu.xml
@@ -1,16 +1,414 @@
- 1002
+
+
+ 1100
+
+
-
- FCACA
- DH8D
- ABISA-BERNI
+
+
+
+
+
+ AZA2310
+
+
+ A320
+
+
+ GAI-JUVEN
+
+
+ 34000
+
+
+ False
+
+
+ 1135.3324760807482
+
+
+ 1228.8072431366452
+
+
+ 340
+
+
+
+
+
+
+
+
+ RYR1463
+
+
+ B738
+
+
+ ATN-SAMOS
+
+
+ 31000
+
+
+ False
+
+
+ 1391.831528809085
+
+
+ 679.2623145312475
+
+
+ 310
+
+
+
+
+
+
+
+
+ BAW2356
+
+
+ A320
+
+
+ ATN-VAREK
+
+
+ 33000
+
+
+ False
+
+
+ 1273
+
+
+ 446
+
+
+ 330
+
+
+
+
+
+
+
+
+ TAP1423
+
+
+ B738
+
+
+ FRI-GAI
+
+
+ 33000
+
+
+ False
+
+
+ 1817.5277008612927
+
+
+ 522.2153916966897
+
+
+ 330
+
+
+
+
+
+
+
+
+ IBE1223
+
+
+ B738
+
+
+ Depart LIML
+
+
+ 2000
+
+
+ False
+
+
+ 2229
+
+
+ 944
+
+
+ 370
+
+
+
+
+
+
+
+
+ HOP1203
+
+
+ AT72
+
+
+ ABISA-NEV
+
+
+ 32000
+
+
+ False
+
+
+ 1283.213204244729
+
+
+ 1062.0078521348714
+
+
+ 320
+
+
+
+
+
+
+
+
+ SWR1203
+
+
+ A320
+
+
+ GAI-RAPID
+
+
+ 34000
+
+
+ True
+
+
+ 699
+
+
+ 1341
+
+
+ 340
+
+
+
+
+
+
+
+
+ TAP2356
+
+
+ B738
+
+
+ FRI-GAI
+
+
+ 33000
+
+
+ False
+
+
+ 1347.300142085819
+
+
+ 862.4423715769826
+
+
+ 330
+
+
+
+
+
+
+
+
+ SWR3104
+
+
+ A320
+
+
+ GAI-RAPID
+
+
+ 32000
+
+
+ True
+
+
+ 706.5181602549122
+
+
+ 1339.095399402089
+
+
+ 320
+
+
+
+
+
+
+
+
+ BAW1203
+
+
+ A320
+
+
+ MIROS-DIRMO
+
+
+ 36000
+
+
+ False
+
+
+ 1947
+
+
+ 1538
+
+
+ 360
+
+
+
+
+
+
+ BAW123C
+ B738
+ MIROS-DIRMO
30000
False
- 1400
- 1300
+ 1947
+ 1538
300
+
+ EJU1245
+ A320
+ Depart RETNO SAMOS
+ 2000
+ False
+ 1390.5612858047484
+ 761.8281404330812
+ 330
+
+
+ DLH1230
+ B738
+ ABISA-RAPID
+ 30000
+ False
+ 1375
+ 1644
+ 300
+
+
+ AFR1203
+ A320
+ ATN-VAREK
+ 30000
+ False
+ 1273
+ 446
+ 300
+
+
+ EWG1542
+ A320
+ FRI-GAI
+ 29000
+ False
+ 1901
+ 463
+ 290
+
+
+ EZY1299
+ B738
+ Depart MEN
+ 2000
+ False
+ 1384
+ 759
+ 310
+
+
+ AZA142M
+ B738
+ GAI-JUVEN
+ 38000
+ False
+ 699
+ 1341
+ 300
+
+
+ TVF1236
+ B738
+ ATN-SAMOS
+ 31000
+ False
+ 1273
+ 446
+ 310
+
+
+ DAH1278
+ A320
+ ABISA-RAPID
+ 32000
+ True
+ 1375
+ 1644
+ 320
+
+
+ SWR1244
+ B738
+ ABISA-RAPID
+ 34000
+ True
+ 1375
+ 1644
+ 340
+
+
+
diff --git a/Python/client.py b/Python/client.py
index 2c61f36..c44fa2f 100644
--- a/Python/client.py
+++ b/Python/client.py
@@ -16,14 +16,21 @@
# recherche de tous les serveurs sur le réseau
address = server_browser.serverBrowser()
-print(address)
+if address:
+ print(address)
+else:
+ time.sleep(20)
+ exit()
# fenêtre Pygame, mettre en 1920, 1080 pour plein écran
pygame.init()
width = 1000
height = 1000
-
win = pygame.display.set_mode((width, height))
+
+# win = pygame.display.set_mode()
+# width, height = pygame.display.get_surface().get_size()
+
path = Path(os.getcwd())
manager = pygame_gui.UIManager((width, height), path / 'ressources' / 'theme.json')
@@ -511,7 +518,7 @@ def main(server_ip: str):
avion.drawEstimatedRoute(carte['points'], conflitGen.temps, color, win, zoom, scroll)
for avion in dictAvionsAff.values():
- avion.draw(win, zoom, scroll, vecteurs, vecteurSetting, carte['points'])
+ avion.draw(win, zoom, scroll, vecteurs, vecteurSetting, carte['points'], game.heure)
# on affiche les boutons
manager.update(time_delta)
diff --git a/Python/horloge.py b/Python/horloge.py
index 0041236..52643f4 100644
--- a/Python/horloge.py
+++ b/Python/horloge.py
@@ -9,3 +9,15 @@ def affichageHeure(heure: float) -> str:
minutes = '0' + minutes
return heures + ':' + minutes
+
+
+def heureXML(heure: float) -> str:
+
+ heures = str(round(heure // 3600 % 24))
+ if len(heures) == 1:
+ heures = '0' + heures
+ minutes = str(round(heure % 3600 // 60))
+ if len(minutes) == 1:
+ minutes = '0' + minutes
+
+ return heures + minutes
diff --git a/Python/interface.py b/Python/interface.py
index 7a8a304..0570a2b 100644
--- a/Python/interface.py
+++ b/Python/interface.py
@@ -199,7 +199,10 @@ def checkFields(self, event):
self.returnValues.update({'PFL': int(event.text)})
except: # si l'utilisateur rentre n'importe quoi, on remet à la valeur du FL
- self.returnValues.update({'PFL': self.returnValues['FL']})
+ if 'FL' in self.returnValues:
+ self.returnValues.update({'PFL': self.returnValues['FL']})
+ else:
+ self.returnValues.update({'PFL': 310})
# on vérifie l'indicatif
elif event.ui_element == self.indicatifinput:
@@ -782,7 +785,7 @@ def __init__(self, avion, pos: list[float, float], valeur: str):
self.listeDroite = None
objectID = None
- if valeur == 'DCT': # TODO boutons directs en blanc
+ if valeur == 'DCT':
self.liste = [point['name'] for point in self.avion.papa.route['points']]
self.listeAff = self.liste[self.liste.index(avion.papa.nextPoint['name']):]
objectID = pygame_gui.core.ObjectID('@menuLabel', 'menuBlanc')
diff --git a/Python/paquets_avion.py b/Python/paquets_avion.py
index 65c4259..5c536ca 100644
--- a/Python/paquets_avion.py
+++ b/Python/paquets_avion.py
@@ -71,7 +71,12 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
else:
self.medevac = ''
- self.callsignFreq = 'Austrian' # TODO ajouter les callsigns
+ if indicatif[:2] in gameMap['callsigns']:
+ self.callsignFreq = gameMap['callsigns'][indicatif[:2]]
+ elif indicatif[:3] in gameMap['callsigns']:
+ self.callsignFreq = gameMap['callsigns'][indicatif[:3]]
+ else:
+ self.callsignFreq = 'caca'
if route['type'] == 'DEPART':
self.provenance = route['provenance']
@@ -164,6 +169,7 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
def findNextPoint(self, carte):
self.nextPoint = findClosestSegment(self.route['points'], (self.x, self.y), carte['points'])[1]
+ self.DCT = self.nextPoint['name']
def changeXFL(self, carte) -> None:
"""
diff --git a/Python/player.py b/Python/player.py
index 5cf8416..f62d445 100644
--- a/Python/player.py
+++ b/Python/player.py
@@ -6,10 +6,12 @@
import pygame
import pygame_gui
+import horloge
# Imports fichiers
from Python.valeurs_config import *
import Python.geometry as geometry
import Python.interface as interface
+import Python.horloge as horloge
def positionAffichage(x: int, y: int, zoom: float, scrollX: float, scrollY: float):
@@ -154,7 +156,7 @@ def drawSep(self, window, zoom):
img = font.render(lettre, True, (170, 170, 255))
window.blit(img, coords)
- def draw(self, win, zoom, scroll, vecteurs, vecteurSetting, points):
+ def draw(self, win, zoom, scroll, vecteurs, vecteurSetting, points, temps):
# updates
@@ -165,7 +167,7 @@ def draw(self, win, zoom, scroll, vecteurs, vecteurSetting, points):
self.bouton.set_position((self.affX, self.affY))
if self.drawRouteBool:
- self.drawRoute(points, win, zoom, scroll)
+ self.drawRoute(points, win, zoom, scroll, temps)
if self.pointDessinDirect:
self.drawDirect(points, self.pointDessinDirect, win, zoom, scroll)
@@ -323,13 +325,14 @@ def drawEstimatedRoute(self, points, temps, color, win, zoom, scroll):
distance -= legDistance # on enlève la distance de la branche parcourue à la distance à parcourir
pointUn = pointDeux # on passe au prochain point
- def drawRoute(self, points, win, zoom, scroll):
+ def drawRoute(self, points: dict, win, zoom: float, scroll: tuple[float, float] | list[float, float], temps: float):
"""
Dessine la route future de l'avion avec les estimées en temps
:param points: la liste des points récupérer les coords
:param win: l'écran pygame
:param zoom: le niveau de zoom
:param scroll: le scroll format [x, y]
+ :param temps: l'heure de la partie
:return:
"""
@@ -339,16 +342,23 @@ def drawRoute(self, points, win, zoom, scroll):
point1 = points[route[route.index(nextPoint) - 1]['name']][:2]
point2 = points[nextPoint['name']][:2]
pointUn = geometry.calculateShortestPoint(point1, point2, [self.papa.x, self.papa.y])
- # TODO heure de passage pour chaque point
route = route[route.index(nextPoint):] # on ne considère que la route devant l'avion
+ font = pygame.font.SysFont('arial', 15)
+
for point in route:
+
pointDeux = [points[point['name']][0], points[point['name']][1]]
+ temps += geometry.calculateDistance(pointUn[0], pointUn[1], pointDeux[0], pointDeux[1]) / self.papa.speedPx * radarRefresh
pygame.draw.line(win, (46, 80, 174),
(pointUn[0] * zoom + scroll[0], pointUn[1] * zoom + scroll[1]),
(pointDeux[0] * zoom + scroll[0], pointDeux[1] * zoom + scroll[1]), 3)
+ img = font.render(horloge.affichageHeure(temps), True, (170, 170, 255))
+ coords = (pointDeux[0] * zoom - 5 + scroll[0], pointDeux[1] * zoom - 20 + scroll[1])
+ win.blit(img, coords)
+
pointUn = pointDeux # on passe au prochain point
def checkClicked(self, event) -> bool:
diff --git a/Python/server.py b/Python/server.py
index 91cb6f8..7d5a3dd 100644
--- a/Python/server.py
+++ b/Python/server.py
@@ -14,6 +14,7 @@
from pathlib import Path
# Import fichiers
+import Python.horloge as horloge
from Python.network import MCAST_GRP, MCAST_PORT, port
from Python.paquets_avion import *
@@ -214,29 +215,39 @@
tree = ET.parse(dossierXML / aircraftFile)
root = tree.getroot()
-for aircraft in root:
+for aircraft in root.find('aircrafts'):
aircraftType.update(
{aircraft.attrib['name']: {'IAS': int(aircraft.find('speed').text),
'plafond': int(aircraft.find('ceiling').text),
'ROC': int(aircraft.find('ROC').text),
'ROD': int(aircraft.find('ROD').text)}})
+callsignList = {}
+for callsign in root.find('callsigns'):
+ callsignList.update({callsign.attrib['indicatif']: callsign.text})
+
+gameMap.update({'callsigns': callsignList})
planeId = 0
+
+simuTree = None
try: # on essaye de charger une simu, si elle existe
- tree = ET.parse(dossierXML / simu)
+ simuTree = ET.parse(dossierXML / simu).getroot()
- heure = tree.find('heure').text
+ heure = simuTree.find('heure').text
heure = int(heure[0:2]) * 3600 + int(heure[2:]) * 60
+ game = Game(heure)
+
avionSpawnListe = []
- for avion in tree.find('avions'):
+ avionsXML = simuTree.find('avions')
+ for avion in avionsXML:
avionDict = {}
for XMLpoint in avion:
try:
- XMLpointValue = int(XMLpoint.text)
+ XMLpointValue = float(XMLpoint.text)
except:
XMLpointValue = XMLpoint.text
avionDict.update({XMLpoint.tag: XMLpointValue})
@@ -271,16 +282,11 @@
heure = input('Heure de début de simu, format: hhmm')
heure = int(heure[0:2]) * 3600 + int(heure[2:]) * 60
avionSpawnListe = []
-
-game = Game(heure)
-
-# XML écriture
-
-SimuTree = ET.Element('simu')
-heureXML = ET.SubElement(SimuTree, 'heure')
-heureXML.text = '1002'
-avionsXML = ET.SubElement(SimuTree, 'avions')
-
+ simuTree = ET.Element('simu')
+ game = Game(heure)
+ heureXML = ET.SubElement(simuTree, 'heure')
+ heureXML.text = horloge.heureXML(game.heure)
+ avionsXML = ET.SubElement(simuTree, 'avions')
def generateAvionXML(parent, heureEcriture, indicatifEcriture, aircraftEcriture, routeEcriture, altitudeEcriture, xEcriture=None, yEcriture=None, headingEcriture=None, PFLEcriture=None):
@@ -403,14 +409,17 @@ def threaded_ping_responder():
PFLEcriture=req[2].PFL)
elif req[1] == 'DelayedAdd':
+ req[2][1].Id = planeId
+ planeId += 1
+
avionSpawnListe.append((game.heure + req[2][0], req[2][1]))
if mode_ecriture:
- heures = str(round(game.heure + req[2][0] // 3600))
+ heures = str(round((game.heure + req[2][0]) // 3600))
if len(heures) == 1:
heures = '0' + heures
- minutes = str(round(game.heure + req[2][0] % 3600 // 60))
+ minutes = str(round((game.heure + req[2][0]) % 3600 // 60))
if len(minutes) == 1:
minutes = '0' + minutes
@@ -490,7 +499,7 @@ def threaded_ping_responder():
if accelerationTemporelle > 0.5:
accelerationTemporelle -= 0.5
elif req[1] == 'Save' and mode_ecriture:
- xmlstr = minidom.parseString(ET.tostring(SimuTree)).toprettyxml(indent=" ")
+ xmlstr = minidom.parseString(ET.tostring(simuTree)).toprettyxml(indent=" ")
with open("XML/simu.xml", "w") as f:
f.write(xmlstr)
diff --git a/Python/server_browser.py b/Python/server_browser.py
index 6dd4201..3439d59 100644
--- a/Python/server_browser.py
+++ b/Python/server_browser.py
@@ -26,7 +26,11 @@ def serverBrowser():
serverList.update({data: address})
sock.close()
if len(serverList) <= 1:
- return list(serverList.values())[0][0]
+ try:
+ return list(serverList.values())[0][0]
+ except IndexError:
+ print('Aucun serveur trouvé')
+ return None
print('Liste des serveurs actifs:')
for i in range(len(list(serverList.keys()))):
print(i, ' - ', list(serverList.keys())[i], '\n')
From 3bf59567023d1132215bb19312a87c40ccbec58b Mon Sep 17 00:00:00 2001
From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com>
Date: Sun, 6 Oct 2024 00:50:25 +0200
Subject: [PATCH 2/7] Menus pilotes
feet : suppression de l'ancien menu pilote pour les menus controleurs plus ergonomiques
---
Python/client.py | 30 +-----
Python/interface.py | 232 +++++---------------------------------------
Python/player.py | 30 +++---
Python/server.py | 19 +++-
4 files changed, 56 insertions(+), 255 deletions(-)
diff --git a/Python/client.py b/Python/client.py
index c44fa2f..2345839 100644
--- a/Python/client.py
+++ b/Python/client.py
@@ -50,7 +50,6 @@ def main(server_ip: str):
# menus
conflitBool = False
conflitGen = None
- menuAvion = None
menuATC = None
menuValeurs = None
flightDataWindow = None
@@ -213,21 +212,6 @@ def main(server_ip: str):
curseur_cercles = True
pygame.mouse.set_cursor(pygame.cursors.broken_x)
- # on regarde si notre menu pour le pilote est actif
- if menuAvion is not None:
-
- # si on valide les modifs, alors la fonction checkEvent retourne les modifs
- modifications = menuAvion.checkEvent(event)
- if modifications:
-
- # on applique alors les modifs
- avionId = modifications[0]
- modifications = modifications[1]
-
- # pour chaque modif, on prépare une requête au serveur
- for changement, valeur in modifications.items():
- localRequests.append((avionId, changement, valeur))
-
if menuATC is not None:
# si on valide les modifs, alors la fonction checkEvent retourne les modifs
@@ -278,15 +262,12 @@ def main(server_ip: str):
if type(action) in [list, tuple]: # si c'est un tuple alors cela correspond à une requête
localRequests.append(action)
- elif action == 'menuPIL' and menuAvion is None: # si c'est menu alors, on vérifie qu'on peut menu
- menuAvion = interface.menuAvion(avion)
-
elif action == 'menuATC' and menuATC is None:
menuATC = interface.menuATC(avion, pygame.mouse.get_pos())
elif menuValeurs is None and action is not None:
# si on a renvoyé autre chose alors c'est une valeur pour ouvrir un menu
- menuValeurs = interface.menuValeurs(avion, pygame.mouse.get_pos(), action)
+ menuValeurs = interface.menuValeurs(avion, pygame.mouse.get_pos(), action, pilote)
# Menu de selection nouvel avion
# si notre menu est ouvert
@@ -325,7 +306,7 @@ def main(server_ip: str):
elif event.type == pygame_gui.UI_TEXT_ENTRY_CHANGED:
nouvelAvionWin.checkFields(event)
- if menuAvion or nouvelAvionWin:
+ if nouvelAvionWin:
pass
# zoom géré ici
@@ -376,9 +357,6 @@ def main(server_ip: str):
manager.process_events(event)
- if menuAvion is not None:
- menuAvion.checkSliders()
-
if conflitGen is not None:
conflitGen.checkScrollBar(carte)
@@ -443,10 +421,6 @@ def main(server_ip: str):
pressing = False
# on se débarrasse des menus inutils
- if menuAvion is not None:
- if not menuAvion.checkAlive():
- menuAvion = None
-
if menuATC is not None:
if not menuATC.checkAlive():
menuATC = None
diff --git a/Python/interface.py b/Python/interface.py
index 0570a2b..8f4f160 100644
--- a/Python/interface.py
+++ b/Python/interface.py
@@ -215,200 +215,6 @@ def checkAlive(self):
return self.window.alive()
-class menuAvion:
-
- def __init__(self, avion):
- self.avion = avion
- self.window = self.window = pygame_gui.elements.UIWindow(pygame.Rect((400, 400), (600, 350)))
-
- # génération boutons heading
- self.headingLabel = pygame_gui.elements.UILabel(
- relative_rect=pygame.Rect((0, 17), (100, 17)),
- container=self.window,
- text=('Cap - ' + str(round(avion.papa.heading))))
-
- self.headingContainer = pygame_gui.elements.UIScrollingContainer(
- pygame.Rect((0, 34), (100, 200)),
- container=self.window)
-
- tempo = scrollListGen(range(round(avion.papa.heading / 5) * 5 - 25, round(avion.papa.heading / 5) * 5 + 30, 5),
- pygame.Rect((0, 0), (75, 17)), self.headingContainer)
-
- self.headingBoutonListe = tempo[1]
- self.headingSlider = tempo[0]
- self.headingSlider.set_scroll_from_start_percentage((round(avion.papa.heading / 5) * 5 - 15) / 300 * 0.8)
-
- # génération boutons Alti
- self.altiLabel = pygame_gui.elements.UILabel(
- relative_rect=pygame.Rect((0, 17), (100, 17)),
- container=self.window,
- text=('FL - ' + str(round(avion.papa.altitude / 100))),
- anchors={'left': 'left', 'left_target': self.headingLabel})
-
- self.altiContainer = pygame_gui.elements.UIScrollingContainer(
- pygame.Rect((0, 34), (100, 200)),
- container=self.window,
- anchors={'left': 'left', 'left_target': self.headingContainer})
-
- tempo = scrollListGen(
- range(round(avion.papa.altitude / 1000) * 10 - 50, round(avion.papa.altitude / 1000) * 10 + 60, 10),
- pygame.Rect((0, 0), (75, 17)), self.altiContainer)
-
- self.altiBoutonListe = tempo[1]
- self.altiSlider = tempo[0]
-
- self.altiSlider.set_scroll_from_start_percentage((round(avion.papa.altitude / 1000) * 10 - 30) / 410 * 0.8)
-
- # génération boutons speed
- self.speedLabel = pygame_gui.elements.UILabel(
- relative_rect=pygame.Rect((0, 17), (100, 17)),
- container=self.window, text=('IAS - ' + str(avion.papa.speedIAS)),
- anchors={'left': 'left', 'left_target': self.altiLabel})
-
- self.speedContainer = pygame_gui.elements.UIScrollingContainer(
- pygame.Rect((0, 34), (100, 200)),
- container=self.window,
- anchors={'left': 'left', 'left_target': self.altiContainer})
-
- tempo = scrollListGen(
- range(round(avion.papa.speedIAS / 10) * 10 - 50, round(avion.papa.speedIAS / 10) * 10 + 60, 10),
- pygame.Rect((0, 0), (75, 17)), self.speedContainer)
-
- self.speedBoutonListe = tempo[1]
- self.speedSlider = tempo[0]
- self.speedSlider.set_scroll_from_start_percentage((round(avion.papa.speedIAS / 10) * 10 - 100) / 330 * 0.8)
-
- # génération boutons points
-
- self.pointContainer = pygame_gui.elements.UIScrollingContainer(
- pygame.Rect((0, 0), (100, 200)),
- container=self.window,
- anchors={'left': 'left', 'left_target': self.speedContainer})
-
- tempo = scrollListGen([point['name'] for point in avion.papa.route['points']],
- pygame.Rect((0, 0), (75, 17)),
- self.pointContainer,
- sliderBool=False)
-
- self.pointBoutonListe = tempo[1]
-
- # génération boutons next routes
-
- self.routeContainer = pygame_gui.elements.UIScrollingContainer(
- pygame.Rect((0, 0), (100, 200)),
- container=self.window,
- anchors={'left': 'left', 'left_target': self.pointContainer})
-
- # bouton validation
-
- self.validerBouton = pygame_gui.elements.UIButton(
- pygame.Rect((200, 90), (75, 17)),
- text='valider',
- container=self.window,
- anchors={'top': 'top', 'top_target': self.pointContainer})
-
- # dict pour les valeurs que le menu renverra
- self.returnValues = {}
-
- def checkAlive(self):
- return self.window.alive()
-
- def checkSliders(self):
-
- """
- Change la valeur des boutons en fonction de la position du slider, pour tout le menu
- """
-
- selectedValue = None
- if self.headingSlider.has_moved_recently:
- if 'Heading' in self.returnValues:
- selectedValue = self.returnValues['Heading']
-
- value = round(
- (360 - 5 * (len(self.headingBoutonListe) - 1)) * (self.headingSlider.start_percentage / 0.8) / 5) * 5
- for bouton in self.headingBoutonListe:
- bouton.text = str(value)
- bouton.rebuild()
- if selectedValue == value:
- bouton.disable()
- else:
- bouton.enable()
- value += 5
-
- elif self.altiSlider.has_moved_recently:
- if 'Altitude' in self.returnValues:
- selectedValue = self.returnValues['Altitude']
-
- # la valeur de niveau oscille entre 0 et 410
- value = round(
- (410 - 10 * (len(self.headingBoutonListe) - 1)) * (self.altiSlider.start_percentage / 0.8) / 10) * 10
- for bouton in self.altiBoutonListe:
- bouton.text = str(value)
- bouton.rebuild()
- if selectedValue == value:
- bouton.disable()
- else:
- bouton.enable()
- value += 10
-
- elif self.speedSlider.has_moved_recently:
- if 'IAS' in self.returnValues:
- selectedValue = self.returnValues['IAS']
-
- value = round((330 - 10 * (len(self.headingBoutonListe) - 1)) * (
- self.speedSlider.start_percentage / 0.8) / 10) * 10 + 70
- for bouton in self.speedBoutonListe:
- bouton.text = str(value)
- bouton.rebuild()
- if selectedValue == value:
- bouton.disable()
- else:
- bouton.enable()
- value += 10
-
- def checkEvent(self, event):
-
- """
- Vérifie si un des boutons du menu a été pressé et modifie les données en conséquence
- :arg event: l'évenement qu'il faut vérifier
- :returns: le dictionaire de valeurs si on valide, None sinon
- """
-
- # heading
- if event.ui_element in self.headingBoutonListe:
-
- self.returnValues.update({'Heading': int(event.ui_element.text)})
- selectButtonInList(self.headingBoutonListe, event.ui_element)
- # on enlève le direct pour ne pas faire de confusion
- if 'Direct' in self.returnValues:
- self.returnValues.pop('Direct')
-
- # ALTI
- elif event.ui_element in self.altiBoutonListe:
-
- self.returnValues.update({'Altitude': int(event.ui_element.text) * 100})
- selectButtonInList(self.altiBoutonListe, event.ui_element)
-
- # speed
- elif event.ui_element in self.speedBoutonListe:
-
- selectButtonInList(self.speedBoutonListe, event.ui_element)
- self.returnValues.update({'IAS': int(event.ui_element.text)})
-
- # direct
- elif event.ui_element in self.pointBoutonListe:
-
- selectButtonInList(self.pointBoutonListe, event.ui_element)
- self.returnValues.update({'Direct': event.ui_element.text})
- if 'Heading' in self.returnValues:
- self.returnValues.pop('Heading')
-
- elif event.ui_element is self.validerBouton:
-
- self.window.kill()
- return self.avion.Id, self.returnValues
-
-
class etiquette:
def __init__(self, avion):
@@ -756,13 +562,14 @@ def checkAlive(self):
class menuValeurs:
- def __init__(self, avion, pos: list[float, float], valeur: str):
+ def __init__(self, avion, pos: list[float, float] | tuple[float, float], valeur: str, pilote: bool):
"""
Menu utilisé par le controleur pour changer les valeurs des différents champs
:param avion:
:param pos:
:param valeur:
+ :param pilote: si on est en pilote ou non
"""
self.avion = avion
@@ -809,16 +616,16 @@ def __init__(self, avion, pos: list[float, float], valeur: str):
self.liste.reverse()
self.listeAff = self.liste[-7:]
- elif valeur in ['XFL', 'PFL', 'CFL']:
+ elif valeur in ['XFL', 'PFL', 'CFL', 'FL']:
self.liste = [*range(0, 600, 10)]
self.liste.reverse()
indexDuFL = self.liste.index(avion.papa.PFL)
self.liste[indexDuFL] = "R" + str(avion.papa.PFL)
self.listeAff = self.liste[indexDuFL - 4: indexDuFL + 5]
- elif valeur == 'HDG':
+ elif valeur in ['HDG', 'C_HDG']:
- cap = round(avion.papa.heading // 5) * 5 + 5
+ cap = round(avion.papa.selectedHeading // 5) * 5 + 5
self.liste = [*range(5, 365, 5)]
indexDuCap = self.liste.index(cap)
@@ -910,7 +717,7 @@ def __init__(self, avion, pos: list[float, float], valeur: str):
self.topContainer.set_dimensions((width, self.headingDCT.get_abs_rect()[3] * 2))
- if self.valeur == 'HDG':
+ if self.valeur in ['C_HDG', 'HDG']:
listeDroite = []
listeGauche = []
@@ -1015,6 +822,16 @@ def __init__(self, avion, pos: list[float, float], valeur: str):
(width,
height))
+ if pilote:
+ if self.valeur == 'DCT':
+ self.valeur = 'Direct'
+ elif self.valeur == 'C_Rate':
+ self.valeur = 'Rate'
+ elif self.valeur == 'C_IAS':
+ self.valeur = 'IAS'
+ elif self.valeur == 'C_HDG':
+ self.valeur = 'HDG'
+
def checkEvent(self, event):
"""
Vérifies si un event est relié à ce menu et prend les actions en conséquence
@@ -1068,27 +885,30 @@ def checkEvent(self, event):
elif event.ui_element == self.resume:
self.kill()
- if self.valeur in ['DCT', 'HDG']: # si c'est un cap, alors on veut continuer au cap
- return self.avion.Id, 'HDG', ' '
+ if self.valeur in ['DCT', 'C_HDG']: # si c'est un cap, alors on veut continuer au cap
+ return self.avion.Id, 'C_HDG', self.avion.papa.selectedHeading
+
+ elif self.valeur in ['Direct', 'HDG']:
+ return self.avion.Id, 'HDG', self.avion.papa.selectedHeading
else: # si c'est une rate ou IAS : on enlève
return self.avion.Id, self.valeur, None
elif event.ui_element == self.headingDCT:
self.kill()
- if self.valeur == 'HDG':
+ if self.valeur in ['C_HDG', 'HDG']:
return 'DCT'
else:
- return 'HDG'
+ return 'C_HDG'
- elif self.valeur == 'HDG':
+ elif self.valeur in ['C_HDG', 'HDG']:
if event.ui_element in self.listeGauche:
self.kill()
if self.avion.papa.clearedHeading:
heading = round(self.avion.papa.clearedHeading - int(event.ui_element.text[1:]))
else:
heading = round(self.avion.papa.selectedHeading - int(event.ui_element.text[1:]))
- return self.avion.Id, 'HDG', heading
+ return self.avion.Id, self.valeur, heading
elif event.ui_element in self.listeDroite:
self.kill()
@@ -1096,7 +916,7 @@ def checkEvent(self, event):
heading = round(self.avion.papa.clearedHeading + int(event.ui_element.text[1:]))
else:
heading = round(self.avion.papa.selectedHeading + int(event.ui_element.text[1:]))
- return self.avion.Id, 'HDG', heading
+ return self.avion.Id, self.valeur, heading
def checkScrolled(self, event):
"""
diff --git a/Python/player.py b/Python/player.py
index f62d445..20047ac 100644
--- a/Python/player.py
+++ b/Python/player.py
@@ -6,7 +6,6 @@
import pygame
import pygame_gui
-import horloge
# Imports fichiers
from Python.valeurs_config import *
import Python.geometry as geometry
@@ -430,15 +429,11 @@ def checkEvent(self, event, pilote, conflitBool):
if event.mouse_button == 3 and pilote:
return self.Id, 'EtatFreq', None
- if event.mouse_button == 1 and pilote:
- return 'menuPIL'
-
- elif event.mouse_button == 1:
+ elif event.mouse_button == 1 and pilote:
return 'menuATC'
elif event.mouse_button == 3 and self.papa.integreOrganique and (
- self.etiquette.indicatif.get_object_ids()[1] in ['@etiquetteBold', '@etiquetteBoldBlue']
- or pilote): # clic droit
+ self.etiquette.indicatif.get_object_ids()[1] in ['@etiquetteBold', '@etiquetteBoldBlue']):
self.unBold()
@@ -449,28 +444,31 @@ def checkEvent(self, event, pilote, conflitBool):
elif event.ui_element == self.etiquette.XPT and event.mouse_button == 3 and not pilote:
self.drawRouteBool = not self.drawRouteBool
- elif event.ui_element == self.etiquette.XPT and event.mouse_button == 1 and not pilote:
+ elif event.ui_element == self.etiquette.XPT and event.mouse_button == 1:
return 'XPT'
- elif event.ui_element == self.etiquette.DCT and event.mouse_button == 1 and not pilote:
+ elif event.ui_element == self.etiquette.DCT and event.mouse_button == 1:
return 'DCT'
- elif event.ui_element == self.etiquette.DCT and event.mouse_button == 2 and not pilote:
- return 'HDG'
+ elif event.ui_element == self.etiquette.DCT and event.mouse_button == 2:
+ return 'C_HDG'
- elif event.ui_element == self.etiquette.XFL and event.mouse_button == 1 and not pilote:
+ elif event.ui_element == self.etiquette.XFL and event.mouse_button == 1:
return 'XFL'
- elif event.ui_element == self.etiquette.PFL and event.mouse_button == 1 and not pilote:
+ elif event.ui_element == self.etiquette.PFL and event.mouse_button == 1:
return 'PFL'
- elif event.ui_element == self.etiquette.CFL and event.mouse_button == 1 and not pilote:
+ elif event.ui_element == self.etiquette.CFL and event.mouse_button == 1:
return 'CFL'
- elif event.ui_element == self.etiquette.clearedSpeed and event.mouse_button == 1 and not pilote:
+ elif event.ui_element == self.etiquette.AFL and event.mouse_button == 1 and pilote:
+ return 'FL'
+
+ elif event.ui_element == self.etiquette.clearedSpeed and event.mouse_button == 1:
return 'C_IAS'
- elif event.ui_element == self.etiquette.rate and event.mouse_button == 1 and not pilote:
+ elif event.ui_element == self.etiquette.rate and event.mouse_button == 1:
return 'C_Rate'
def checkEtiquetteOnHover(self):
diff --git a/Python/server.py b/Python/server.py
index 7d5a3dd..26aef03 100644
--- a/Python/server.py
+++ b/Python/server.py
@@ -435,8 +435,8 @@ def threaded_ping_responder():
elif req[1] == 'Remove':
dictAvion.pop(req[0])
- elif req[1] == 'Altitude':
- dictAvion[req[0]].selectedAlti = req[2]
+ elif req[1] == 'FL':
+ dictAvion[req[0]].selectedAlti = req[2] * 100
elif req[1] == 'PFL':
dictAvion[req[0]].PFL = req[2]
dictAvion[req[0]].changeXFL(gameMap)
@@ -452,18 +452,27 @@ def threaded_ping_responder():
dictAvion[req[0]].clearedRate = req[2]
else:
dictAvion[req[0]].clearedRate = None
+ elif req[1] == 'Rate':
+ signe = (dictAvion[req[0]].evolution * req[2]) / abs(dictAvion[req[0]].evolution * req[2])
+ dictAvion[req[0]].evolution = signe * req[2]
elif req[1] == 'XFL':
dictAvion[req[0]].XFL = req[2]
dictAvion[req[0]].changeSortieSecteur(gameMap)
elif req[1] == 'XPT':
dictAvion[req[0]].XPT = req[2]
- elif req[1] == 'HDG':
+ elif req[1] == 'C_HDG':
dictAvion[req[0]].clearedHeading = req[2]
- elif req[1] == 'Heading':
+ elif req[1] == 'HDG':
+ if type(req[2]) in [float, int]:
+ newHeading = req[2]
+ elif req[2][0] == '-':
+ newHeading = dictAvion[req[0]].selectedHeading - int(req[2][1:])
+ elif req[2][0] == '+':
+ newHeading = dictAvion[req[0]].selectedHeading + int(req[2][1:])
dictAvion[req[0]].headingMode = True
dictAvion[req[0]].selectedHeading = req[2]
elif req[1] == 'IAS':
- dictAvion[req[0]].selectedIAS = req[2]
+ dictAvion[req[0]].selectedIAS = req[2] * 10
elif req[1] == 'DCT':
dictAvion[req[0]].clearedHeading = None
dictAvion[req[0]].DCT = req[2]
From 5902c12b26609e51cc46a91783a9e401cfd9d3a9 Mon Sep 17 00:00:00 2001
From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com>
Date: Sun, 6 Oct 2024 23:47:09 +0200
Subject: [PATCH 3/7] feet and fic
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
feet : XML joli mtn (vraiment)
feet : heure avion plus précise
fix : generateXML refait
fix : arrivées XML mieux
fix : menus Cap s'ouvrent à partir de DCT
---
Python/XML/simu.xml | 444 +++------------------------------------
Python/client.py | 4 +-
Python/horloge.py | 13 +-
Python/player.py | 2 +-
Python/server.py | 230 ++++++++------------
Python/server_browser.py | 1 +
Python/server_def.py | 50 +++++
7 files changed, 189 insertions(+), 555 deletions(-)
diff --git a/Python/XML/simu.xml b/Python/XML/simu.xml
index 66365d6..d38a1e6 100644
--- a/Python/XML/simu.xml
+++ b/Python/XML/simu.xml
@@ -1,414 +1,36 @@
-
-
- 1100
-
-
-
-
-
-
-
-
- AZA2310
-
-
- A320
-
-
- GAI-JUVEN
-
-
- 34000
-
-
- False
-
-
- 1135.3324760807482
-
-
- 1228.8072431366452
-
-
- 340
-
-
-
-
-
-
-
-
- RYR1463
-
-
- B738
-
-
- ATN-SAMOS
-
-
- 31000
-
-
- False
-
-
- 1391.831528809085
-
-
- 679.2623145312475
-
-
- 310
-
-
-
-
-
-
-
-
- BAW2356
-
-
- A320
-
-
- ATN-VAREK
-
-
- 33000
-
-
- False
-
-
- 1273
-
-
- 446
-
-
- 330
-
-
-
-
-
-
-
-
- TAP1423
-
-
- B738
-
-
- FRI-GAI
-
-
- 33000
-
-
- False
-
-
- 1817.5277008612927
-
-
- 522.2153916966897
-
-
- 330
-
-
-
-
-
-
-
-
- IBE1223
-
-
- B738
-
-
- Depart LIML
-
-
- 2000
-
-
- False
-
-
- 2229
-
-
- 944
-
-
- 370
-
-
-
-
-
-
-
-
- HOP1203
-
-
- AT72
-
-
- ABISA-NEV
-
-
- 32000
-
-
- False
-
-
- 1283.213204244729
-
-
- 1062.0078521348714
-
-
- 320
-
-
-
-
-
-
-
-
- SWR1203
-
-
- A320
-
-
- GAI-RAPID
-
-
- 34000
-
-
- True
-
-
- 699
-
-
- 1341
-
-
- 340
-
-
-
-
-
-
-
-
- TAP2356
-
-
- B738
-
-
- FRI-GAI
-
-
- 33000
-
-
- False
-
-
- 1347.300142085819
-
-
- 862.4423715769826
-
-
- 330
-
-
-
-
-
-
-
-
- SWR3104
-
-
- A320
-
-
- GAI-RAPID
-
-
- 32000
-
-
- True
-
-
- 706.5181602549122
-
-
- 1339.095399402089
-
-
- 320
-
-
-
-
-
-
-
-
- BAW1203
-
-
- A320
-
-
- MIROS-DIRMO
-
-
- 36000
-
-
- False
-
-
- 1947
-
-
- 1538
-
-
- 360
-
-
-
-
-
-
- BAW123C
- B738
- MIROS-DIRMO
- 30000
- False
- 1947
- 1538
- 300
-
-
- EJU1245
- A320
- Depart RETNO SAMOS
- 2000
- False
- 1390.5612858047484
- 761.8281404330812
- 330
-
-
- DLH1230
- B738
- ABISA-RAPID
- 30000
- False
- 1375
- 1644
- 300
-
-
- AFR1203
- A320
- ATN-VAREK
- 30000
- False
- 1273
- 446
- 300
-
-
- EWG1542
- A320
- FRI-GAI
- 29000
- False
- 1901
- 463
- 290
-
-
- EZY1299
- B738
- Depart MEN
- 2000
- False
- 1384
- 759
- 310
-
-
- AZA142M
- B738
- GAI-JUVEN
- 38000
- False
- 699
- 1341
- 300
-
-
- TVF1236
- B738
- ATN-SAMOS
- 31000
- False
- 1273
- 446
- 310
-
-
- DAH1278
- A320
- ABISA-RAPID
- 32000
- True
- 1375
- 1644
- 320
-
-
- SWR1244
- B738
- ABISA-RAPID
- 34000
- True
- 1375
- 1644
- 340
-
-
-
-
+ 100200
+
+
+ FCACA
+ E195
+ FRI-GAI
+ 30000
+ False
+ 1901
+ 463
+ 300
+
+
+ FCACA
+ B738
+ MIROS-DIRMO
+ 30000
+ False
+ 1848.27707757998
+ 1472.4922664315754
+ 300
+
+
+ FCACA
+ E195
+ ABISA-RAPID
+ 30000
+ False
+ 1375
+ 1644
+ 300
+
+
diff --git a/Python/client.py b/Python/client.py
index 2345839..4dd2e0b 100644
--- a/Python/client.py
+++ b/Python/client.py
@@ -240,8 +240,8 @@ def main(server_ip: str):
if action:
if type(action) in [list, tuple]: # si c'est un tuple alors cela correspond à une requête
localRequests.append(action)
- elif action in ['HDG', 'DCT']:
- menuValeurs = interface.menuValeurs(menuValeurs.avion, pygame.mouse.get_pos(), action)
+ elif action in ['C_HDG', 'DCT']:
+ menuValeurs = interface.menuValeurs(menuValeurs.avion, pygame.mouse.get_pos(), action, pilote)
if curseur_aliSep:
for sep in sepDict:
diff --git a/Python/horloge.py b/Python/horloge.py
index 52643f4..6892dac 100644
--- a/Python/horloge.py
+++ b/Python/horloge.py
@@ -13,11 +13,22 @@ def affichageHeure(heure: float) -> str:
def heureXML(heure: float) -> str:
+ """
+ Renvoies un str avec l'heure en format hhmmss
+ :param heure:
+ :return:
+ """
+
heures = str(round(heure // 3600 % 24))
if len(heures) == 1:
heures = '0' + heures
+
minutes = str(round(heure % 3600 // 60))
if len(minutes) == 1:
minutes = '0' + minutes
- return heures + minutes
+ secondes = str(round(heure % 3600 % 60))
+ if len(secondes) == 1:
+ secondes = '0' + secondes
+
+ return heures + minutes + secondes
diff --git a/Python/player.py b/Python/player.py
index 20047ac..90ab4be 100644
--- a/Python/player.py
+++ b/Python/player.py
@@ -429,7 +429,7 @@ def checkEvent(self, event, pilote, conflitBool):
if event.mouse_button == 3 and pilote:
return self.Id, 'EtatFreq', None
- elif event.mouse_button == 1 and pilote:
+ elif event.mouse_button == 1 and not pilote:
return 'menuATC'
elif event.mouse_button == 3 and self.papa.integreOrganique and (
diff --git a/Python/server.py b/Python/server.py
index 26aef03..3cb96d4 100644
--- a/Python/server.py
+++ b/Python/server.py
@@ -17,6 +17,7 @@
import Python.horloge as horloge
from Python.network import MCAST_GRP, MCAST_PORT, port
from Python.paquets_avion import *
+import Python.server_def as server_def
dossierXML = Path("").absolute() / 'XML'
@@ -235,7 +236,7 @@
simuTree = ET.parse(dossierXML / simu).getroot()
heure = simuTree.find('heure').text
- heure = int(heure[0:2]) * 3600 + int(heure[2:]) * 60
+ heure = int(heure[0:2]) * 3600 + int(heure[2:4]) * 60 + int(heure[4:])
game = Game(heure)
@@ -253,7 +254,7 @@
avionDict.update({XMLpoint.tag: XMLpointValue})
heureSpawn = avion.attrib['heure']
- heureSpawn = int(heureSpawn[0:2]) * 3600 + int(heureSpawn[2:]) * 60
+ heureSpawn = int(heureSpawn[0:2]) * 3600 + int(heureSpawn[2:4]) * 60 + int(heureSpawn[4:])
for route in gameMap['routes']:
if route == avionDict['route']:
@@ -288,36 +289,6 @@
heureXML.text = horloge.heureXML(game.heure)
avionsXML = ET.SubElement(simuTree, 'avions')
-def generateAvionXML(parent, heureEcriture, indicatifEcriture, aircraftEcriture, routeEcriture, altitudeEcriture, xEcriture=None, yEcriture=None, headingEcriture=None, PFLEcriture=None):
-
- avionXML = ET.SubElement(parent, 'avion')
- avionXML.set('heure', str(heureEcriture))
-
- node = ET.SubElement(avionXML, 'indicatif')
- node.text = str(indicatifEcriture)
- node = ET.SubElement(avionXML, 'aircraft')
- node.text = str(aircraftEcriture)
- node = ET.SubElement(avionXML, 'route')
- node.text = str(routeEcriture)
- node = ET.SubElement(avionXML, 'altitude')
- node.text = str(altitudeEcriture)
- node = ET.SubElement(avionXML, 'arrival')
- node.text = str(arrival)
-
- if xEcriture is not None:
- node = ET.SubElement(avionXML, 'x')
- node.text = str(xEcriture)
- node = ET.SubElement(avionXML, 'y')
- node.text = str(yEcriture)
-
- if headingEcriture is not None:
- node = ET.SubElement(avionXML, 'heading')
- node.text = str(headingEcriture)
-
- if PFLEcriture is not None:
- node = ET.SubElement(avionXML, 'PFL')
- node.text = str(PFLEcriture)
-
def threaded_client(conn, caca):
global dictAvion
@@ -385,130 +356,109 @@ def threaded_ping_responder():
requests.append(inReq)
for reqSublist in requests:
for req in reqSublist: # format requêtes : [Id avion, type requête, data]
- if req[1] == 'Add':
- req[2].Id = planeId
- dictAvion.update({planeId: req[2]})
+ reqType = req[1]
+ reqId = req[0]
+ reqContent = None
+
+ if len(req) == 3:
+ reqContent = req[2]
+
+ if reqType == 'Add':
+
+ reqContent.Id = planeId
+ dictAvion.update({planeId: reqContent})
planeId += 1
+
if mode_ecriture:
+ heure = horloge.heureXML(game.heure)
+ server_def.generateAvionXML(avionsXML, reqContent, heure)
- heures = str(round(game.heure // 3600))
- if len(heures) == 1:
- heures = '0' + heures
- minutes = str(round(game.heure % 3600 // 60))
- if len(minutes) == 1:
- minutes = '0' + minutes
-
- generateAvionXML(avionsXML,
- heures + minutes,
- req[2].indicatif,
- req[2].aircraft,
- req[2].route['name'],
- req[2].altitude,
- xEcriture=req[2].x,
- yEcriture=req[2].y,
- PFLEcriture=req[2].PFL)
- elif req[1] == 'DelayedAdd':
-
- req[2][1].Id = planeId
- planeId += 1
+ elif reqType == 'DelayedAdd':
- avionSpawnListe.append((game.heure + req[2][0], req[2][1]))
+ reqContent[1].Id = planeId
+ avionSpawnListe.append((game.heure + reqContent[0], reqContent[1]))
+ planeId += 1
if mode_ecriture:
-
- heures = str(round((game.heure + req[2][0]) // 3600))
- if len(heures) == 1:
- heures = '0' + heures
- minutes = str(round((game.heure + req[2][0]) % 3600 // 60))
- if len(minutes) == 1:
- minutes = '0' + minutes
-
- generateAvionXML(avionsXML,
- heures + minutes,
- req[2][1].indicatif,
- req[2][1].aircraft,
- req[2][1].route['name'],
- req[2][1].altitude,
- xEcriture=req[2][1].x,
- yEcriture=req[2][1].y,
- PFLEcriture=req[2][1].PFL)
-
- elif req[1] == 'Remove':
- dictAvion.pop(req[0])
- elif req[1] == 'FL':
- dictAvion[req[0]].selectedAlti = req[2] * 100
- elif req[1] == 'PFL':
- dictAvion[req[0]].PFL = req[2]
- dictAvion[req[0]].changeXFL(gameMap)
- elif req[1] == 'CFL':
- dictAvion[req[0]].CFL = req[2]
- elif req[1] == 'C_IAS':
+ heure = horloge.heureXML(game.heure)
+ server_def.generateAvionXML(avionsXML, reqContent, heure)
+
+ elif reqType == 'Remove':
+ dictAvion.pop(reqId)
+ elif reqType == 'FL':
+ dictAvion[reqId].selectedAlti = reqContent * 100
+ elif reqType == 'PFL':
+ dictAvion[reqId].PFL = reqContent
+ dictAvion[reqId].changeXFL(gameMap)
+ elif reqType == 'CFL':
+ dictAvion[reqId].CFL = reqContent
+ elif reqType == 'C_IAS':
if len(req) == 3:
- dictAvion[req[0]].clearedIAS = req[2]
+ dictAvion[reqId].clearedIAS = reqContent
else:
- dictAvion[req[0]].clearedIAS = None
- elif req[1] == 'C_Rate':
+ dictAvion[reqId].clearedIAS = None
+ elif reqType == 'C_Rate':
if len(req) == 3:
- dictAvion[req[0]].clearedRate = req[2]
+ dictAvion[reqId].clearedRate = reqContent
else:
- dictAvion[req[0]].clearedRate = None
- elif req[1] == 'Rate':
- signe = (dictAvion[req[0]].evolution * req[2]) / abs(dictAvion[req[0]].evolution * req[2])
- dictAvion[req[0]].evolution = signe * req[2]
- elif req[1] == 'XFL':
- dictAvion[req[0]].XFL = req[2]
- dictAvion[req[0]].changeSortieSecteur(gameMap)
- elif req[1] == 'XPT':
- dictAvion[req[0]].XPT = req[2]
- elif req[1] == 'C_HDG':
- dictAvion[req[0]].clearedHeading = req[2]
- elif req[1] == 'HDG':
- if type(req[2]) in [float, int]:
- newHeading = req[2]
- elif req[2][0] == '-':
- newHeading = dictAvion[req[0]].selectedHeading - int(req[2][1:])
- elif req[2][0] == '+':
- newHeading = dictAvion[req[0]].selectedHeading + int(req[2][1:])
- dictAvion[req[0]].headingMode = True
- dictAvion[req[0]].selectedHeading = req[2]
- elif req[1] == 'IAS':
- dictAvion[req[0]].selectedIAS = req[2] * 10
- elif req[1] == 'DCT':
- dictAvion[req[0]].clearedHeading = None
- dictAvion[req[0]].DCT = req[2]
- elif req[1] == 'Warning':
- dictAvion[req[0]].warning = not dictAvion[req[0]].warning
- elif req[1] == 'Integre':
- dictAvion[req[0]].integreOrganique = True
- elif req[1] == 'Direct':
- dictAvion[req[0]].headingMode = False
- for point in dictAvion[req[0]].route['points']:
- if point['name'] == req[2]:
- dictAvion[req[0]].nextPoint = point
+ dictAvion[reqId].clearedRate = None
+ elif reqType == 'Rate':
+ signe = (dictAvion[reqId].evolution * reqContent) / abs(dictAvion[reqId].evolution * reqContent)
+ dictAvion[reqId].evolution = signe * reqContent
+ elif reqType == 'XFL':
+ dictAvion[reqId].XFL = reqContent
+ dictAvion[reqId].changeSortieSecteur(gameMap)
+ elif reqType == 'XPT':
+ dictAvion[reqId].XPT = reqContent
+ elif reqType == 'C_HDG':
+ dictAvion[reqId].clearedHeading = reqContent
+ elif reqType == 'HDG':
+ if type(reqContent) in [float, int]:
+ newHeading = reqContent
+ elif reqContent[0] == '-':
+ newHeading = dictAvion[reqId].selectedHeading - int(reqContent[1:])
+ elif reqContent[0] == '+':
+ newHeading = dictAvion[reqId].selectedHeading + int(reqContent[1:])
+ dictAvion[reqId].headingMode = True
+ dictAvion[reqId].selectedHeading = reqContent
+ elif reqType == 'IAS':
+ dictAvion[reqId].selectedIAS = reqContent * 10
+ elif reqType == 'DCT':
+ dictAvion[reqId].clearedHeading = None
+ dictAvion[reqId].DCT = reqContent
+ elif reqType == 'Warning':
+ dictAvion[reqId].warning = not dictAvion[reqId].warning
+ elif reqType == 'Integre':
+ dictAvion[reqId].integreOrganique = True
+ elif reqType == 'Direct':
+ dictAvion[reqId].headingMode = False
+ for point in dictAvion[reqId].route['points']:
+ if point['name'] == reqContent:
+ dictAvion[reqId].nextPoint = point
break
- elif req[1] == 'Route':
- dictAvion[req[0]].nextRoute = req[2]
- dictAvion[req[0]].changeRoute(gameMap)
- elif req[1] == 'HighlightBouton':
- if req[2] in dictAvion[req[0]].boutonsHighlight: # si le bouton est déjà highlight alors:
- dictAvion[req[0]].boutonsHighlight.remove(req[2])
+ elif reqType == 'Route':
+ dictAvion[reqId].nextRoute = reqContent
+ dictAvion[reqId].changeRoute(gameMap)
+ elif reqType == 'HighlightBouton':
+ if reqContent in dictAvion[reqId].boutonsHighlight: # si le bouton est déjà highlight alors:
+ dictAvion[reqId].boutonsHighlight.remove(reqContent)
else:
- dictAvion[req[0]].boutonsHighlight.append(req[2])
- elif req[1] == 'Montrer':
- dictAvion[req[0]].montrer = not dictAvion[req[0]].montrer
- elif req[1] == 'EtatFreq':
- dictAvion[req[0]].updateEtatFreq(req[2])
- elif req[1] == 'FL?':
- dictAvion[req[0]].FLInterro = not dictAvion[req[0]].FLInterro
- elif req[1] == 'Pause':
+ dictAvion[reqId].boutonsHighlight.append(reqContent)
+ elif reqType == 'Montrer':
+ dictAvion[reqId].montrer = not dictAvion[reqId].montrer
+ elif reqType == 'EtatFreq':
+ dictAvion[reqId].updateEtatFreq(reqContent)
+ elif reqType == 'FL?':
+ dictAvion[reqId].FLInterro = not dictAvion[reqId].FLInterro
+ elif reqType == 'Pause':
game.paused = not game.paused
- elif req[1] == 'Faster':
+ elif reqType == 'Faster':
accelerationTemporelle += 0.5
- elif req[1] == 'Slower':
+ elif reqType == 'Slower':
if accelerationTemporelle > 0.5:
accelerationTemporelle -= 0.5
- elif req[1] == 'Save' and mode_ecriture:
- xmlstr = minidom.parseString(ET.tostring(simuTree)).toprettyxml(indent=" ")
+ elif reqType == 'Save' and mode_ecriture:
+ xmlstr = server_def.prettyPrint(minidom.parseString(ET.tostring(simuTree)))
with open("XML/simu.xml", "w") as f:
f.write(xmlstr)
diff --git a/Python/server_browser.py b/Python/server_browser.py
index 3439d59..ea06345 100644
--- a/Python/server_browser.py
+++ b/Python/server_browser.py
@@ -5,6 +5,7 @@
# Imports fichiers
from Python.network import MCAST_GRP, MCAST_PORT
+
def serverBrowser():
"""Lan scan et server browser en une fonction
renvoie une adresse IP en str"""
diff --git a/Python/server_def.py b/Python/server_def.py
index 88c01fb..204949b 100644
--- a/Python/server_def.py
+++ b/Python/server_def.py
@@ -2,6 +2,9 @@
# Native imports
import math
+# Module imports
+import xml.etree.ElementTree as ET
+
# Imports fichiers
import Python.geometry as geometry
from Python.valeurs_config import *
@@ -39,3 +42,50 @@ def STCA(avion1, avion2, carte) -> bool:
return False
+def generateAvionXML(parentNode, avion, heureXML):
+
+ """
+ Transforme un avion packet en un element XML
+ :param parentNode: La node XML dans laquelle on va inscrire notre nouvel avion
+ :param avion: L'avion Packet qu'il faut transformer en XML
+ :param heureXML:
+ :return:
+ """
+
+ avionXML = ET.SubElement(parentNode, 'avion')
+ avionXML.set('heure', str(heureXML))
+
+ node = ET.SubElement(avionXML, 'indicatif')
+ node.text = str(avion.indicatif)
+ node = ET.SubElement(avionXML, 'aircraft')
+ node.text = str(avion.aircraft)
+ node = ET.SubElement(avionXML, 'route')
+ node.text = str(avion.route['name'])
+ node = ET.SubElement(avionXML, 'altitude')
+ node.text = str(avion.altitude)
+ node = ET.SubElement(avionXML, 'arrival')
+ node.text = str(avion.arrival)
+
+ node = ET.SubElement(avionXML, 'x')
+ node.text = str(avion.x)
+ node = ET.SubElement(avionXML, 'y')
+ node.text = str(avion.y)
+
+ node = ET.SubElement(avionXML, 'PFL')
+ node.text = str(avion.PFL)
+
+
+def prettyPrint(docXML):
+ """
+ Rend le XML joli à regarder
+ :param docXML: le doc XML à transformer
+ :return:
+ """
+
+ XMLstring = ''
+
+ for line in docXML.toprettyxml().split('\n'):
+ if not line.strip() == '':
+ XMLstring += line + '\n'
+
+ return XMLstring
From 330e500868f01859b6dff8624ebecc2e1f209459 Mon Sep 17 00:00:00 2001
From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com>
Date: Mon, 7 Oct 2024 11:31:46 +0200
Subject: [PATCH 4/7] mach number
---
Python/paquets_avion.py | 34 ++++++++++++++-
Python/server.py | 90 ++++++++++++++++++----------------------
Python/valeurs_config.py | 2 +
3 files changed, 74 insertions(+), 52 deletions(-)
diff --git a/Python/paquets_avion.py b/Python/paquets_avion.py
index 5c536ca..7fbf8e2 100644
--- a/Python/paquets_avion.py
+++ b/Python/paquets_avion.py
@@ -1,4 +1,4 @@
-
+import math
# Native imports
import random
@@ -7,6 +7,33 @@
from Python.valeurs_config import *
+def densite_de_l_air(altitude: float) -> float:
+ """
+ Cacule la densité de l'air à cette altitude
+ :param altitude: en ft
+ :return:
+ """
+
+ altitude = 0.3048 * altitude
+ densite = 352.995 * (1 - 0.0000225577 * altitude) ** 5.25516 / (288.15 - 0.0065 * altitude)
+
+ return densite
+
+
+def trueAirSpeed(IAS: float, densite: float) -> float:
+
+ return IAS * math.sqrt(densite_air_surface / densite)
+
+
+def machNumber(TAS, altitude):
+
+ temperature = 15 - altitude / 500 + 273.15
+ if temperature <= 217.15:
+ temperature = 217.15
+
+ return TAS / math.sqrt(TAS_to_mach_yR * temperature)
+
+
class Game:
def __init__(self, heure):
self.ready = False
@@ -53,6 +80,10 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
self.altitude = altiDefault
self.speedIAS = perfos['IAS']
+ densite = densite_de_l_air(self.altitude)
+ self.TAS = trueAirSpeed(self.speedIAS, densite)
+ self.mach = machNumber(self.TAS, self.altitude)
+ print(self.mach)
self.speedGS = self.speedIAS + self.altitude / 200 # la GS dépends de l'alti
self.speedPx = self.speedGS / gameMap['mapScale'] * heureEnRefresh
@@ -160,7 +191,6 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
self.selectedAlti = self.CFL * 100
self.selectedHeading = self.heading
self.selectedIAS = self.speedIAS
- self.mach = self.speedIAS
self.clearedIAS = None
self.clearedMach = None
self.clearedHeading = None
diff --git a/Python/server.py b/Python/server.py
index 3cb96d4..8d3f31b 100644
--- a/Python/server.py
+++ b/Python/server.py
@@ -231,63 +231,53 @@
planeId = 0
simuTree = None
-try: # on essaye de charger une simu, si elle existe
- simuTree = ET.parse(dossierXML / simu).getroot()
- heure = simuTree.find('heure').text
- heure = int(heure[0:2]) * 3600 + int(heure[2:4]) * 60 + int(heure[4:])
+simuTree = ET.parse(dossierXML / simu).getroot()
- game = Game(heure)
+heure = simuTree.find('heure').text
+heure = int(heure[0:2]) * 3600 + int(heure[2:4]) * 60 + int(heure[4:])
- avionSpawnListe = []
- avionsXML = simuTree.find('avions')
- for avion in avionsXML:
+game = Game(heure)
- avionDict = {}
+avionSpawnListe = []
+avionsXML = simuTree.find('avions')
+for avion in avionsXML:
- for XMLpoint in avion:
- try:
- XMLpointValue = float(XMLpoint.text)
- except:
- XMLpointValue = XMLpoint.text
- avionDict.update({XMLpoint.tag: XMLpointValue})
-
- heureSpawn = avion.attrib['heure']
- heureSpawn = int(heureSpawn[0:2]) * 3600 + int(heureSpawn[2:4]) * 60 + int(heureSpawn[4:])
+ avionDict = {}
- for route in gameMap['routes']:
- if route == avionDict['route']:
- spawnRoute = gameMap['routes'][route]
- break
- if 'altitude' in avionDict:
- spawnFL = round(avionDict['altitude'] / 100)
- else:
- spawnFL = None
- avionPack = AvionPacket(
- gameMap,
- planeId,
- avionDict['indicatif'],
- avionDict['aircraft'],
- aircraftType[avionDict['aircraft']],
- spawnRoute,
- avionDict['arrival'] == 'True',
- FL=spawnFL,
- x=avionDict['x'],
- y=avionDict['y'])
- planeId += 1
-
- avionSpawnListe.append((heureSpawn, avionPack))
-except: # sinon, on demande juste l'heure de début
-
- heure = input('Heure de début de simu, format: hhmm')
- heure = int(heure[0:2]) * 3600 + int(heure[2:]) * 60
- avionSpawnListe = []
- simuTree = ET.Element('simu')
- game = Game(heure)
- heureXML = ET.SubElement(simuTree, 'heure')
- heureXML.text = horloge.heureXML(game.heure)
- avionsXML = ET.SubElement(simuTree, 'avions')
+ for XMLpoint in avion:
+ try:
+ XMLpointValue = float(XMLpoint.text)
+ except:
+ XMLpointValue = XMLpoint.text
+ avionDict.update({XMLpoint.tag: XMLpointValue})
+
+ heureSpawn = avion.attrib['heure']
+ heureSpawn = int(heureSpawn[0:2]) * 3600 + int(heureSpawn[2:4]) * 60 + int(heureSpawn[4:])
+
+ for route in gameMap['routes']:
+ if route == avionDict['route']:
+ spawnRoute = gameMap['routes'][route]
+ break
+ if 'altitude' in avionDict:
+ spawnFL = round(avionDict['altitude'] / 100)
+ else:
+ spawnFL = None
+ avionPack = AvionPacket(
+ gameMap,
+ planeId,
+ avionDict['indicatif'],
+ avionDict['aircraft'],
+ aircraftType[avionDict['aircraft']],
+ spawnRoute,
+ avionDict['arrival'] == 'True',
+ FL=spawnFL,
+ x=avionDict['x'],
+ y=avionDict['y'])
+ planeId += 1
+
+ avionSpawnListe.append((heureSpawn, avionPack))
def threaded_client(conn, caca):
diff --git a/Python/valeurs_config.py b/Python/valeurs_config.py
index b6a6cf1..b481360 100644
--- a/Python/valeurs_config.py
+++ b/Python/valeurs_config.py
@@ -11,3 +11,5 @@
dragDelay = 150 # on utilise cette valeur seuil pour déterminer si on doit cliquer sur un bouton ou drag l'etiquette
offsettEtiquetteDefault = 30 # de combien les etiquettes sont décalées en px à quand on les dessine la 1ere fois
temps_disparition_menus = 300 # en combien de milli sec les menus disparaissent après ne plus être survolé
+TAS_to_mach_yR = 287.052874 * 1.4
+densite_air_surface = 1.225
From a3ffb3e18e55fd1c0edc0a883e0578c95b154bbe Mon Sep 17 00:00:00 2001
From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com>
Date: Mon, 7 Oct 2024 22:11:13 +0200
Subject: [PATCH 5/7] =?UTF-8?q?d=C3=A9but=20mach=20et=20perfos?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
menus mach nickel, transition mach IAS à travailler
---
Python/XML/aircraft.xml | 285 +++++++++++++++++++++++++++++-------
Python/XML/carteSecteur.xml | 8 +-
Python/XML/simu.xml | 26 +---
Python/client.py | 2 +-
Python/interface.py | 31 +++-
Python/paquets_avion.py | 184 ++++++++++++++++-------
Python/server.py | 14 +-
Python/valeurs_config.py | 7 +-
Python/vitesses.py | 94 ++++++++++++
9 files changed, 509 insertions(+), 142 deletions(-)
create mode 100644 Python/vitesses.py
diff --git a/Python/XML/aircraft.xml b/Python/XML/aircraft.xml
index b8dfd30..100b686 100644
--- a/Python/XML/aircraft.xml
+++ b/Python/XML/aircraft.xml
@@ -3,62 +3,235 @@
-
- 280
- 410
- 2000
- 3000
-
-
- 200
- 450
- 1500
- 2000
-
-
- 280
- 410
- 2000
- 2500
-
-
- 240
- 450
- 1300
- 1700
-
-
- 250
- 450
- 2000
- 3000
-
-
- 310
- 550
- 2000
- 2500
-
-
- 210
- 550
- 2000
- 2500
-
-
- 280
- 550
- 1500
- 2000
-
-
- 280
- 550
- 2500
- 3000
-
-
-
+
+ 0.74
+ 0.70
+ 0.74
+
+ 270
+ 270
+
+ 280
+
+ 1000
+ 1500
+
+ 2500
+ 2500
+
+ 3500
+
+
+
+ 0.79
+ 0.78
+ 0.78
+
+ 290
+ 290
+
+ 280
+
+ 1500
+ 800
+
+ 2000
+ 2000
+
+ 3500
+
+
+
+ 0.79
+ 0.76
+ 0.76
+
+ 290
+ 290
+
+ 290
+
+ 1000
+ 800
+
+ 2000
+ 2000
+
+ 3500
+
+
+
+ 0.79
+ 0.78
+ 0.78
+
+ 290
+ 290
+
+ 290
+
+ 1000
+ 800
+
+ 1500
+ 2200
+
+ 3500
+
+
+
+ 0.79
+ 0.78
+ 0.78
+
+ 290
+ 290
+
+ 290
+
+ 1000
+ 800
+
+ 1400
+ 2000
+
+ 3500
+
+
+
+ 0.79
+ 0.78
+ 0.78
+
+ 290
+ 290
+
+ 290
+
+ 1000
+ 1000
+
+ 1800
+ 2000
+
+ 2500
+
+
+
+ 0.78
+ 0.78
+ 0.78
+
+ 290
+ 290
+
+ 290
+
+ 1000
+ 1000
+
+ 1500
+ 2300
+
+ 2500
+
+
+
+ 0.78
+ 0.78
+ 0.78
+
+ 290
+ 290
+
+ 290
+
+ 1000
+ 1000
+
+ 1500
+ 2100
+
+ 2500
+
+
+
+ 0.78
+ 0.78
+ 0.78
+
+ 290
+ 290
+
+ 290
+
+ 1000
+ 1500
+
+ 1200
+ 1800
+
+ 2500
+
+
+
+ 0.81
+ 0.80
+ 0.81
+
+ 290
+ 290
+
+ 290
+
+ 1200
+ 1500
+
+ 1200
+ 1500
+
+ 2500
+
+
+
+ 0.84
+ 0.82
+ 0.84
+
+ 300
+ 300
+
+ 300
+
+ 1500
+ 1000
+
+ 2000
+ 2500
+
+ 2500
+
+
+
+ 0.46
+ 0.46
+ 0.46
+
+ 200
+ 200
+
+ 240
+
+ 1000
+ 1500
+
+ 1500
+ 1000
+
+ 1500
+
+
+
AIGLE AZUR
diff --git a/Python/XML/carteSecteur.xml b/Python/XML/carteSecteur.xml
index ba3c058..931d434 100644
--- a/Python/XML/carteSecteur.xml
+++ b/Python/XML/carteSecteur.xml
@@ -771,7 +771,7 @@
S
BST
- 20
+ 50
LSE
@@ -802,7 +802,7 @@
SE
BST
- 20
+ 50
LSE
@@ -836,7 +836,7 @@
SE
BST
- 20
+ 50
LSE
@@ -867,7 +867,7 @@
SO
BST
- 20
+ 50
LSE
diff --git a/Python/XML/simu.xml b/Python/XML/simu.xml
index d38a1e6..ead6d33 100644
--- a/Python/XML/simu.xml
+++ b/Python/XML/simu.xml
@@ -2,35 +2,15 @@
100200
-
+
FCACA
- E195
+ B738
FRI-GAI
- 30000
+ 26000
False
1901
463
300
-
- FCACA
- B738
- MIROS-DIRMO
- 30000
- False
- 1848.27707757998
- 1472.4922664315754
- 300
-
-
- FCACA
- E195
- ABISA-RAPID
- 30000
- False
- 1375
- 1644
- 300
-
diff --git a/Python/client.py b/Python/client.py
index 4dd2e0b..fab957f 100644
--- a/Python/client.py
+++ b/Python/client.py
@@ -240,7 +240,7 @@ def main(server_ip: str):
if action:
if type(action) in [list, tuple]: # si c'est un tuple alors cela correspond à une requête
localRequests.append(action)
- elif action in ['C_HDG', 'DCT']:
+ elif type(action) is str:
menuValeurs = interface.menuValeurs(menuValeurs.avion, pygame.mouse.get_pos(), action, pilote)
if curseur_aliSep:
diff --git a/Python/interface.py b/Python/interface.py
index 8f4f160..6f3c312 100644
--- a/Python/interface.py
+++ b/Python/interface.py
@@ -611,6 +611,17 @@ def __init__(self, avion, pos: list[float, float] | tuple[float, float], valeur:
indexDeVitesse = self.liste.index(round(avion.papa.speedIAS / 10))
self.listeAff = self.liste[indexDeVitesse - 4: indexDeVitesse + 5]
+ elif valeur == 'C_Mach':
+ self.liste = [*range(30, 99)]
+ self.liste.reverse()
+
+ for i in range(len(self.liste)):
+ self.liste[i] = self.liste[i] / 100
+
+ indexDeVitesse = self.liste.index(round(avion.papa.mach, 2))
+
+ self.listeAff = self.liste[indexDeVitesse - 4: indexDeVitesse + 5]
+
elif valeur == 'C_Rate':
self.liste = [*range(500, 6000, 500)]
self.liste.reverse()
@@ -649,7 +660,7 @@ def __init__(self, avion, pos: list[float, float] | tuple[float, float], valeur:
self.plusBouton = None
self.moinsBouton = None
- if valeur == 'C_IAS':
+ if valeur in ['C_IAS', 'C_Mach']:
self.noeud = pygame_gui.elements.UIButton(
pygame.Rect((0, 0), (width / 2, -1)),
container=self.topContainer,
@@ -822,6 +833,11 @@ def __init__(self, avion, pos: list[float, float] | tuple[float, float], valeur:
(width,
height))
+ if self.valeur == 'C_IAS':
+ self.noeud.select()
+ elif self.valeur == 'C_Mach':
+ self.mach.select()
+
if pilote:
if self.valeur == 'DCT':
self.valeur = 'Direct'
@@ -829,6 +845,8 @@ def __init__(self, avion, pos: list[float, float] | tuple[float, float], valeur:
self.valeur = 'Rate'
elif self.valeur == 'C_IAS':
self.valeur = 'IAS'
+ elif self.valeur == 'C_Mach':
+ self.valeur = 'Mach'
elif self.valeur == 'C_HDG':
self.valeur = 'HDG'
@@ -883,6 +901,16 @@ def checkEvent(self, event):
self.moinsBouton.select()
self.plusBouton.unselect()
+ elif event.ui_element == self.noeud:
+ if self.mach.is_selected:
+ self.kill()
+ return 'C_IAS'
+
+ elif event.ui_element == self.mach:
+ if self.noeud.is_selected:
+ self.kill()
+ return 'C_Mach'
+
elif event.ui_element == self.resume:
self.kill()
if self.valeur in ['DCT', 'C_HDG']: # si c'est un cap, alors on veut continuer au cap
@@ -918,6 +946,7 @@ def checkEvent(self, event):
heading = round(self.avion.papa.selectedHeading + int(event.ui_element.text[1:]))
return self.avion.Id, self.valeur, heading
+
def checkScrolled(self, event):
"""
Vérifie si le menu est en train d'être scrollé
diff --git a/Python/paquets_avion.py b/Python/paquets_avion.py
index 7fbf8e2..119384f 100644
--- a/Python/paquets_avion.py
+++ b/Python/paquets_avion.py
@@ -5,33 +5,7 @@
# Imports fichiers
from Python.geometry import *
from Python.valeurs_config import *
-
-
-def densite_de_l_air(altitude: float) -> float:
- """
- Cacule la densité de l'air à cette altitude
- :param altitude: en ft
- :return:
- """
-
- altitude = 0.3048 * altitude
- densite = 352.995 * (1 - 0.0000225577 * altitude) ** 5.25516 / (288.15 - 0.0065 * altitude)
-
- return densite
-
-
-def trueAirSpeed(IAS: float, densite: float) -> float:
-
- return IAS * math.sqrt(densite_air_surface / densite)
-
-
-def machNumber(TAS, altitude):
-
- temperature = 15 - altitude / 500 + 273.15
- if temperature <= 217.15:
- temperature = 217.15
-
- return TAS / math.sqrt(TAS_to_mach_yR * temperature)
+import Python.vitesses as vitesses
class Game:
@@ -79,13 +53,8 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
else:
self.altitude = altiDefault
- self.speedIAS = perfos['IAS']
- densite = densite_de_l_air(self.altitude)
- self.TAS = trueAirSpeed(self.speedIAS, densite)
- self.mach = machNumber(self.TAS, self.altitude)
- print(self.mach)
- self.speedGS = self.speedIAS + self.altitude / 200 # la GS dépends de l'alti
- self.speedPx = self.speedGS / gameMap['mapScale'] * heureEnRefresh
+ self.evolution = 0 # taux de variation/radar refresh
+ self.altitudeEvoTxt = '-'
# RADAR display
self.warning = False
@@ -119,11 +88,6 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
else:
self.destination = random.choice(gameMap['aeroports'][route['destination']])
- # perfo
- self.turnRate = turnRateDefault
- self.maxROC = perfos['ROC']
- self.maxROD = perfos['ROD']
-
# format route {nomRoute, routeType, listeRoutePoints, sortie} points : {caractéristiques eg : nom alti IAS}
self.route = route
@@ -132,8 +96,6 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
self.nextPoint = None
self.findNextPoint(gameMap)
- self.evolution = 0 # taux de variation/radar refresh
- self.altitudeEvoTxt = '-'
if PFL is not None:
self.PFL = PFL
elif gameMap['floor'] < self.altitude/100 < gameMap['ceiling']:
@@ -187,15 +149,36 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
gameMap['points'][self.nextPoint['name']][1])
self.headingRad = (self.heading - 90) / 180 * math.pi
- # selected
+ # perfo
+ self.turnRate = turnRateDefault
+ self.perfos = perfos
+ self.forcedSpeed = False
+ self.forcedEvo = False
+ self.machMode = False
+ self.changeSpeed()
+
+ # selected + vitesses
+ if self.machMode:
+ self.speedIAS = self.perfos['descentIAS']
+ self.selectedIAS = self.perfos['descentIAS']
+ self.mach = self.selectedMach
+ else:
+ self.speedIAS = self.selectedIAS
+ self.mach = vitesses.IAS_to_Mach(self.speedIAS, self.altitude)
+
+ self.speedTAS = vitesses.mach_to_TAS(self.mach, self.altitude)
+ self.speedGS = self.speedTAS
+
self.selectedAlti = self.CFL * 100
self.selectedHeading = self.heading
- self.selectedIAS = self.speedIAS
+ self.selectedMach = self.mach
self.clearedIAS = None
self.clearedMach = None
self.clearedHeading = None
self.clearedRate = None
+ self.speedPx = self.speedGS / gameMap['mapScale'] * heureEnRefresh
+
def findNextPoint(self, carte):
self.nextPoint = findClosestSegment(self.route['points'], (self.x, self.y), carte['points'])[1]
@@ -247,7 +230,6 @@ def updateAlti(self):
if self.altitude != self.selectedAlti: # on regarde s'il faut évoluer
if self.altitude - self.selectedAlti > 0:
- self.evolution = - self.maxROD
# on arrive dans moins d'un refresh ?
if abs(self.altitude - self.selectedAlti) <= abs(self.evolution / 60 * radarRefresh):
@@ -257,8 +239,6 @@ def updateAlti(self):
self.altitudeEvoTxt = '↓'
else:
- self.evolution = self.maxROC
-
# on arrive dans moins d'un refresh ?
if abs(self.altitude - self.selectedAlti) <= abs(self.evolution / 60 * radarRefresh):
self.altitude = self.selectedAlti # alors, on met le niveau cible
@@ -270,6 +250,42 @@ def updateAlti(self):
self.altitudeEvoTxt = '-'
self.evolution = 0
+ def changeEvolution(self) -> None:
+ """
+ Sélectionne la vitesse en fonction de la phase de vol
+ :return:
+ """
+
+ if self.forcedEvo:
+ return None
+
+ if self.altitude >= altitude_conversion:
+ # ici, on prend les perfos en croisière
+
+ if self.selectedAlti < self.altitude:
+ self.evolution = - self.perfos['cruiseROD']
+
+ else:
+ self.evolution = self.perfos['cruiseROC']
+
+ elif self.altitude >= altitude_cruise:
+ # ici, on regarde si on est en montée/descente ou alors, si on approche du niveau de croisière
+
+ if self.selectedAlti < self.altitude:
+ self.evolution = - self.perfos['cruiseROD']
+
+ else:
+ self.evolution = self.perfos['climbROC']
+
+ else:
+ # ici, on est dans les basses couches donc on prend les perfos en basse alti
+
+ if self.selectedAlti < self.altitude:
+ self.evolution = - self.perfos['descentROD']
+
+ else:
+ self.evolution = self.perfos['initialClimbROC']
+
def move(self, gameMap):
# frequence update
@@ -313,19 +329,87 @@ def move(self, gameMap):
self.comete = self.comete[1:9]
self.comete.append((self.x, self.y))
+ self.changeEvolution()
self.updateAlti() # on change le niveau de l'avion si on est en evolution
- if self.speedIAS != self.selectedIAS: # s'il faut accélérer ou ralentir
- # on change la vitesse par un pas d'accél/deccel défaut
- self.speedIAS += (self.selectedIAS - self.speedIAS)/abs(self.selectedIAS - self.speedIAS) * acceldefault
+ self.changeSpeed()
+ self.computeSpeed()
- self.speedGS = self.speedIAS + self.altitude / 200
self.speedPx = self.speedGS / gameMap['mapScale'] * heureEnRefresh # on convertit les kt en px/refresh
# mouvement
self.x += self.speedPx * math.cos(self.headingRad)
self.y += self.speedPx * math.sin(self.headingRad)
+ def computeSpeed(self):
+
+ """
+ Fait évoluer la vitesse si on a besoin
+ :return:
+ """
+ if not self.machMode:
+ if self.speedIAS != self.selectedIAS: # s'il faut accélérer ou ralentir
+ # on change la vitesse par un pas d'accél/deccel défaut
+ if abs(self.selectedIAS - self.speedIAS) <= acceldefault:
+ self.speedIAS = self.selectedIAS
+ else:
+ self.speedIAS += (self.selectedIAS - self.speedIAS)/abs(self.selectedIAS - self.speedIAS) * acceldefault
+
+ self.mach = vitesses.IAS_to_Mach(self.speedIAS, self.altitude)
+ else:
+ if self.mach != self.selectedMach:
+ # on change la vitesse par un pas d'accél/deccel défaut
+ if abs(self.selectedMach - self.mach) <= acceldefaultMach:
+ self.mach = self.selectedMach
+ else:
+ self.mach += (self.selectedMach - self.mach) / abs(self.selectedMach - self.mach) * acceldefaultMach
+
+ self.speedTAS = vitesses.mach_to_TAS(self.mach, self.altitude)
+ self.speedGS = self.speedTAS
+
+ def changeSpeed(self) -> None:
+ """
+ Sélectionne la vitesse en fonction de la phase de vol
+ :return:
+ """
+
+ self.machMode = False
+
+ if self.forcedSpeed:
+ return None
+
+ if self.altitude >= altitude_conversion: # au-dessus de l'alti de conversion tout se fera en mach
+
+ self.machMode = True
+
+ if self.evolution == 0:
+ self.selectedMach = self.perfos['cruiseMach']
+
+ elif self.evolution < 0:
+ self.selectedMach = self.perfos['descentMach']
+
+ else:
+ self.selectedMach = self.perfos['climbMach']
+
+ elif self.altitude >= altitude_cruise: # en-dessous de l'alti de conversion tout se fera en IAS
+ # ici, on regarde si on est en montée/descente initiale ou alors, si on approche du niveau de croisière
+
+ if self.evolution <= 0: # on prend les perfs de descente pour la croisière (pas trouvé de perfo IAS cruise)
+ self.selectedIAS = self.perfos['descentIAS']
+
+ else:
+ self.selectedIAS = self.perfos['climbIAS']
+
+ else:
+ # ici, on est dans les basses couches donc on prend les perfos en basse alti
+
+ if self.evolution <= 0:
+ self.selectedIAS = self.perfos['descentIAS']
+ # les perfos sont les mêmes pendant la majorité de la descente d'où le manque de 240
+
+ else:
+ self.selectedIAS = self.perfos['initialClimbIAS']
+
def calculeEstimate(self, points: dict, pointVoulu: str) -> float:
"""
Calcule le temps à un point sur notre route. Pour avoir l'estimée, il faudra rajouter l'heure courante
diff --git a/Python/server.py b/Python/server.py
index 8d3f31b..72141b2 100644
--- a/Python/server.py
+++ b/Python/server.py
@@ -217,11 +217,17 @@
root = tree.getroot()
for aircraft in root.find('aircrafts'):
+
+ aircraftPerf = {}
+ for XMLpoint in aircraft:
+ try:
+ XMLpointValue = float(XMLpoint.text)
+ except:
+ XMLpointValue = XMLpoint.text
+ aircraftPerf.update({XMLpoint.tag: XMLpointValue})
+
aircraftType.update(
- {aircraft.attrib['name']: {'IAS': int(aircraft.find('speed').text),
- 'plafond': int(aircraft.find('ceiling').text),
- 'ROC': int(aircraft.find('ROC').text),
- 'ROD': int(aircraft.find('ROD').text)}})
+ {aircraft.attrib['name']: aircraftPerf})
callsignList = {}
for callsign in root.find('callsigns'):
diff --git a/Python/valeurs_config.py b/Python/valeurs_config.py
index b481360..9014775 100644
--- a/Python/valeurs_config.py
+++ b/Python/valeurs_config.py
@@ -3,7 +3,8 @@
nmToFeet = 6076
secteurDefault = 'RU' # secteur par défault, si le programme n'arrive pas à trouver un secteur de sortie
altiDefault = 30000 # alti en pied par défault, si on ne rentre pas d'alti pour spawn un avion
-acceldefault = 3 # accélération/decelération de kt par refresh
+acceldefault = 3 # accélération/decelération en kt par refresh
+acceldefaultMach = 0.003 # accélération/decelération en point de mach par refresh
turnRateDefault = 10 # turnrate/refresh par défault
liste_etat_freq = ['previousFreq', 'previousShoot', 'inFreq', 'nextCoord', 'nextShoot', 'nextFreq']
valeurCoord = 8 # combien de minute avant la sortie la coord passe
@@ -11,5 +12,5 @@
dragDelay = 150 # on utilise cette valeur seuil pour déterminer si on doit cliquer sur un bouton ou drag l'etiquette
offsettEtiquetteDefault = 30 # de combien les etiquettes sont décalées en px à quand on les dessine la 1ere fois
temps_disparition_menus = 300 # en combien de milli sec les menus disparaissent après ne plus être survolé
-TAS_to_mach_yR = 287.052874 * 1.4
-densite_air_surface = 1.225
+altitude_conversion = 27900
+altitude_cruise = 25000
diff --git a/Python/vitesses.py b/Python/vitesses.py
new file mode 100644
index 0000000..7e56c33
--- /dev/null
+++ b/Python/vitesses.py
@@ -0,0 +1,94 @@
+
+# Native imports
+from math import sqrt
+
+ms_per_kt = 0.51444
+feet_per_metre = 3.28
+
+# Some useful constants
+
+g = 9.81 # Acceleration due to gravity
+R = 287 # Specific gas constant for air
+L = 0.0065 # Lapse rate in K/m
+T0 = 288.15 # ISA sea level temp in K
+p0 = 101325 # ISA sea level pressure in Pa
+k = 1.4 # k is a shorthand for Gamma, the ratio of specific heats for air
+lss0 = sqrt(k*R*T0) # ISA sea level speed sound
+
+
+def compressible_pitot(M):
+ """
+ Renvoies un delta de pression en fonction d'un mach
+ :param M:
+ :return:
+ """
+
+ return (M*M*(k-1)/2 + 1) ** (k/(k-1)) - 1
+
+
+def pitot_to_Mach(d):
+ """
+ Retourne un machNumber en fonction d'un delta de pression
+ :param d:
+ :return:
+ """
+ return sqrt(((d+1)**((k-1)/k) - 1)*2/(k-1))
+
+
+def temperature(h):
+ """
+ Température en fonction de l'alti (bloquée à -56C)
+ :param h:
+ :return:
+ """
+ T = T0 - h*L
+ if T <= 217.15:
+ T = 217.15
+ return T
+
+
+def lss(h):
+ """
+ Vitesse du son en fonction de l'alti
+ :param h:
+ :return:
+ """
+ return sqrt(k*R*temperature(h))
+
+
+def pressure(h):
+ """
+ Pression en fonction de l'alti
+ :param h:
+ :return:
+ """
+ return p0 * (temperature(h) / T0) ** (g / L / R)
+
+
+def IAS_to_Mach(IAS, alti):
+
+ """
+ Converti une IAS en Mach
+ :param IAS:
+ :param alti:
+ :return:
+ """
+
+ alti = alti / feet_per_metre
+ IAS = IAS * ms_per_kt
+ ps = pressure(alti)
+ pd = compressible_pitot(IAS/lss0) * p0
+
+ return pitot_to_Mach(pd / ps)
+
+
+def mach_to_TAS(M, alti):
+ """
+ Converti un point de mach en TAS
+ :param M:
+ :param alti:
+ :return:
+ """
+ alti = alti / feet_per_metre
+ return lss(alti) * M / ms_per_kt
+
From 23250836fa283e48d3cae5cc7970e70fcdd98144 Mon Sep 17 00:00:00 2001
From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com>
Date: Tue, 8 Oct 2024 00:50:26 +0200
Subject: [PATCH 6/7] bordel
---
Python/interface.py | 2 +-
Python/paquets_avion.py | 11 ++++++---
Python/player.py | 3 +++
Python/server.py | 54 ++++++++++++++++++++++++++++++++++++++---
Python/vitesses.py | 9 +++++++
5 files changed, 71 insertions(+), 8 deletions(-)
diff --git a/Python/interface.py b/Python/interface.py
index 6f3c312..781bf25 100644
--- a/Python/interface.py
+++ b/Python/interface.py
@@ -371,7 +371,7 @@ def update(self, avion):
if avion.papa.clearedIAS and self.extended:
self.clearedSpeed.set_text("k" + avion.papa.clearedIAS)
elif avion.papa.clearedMach and self.extended:
- self.clearedSpeed.set_text("k" + avion.papa.clearedMach)
+ self.clearedSpeed.set_text("m" + avion.papa.clearedMach)
else:
self.clearedSpeed.set_text("S")
diff --git a/Python/paquets_avion.py b/Python/paquets_avion.py
index 119384f..e245c92 100644
--- a/Python/paquets_avion.py
+++ b/Python/paquets_avion.py
@@ -159,14 +159,15 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
# selected + vitesses
if self.machMode:
- self.speedIAS = self.perfos['descentIAS']
self.selectedIAS = self.perfos['descentIAS']
self.mach = self.selectedMach
+ self.speedTAS = vitesses.mach_to_TAS(self.mach, self.altitude)
+ self.speedIAS = vitesses.TAS_to_IAS(self.speedTAS, self.altitude)
else:
self.speedIAS = self.selectedIAS
self.mach = vitesses.IAS_to_Mach(self.speedIAS, self.altitude)
+ self.speedTAS = vitesses.mach_to_TAS(self.mach, self.altitude)
- self.speedTAS = vitesses.mach_to_TAS(self.mach, self.altitude)
self.speedGS = self.speedTAS
self.selectedAlti = self.CFL * 100
@@ -347,6 +348,7 @@ def computeSpeed(self):
Fait évoluer la vitesse si on a besoin
:return:
"""
+
if not self.machMode:
if self.speedIAS != self.selectedIAS: # s'il faut accélérer ou ralentir
# on change la vitesse par un pas d'accél/deccel défaut
@@ -364,6 +366,8 @@ def computeSpeed(self):
else:
self.mach += (self.selectedMach - self.mach) / abs(self.selectedMach - self.mach) * acceldefaultMach
+ self.speedIAS = vitesses.TAS_to_IAS(self.speedTAS, self.altitude)
+
self.speedTAS = vitesses.mach_to_TAS(self.mach, self.altitude)
self.speedGS = self.speedTAS
@@ -373,11 +377,10 @@ def changeSpeed(self) -> None:
:return:
"""
- self.machMode = False
-
if self.forcedSpeed:
return None
+ self.machMode = False
if self.altitude >= altitude_conversion: # au-dessus de l'alti de conversion tout se fera en mach
self.machMode = True
diff --git a/Python/player.py b/Python/player.py
index 90ab4be..f480e0b 100644
--- a/Python/player.py
+++ b/Python/player.py
@@ -465,6 +465,9 @@ def checkEvent(self, event, pilote, conflitBool):
elif event.ui_element == self.etiquette.AFL and event.mouse_button == 1 and pilote:
return 'FL'
+ elif event.ui_element == self.etiquette.clearedSpeed and event.mouse_button == 1 and self.papa.machMode:
+ return 'C_Mach'
+
elif event.ui_element == self.etiquette.clearedSpeed and event.mouse_button == 1:
return 'C_IAS'
diff --git a/Python/server.py b/Python/server.py
index 72141b2..eecc9fd 100644
--- a/Python/server.py
+++ b/Python/server.py
@@ -381,33 +381,54 @@ def threaded_ping_responder():
elif reqType == 'Remove':
dictAvion.pop(reqId)
+
elif reqType == 'FL':
dictAvion[reqId].selectedAlti = reqContent * 100
+
elif reqType == 'PFL':
dictAvion[reqId].PFL = reqContent
dictAvion[reqId].changeXFL(gameMap)
+
elif reqType == 'CFL':
dictAvion[reqId].CFL = reqContent
+
elif reqType == 'C_IAS':
if len(req) == 3:
dictAvion[reqId].clearedIAS = reqContent
else:
dictAvion[reqId].clearedIAS = None
+
+ elif reqType == 'C_Mach':
+ print(req)
+ if reqContent:
+ dictAvion[reqId].clearedMach = reqContent
+ else:
+ dictAvion[reqId].clearedMach = None
+
elif reqType == 'C_Rate':
if len(req) == 3:
dictAvion[reqId].clearedRate = reqContent
else:
dictAvion[reqId].clearedRate = None
+
elif reqType == 'Rate':
- signe = (dictAvion[reqId].evolution * reqContent) / abs(dictAvion[reqId].evolution * reqContent)
- dictAvion[reqId].evolution = signe * reqContent
+ if reqContent:
+ dictAvion[reqId].forcedEvo = True
+ signe = (dictAvion[reqId].evolution * reqContent) / abs(dictAvion[reqId].evolution * reqContent)
+ dictAvion[reqId].evolution = signe * reqContent
+ else:
+ dictAvion[reqId].forcedEvo = True
+
elif reqType == 'XFL':
dictAvion[reqId].XFL = reqContent
dictAvion[reqId].changeSortieSecteur(gameMap)
+
elif reqType == 'XPT':
dictAvion[reqId].XPT = reqContent
+
elif reqType == 'C_HDG':
dictAvion[reqId].clearedHeading = reqContent
+
elif reqType == 'HDG':
if type(reqContent) in [float, int]:
newHeading = reqContent
@@ -417,42 +438,69 @@ def threaded_ping_responder():
newHeading = dictAvion[reqId].selectedHeading + int(reqContent[1:])
dictAvion[reqId].headingMode = True
dictAvion[reqId].selectedHeading = reqContent
+
elif reqType == 'IAS':
- dictAvion[reqId].selectedIAS = reqContent * 10
+ if reqContent:
+ dictAvion[reqId].forcedSpeed = True
+ dictAvion[reqId].machMode = False
+ dictAvion[reqId].selectedIAS = reqContent * 10
+ else:
+ dictAvion[reqId].forcedSpeed = False
+
+ elif reqType == 'Mach':
+ if reqContent:
+ dictAvion[reqId].forcedSpeed = True
+ dictAvion[reqId].machMode = True
+ dictAvion[reqId].selectedMach = float(reqContent)
+ else:
+ dictAvion[reqId].forcedSpeed = False
+
elif reqType == 'DCT':
dictAvion[reqId].clearedHeading = None
dictAvion[reqId].DCT = reqContent
+
elif reqType == 'Warning':
dictAvion[reqId].warning = not dictAvion[reqId].warning
+
elif reqType == 'Integre':
dictAvion[reqId].integreOrganique = True
+
elif reqType == 'Direct':
dictAvion[reqId].headingMode = False
for point in dictAvion[reqId].route['points']:
if point['name'] == reqContent:
dictAvion[reqId].nextPoint = point
break
+
elif reqType == 'Route':
dictAvion[reqId].nextRoute = reqContent
dictAvion[reqId].changeRoute(gameMap)
+
elif reqType == 'HighlightBouton':
if reqContent in dictAvion[reqId].boutonsHighlight: # si le bouton est déjà highlight alors:
dictAvion[reqId].boutonsHighlight.remove(reqContent)
else:
dictAvion[reqId].boutonsHighlight.append(reqContent)
+
elif reqType == 'Montrer':
dictAvion[reqId].montrer = not dictAvion[reqId].montrer
+
elif reqType == 'EtatFreq':
dictAvion[reqId].updateEtatFreq(reqContent)
+
elif reqType == 'FL?':
dictAvion[reqId].FLInterro = not dictAvion[reqId].FLInterro
+
elif reqType == 'Pause':
game.paused = not game.paused
+
elif reqType == 'Faster':
accelerationTemporelle += 0.5
+
elif reqType == 'Slower':
if accelerationTemporelle > 0.5:
accelerationTemporelle -= 0.5
+
elif reqType == 'Save' and mode_ecriture:
xmlstr = server_def.prettyPrint(minidom.parseString(ET.tostring(simuTree)))
with open("XML/simu.xml", "w") as f:
diff --git a/Python/vitesses.py b/Python/vitesses.py
index 7e56c33..504194b 100644
--- a/Python/vitesses.py
+++ b/Python/vitesses.py
@@ -92,3 +92,12 @@ def mach_to_TAS(M, alti):
alti = alti / feet_per_metre
return lss(alti) * M / ms_per_kt
+
+def TAS_to_IAS(TAS, alti):
+ """
+ Convertit une TAS en IAS, de façon très grossière
+ :return:
+ """
+
+ return TAS - alti / 185
+
From 7527f748259b1f554c302d90aa3eb4d6ac4223a6 Mon Sep 17 00:00:00 2001
From: MaelkMaelk <65122264+MaelkMaelk@users.noreply.github.com>
Date: Tue, 8 Oct 2024 13:42:29 +0200
Subject: [PATCH 7/7] replay
fix : menus mach et IAS fonctionnent mtn
feet: replays
---
Python/XML/simu.xml | 16 -------
Python/capture.py | 10 ++++
Python/client.py | 14 ++++++
Python/paquets_avion.py | 2 +
Python/player.py | 4 +-
Python/server.py | 100 ++++++++++++++++++++++-----------------
Python/valeurs_config.py | 3 ++
7 files changed, 89 insertions(+), 60 deletions(-)
delete mode 100644 Python/XML/simu.xml
create mode 100644 Python/capture.py
diff --git a/Python/XML/simu.xml b/Python/XML/simu.xml
deleted file mode 100644
index ead6d33..0000000
--- a/Python/XML/simu.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
- 100200
-
-
- FCACA
- B738
- FRI-GAI
- 26000
- False
- 1901
- 463
- 300
-
-
-
diff --git a/Python/capture.py b/Python/capture.py
new file mode 100644
index 0000000..307c3d5
--- /dev/null
+++ b/Python/capture.py
@@ -0,0 +1,10 @@
+
+
+# Module Import
+
+import pygame
+
+
+def saveScreenshot(win, path):
+ screencopy = win.copy()
+ pygame.image.save(screencopy, path)
diff --git a/Python/client.py b/Python/client.py
index fab957f..c2f3859 100644
--- a/Python/client.py
+++ b/Python/client.py
@@ -13,6 +13,7 @@
import Python.interface as interface
from Python.paquets_avion import *
import Python.outils_radar as outils_radar
+import Python.capture as capture
# recherche de tous les serveurs sur le réseau
address = server_browser.serverBrowser()
@@ -39,6 +40,11 @@
clock = pygame.time.Clock()
font = pygame.font.SysFont('arial', 18)
+if replayMode:
+ dossierScreen = Path('replay') / (str(time.localtime()[1]) + '_' + str(time.localtime()[2]) + '_' +
+ str(time.localtime()[3]) + 'h' + str(time.localtime()[4]))
+ dossierScreen.mkdir()
+
def main(server_ip: str):
global temps
@@ -55,6 +61,9 @@ def main(server_ip: str):
flightDataWindow = None
menuRadar = interface.menuRadar()
+ # screenshots replays
+ dernierScreen = pygame.time.get_ticks()
+
# on se connecte au serveur
n = Network(server_ip)
packet = n.getP()
@@ -516,6 +525,11 @@ def main(server_ip: str):
img = font.render(str(distance), True, (255, 105, 180))
win.blit(img, (pygame.mouse.get_pos()[0] + 20, pygame.mouse.get_pos()[1]))
+ # prise des screenshots
+ if pygame.time.get_ticks() >= dernierScreen + delaiScreen and replayMode and not pilote:
+ capture.saveScreenshot(win, dossierScreen / (horloge.heureXML(game.heure) + '.png'))
+ dernierScreen = pygame.time.get_ticks()
+
# envoi des packets
# on fait avec un try and except au cas où un paquet se perde
diff --git a/Python/paquets_avion.py b/Python/paquets_avion.py
index e245c92..73974f6 100644
--- a/Python/paquets_avion.py
+++ b/Python/paquets_avion.py
@@ -177,6 +177,8 @@ def __init__(self, gameMap, Id, indicatif, aircraft, perfos, route, arrival, FL=
self.clearedMach = None
self.clearedHeading = None
self.clearedRate = None
+ self.clearedMachMode = False
+ self.clearedIASMode = False
self.speedPx = self.speedGS / gameMap['mapScale'] * heureEnRefresh
diff --git a/Python/player.py b/Python/player.py
index f480e0b..8fc7220 100644
--- a/Python/player.py
+++ b/Python/player.py
@@ -465,7 +465,9 @@ def checkEvent(self, event, pilote, conflitBool):
elif event.ui_element == self.etiquette.AFL and event.mouse_button == 1 and pilote:
return 'FL'
- elif event.ui_element == self.etiquette.clearedSpeed and event.mouse_button == 1 and self.papa.machMode:
+ elif (event.ui_element == self.etiquette.clearedSpeed and event.mouse_button == 1 and
+ (self.papa.machMode or self.papa.clearedMach) and not self.papa.clearedIAS):
+
return 'C_Mach'
elif event.ui_element == self.etiquette.clearedSpeed and event.mouse_button == 1:
diff --git a/Python/server.py b/Python/server.py
index eecc9fd..6ff2ad5 100644
--- a/Python/server.py
+++ b/Python/server.py
@@ -238,52 +238,62 @@
simuTree = None
+try:
+ simuTree = ET.parse(dossierXML / simu).getroot()
-simuTree = ET.parse(dossierXML / simu).getroot()
-
-heure = simuTree.find('heure').text
-heure = int(heure[0:2]) * 3600 + int(heure[2:4]) * 60 + int(heure[4:])
+ heure = simuTree.find('heure').text
+ heure = int(heure[0:2]) * 3600 + int(heure[2:4]) * 60 + int(heure[4:])
-game = Game(heure)
+ game = Game(heure)
-avionSpawnListe = []
-avionsXML = simuTree.find('avions')
-for avion in avionsXML:
+ avionSpawnListe = []
+ avionsXML = simuTree.find('avions')
+ for avion in avionsXML:
- avionDict = {}
+ avionDict = {}
- for XMLpoint in avion:
- try:
- XMLpointValue = float(XMLpoint.text)
- except:
- XMLpointValue = XMLpoint.text
- avionDict.update({XMLpoint.tag: XMLpointValue})
+ for XMLpoint in avion:
+ try:
+ XMLpointValue = float(XMLpoint.text)
+ except:
+ XMLpointValue = XMLpoint.text
+ avionDict.update({XMLpoint.tag: XMLpointValue})
- heureSpawn = avion.attrib['heure']
- heureSpawn = int(heureSpawn[0:2]) * 3600 + int(heureSpawn[2:4]) * 60 + int(heureSpawn[4:])
+ heureSpawn = avion.attrib['heure']
+ heureSpawn = int(heureSpawn[0:2]) * 3600 + int(heureSpawn[2:4]) * 60 + int(heureSpawn[4:])
- for route in gameMap['routes']:
- if route == avionDict['route']:
- spawnRoute = gameMap['routes'][route]
- break
- if 'altitude' in avionDict:
- spawnFL = round(avionDict['altitude'] / 100)
- else:
- spawnFL = None
- avionPack = AvionPacket(
- gameMap,
- planeId,
- avionDict['indicatif'],
- avionDict['aircraft'],
- aircraftType[avionDict['aircraft']],
- spawnRoute,
- avionDict['arrival'] == 'True',
- FL=spawnFL,
- x=avionDict['x'],
- y=avionDict['y'])
- planeId += 1
-
- avionSpawnListe.append((heureSpawn, avionPack))
+ for route in gameMap['routes']:
+ if route == avionDict['route']:
+ spawnRoute = gameMap['routes'][route]
+ break
+ if 'altitude' in avionDict:
+ spawnFL = round(avionDict['altitude'] / 100)
+ else:
+ spawnFL = None
+ avionPack = AvionPacket(
+ gameMap,
+ planeId,
+ avionDict['indicatif'],
+ avionDict['aircraft'],
+ aircraftType[avionDict['aircraft']],
+ spawnRoute,
+ avionDict['arrival'] == 'True',
+ FL=spawnFL,
+ x=avionDict['x'],
+ y=avionDict['y'])
+ planeId += 1
+
+ avionSpawnListe.append((heureSpawn, avionPack))
+except:
+
+ heure = input('Heure de début de simu, format: hhmm')
+ heure = int(heure[0:2]) * 3600 + int(heure[2:]) * 60
+ avionSpawnListe = []
+ simuTree = ET.Element('simu')
+ game = Game(heure)
+ heureXML = ET.SubElement(simuTree, 'heure')
+ heureXML.text = horloge.heureXML(game.heure)
+ avionsXML = ET.SubElement(simuTree, 'avions')
def threaded_client(conn, caca):
@@ -358,6 +368,7 @@ def threaded_ping_responder():
if len(req) == 3:
reqContent = req[2]
+ print(req)
if reqType == 'Add':
@@ -393,20 +404,23 @@ def threaded_ping_responder():
dictAvion[reqId].CFL = reqContent
elif reqType == 'C_IAS':
- if len(req) == 3:
+ if reqContent:
dictAvion[reqId].clearedIAS = reqContent
+ dictAvion[reqId].clearedMach = None
else:
+ dictAvion[reqId].clearedMach = None
dictAvion[reqId].clearedIAS = None
elif reqType == 'C_Mach':
- print(req)
if reqContent:
dictAvion[reqId].clearedMach = reqContent
+ dictAvion[reqId].clearedIAS = None
else:
dictAvion[reqId].clearedMach = None
+ dictAvion[reqId].clearedIAS = None
elif reqType == 'C_Rate':
- if len(req) == 3:
+ if reqContent:
dictAvion[reqId].clearedRate = reqContent
else:
dictAvion[reqId].clearedRate = None
@@ -417,7 +431,7 @@ def threaded_ping_responder():
signe = (dictAvion[reqId].evolution * reqContent) / abs(dictAvion[reqId].evolution * reqContent)
dictAvion[reqId].evolution = signe * reqContent
else:
- dictAvion[reqId].forcedEvo = True
+ dictAvion[reqId].forcedEvo = False
elif reqType == 'XFL':
dictAvion[reqId].XFL = reqContent
diff --git a/Python/valeurs_config.py b/Python/valeurs_config.py
index 9014775..fc219fb 100644
--- a/Python/valeurs_config.py
+++ b/Python/valeurs_config.py
@@ -14,3 +14,6 @@
temps_disparition_menus = 300 # en combien de milli sec les menus disparaissent après ne plus être survolé
altitude_conversion = 27900
altitude_cruise = 25000
+
+delaiScreen = 6900
+replayMode = False