<?php
class ModeloCompacto {
	
	private $conexion;
	private $elementosOrdenados;
    private $puntosInvesionista;

    private $TIPO_CONSUMIDOR = 1;

    private $TIPO_DISTRIBUIDOR = 2;
	private $maxLevel = 13;
	private $modeloCompensacion = array(
			1 => array('nombre' => 'Primero', 'porcentaje' => 10, 'personas' => 1),
			2 => array('nombre' => 'Segundo', 'porcentaje' => 17, 'personas' => 2),
			3 => array('nombre' => 'Tercero', 'porcentaje' => 17, 'personas' => 3),
			4 => array('nombre' => 'Cuarto', 'porcentaje' => 17, 'personas' => 4),
			5 => array('nombre' => 'Quinto', 'porcentaje' => 1, 'personas' => 5),
			6 => array('nombre' => 'Sexto', 'porcentaje' => 1, 'personas' => 6),
			7 => array('nombre' => 'Septimo', 'porcentaje' => 1, 'personas' => 7),
			8 => array('nombre' => 'Octavo', 'porcentaje' => 1, 'personas' => 8),
			9 => array('nombre' => 'Noveno', 'porcentaje' => 1, 'personas' => 9),
			10 => array('nombre' => 'Décimo', 'porcentaje' => 1, 'personas' => 10),
			11 => array('nombre' => 'Onceavo', 'porcentaje' => 1, 'personas' => 11),
			12 => array('nombre' => 'Doceavo', 'porcentaje' => 1, 'personas' => 12),
			13 => array('nombre' => 'Treceavo', 'porcentaje' => 1, 'personas' => 13),
			14 => array('nombre' => 'Catorceavo', 'porcentaje' => 1, 'personas' => 14),
			15 => array('nombre' => 'Quinceavo', 'porcentaje' => 1, 'personas' => 15),
			16 => array('nombre' => 'Dieciseisavo', 'porcentaje' => 1, 'personas' => 16),
			17 => array('nombre' => 'Diecisieteavo', 'porcentaje' => 1, 'personas' => 17),
			18 => array('nombre' => 'Dieciochoavo', 'porcentaje' => 1, 'personas' => 18),
			19 => array('nombre' => 'Diecinueveavo', 'porcentaje' => 1, 'personas' => 19)
	);
	
	function __construct($conexion){
		$this->conexion = $conexion;
	}
	
	
	public function obtenerRed($id_inversionista, &$childs, $level, $initialDate, $finalDate, $others) {
		
		if($id_inversionista != ""){
		
			$level ++;

			$query = "SELECT  
						idprom, id_inver, CONCAT_WS(' ', nombre, appat, apmat) as nombreInversionitas, referencia, rfc, 
						(select sum(puntos) as sumapuntos FROM transacciones tr JOIN depositos dp ON tr.idtransacciones = dp.transacciones_idtransacciones
						AND tr.tipostr_idtipostr!='11' AND fechat BETWEEN '$initialDate' AND '$finalDate'
						WHERE tr.inversionista_id_inver = id_inver GROUP BY tr.inversionista_id_inver) AS sumapuntos
					FROM inversionista WHERE idprom = $id_inversionista";

			
			if($others != null){
				$query .= " $others";
			}
			
			$others = "";
			
			$result = mysql_query ( $query, $this->conexion );
			
			
			$id_invTemp = "";
			
			while ( $fila = mysql_fetch_array ( $result, MYSQL_NUM ) ) {
				
				$childs [$level] [] = $fila;
				$others .= " OR idprom = $fila[1] ";
				$id_invTemp = $fila[1];
			}
			
			
			$this->obtenerRed ( $id_invTemp, $childs, $level, $initialDate, $finalDate, $others);
		}
	}
	
	
	private function procesarModeloCompacto(&$orderedElementsWithModel, $nivel){
	
		$nivel++;
	
		if(count($orderedElementsWithModel[$nivel]) > 0){
			foreach ($orderedElementsWithModel[$nivel] as $keyElement => $element){
	
				if ($element[5] < 624) {
						
					$this->procesarModeloCompacto($orderedElementsWithModel, $nivel);
						
					$this->procesarSiguienteNivel($orderedElementsWithModel, $nivel, $element);
						
					unset($orderedElementsWithModel[$nivel][$keyElement]);
	
				}
			}
		}else{
			unset($orderedElementsWithModel[$nivel]);
		}
	}
	
	private function procesarSiguienteNivel(&$orderedElementsWithModel, $siguienteNivel, $element){
	
		$siguienteNivel++;
		if(count($orderedElementsWithModel[$siguienteNivel]) > 0)
			foreach ($orderedElementsWithModel[$siguienteNivel] as $keySig => $elementSig){
	
				if($element[1] == $elementSig[0]){
					$orderedElementsWithModel[($siguienteNivel-1)][] = $elementSig;
					unset($orderedElementsWithModel[$siguienteNivel][$keySig]);
					$this->procesarSiguienteNivel($orderedElementsWithModel, $siguienteNivel, $elementSig);
				}
					
					
	
		}
	
	}
	
	
	private function procesarModeloNormal(&$orderedElementsWithModel, $puntosInvesionista){

        $this->puntosInvesionista = $puntosInvesionista;
		
		$this->maxLevel = 0;
	
		foreach ($orderedElementsWithModel as $nivel => $elementsOnLevel){
			
			if(count($elementsOnLevel) > 0){
				
				foreach ($elementsOnLevel as $keyElement => $element){

                    // Si el asociado no tiene puntos, lo quitamos del listado.
					if ($element[5] < 1) {
						unset($orderedElementsWithModel[$nivel][$keyElement]);
					}
					// Compara si los puntos de su asociado es más o igual de 624 en el nivel 1, entoces agrega un nivel por cada calificado.
					if($element[5] >= 624 && $nivel == 1){
						$this->maxLevel++;
					}
				}
			}
		}

        // 31 de mayo 2024: Si el inversionista se califica con 1500, cargarle al menos los primeros 4 niveles.
        if($this->puntosInvesionista >= 1500 && $this->maxLevel < 4){
            $this->maxLevel = 4;
        }
	}

    private function procesarElementosSinPuntos(&$elementosOrdenados, $nivel){
        foreach ($elementosOrdenados[$nivel] as $index => $inversionista){
                // Revisar si el inversionista está calificado
               if($inversionista[5] > 624){
                   $this->normalizarIniversionistaCalificado($elementosOrdenados, $nivel-1, $inversionista);
               }
        }
        $nivel++;
    }
    private function normalizarIniversionistaCalificado(&$elementosOrdenados, $nivel, $inverionista){
        foreach ($elementosOrdenados[$nivel] as $elementsNivel){
            if($elementsNivel[1] == $inverionista[0]){

                if($elementsNivel[5] < 624){
                    $inverionista[0] = $elementsNivel[0];
                    $elementosOrdenados[$nivel][] = $inverionista;

                    foreach ($elementosOrdenados[$nivel+1] as $key => $elementsNivelTmp){
                        if($elementsNivelTmp[1] == $inverionista[1]){
                            unset($elementosOrdenados[$nivel+1][$key]);
                            break;
                        }
                    }

                    $this->normalizarIniversionistaCalificado($elementosOrdenados, $nivel-1, $inverionista);
                }
            }
        }
        return true;
    }
	
	
	public function procesarInversionistaCompacto($id_inversionista, $initialDate, $finalDate){
		
		$this->elementosOrdenados = array();
		$level = 0;
		$this->obtenerRed($id_inversionista, $this->elementosOrdenados, $level, $initialDate, $finalDate, null);

        for($i = 2; $i <= count($this->elementosOrdenados); $i++){
            $this->procesarElementosSinPuntos($this->elementosOrdenados, $i);
        }

		$this->procesarModeloCompacto($this->elementosOrdenados, 0);
		
		foreach ($this->elementosOrdenados as $key => $elemento){
			if(count($elemento) == 0){
				for($x = $key; $x <= count($this->elementosOrdenados); $x++){
					$this->elementosOrdenados[$x] = $this->elementosOrdenados[$x+1];
				}
				unset($this->elementosOrdenados[count($this->elementosOrdenados)]);
			}
		}
		
		//Delete more than 6 levels
		 $noLevels = count($this->elementosOrdenados);
		 if($noLevels > $this->maxLevel){
			 for ($x = ($this->maxLevel + 1); $x <= $noLevels; $x++){
			 	unset($this->elementosOrdenados[$x]);
			 }
		 }
		
		
	}
	
	public function procesarInversionistaNormal($id_inversionista, $initialDate, $finalDate, $puntosInvesionista){
	
		$this->elementosOrdenados = array();
		$level = 0;
		$this->obtenerRed($id_inversionista, $this->elementosOrdenados, $level, $initialDate, $finalDate, null);
		
		$this->procesarModeloNormal($this->elementosOrdenados, $puntosInvesionista);

        // Si no tiene mas de 1500, solo califica 1 nivel
        if($puntosInvesionista < 1500){
            $this->maxLevel = 1;
        }
		
		//Delete more than 6 levels
		$noLevels = count($this->elementosOrdenados);
		if($noLevels > $this->maxLevel){
			for ($x = ($this->maxLevel + 1); $x <= $noLevels; $x++){
				unset($this->elementosOrdenados[$x]);
			}
		}
	}
	
	private function obtenerCalculos(){
		
		$puntosObtenidosNivel = array();
		
		foreach ($this->elementosOrdenados as $key => $row){
		
			if(count($row) > 0)
			foreach ($row as $registro){
				$puntosObtenidosNivel[$key]['puntos'] += $registro[5];
			}
			
			$puntosObtenidosNivel[$key]['personasCalificadas'] = count($row);
		}
		
		return $puntosObtenidosNivel;
		
	}
	
	public function imprimirDatos(){
		
		foreach ($this->elementosOrdenados as $key => $row){
		
				echo "
						
			<h3>Nivel $key - ".count($row)." calificados</h3>
				<div>
				<table>";
				echo
				"
		<thead>
		<tr>
			<th>Idprom</th>
			<th>Id_inver</th>
			<th>Nombre</th>
			<th>Referencia</th>
			<th>RFC</th>
			<th>Puntos</th>
		</tr>
		</thead>";
				foreach ($row as $registro){
					echo
					"
					<tr>
					<td>$registro[0]</td>
					<td>$registro[1]</td>
					<td>$registro[2]</td>
					<td>$registro[3]</td>
					<td>$registro[4]</td>
					<td>$registro[5]</td>
					</tr>";
				}
				echo "
					</table>
				</div>";
		
		}
	}
	
	public function imprimirCalculos(){
		$puntosObtenidosNivel = $this->obtenerCalculos();
		
		echo
		"<table>
		<tr>
			<th>Nivel</th>
			<th>Personas requeridas</th>
			<th>Personas obtenidas</th>
			<th>Porcentaje</th>
			<th>Generados</th>
			<th>A recibir</th>
		</tr>";
		
		$totalGenerado = 0;
		$totalObtenido = 0;
		
		foreach ($puntosObtenidosNivel as $key => $puntos){
			
			$currentModel = $this->modeloCompensacion[$key];
			
			$generados = $puntos['puntos'] * ($currentModel['porcentaje'] / 100);
			$obtenidos = 0;

			if(($this->puntosInvesionista >= 1500 && $key < 5) ||
                $puntosObtenidosNivel[1]['personasCalificadas'] >= $currentModel['personas']){
				$obtenidos = $generados; 
			}
			
			$totalGenerado += $generados;
			$totalObtenido += $obtenidos;
			
			echo
			"
			<tr>
				<td>".$currentModel['nombre']."</td>
				<td>".$currentModel['personas']."</td>
				<td>".$puntos['personasCalificadas']."</td>
				<td>".$currentModel['porcentaje']." %</td>
				<td>".number_format ($generados,2, '.', ',')."</td>
				<td>".number_format ($obtenidos,2, '.', ',')."</td>
			</tr>";
		
		}
		echo "<tr>";
		echo "<td colspan='4'></td>";
		echo "<td>".number_format ($totalGenerado,2, '.', ',')."</td>";
		echo "<td>".number_format ($totalObtenido,2, '.', ',')."</td>";
		echo "</tr>";
        echo "</table>";
		
	}
	
	
	public function resumenCalculos(){
		$puntosObtenidosNivel = $this->obtenerCalculos();
	
	
		$totalGenerado = 0;
		$totalObtenido = 0;
		$totalPersonasCalificadas = 0;
	
		foreach ($puntosObtenidosNivel as $key => $puntos){
				
			$currentModel = $this->modeloCompensacion[$key];
				
			$generados = $puntos['puntos'] * ($currentModel['porcentaje'] / 100);
			$obtenidos = 0;
				
			if(($this->puntosInvesionista >= 1500 && $key < 5) ||
                $puntosObtenidosNivel[1]['personasCalificadas'] >= $currentModel['personas']){
				$obtenidos = $generados;
			}
				
			$totalGenerado += $generados;
			$totalObtenido += $obtenidos;
			$totalPersonasCalificadas += $puntos['personasCalificadas'];
				
		}
		
		return array('totalGenerado' => $totalGenerado, 'totalObtenido' => $totalObtenido, 'totalPersonasCalificadas' => $totalPersonasCalificadas, 'totalCalificadasPrimerNivel' => $this->maxLevel);
	
	}
	
	
	public function obtenerDatosInversionita($id_inversionista){
		
		$query = "SELECT
		idprom, id_inver, CONCAT_WS(' ', nombre, appat, apmat) as nombreInversionitas, referencia, rfc,
		(select sum(puntos) as sumapuntos FROM transacciones tr JOIN depositos dp ON tr.idtransacciones = dp.transacciones_idtransacciones
		AND tr.tipostr_idtipostr!='11' AND fechat BETWEEN '2017-03-01' AND '2017-03-31'
		WHERE tr.inversionista_id_inver = id_inver GROUP BY tr.inversionista_id_inver) AS sumapuntos
		FROM inversionista WHERE id_inver = $id_inversionista";
		
		$result = mysql_query ( $query, $this->conexion );
		
		return mysql_fetch_row($result);
		
	}
	
	public function obtenerMes($mes){
		
		$meses = array();
		
		$meses['01'] = "Enero";
		$meses['02'] = "Febrero";
		$meses['03'] = "Marzo";
		$meses['04'] = "Abril";
		$meses['05'] = "Mayo";
		$meses['06'] = "Junio";
		$meses['07'] = "Julio";
		$meses['08'] = "Agosto";
		$meses['09'] = "Septiembre";
		$meses['10'] = "Octubre";
		$meses['11'] = "Noviembre";
		$meses['12'] = "Diciembre";
		
		return $meses[$mes];
		
	}
}

?>