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

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

Correction régression introduite dans la r104873 sur la gestion des champs obligatoires.

File size: 18.6 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(self::DBG) spip_log( $champ.'=>'._request($champ),'hydraulic',_LOG_DEBUG);
214                        if (_request($champ)!==false){
215                                $data[$champ] = _request($champ);
216                        } else {
217                                $data[$champ] = 999.;
218                        }
219                        $data[$champ] = str_replace(',','.',$data[$champ]); // Bug #574
220                }
221                // On ajoute la langue en cours pour différencier le fichier de cache par langue
222                $data['sLang'] = $spip_lang;
223
224                // On récupère les différents choix effectué sur les boutons radios ainsi que les libelles de tous les paramètres
225                foreach($tChCalc as $cle){
226                        $choix_radio[$cle] = _request('choix_champs_'.$cle);
227                }
228                if(self::DBG) spip_log($choix_radio,'hydraulic',_LOG_DEBUG);
229
230                $data['min'] = 0;
231                $data['max'] = 0;
232                $data['pas'] = 1;
233                $data['i'] = 999.;
234
235                foreach($choix_radio as $sVar=>$valeur){
236                        // Si il y a une valeur a calculer
237                        if($valeur == 'cal'){
238                                $data['ValCal'] = $sVar; // Stockage du nom de la variable à calculer
239                        }
240                        // Sinon si une valeur varie
241                        else if($valeur == 'var'){
242                                // alors on récupère sa valeur maximum, minimum et son pas de variation
243                                $data['min'] = _request('val_min_'.$sVar);
244                                $data['max'] = _request('val_max_'.$sVar);
245                                $data['pas'] = _request('pas_var_'.$sVar);
246                                // On fait pointer la variable qui varie sur l'indice de parcours du tableau i
247                                $data['ValVar'] = $sVar; // Stockage du nom de la variable qui varie
248                                $data[$sVar] = &$data['i']; // Pointeur pour relier le compteur de boucle à la variable
249                        }
250                }
251                // Pour afficher correctement la valeur maximum avec les pb d'arrondi des réels
252                $data['max'] += $data['pas']/2;
253
254                $this->data = $data;
255                if(self::DBG) spip_log($data,'hydraulic',_LOG_DEBUG);
256        }
257
258
259        /***************************************************************************
260         * Méthode à appeler par la procédure traiter du formulaire CVT
261         * Vérification des données transmises et génération des messages d'erreur pour le formulaire
262         ***************************************************************************/
263        public function verifier() {
264                // Chargement des données du formulaire
265                $this->charge_data();
266                $tCtrl = array();
267                $tData = array();
268                $sValCal = (isset($this->data['ValCal']))?$this->data['ValCal']:false;
269
270                foreach($this->saisies as $fs) {
271                        foreach($fs[1] as $cle=>$val) {
272                                if($cle != $sValCal) {
273                                        if(isset($this->data[$cle])) {
274                                                $tData[$cle] = $this->data[$cle];
275                                        }
276                                        $tCtrl[$cle] = $val[2];
277                                }
278                        }
279                }
280                // Vérifications des données
281                $erreurs = array();
282                foreach($tCtrl as $Cle=>$Ctrl) {
283                        if(isset($tData[$Cle])) {
284                                $tData[$Cle] = trim(str_replace(',','.',$tData[$Cle]));
285                        }
286                        if(strpos($Ctrl,'o')!==false & (!isset($tData[$Cle]) | $tData[$Cle]=="")) {
287                                // Champ obligatoire
288                                $erreurs[$Cle] = _T('hydraulic:erreur_obligatoire');
289                        } elseif(strpos($Ctrl,'s')===false & !preg_match('#^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$#', $tData[$Cle]) & $tData[$Cle]!="") {
290                                // Valeurs numériques obligatoire
291                                $erreurs[$Cle] = _T('hydraulic:erreur_non_numerique');
292            } else {
293                                // Conversion des champs en valeur réelle
294                                $tData[$Cle] =  floatval($tData[$Cle]);
295                                if(strpos($Ctrl,'p')!==false & strpos($Ctrl,'n')!==false & $tData[$Cle] < 0) {
296                                        // Contrôles des valeurs qui doivent être positives ou nulles
297                                        $erreurs[$Cle] = _T('hydraulic:erreur_val_positive_nulle');
298                                } elseif(strpos($Ctrl,'p')!==false & strpos($Ctrl,'n')===false & $tData[$Cle] <= 0) {
299                                        // Contrôles des valeurs qui doivent être strictement positives
300                                        $erreurs[$Cle] = _T('hydraulic:erreur_val_positive');
301                                }
302                        }
303                }
304
305                // On compte s'il y a des erreurs. Si oui, alors on affiche un message
306                if (count($erreurs)) {
307                        $erreurs['message_erreur'] = _T('hydraulic:saisie_erreur');
308                }
309                if(self::DBG) spip_log($erreurs,'hydraulic',_LOG_DEBUG);
310                return $erreurs;
311        }
312
313
314        /***************************************************************************
315         * Méthode à appeler par la procédure traiter du formulaire CVT
316         ***************************************************************************/
317        public function traiter() {
318                spip_log('toto','hydraulic',_LOG_DEBUG);
319                include_spip('hyd_inc/cache');
320                if(self::DBG) spip_log('toto','hydraulic',_LOG_DEBUG);
321                // Calcul des résultats
322                $CacheFileName = md5(serialize($this->data)); // Nom du fichier en cache pour calcul déjà fait
323                if(!$this->bNoCache && is_file(HYD_CACHE_DIRECTORY.$CacheFileName)) {
324                        // On récupère toutes les données dans un cache déjà créé
325                        $this->result = ReadCacheFile($CacheFileName);
326                } else {
327                        // On effectue les calculs
328                        $this->result = $this->calculer();
329                }
330                if(self::DBG) spip_log($this->result,'hydraulic',_LOG_DEBUG);
331
332                // Affichage des résultats
333                return array('message_ok'=>$this->afficher_result());
334        }
335
336
337        /***************************************************************************
338         * Récupération des libellés des champs des variables de calcul (fvc)
339         ***************************************************************************/
340        protected function get_champs_libelles() {
341                $lib = array();
342                foreach($this->saisies as $fs) {
343                        foreach($fs[1] as $cle=>$val) {
344                                if($fs[2]!='fix') {
345                                        $lib[$cle] = _T('hydraulic:'.$val[0]);
346                                }
347                        }
348                }
349                return $lib;
350        }
351
352
353        /***************************************************************************
354         * Affichage des tableaux et graphiques des résultats des calculs
355         * @return Chaîne de caractère avec le code HTML à afficher
356         ***************************************************************************/
357        protected function afficher_result() {
358                // Initialisation des données nécessaires
359                $data = &$this->data; // Données du formulaire
360                $tAbs = &$this->result['abs']; // Valeur de la variable qui varie
361                $tRes = &$this->result['res']; // Résultats du calcul
362                if(isset($this->result['flag'])) {
363                        $tFlag = &$this->result['flag']; // Type d'écoulement pour les vannes
364                } else {
365                        $tFlag = false;
366                }
367                $tLib = $this->get_champs_libelles(); // Libellé traduit des champs fvc
368
369                $echo = $this->oLog->Result(); // Insertion du journal de calcul
370
371                if(!isset($data['ValVar'])) {
372                        $data['ValVar']='';
373                }
374                // Affichage des paramètres fixes
375                $tCnt = array();
376                foreach($data as $k=>$v) {
377                        if(in_array($k,$this->champs_fvc) && !in_array($k,array($data['ValCal'],$data['ValVar']))) {
378                                $tCnt[]=array($tLib[$k],format_nombre($data[$k], $data['iPrec']));
379                        }
380                }
381                // Si il n'y a pas de valeur à varier on ajoute le résultat et le flag de calcul s'il existe
382                if(!$data['ValVar']) {
383                        $tCnt[]=array('<b>'.$tLib[$data['ValCal']].'</b>','<b>'.format_nombre($tRes[0], $data['iPrec']).'</b>');
384                        if($tFlag) {
385                                if(self::DBG) spip_log($tFlag,'hydraulic.'._LOG_DEBUG);
386                                $tCnt[]= array(_T('hydraulic:type_ecoulement'),_T('hydraulic:flag_'.$tFlag[0]));
387                        }
388                }
389                $tableau_fixe = $this->get_result_table($tCnt,array(_T('hydraulic:param_fixes'),_T('hydraulic:valeurs')));
390
391                // Affichage d'un tableau pour un paramètre qui varie
392                if($data['ValVar']) {
393                        $tCnt=array();
394                        foreach($tAbs as $k=>$Abs){
395                                $tCnt[] = array(format_nombre($Abs, $data['iPrec']),format_nombre($tRes[$k], $data['iPrec']));
396                        }
397                        $tEnt = array($tLib[$data['ValVar']],$tLib[$data['ValCal']]);
398                        $tableau_variable = $this->get_result_table($tCnt,$tEnt);
399
400                        // Si la première valeur est infinie alors ...
401                        if(is_infinite($tRes[0])){
402                                // ... on supprime cette valeur
403                                unset($tRes[0]);
404                                // ... on tasse le tableau des résultats
405                                $tRes = array_values($tRes);
406                                // ... on supprime l'abscisse correspond
407                                unset($tAbs[0]);
408                                // ... on tasse le tableau des abscisses
409                                $tAbs = array_values($tAbs);
410                        }
411
412                        // Affichage du graphique
413
414                        $echo .= $this->getGraph($tLib[$data['ValVar']], $tLib[$data['ValCal']], $tAbs, $tRes);
415                }
416                $echo .= '<div class="hyd_table">'.$tableau_fixe.'</div>';
417                if(isset($tableau_variable)) {
418                        $echo .= '<div class="hyd_table">'.$tableau_variable.'</div>';
419                }
420                return $echo;
421        }
422
423
424        /**
425         * Affichage du graphique de la variable calculée
426         * @param $sLibVar Libellé de la variable variée
427         * @param $sLibCal Libellé de la variable calculée
428         * @param $tAbs Vecteur des abscisses
429         * @param $tRes Vecteur des valeurs calculées
430         */
431        protected function getGraph($sLibVar, $LibCal, $tAbs, $tRes) {
432                include_spip('hyd_inc/graph.class');
433                $oGraph = new cGraph('',$sLibVar,'');
434                if(isset($tRes)) {
435                        $oGraph->AddSerie(
436                                $LibCal,
437                                $tAbs,
438                                $tRes,
439                                '#00a3cd',
440                                'lineWidth:3, showMarker:true, markerOptions:{style:\'filledCircle\', size:8}');
441                }
442                // Récupération du graphique
443                return $oGraph->GetGraph('graphique',400,600)."\n";
444        }
445
446
447        /***************************************************************************
448         * Renvoie un tableau formaté à partir d'un array à deux dimensions
449         * @param $tContent Tableau à 2 dimensions contenant les cellules [ligne][colonne]
450         * @param $tEntetes Tableau contenant les entêtes de colonne
451         ***************************************************************************/
452        protected function get_result_table($tContent,$tEntetes=false) {
453                // On génère les entêtes du tableau de résulats
454                $echo='<table class="spip">';
455
456                        if($tEntetes) {
457                                $echo.='<thead>
458                                        <tr class="row_first">';
459                                                foreach($tEntetes as $s){
460                                                        $echo.= '<th scope="col" rowspan="2">'.$s.'</th>';
461                                                }
462                                        $echo.= '</tr>
463                                </thead>';
464                        }
465                        $echo.='<tbody>';
466                                $i=0;
467                                foreach($tContent as $Ligne){
468                                        $i++;
469                                        $echo.= '<tr class="align_right ';
470                                                $echo.=($i%2==0)?'row_even':'row_odd';
471                                                $echo.='">';
472                                                foreach($Ligne as $Cellule){
473                                                        $echo.= '<td>'.$Cellule.'</td>';
474                                                }
475                                        $echo.= '</tr>';
476                                }
477                        $echo.= '</tbody>
478                </table>';
479                return $echo;
480        }
481}
482?>
Note: See TracBrowser for help on using the repository browser.