backend-h / app.py
enzo-09's picture
Initial commit with Flask API and Docker setup
c167dd2
# app.py (modifié)
from flask import Flask, request, jsonify
from flask_cors import CORS
import numpy as np
from random import randint, choice
app = Flask(__name__)
CORS(app)
class Patient:
def __init__(self, id, esi_level, needs):
self.id = id
self.esi_level = esi_level
self.needs = needs
class CHU:
def __init__(self, id, resources, distance):
self.id = id
self.resources = resources.copy()
self.assigned_patients = {}
self.available_resources = resources.copy()
self.distance = distance # Nouvelle propriété pour la distance
def update_resources(chu, patient, action="remove"):
for r, qty in patient.needs.items():
if action == "remove":
chu.available_resources[r] = chu.available_resources.get(r, 0) - qty
print(f"CHU {chu.id} - {r} décrémenté: {chu.available_resources[r]}")
elif action == "add":
chu.available_resources[r] = chu.available_resources.get(r, 0) + qty
print(f"CHU {chu.id} - {r} incrémenté: {chu.available_resources[r]}")
def has_sufficient_resources(chu, needs):
for r, qty in needs.items():
available = chu.available_resources.get(r, 0)
if available < qty:
print(f"Échec pour {r}: besoin {qty}, disponible {available} dans CHU {chu.id}")
return False
print(f"Ressources suffisantes dans CHU {chu.id}")
return True
def assign_to_chu(chu, patient):
chu.assigned_patients[patient.id] = patient
update_resources(chu, patient, "remove")
def release_from_chu(chu, patient_id):
if patient_id in chu.assigned_patients:
patient = chu.assigned_patients[patient_id]
update_resources(chu, patient, "add")
del chu.assigned_patients[patient_id]
def generate_random_resources(nb_chus):
chus = []
for i in range(nb_chus):
resources = {
"lit": randint(35, 45),
"specialiste": randint(15, 25),
"generaliste": randint(15, 25),
"defibrillateur": randint(3, 8),
"scanner": randint(2, 5),
"respirateur": randint(5, 10),
"poche_sang": randint(50, 100)
}
# Générer une distance fictive entre 1 et 50 km
distance = randint(1, 50)
chus.append(CHU(i, resources, distance))
return chus
def generate_patient_needs(esi_level, requested_resources):
needs = {}
if esi_level == 1:
needs = {"lit": 1, "specialiste": 1, "defibrillateur": randint(0, 1), "respirateur": randint(0, 1), "poche_sang": randint(0, 3)}
elif esi_level == 2:
needs = {"lit": 1, "specialiste": 1, "scanner": randint(0, 1), "respirateur": randint(0, 1)}
elif esi_level == 3:
needs = {"lit": 1, "scanner": randint(0, 1), "specialiste": randint(0, 1), "generaliste": randint(0, 1)}
elif esi_level == 4:
needs = {"lit": randint(0, 1), "scanner": randint(0, 1), "generaliste": randint(0, 1)}
elif esi_level == 5:
needs = {"lit": randint(0, 1)} if randint(0, 1) else {}
resource_mapping = {
"Lit": "lit",
"Respirateur": "respirateur",
"Oxygène": "poche_sang",
"Sang": "poche_sang",
"Spécialiste": "specialiste",
"Généraliste": "generaliste",
"Défibrillateur": "defibrillateur"
}
for res in requested_resources:
key = resource_mapping.get(res)
if key:
needs[key] = needs.get(key, 0) + 1
else:
print(f"Ressource non reconnue: {res}")
print(f"Besoins générés pour ESI {esi_level}: {needs}")
return needs
def assign_patients_with_reallocation(patients, chus):
allocation = {p.id: chu.id for chu in chus for p in chu.assigned_patients.values()}
reallocations = []
patients_sorted = sorted(patients, key=lambda p: p.esi_level)
for patient in patients_sorted:
# Trouver tous les CHU avec assez de ressources
eligible_chus = [chu for chu in chus if has_sufficient_resources(chu, patient.needs)]
if eligible_chus:
# Choisir le CHU le plus proche parmi ceux qui ont assez de ressources
best_chu = min(eligible_chus, key=lambda chu: chu.distance)
print(f"CHU {best_chu.id} sélectionné pour patient {patient.id} (distance: {best_chu.distance} km)")
allocation[patient.id] = best_chu.id
assign_to_chu(best_chu, patient)
else:
# Si aucun CHU n'a assez de ressources et ESI <= 3, tenter une réallocation
if patient.esi_level <= 3:
for chu in chus:
to_release = [p for p in chu.assigned_patients.values() if p.esi_level > patient.esi_level]
if to_release:
candidate = max(to_release, key=lambda p: p.esi_level)
release_from_chu(chu, candidate.id)
reallocations.append((candidate.id, chu.id, patient.id, candidate.needs))
if has_sufficient_resources(chu, patient.needs):
allocation[patient.id] = chu.id
assign_to_chu(chu, patient)
break
unassigned = [p for p in patients if p.id not in allocation]
return allocation, reallocations, unassigned
# Initialiser 10 CHU au lieu de 3
chus = generate_random_resources(10)
@app.route('/assign_patient', methods=['POST'])
def assign_patient():
data = request.json
patient_id = data.get('id', f"PAT-{randint(1000, 9999)}")
esi_level = int(data['esi'])
requested_resources = data.get('ressources', [])
print(f"Données reçues: id={patient_id}, esi={esi_level}, ressources={requested_resources}")
patient_needs = generate_patient_needs(esi_level, requested_resources)
patient = Patient(patient_id, esi_level, patient_needs)
allocation, reallocations, unassigned = assign_patients_with_reallocation([patient], chus)
response = {
"patient_id": patient_id,
"assigned_chu": allocation.get(patient_id, None),
"chus": [
{
"id": chu.id,
"available_resources": chu.available_resources,
"assigned_patients": len(chu.assigned_patients),
"distance": chu.distance # Ajouter la distance dans la réponse
}
for chu in chus
],
"reallocations": reallocations,
"unassigned": [p.id for p in unassigned]
}
return jsonify(response)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=7860)