--- /dev/null
+<?php
+// vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4:
+// +--------------------------------------------------------------------+
+// | HORAS EXTRA |
+// +--------------------------------------------------------------------+
+// | Sistema de Horas Extra - Ministerio de Economía - Argentina |
+// +--------------------------------------------------------------------+
+// | Creado: lun abr 22 16:05:33 ART 2002 |
+// | Autor: Gonzalo Merayo <gmeray@mecon.gov.ar> |
+// +--------------------------------------------------------------------+
+//
+// $URL$
+// $Rev$
+// $Date$
+// $Author$
+//
+
+require_once 'HE/Intervalo.php';
+
+/**
+ * Representa un conjunto de entradas y salidas para formar una banda horaria
+ *
+ * @package HE
+ * @abstract
+ * @version $Rev$
+ * @author Gonzalo Merayo <gmeray@mecon.gov.ar>
+ */
+class Banda {
+
+ var $intervalos;
+
+ function Banda() {
+ $this->intervalos = array();
+ }
+
+ function Cargar($agente, $fecha)
+ {
+ $dsn = "mysql://intranet:intranet@intranet-db/bandas";
+ $db = DB::connect( $dsn , true);
+ if(DB::isError($db))
+ die($db->getMessage());
+ $fecha = $fecha->format("%Y%m%d");
+ $query = "SELECT A.tipo_acceso, A.hora
+ FROM agentes G, accesos A
+ WHERE G.cred = A.cred
+ AND G.docu = $agente
+ AND A.fecha = $fecha
+ AND A.inconsistencia = 0
+ ORDER BY A.hora";
+ $result = $db->query($query);
+ if(DB::isError($result))
+ die($result->getMessage());
+
+ $sip =& new HE_DB_Persona;
+ $datos = $sip->obtener($agente);
+ $age =& new HE_DB_Agente;
+ $ag = $age->obtener($agente, $datos['codep']);
+ $funcion = @$ag['funcion'];
+
+ if($funcion != 'SE')
+ {//Version tough
+ $int == null;
+ while( $r = $result->fetchRow() )
+ {
+ if($r[0] == 'E') $int = new Intervalo(new Hora( $r[1] ), new Hora( $r[1] ));
+ if($r[0] == 'S' && $int != null)
+ {
+ $int->setFin( new Hora( $r[1] ) );
+ $this->agregarIntervalo( $int );
+ $int = null;
+ }
+ }
+ }
+ else
+ {
+ if($result->numRows() > 0)
+ {//Version Light o Serenos
+ $int = new Intervalo(new Hora('00:00'), new Hora('00:00'));
+ while( $r = $result->fetchRow() )
+ {
+ if($r[0] == 'E') $int = new Intervalo(new Hora( $r[1] ), new Hora( $r[1] ));
+ if($r[0] == 'S' && $int != null)
+ {
+ $int->setFin( new Hora( $r[1] ) );
+ $this->agregarIntervalo( $int );
+ $int = null;
+ }
+ }
+ if($int != null)
+ {
+ $int->setFin( new Hora('24:00') );
+ $this->agregarIntervalo( $int );
+ $int = null;
+ }
+ }
+ }
+ }
+
+ /*
+ *
+ * Completa las salidas del medio del dia.
+ *
+ */
+ function CompletarSalidas()
+ {
+ if(count($this->intervalos) > 0)
+ {
+ $p = reset($this->intervalos);
+ $u = end($this->intervalos);
+ $p->setFin($u->fin);
+ $this->intervalos = array($p);
+ }
+ }
+
+
+ /**
+ * Agrega un intervalo a la banda
+ * Chequeando superposiciones y en orden
+ *
+ * @param Intervalo $intervalo Intervalo a agregar.
+ */
+ function agregarIntervalo($intervalo)
+ {
+ if(! is_a($intervalo, "intervalo")) return false;
+ if ($intervalo->invertido()) {
+ $intervalo->_chequear();
+ $this->agregarIntervalo(new Intervalo(new Hora('00:00'), new Hora ('24:00')));
+ $this->sacarIntervalo($intervalo);
+ return true;
+ }
+ $n_intervalos = array();
+ $insertado = false;
+ // recorre el vector de intervalos
+ foreach( $this->intervalos as $i )
+ {
+ // si se superpone con alguno, fusionar con ese
+ if($i->seSuperpone($intervalo))
+ $intervalo->fusionar($i);
+ else{
+ if($i->inicio->greater($intervalo->inicio) && ! $insertado)
+ {
+ array_push($n_intervalos, $intervalo);
+ $insertado = true;
+ }
+ array_push($n_intervalos, $i);
+ }
+ }
+ if(! $insertado ) array_push($n_intervalos,$intervalo);
+ $this->intervalos = $n_intervalos;
+ return true;
+ }
+
+ /**
+ * Saca
+ *
+ *
+ */
+ function sacarBanda($banda)
+ {
+ foreach($banda->intervalos as $i)
+ $this->sacarIntervalo($i);
+ }
+
+ /**
+ * Saca un intervalo de una banda horaria.
+ *
+ */
+ function sacarIntervalo($intervalo)
+ {
+ if(! is_a($intervalo, "intervalo")) return false;
+ // Si el intervalo está vacío, no hace nada.
+ $dur = $intervalo->getDuracion();
+ if ($dur->isEmpty()) {
+ return true;
+ }
+ $n_intervalos = array();
+ // recorre el vector de intervalos
+ foreach( $this->intervalos as $i )
+ {
+ if($i->seSuperpone($intervalo)) {
+ $a = $i->cortar($intervalo);
+ $d = $a->getDuracion();
+ if($d->toSeconds() > 0) {
+ $n_intervalos[] = $a;
+ }
+ $d = $i->getDuracion();
+ if($d->toSeconds() > 0) {
+ $n_intervalos[] = $i;
+ }
+ } else {
+ $n_intervalos[] = $i;
+ }
+ }
+ $this->intervalos = $n_intervalos;
+ return true;
+
+ }
+
+ function sacarTiempo($t)
+ {
+ if(! is_a($t, "time_span")) return false;
+ $n_int = array();
+ while(count($this->intervalos) > 0)
+ {
+ $int = array_shift($this->intervalos);
+ if($t->toSeconds() > 0){
+ $d = $int->getDuracion();
+ if($d->greater($t))
+ {
+ #con cortar alcanza
+ $ini = new Hora();
+ $ini->copy($int->inicio);
+ $ini->add($t);
+ /*TODO guardar este tiempo como rechazado*/$int->cortar($ini);
+ $t->setFromSeconds(0);
+ }else{
+ #con cortar no alcanza y hay que sacar...
+ $t->subtract($int->getDuracion());
+ /*TODO guardar int como rechazado*/
+ }
+ }
+ $n_int[] = $int;
+ }
+ $this->intervalos = $n_int;
+ }
+
+ /*
+ * Chequea si el intervalo pedido esta cubierto por la banda, si faltan
+ * horas en la banta se retorna el tiempo que falta
+ *
+ * @return Time_Span el periodo faltante
+ *
+ */
+ function chequearIntervalo($intervalo)
+ {
+ if(! is_a($intervalo, "intervalo")) return false;
+ $t = new Hora();
+ foreach ($this->intervalos as $i)
+ $t->add($i->superponer($intervalo));
+ $d = $intervalo->getDuracion();
+ $d->subtract($t);
+ return $d;
+ }
+
+ /*
+ * Chequea si la banda(parametro) esta cubierto por la banda(this),
+ * si faltan horas en la banda(this) para llegar a banda(parametro)
+ * se retorna el tiempo que falta
+ *
+ * @return Time_Span el periodo faltante
+ *
+ */
+ function chequearBanda($banda)
+ {
+ if(! is_a($banda, "banda")) return false;
+ $f = new Hora();
+ foreach ($banda->intervalos as $i)
+ $f->add($this->chequearIntervalo($i));
+ return $f;
+ }
+
+
+ /*
+ * Devuelve una representacion del objeto como un string.
+ *
+ * @return string Representacion del objeto.
+ *
+ */
+ function toString()
+ {
+ $s = '';
+ $t = count($this->intervalos);
+ for ($n = 0; $n < ($t - 1); $n++) {
+ $s .= "intervalo $n: [" . $this->intervalos[$n]->toString() . '] | ';
+ }
+ $n = $t - 1;
+ if ($n != -1) {
+ $s .= "intervalo $n: [" . $this->intervalos[$n]->toString() . ']';
+ }
+ return $s;
+ }
+
+ function getIntervalos() {
+ return $this->intervalos;
+ }
+
+ /**
+ * Corta una banda, devolviendo la banda previa al punto de corte.
+ *
+ * La banda actual queda con los intervalos posteriores al punto de corte
+ * y se devuelve la banda con los intervalos anteriores.
+ * El punto de corte puede ser tanto una hora como un intervalo.
+ *
+ * @param mixed $c Donde cortar.
+ *
+ * @return object Banda Bnada anterior al punto de corte.
+ */
+ function cortar($c)
+ {
+ if(!is_a($c, 'hora') and !is_a($c, 'intervalo')) return false;
+ $b = $this->__clone();
+ $b->intervalos = array();
+ $intervalos = array();
+ foreach ($this->intervalos as $i) {
+ $a = $i->cortar($c);
+ $da = $a->getDuracion();
+ if (!$da->isEmpty()) {
+ $b->agregarIntervalo($a);
+ }
+ $di = $i->getDuracion();
+ if (!$di->isEmpty()) {
+ $intervalos[] = $i;
+ }
+ }
+ $this->intervalos = $intervalos;
+ return $b;
+ }
+
+ /**
+ * Devuelve el timpo total que contiene la banda.
+ *
+ * @return object Time_Span Tiempo total.
+ */
+ function total() {
+ $t = new Time_Span;
+ foreach ($this->intervalos as $i) {
+ $t->add($i->getDuracion());
+ }
+ return $t;
+ }
+
+ /**
+ * Alias de Banda::total() para compatibilidad con Intervalo.
+ *
+ * @return object Time_Span Tiempo total.
+ */
+ function getDuracion() {
+ return $this->total();
+ }
+
+ /**
+ * Resetea la banda.
+ */
+ function flush() {
+ $this->intervalos = array();
+ }
+
+ function copy($b) {
+ $this->flush();
+ foreach ($b->intervalos as $i) {
+ $this->intervalos[] = $i->__clone();
+ }
+ }
+
+ function __clone() {
+ $class = get_class($this);
+ $b = new $class;
+ $b->copy($this);
+ return $b;
+ }
+
+}
+
+// $Id$
+?>
--- /dev/null
+<?php
+// vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4:
+// +--------------------------------------------------------------------+
+// | HORAS EXTRA |
+// +--------------------------------------------------------------------+
+// | Sistema de Horas Extra - Ministerio de Economía - Argentina |
+// +--------------------------------------------------------------------+
+// | Creado: lun abr 22 16:05:33 ART 2002 |
+// | Autor: Gonzalo Merayo <gmeray@mecon.gov.ar> |
+// +--------------------------------------------------------------------+
+//
+// $URL$
+// $Rev$
+// $Date$
+// $Author$
+//
+
+require_once "Time/Span.php";
+
+/**
+ * Representa un Intervalo entre 2 horas del mismo dia
+ *
+ * @package HE
+ * @abstract
+ * @version $Rev$
+ * @author Gonzalo Merayo <gmeray@mecon.gov.ar>
+ */
+class Hora extends Time_Span {
+
+ function set($str)
+ {
+ $str = strval($str);
+ if (preg_match('/^\d+$/', $str)) {
+ if ($str < 24) {
+ $str = sprintf('0:%02d:00:00', $str );
+ } elseif ($str == 24 or $str == 2400) {
+ $str = '1:00:00:00';
+ } elseif ($str < 2400) {
+ switch (strlen($str)) {
+ case 2:
+ $str = sprintf('0:%02d:%02d:00', $str{0}, $str{1});
+ break;
+ case 3:
+ $str = sprintf('0:%02d:%02d:00', $str{0}, $str{1} . $str{2});
+ break;
+ case 4:
+ $str = sprintf('0:%02d:%02d:00', $str{0} . $str{1}, $str{2} . $str{3});
+ break;
+ }
+ } else {
+ return false;
+ }
+ } elseif (preg_match('/^(\d{0,2})\D(\d{1,2})$/', $str, $m)) {
+ if ($m[1] < 24 and $m[2] < 60) {
+ $str = sprintf('0:%02d:%02d:00', $m[1], $m[2]);
+ } elseif ($m[1] == 24 and $m[2] == 0) {
+ $str = '1:00:00:00';
+ } else {
+ return false;
+ }
+ } elseif (preg_match('/^(\d{0,2})\D(\d{1,2})\D(\d{1,2})$/', $str, $m)) {
+ if ($m[1] < 24 and $m[2] < 60 and $m[3] < 60) {
+ $str = sprintf('0:%02d:%02d:%02d', $m[1], $m[2], $m[3]);
+ } elseif ($m[1] == 24 and $m[2] == 0 and $m[3] == 0) {
+ $str = '1:00:00:00';
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ $this->setFromString($str, "%D:%H:%M:%S");
+ return true;
+ }
+
+ function get()
+ {
+ return $this->format("%E:%M");
+ }
+
+}
+// $Id$
+?>
--- /dev/null
+<?php
+// vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4:
+// +--------------------------------------------------------------------+
+// | HORAS EXTRA |
+// +--------------------------------------------------------------------+
+// | Sistema de Horas Extra - Ministerio de Economía - Argentina |
+// +--------------------------------------------------------------------+
+// | Creado: lun abr 22 16:05:33 ART 2002 |
+// | Autor: Gonzalo Merayo <gmeray@mecon.gov.ar> |
+// +--------------------------------------------------------------------+
+//
+// $URL$
+// $Rev$
+// $Date$
+// $Author$
+//
+
+require_once 'HE/Hora.php';
+
+/**
+ * Representa un Intervalo entre 2 horas del mismo dia
+ *
+ * @package HE
+ * @version $Rev$
+ * @author Gonzalo Merayo <gmeray@mecon.gov.ar>
+ */
+class Intervalo {
+ /**
+ *
+ * Hora de inicio del intervalo
+ *
+ * @var object Hora
+ */
+ var $inicio;
+
+ /**
+ *
+ * Hora de fin del intervalo
+ *
+ * @var object Hora
+ */
+ var $fin;
+
+ /**
+ * Constructor.
+ *
+ * @param Hora $inicio Hora de inicio (por defecto cero).
+ * @param Hora $fin Hora de fin (por defecto cero).
+ * @param bool $chequear Invierte el intervalo si la hora de
+ * fin es anterior a la de inicio.
+ *
+ */
+ function Intervalo( $inicio = null, $fin = null, $chequear = true ) {
+ if (is_null($inicio)) $inicio = new Hora;
+ if (is_null($fin)) $fin = new Hora;
+ if(!is_a($inicio, 'hora')) return false;
+ if(!is_a($fin, 'hora')) return false;
+ $this->inicio = $inicio;
+ $this->fin = $fin;
+ if ($chequear) {
+ $this->_chequear();
+ }
+ }
+
+ function _chequear()
+ {
+ $a = $this->fin;
+ if($a->lower($this->inicio))
+ {
+ $tmp = $this->fin;
+ $this->fin = $this->inicio;
+ $this->inicio = $tmp;
+ }
+ }
+
+ function invertido()
+ {
+ return $this->fin->lower($this->inicio);
+ }
+
+ function setInicio( $inicio ) {
+ if(! is_a($inicio, "hora")) return false;
+ $this->inicio = $inicio;
+ $this->_chequear();
+ }
+
+ /**
+ *
+ * setFin
+ *
+ * @param var $fin
+ *
+ */
+ function setFin( $fin )
+ {
+ if(! is_a($fin, "hora")) return false;
+ $this->fin = $fin;
+ $this->_chequear();
+ }
+
+ function getDuracion()
+ {
+ $c = new Hora;
+ $c->copy($this->fin);
+ $c->subtract($this->inicio);
+ return $c;
+ }
+
+ // XXX - Amplié el método para comparar con varios intervalos a la vez,
+ // si el argumento no es un array, anda de todas maneras.
+ function seSuperpone( $intervalos )
+ {
+ if (!is_array($intervalos)) $intervalos = array($intervalos);
+ foreach ($intervalos as $i) {
+ if (is_a($i, "intervalo")) {
+ if ($i->fin->greaterEqual($this->inicio) &&
+ $this->fin->greaterEqual($i->inicio)) return true;
+ if ($this->fin->greaterEqual($i->inicio) &&
+ $i->fin->greaterEqual($this->inicio)) return true;
+ }
+ }
+ return false;
+ }
+
+ function fusionar( $f )
+ {
+ if(! is_a($f, "intervalo")) return false;
+ if(! $this->seSuperpone( $f )) return false;
+ if($f->fin->greater($this->fin))
+ $this->fin = $f->fin;
+ if($f->inicio->lower($this->inicio))
+ $this->inicio = $f->inicio;
+ return true;
+ }
+
+ function superponer( $i )
+ {
+ if(! is_a($i, "intervalo")) return false;
+ $inicio = $this->inicio;
+ $fin = $this->fin;
+ if($this->inicio->lower($i->inicio)) $inicio = $i->inicio;
+ if($this->fin->greater( $i->fin )) $fin = $i->fin;
+ $fin->subtract($inicio);
+ return $fin;
+ }
+
+ /**
+ * Corta un intervalo, devolviendo el intervalo previo al punto de corte.
+ * El intervalo actual queda con el intervalo posterior al punto de corte.
+ * El punto de corte puede ser tanto una hora como un intervalo.
+ *
+ * @param mixed $c Donde cortar.
+ *
+ * @return object Intervalo Intervalo anterior al punto de corte.
+ */
+ function cortar($c)
+ {
+ if(is_a($c, 'hora')) {
+ return $this->cortarHora($c);
+ } elseif (is_a($c, 'intervalo')) {
+ return $this->cortarIntervalo($c);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Corta un intervalo, devolviendo el intervalo previo a la hora de corte.
+ * El intervalo actual queda con el intervalo posterior a la hora de corte.
+ *
+ * @param mixed $h Donde cortar.
+ *
+ * @return object Intervalo Intervalo anterior a la hora de corte.
+ */
+ function cortarHora($h)
+ {
+ if (!is_a($h, 'hora')) return false;
+ $class = get_class($this);
+ $r = new $class;
+ $r->copy($this);
+ if($this->inicio->greater($h)) {
+ $r->setFin($r->inicio);
+ return $r;
+ }
+ if($this->fin->lowerEqual($h)) {
+ $this->setInicio($this->fin);
+ }else{
+ $this->setInicio($h);
+ $r->setFin($h);
+ }
+ return $r;
+ }
+
+ /**
+ * Corta un intervalo, devolviendo el intervalo previo al intervalo de corte.
+ * El intervalo actual queda con el intervalo posterior al intervalo de corte.
+ *
+ * @param mixed $i Donde cortar.
+ *
+ * @return object Intervalo Intervalo anterior al intervalo de corte.
+ */
+ function cortarIntervalo($i)
+ {
+ if (!is_a($i, 'intervalo')) return false;
+ $ant = $this->cortarHora($i->inicio);
+ $this->cortarHora($i->fin);
+ return $ant;
+ }
+
+ function toString() {
+ return 'inicio: ' . $this->inicio->format() . ' | fin: ' . $this->fin->format();
+ }
+
+ function copy($int = null) {
+ if (!(is_a($int, 'intervalo'))) return false;
+ $this->inicio = new Hora($int->inicio->get());
+ $this->fin = new Hora($int->fin->get());
+ return true;
+ }
+
+ function __clone() {
+ $class = get_class($this);
+ $i = new $class;
+ $i->inicio = $this->inicio->__clone();
+ $i->fin = $this->fin->__clone();
+ return $i;
+ }
+
+}
+
+// $Id$
+?>