import os from django.utils import timezone from django.conf import settings from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import AllowAny from .models import Simulation from .serializers import SimulationSerializer from .fenics_runner import run_simulation from rest_framework.views import APIView from DangVan.dangvan import compute_dang_van import threading class SimulationViewSet(viewsets.ModelViewSet): permission_classes = [AllowAny] queryset = Simulation.objects.all().order_by('-created_at') serializer_class = SimulationSerializer def create(self, request, *args, **kwargs): name = request.data.get('name', '') parameters = request.data.get('parameters', {}) simulation = Simulation.objects.create( name=name, parameters=parameters, status='running' ) thread = threading.Thread( target=self._run_simulation_async, args=(simulation.id, parameters) ) thread.start() serializer = self.get_serializer(simulation) return Response(serializer.data, status=status.HTTP_201_CREATED) def _run_simulation_async(self, simulation_id, parameters): simulation = Simulation.objects.get(id=simulation_id) try: result = run_simulation(parameters) results_dir = os.path.join(settings.BASE_DIR, 'simulation_results') os.makedirs(results_dir, exist_ok=True) import shutil final_result_path = os.path.join( results_dir, f'result_{simulation_id}.txt' ) shutil.copy(result['results_file'], final_result_path) final_image_path = os.path.join( results_dir, f'result_{simulation_id}.png' ) shutil.copy(result['image_file'], final_image_path) # Copy generated frames if present frames_meta = None frames_src = result.get('frames') or [] if frames_src: frames_target_dir = os.path.join(results_dir, f'frames_{simulation_id}') os.makedirs(frames_target_dir, exist_ok=True) copied = [] for fp in frames_src: try: basename = os.path.basename(fp) dest = os.path.join(frames_target_dir, basename) shutil.copy(fp, dest) copied.append(f'simulation_results/frames_{simulation_id}/{basename}') except Exception: continue if copied: frames_meta = { 'dir': f'simulation_results/frames_{simulation_id}', 'files': copied, 'count': len(copied), } simulation.result_summary = { 'final_max': result['final_max'], 'final_mean': result['final_mean'], 'time_series': result['time_series'], 'frames': frames_meta } simulation.result_file_path = f'simulation_results/result_{simulation_id}.txt' simulation.result_image_path = f'simulation_results/result_{simulation_id}.png' simulation.status = 'completed' simulation.completed_at = timezone.now() simulation.save() except Exception as e: simulation.status = 'failed' simulation.error_message = str(e) simulation.save() @action(detail=True, methods=['get']) def result_image(self, request, pk=None): simulation = self.get_object() if simulation.result_image_path: image_path = os.path.join(settings.BASE_DIR, simulation.result_image_path) from django.http import FileResponse return FileResponse(open(image_path, 'rb'), content_type='image/png') return Response({'error': 'Aucune image disponible'}, status=404) @action(detail=True, methods=['get'], url_path='frame/(?P\\d+)') def frame(self, request, pk=None, index=None): simulation = self.get_object() frames = (simulation.result_summary or {}).get('frames') or {} files = frames.get('files') or [] try: idx = int(index) except Exception: return Response({'error': 'Index invalide'}, status=400) if 0 <= idx < len(files): frame_rel = files[idx] frame_abs = os.path.join(settings.BASE_DIR, frame_rel) from django.http import FileResponse return FileResponse(open(frame_abs, 'rb'), content_type='image/png') return Response({'error': 'Frame non disponible'}, status=404) class DangVanView(APIView): permission_classes = [AllowAny] def post(self, request): data = request.data or {} stress_series = data.get('stress_series') a = data.get('a') b = data.get('b') if stress_series is None or a is None or b is None: return Response({'error': 'Paramètres requis: stress_series, a, b'}, status=status.HTTP_400_BAD_REQUEST) try: result = compute_dang_van(stress_series, a, b) return Response(result, status=status.HTTP_200_OK) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)