index.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <?php
  2. require_once "libs/fnMain.php";
  3. /**************************
  4. * VALIDATION DES DONNEES
  5. **************************/
  6. $isClassementValid = isset($_GET["classement"]) && (int) $_GET["classement"] !== 0;
  7. $isTriVilleValid = isset($_GET["v"]) && is_array($_GET["v"]) && $_GET["v"] !== [];
  8. $isTriSpeValid = isset($_GET["s"]) && is_array($_GET["s"]) && $_GET["s"] !== [];
  9. $specialitySourceDatasetAbrev = getCsvToArrayKeyValue($_SETTINGS["datasetFolder"]."/liste_specialites_abrev.csv");
  10. $specialitySourceDataset = getCsvToArrayKeyValue($_SETTINGS["datasetFolder"]."/liste_specialites.csv");
  11. $citySourceDataset = getCsvToArrayKeyValue($_SETTINGS["datasetFolder"]."/liste_villes.csv");
  12. /**************************
  13. * Affichage du formulaire
  14. **************************/
  15. ?>
  16. <!doctype html>
  17. <html lang="fr">
  18. <head>
  19. <meta charset="UTF-8">
  20. <meta name="viewport"
  21. content="width=device-width, initial-scale=1.0">
  22. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  23. <title>RangLimier</title>
  24. <link rel="icon" type="image/png" href="assets/favicon.png">
  25. <link rel="stylesheet" href="assets/fonts/material-icons.min.css">
  26. <link rel="stylesheet" href="assets/bootstrap.min.css">
  27. <link rel="stylesheet" href="assets/divers.css">
  28. <!-- Font Awesome icons (free version)-->
  29. <script src="https://use.fontawesome.com/releases/v5.15.1/js/all.js" crossorigin="anonymous"></script>
  30. <!-- Google fonts-->
  31. <link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css" />
  32. <link href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic" rel="stylesheet" type="text/css" />
  33. </head>
  34. <body>
  35. <div id="navbar">
  36. <nav id="mainNav" class="navbar navbar-expand-lg text-uppercase sticky-top">
  37. <div class="container">
  38. <a href="https://asclepia.io/" class="navbar-brand">
  39. <div class="text-lowercase" style="font-family: no-name;">asclepia</div>
  40. </a>
  41. <button type="button" data-toggle="collapse" data-target="#navbarResponsive"
  42. aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"
  43. class="navbar-toggler navbar-toggler-right text-uppercase font-weight-bold bg-primary text-white rounded collapsed">
  44. Menu
  45. <svg class="svg-inline--fa fa-bars fa-w-14" aria-hidden="true" focusable="false"
  46. data-prefix="fas" data-icon="bars" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"
  47. data-fa-i2svg="">
  48. <path fill="currentColor"
  49. d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"></path>
  50. </svg>
  51. </button>
  52. <div id="navbarResponsive" class="navbar-collapse collapse" style="">
  53. <ul class="navbar-nav ml-auto">
  54. <li class="nav-item mx-0 mx-lg-1">
  55. <a href="https://asclepia.io/utilisateur" class="nav-link py-3 px-0 px-lg-3 rounded js-scroll-trigger">Se connecter</a>
  56. </li>
  57. <li class="nav-item mx-0 mx-lg-1">
  58. <a href="https://asclepia.io/inscription" class="nav-link py-3 px-0 px-lg-3 rounded js-scroll-trigger">Découvrir</a>
  59. </li>
  60. </ul>
  61. </div>
  62. </div>
  63. </nav>
  64. </div>
  65. <div id="rangLimier">
  66. <br>
  67. <h1 style="text-align: center;">Rangs Limites</h1>
  68. <p>Cet outil permet d'apprécier les choix de postes accessibles pour un rang de classement donné sur les années post R3C (à partir des ECNi 2017 jusqu'aux derniers ECNi) <br>
  69. Sur un seul tableau<!--, qui'il est possible de restreindre à certains DES et/ou certaines subdivisions -->, est affiché, dans chaque case, le nombre d'année où le poste aurait été accessible.
  70. </p>
  71. <ul>
  72. <li>En rouge : Jamais accessible à ce classement</li>
  73. <li>En Jaune : Accessible sur au moins un an (mais pas toutes les années)</li>
  74. <li>En vert : Accessible toutes les années jusqu'aux derniers ECNi</li>
  75. </ul>
  76. <p>
  77. ⚠ <i> Ces informations sont données à titre indicatif et ne peuvent constituer une quelconque garantie pour les procédures de choix à venir</i>
  78. <br>
  79. <i>Toutes les données exploitées par cet outil proviennent du site <a href="https://www.cng.sante.fr/">cng.sante.fr</a> et de son application
  80. <a href="https://www.cngsante.fr/chiron/celine/">CELINE</a>. Pour toute information officielle, veuillez vous référer à ces derniers.</i>
  81. </p>
  82. <form action="index.php" method="get" class="d-flex flex-column align-items-left">
  83. <div class="form-group row align-items-center">
  84. <label for="classement" class="col-sm-2">Saisissez un rang de classement : </label>
  85. <div class="col-sm-1">
  86. <input type="text" name="classement" class="form-control rounded-pill" <?= ($isClassementValid === TRUE) ? 'value='.(int) $_GET["classement"] : "" ?>>
  87. </div>
  88. </div>
  89. <div class="d-flex flex-row flex-sm-wrap">
  90. <div class="form-group align-item-center" style="margin-right: 10px;">
  91. <label for="triSpe">Restreindre aux DES suivants : </label> <br>
  92. <select name="s[]" id="triSpe" multiple size="7" class="form-control rounded">
  93. <?php
  94. if ($isTriSpeValid) { $selectedSpeId = array_flip($_GET['s']); }
  95. foreach ($specialitySourceDataset as $speId => $speName) : ?>
  96. <option
  97. <?= (isset($selectedSpeId[$speId])) ? "selected " : "" ?>
  98. value="<?= $speId ?>">
  99. <?= $specialitySourceDatasetAbrev[$speId]." - ".$speName ?>
  100. </option>
  101. <?php endforeach; ?>
  102. </select>
  103. </div>
  104. <div class="form-group align-item-center">
  105. <label for="triVille">Restreindre aux villes suivantes : </label> <br>
  106. <select name="v[]" id="triVille" multiple size="7" class="form-control rounded">
  107. <?php
  108. if ($isTriVilleValid) { $selectedVilleId = array_flip($_GET['v']); }
  109. foreach ($citySourceDataset as $cityId => $cityName) :
  110. if ($cityName !== "XX") : ?>
  111. <option
  112. <?= (isset($selectedVilleId[$cityId])) ? "selected " : "" ?>
  113. value="<?= $cityId ?>">
  114. <?= $cityName ?>
  115. </option>
  116. <?php endif; endforeach; ?>
  117. </select>
  118. </div>
  119. </div>
  120. <i>Utiliser Ctrl/Command + Clic pour (dé)sélectionner plusieurs options sur PC/Mac</i> <br>
  121. <button type="submit" class="btn btn-info rounded-pill col-sm-2" >Envoyer</button>
  122. </form>
  123. <?php if ($isClassementValid) : ?>
  124. <!--
  125. <hr><h1>Tableau de classement</h1>
  126. <h2>Légende</h2>
  127. <table>
  128. <thead>
  129. <th colspan="5" style="text-align: center;">Légende (sur toutes les années)</th>
  130. </thead>
  131. <tbody>
  132. <tr>
  133. <td class="never-available">Jamais proposé</td>
  134. <td class="no-choice">Aucun choix</td>
  135. <td class="half-choices">Plusieurs choix</td>
  136. <td class="all-choices">Tous les choix</td>
  137. </tr>
  138. </tbody>
  139. </table>
  140. <p>
  141. Chaque nombre dans chaque case correspond au nombre d'années où ce choix était dispo au classement rentré <br>
  142. </p> -->
  143. <?php
  144. // $html = "<h2>Résultats</h2>";
  145. $html = "<br><br><br>";
  146. // On va récupérer tous les rangs limited dispo triés par idChoix
  147. //Mysql
  148. $reqRL = $db->query('SELECT idChoix, annee, rangLimite FROM dataset');
  149. //pgsql
  150. // $reqRL = $db->query('SELECT dataset."idChoix", annee, dataset."rangLimite" FROM dataset');
  151. $rangLimites = $reqRL->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC);
  152. $inputClassement = (int) $_GET["classement"];
  153. //////////////////////////////////
  154. // Calcul et affichage des données
  155. //////////////////////////////////
  156. // v2. Conversion du filtre spé/ville de l'utilisateur
  157. // On croise l'array source de données avec les id sélectionnés via le GET (ce qui sécurise les données en plus)
  158. // array_intersect_key(array_source, clés_à_garder)
  159. $cityDataset = ($isTriVilleValid === TRUE) ? array_intersect_key($citySourceDataset, array_flip($_GET["v"])) : $citySourceDataset;
  160. $specialityDatasetAbrev = ($isTriSpeValid === TRUE) ? array_intersect_key($specialitySourceDatasetAbrev, array_flip($_GET["s"])) : $specialitySourceDatasetAbrev;
  161. $specialityDataset = ($isTriSpeValid === TRUE) ? array_intersect_key($specialitySourceDataset, array_flip($_GET['s'])) : $specialitySourceDataset;
  162. // Affichage de la 1ère ligne = Titre des colonnes
  163. $html .= "<table><thead><tr><th></th>";
  164. foreach ($specialityDatasetAbrev as $specialityName) {
  165. $html .= "<th scope='col'>".$specialityName."</th>";
  166. }
  167. $html .= "</tr></thead><tbody>";
  168. // Affichage de la suite du tableau avec le calcul
  169. foreach ($cityDataset as $cityId => $cityName) {
  170. // On gère la séparation des différentes régions entre elles (représentées dans le csv villes par les lignes XX_:XX)
  171. // La notation des lignes de séparation est sous forme XX_x car si on laissait XX, la fonction getCsvToArrayKeyValue
  172. // ne retourne la position que pour la 1ère occurence de XX;XX
  173. // La manière de fix ça de manière la plus opti et sale, c'est de faire un substr et de tester les 2 premiers charactères
  174. // si ils sont égaux à XX, on fait une séparation
  175. // TODO : Faire un parseur csv qui prend en compte chaque ligne du csv dans l'ordre du fichier
  176. if (strpos($cityId, "XX") !== FALSE) {
  177. $html .= "<tr><th></th>";
  178. foreach ($specialityDatasetAbrev as $specialityName) {
  179. $html .= "<th scope='col'>".$specialityName."</th>";
  180. }
  181. $html .= "</th>";
  182. continue;
  183. }
  184. $html .= "<tr><th scope='row'>".$cityName."</th>";
  185. foreach ($specialityDatasetAbrev AS $specialityId => $specialityName) {
  186. $idChoice = "0".$cityId.$specialityId;
  187. if (!isset($rangLimites[$idChoice])) {
  188. $nbAnneePropose = 0;
  189. $nbPossibleAnneePropose = 0;
  190. } else {
  191. $nbAnneePropose = count($rangLimites[$idChoice]);
  192. $nbPossibleAnneePropose = 0;
  193. foreach ($rangLimites[$idChoice] as $rangLimite) {
  194. if ((int) $rangLimite["rangLimite"] >= $inputClassement) {$nbPossibleAnneePropose++;}
  195. }
  196. }
  197. // Affichage de la cellule
  198. $html .= "<td class=\"";
  199. switch (TRUE) {
  200. case ($nbPossibleAnneePropose === 0 && $nbAnneePropose === 0):
  201. $html .= "never-available";
  202. break;
  203. case ($nbPossibleAnneePropose === 0):
  204. $html .= "no-choice";
  205. break;
  206. case ($nbAnneePropose > $nbPossibleAnneePropose && $nbPossibleAnneePropose === 1):
  207. $html .= "last-choice";
  208. break;
  209. case ($nbAnneePropose > $nbPossibleAnneePropose && $nbPossibleAnneePropose !== 1):
  210. $html .= "half-choices";
  211. break;
  212. case ($nbAnneePropose === $nbPossibleAnneePropose):
  213. $html .= "all-choices";
  214. break;
  215. }
  216. $html .= "\">";
  217. if ($nbPossibleAnneePropose > 0) {
  218. $html .= $nbPossibleAnneePropose;
  219. } else if ($nbPossibleAnneePropose === 0 && $nbAnneePropose !== 0) {
  220. $html .= "0";
  221. }
  222. $html .= "</td>";
  223. }
  224. $html .= "</tr>";
  225. }
  226. $html .= "</tbody></table><br>";
  227. echo $html;
  228. ?>
  229. <table>
  230. </table>
  231. <?php endif;?>
  232. </div>
  233. <!-- Bootstrap core JS-->
  234. <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  235. <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"></script>
  236. </body>
  237. </html>