<commit_before>package logica;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Random;

import db.Bloque;
import db.Facultad;
import db.Sala;
import db.Seccion;
import db.TiempoInicio;
import gui.VentanaPrincipal;
public class Clase {

    //Por ejemplo la asignatura X tiene 5 horas.
    //Queremos las clases de 2 horas o a lo ms una de 3 por seccion. (caso horas totales impares)
    //se crea una clase para la de dos y otra para la de 3, cada una se busca su horario.

    private static Integer contador = 0;
    private static LinkedList<Bloque> bloques = new LinkedList<>();
    private Integer id;
    private Integer horasContinuadas;
    private ArrayList<Bloque> bloquesAsignados;
    private Seccion seccion;
    private String tipo;
    private Planificador planificador;

    public Clase(Planificador planificador, Integer horasContinuadas, Seccion seccion, String tipo) {
	this.id = Clase.contador++;
	this.horasContinuadas = horasContinuadas;
	this.seccion = seccion;
	this.tipo = tipo;
	this.planificador = planificador;
	this.bloquesAsignados = new ArrayList<Bloque>();
    }

    private ArrayList<Sala> filtrarSalaPorTipoFacultadYCapacidad(ArrayList<Sala> salas, VentanaPrincipal ventana){
	//(Considerar agregar) 6. Se prefiere a una sala para una clase de hora impar estar despues de otra clase de hora impar que este despues de una hora par. 

	ArrayList<Sala> r = new ArrayList<>();
	if(this.getTipo().equals("Normal")){
	    for(Sala sala: salas){
		//2. Se prefiere la sala con capacidad con diferencia a cupo igual o mayor a cero y mientras menor mejor. (Listo)
		if(sala.getIdTipoSala().equals(1) && sala.getCapacidadSala().compareTo(this.getSeccion().getCupo()) >= 0){  
		    r.add(sala);
		}
	    }
	}

	//4. Para una carrera se prefiere clases en edificios de su facultad. (Listo)
	ArrayList<Sala> igualFacultad = new ArrayList<>(); //edificios con facultad determinada
	ArrayList<Sala> sinFacultad = new ArrayList<>(); //edificios sin facultad determinada
	ArrayList<Sala> otraFacultad = new ArrayList<>(); //las dems salas de otras facultades que cumplen con las caracteristicas para la clase
	Facultad f = ventana.getFacultad( ventana.getCarrera( ventana.getAsignatura(this.getSeccion().getIdAsignatura()  ).getIdCarrera() ).getIdFacultad());
	for(Sala sala : r){
	    if( ventana.getEdificio(sala.getIdEdificio()).getIdFacultad().equals(f.getIdFacultad())){
		igualFacultad.add(sala);
	    }else if(sala.getIdEdificio() == null){
		sinFacultad.add(sala);
	    }else{
		otraFacultad.add(sala);
	    }
	}
	r = new ArrayList<>();
	r.addAll(igualFacultad);
	r.addAll(sinFacultad);
	r.addAll(otraFacultad);
	return r;
    }
       
    
    public void obtenerBloques(VentanaPrincipal ventana, ArrayList<Integer> dias){ //para ser llamada desde el planificador
	// dias en orden aleatorio, cuantos dias?? En ventana debe de ponerse o en planificar
	Collections.shuffle(dias, new Random());
	this.ordenarDiasSegunClase(dias);
	//if(this.getTipo().equals("Normal")){ //eligiendo salas normales (no olvidar incluir ayudantias despues...)

	for(Sala sala: this.filtrarSalaPorTipoFacultadYCapacidad(ventana.getSalas(), ventana)){ 
	    for(Integer dia: dias){
		ArrayList<Bloque> bloquesDeUnaSalaYDia = this.bloquesDeUnaSalaYDia(sala, dia, ventana); 
		for(Bloque bloque: bloquesDeUnaSalaYDia){
		    this.getBloquesAsignados().add(bloque);
		    //System.out.println("horas continuadas"+this.getHorasContinuadas());
		    for(int i = 1; i < this.getHorasContinuadas(); i++){
			//System.out.println("contador "+i);
			String tiempoAnterior = this.getBloquesAsignados().get(this.getBloquesAsignados().size()-1).getInicio();
			int posTiempoAnterior = -1;
			for(TiempoInicio t: ventana.getTiempoInicios()){
			    if(tiempoAnterior.equals(t.getInicio())){
				posTiempoAnterior = ventana.getTiempoInicios().indexOf(t);
				break;
			    }
			}
			Bloque bloqueSiguiente = null;
			//System.out.println("posTiempoAnterior" + posTiempoAnterior+ " tamao lista tiempos "+ ventana.getTiempoInicios().size() );
			if(posTiempoAnterior < ventana.getTiempoInicios().size()-1){
			    for(Bloque b: bloquesDeUnaSalaYDia){
				if(b.getInicio().equals(ventana.getTiempoInicios().get(posTiempoAnterior+1).getInicio())){
				    bloqueSiguiente = b;
				    //System.out.println("b: "+b);
				    this.getBloquesAsignados().add(b);
				    break;
				}
				//System.out.println("Bloques asignados cumpliendo: " + this.getBloquesAsignados().size());
			    }
			    if(bloqueSiguiente == null){

				this.getBloquesAsignados().clear();
				break;

			    }

			}else {
			    this.getBloquesAsignados().clear();
			    // System.out.println("borrar!! no hay tiempo siguientes suficiente");
			    break;
			}
		    }
		    //System.out.println("Bloques asignados restricciones: " + this.getBloquesAsignados().size());
		    if(!noChoque(ventana) && !profesorNoParalelo(ventana)){
			this.getBloquesAsignados().clear();
			//System.out.println("borrar!! no cumple restriccioes");
			break;
		    }
		    // System.out.println("Bloques asignadosf: " + this.getBloquesAsignados().size());
		    if(this.getBloquesAsignados().size() == this.getHorasContinuadas()){
			break;
		    }
		}
		if(this.getBloquesAsignados().size() == this.getHorasContinuadas()){
		    break;
		}
	    }
	    if(this.getBloquesAsignados().size() == this.getHorasContinuadas()){
		break;
	    }

	    if(this.getBloquesAsignados().size() == this.getHorasContinuadas()){
		break;
	    }
	}
	if(this.getBloquesAsignados().size() != this.getHorasContinuadas()){
	    //5. si no existen salas que cumplan con las restricciones duras, se debe buscar la alternativa de "intercambio" con alguna ya asignada. 
	    //El ms dificil pendiente... xD
	    //En una funcion -> (obtener del planificador, todas las clases del mismo tipo, que tengan la misma cantidad de bloques y que se pueda insertar en otro lado
	    

	    // -> Aqu codgo 
	    
	    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	}
	Clase.getBloques().removeAll(this.getBloquesAsignados());
	System.out.println("Asignado clase; sobran: " + Clase.getBloques().size() + " Bloques");
	System.out.println("Bloques clase "+ventana.getAsignatura(this.getSeccion().getIdAsignatura()).getNombreAsignatura()+" : "+this.getBloquesAsignados().toString());

	//}

    }
    
    public Boolean getAlternativas(){
	Boolean r = false;
	for(Clase c: this.getPlanificador().getListaDeClases()){
	    if(c.getTipo().equals(this.getTipo()) && c.getHorasContinuadas().equals(this.horasContinuadas)){
		
	    }
	}
	return r;
    }


    
    private ArrayList<Bloque> bloquesDeUnaSalaYDia(Sala sala, int dia, VentanaPrincipal ventana){
	
	ArrayList<Bloque> lista = new ArrayList<Bloque>();
	for(Bloque bloque: Clase.bloques){
	    if(bloque.getIdDia().equals(dia) && bloque.getIdSala().equals(sala.getIdSala()) && Clase.getBloques().contains(bloque)){
		    lista.add(bloque);
	    }
	}
	
	return lista;
    }


    private Boolean noChoque(VentanaPrincipal ventana){
	/*No puede estar la asignatura de una carrera de un mismo semestre y
	 ao junto con otra en el mismo dia en la misma hora, 
	 exepto si existe alguna N-esima (n>=2) seccion de la misma asigantura que no choque. <-listo
	 */

	String carrera = ventana.getAsignatura(this.getSeccion().getIdAsignatura()).getIdCarrera();<commit_msg>Borrando<commit_after>package logica;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Random;

import db.Bloque;
import db.Facultad;
import db.Sala;
import db.Seccion;
import db.TiempoInicio;
import gui.VentanaPrincipal;
public class Clase {

    //Por ejemplo la asignatura X tiene 5 horas.
    //Queremos las clases de 2 horas o a lo ms una de 3 por seccion. (caso horas totales impares)
    //se crea una clase para la de dos y otra para la de 3, cada una se busca su horario.

    private static Integer contador = 0;
    private static LinkedList<Bloque> bloques = new LinkedList<>();
    private Integer id;
    private Integer horasContinuadas;
    private ArrayList<Bloque> bloquesAsignados;
    private Seccion seccion;
    private String tipo;
    private Planificador planificador;

    public Clase(Planificador planificador, Integer horasContinuadas, Seccion seccion, String tipo) {
	this.id = Clase.contador++;
	this.horasContinuadas = horasContinuadas;
	this.seccion = seccion;
	this.tipo = tipo;
	this.planificador = planificador;
	this.bloquesAsignados = new ArrayList<Bloque>();
    }

    private ArrayList<Sala> filtrarSalaPorTipoFacultadYCapacidad(ArrayList<Sala> salas, VentanaPrincipal ventana){
	//(Considerar agregar) 6. Se prefiere a una sala para una clase de hora impar estar despues de otra clase de hora impar que este despues de una hora par. 

	ArrayList<Sala> r = new ArrayList<>();
	if(this.getTipo().equals("Normal")){
	    for(Sala sala: salas){
		//2. Se prefiere la sala con capacidad con diferencia a cupo igual o mayor a cero y mientras menor mejor. (Listo)
		if(sala.getIdTipoSala().equals(1) && sala.getCapacidadSala().compareTo(this.getSeccion().getCupo()) >= 0){  
		    r.add(sala);
		}
	    }
	}

	//4. Para una carrera se prefiere clases en edificios de su facultad. (Listo)
	ArrayList<Sala> igualFacultad = new ArrayList<>(); //edificios con facultad determinada
	ArrayList<Sala> sinFacultad = new ArrayList<>(); //edificios sin facultad determinada
	ArrayList<Sala> otraFacultad = new ArrayList<>(); //las dems salas de otras facultades que cumplen con las caracteristicas para la clase
	Facultad f = ventana.getFacultad( ventana.getCarrera( ventana.getAsignatura(this.getSeccion().getIdAsignatura()  ).getIdCarrera() ).getIdFacultad());
	for(Sala sala : r){
	    if( ventana.getEdificio(sala.getIdEdificio()).getIdFacultad().equals(f.getIdFacultad())){
		igualFacultad.add(sala);
	    }else if(sala.getIdEdificio() == null){
		sinFacultad.add(sala);
	    }else{
		otraFacultad.add(sala);
	    }
	}
	r = new ArrayList<>();
	r.addAll(igualFacultad);
	r.addAll(sinFacultad);
	r.addAll(otraFacultad);
	return r;
    }
       
    
    public void obtenerBloques(VentanaPrincipal ventana, ArrayList<Integer> dias){ //para ser llamada desde el planificador
	// dias en orden aleatorio, cuantos dias?? En ventana debe de ponerse o en planificar
	Collections.shuffle(dias, new Random());
	this.ordenarDiasSegunClase(dias);
	for(Sala sala: this.filtrarSalaPorTipoFacultadYCapacidad(ventana.getSalas(), ventana)){ 
	    for(Integer dia: dias){
		ArrayList<Bloque> bloquesDeUnaSalaYDia = this.bloquesDeUnaSalaYDia(sala, dia, ventana); 
		for(Bloque bloque: bloquesDeUnaSalaYDia){
		    this.getBloquesAsignados().add(bloque);
		    //System.out.println("horas continuadas"+this.getHorasContinuadas());
		    for(int i = 1; i < this.getHorasContinuadas(); i++){
			//System.out.println("contador "+i);
			String tiempoAnterior = this.getBloquesAsignados().get(this.getBloquesAsignados().size()-1).getInicio();
			int posTiempoAnterior = -1;
			for(TiempoInicio t: ventana.getTiempoInicios()){
			    if(tiempoAnterior.equals(t.getInicio())){
				posTiempoAnterior = ventana.getTiempoInicios().indexOf(t);
				break;
			    }
			}
			Bloque bloqueSiguiente = null;
			//System.out.println("posTiempoAnterior" + posTiempoAnterior+ " tamao lista tiempos "+ ventana.getTiempoInicios().size() );
			if(posTiempoAnterior < ventana.getTiempoInicios().size()-1){
			    for(Bloque b: bloquesDeUnaSalaYDia){
				if(b.getInicio().equals(ventana.getTiempoInicios().get(posTiempoAnterior+1).getInicio())){
				    bloqueSiguiente = b;
				    //System.out.println("b: "+b);
				    this.getBloquesAsignados().add(b);
				    break;
				}
				//System.out.println("Bloques asignados cumpliendo: " + this.getBloquesAsignados().size());
			    }
			    if(bloqueSiguiente == null){

				this.getBloquesAsignados().clear();
				break;

			    }

			}else {
			    this.getBloquesAsignados().clear();
			    // System.out.println("borrar!! no hay tiempo siguientes suficiente");
			    break;
			}
		    }
		    //System.out.println("Bloques asignados restricciones: " + this.getBloquesAsignados().size());
		    if(!noChoque(ventana) && !profesorNoParalelo(ventana)){
			this.getBloquesAsignados().clear();
			//System.out.println("borrar!! no cumple restriccioes");
			break;
		    }
		    // System.out.println("Bloques asignadosf: " + this.getBloquesAsignados().size());
		    if(this.getBloquesAsignados().size() == this.getHorasContinuadas()){
			break;
		    }
		}
		if(this.getBloquesAsignados().size() == this.getHorasContinuadas()){
		    break;
		}
	    }
	    if(this.getBloquesAsignados().size() == this.getHorasContinuadas()){
		break;
	    }

	    if(this.getBloquesAsignados().size() == this.getHorasContinuadas()){
		break;
	    }
	}
	
	Clase.getBloques().removeAll(this.getBloquesAsignados());
	System.out.println("Asignado clase; sobran: " + Clase.getBloques().size() + " Bloques");
	System.out.println("Bloques clase "+ventana.getAsignatura(this.getSeccion().getIdAsignatura()).getNombreAsignatura()+" : "+this.getBloquesAsignados().toString());


    }
    
    
    private ArrayList<Bloque> bloquesDeUnaSalaYDia(Sala sala, int dia, VentanaPrincipal ventana){
	
	ArrayList<Bloque> lista = new ArrayList<Bloque>();
	for(Bloque bloque: Clase.bloques){
	    if(bloque.getIdDia().equals(dia) && bloque.getIdSala().equals(sala.getIdSala()) && Clase.getBloques().contains(bloque)){
		    lista.add(bloque);
	    }
	}
	
	return lista;
    }


    private Boolean noChoque(VentanaPrincipal ventana){
	/*No puede estar la asignatura de una carrera de un mismo semestre y
	 ao junto con otra en el mismo dia en la misma hora, 
	 exepto si existe alguna N-esima (n>=2) seccion de la misma asigantura que no choque. <-listo
	 */

	String carrera = ventana.getAsignatura(this.getSeccion().getIdAsignatura()).getIdCarrera();
{'fraction_non_alphanumeric': 0.13694313135653918, 'fraction_numerical': 0.002363558229480017, 'mean_word_length': 4.055394641564084, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5804770', 'n_tokens_mistral': 5282, 'n_tokens_neox': 4902, 'n_words': 1033}