|
|
|
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 |
|
|
|
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) |
|
} |
|
|
|
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: |
|
|
|
eligible_chus = [chu for chu in chus if has_sufficient_resources(chu, patient.needs)] |
|
|
|
if eligible_chus: |
|
|
|
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: |
|
|
|
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 |
|
|
|
|
|
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 |
|
} |
|
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) |