src/Controller/EvaluationController.php line 135

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Mark;
  4. use App\Entity\Evaluation;
  5. use App\Filter\EvaluationSearch;
  6. use App\Form\EvaluationType;
  7. use App\Form\Filter\EvaluationSearchType;
  8. use App\Repository\UserRepository;
  9. use App\Repository\CourseRepository;
  10. use App\Repository\StudentRepository;
  11. use App\Repository\AttributionRepository;
  12. use App\Repository\SequenceRepository;
  13. use App\Repository\ClassRoomRepository;
  14. use App\Repository\EvaluationRepository;
  15. use App\Repository\SchoolYearRepository;
  16. use App\Repository\MarkRepository;
  17. use Doctrine\ORM\EntityManagerInterface;
  18. use Knp\Component\Pager\PaginatorInterface;
  19. use Knp\Snappy\Pdf;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\HttpFoundation\Response;
  22. use Symfony\Component\Routing\Annotation\Route;
  23. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
  24. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  25. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  26. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  27. use App\Service\SchoolYearService;
  28. use Symfony\Component\Form\Forms;
  29. /**
  30. * Evaluationme controller.
  31. *
  32. * @Route("/evaluations")
  33. */
  34. class EvaluationController extends AbstractController
  35. {
  36. private $em;
  37. private EvaluationRepository $repo;
  38. private UserRepository $userRepo;
  39. private $scRepo;
  40. private StudentRepository $stdRepo;
  41. private $clRepo;
  42. private CourseRepository $crsRepo;
  43. private $seqRepo;
  44. private AttributionRepository $attrRepo;
  45. private $notes ;
  46. private MarkRepository $markRepo;
  47. private SchoolYearService $schoolYearService;
  48. public function __construct(
  49. UserRepository $userRepo,
  50. SchoolYearService $schoolYearService,
  51. EntityManagerInterface $em,
  52. EvaluationRepository $repo,
  53. StudentRepository $stdRepo,
  54. CourseRepository $crsRepo,
  55. SchoolYearRepository $scRepo,
  56. ClassRoomRepository $clRepo,
  57. SequenceRepository $seqRepo,
  58. AttributionRepository $attrRepo,
  59. MarkRepository $markRepo
  60. ) {
  61. $this->em = $em;
  62. $this->repo = $repo;
  63. $this->scRepo = $scRepo;
  64. $this->stdRepo = $stdRepo;
  65. $this->notes = array();
  66. $this->clRepo = $clRepo;
  67. $this->crsRepo = $crsRepo;
  68. $this->seqRepo = $seqRepo;
  69. $this->schoolYearService = $schoolYearService;
  70. $this->markRepo = $markRepo;
  71. $this->attrRepo = $attrRepo;
  72. $this->userRepo = $userRepo;
  73. }
  74. /**
  75. * Lists all Evaluationme entities.
  76. *
  77. * @Route("/", name="admin_evaluations")
  78. * @Method("GET")
  79. * @Template()
  80. */
  81. public function indexAction(PaginatorInterface $paginator, Request $request, SessionInterface $session)
  82. {
  83. if (!$this->getUser()) {
  84. $this->addFlash('warning', 'You need login first!');
  85. return $this->redirectToRoute('app_login');
  86. }
  87. if (!$this->getUser()->isVerified()) {
  88. $this->addFlash('warning', 'You need to have a verified account!');
  89. return $this->redirectToRoute('app_login');
  90. }
  91. $search = new EvaluationSearch();
  92. $searchForm = $this->createForm(EvaluationSearchType::class, $search);
  93. $year = $this->schoolYearService->sessionYearById();
  94. $searchForm->handleRequest($request);
  95. if ($searchForm->isSubmitted() && $searchForm->isValid()) {
  96. $room = $this->clRepo->findOneBy(array("id" => $_GET['room']));
  97. $sequence = $this->seqRepo->findOneBy(array("id" => $_GET['sequence']));
  98. $course = $this->crsRepo->findOneBy(array("id" => $_GET['course']));
  99. $entities = $this->repo->findEvaluations($year->getId(), $room, $sequence, $course);
  100. } else {
  101. $entities = $this->repo->findAnnualEvaluations($year->getId());
  102. }
  103. $evaluations = $paginator->paginate($entities, $request->query->get('page', 1), Evaluation::NUM_ITEMS_PER_PAGE);
  104. $evaluations->setCustomParameters([
  105. 'position' => 'centered',
  106. 'size' => 'large',
  107. 'rounded' => true,
  108. ]);
  109. return $this->render('evaluation/index.html.twig', ['pagination' => $evaluations, 'searchForm' => $searchForm->createView()]);
  110. }
  111. /**
  112. * Endpoint AJAX — retourne uniquement le fragment tableau + pagination.
  113. * Appelé automatiquement à chaque changement de filtre (sans bouton).
  114. *
  115. * @Route("/search", name="admin_evaluations_search", options={"expose"=true})
  116. * @Method("GET")
  117. */
  118. public function searchAction(PaginatorInterface $paginator, Request $request): Response
  119. {
  120. if (!$this->getUser() || !$this->getUser()->isVerified()) {
  121. return new Response('', 403);
  122. }
  123. $year = $this->schoolYearService->sessionYearById();
  124. $roomId = $request->query->get('room');
  125. $seqId = $request->query->get('sequence');
  126. $courseId = $request->query->get('course');
  127. $room = $roomId ? $this->clRepo->findOneById($roomId) : null;
  128. $sequence = $seqId ? $this->seqRepo->findOneById($seqId) : null;
  129. $course = $courseId ? $this->crsRepo->findOneById($courseId) : null;
  130. // Aucun filtre actif → toutes les évaluations de l'année
  131. if (!$room && !$sequence && !$course) {
  132. $entities = $this->repo->findAnnualEvaluations($year->getId());
  133. } else {
  134. $entities = $this->repo->findEvaluations($year->getId(), $room, $sequence, $course);
  135. }
  136. $pagination = $paginator->paginate(
  137. $entities,
  138. $request->query->getInt('page', 1),
  139. Evaluation::NUM_ITEMS_PER_PAGE
  140. );
  141. $pagination->setCustomParameters([
  142. 'position' => 'centered',
  143. 'size' => 'large',
  144. 'rounded' => true,
  145. ]);
  146. // Fragment uniquement — pas le layout complet
  147. return $this->render('evaluation/_results.html.twig', [
  148. 'pagination' => $pagination,
  149. ]);
  150. }
  151. /**
  152. * Finds and displays a Evaluationme entity.
  153. *
  154. * @Route("/{id}/show", name="admin_evaluations_show", requirements={"id"="\d+"})
  155. * @Method("GET")
  156. * @Template()
  157. */
  158. public function showAction(Evaluation $evaluation, SessionInterface $session)
  159. {
  160. if (!$this->getUser()) {
  161. $this->addFlash('warning', 'You need login first!');
  162. return $this->redirectToRoute('app_login');
  163. }
  164. if (!$this->getUser()->isVerified()) {
  165. $this->addFlash('warning', 'You need to have a verified account!');
  166. return $this->redirectToRoute('app_login');
  167. }
  168. $year = $this->schoolYearService->sessionYearById();
  169. $studentsEnrolledInClass = $this->stdRepo->findEnrolledStudentsThisYearInClass($evaluation->getClassRoom(), $year);
  170. return $this->render('evaluation/show.html.twig', ['studentEnrolled' => $studentsEnrolledInClass, 'evaluation' => $evaluation]);
  171. }
  172. /**
  173. * @Route("/new",name= "admin_evaluations_new", methods={"GET"})
  174. */
  175. public function new(Request $request, SessionInterface $session): Response
  176. {
  177. if (!$this->getUser()) {
  178. $this->addFlash('warning', 'You need login first!');
  179. return $this->redirectToRoute('app_login');
  180. }
  181. if (!$this->getUser()->isVerified()) {
  182. $this->addFlash('warning', 'You need to have a verified account!');
  183. return $this->redirectToRoute('app_login');
  184. }
  185. $year = $this->schoolYearService->sessionYearById();
  186. $evaluation = new Evaluation();
  187. $form = $this->createForm(EvaluationType::class, $evaluation);
  188. return $this->render('evaluation/new.html.twig', array(
  189. 'evaluation' => $evaluation,
  190. 'response' => null,
  191. 'form' => $form->createView(),
  192. ));
  193. }
  194. /**
  195. * Creates a new Evaluation entity.
  196. *
  197. * @Route("/create", name="admin_evaluations_create")
  198. * @Method({"POST"})
  199. * @Template()
  200. */
  201. public function create(Request $request, SessionInterface $session)
  202. {
  203. if (!$this->getUser()) {
  204. $this->addFlash('warning', 'You need login first!');
  205. return $this->redirectToRoute('app_login');
  206. }
  207. if (!$this->getUser()->isVerified()) {
  208. $this->addFlash('warning', 'You need to have a verified account!');
  209. return $this->redirectToRoute('app_login');
  210. }
  211. $evaluation = new Evaluation();
  212. if ($content = $request->getContent()) {
  213. $marks = json_decode($_POST['marks'], true);
  214. $notes = array();
  215. $effectif = 0;
  216. $total = 0;
  217. $pos = 0;
  218. $room = $request->request->get('idroom');
  219. $idcourse = $request->request->get('idcourse');
  220. $idsequence = $request->request->get('idsequence');
  221. $competence = $request->request->get('competence');
  222. $year = $this->schoolYearService->sessionYearById();
  223. $classRoom = $this->clRepo->findOneBy(array("id" => $room));
  224. $course = $this->crsRepo->findOneBy(array("id" => $idcourse));
  225. $sequence = $this->seqRepo->findOneBy(array("id" => $idsequence));
  226. if($sequence == null)
  227. {
  228. $sequence = $this->seqRepo->findOneBy(array("activated" => true));
  229. }
  230. $evaluation->setCourse($course);
  231. $evaluation->setAuthor($this->getUser());
  232. $evaluation->setClassRoom($classRoom);
  233. $evaluation->setSequence($sequence);
  234. $evaluation->setCompetence($competence);
  235. foreach ($marks as $record) {
  236. $mark = new Mark();
  237. $matricule = $record["matricule"];
  238. $note = $record["note"];
  239. $poids = $record["weight"];
  240. $appreciation = $record["appreciation"];
  241. $student = $this->stdRepo->findOneByMatricule($matricule);
  242. if (strcmp($student->getGender(), "M") == 0) {
  243. if ($note < 10) {
  244. $evaluation->addFailluresH();
  245. } else {
  246. $evaluation->addSuccessH();
  247. }
  248. } else {
  249. if ($note < 10) {
  250. $evaluation->addFailluresf();
  251. } else {
  252. $evaluation->addSuccessF();
  253. }
  254. }
  255. if ($poids == 0) {
  256. $evaluation->addAbscent();
  257. } else {
  258. $effectif++;
  259. $total += $note;
  260. }
  261. $mark->setValue($note);
  262. $mark->setWeight($poids);
  263. $mark->setAppreciation($appreciation);
  264. $mark->setEvaluation($evaluation);
  265. $mark->setStudent($student);
  266. $notes[$pos++] = $mark; // Construction d'un arrayList pour trie
  267. $this->em->persist($mark);
  268. $evaluation->addMark($mark);
  269. }
  270. // analysons si l'utilisateur est autorise a enregistrer les notes sur la matiere
  271. // disposition des rang dans les notes
  272. usort($notes, function ($a, $b) {
  273. if ($a->getValue() == $b->getValue()) {
  274. return 0;
  275. }
  276. return ($a->getValue() < $b->getValue()) ? -1 : 1;
  277. });
  278. $evaluation->setMini($notes[0]->getValue());
  279. if($effectif>1){
  280. $evaluation->setMaxi($notes[$effectif-1]->getValue());
  281. } else {
  282. $evaluation->setMaxi(0);
  283. }
  284. foreach ($notes as $mark) {
  285. $mark->setRank2($pos);
  286. $pos--;
  287. }
  288. if ($effectif != 0) {
  289. $evaluation->setMoyenne($total / $effectif);
  290. } else {
  291. $evaluation->setMoyenne(0);
  292. }
  293. $this->em->persist($evaluation);
  294. $this->em->flush();
  295. }
  296. return $this->redirect($this->generateUrl('admin_evaluations_new'));
  297. }
  298. /**
  299. * Displays a form to edit an existing Evaluationme entity.
  300. *
  301. * @Route("/{id}/edit", name="admin_evaluations_edit", requirements={"id"="\d+"}, methods={"GET","PUT"})
  302. * @Template()
  303. */
  304. public function edit(Request $request, Evaluation $evaluation, SessionInterface $session): Response
  305. {
  306. if (!$this->getUser()) {
  307. $this->addFlash('warning', 'You need login first!');
  308. return $this->redirectToRoute('app_login');
  309. }
  310. if (!$this->getUser()->isVerified()) {
  311. $this->addFlash('warning', 'You need to have a verified account!');
  312. return $this->redirectToRoute('app_login');
  313. }
  314. if(($evaluation->getAuthor()!=$this->getUser()) && !($this->isGranted('ROLE_ADMIN')))
  315. {
  316. $this->addFlash('warning', 'Access forbidden!');
  317. return $this->redirectToRoute('admin_evaluations');
  318. }
  319. $form = $this->createForm(EvaluationType::class, $evaluation, array(
  320. 'action' => $this->generateUrl('prof_evaluations_update', array('id' => $evaluation->getId())),
  321. 'method' => 'PUT',
  322. ));
  323. $form->handleRequest($request);
  324. $sequence = $evaluation->getSequence();
  325. $marks = $this->markRepo->findBy(array("evaluation" => $evaluation));
  326. $notes = array();
  327. $year = $this->schoolYearService->sessionYearById();
  328. $studentsEnrolledInClass = $this->stdRepo->findEnrolledStudentsThisYearInClass($evaluation->getClassRoom(), $year);
  329. foreach ($studentsEnrolledInClass as $std) {
  330. foreach ($marks as $mark) {
  331. if ($mark->getStudent()->getId() == $std->getId()) {
  332. $notes[$std->getMatricule()] = $mark;
  333. break;
  334. }
  335. }
  336. }
  337. return $this->render('evaluation/edit.html.twig', [
  338. 'marks' => $notes,
  339. 'students' => $studentsEnrolledInClass,
  340. 'evaluation' => $evaluation,
  341. 'edit_form' => $form->createView()
  342. ]);
  343. }
  344. /**
  345. * Update a mark on an evaluation entity if the student is not absent or add a new mark if the student was absent.
  346. */
  347. public function editMark(Request $request, Evaluation $evaluation, String $matricule)
  348. {
  349. if (!$this->getUser()) {
  350. $this->addFlash('warning', 'You need login first!');
  351. return $this->redirectToRoute('app_login');
  352. }
  353. if (!$this->getUser()->isVerified()) {
  354. $this->addFlash('warning', 'You need to have a verified account!');
  355. return $this->redirectToRoute('app_login');
  356. }
  357. $year = $this->schoolYearService->sessionYearById();
  358. $studentsEnrolledInClass = $this->stdRepo->findEnrolledStudentsThisYearInClass($evaluation->getClassRoom(), $year);
  359. $marks = $this->markRepo->findBy(array("evaluation" => $evaluation));
  360. $note = $_POST[$matricule."note"];
  361. $appr = $_POST[$matricule."appr"];
  362. $weight = $_POST[$matricule."weight"];
  363. $pos = 0;
  364. $index=0;
  365. $found = false;
  366. while($index < count($marks) && !$found)
  367. {
  368. if($marks[$index]->getStudent()->getMatricule() == $matricule)
  369. {
  370. $found = true;
  371. $marks[$index]->setValue($note);
  372. $marks[$index]->setWeight($weight);
  373. $marks[$index]->setAppreciation($appr);
  374. $this->em->persist($marks[$index]);
  375. $this->notes[$pos++] = $marks[$index]; // Construction d'un arrayList pour trie
  376. }
  377. else
  378. {
  379. $index++;
  380. }
  381. }
  382. if(!$found)
  383. {
  384. $newMark = new Mark();
  385. $student = $this->stdRepo->findOneByMatricule($matricule);
  386. $newMark->setValue($note);
  387. $newMark->setWeight($weight);
  388. $newMark->setAppreciation($appr);
  389. $newMark->setEvaluation($evaluation);
  390. $newMark->setStudent($student);
  391. $evaluation->addMark($newMark);
  392. $this->em->persist($newMark);
  393. $this->notes[$pos++] = $newMark; // Construction d'un arrayList pour trie
  394. }
  395. $evaluation->setMini($this->notes[0]->getValue());
  396. $evaluation->setMaxi($this->notes[$pos-1]->getValue());
  397. $evaluation->setAuthor($this->getUser());
  398. $this->em->persist($evaluation);
  399. $this->em->flush();
  400. }
  401. /**
  402. * Edits an existing Evaluation entity.
  403. *
  404. * @Route("/{id}/update", name="prof_evaluations_update", requirements={"id"="\d+"})
  405. * @Method("PUT")
  406. */
  407. public function updateAction(Evaluation $evaluation, Request $request, SessionInterface $session)
  408. {
  409. if (!$this->getUser()) {
  410. $this->addFlash('warning', 'You need login first!');
  411. return $this->redirectToRoute('app_login');
  412. }
  413. if (!$this->getUser()->isVerified()) {
  414. $this->addFlash('warning', 'You need to have a verified account!');
  415. return $this->redirectToRoute('app_login');
  416. }
  417. $year = $this->schoolYearService->sessionYearById();
  418. $studentsEnrolledInClass = $this->stdRepo->findEnrolledStudentsThisYearInClass($evaluation->getClassRoom(), $year);
  419. if ($content = $request->getContent()) {
  420. $competence = ($request->request->get("evaluation")["competence"]);
  421. $evaluation->setCompetence($competence);
  422. $evaluation->setFailluresF(0);
  423. $evaluation->setFailluresH(0);
  424. $evaluation->setSuccessF(0);
  425. $evaluation->setSuccessH(0);
  426. $evaluation->setAbscent(0);
  427. $effectif = 0;
  428. $total = 0;
  429. foreach ($studentsEnrolledInClass as $std) {
  430. $this->editMark($request, $evaluation, $std->getMatricule());
  431. $note = $_POST[$std->getMatricule()."note"];
  432. $weight = $_POST[$std->getMatricule() . "weight"];
  433. if (strcmp($std->getGender(), "M") == 0) {
  434. if ($note < 10) {
  435. $evaluation->addFailluresH();
  436. } else {
  437. $evaluation->addSuccessH();
  438. }
  439. } else {
  440. if ($note < 10) {
  441. $evaluation->addFailluresH();
  442. } else {
  443. $evaluation->addSuccessF();
  444. }
  445. }
  446. if ($weight == 0) {
  447. $evaluation->addAbscent();
  448. } else {
  449. $effectif++;
  450. $total += $note;
  451. }
  452. }
  453. }
  454. // disposition des rang dans les notes
  455. usort($this->notes, function ($a, $b) {
  456. if ($a->getValue() == $b->getValue()) {
  457. return 0;
  458. }
  459. return ($a->getValue() < $b->getValue()) ? -1 : 1;
  460. });
  461. $pos = count($this->notes);
  462. foreach ($this->notes as $mark) {
  463. $mark->setRank2($pos);
  464. $pos--;
  465. }
  466. if ($effectif != 0) {
  467. $evaluation->setMoyenne($total / $effectif);
  468. }
  469. $this->em->flush();
  470. $this->addFlash('success', 'Evaluation succesfully updated');
  471. return $this->redirect($this->generateUrl('admin_evaluations'));
  472. }
  473. /**
  474. * Deletes a Evaluationme entity.
  475. *
  476. * @Route("/{id}/delete", name="admin_evaluations_delete", requirements={"id"="\d+"}, methods={"DELETE"})
  477. */
  478. public function delete(Evaluation $evaluation, Request $request): Response
  479. {
  480. if (!$this->getUser()) {
  481. $this->addFlash('warning', 'You need login first!');
  482. return $this->redirectToRoute('app_login');
  483. }
  484. if (!$this->getUser()->isVerified()) {
  485. $this->addFlash('warning', 'You need to have a verified account!');
  486. return $this->redirectToRoute('app_login');
  487. }
  488. if (!$this->getUser()) {
  489. $this->addFlash('warning', 'You need login first!');
  490. return $this->redirectToRoute('app_login');
  491. }
  492. if (!$this->getUser()->isVerified()) {
  493. $this->addFlash('warning', 'You need to have a verified account!');
  494. return $this->redirectToRoute('app_login');
  495. }
  496. /* if($evaluation->getTeacher()!=$this->getUser())
  497. {
  498. $this->addFlash('warning', 'Access forbidden!');
  499. return $this->redirectToRoute('app_home');
  500. }*/
  501. // dd($this->isCsrfTokenValid('evaluations_deletion'.$evaluation->getId(), $request->request->get('csrf_token') ));
  502. // if($this->isCsrfTokenValid('evaluations_deletion'.$evaluation->getId(), $request->request->get('csrf_token') )){
  503. foreach ($evaluation->getMarks() as $mark) {
  504. $this->em->remove($mark);
  505. }
  506. $this->em->remove($evaluation);
  507. $this->em->flush();
  508. $this->addFlash('info', 'Evaluation succesfully deleted');
  509. // }
  510. return $this->redirectToRoute('admin_evaluations');
  511. }
  512. /**
  513. * Displays a form to create a new Evaluation entity.
  514. *
  515. * @Route("/fiche", name="admin_classroom_students", options = { "expose" = true })
  516. * @Method("POST")
  517. * @Template()
  518. */
  519. public function listStudentsFicheAction(Request $request, SessionInterface $session)
  520. {
  521. if ($_POST["idclassroom"] ) {
  522. $idclassroom = $_POST["idclassroom"];
  523. if ($idclassroom != null) {
  524. $idsequence = isset($_POST['idsequence']) ? $_POST["idsequence"] : null;
  525. $year = $this->schoolYearService->sessionYearById();
  526. $classRoom = $this->clRepo->findOneById($idclassroom);
  527. $sequence = ($idsequence != null)? $this->seqRepo->findOneById($idsequence) : $this->seqRepo->findOneBy(array("activated" => true));
  528. $coursesOfRoom = $this->crsRepo->findProgrammedCoursesInClassAndNoYetEvaluated($classRoom, $sequence);
  529. $coursesOfConnectedUser = $this->getUser()->getCourses($year);
  530. if ($this->isGranted('ROLE_PROF')) {
  531. $courses = array_intersect($coursesOfRoom, $coursesOfConnectedUser);
  532. }
  533. if ($this->isGranted('ROLE_ADMIN')) {
  534. $courses = $coursesOfRoom;
  535. }
  536. // Liste des élèves inscrit dans la salle de classe sélectionnée
  537. $studentsEnrolledInClass = $this->stdRepo->findEnrolledStudentsThisYearInClass($classRoom, $year);
  538. if ($studentsEnrolledInClass != null) {
  539. return $this->render('evaluation/liststudents.html.twig', array('students' => $studentsEnrolledInClass, 'courses' => $courses));
  540. }
  541. }
  542. }
  543. return new Response("No Students");
  544. }
  545. /**
  546. * Finds and displays a Evaluation entity.
  547. *
  548. * @Route("/{id}/pdf", name="admin_evaluations_pdf", requirements={"id"="\d+"})
  549. * @Method("GET")
  550. * @Template()
  551. */
  552. public function pdfAction(Evaluation $evaluation, \Knp\Snappy\Pdf $snappy)
  553. {
  554. if (!$this->getUser()) {
  555. $this->addFlash('warning', 'You need login first!');
  556. return $this->redirectToRoute('app_login');
  557. }
  558. if (!$this->getUser()->isVerified()) {
  559. $this->addFlash('warning', 'You need to have a verified account!');
  560. return $this->redirectToRoute('app_login');
  561. }
  562. $author = $this->userRepo->findOneBy(["id"=>$evaluation->getAuthor()->getId()]);
  563. $html = $this->renderView('evaluation/pdf.html.twig', array(
  564. 'evaluation' => $evaluation,
  565. 'author' => $author
  566. ));
  567. return new Response(
  568. $snappy->getOutputFromHtml($html, array(
  569. 'default-header' => false
  570. )),
  571. 200,
  572. array(
  573. 'Content-Type' => 'application/pdf',
  574. 'Content-Disposition' => 'attachment; filename="' . $evaluation->getSequence()->getWording() . '_' . $evaluation->getClassRoom()->getName() . '_' . $evaluation->getId() . '.pdf"',
  575. )
  576. );
  577. }
  578. }