source: spip-zone/_plugins_/hydraulic/trunk/hyd_inc/formulaire.abstract.class.php @ 104873

Last change on this file since 104873 was 104873, checked in by dorch@…, 4 years ago

Correction d'un bug causé par un mauvais test sur les valeurs zéro pouvant être envoyées par le formulaire.

File size: 18.3 KB
Line 
1<?php
2// Instanciation du journal de calcul
3
4
5/*******************************************************************************
6 * Gestion des formulaires des calculettes pour l'hydraulique
7 *******************************************************************************/
8abstract class formulaire {
9
10        const DBG = false; /// Debuggage de la classe et des classes filles
11        const DBG_CHARGER = false; /// Debuggage de la methode charger
12
13        /***************************************************************************
14         * Structure du formulaire qui contient un tableau avec les regroupements de champs (fieldset).
15         * Dans un fieldset, on a :
16         *  - 0 : identifiant utilisé sur l'élément id (qui sera suivi de "_fs')
17         *  - 1 : tableau contenant la description des champs, pour chaque champ, on a une clé correspondant au code du champ (name) et un tableau avec :
18         *      - 0 : code de langue du libellé du champ
19         *      - 1 : valeur par défaut du champ ou chaîne commençant par "form_" donnant le nom du squelette à charger dans le répertoire "hyd_inc" du plugin
20         *      - 3 : Codes de contrôle qui signifient :
21         *          - o : Champ obligatoire (une valeur différente de "" est exigée)
22         *          - p : Valeur strictement positive exigée
23         *          - n : Valeur nulle acceptée (à associer systématiquement avec p)
24         *          - s : chaîne de caractère acceptée (Une valeur numérique est exigée sinon)
25         *  - 2 : Type de fieldset :
26         *      - fix : Valeur fixe uniquement (pas de boutons radios)
27         *      - var : Valeur fixe ou valeur variable
28         *      - cal : var + valeur à calculer
29         ***************************************************************************/
30        protected $saisies;
31        protected $champs_fvc; ///< Liste des codes de champs du formulaire avec bouton radio
32        protected $champs; ///< Liste des codes de champs du formulaire
33        protected $data; ///< Données du formulaire
34        protected $sVarCal=''; ///< Nom du champ à calculer par défaut
35        public $VarCal; ///< Pointeur vers la variable de section qui sera calculée
36        protected $nb_col; ///< Nombre de colonnes du tableau du formulaire (2,4 ou 5)
37        /** Résultats du calcul - tableau associatif contenant :
38         *  - 'abs' => Vecteur de la donnée qui varie (abscisse)
39         *  - 'res' => Vecteur du résultat du calcul (ordonnée)
40         *  - 'flag' => Vecteur du flags d'écoulement pour les ouvrages (facultatif)
41         *  -  Plus d'autres qui peuvent être définies et utilisées par la méthode 'afficher' des classes filles */
42        protected $result;
43        protected $oLog; ///< Journal de calcul
44        private $bNoCache = true; ///< Utilisation du cache pour ne pas refaire les calculs (true pour débugage)
45
46        /// Nombre de pas de variation par défaut
47        protected $nbPas = 15;
48        protected $bFVC = true; ///< Formulaire FVC (boutons fixe, varie, calcul)
49
50        /***************************************************************************
51         * Calcul des résultats
52         * @return un tableau au format de $this->result
53         ***************************************************************************/
54        abstract protected function calculer();
55
56        /***************************************************************************
57         * Constructeur de la classe : initialisation de la liste des champs du formulaire
58         ***************************************************************************/
59        public function __construct() {
60                $this->champs_fvc = $this->get_champs_fvc();
61                $this->champs = $this->get_champs();
62                if(self::DBG) spip_log($this->saisies,'hydraulic',_LOG_DEBUG);
63                if(self::DBG) spip_log($this->champs_fvc,'hydraulic',_LOG_DEBUG);
64                include_spip('hyd_inc/log.class');
65                $this->oLog = new cLog();
66        }
67
68        /***************************************************************************
69         * Initialisation de la liste des champs des variables du calcul qui peuvent
70         * être fixe, variant ou calculés (fvc)
71         ***************************************************************************/
72        private function get_champs_fvc() {
73                $champs = array();
74                foreach($this->saisies as $fs) {
75                        foreach($fs[1] as $cle=>$val) {
76                                if($fs[2]!='fix') {
77                                        // Le champ peut être "à varier", il nécessite les vérifications des champs de variation
78                                        $champs[] = $cle;
79                                }
80                        }
81                }
82                return $champs;
83        }
84
85        /***************************************************************************
86         * Initialisation de la liste complète des champs du formulaire
87         ***************************************************************************/
88        private function get_champs() {
89                $champs = array();
90                foreach($this->saisies as $fs) {
91                        foreach($fs[1] as $cle=>$val) {
92                                $champs[] = $cle;
93                        }
94                }
95                return $champs;
96        }
97
98
99        /***************************************************************************
100         * Ce tableau contient la liste de tous les champs du formulaire en fonction
101         * des choix faits sur les variables à varier et à calculer
102         ***************************************************************************/
103        private function champs_obligatoires($bCalc = false){
104                $tChOblig = $this->champs;
105                $tChCalc = $this->champs_fvc;
106
107                if($bCalc) {
108                        return $tChCalc;
109                }
110
111                $choix_champs = array();
112                foreach($tChCalc as $valeur){
113                        $choix_champs[$valeur] = _request('choix_champs_'.$valeur);
114                }
115
116                foreach($choix_champs as $cle=>$valeur){
117                        // Si le choix du select est de calculer une valeur...
118                        if($valeur != 'fix'){
119                                foreach($tChOblig as $cle1=>$valeur1){
120                                        if($cle == $valeur1){
121                                                // Permet de tasser le tableau
122                                                $tChOblig = array_values($tChOblig);
123                                        }
124                                }
125                        }
126                        // Si le choix du select est de faire varier une valeur alors on ajoute les 3 champs nécessaires
127                        if($valeur == 'var'){
128                                $tChOblig[] = 'val_min_'.$cle;
129                                $tChOblig[] = 'val_max_'.$cle;
130                                $tChOblig[] = 'pas_var_'.$cle;
131                        }
132                }
133                return $tChOblig;
134        }
135
136
137        /***************************************************************************
138         * Méthode à appeler par la procédure charger du formulaire CVT
139         * @note Etendre la méthode en faisant un $valeurs = parent::charger()
140         * pour ajouter des variables supplémentaires dans l'environnement du
141         * formulaire.
142         * @param bFix true = Formulaire sans choix fvc
143         ***************************************************************************/
144        public function charger() {
145                $valeurs['saisies'] = $this->saisies;
146                $valeurs['nb_col'] = $this->nb_col;
147                $valeurs['sVarCal'] = $this->sVarCal;
148                $valeurs['champs_fvc'] = $this->champs_fvc;
149
150                // Initialisation de la valeur des champs pour le formulaire
151                foreach($this->saisies as $fs) {
152                        foreach($fs[1] as $cle=>$val) {
153                                $request = _request($cle);
154                                if(self::DBG_CHARGER) spip_log("cle=$cle request=$request",'hydraulic',_LOG_DEBUG);
155                                if($request != '') {
156                                        // La valeur du champ est dans l'adresse de la page
157                                        $valeurs[$cle] = $request;
158                                } else {
159                                        // Valeur par défaut
160                                        $valeurs[$cle] = $val[1];
161                                }
162                        }
163                }
164
165                // On parcourt tous le tableau des indices, et on initialise les valeurs des boutons radios, et des champs de variation
166                if($this->bFVC) {
167                        $sVarCal = $this->sVarCal;
168                        foreach($this->champs_fvc as $cle){
169                                $valeurs['choix_champs_'.$cle] = 'fix';
170                                $valeurs['val_min_'.$cle] = $valeurs[$cle]/2;
171                                $valeurs['val_max_'.$cle] = $valeurs[$cle]*2;
172                                $valeurs['pas_var_'.$cle] = 1.5*$valeurs[$cle]/$this->nbPas;
173                                if(_request('choix_champs_'.$cle)=='cal') {
174                                        $sVarCal = $cle;
175                                }
176                        }
177                        $valeurs['choix_champs_'.$sVarCal] = 'cal';
178                }
179
180                return $valeurs;
181        }
182
183
184        /***************************************************************************
185         * Charge les données d'un formulaire avec choix des variables fixées, qui varient et à calculer
186         * @param $bLibelles Remplit la clé tlib avec les libellés traduits des variables
187         * @return un tableau avec les clés suivantes:
188         *      - Couples clés/valeur des champs du formulaire
189         *      - iPrec : nombre de décimales pour la précision des calculs
190         *      - tLib: tableau avec couples clés/valeurs des libellés traduits des champs du formulaire
191         *      - sLang : la langue en cours
192         *      - CacheFileName : Le nom du fichier de cache
193         *      - min, max, pas : resp. le min, le max et le pas de variation de la variable qui varie
194         *      - i : pointeur vers la variable qui varie
195         *      - ValCal : Nom de la variable à calculer
196         *      - ValVar : Nom de la variable qui varie
197         * @author David Dorchies
198         * @date Juillet 2012
199         ***************************************************************************/
200        public function charge_data() {
201                global $spip_lang;
202
203                $tChOblig = $this->champs_obligatoires();
204                $tChCalc = $this->champs_obligatoires(true);
205                if(self::DBG) spip_log($tChCalc,'hydraulic',_LOG_DEBUG);
206                $choix_radio = array();
207                $tLib = array();
208                $data=array();
209                $data['iPrec']=(int)-log10(_request('rPrec'));
210
211                //On récupère les données
212                foreach($tChOblig as $champ) {
213                        if (_request($champ)!==false){
214                                $data[$champ] = _request($champ);
215                        } else {
216                                $data[$champ] = 999.;
217                        }
218                        $data[$champ] = str_replace(',','.',$data[$champ]); // Bug #574
219                }
220                // On ajoute la langue en cours pour différencier le fichier de cache par langue
221                $data['sLang'] = $spip_lang;
222
223                // On récupère les différents choix effectué sur les boutons radios ainsi que les libelles de tous les paramètres
224                foreach($tChCalc as $cle){
225                        $choix_radio[$cle] = _request('choix_champs_'.$cle);
226                }
227
228                $data['min'] = 0;
229                $data['max'] = 0;
230                $data['pas'] = 1;
231                $data['i'] = 999.;
232
233                foreach($choix_radio as $sVar=>$valeur){
234                        // Si il y a une valeur a calculer
235                        if($valeur == 'cal'){
236                                $data['ValCal'] = $sVar; // Stockage du nom de la variable à calculer
237                        }
238                        // Sinon si une valeur varie
239                        else if($valeur == 'var'){
240                                // alors on récupère sa valeur maximum, minimum et son pas de variation
241                                $data['min'] = _request('val_min_'.$sVar);
242                                $data['max'] = _request('val_max_'.$sVar);
243                                $data['pas'] = _request('pas_var_'.$sVar);
244                                // On fait pointer la variable qui varie sur l'indice de parcours du tableau i
245                                $data['ValVar'] = $sVar; // Stockage du nom de la variable qui varie
246                                $data[$sVar] = &$data['i']; // Pointeur pour relier le compteur de boucle à la variable
247                        }
248                }
249                // Pour afficher correctement la valeur maximum avec les pb d'arrondi des réels
250                $data['max'] += $data['pas']/2;
251
252                $this->data = $data;
253                if(self::DBG) spip_log($data,'hydraulic',_LOG_DEBUG);
254        }
255
256
257        /***************************************************************************
258         * Méthode à appeler par la procédure traiter du formulaire CVT
259         * Vérification des données transmises et génération des messages d'erreur pour le formulaire
260         ***************************************************************************/
261        public function verifier() {
262                // Chargement des données du formulaire
263                $this->charge_data();
264                $tCtrl = array();
265                $tData = array();
266
267                foreach($this->saisies as $fs) {
268                        foreach($fs[1] as $cle=>$val) {
269                                $tData[$cle] = (isset($this->data[$cle]))?$this->data[$cle]:999;
270                                $tCtrl[$cle] = $val[2];
271                        }
272                }
273                // Vérifications des données
274                $erreurs = array();
275                foreach($tCtrl as $Cle=>$Ctrl) {
276                        $tData[$Cle] = trim(str_replace(',','.',$tData[$Cle]));
277                        if(strpos($Ctrl,'o')!==false & (!isset($tData[$Cle]) | $tData[$Cle]=="")) {
278                                // Champ obligatoire
279                                $erreurs[$Cle] = _T('hydraulic:erreur_obligatoire');
280                        } elseif(strpos($Ctrl,'s')===false & !preg_match('#^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$#', $tData[$Cle]) & $tData[$Cle]!="") {
281                                // Valeurs numériques obligatoire
282                                $erreurs[$Cle] = _T('hydraulic:erreur_non_numerique');
283            } else {
284                                // Conversion des champs en valeur réelle
285                                $tData[$Cle] =  floatval($tData[$Cle]);
286                                if(strpos($Ctrl,'p')!==false & strpos($Ctrl,'n')!==false & $tData[$Cle] < 0) {
287                                        // Contrôles des valeurs qui doivent être positives ou nulles
288                                        $erreurs[$Cle] = _T('hydraulic:erreur_val_positive_nulle');
289                                } elseif(strpos($Ctrl,'p')!==false & strpos($Ctrl,'n')===false & $tData[$Cle] <= 0) {
290                                        // Contrôles des valeurs qui doivent être strictement positives
291                                        $erreurs[$Cle] = _T('hydraulic:erreur_val_positive');
292                                }
293                        }
294                }
295
296                // On compte s'il y a des erreurs. Si oui, alors on affiche un message
297                if (count($erreurs)) {
298                        $erreurs['message_erreur'] = _T('hydraulic:saisie_erreur');
299                }
300                if(self::DBG) spip_log($erreurs,'hydraulic',_LOG_DEBUG);
301                return $erreurs;
302        }
303
304
305        /***************************************************************************
306         * Méthode à appeler par la procédure traiter du formulaire CVT
307         ***************************************************************************/
308        public function traiter() {
309                spip_log('toto','hydraulic',_LOG_DEBUG);
310                include_spip('hyd_inc/cache');
311                if(self::DBG) spip_log('toto','hydraulic',_LOG_DEBUG);
312                // Calcul des résultats
313                $CacheFileName = md5(serialize($this->data)); // Nom du fichier en cache pour calcul déjà fait
314                if(!$this->bNoCache && is_file(HYD_CACHE_DIRECTORY.$CacheFileName)) {
315                        // On récupère toutes les données dans un cache déjà créé
316                        $this->result = ReadCacheFile($CacheFileName);
317                } else {
318                        // On effectue les calculs
319                        $this->result = $this->calculer();
320                }
321                if(self::DBG) spip_log($this->result,'hydraulic',_LOG_DEBUG);
322
323                // Affichage des résultats
324                return array('message_ok'=>$this->afficher_result());
325        }
326
327
328        /***************************************************************************
329         * Récupération des libellés des champs des variables de calcul (fvc)
330         ***************************************************************************/
331        protected function get_champs_libelles() {
332                $lib = array();
333                foreach($this->saisies as $fs) {
334                        foreach($fs[1] as $cle=>$val) {
335                                if($fs[2]!='fix') {
336                                        $lib[$cle] = _T('hydraulic:'.$val[0]);
337                                }
338                        }
339                }
340                return $lib;
341        }
342
343
344        /***************************************************************************
345         * Affichage des tableaux et graphiques des résultats des calculs
346         * @return Chaîne de caractère avec le code HTML à afficher
347         ***************************************************************************/
348        protected function afficher_result() {
349                // Initialisation des données nécessaires
350                $data = &$this->data; // Données du formulaire
351                $tAbs = &$this->result['abs']; // Valeur de la variable qui varie
352                $tRes = &$this->result['res']; // Résultats du calcul
353                if(isset($this->result['flag'])) {
354                        $tFlag = &$this->result['flag']; // Type d'écoulement pour les vannes
355                } else {
356                        $tFlag = false;
357                }
358                $tLib = $this->get_champs_libelles(); // Libellé traduit des champs fvc
359
360                $echo = $this->oLog->Result(); // Insertion du journal de calcul
361
362                if(!isset($data['ValVar'])) {
363                        $data['ValVar']='';
364                }
365                // Affichage des paramètres fixes
366                $tCnt = array();
367                foreach($data as $k=>$v) {
368                        if(in_array($k,$this->champs_fvc) && !in_array($k,array($data['ValCal'],$data['ValVar']))) {
369                                $tCnt[]=array($tLib[$k],format_nombre($data[$k], $data['iPrec']));
370                        }
371                }
372                // Si il n'y a pas de valeur à varier on ajoute le résultat et le flag de calcul s'il existe
373                if(!$data['ValVar']) {
374                        $tCnt[]=array('<b>'.$tLib[$data['ValCal']].'</b>','<b>'.format_nombre($tRes[0], $data['iPrec']).'</b>');
375                        if($tFlag) {
376                                if(self::DBG) spip_log($tFlag,'hydraulic.'._LOG_DEBUG);
377                                $tCnt[]= array(_T('hydraulic:type_ecoulement'),_T('hydraulic:flag_'.$tFlag[0]));
378                        }
379                }
380                $tableau_fixe = $this->get_result_table($tCnt,array(_T('hydraulic:param_fixes'),_T('hydraulic:valeurs')));
381
382                // Affichage d'un tableau pour un paramètre qui varie
383                if($data['ValVar']) {
384                        $tCnt=array();
385                        foreach($tAbs as $k=>$Abs){
386                                $tCnt[] = array(format_nombre($Abs, $data['iPrec']),format_nombre($tRes[$k], $data['iPrec']));
387                        }
388                        $tEnt = array($tLib[$data['ValVar']],$tLib[$data['ValCal']]);
389                        $tableau_variable = $this->get_result_table($tCnt,$tEnt);
390
391                        // Si la première valeur est infinie alors ...
392                        if(is_infinite($tRes[0])){
393                                // ... on supprime cette valeur
394                                unset($tRes[0]);
395                                // ... on tasse le tableau des résultats
396                                $tRes = array_values($tRes);
397                                // ... on supprime l'abscisse correspond
398                                unset($tAbs[0]);
399                                // ... on tasse le tableau des abscisses
400                                $tAbs = array_values($tAbs);
401                        }
402
403                        // Affichage du graphique
404
405                        $echo .= $this->getGraph($tLib[$data['ValVar']], $tLib[$data['ValCal']], $tAbs, $tRes);
406                }
407                $echo .= '<div class="hyd_table">'.$tableau_fixe.'</div>';
408                if(isset($tableau_variable)) {
409                        $echo .= '<div class="hyd_table">'.$tableau_variable.'</div>';
410                }
411                return $echo;
412        }
413
414
415        /**
416         * Affichage du graphique de la variable calculée
417         * @param $sLibVar Libellé de la variable variée
418         * @param $sLibCal Libellé de la variable calculée
419         * @param $tAbs Vecteur des abscisses
420         * @param $tRes Vecteur des valeurs calculées
421         */
422        protected function getGraph($sLibVar, $LibCal, $tAbs, $tRes) {
423                include_spip('hyd_inc/graph.class');
424                $oGraph = new cGraph('',$sLibVar,'');
425                if(isset($tRes)) {
426                        $oGraph->AddSerie(
427                                $LibCal,
428                                $tAbs,
429                                $tRes,
430                                '#00a3cd',
431                                'lineWidth:3, showMarker:true, markerOptions:{style:\'filledCircle\', size:8}');
432                }
433                // Récupération du graphique
434                return $oGraph->GetGraph('graphique',400,600)."\n";
435        }
436
437
438        /***************************************************************************
439         * Renvoie un tableau formaté à partir d'un array à deux dimensions
440         * @param $tContent Tableau à 2 dimensions contenant les cellules [ligne][colonne]
441         * @param $tEntetes Tableau contenant les entêtes de colonne
442         ***************************************************************************/
443        protected function get_result_table($tContent,$tEntetes=false) {
444                // On génère les entêtes du tableau de résulats
445                $echo='<table class="spip">';
446
447                        if($tEntetes) {
448                                $echo.='<thead>
449                                        <tr class="row_first">';
450                                                foreach($tEntetes as $s){
451                                                        $echo.= '<th scope="col" rowspan="2">'.$s.'</th>';
452                                                }
453                                        $echo.= '</tr>
454                                </thead>';
455                        }
456                        $echo.='<tbody>';
457                                $i=0;
458                                foreach($tContent as $Ligne){
459                                        $i++;
460                                        $echo.= '<tr class="align_right ';
461                                                $echo.=($i%2==0)?'row_even':'row_odd';
462                                                $echo.='">';
463                                                foreach($Ligne as $Cellule){
464                                                        $echo.= '<td>'.$Cellule.'</td>';
465                                                }
466                                        $echo.= '</tr>';
467                                }
468                        $echo.= '</tbody>
469                </table>';
470                return $echo;
471        }
472}
473?>
Note: See TracBrowser for help on using the repository browser.