413 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			413 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
Mapeate.Mapas = function(mapeate, entradas){
 | 
						|
 | 
						|
    const self = this, 
 | 
						|
          tipos = {}, 
 | 
						|
          mapas = {}, 
 | 
						|
          cache = {}, 
 | 
						|
          claves = ["x", "y", "ancho", "alto"], 
 | 
						|
          tamano_cache = {x : 0, y : 0};
 | 
						|
    let iniciado = false, 
 | 
						|
        sobreescribir_por_defecto, 
 | 
						|
        sobreescribir_tipos_por_defecto, 
 | 
						|
        mapas_hilo_de_proceso, 
 | 
						|
        fecha_inicio_juego, 
 | 
						|
        tiempo_partida, tiempo_crudo_partida, 
 | 
						|
        puntos_tiempo_respuesta, puntos_aciertos, puntos_fallos, 
 | 
						|
        aciertos, fallos, puntos_total, finalizada_partida;
 | 
						|
 | 
						|
    let selector = this.selector;
 | 
						|
    let global = this.global;
 | 
						|
    let espana = this.espana;
 | 
						|
 | 
						|
    const constructor = () => {
 | 
						|
 | 
						|
        mapeate.print("info", "mapeate_mapas_construyendose");
 | 
						|
 | 
						|
        selector = self.selector = new Mapeate.Mapas.Selector(mapeate, entradas);
 | 
						|
        global = self.global = new Mapeate.Mapas.Global(mapeate, entradas);
 | 
						|
        espana = self.espana = new Mapeate.Mapas.Espana(mapeate, entradas);
 | 
						|
 | 
						|
        mapeate.print("ok", "mapeate_mapas_construido");
 | 
						|
    
 | 
						|
    };
 | 
						|
 | 
						|
    this.iniciar = callback => {
 | 
						|
 | 
						|
        const terminar = estado => typeof callback == "function" && callback(estado);
 | 
						|
 | 
						|
        mapeate.print("info", "mapeate_mapas_iniciando");
 | 
						|
 | 
						|
        if(iniciado){
 | 
						|
            mapeate.print("warn", "mapeate_mapas_ya_iniciado");
 | 
						|
            terminar(false);
 | 
						|
            return false;
 | 
						|
        };
 | 
						|
        iniciado = true;
 | 
						|
 | 
						|
        sobreescribir_por_defecto = mapeate.configuracion(["mapas_sobreescribir", "sobreescribir"]);
 | 
						|
        sobreescribir_tipos_por_defecto = mapeate.configuracion(["mapas_tipos_sobreescribir", "mapas_sobreescribir", "sobreescribir"]);
 | 
						|
        puntos_tiempo_respuesta = mapeate.configuracion("puntos_tiempo_respuesta");
 | 
						|
        puntos_aciertos = mapeate.configuracion("puntos_aciertos");
 | 
						|
        puntos_fallos = mapeate.configuracion("puntos_fallos");
 | 
						|
 | 
						|
        mapeate.ejecutar_array_asincrono([
 | 
						|
            "archivos_de_mapas_tipos_por_defecto", 
 | 
						|
            "archivos_de_mapas_tipos", 
 | 
						|
            "mapas_tipos_por_defecto", 
 | 
						|
            "mapas_tipos"
 | 
						|
        ], (clave, callback) => self.cargar_tipos(mapeate.configuracion(clave), true, callback), () => {
 | 
						|
            mapeate.ejecutar_array_asincrono([
 | 
						|
                "archivos_de_mapas_por_defecto", 
 | 
						|
                "archivos_de_mapas", 
 | 
						|
                "mapas_por_defecto", 
 | 
						|
                "mapas"
 | 
						|
            ], (clave, callback) => self.cargar(mapeate.configuracion(clave), true, callback), () => {
 | 
						|
                mapeate.ejecutar_array_asincrono([
 | 
						|
                    selector, global, espana
 | 
						|
                ], (elemento, callback) => elemento.iniciar(callback), () => {
 | 
						|
                    mapeate.print("ok", "mapeate_mapas_iniciado");
 | 
						|
                    mapas_hilo_de_proceso = mapeate.anadir_hilo_de_proceso(hilo_de_proceso_metodo);
 | 
						|
                    terminar(true);
 | 
						|
                });
 | 
						|
            });
 | 
						|
        });
 | 
						|
 | 
						|
        return true;
 | 
						|
    };
 | 
						|
 | 
						|
    const hilo_de_proceso_metodo = () => {
 | 
						|
        if(!mapeate.si_mismo)
 | 
						|
            return;
 | 
						|
 | 
						|
        const mapa = mapeate.si_mismo.querySelector(".juego>.mapa"), 
 | 
						|
              svg = mapa.querySelector("svg");
 | 
						|
 | 
						|
        if(svg){
 | 
						|
 | 
						|
            const limites = {}, 
 | 
						|
                  final = {};
 | 
						|
 | 
						|
            [limites.x, limites.y, limites.ancho, limites.alto] = svg.getAttribute("data-caja").split(" ").map(valor => Number(valor));
 | 
						|
            [final.x, final.y, final.ancho, final.alto] = mapeate.porcentuar(
 | 
						|
                limites.ancho, limites.alto, mapa.offsetWidth, mapa.offsetHeight
 | 
						|
            );
 | 
						|
                  
 | 
						|
 | 
						|
            if(tamano_cache.x != final.ancho || tamano_cache.y != final.alto){
 | 
						|
                
 | 
						|
                const proporcion = final.ancho / limites.ancho;
 | 
						|
 | 
						|
                // console.log([proporcion, Object.values(limites).map(valor => valor * proporcion >> 0).join(" ")]);
 | 
						|
                
 | 
						|
                // svg.currentScale = proporcion;
 | 
						|
                svg.setAttribute("viewBox", Object.values(limites).join(" "));
 | 
						|
                svg.setAttribute("width", final.ancho);
 | 
						|
                svg.setAttribute("height", final.alto);
 | 
						|
                // svg.style.width = ancho + "px";
 | 
						|
                // svg.style.height = alto + "px";
 | 
						|
                svg.style.marginLeft = -(final.ancho / 2) + "px";
 | 
						|
                svg.style.marginTop = -(final.alto / 2) + "px";
 | 
						|
                
 | 
						|
                tamano_cache.x = final.ancho;
 | 
						|
                tamano_cache.y = final.alto;
 | 
						|
 | 
						|
            };
 | 
						|
 | 
						|
            if(!finalizada_partida){
 | 
						|
                tiempo_crudo_partida = Date.now() - fecha_inicio_juego;
 | 
						|
                mapeate.si_mismo.querySelector(".juego .temporizador>section").innerText = tiempo_partida = (
 | 
						|
                    ("00" + (tiempo_crudo_partida / 3600000 >> 0)).slice(-2) + ":" + 
 | 
						|
                    ("00" + (tiempo_crudo_partida / 60000 % 60 >> 0)).slice(-2) + ":" + 
 | 
						|
                    ("00" + (tiempo_crudo_partida / 1000 % 60 >> 0)).slice(-2) + "." + 
 | 
						|
                    ("00" + (tiempo_crudo_partida % 1000 >> 0)).slice(-3)
 | 
						|
                );
 | 
						|
            };
 | 
						|
 | 
						|
        };
 | 
						|
        
 | 
						|
    };
 | 
						|
 | 
						|
    const cargar_tipos = (clave, callback) => mapeate.leer_archivo(tipos[clave].url, datos => {
 | 
						|
        if(datos){
 | 
						|
            tipos[clave].datos = datos;
 | 
						|
            tipos[clave].ok = true;
 | 
						|
        };
 | 
						|
        mapeate.ejecutar(callback);
 | 
						|
    });
 | 
						|
 | 
						|
    this.cargar_tipos = (entradas, sobreescribir, callback) => {
 | 
						|
        typeof sobreescribir == "boolean" || (sobreescribir = sobreescribir_tipos_por_defecto);
 | 
						|
        mapeate.cargar_diccionarios(mapeate.coger_array(entradas), (nuevos_tipos, callback) => {
 | 
						|
 | 
						|
            let i = 0;
 | 
						|
            const l = Object.keys(nuevos_tipos).length, 
 | 
						|
                  terminar = () => ++ i == l && mapeate.ejecutar(callback);
 | 
						|
 | 
						|
            for(const clave in nuevos_tipos){
 | 
						|
                if(sobreescribir || !tipos[clave]){
 | 
						|
                    tipos[clave] = {
 | 
						|
                        url : nuevos_tipos[clave].url, 
 | 
						|
                        clase : nuevos_tipos[clave].clase, 
 | 
						|
                        niveles_ocultables : nuevos_tipos[clave].niveles_ocultables, 
 | 
						|
                        datos : null, 
 | 
						|
                        ok : false
 | 
						|
                    };
 | 
						|
                    cargar_tipos(clave, terminar);
 | 
						|
                }else 
 | 
						|
                    terminar();
 | 
						|
            };
 | 
						|
 | 
						|
        }, callback, 0);
 | 
						|
 | 
						|
    };
 | 
						|
 | 
						|
    this.cargar = (entradas, sobreescribir, callback) => {
 | 
						|
        typeof sobreescribir == "boolean" || (sobreescribir = sobreescribir_por_defecto);
 | 
						|
        mapeate.cargar_diccionarios(mapeate.coger_array(entradas), (nuevos_mapas, callback) => {
 | 
						|
            for(const clave in nuevos_mapas)
 | 
						|
                (sobreescribir || !mapas[clave]) && 
 | 
						|
                nuevos_mapas[clave] && 
 | 
						|
                typeof nuevos_mapas[clave] == "object" && 
 | 
						|
                (mapas[clave] = {
 | 
						|
                    ...nuevos_mapas[clave], 
 | 
						|
                    ...(nuevos_mapas[clave].tipo && tipos[nuevos_mapas[clave].tipo] ? tipos[nuevos_mapas[clave].tipo] : {})
 | 
						|
                });
 | 
						|
            mapeate.ejecutar(callback);
 | 
						|
        }, callback, 0);
 | 
						|
    };
 | 
						|
 | 
						|
    this.coger = claves => {
 | 
						|
 | 
						|
        const l = (claves = mapeate.coger_array_de_strings(claves)).length;
 | 
						|
 | 
						|
        for(let i = 0; i < l; i ++)
 | 
						|
            if(mapas[claves[i]] !== undefined)
 | 
						|
                return mapas[claves[i]];
 | 
						|
        return claves[0] || null;
 | 
						|
    };
 | 
						|
 | 
						|
    this.coger_todos = () => ({...mapas});
 | 
						|
 | 
						|
    this.cache = (clave, datos) => datos === undefined ? cache[clave] : (cache[clave] = datos);
 | 
						|
 | 
						|
    this.construir = (clave, niveles) => {
 | 
						|
 | 
						|
        let error = (
 | 
						|
            clave === undefined ? 1 << 0 : 
 | 
						|
            clave === null ? 1 << 1 : 
 | 
						|
            typeof clave != "string" ? 1 << 2 : 
 | 
						|
            !clave ? 1 << 3 : 
 | 
						|
            !(clave = clave.trim()) ? 1 << 4 : 
 | 
						|
            mapas[clave] === undefined ? 1 << 5 : 
 | 
						|
            mapas[clave] === null ? 1 << 6 : 
 | 
						|
        0) << 1;
 | 
						|
 | 
						|
        if(error)
 | 
						|
            return;
 | 
						|
 | 
						|
        const mapa = {
 | 
						|
            nombre : clave, 
 | 
						|
            ...mapas[clave], 
 | 
						|
            datos : cache[mapas[clave].url]
 | 
						|
        };
 | 
						|
        let objetivos = "", seleccion;
 | 
						|
 | 
						|
        (seleccion = [].concat(...mapa.elementos.filter((bloque, i) => niveles.includes(i)))).sort(() => .5 - Math.random()).forEach((elemento, i) => {
 | 
						|
 | 
						|
            const datos_comunes = {
 | 
						|
                elemento : elemento, 
 | 
						|
                formato : mapa.formato, 
 | 
						|
                seleccionado : !i
 | 
						|
            };
 | 
						|
 | 
						|
            objetivos += mapeate.string_variables(mapeate.string_variables(mapeate.vistas.coger("elemento_juego_seleccion", datos_comunes), datos_comunes));
 | 
						|
            
 | 
						|
        });
 | 
						|
 | 
						|
        mapeate.si_mismo.querySelector(".juego .objetivos ul").innerHTML = objetivos;
 | 
						|
        mapeate.si_mismo.querySelector(".juego .puntos section").innerText = 0;
 | 
						|
 | 
						|
        if(!mapa.datos)
 | 
						|
            mapeate.leer_archivo(mapas[clave].url, datos => {
 | 
						|
 | 
						|
                mapas[clave].clase && 
 | 
						|
                self[mapas[clave].clase] && 
 | 
						|
                self[mapas[clave].clase].preparar && 
 | 
						|
                (datos = self[mapas[clave].clase].preparar(datos));
 | 
						|
 | 
						|
                cache[mapas[clave].url] = datos;
 | 
						|
                mapa.datos = datos;
 | 
						|
 | 
						|
                construir(mapa, niveles, seleccion);
 | 
						|
 | 
						|
            });
 | 
						|
        else 
 | 
						|
            construir(mapa, niveles, seleccion);
 | 
						|
 | 
						|
    };
 | 
						|
 | 
						|
    const construir = (datos, niveles, seleccion) => {
 | 
						|
 | 
						|
        const juego = mapeate.si_mismo.querySelector(".juego"), 
 | 
						|
              mapa = juego.querySelector(".mapa section"), 
 | 
						|
              menu = mapeate.si_mismo.querySelector(".juego .objetivos ul");
 | 
						|
 | 
						|
        mapa.innerHTML = (`
 | 
						|
            <div class="` + datos.nombre + `" data-clase="` + datos.clase + `"` + [0, 1, 2, 3].map(i => (
 | 
						|
                ` data-nivel-` + i + `-ocultable="` + datos.niveles_ocultables.includes(i) + `"` + 
 | 
						|
                ` data-nivel-` + i + `="` + niveles.includes(i) + `"`
 | 
						|
            )).join("") + `>` + datos.datos + `</div>
 | 
						|
        `);
 | 
						|
 | 
						|
        mapeate.si_mismo.querySelector(".menu-mapas").setAttribute("data-visible", false);
 | 
						|
        mapeate.si_mismo.querySelector(".juego").setAttribute("data-visible", true);
 | 
						|
 | 
						|
        mapeate.precargar("." + datos.nombre + ">svg", svg => {
 | 
						|
 | 
						|
            const limites = svg.getBBox();
 | 
						|
 | 
						|
            svg.setAttribute("data-ancho", limites.width);
 | 
						|
            svg.setAttribute("data-alto", limites.height);
 | 
						|
            svg.setAttribute("data-caja", datos.posicion.join(" "));
 | 
						|
 | 
						|
            tamano_cache.x = 0;
 | 
						|
            tamano_cache.y = 0;
 | 
						|
 | 
						|
            svg.querySelectorAll("[data-habilitado]").forEach(elemento => {
 | 
						|
 | 
						|
                let clon = elemento;
 | 
						|
                const clave = elemento.getAttribute("data-objetivo");
 | 
						|
 | 
						|
                while(clon && clon.hasAttribute){
 | 
						|
                    if(clon.tagName.toLowerCase() == "svg")
 | 
						|
                        break;
 | 
						|
 | 
						|
                    const objetivo = clon.getAttribute("data-objetivo");
 | 
						|
 | 
						|
                    if(objetivo != clave && seleccion.includes(objetivo)){
 | 
						|
 | 
						|
                        const opcion = menu.querySelector("[data-clave=" + clave + "]");
 | 
						|
 | 
						|
                        opcion && opcion.remove();
 | 
						|
 | 
						|
                        return;
 | 
						|
                    };
 | 
						|
                    clon = clon.parentNode;
 | 
						|
                };
 | 
						|
 | 
						|
                elemento.setAttribute("data-habilitado", seleccion.includes(elemento.getAttribute("data-objetivo")))
 | 
						|
 | 
						|
            });
 | 
						|
            mapeate.si_mismo.querySelectorAll(".juego fieldset:not(.mapa)").forEach(campo => campo.innerHTML += mapeate.vistas.coger("posicionador"));
 | 
						|
 | 
						|
            fecha_inicio_juego = Date.now();
 | 
						|
            aciertos = 0;
 | 
						|
            fallos = 0;
 | 
						|
            puntos_total = 0;
 | 
						|
            finalizada_partida = false;
 | 
						|
 | 
						|
        });
 | 
						|
 | 
						|
    };
 | 
						|
 | 
						|
    this.volver_al_menu = (elemento, evento) => {
 | 
						|
 | 
						|
        mapeate.si_mismo.querySelector(".menu-mapas").setAttribute("data-visible", true);
 | 
						|
        mapeate.si_mismo.querySelector(".juego").setAttribute("data-visible", false);
 | 
						|
 | 
						|
    };
 | 
						|
 | 
						|
    this.mostrar_seleccion = (elemento, evento) => mapeate.si_mismo.querySelector(".juego .elemento section").innerText = (
 | 
						|
        elemento.getAttribute("data-habilitado") == "false" ? "" : 
 | 
						|
        elemento.getAttribute("data-acertado") == "false" ? "??????" : 
 | 
						|
        elemento.getAttribute("data-title")
 | 
						|
    );
 | 
						|
 | 
						|
    this.ocultar_seleccion = (elemento, evento) => mapeate.si_mismo.querySelector(".juego .elemento section").innerText = "";
 | 
						|
 | 
						|
    this.elegir = (elemento, evento) => {
 | 
						|
        if(elemento.getAttribute("data-habilitado") == "false")
 | 
						|
            return;
 | 
						|
 | 
						|
        const clave = elemento.getAttribute("data-objetivo"), 
 | 
						|
              seleccionado = mapeate.si_mismo.querySelector(".juego .objetivos [data-seleccionado=true][data-ok=false]");
 | 
						|
 | 
						|
        if(!seleccionado)
 | 
						|
            mapeate.alerta("mapeate_mapas_seleccionar_objetivo");
 | 
						|
        else if(seleccionado.getAttribute("data-clave") == clave){
 | 
						|
 | 
						|
            const opciones = [...seleccionado.parentNode.querySelectorAll("li")];
 | 
						|
            let siguiente = null, 
 | 
						|
                preparado = false;
 | 
						|
 | 
						|
            [0, 1].some(() => opciones.some(nuevo => {
 | 
						|
                if(preparado){
 | 
						|
                    if(nuevo.getAttribute("data-seleccionado") == "false" && nuevo.getAttribute("data-ok") == "false"){
 | 
						|
                        siguiente = nuevo;
 | 
						|
                        return true;
 | 
						|
                    };
 | 
						|
                }else if(nuevo.getAttribute("data-clave") == clave)
 | 
						|
                    preparado = true;
 | 
						|
            }));
 | 
						|
 | 
						|
            seleccionado.setAttribute("data-seleccionado", false);
 | 
						|
            seleccionado.setAttribute("data-ok", true);
 | 
						|
            elemento.setAttribute("data-acertado", true);
 | 
						|
            mapeate.si_mismo.querySelector(".juego .puntos section").innerText = puntos_total += puntos_aciertos;
 | 
						|
            aciertos ++;
 | 
						|
 | 
						|
            if(siguiente){
 | 
						|
                siguiente.setAttribute("data-seleccionado", true);
 | 
						|
                seleccionado.parentNode.parentNode.scrollTop = siguiente.offsetTop - (siguiente.offsetHeight / 2) - (siguiente.parentNode.parentNode.offsetHeight / 2);
 | 
						|
            }else{
 | 
						|
 | 
						|
                const total = aciertos + fallos, 
 | 
						|
                      porcentage_aciertos = aciertos / total, 
 | 
						|
                      marco_tiempo = tiempo_crudo_partida / aciertos, 
 | 
						|
                      puntos_tiempo = (
 | 
						|
                          marco_tiempo < puntos_tiempo_respuesta[0] ? 1 : 
 | 
						|
                          marco_tiempo > puntos_tiempo_respuesta[1] ? 0 : 
 | 
						|
                          1 * (puntos_tiempo_respuesta[1] - marco_tiempo - puntos_tiempo_respuesta[0]) / (puntos_tiempo_respuesta[1] - puntos_tiempo_respuesta[0])
 | 
						|
                      );
 | 
						|
 | 
						|
                finalizada_partida = true;
 | 
						|
 | 
						|
                mapeate.alerta("mapeate_mapas_ganaste", () => self.volver_al_menu(elemento, evento), {
 | 
						|
                    final : mapeate.vistas.coger("resumen_fin_juego", {
 | 
						|
                        tiempo : tiempo_partida, 
 | 
						|
                        aciertos : aciertos, 
 | 
						|
                        fallos : fallos, 
 | 
						|
                        porcentaje_aciertos : (100 * porcentage_aciertos).toFixed(2), 
 | 
						|
                        porcentaje_fallos : (100 * fallos / total).toFixed(2), 
 | 
						|
                        puntos : puntos_total, 
 | 
						|
                        puntos_tiempo : (aciertos * puntos_tiempo).toFixed(2), 
 | 
						|
                        puntos_totales : (10 * porcentage_aciertos * puntos_tiempo).toFixed(2)
 | 
						|
                    })
 | 
						|
                });
 | 
						|
 | 
						|
            };
 | 
						|
 | 
						|
        }else{
 | 
						|
            mapeate.si_mismo.querySelector(".juego .puntos section").innerText = puntos_total -= puntos_fallos;
 | 
						|
            fallos ++;
 | 
						|
            if(puntos_total < 0){
 | 
						|
                finalizada_partida = true;
 | 
						|
                mapeate.alerta("mapeate_mapas_has_perdido", () => self.volver_al_menu(elemento, evento));
 | 
						|
            }else 
 | 
						|
                mapeate.alerta("mapeate_mapas_mal_elegido");
 | 
						|
        };
 | 
						|
 | 
						|
    };
 | 
						|
 | 
						|
    this.seleccionar_objetivo = (elemento, evento) => {
 | 
						|
        if(elemento.getAttribute("data-seleccionado") == "true" || elemento.getAttribute("data-ok") == "true")
 | 
						|
            return;
 | 
						|
 | 
						|
        mapeate.si_mismo.querySelectorAll(".juego .objetivos li[data-seleccionado=true]").forEach(elemento => elemento.setAttribute("data-seleccionado", false));
 | 
						|
        elemento.setAttribute("data-seleccionado", true);
 | 
						|
 | 
						|
    };
 | 
						|
 
 | 
						|
    constructor();
 | 
						|
 | 
						|
}; |