Mapeate/Public/ecma/Mapeate.Mapas.ecma.js

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();
};