horraire.inc.php 11.6 KB
Newer Older
Feu's avatar
Feu committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<?php
/* Copyright 2007
 * - Julien Etelain <julien CHEZ pmad POINT net>
 *
 * Ce fichier fait partie du site de l'Association des 0tudiants de
 * l'UTBM, http://ae.utbm.fr.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */
23

Feu's avatar
Feu committed
24 25 26
/**
 * @file
 */
27

Feu's avatar
Feu committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
define("HR_SDIMANCHE",  0x0001);
define("HR_SLUNDI",     0x0002);
define("HR_SMARDI",     0x0004);
define("HR_SMERCREDI",  0x0008);
define("HR_SJEUDI",     0x0010);
define("HR_SVENDREDI",  0x0020);
define("HR_SSAMEDI",    0x0040);

define("HR_TDIMANCHE",  0x0101);
define("HR_TLUNDI",     0x0202);
define("HR_TMARDI",     0x0404);
define("HR_TMERCREDI",  0x0808);
define("HR_TJEUDI",     0x1010);
define("HR_TVENDREDI",  0x2020);
define("HR_TSAMEDI",    0x4040);

define("HR_JOURSFERIES",0x0080);
define("HR_SCOLAIRE",   0x007F);
define("HR_VACANCES",   0x7F00);

$GLOBALS["hr_jours_semaine"] = array(
  HR_SDIMANCHE=>"dimanche",
  HR_SLUNDI=>"lundi",
  HR_SMARDI=>"mardi",
  HR_SMERCREDI=>"mercredi",
  HR_SJEUDI=>"jeudi",
  HR_SVENDREDI=>"vendredi",
  HR_SSAMEDI=>"samedi");

/**
 * Classe offrant des fonctions pour la gestion d'horraires.
59
 *
Feu's avatar
Feu committed
60 61 62 63
 * Elle offre la possibilité de gérer des horraires par jours de la semaine,
 * de prendre en compte les jours fériés et les vacances scolaires.
 * Il n'est pas nécessaire de l'instancier pour les fonctions n'ayant pas besoin
 * d'accéder à la base de données (et donc d'accéder au calendrier officiel)
64 65 66
 *
 * @ingroup pg2
 * @author Julien Etelain
Feu's avatar
Feu committed
67 68 69 70
 */
class horraire
{
  var $db;
71

Feu's avatar
Feu committed
72 73
  function horraire ( &$db )
  {
74
    $this->db = $db;
Feu's avatar
Feu committed
75
  }
76

Feu's avatar
Feu committed
77 78 79 80
  static function distinction_vacances ( $jours )
  {
    return ($jours & HR_SCOLAIRE) != (($jours & HR_VACANCES) >> 8);
  }
81

Feu's avatar
Feu committed
82 83 84 85
  static function _jours_to_text ( $jours )
  {
    $res = "";
    $n = 1;
86

Feu's avatar
Feu committed
87 88
    $prev=null;
    $first=null;
89

Feu's avatar
Feu committed
90 91 92 93 94
    while ( $n < HR_JOURSFERIES )
    {
      if ( $jours & $n )
      {
        if ( is_null($first) )
95 96
          $first=$n;

Feu's avatar
Feu committed
97 98 99 100 101 102 103 104
        $prev=$n;
      }
      else
      {
        if ( !is_null($first) )
        {
          if ( $res )
            $res .= ", ";
105

Feu's avatar
Feu committed
106 107
          if ( $prev == $first )
            $res .= $GLOBALS["hr_jours_semaine"][$prev];
108
          elseif ( $prev  == ($first << 1) )
Feu's avatar
Feu committed
109 110 111 112 113 114 115
            $res .= $GLOBALS["hr_jours_semaine"][$first].", ".$GLOBALS["hr_jours_semaine"][$prev];
          else
            $res .= $GLOBALS["hr_jours_semaine"][$first]." au ".$GLOBALS["hr_jours_semaine"][$prev];
        }
        $prev=null;
        $first=null;
      }
116

Feu's avatar
Feu committed
117 118
      $n = $n << 1;
    }
119

Feu's avatar
Feu committed
120 121 122 123
    if ( !is_null($first) )
    {
      if ( $res )
        $res .= ", ";
124

Feu's avatar
Feu committed
125 126
      if ( $prev == $first )
        $res .= $GLOBALS["hr_jours_semaine"][$prev];
127
      elseif ( $prev  == ($first << 1) )
Feu's avatar
Feu committed
128 129 130 131
        $res .= $GLOBALS["hr_jours_semaine"][$first].", ".$GLOBALS["hr_jours_semaine"][$prev];
      else
        $res .= $GLOBALS["hr_jours_semaine"][$first]." au ".$GLOBALS["hr_jours_semaine"][$prev];
    }
132

Feu's avatar
Feu committed
133 134 135 136 137
    if ( $jours & HR_JOURSFERIES )
    {
      if ( $res )
        $res .= " et ";
      $res .= "jours fériés";
138 139
    }

Feu's avatar
Feu committed
140
    return $res;
141 142
  }

Feu's avatar
Feu committed
143 144 145 146
  static function jours_to_text ( $jours )
  {
    if ( $jours == (HR_VACANCES|HR_SCOLAIRE|HR_JOURSFERIES) )
      return "7j/7";
147

Feu's avatar
Feu committed
148 149 150
    if ( horraire::distinction_vacances($jours) )
    {
      $res = "";
151

Feu's avatar
Feu committed
152 153 154 155 156 157 158
      if ( $jours & HR_JOURSFERIES )
      {
        $res .= "jours fériés";
        $jours &= ~HR_JOURSFERIES;
      }

      $j1 = $jours & HR_SCOLAIRE;
159

Feu's avatar
Feu committed
160 161 162 163 164
      if ( $j1 )
      {
        if ( $res )
          $res .= " et ";
        $res .= horraire::_jours_to_text($j1)." en période scolaire";
165 166
      }

Feu's avatar
Feu committed
167
      $j2 = ($jours & HR_VACANCES) >> 8;
168

Feu's avatar
Feu committed
169 170 171 172 173 174 175 176 177 178
      if ( $j2 )
      {
        if ( $res )
          $res .= " et ";
        $res .= horraire::_jours_to_text($j2)." lors des vacances scolaires";
      }
      return $res;
    }
    return horraire::_jours_to_text($jours & (HR_SCOLAIRE|HR_JOURSFERIES));
  }
179

Feu's avatar
Feu committed
180
  static function heures_to_text ( $heures )
181
  {
Feu's avatar
Feu committed
182
    $res = "";
183

Feu's avatar
Feu committed
184 185 186
    foreach ( $heures as $creneau )
    {
      if ( !empty($res) )
187 188
        $res .= " ";

Feu's avatar
Feu committed
189 190
      $h = floor($creneau[0]/3600);
      $m = ($creneau[0]/60)%60;
191

Feu's avatar
Feu committed
192 193 194 195
      if ( $m )
        $res .= $h."h".$m."-";
      else
        $res .= $h."h"."-";
196

Feu's avatar
Feu committed
197
      $h = floor($creneau[1]/3600);
198 199
      $m = ($creneau[1]/60)%60;

Feu's avatar
Feu committed
200 201 202 203 204 205 206
      if ( $m )
        $res .= $h."h".$m;
      else
        $res .= $h."h";
    }
    return $res;
  }
207

Feu's avatar
Feu committed
208 209 210
  static function horraires_to_text ( $horraires )
  {
    $horraires = horraire::optimiser_par_jours($horraires);
211

Feu's avatar
Feu committed
212
    $res = "";
213

Feu's avatar
Feu committed
214 215 216 217 218 219 220 221 222
    foreach ( $horraires as $jours => $heures )
    {
      if ( !empty($res) )
        $res .= " ";

      $res .= horraire::heures_to_text($heures)." ".horraire::jours_to_text($jours).".";
    }
    return $res;
  }
223

Feu's avatar
Feu committed
224 225 226 227
  static function _eclater ( $horraires )
  {
    $data=array();
    $mask=HR_SCOLAIRE|HR_JOURSFERIES;
228

Feu's avatar
Feu committed
229 230 231
    foreach ( $horraires as $jours => $hor )
    {
      if ( horraire::distinction_vacances($jours) )
232
        $mask=HR_VACANCES|HR_SCOLAIRE|HR_JOURSFERIES;
Feu's avatar
Feu committed
233
    }
234

Feu's avatar
Feu committed
235 236 237 238 239 240 241 242 243 244 245
    foreach ( $horraires as $jours => $heures )
    {
      $jours = $jours & $mask;
      $jour = 1;
      while ( $jour & $mask )
      {
        if ( $jours & $jour )
        {
          $j = $jour;
          if ( !($mask & HR_VACANCES) && $j < HR_JOURSFERIES )
            $j = $j | ($j << 8);
246

Feu's avatar
Feu committed
247 248 249 250 251 252 253 254 255 256
          if ( isset($data[$j]) )
            $data[$j] = array_merge($data[$j],$heures);
          else
            $data[$j] = $heures;
        }
        $jour = ($jour << 1);
      }
    }
    return $data;
  }
257

Feu's avatar
Feu committed
258 259 260
  static function optimiser_par_jours ( $horraires )
  {
    $horraires = horraire::_eclater($horraires);
261
    $data = array();
Feu's avatar
Feu committed
262 263 264
    foreach ( $horraires as $jour => $heures )
    {
      if ( count($data) == 0 )
265
        $data[$jour] = $heures;
Feu's avatar
Feu committed
266 267 268 269 270 271 272 273 274 275 276 277
      else
      {
        $fait=false;
        foreach ( $data as $jours => $heures2 )
        {
          if ( $heures2 == $heures )
          {
            $data[$jours|$jour] = $heures;
            unset($data[$jours]);
            $fait=true;
            break;
          }
278
        }
Feu's avatar
Feu committed
279
        if ( !$fait )
280
          $data[$jour] = $heures;
Feu's avatar
Feu committed
281 282 283 284
      }
    }
    return $data;
  }
285

Feu's avatar
Feu committed
286 287 288 289
  static function texte_to_horraires ( $texte )
  {
    $jours_liste = array("dimanche"=>0x101,"lundi"=>0x202,"mardi"=>0x404,"mercredi"=>0x808,"jeudi"=>0x1010,"vendredi"=>0x2020,"samedi"=>0x4040);
    $jours_etendu_liste = array_merge($jours_liste,array("jours fériés"=>0x80));
290

Feu's avatar
Feu committed
291
    $jours_pattern="dimanche|lundi|mardi|mercredi|jeudi|vendredi|samedi";
292 293
    $jours_etendu_pattern="dimanche|lundi|mardi|mercredi|jeudi|vendredi|samedi|jours fériés";

Feu's avatar
Feu committed
294 295
    $segments = preg_split("/([\\.]{1})/iu", $texte);
    $horraires=array();
296

Feu's avatar
Feu committed
297
    echo "\n\n======== $texte ========\n";
298

Feu's avatar
Feu committed
299 300 301
    foreach ( $segments as $segment )
    {
      $segment = trim($segment);
302

Feu's avatar
Feu committed
303 304 305
      if ( !empty($segment) )
      {
        echo "==== $segment ====\n";
306

Feu's avatar
Feu committed
307
        $tokens = explode(" ", $segment);
308

Feu's avatar
Feu committed
309 310 311
        $heures=array();
        $jours=0;
        $cumul="";
312 313


Feu's avatar
Feu committed
314 315 316
        foreach ( $tokens as $token )
        {
          $token = trim($token);
317

Feu's avatar
Feu committed
318
          $cumul=trim($cumul." ".$token);
319 320
          echo "=> $cumul\n";

Feu's avatar
Feu committed
321 322 323 324
          if ( $token == "24h/24" )
          {
            $heures[] = array(0,24*60*60);
            $cumul="";
325

Feu's avatar
Feu committed
326 327 328 329 330 331
            if ( $jours )
            {
              $horraires[$jours]=$heures;
              $heures=array();
              $jours=0;
            }
332

Feu's avatar
Feu committed
333 334 335 336 337
          }
          elseif ( $token == "7j/7" || $cumul == "7 jours/7" )
          {
            $jours = 0x7FFF;
            $cumul="";
338

Feu's avatar
Feu committed
339 340 341 342 343
            if ( count($heures) )
            {
              $horraires[$jours]=$heures;
              $heures=array();
              $jours=0;
344
            }
Feu's avatar
Feu committed
345 346 347 348 349
          }
          elseif ( preg_match("/semaine/ui",$token) )
          {
            $jours = 0x202|0x404|0x808|0x1010|0x2020;
            $cumul="";
350

Feu's avatar
Feu committed
351 352 353 354 355
            if ( count($heures) )
            {
              $horraires[$jours]=$heures;
              $heures=array();
              $jours=0;
356
            }
Feu's avatar
Feu committed
357 358 359 360 361
          }
          elseif ( preg_match("@([0-9]{1,2})h([0-9]*)(-|\\\\|/)([0-9]{1,2})h([0-9]*)@iu",$token,$match) )
          {
            $heures[] = array((($match[1]*60)+$match[2])*60,(($match[4]*60)+$match[5])*60);
            $cumul="";
362

Feu's avatar
Feu committed
363 364 365
            if ( $jours )
            {
              $horraires[$jours]=$heures;
366
            }
Feu's avatar
Feu committed
367 368 369 370 371
          }
          elseif ( preg_match("@([0-9]{1,2})h([0-9]*) à ([0-9]{1,2})h([0-9]*)@iu",$cumul,$match) )
          {
            $heures[] = array((($match[1]*60)+$match[2])*60,(($match[3]*60)+$match[4])*60);
            $cumul="";
372

Feu's avatar
Feu committed
373 374 375
            if ( $jours )
            {
              $horraires[$jours]=$heures;
376
            }
Feu's avatar
Feu committed
377 378 379 380 381 382 383 384 385 386 387
          }
          elseif ( preg_match("@($jours_pattern) au ($jours_pattern)@iu",$cumul,$match) )
          {
            $match[1]=mb_strtolower($match[1],"UTF-8");
            $match[2]=mb_strtolower($match[2],"UTF-8");
            $cumul="";
            $started=false;
            foreach ( $jours_liste as $jour => $key )
            {
              if ( $jour == $match[1] )
                $started=true;
388

Feu's avatar
Feu committed
389 390
              if ( $started )
                $jours |= $key;
391

Feu's avatar
Feu committed
392
              if ( $jour == $match[2] )
393 394
                $started=false;

Feu's avatar
Feu committed
395 396 397 398 399 400 401
            }
            if ( $started )
            {
              foreach ( $jours_liste as $jour => $key )
              {
                if ( $started )
                  $jours |= $key;
402

Feu's avatar
Feu committed
403
                if ( $jour == $match[2] )
404
                  $started=false;
Feu's avatar
Feu committed
405 406
              }
            }
407

Feu's avatar
Feu committed
408 409 410 411 412
            if ( count($heures) )
            {
              $horraires[$jours]=$heures;
              $heures=array();
              $jours=0;
413
            }
Feu's avatar
Feu committed
414 415 416 417 418 419 420 421 422 423 424 425
          }
          elseif ( preg_match("@($jours_etendu_pattern) et ($jours_etendu_pattern)@iu",$cumul,$match) )
          {
            $match[1]=mb_strtolower($match[1],"UTF-8");
            $match[2]=mb_strtolower($match[2],"UTF-8");
            $cumul="";
            $jours|=$jours_etendu_liste[$match[1]]|$jours_etendu_liste[$match[2]];
            if ( count($heures) )
            {
              $horraires[$jours]=$heures;
              $heures=array();
              $jours=0;
426
            }
Feu's avatar
Feu committed
427 428 429 430 431 432 433 434 435 436
          }
          elseif ( preg_match("@sauf (le|les) ($jours_etendu_pattern)(s?)@iu",$cumul,$match) )
          {
            $match[1]=mb_strtolower($match[1],"UTF-8");
            $jours&=~$jours_etendu_liste[$match[1]];
          }
          elseif ( preg_match("@($jours_etendu_pattern)@iu",$cumul,$match) )
          {
            $match[1]=mb_strtolower($match[1],"UTF-8");
            $jours|=$jours_etendu_liste[$match[1]];
437 438 439
          }
        }

Feu's avatar
Feu committed
440 441 442 443
        if ( $jours || count($heures) )
          $horraires[$jours]=$heures;
      }
    }
444

Feu's avatar
Feu committed
445 446 447
    echo "Resultat => ".horraire::horraires_to_text($horraires)."\n\n\n";
    return $horraires;
  }
448

Feu's avatar
Feu committed
449 450 451 452 453 454 455 456 457 458
}
/*
$testsuite=array("24h/24","24h/24 et 7j/7","7 jours/7 de 11h à 00h","7h/19h la semaine, 8h30/13h le dimanche et jours fériés","7j/7","7j/7 et 24h/24","9h-12h 14h-18h du lundi au vendredi",
"9h-15h lundi et mardi. Du mercredi au vendredi de 17h30 à 21h30. Samedi : 9h-15h. Journée complète le dimanche.");

foreach ( $testsuite as $test )
{
  horraire::texte_to_horraires($test);
}
*/
459
?>