]> git.llucax.com Git - mecon/meconlib.git/blob - lib/MLIB/Tiempo/Banda.php
Se agrega un objeto que permite armar tablas html a partir de templates.
[mecon/meconlib.git] / lib / MLIB / Tiempo / Banda.php
1 <?php /* vim: set binary expandtab tabstop=4 shiftwidth=4 textwidth=80:
2 -------------------------------------------------------------------------------
3                                     mlib
4 -------------------------------------------------------------------------------
5 This file is part of mlib.
6  
7 mlib is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your option)
10 any later version.
11  
12 mlib is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15  
16 You should have received a copy of the GNU General Public License; if not,
17 write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 Boston, MA  02111-1307  USA
19 -------------------------------------------------------------------------------
20 Creado: lun abr 22 16:05:33 ART 2002
21 Autor:  Gonzalo Merayo <gmeray@mecon.gov.ar>
22 -------------------------------------------------------------------------------
23 $Id$
24 -----------------------------------------------------------------------------*/
25
26 require_once 'DB.php'; // FIXME - esto debe volar!!!
27 require_once 'MLIB/Tiempo/Intervalo.php';
28
29 /**
30  * Representa un conjunto de entradas y salidas para formar una banda horaria
31  *
32  * @package HE
33  * @abstract
34  * @version $Rev$
35  * @author  Gonzalo Merayo <gmeray@mecon.gov.ar>
36  */
37 class MLIB_Tiempo_Banda {
38
39     var $intervalos;
40     var $db;
41
42     /**
43      * Constructor.
44      * @param $db Conexión opcional a una base de datos.
45      */
46     function MLIB_Tiempo_Banda($db = null)
47     {
48         $this->db = $db;
49         $this->intervalos = array();
50     }
51
52     /**
53      * Funcion que se encarga de cargar los intervalos de tiempo de un agente.
54      * Devuelve true en caso de detectar una inconsistecia de reloj o false en caso contrario
55      * 
56      * @param $agente Documento del agente
57      * @param $accesos Array o Date Variable que puede ser un array con todos los accesos
58      *        de un agente o un objeto Date que indica la fecha de la banda a procesar
59      * @param $db Conexión opcional a una base de datos.
60      */
61     function cargar($agente, $accesos, $db = null)
62     {
63         if ($db) {
64             $this->db = $db;
65         }
66
67         $funcion = $this->db->getOne(
68                 "SELECT E.funcion
69                 FROM novedades.estado as E, novedades.web003 as S
70                 WHERE
71                 E.nrodoc = $agente AND
72                 S.nrodoc = $agente AND
73                 S.codep  = E.dependencia"
74                 );
75
76         if (is_a($accesos,'date')) {
77             $fecha =& $accesos;
78             $fecha = $fecha->format("%Y%m%d");
79             $query = "SELECT TA.tipo_acceso, A.hora 
80                 FROM bandas.Acceso A, bandas.Agente_Credencial AC, bandas.Tipo_Acceso TA
81                 WHERE AC.credencial = A.credencial
82                 AND A.fecha = '$fecha'
83                 AND AC.agente = $agente
84                 AND TA.puerta = A.puerta
85                 AND AC.desde <= '$fecha'
86                 AND (  AC.hasta >= '$fecha'
87                         OR   AC.hasta IS NULL)
88                 ORDER BY A.hora";
89             $result = $this->db->query($query);
90             if(DB::isError($result))
91                 trigger_error($result->getMessage(), E_USER_ERROR);
92
93             $inconsistencia = false;
94             if($funcion != 'SE')
95             {//Version tough
96                 $int = null;
97                 while( $r = $result->fetchRow() )
98                 {
99                     if($r[0] == 'E')
100                     {
101                         if($int != null)
102                             $inconsistencia = true;
103                         $int = new MLIB_Tiempo_Intervalo(new MLIB_Tiempo_Hora( $r[1] ),
104                                 new MLIB_Tiempo_Hora( $r[1] ));
105                     }
106                     if($r[0] == 'S')
107                     {
108                         if($int != null)
109                         {
110                             $int->setFin( new MLIB_Tiempo_Hora( $r[1] ) );
111                             $this->agregarIntervalo( $int );
112                             $int = null;
113                         }
114                         else
115                             $inconsistencia = true;
116                     }
117                 }
118                 if($int != null)
119                     $inconsistencia = true;
120             }
121             else
122             {
123                 if($result->numRows() > 0)
124                 {//Version Light o Serenos
125                     $int = new MLIB_Tiempo_Intervalo(new MLIB_Tiempo_Hora('00:00'),
126                             new MLIB_Tiempo_Hora('00:00'));
127                     while( $r = $result->fetchRow() )
128                     {
129                         if($r[0] == 'E')
130                         {
131                             // if($int != null)
132                             //$inconsistencia = true;
133                             $int = new MLIB_Tiempo_Intervalo(new MLIB_Tiempo_Hora( $r[1] ),
134                                     new MLIB_Tiempo_Hora( $r[1] ));
135                         }
136                         if($r[0] == 'S')
137                         {
138                             if($int != null)
139                             {
140                                 $int->setFin( new MLIB_Tiempo_Hora( $r[1] ) );
141                                 $this->agregarIntervalo( $int );
142                                 $int = null;
143                             }
144                             //else
145                             //  $inconsistencia = true;
146                         }
147                     }
148                     if($int != null)
149                     {
150                         $int->setFin( new Hora('24:00') );
151                         $this->agregarIntervalo( $int );
152                         $int = null;
153                     }
154                 }
155             }
156         }
157         else
158         {
159             $inconsistencia = false;
160             if($funcion != 'SE')
161             {//Version tough
162                 $int = null;
163                 if(!is_null($accesos))
164                 {
165                     foreach( $accesos as $r )
166                     {
167                         if($r[0] == 'E')
168                         {
169                             if($int != null)
170                                 $inconsistencia = true;
171                             $int = new MLIB_Tiempo_Intervalo(new MLIB_Tiempo_Hora( $r[1] ),
172                                     new MLIB_Tiempo_Hora( $r[1] ));
173                         }
174                         if($r[0] == 'S')
175                         {
176                             if($int != null)
177                             {
178                                 $int->setFin( new MLIB_Tiempo_Hora( $r[1] ) );
179                                 $this->agregarIntervalo( $int );
180                                 $int = null;
181                             }
182                             else
183                                 $inconsistencia = true;
184                         }
185                     }
186                 }
187                 if($int != null)
188                     $inconsistencia = true;
189             }
190             else
191             {
192                 //Version Light o Serenos
193                 $int = new MLIB_Tiempo_Intervalo(new MLIB_Tiempo_Hora('00:00'),
194                         new MLIB_Tiempo_Hora('00:00'));
195
196                 if(!is_null($accesos))
197                 {
198                     foreach( $accesos as $r )
199                     {
200                         if($r[0] == 'E')
201                         {
202                             // if($int != null)
203                             //$inconsistencia = true;
204                             $int = new MLIB_Tiempo_Intervalo(new MLIB_Tiempo_Hora( $r[1] ),
205                                     new MLIB_Tiempo_Hora( $r[1] ));
206                         }
207                         if($r[0] == 'S')
208                         {
209                             if($int != null)
210                             {
211                                 $int->setFin( new MLIB_Tiempo_Hora( $r[1] ) );
212                                 $this->agregarIntervalo( $int );
213                                 $int = null;
214                             }
215                             //else
216                             //  $inconsistencia = true;
217                         }
218                     }
219                 }
220                 if($int != null)
221                 {
222                     $int->setFin( new Hora('24:00') );
223                     $this->agregarIntervalo( $int );
224                     $int = null;
225                 }
226             }
227         } 
228         return $inconsistencia;
229     }
230
231     /**
232      * Completa las salidas del medio del dia.
233      *
234      */
235     function CompletarSalidas()
236     {
237         if(count($this->intervalos) > 0) {
238             $p = reset($this->intervalos);
239             $u = end($this->intervalos);
240             $p->setFin($u->fin);
241             $this->intervalos = array($p);
242         }
243     }
244
245
246     /**
247      * Agrega un intervalo a la banda
248      * Chequeando superposiciones y en orden
249      *
250      * @param Intervalo $intervalo Intervalo a agregar.
251      */
252     function agregarIntervalo($intervalo)
253     {
254         if ($intervalo->invertido()) {
255             $intervalo->_chequear();
256             $this->agregarIntervalo(new MLIB_Tiempo_Intervalo(new MLIB_Tiempo_Hora('00:00'), new MLIB_Tiempo_Hora ('24:00')));
257             $this->sacarIntervalo($intervalo);
258             return true;
259         }
260         $n_intervalos = array();
261         $insertado = false;
262         // recorre el vector de intervalos
263         foreach( $this->intervalos as $i ) {
264             // si se superpone con alguno, fusionar con ese
265             if($i->seSuperpone($intervalo) || $i->esAdyacente($intervalo)) {
266                 $intervalo->fusionar($i);
267             } else {
268                 if($i->inicio->greater($intervalo->inicio) && ! $insertado) {
269                     array_push($n_intervalos, $intervalo);
270                     $insertado = true;
271                 }
272                 array_push($n_intervalos, $i);
273             }
274         }
275         if(! $insertado )
276             array_push($n_intervalos,$intervalo);
277         $this->intervalos = $n_intervalos;
278         return true;
279     }
280
281     /**
282      * Saca.
283      */
284     function sacarBanda($banda)
285     {
286         foreach($banda->intervalos as $i)
287             $this->sacarIntervalo($i);
288     }
289
290     /**
291      * Saca un intervalo de una banda horaria.
292      */
293     function sacarIntervalo($intervalo)
294     {
295         // Si el intervalo está vacío, no hace nada.
296         $dur = $intervalo->getDuracion();
297         if ($dur->isEmpty()) {
298             return true;
299         }
300         $n_intervalos = array();
301         // recorre el vector de intervalos
302         foreach( $this->intervalos as $i ) {
303             if($i->seSuperpone($intervalo)) {
304                 $a = $i->cortar($intervalo);
305                 $d = $a->getDuracion();
306                 if($d->toSeconds() > 0) {
307                     $n_intervalos[] = $a;
308                 }
309                 $d = $i->getDuracion();
310                 if($d->toSeconds() > 0) {
311                     $n_intervalos[] = $i;
312                 }
313             } else {
314                 $n_intervalos[] = $i;
315             }
316         }
317         $this->intervalos = $n_intervalos;
318         return true;
319
320     }
321
322     /**
323      * Saca.
324      */
325     function sacarTiempo($t)
326     {
327         $n_int = array();
328         while(count($this->intervalos) > 0) {
329             $int = array_shift($this->intervalos);
330             if($t->toSeconds() > 0) {
331                 $d = $int->getDuracion();
332                 if($d->greater($t)) {
333 #con cortar alcanza
334                     $ini = new MLIB_Tiempo_Hora();
335                     $ini->copy($int->inicio);
336                     $ini->add($t);
337                     /*TODO guardar este tiempo como rechazado*/
338                     $int->cortar($ini);
339                     $t->setFromSeconds(0);
340                 } else {
341 #con cortar no alcanza y hay que sacar...
342                     $t->subtract($int->getDuracion());
343                     /*TODO guardar int como rechazado*/
344                 }
345             }
346             $n_int[] = $int;
347         }
348         $this->intervalos = $n_int;
349     }
350
351     /**
352      * Chequea si el intervalo pedido esta cubierto por la banda, si faltan
353      *  horas en la banta se retorna el tiempo que falta
354      *
355      * @return Date_Span el periodo faltante
356      */
357     function chequearIntervalo($intervalo)
358     {
359         $t = new MLIB_Tiempo_Hora();
360         foreach ($this->intervalos as $i)
361             $t->add($i->superponer($intervalo));
362         $d = $intervalo->getDuracion();
363         $d->subtract($t);
364         return $d;
365     }
366
367     /**
368      * Chequea si la banda(parametro) esta cubierto por la banda(this),
369      * si faltan horas en la banda(this) para llegar a banda(parametro)
370      * se retorna el tiempo que falta
371      *
372      * @return Date_Span el periodo faltante
373      */
374     function chequearBanda($banda)
375     {
376         $f = new MLIB_Tiempo_Hora();
377         foreach ($banda->intervalos as $i)
378             $f->add($this->chequearIntervalo($i));
379         return $f;
380     }
381
382
383     /**
384      * Devuelve una representacion del objeto como un string.
385      *
386      * @return string Representacion del objeto.
387      */
388     function toString()
389     {
390         $s = '';
391         $t = count($this->intervalos);
392         for ($n = 0; $n < ($t - 1); $n++) {
393             $s .= "intervalo $n: [" . $this->intervalos[$n]->toString() . '] | ';
394         }
395         $n = $t - 1;
396         if ($n != -1) {
397             $s .= "intervalo $n: [" . $this->intervalos[$n]->toString() . ']';
398         }
399         return $s;
400     }
401
402     function getIntervalos()
403     {
404         return $this->intervalos;
405     }
406
407     /**
408      * Corta una banda, devolviendo la banda previa al punto de corte.
409      *
410      * La banda actual queda con los intervalos posteriores al punto de corte
411      * y se devuelve la banda con los intervalos anteriores.
412      * El punto de corte puede ser tanto una hora como un intervalo.
413      *
414      * @param mixed $c Donde cortar.
415      *
416      * @return object Banda Bnada anterior al punto de corte.
417      */
418     function cortar($c)
419     {
420         $b = $this->__clone();
421         $b->intervalos = array();
422         $intervalos = array();
423         foreach ($this->intervalos as $i) {
424             $a = $i->cortar($c);
425             $da = $a->getDuracion();
426             if (!$da->isEmpty()) {
427                 $b->agregarIntervalo($a);
428             }
429             $di = $i->getDuracion();
430             if (!$di->isEmpty()) {
431                 $intervalos[] = $i;
432             }
433         }
434         $this->intervalos = $intervalos;
435         return $b;
436     }
437
438     /**
439      * Devuelve el timpo total que contiene la banda.
440      *
441      * @return object Date_Span Tiempo total.
442      */
443     function total()
444     {
445         $t = new Date_Span;
446         foreach ($this->intervalos as $i) {
447             $t->add($i->getDuracion());
448         }
449         return $t;
450     }
451
452     /**
453      * Alias de Banda::total() para compatibilidad con Intervalo.
454      *
455      * @return object Date_Span Tiempo total.
456      */
457     function getDuracion()
458     {
459         return $this->total();
460     }
461
462     /**
463      * Chequea si el período pasado como argumento se superpone con la banda.
464      * @param $periodo Puede ser un MLIB_Tiempo_Intervalo o MLIB_Tiempo_Banda.
465      * @return true si se superpone, false si no.
466      */
467     function seSuperpone($periodo)
468     {
469         $intervalos = array($periodo);
470         if (is_a($periodo, 'MLIB_tiempo_banda')) {
471             $intervalos = $periodo->intervalos;
472         }
473         foreach ($intervalos as $i) {
474             if ($i->seSuperpone($this->intervalos)) {
475                 return true;
476             }
477         }
478         return false;
479     }
480
481     /**
482      * Resetea la banda.
483      */
484     function flush()
485     {
486         $this->intervalos = array();
487     }
488
489     function copy($b)
490     {
491         $this->flush();
492         foreach ($b->intervalos as $i) {
493             $this->intervalos[] = $i->__clone();
494         }
495     }
496
497     function __clone()
498     {
499         $class = get_class($this);
500         $b = new $class;
501         $b->copy($this);
502         return $b;
503     }
504
505 }
506
507 ?>