Calculettes pour l'hydraulique
formulaire.abstract.class.php
Aller à la documentation de ce fichier.
1 <?php
2 // Instanciation du journal de calcul
3 
4 
5 /*******************************************************************************
6  * Gestion des formulaires des calculettes pour l'hydraulique
7  *******************************************************************************/
8 abstract 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) {
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 ?>
$nb_col
Nombre de colonnes du tableau du formulaire (2,4 ou 5)
champs_obligatoires($bCalc=false)
$bFVC
Formulaire FVC (boutons fixe, varie, calcul)
$nbPas
Nombre de pas de variation par défaut.
$data
Données du formulaire.
$bNoCache
Utilisation du cache pour ne pas refaire les calculs (true pour débugage)
const DBG_CHARGER
Debuggage de la classe et des classes filles.
ReadCacheFile($FileName)
Definition: cache.php:25
getGraph($sLibVar, $LibCal, $tAbs, $tRes)
Affichage du graphique de la variable calculée.
$saisies
Debuggage de la methode charger.
Classe pour l&#39;affichage des graphiques.
Definition: graph.class.php:48
$champs_fvc
Liste des codes de champs du formulaire avec bouton radio.
$champs
Liste des codes de champs du formulaire.
$VarCal
Pointeur vers la variable de section qui sera calculée.
format_nombre($nombre, $dec)
Definition: cache.php:55
$oLog
Journal de calcul.
$result
Résultats du calcul - tableau associatif contenant :
$sVarCal
Nom du champ à calculer par défaut.
get_result_table($tContent, $tEntetes=false)