text:
function oComprobacion(idPanel, nomObjeto)
{
	/**
    * Cadena con el nombre del objeto
    * @access	private
    * @var string nomObjeto
    */
	this.nomObjeto = nomObjeto;

	/**
    * Cadena con el texto del Mensaje de error
    * @access	private
    * @var string camposErroneos
    */
    this.camposErroneos = "";

    /**
    * Identificador del Panel donde se encuentra el objeto
    * Esta cadena esta relacionada con el nombre de otros
    * objetos de ese panel, así como con el formulario
    * @access	private
    * @var string idPanel
    */
	this.idPanel = idPanel;
	this.formulario = "F_"+idPanel;

	/**
	* Vector de campos
    * Esta cadena esta relacionada con el nombre de otros
    * objetos de ese panel, así como con el formulario
    * @access	private
    * @var string idPanel
    */
	this.vCamposComprobar = new Array();

	/**
	* Instancia del objeto Paginador referenciará al
	* paginador de ese panel simpre que no sea fil
	* @access	private
	* @var oPaginacion objPaginador
    */
	this.objPaginador = null;
	/*
	if ( (this.idPanel!=null) && ((this.idPanel!='fil')) )
	{
		this.objPaginador = eval(this.idPanel+'_paginacion');
	}
	*/

	this.error = false;

	//Métodos de la Clase
	//Declaracion de las cabeceras
	this.esVacio = f_oComprobacion_esVacio;
	this.soloUnCheck = f_oComprobacion_soloUnCheck;
	this.establecerBooleano = f_oComprobacion_establecerBooleano;
	this.actualizarElemento = f_oComprobacion_actualizarElemento;
	this.comprobarMaximo = f_oComprobacion_comprobarMaximo;
	this.comprobarMinimo = f_oComprobacion_comprobarMinimo;
	this.informaAvisoJS = f_oComprobacion_informaAvisoJS;
	this.getCamposErroneos =f_oComprobacion_getCamposErroneos;
	this.getPagActiva =f_oComprobacion_getPagActiva;
	this.addCampo = f_oComprobacion_addCampo;
	this.getAccion = f_oComprobacion_getAccion;
	this.obtenerEtiquetaCampo = f_oComprobacion_obtenerEtiquetaCampo;
	this.comprobarObligatorios = f_oComprobacion_comprobarObligatorios;
	this.comprobarModificacion = f_oComprobacion_comprobarModificacion;
	this.marcarModificacionCampo = f_oComprobacion_marcarModificacionCampo;
	this.bloquearSalida = f_oComprobacion_bloquearSalida;
	this.formateaNumero = f_oComprobacion_formateaNumero;
	this.formatoFecha = f_oComprobacion_formatoFecha;
	this.mostrarDiaSemanaJS = f_oComprobacion_mostrarDiaSemanaJS;
	this.calcularSemanaJS = f_oComprobacion_calcularSemanaJS;
	this.calcularDiaAnyoJS = f_oComprobacion_calcularDiaAnyoJS;
	this.mostrarInfoFechaJS = f_oComprobacion_mostrarInfoFechaJS;
}

/* Elimina caracteres blancos por delante y por detrás de la cadena */
function trimRight( str )
{
	var resultStr = "";
	var i = 0;

	if (str+"" == "undefined" || str == null)
	return null;

	str += "";
	if (str.length == 0)
		resultStr = "";
	else {
		i = str.length - 1;
		while ((i >= 0) && (str.charAt(i) == " "))
		i--;
		resultStr = str.substring(0, i + 1);
	}

	return resultStr;
}

function trimLeft( str ) {
	var resultStr = "";
	var i = len = 0;

	if (str+"" == "undefined" || str == null)
		return null;
	str += "";
	if (str.length == 0)
		resultStr = "";
	else {
		len = str.length;
		while ((i <= len) && (str.charAt(i) == " "))
			i++;
		resultStr = str.substring(i, len);
	}
	return resultStr;
}

function trim( str ) {
	var resultStr = "";

	resultStr = trimLeft(str);
	resultStr = trimRight(resultStr);

	return resultStr;
}

String.prototype.trim = function()
{
return this.replace(/^\s*(\b.*\b|)\s*$/, "$1");
}

/**
* Comprueba si el elemento HTML es vacío
* @access	private
* @var tipoCampo text|textarea|select-one
* @var campo id o name del campo
*/
function f_oComprobacion_esVacio(tipoCampo, campo)
{
	switch(tipoCampo)
 	{
 		case 'text':
 		case 'textarea':
 			if (trim(campo.value) == '') return true;
 			break;
 		case 'select-one':
 		case 'select-multiple':
 			if (campo.options.selectedIndex == -1)
 				return true;
			if (trim(campo.options[campo.options.selectedIndex].value) == '') return true;
 		break;
 	}
 	return false;
}

// Comprobar que solamente se ha seleccionado un checkbox
function f_oComprobacion_soloUnCheck()
{
	formulario = eval('document.getElementById("'+this.formulario+'")');
	contador = 0;
	checkSeleccionado = '';
	for(i=0;i<formulario.length;i++)
	{
		if ((formulario.elements[i].type == "checkbox") & (formulario.elements[i].checked))
		{
			contador++;
			if (contador >1)
			{
				checkSeleccionado = '';
				break;
			}
			checkSeleccionado = formulario.elements[i].id;
		}
	}
	return checkSeleccionado;
}

//funcion que copia el valor correspondiente al estado del check box
function f_oComprobacion_establecerBooleano(campoCheck,nomCampoOculto,valorSi, valorNo)
{
	nomForm = "F_"+this.idPanel;
	formulario = eval('document.forms["'+nomForm+'"]');
	if (campoCheck.checked == true) {
		eval('formulario.'+nomCampoOculto+'.value=valorSi');
	}
	else{
		eval('formulario.'+nomCampoOculto+'.value=valorNo');
	}
}

//function f_oComprobacion_actualizarElemento(tipoDestino, objElemento, destino)
function f_oComprobacion_actualizarElemento(objElemento, destino)
{
	if (this.error) return;
	formulario = eval('document.getElementById("'+this.formulario+'")');
	objElemento = eval(objElemento);
	tipo = objElemento.type;
	origen = objElemento.id;
	switch (tipo) {
		case 'select-multiple':
			valor = objElemento.options[objElemento.selectedIndex].value;
			origen = objElemento.name;
		break;
		case 'select-one':
			valor = objElemento.options[objElemento.selectedIndex].value;
		break;
		case 'text':
		case 'textarea':
		case 'hidden':
			valor = objElemento.value;
		break;
		case 'radio':
			valor = objElemento.value;
			origen = objElemento.name;
		break;
		default:
			valor = objElemento.value;
		break;
	}
	claseManejadora = formulario.claseManejadora.value;
	accionAntigua = formulario.action;
	formulario.action = 'phrame.php?action=gvHrefreshUI&gvHclass='+claseManejadora+'&gvHfname='+this.formulario+'&gvHfrom='+origen+'&gvHvalue='+valor+'&gvHtarget='+destino;
	formulario.target = 'oculto';
	formulario.submit();
	formulario.action = accionAntigua;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
*Comprueba que la longitud del campo es inferior a la longitud máxima
Devuelve true/false
*/
function f_oComprobacion_comprobarMaximo(tipoCampo, campo, maxLongitud)
 {
 	switch(tipoCampo)
 	 {
 		case 'textarea':
 			if (campo.value.length > maxLongitud) campo.value = campo.value.slice(0, maxLongitud);
 		break;
 		case 'text':
			return(campo.value.length>maxLongitud);
 		break;
 	};
 }

/*
Comprueba que la longitud del campo es superior a la longitud mínima
Devuelve true/false
*/
function f_oComprobacion_comprobarMinimo(tipoCampo, campo, minLongitud)
{
	return (campo.value.length < minLongitud);
}

function f_oComprobacion_informaAvisoJS(mensaje, objetoGenerador)
{
	var descBreve='';
	var textoAviso='';
	var codAviso='IGEP-';
	var tipoAviso='';
	switch (mensaje)
	{
		case 'LONGITUDMAXIMA':
			codAviso = 'IGEP-902';
			tipoAviso='ALERTA';
			descBreve='Se sobrepasa la longitud
 máxima permitida.';
			textoAviso='No puede usted introducir más de '+arguments[2]+' caracteres.';
			this.error=this.comprobarMaximo (objetoGenerador.type, objetoGenerador, arguments[2]);
		break;
		case 'LONGITUDMINIMA':
			codAviso = 'IGEP-903';
			tipoAviso='ALERTA';
			descBreve='Longitud mínima no alcanzada.';
			textoAviso='Debe usted introducir al menos '+arguments[2]+' caracteres.';
			this.error=this.comprobarMinimo (objetoGenerador.type, objetoGenerador, arguments[2]);
		break;
		case 'FECHAINICIO':
			codAviso = 'IGEP-904';
			tipoAviso='ALERTA';
			descBreve='Fecha inferior al límite.';
			textoAviso='La fecha debe ser posterior a: '+arguments[2]+'.';
			this.error=comprobarLimiteFechas (objetoGenerador.value, arguments[2]);
		break;
		case 'FECHAFIN':
			codAviso = 'IGEP-905';
			tipoAviso='ALERTA';
			descBreve='Fecha superior al límite';
			textoAviso='La fecha debe ser inferior a: '+arguments[2]+'.';
			this.error=comprobarLimiteFechas (arguments[2], objetoGenerador.value);
		break;
		case 'RANGOFECHAS':
			codAviso = 'IGEP-906';
			tipoAviso='ALERTA';
			descBreve='Fecha fuera de rango';
			textoAviso='La fecha debe situarse entre: '+arguments[2]+' y '+arguments[3]+'.';
			error1 = comprobarLimiteFechas (arguments[2], objetoGenerador.value);
			error2 = comprobarLimiteFechas (objetoGenerador.value, arguments[3]);
			if (error1 || error2)
			{
				this.error = true;
			}
		break;
		case 'ESVACIO':
			codAviso = 'IGEP-907';
			tipoAviso='ALERTA';
			descBreve='Campo obligatorio';
			textoAviso='El campo no puede ser vacío.';
			this.error=this.esVacio (objetoGenerador.type, objetoGenerador);

		break;
		case 'MASCARA':
			//Método en desuso?
			codAviso = 'IGEP-908';
			//Si hay máscara y es de fecha (nn/nn/nnnn o nn/nn/nn) comprobamos
			//Si la fecha existe
			if ( (arguments[2]=='nn/nn/nnnn') || (arguments[2]=='nn/nn/nn' ) )
			{
				tipoAviso='ALERTA';
				descBreve='Fecha Errónea';
				textoAviso='La fecha introducida ('+objetoGenerador.value+') no es una fecha válida.';
				this.error=comprobarFecha(objetoGenerador.value);
			};

		break;
		case 'FORMATO_NUMERICO':
			//Informa sobre errores en la introducción de números
			codAviso = 'IGEP-909';
			tipoAviso='ERROR';
			descBreve='Campos numéricos';
			textoAviso='El campo valor que ha intoducido en el campo no es un número válido.';
		break;
		case 'FORMATO_FECHA':
			//Informa sobre errores en la introducción de números
			codAviso = 'IGEP-910';
			tipoAviso='ERROR';
			descBreve='Formato fecha';
			textoAviso='El campo de fecha no tiene el formato correcto (dd/mm/aaaa o dd-mm-aaaa).';
		break;
		case 'REGEXP':
			//Valida la expresion regular
			this.error=false;
			if (objetoGenerador.value!='') {
				if (!arguments[2].test(objetoGenerador.value)) {
					codAviso = 'IGEP-911';
					tipoAviso='ERROR';
					descBreve='Error de formato
';
					textoAviso='El campo no cumple con el formato de entrada propuesto.';
					this.error=true;
				}
			}
		break;
		default:
			codAviso = 'IGEP-900';
			tipoAviso='ERROR';
			descBreve='Error indefinido';
			textoAviso='Hay un error de E/S en la IU sin definir.';
			this.error=true;
		break;
	};

	if(this.error)
	{
		//this.error=false;
		aviso=eval('aviso');
		aviso.set('aviso','capaAviso',tipoAviso, codAviso, descBreve, textoAviso);
		aviso.mostrarAviso(objetoGenerador);
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
FUNCION: getCamposErroneos();
*/
function f_oComprobacion_getCamposErroneos()
{
	return(this.camposErroneos);
}

/*
-----------------------------------
*/
function f_oComprobacion_getPagActiva()
{

	if ( (this.objPaginador==null) || (this.objPaginador===null) )
	{
		this.objPaginador = eval(this.idPanel+'_paginacion');
	}

	if ( (this.objPaginador==null) || (this.objPaginador===null) )
	{
		alert('ObjComprobación: No existe un paginador, necesitas definirlo');
		return(-1);
	}
	else
	{
		return(this.objPaginador.getPaginaActiva());
	}
}

/*
-----------------------------------
*/

function f_oComprobacion_addCampo(campo)
{
	//Añadimos al vector el campo a comprobar
	this.vCamposComprobar.push(campo);
}//Fin método faddCampo

function f_oComprobacion_getAccion()
{
	btnToolTip = null;
	accionActiva = null;
	if ( eval('document.getElementById("accionActivaP_F_'+this.idPanel+'")') )
	{
		btnToolTip = eval('document.getElementById("accionActivaP_F_'+this.idPanel+'")'); // Cdo es un cambio d capa
		if ((btnToolTip != null) && (btnToolTip.value != ""))
			return(btnToolTip.value);
	}
	if ( eval('document.getElementById("accionActiva")') )
	{
		accionActiva = eval('document.getElementById("accionActiva")'); // Para cdo viene d Phrame
		if ((accionActiva != null) && (accionActiva.value != ''))
			return(accionActiva.value);
	}

	return('buscar');
}

/*
PRIVADA
Devuelve el texto asociado a un campo
*/
function f_oComprobacion_obtenerEtiquetaCampo(nomCampo)
{
	if ( eval('document.getElementById("txt'+this.idPanel+'_'+nomCampo+'")') )
	{
		txtLabel = eval('document.getElementById("txt'+this.idPanel+'_'+nomCampo+'")');
		txtLabel = txtLabel.innerHTML;
	}
	else
	{
		txtLabel = nomCampo;
	}
	return (txtLabel);
}

function f_oComprobacion_comprobarObligatorios()
{
	switch (this.getAccion())
	{
		case 'modificar':
			prefijo ="cam___";
		break;
		case 'insertar':
			prefijo ="ins___";
		break;
		default:
			prefijo ="";
		break;
	}

	this.camposErroneos="";
	numCampos = this.vCamposComprobar.length;
	vCamposErroneos = new Array();
	switch (this.idPanel)
	{
		case 'fil':
		case 'filDetalle':
		case 'filMaestro':
			for (i=0;i<numCampos;i++)
			{
				campo = eval('document.getElementById("'+this.vCamposComprobar[i]+'")');

				if (this.esVacio(campo.type,campo))
				{
					vCamposErroneos.push(campo.id);
					this.camposErroneos += "
 * "+this.obtenerEtiquetaCampo(this.vCamposComprobar[i]);
				}
			}
		break;
		case 'edi':
		case 'ediDetalle':
		case 'ediMaestro':
			for (i=0;i<numCampos;i++)
			{
				longNombre = this.vCamposComprobar[i].length;
				nomCampo = this.vCamposComprobar[i].substr(0,longNombre-1);
				nomCampo = nomCampo+this.getPagActiva();
				nomCampo = nomCampo.replace('cam___', prefijo);
				if (eval('document.getElementById("'+nomCampo+'")'))
				{
					campo = eval('document.getElementById("'+nomCampo+'")');
					if (this.esVacio(campo.type,campo))
					{
						vCampo = nomCampo.split('___');
						if (vCampo.length > 1)
						{
							nomCampo = vCampo[1];
						};
						vCamposErroneos.push(nomCampo);
						this.camposErroneos += "
 * "+this.obtenerEtiquetaCampo(this.vCamposComprobar[i]);
					}
				}
			}
		break;

		case 'lis':
		case 'lisDetalle':
		case 'lisMaestro':
			objTabla = eval(this.idPanel+'_tabla');
			numFilas = objTabla.vFilasComprobar.length;
			// nomCampo = cam___nomCampo___panel_fila
			for (i=0;i<numCampos;i++)  // Recorrer los campos a comprobar
			{
					// Cambio de prefijo para el estado en el q estamos
					nomCampo = this.vCamposComprobar[i];
					if (prefijo != '')  nomCampo = nomCampo.replace('cam___',prefijo);
 					v_nomCampo = nomCampo.split('___');

					if (v_nomCampo.length == 1) // Es un campo external
					{
						campo = eval('document.getElementById("'+nomCampo+'")');
						if (this.esVacio(campo.type,campo))
						{
							campoComprobar = nomCampo;
						   	yaExiste=false;
							for(j=0;j<vCamposErroneos.length;j++)
						    {
						    	if (vCamposErroneos[j]==campoComprobar)
						    	{
						    		yaExiste=true;
						    		break;
						    	}
						    }
							if (!yaExiste)
							{
								vCamposErroneos.push(campoComprobar);
								this.camposErroneos += "
 * "+this.obtenerEtiquetaCampo(campoComprobar);
							}
						}
					}
					else
					{

	 					// Tenemos q cambiar la fila por el número d fila del campo a comprobar
	 					numFila = v_nomCampo[2].split('_')[1];
	 					for (fila=0;fila<numFilas;fila++)
	 					{
	 						cadFila = "_"+numFila;
	 						nuevaFila = "_"+objTabla.vFilasComprobar[fila];
	 						campoComprobar = nomCampo.replace(cadFila,nuevaFila);
	 						if (eval('document.getElementById("'+campoComprobar+'")'))
							{
								campo = eval('document.getElementById("'+campoComprobar+'")');
								if (this.esVacio(campo.type,campo))
								{
									vCampo = campoComprobar.split('___');
									if (vCampo.length > 1)
									{
										campoComprobar = vCampo[1];
									}

								   	yaExiste=false;
		    						for(j=0;j<vCamposErroneos.length;j++)
								    {
								    	if (vCamposErroneos[j]==campoComprobar)
								    	{
								    		yaExiste=true;
								    		break;
								    	}
								    }
	 								if (!yaExiste)
									{
										vCamposErroneos.push(campoComprobar);
										this.camposErroneos += "
 * "+this.obtenerEtiquetaCampo(campoComprobar);
									}
								} //if
							}//if
	 					}//for
					}//else
				}//for
		break;
	}
	if (this.camposErroneos != '')
	{
		return false;
	}
	return true;
}

function f_oComprobacion_bloquearSalida(estado)
{
	str_imagen = this.idPanel+'_imgModificado';

	// Existe menú en la ventana
	if (eval('document.getElementById("capa_menuReal")'))
	{
		if (estado == true)
		{
			document.getElementById(str_imagen).style.display='inline';
			document.getElementById('capa_menuFalso').style.display='inline';
			document.getElementById('capa_menuReal').style.display='none';
			document.getElementById('permitirCerrarAplicacion').value='no';
		}
		else
		{
			document.getElementById(str_imagen).style.display='none';
			document.getElementById('capa_menuFalso').style.display='none';
			document.getElementById('capa_menuReal').style.display='inline';
			document.getElementById('permitirCerrarAplicacion').value='si';
		}
	}
}

function f_oComprobacion_comprobarModificacion(idCampo)
{
	//Si no soy un panel de edición fin	(y las tablas?)
	if ((this.idPanel !='edi') && (this.idPanel !='ediDetalle')) return;

	var arrayAux = String(idCampo).split('___');
	idCampoEstado = 'est_'+arrayAux[2];
	campoEstado = eval('document.getElementById("'+idCampoEstado+'")');

	// 08/02/2010 Vero: Para comprobar si ha habido modificación en alguno de los radio
	if (arguments[1])
	{
		numRadios = arguments[1];
		nomCampo = arrayAux[1];
		idRadioAnt = 'ant___'+nomCampo+'___'+arrayAux[2];
		radioAnt = eval('document.getElementById("'+idRadioAnt+'")');
		for (i=0;i<numRadios;i++)
		{
			idRadio = arrayAux[0]+'___'+nomCampo+''+i+'___'+arrayAux[2];
			//idRadioAnt = String(idRadio).replace('cam','ant');
			radio = eval('document.getElementById("'+idRadio+'")');
			//Si alguno de los campos no Existe...
			if ((radio == null) || (radioAnt == null)) return;
			if (radio.value != radioAnt.value)
			{
		 		if ( (campoEstado.value=='nada') || (campoEstado.value==''))
		 		{
		 			campoEstado.value='modificada';
		 			//Marcamos la página como modificada
		 			if ( (this.objPaginador==null) || (this.objPaginador===null) )
					{
						this.objPaginador = eval(this.idPanel+'_paginacion');
					}
		 			this.objPaginador.paginasModificadas[this.objPaginador.getPaginaActiva()] = true;
		 		}
		 		this.bloquearSalida(true);
		 		break;
			}
		}
	}
	else
	{
		idCampoAnt = String(idCampo).replace('cam','ant');
		campo = eval('document.getElementById("'+idCampo+'")');
		campoAnt = eval('document.getElementById("'+idCampoAnt+'")');

		//Si alguno de los campos no Existe...
		if (
			(campo == null) ||
			(campoAnt == null)
		) return;

		if (campo.value != campoAnt.value)
		{
	 		if ( (campoEstado.value=='nada') || (campoEstado.value==''))
	 		{
	 			campoEstado.value='modificada';
	 			//Marcamos la página como modificada
	 			if ( (this.objPaginador==null) || (this.objPaginador===null) )
				{
					this.objPaginador = eval(this.idPanel+'_paginacion');
				}
	 			this.objPaginador.paginasModificadas[this.objPaginador.getPaginaActiva()] = true;
	 		}
	 		this.bloquearSalida(true);
		}
	}
}

//Marca el campo estado asociado a la ficha/fila como modificado
function f_oComprobacion_marcarModificacionCampo(idCampo)
{
	//DEBUG: Darle un repasito, teoría de Toni
	// Si no soy un panel de edición fin    (y las tablas?)
	if ((this.idPanel !='edi') && (this.idPanel !='ediDetalle')) return;

	var arrayAux1 = String(idCampo).split('___');
	//Si es una lista múltiple sobrarán también los corchetes "[]"
	var arrayAux2 = String(arrayAux1[2]).split('[');
	idCampoEstado = 'est_'+arrayAux2[0];
	campoEstado = eval('document.getElementById("'+idCampoEstado+'")');
	if ((campoEstado.value=='nada') || (campoEstado.value==''))
	{
		campoEstado.value='modificada';
		this.bloquearSalida(true);
	}
}

///////////////////////////////////////////////////////////////////////////////////////
/// INFORMACIÓN ADICIONAL A LA FECHA
/// Semana del año, día de la semana, día del año
///////////////////////////////////////////////////////////////////////////////////////
function f_oComprobacion_formatoFecha(fecha)
{
	if (fecha != '')
	vFecha = fecha.split('/');
	if ((vFecha.length == 1) && (fecha != ''))
	{
		vFecha = fecha.split('-');
		if (vFecha.length == 1)
			this.informaAvisoJS('FORMATO_FECHA', this);
	}
	return(vFecha);
}

function f_oComprobacion_calcularDiaAnyoJS(fecha)
{
    vFecha = this.formatoFecha(fecha);
    // Se empieza a contar desde 0 tanto para el mes como el día
	var now = new Date(vFecha[2], vFecha[1]-1, vFecha[0]);
	var then = new Date(vFecha[2], 0, 0);
	var dif = now.getTime() - then.getTime();
	dia = Math.floor(dif/(1000*60*60*24))+1;
    return(dia);
}

function f_oComprobacion_calcularSemanaJS(fecha)
{
    vFecha = this.formatoFecha(fecha);
    // Se empieza a contar desde 0 tanto para el mes como el día
	var now = new Date(vFecha[2], (vFecha[1]-1), vFecha[0], 0, 0, 0);
	var then = new Date(vFecha[2], 0, 1, 0, 0, 0);
	var time = now - then;
	var day = then.getDay();  // Devuelve el número d día de la semana
	(day > 3) && (day -= 4) || (day += 3);
    semana = Math.round(((time / Date.DAY) + day) / 7);
	return(semana);
}

function f_oComprobacion_mostrarDiaSemanaJS(fecha,tipo)
{
    vFecha = this.formatoFecha(fecha);

	var dia = vFecha[0];
	var mes = vFecha[1];

	var anyo = vFecha[2];
	if (anyo.length == 2)
	{
		if (anyo == 10)
			anyo = "200" + anyo;
		if (anyo < 80)
			anyo = "20" + anyo;
		if (anyo <= 99)
			anyo = "19" + anyo;
		if (anyo < 1000)
			anyo = anyo + 1900;
	}

	var userYear=anyo;  // Año introducido, puede ser d 2 o 4 dígitos

	var dfecha = " "+ anyo +", "+mes + ",  "+dia;
	var thenx = new Date(anyo,mes,dia);
	var year=thenx.getFullYear();
	if (year<100)
	   year="19" + thenx.getYear();
	else
	   year=thenx.getYear();

	if (year > 1969) wyear=year;
	else
	{
		if (userYear<1900)
		{
			if (userYear>1800)
			{
				wrelyear= (eval(year)-1801)%(28);
				wyear = wrelyear+1981;
			}
			else wyear = 1970;
		}
		else
		{
			if (userYear>1900)
			{
				wrelyear= (eval(userYear)-1901)%(28);
				wyear= wrelyear+1985;
			}
			else
			if (userYear==1900)
				wyear= 1990;
		}
	}
	var dob = " "+ wyear +", "+mes + ",  "+dia;
	var thenx = new Date(dob);

	var theday = thenx.getDay()+1;
	var date=thenx.getDate();

	var weekday = new Array(6);
	weekday[1]="Domingo";
	weekday[2]="Lunes";
	weekday[3]="Martes";
	weekday[4]="Miércoles";
	weekday[5]="Jueves";
	weekday[6]="Viernes";
	weekday[7]="Sábado";

	if ((dia != date) && (dia != ''))
		this.informaAvisoJS('FORMATO_FECHA', this);
	else
	{
		dayborn = weekday[theday];
		if (dayborn == "Miércoles")
			diaSemana = "X";
		else
			diaSemana = dayborn.substring(0,1);
	}
	if (tipo == 'short')
		return diaSemana;
	else
		return weekday[theday];
}

/**
  * mostrarInfoFechaJS() Muestra información adicional de una fecha dada
  * @param	dayOfWeek	boolean	Booleano para devolver el nombre del día de la semana (short/long)
  * @param	dayOfYear	boolean	Booleano para devolver el número de día respecto al año entero
  * @param	weekOfYear	boolean		Booleano para devolver el número de la semana del año
*/
function f_oComprobacion_mostrarInfoFechaJS(fecha,campoFecha,dayOfWeek,dayOfYear,weekOfYear)
{
		idCapa = 'infoFecha'+campoFecha;
		capaDia = eval('document.getElementById("'+idCapa+'")');
		textoCapa = capaDia.childNodes[0];
		infoFecha = '';
		if (fecha != '')
		{
			if (dayOfWeek != 'none')
			  infoFecha += " "+this.mostrarDiaSemanaJS(fecha,dayOfWeek);
			if (dayOfYear)
			  infoFecha += " D"+this.calcularDiaAnyoJS(fecha);
			if (weekOfYear)
			  infoFecha += " S"+this.calcularSemanaJS(fecha);
		}
		textoCapa.data = infoFecha+" ";
}
//*********************************************************************************************************************************/

/**
  * formateaNumero() Dada una cadena (formateada o no) que representa un número
  * devuelve una cadena con el número formateado conforme al idioma (es-ES)
  * @param	strNum	string	Cadena (formateada o no) del número a formatear
  * @param	nDec	int		Número de decimales (con redondeo)
*/
function f_oComprobacion_formateaNumero(strNum, nDec)
{
	strNumOrig = strNum;//Guardfamos la cadena inicial

	//Si NO hay número decimales definidos lo fijamos a dos
	if ((nDec =='') || (nDec ==null)) nDec = 2;

	//Cadena vacía o nula...
	if ((strNum =='') || (strNum ==null)) return;

	//Coprueba si la cadena viene formateada y cual es el formato
	//Conseguimos la cadena numérica equivalente válida en javascript

	//1.- Si aparecen VARIAS comas (',')...
	if (strNum.indexOf(',') != strNum.lastIndexOf(','))
	{
		//... consideramos el número como mál formado
		this.error= true;
		this.informaAvisoJS('FORMATO_NUMERICO', this);
		return strNumOrig;
	}

	//Si hay VARIOS puntos ('.') o un punto Y alguna coma
	if (
		(strNum.indexOf('.') != strNum.lastIndexOf('.'))
		||
			(
				(strNum.indexOf('.')>0)
				&&
				(strNum.indexOf(',')>0)
			)
		)
	{
		//Podemos asumir que el punto se ha usado como separador de miles, así que
		//eliminamos todos los separadores de miles (carácteres '.')
		//para convertirlo en una cadena numérica válida en javascript
		strNum = strNum.split('.').join('');
	}

	//Si aparece UNA coma...
	if (strNum.indexOf(',')>0)
	{
		//Podemos asumir que la coma (','), es el separador decimal, lo cambiamos
		// por el separador decimal que reconoce javascript, el punto ('.')
		strNum = strNum.split(',').join('.');
	}

	//Convertimos a número la cadena numérica
	num = parseFloat(strNum);
	if (isNaN(num))
	{
		this.error= true;
		this.informaAvisoJS('FORMATO_NUMERICO', this);
		return strNumOrig;
	}

	//Convertimos el número a entero y quitamos los decimales
	var x = Math.round(num * Math.pow(10, nDec));

	//Signo del número
	var signo='';
	if (x < 0)	signo='-';

	//Creamos un array con el número
	var y = (''+Math.abs(x)).split('');

	var z = y.length - nDec;
	if (z<0) z--;
	for(var i = z; i < 0; i++) y.unshift('0');

	y.splice(z, 0, ',');
	if(y[0] == ',') y.unshift('0');
	while (z > 3)
	{
		z-=3;
		y.splice(z, 0, '.');
	}

	var retorno = signo+y.join('');
	return retorno;
}


text:
var assert = require('assert');

goog.require('cam.permanodeUtils');

describe('cam.permanodeUtils', function() {
  describe('#getSingleAttr', function() {
    it('should return null if attr unknown or empty string', function() {
        var pn = {
            attr: {
                foo: '',
            },
        };
        assert.strictEqual(null, cam.permanodeUtils.getSingleAttr(pn, 'foo'));
        assert.strictEqual(null, cam.permanodeUtils.getSingleAttr(pn, 'bar'));
    });

    it('should return first array val', function() {
        var pn = {
            attr: {
                foo: ['bar', 'baz'],
            },
        };
        assert.equal('bar', cam.permanodeUtils.getSingleAttr(pn, 'foo'));
    });

    it('should return string val', function() {
        var pn = {
            attr: {
                foo: 'bar',
            },
        };
        assert.equal('bar', cam.permanodeUtils.getSingleAttr(pn, 'foo'));
    });
  });
});

redpajama_set_name: RedPajamaGithub


text:
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/services.xsd">
    <description>Product Services</description>
    <vendor>OFBiz</vendor>

    <service name="migrateFacilityRole" engine="simple"
            location="component://product/script/org/ofbiz/product/UpgradeServices.xml" invoke="migrateFacilityRole">
        <description>
            Migrate data from OldFacilityRole to FacilityParty.
            Since revision 698159 (2008-09-23) the entity FacilityRole has been deprecated.
            This service can be used to upgrade existing data from the FacilityRole entity to the new
            FacilityParty entity.
            Before running this service, load the seed data for the RoleType entity from the file:
            party/data/PartyTypeData.xml
        </description>
    </service>
    <service name="migrateFacilitySquareFootage" engine="simple"
            location="component://product/script/org/ofbiz/product/UpgradeServices.xml" invoke="migrateFacilitySquareFootage">
        <description>
            Migrate data from Facility.oldSquareFootage to Facility.facilitySize.
            The field Facility.squareFootageSince has been deprecated since revision 929912 (2010-04-01)
        </description>
    </service>
    <service name="migrateProductKeyword" engine="simple"
            location="component://product/script/org/ofbiz/product/UpgradeServices.xml" invoke="migrateProductKeyword">
        <description>
            Migrate data from oldProductKeyword to ProductKeyword.
            The entity oldProductKeyword has been deprecated.
            This service can be used to upgrade existing data from the oldProductKeyword entity to the new
            ProductKeyword entity.
            Before running this service, load the seed data for the KeywordType entity from the file:
            common/data/CommonTypeData.xml
        </description>
    </service>

</services>


text:
class Solution(object):
    def upsideDownBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        leftbone = [root]
        rightbone = []
        temp = root
        while temp.left:
            leftbone.append(temp.left)
            rightbone.append(self.upsideDownBinaryTree(temp.right))
            temp = temp.left
        leftbone[0].left = None
        leftbone[0].right = None
        for i in range(len(rightbone)):
            leftbone[-i-1].left = rightbone[-i-1]
            leftbone[-i-1].right = leftbone[-i-2]
        return leftbone[-1]


text:
<?php

/** Error reporting */
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
date_default_timezone_set('Europe/London');

define('EOL',(PHP_SAPI == 'cli') ? PHP_EOL : '<br />');

date_default_timezone_set('Europe/London');

/**
 * PHPExcel
 *
 * Copyright (C) 2006 - 2014 PHPExcel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   PHPExcel
 * @package    PHPExcel
 * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt	LGPL
 * @version    ##VERSION##, ##DATE##
 */

/** PHPExcel */
include '../Classes/PHPExcel.php';

if (!file_exists("33chartcreate-bar.xlsx")) {
	exit("Please run 33chartcreate-bar.php first." . EOL);
}

echo date('H:i:s') , " Load from Excel2007 file" , EOL;
$objReader = PHPExcel_IOFactory::createReader("Excel2007");
$objReader->setIncludeCharts(TRUE);
$objPHPExcel = $objReader->load("33chartcreate-bar.xlsx");

echo date('H:i:s') , " Update cell data values that are displayed in the chart" , EOL;
$objWorksheet = $objPHPExcel->getActiveSheet();
$objWorksheet->fromArray(
	array(
		array(50-12,   50-15,		50-21),
		array(50-56,   50-73,		50-86),
		array(50-52,   50-61,		50-69),
		array(50-30,   50-32,		50),
	),
	NULL,
	'B2'
);

// Save Excel 2007 file
echo date('H:i:s') , " Write to Excel2007 format" , EOL;
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->setIncludeCharts(TRUE);
$objWriter->save(str_replace('.php', '.xlsx', __FILE__));
echo date('H:i:s') , " File written to " , str_replace('.php', '.xlsx', pathinfo(__FILE__, PATHINFO_BASENAME)) , EOL;

// Echo memory peak usage
echo date('H:i:s') , " Peak memory usage: " , (memory_get_peak_usage(true) / 1024 / 1024) , " MB" , EOL;

// Echo done
echo date('H:i:s') , " Done writing file" , EOL;
echo 'File has been created in ' , getcwd() , EOL;


text:
package org.apache.kafka.common.security.authenticator;

import org.apache.kafka.common.config.internals.BrokerSecurityConfigs;
import org.apache.kafka.common.errors.IllegalSaslStateException;
import org.apache.kafka.common.message.ApiMessageType;
import org.apache.kafka.common.message.SaslAuthenticateRequestData;
import org.apache.kafka.common.message.SaslHandshakeRequestData;
import org.apache.kafka.common.network.ChannelBuilders;
import org.apache.kafka.common.network.ChannelMetadataRegistry;
import org.apache.kafka.common.network.ClientInformation;
import org.apache.kafka.common.network.DefaultChannelMetadataRegistry;
import org.apache.kafka.common.network.InvalidReceiveException;
import org.apache.kafka.common.network.ListenerName;
import org.apache.kafka.common.network.TransportLayer;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.requests.AbstractRequest;
import org.apache.kafka.common.requests.ApiVersionsRequest;
import org.apache.kafka.common.requests.ApiVersionsResponse;
import org.apache.kafka.common.requests.RequestHeader;
import org.apache.kafka.common.requests.RequestTestUtils;
import org.apache.kafka.common.requests.ResponseHeader;
import org.apache.kafka.common.requests.SaslAuthenticateRequest;
import org.apache.kafka.common.requests.SaslAuthenticateResponse;
import org.apache.kafka.common.requests.SaslHandshakeRequest;
import org.apache.kafka.common.security.auth.AuthenticateCallbackHandler;
import org.apache.kafka.common.security.auth.KafkaPrincipal;
import org.apache.kafka.common.security.auth.KafkaPrincipalBuilder;
import org.apache.kafka.common.security.auth.SecurityProtocol;
import org.apache.kafka.common.security.kerberos.KerberosShortNamer;
import org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule;
import org.apache.kafka.common.security.plain.PlainLoginModule;
import org.apache.kafka.common.security.ssl.SslPrincipalMapper;
import org.apache.kafka.common.utils.AppInfoParser;
import org.apache.kafka.common.utils.MockTime;
import org.apache.kafka.common.utils.Time;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;

import javax.security.auth.Subject;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.apache.kafka.common.security.scram.internals.ScramMechanism.SCRAM_SHA_256;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class SaslServerAuthenticatorTest {

    private final String clientId = "clientId";

    @Test
    public void testOversizeRequest() throws IOException {
        TransportLayer transportLayer = mock(TransportLayer.class);
        Map<String, ?> configs = Collections.singletonMap(BrokerSecurityConfigs.SASL_ENABLED_MECHANISMS_CONFIG,
                Collections.singletonList(SCRAM_SHA_256.mechanismName()));
        SaslServerAuthenticator authenticator = setupAuthenticator(configs, transportLayer,
                SCRAM_SHA_256.mechanismName(), new DefaultChannelMetadataRegistry());

        when(transportLayer.read(any(ByteBuffer.class))).then(invocation -> {
            invocation.<ByteBuffer>getArgument(0).putInt(SaslServerAuthenticator.MAX_RECEIVE_SIZE + 1);
            return 4;
        });
        assertThrows(InvalidReceiveException.class, authenticator::authenticate);
        verify(transportLayer).read(any(ByteBuffer.class));
    }

    @Test
    public void testUnexpectedRequestType() throws IOException {
        TransportLayer transportLayer = mock(TransportLayer.class);
        Map<String, ?> configs = Collections.singletonMap(BrokerSecurityConfigs.SASL_ENABLED_MECHANISMS_CONFIG,
                Collections.singletonList(SCRAM_SHA_256.mechanismName()));
        SaslServerAuthenticator authenticator = setupAuthenticator(configs, transportLayer,
                SCRAM_SHA_256.mechanismName(), new DefaultChannelMetadataRegistry());

        RequestHeader header = new RequestHeader(ApiKeys.METADATA, (short) 0, clientId, 13243);
        ByteBuffer headerBuffer = RequestTestUtils.serializeRequestHeader(header);

        when(transportLayer.read(any(ByteBuffer.class))).then(invocation -> {
            invocation.<ByteBuffer>getArgument(0).putInt(headerBuffer.remaining());
            return 4;
        }).then(invocation -> {
            // serialize only the request header. the authenticator should not parse beyond this
            invocation.<ByteBuffer>getArgument(0).put(headerBuffer.duplicate());
            return headerBuffer.remaining();
        });

        try {
            authenticator.authenticate();
            fail("Expected authenticate() to raise an exception");
        } catch (IllegalSaslStateException e) {
            // expected exception
        }

        verify(transportLayer, times(2)).read(any(ByteBuffer.class));
    }

    @Test
    public void testOldestApiVersionsRequest() throws IOException {
        testApiVersionsRequest(ApiKeys.API_VERSIONS.oldestVersion(),
                ClientInformation.UNKNOWN_NAME_OR_VERSION, ClientInformation.UNKNOWN_NAME_OR_VERSION);
    }

    @Test
    public void testLatestApiVersionsRequest() throws IOException {
        testApiVersionsRequest(ApiKeys.API_VERSIONS.latestVersion(),
                "apache-kafka-java", AppInfoParser.getVersion());
    }

    @Test
    public void testSessionExpiresAtTokenExpiryDespiteNoReauthIsSet() throws IOException {
        String mechanism = OAuthBearerLoginModule.OAUTHBEARER_MECHANISM;
        Duration tokenExpirationDuration = Duration.ofSeconds(1);
        SaslServer saslServer = mock(SaslServer.class);

        MockTime time = new MockTime();
        try (
                MockedStatic<?> ignored = mockSaslServer(saslServer, mechanism, time, tokenExpirationDuration);
                MockedStatic<?> ignored2 = mockKafkaPrincipal("[principal-type]", "[principal-name");
                TransportLayer transportLayer = mockTransportLayer()
        ) {

            SaslServerAuthenticator authenticator = getSaslServerAuthenticatorForOAuth(mechanism, transportLayer, time, 0L);

            mockRequest(saslHandshakeRequest(mechanism), transportLayer);
            authenticator.authenticate();

            when(saslServer.isComplete()).thenReturn(false).thenReturn(true);
            mockRequest(saslAuthenticateRequest(), transportLayer);
            authenticator.authenticate();

            long atTokenExpiryNanos = time.nanoseconds() + tokenExpirationDuration.toNanos();
            assertEquals(atTokenExpiryNanos, authenticator.serverSessionExpirationTimeNanos());

            ByteBuffer secondResponseSent = getResponses(transportLayer).get(1);
            consumeSizeAndHeader(secondResponseSent);
            SaslAuthenticateResponse response = SaslAuthenticateResponse.parse(secondResponseSent, (short) 2);
            assertEquals(tokenExpirationDuration.toMillis(), response.sessionLifetimeMs());
        }
    }

    @Test
    public void testSessionExpiresAtMaxReauthTime() throws IOException {
        String mechanism = OAuthBearerLoginModule.OAUTHBEARER_MECHANISM;
        SaslServer saslServer = mock(SaslServer.class);
        MockTime time = new MockTime(0, 1, 1000);
        long maxReauthMs = 100L;
        Duration tokenExpiryGreaterThanMaxReauth = Duration.ofMillis(maxReauthMs).multipliedBy(10);

        try (
                MockedStatic<?> ignored = mockSaslServer(saslServer, mechanism, time, tokenExpiryGreaterThanMaxReauth);
                MockedStatic<?> ignored2 = mockKafkaPrincipal("[principal-type]", "[principal-name");
                TransportLayer transportLayer = mockTransportLayer()
        ) {

            SaslServerAuthenticator authenticator = getSaslServerAuthenticatorForOAuth(mechanism, transportLayer, time, maxReauthMs);

            mockRequest(saslHandshakeRequest(mechanism), transportLayer);
            authenticator.authenticate();

            when(saslServer.isComplete()).thenReturn(false).thenReturn(true);
            mockRequest(saslAuthenticateRequest(), transportLayer);
            authenticator.authenticate();

            long atMaxReauthNanos = time.nanoseconds() + Duration.ofMillis(maxReauthMs).toNanos();
            assertEquals(atMaxReauthNanos, authenticator.serverSessionExpirationTimeNanos());

            ByteBuffer secondResponseSent = getResponses(transportLayer).get(1);
            consumeSizeAndHeader(secondResponseSent);
            SaslAuthenticateResponse response = SaslAuthenticateResponse.parse(secondResponseSent, (short) 2);
            assertEquals(maxReauthMs, response.sessionLifetimeMs());
        }
    }

    @Test
    public void testSessionExpiresAtTokenExpiry() throws IOException {
        String mechanism = OAuthBearerLoginModule.OAUTHBEARER_MECHANISM;
        SaslServer saslServer = mock(SaslServer.class);
        MockTime time = new MockTime(0, 1, 1000);
        Duration tokenExpiryShorterThanMaxReauth = Duration.ofSeconds(2);
        long maxReauthMs = tokenExpiryShorterThanMaxReauth.multipliedBy(2).toMillis();

        try (
                MockedStatic<?> ignored = mockSaslServer(saslServer, mechanism, time, tokenExpiryShorterThanMaxReauth);
                MockedStatic<?> ignored2 = mockKafkaPrincipal("[principal-type]", "[principal-name");
                TransportLayer transportLayer = mockTransportLayer()
        ) {

            SaslServerAuthenticator authenticator = getSaslServerAuthenticatorForOAuth(mechanism, transportLayer, time, maxReauthMs);

            mockRequest(saslHandshakeRequest(mechanism), transportLayer);
            authenticator.authenticate();

            when(saslServer.isComplete()).thenReturn(false).thenReturn(true);
            mockRequest(saslAuthenticateRequest(), transportLayer);
            authenticator.authenticate();

            long atTokenExpiryNanos = time.nanoseconds() + tokenExpiryShorterThanMaxReauth.toNanos();
            assertEquals(atTokenExpiryNanos, authenticator.serverSessionExpirationTimeNanos());

            ByteBuffer secondResponseSent = getResponses(transportLayer).get(1);
            consumeSizeAndHeader(secondResponseSent);
            SaslAuthenticateResponse response = SaslAuthenticateResponse.parse(secondResponseSent, (short) 2);
            assertEquals(tokenExpiryShorterThanMaxReauth.toMillis(), response.sessionLifetimeMs());
        }
    }

    private SaslServerAuthenticator getSaslServerAuthenticatorForOAuth(String mechanism, TransportLayer transportLayer, Time time, Long maxReauth) {
        Map<String, ?> configs = Collections.singletonMap(BrokerSecurityConfigs.SASL_ENABLED_MECHANISMS_CONFIG,
                Collections.singletonList(mechanism));
        ChannelMetadataRegistry metadataRegistry = new DefaultChannelMetadataRegistry();

        return setupAuthenticator(configs, transportLayer, mechanism, metadataRegistry, time, maxReauth);
    }

    private MockedStatic<?> mockSaslServer(SaslServer saslServer, String mechanism, Time time, Duration tokenExpirationDuration) throws SaslException {
        when(saslServer.getMechanismName()).thenReturn(mechanism);
        when(saslServer.evaluateResponse(any())).thenReturn(new byte[]{});
        long millisToExpiration = tokenExpirationDuration.toMillis();
        when(saslServer.getNegotiatedProperty(eq(SaslInternalConfigs.CREDENTIAL_LIFETIME_MS_SASL_NEGOTIATED_PROPERTY_KEY)))
                .thenReturn(time.milliseconds() + millisToExpiration);
        return Mockito.mockStatic(Sasl.class, (Answer<SaslServer>) invocation -> saslServer);
    }

    private MockedStatic<?> mockKafkaPrincipal(String principalType, String name) {
        KafkaPrincipalBuilder kafkaPrincipalBuilder = mock(KafkaPrincipalBuilder.class);
        when(kafkaPrincipalBuilder.build(any())).thenReturn(new KafkaPrincipal(principalType, name));
        MockedStatic<ChannelBuilders> channelBuilders = Mockito.mockStatic(ChannelBuilders.class, Answers.RETURNS_MOCKS);
        channelBuilders.when(() ->
                ChannelBuilders.createPrincipalBuilder(anyMap(), any(KerberosShortNamer.class), any(SslPrincipalMapper.class))
        ).thenReturn(kafkaPrincipalBuilder);
        return channelBuilders;
    }

    private void consumeSizeAndHeader(ByteBuffer responseBuffer) {
        responseBuffer.getInt();
        ResponseHeader.parse(responseBuffer, (short) 1);
    }

    private List<ByteBuffer> getResponses(TransportLayer transportLayer) throws IOException {
        ArgumentCaptor<ByteBuffer[]> buffersCaptor = ArgumentCaptor.forClass(ByteBuffer[].class);
        verify(transportLayer, times(2)).write(buffersCaptor.capture());
        return buffersCaptor.getAllValues().stream()
                .map(this::concatBuffers)
                .collect(Collectors.toList());
    }

    private ByteBuffer concatBuffers(ByteBuffer[] buffers) {
        int combinedCapacity = 0;
        for (ByteBuffer buffer : buffers) {
            combinedCapacity += buffer.capacity();
        }
        if (combinedCapacity > 0) {
            ByteBuffer concat = ByteBuffer.allocate(combinedCapacity);
            for (ByteBuffer buffer : buffers) {
                concat.put(buffer);
            }
            return safeFlip(concat);
        } else {
            return ByteBuffer.allocate(0);
        }
    }

    private ByteBuffer safeFlip(ByteBuffer buffer) {
        return (ByteBuffer) ((Buffer) buffer).flip();
    }

    private SaslAuthenticateRequest saslAuthenticateRequest() {
        SaslAuthenticateRequestData authenticateRequestData = new SaslAuthenticateRequestData();
        return new SaslAuthenticateRequest.Builder(authenticateRequestData).build(ApiKeys.SASL_AUTHENTICATE.latestVersion());
    }

    private SaslHandshakeRequest saslHandshakeRequest(String mechanism) {
        SaslHandshakeRequestData handshakeRequestData = new SaslHandshakeRequestData();
        handshakeRequestData.setMechanism(mechanism);
        return new SaslHandshakeRequest.Builder(handshakeRequestData).build(ApiKeys.SASL_HANDSHAKE.latestVersion());
    }

    private TransportLayer mockTransportLayer() throws IOException {
        TransportLayer transportLayer = mock(TransportLayer.class, Answers.RETURNS_DEEP_STUBS);
        when(transportLayer.socketChannel().socket().getInetAddress()).thenReturn(InetAddress.getLoopbackAddress());
        when(transportLayer.write(any(ByteBuffer[].class))).thenReturn(Long.MAX_VALUE);
        return transportLayer;
    }

    private void mockRequest(AbstractRequest request, TransportLayer transportLayer) throws IOException {
        mockRequest(new RequestHeader(request.apiKey(), request.apiKey().latestVersion(), clientId, 0), request, transportLayer);
    }

    private void mockRequest(RequestHeader header, AbstractRequest request, TransportLayer transportLayer) throws IOException {
        ByteBuffer headerBuffer = RequestTestUtils.serializeRequestHeader(header);

        ByteBuffer requestBuffer = request.serialize();
        requestBuffer.rewind();

        when(transportLayer.read(any(ByteBuffer.class))).then(invocation -> {
            invocation.<ByteBuffer>getArgument(0).putInt(headerBuffer.remaining() + requestBuffer.remaining());
            return 4;
        }).then(invocation -> {
            invocation.<ByteBuffer>getArgument(0)
                    .put(headerBuffer.duplicate())
                    .put(requestBuffer.duplicate());
            return headerBuffer.remaining() + requestBuffer.remaining();
        });
    }

    private void testApiVersionsRequest(short version, String expectedSoftwareName,
                                        String expectedSoftwareVersion) throws IOException {
        TransportLayer transportLayer = mockTransportLayer();
        Map<String, ?> configs = Collections.singletonMap(BrokerSecurityConfigs.SASL_ENABLED_MECHANISMS_CONFIG,
                Collections.singletonList(SCRAM_SHA_256.mechanismName()));
        ChannelMetadataRegistry metadataRegistry = new DefaultChannelMetadataRegistry();
        SaslServerAuthenticator authenticator = setupAuthenticator(configs, transportLayer, SCRAM_SHA_256.mechanismName(), metadataRegistry);

        RequestHeader header = new RequestHeader(ApiKeys.API_VERSIONS, version, clientId, 0);
        ApiVersionsRequest request = new ApiVersionsRequest.Builder().build(version);
        mockRequest(header, request, transportLayer);

        authenticator.authenticate();

        assertEquals(expectedSoftwareName, metadataRegistry.clientInformation().softwareName());
        assertEquals(expectedSoftwareVersion, metadataRegistry.clientInformation().softwareVersion());

        verify(transportLayer, times(2)).read(any(ByteBuffer.class));
    }

    private SaslServerAuthenticator setupAuthenticator(Map<String, ?> configs, TransportLayer transportLayer,
                                                       String mechanism, ChannelMetadataRegistry metadataRegistry) {
        return setupAuthenticator(configs, transportLayer, mechanism, metadataRegistry, new MockTime(), null);
    }

    private SaslServerAuthenticator setupAuthenticator(Map<String, ?> configs, TransportLayer transportLayer,
                                                       String mechanism, ChannelMetadataRegistry metadataRegistry, Time time, Long maxReauth) {
        TestJaasConfig jaasConfig = new TestJaasConfig();
        jaasConfig.addEntry("jaasContext", PlainLoginModule.class.getName(), new HashMap<>());
        Map<String, Subject> subjects = Collections.singletonMap(mechanism, new Subject());
        Map<String, AuthenticateCallbackHandler> callbackHandlers = Collections.singletonMap(
                mechanism, new SaslServerCallbackHandler());
        ApiVersionsResponse apiVersionsResponse = ApiVersionsResponse.defaultApiVersionsResponse(
                ApiMessageType.ListenerType.ZK_BROKER);
        Map<String, Long> connectionsMaxReauthMsByMechanism = maxReauth != null ?
                Collections.singletonMap(mechanism, maxReauth) : Collections.emptyMap();

        return new SaslServerAuthenticator(configs, callbackHandlers, "node", subjects, null,
                new ListenerName("ssl"), SecurityProtocol.SASL_SSL, transportLayer, connectionsMaxReauthMsByMechanism,
                metadataRegistry, time, () -> apiVersionsResponse);
    }

}


text:
1) Crear un shell script que muestre en líneas separadas cada uno de los parámetros que reciba. Teniendo en cuenta que:

- Recibe un primer parámetro (que debe ser for, while o until) que indica la orden a utilizar para generar la salidad del resto de parámetros.

- Comprueba que los argumentos son correctos (al menos dos argumentos y el primero es una de las órdenes correctas)

- Debe utilizar un case para seleccionar el código a ejecutar (con for, con while o con until) y no utilizar funciones.

``` bash
$> miScript for uno dos tres
uno
dos
tres
```

2) Añadir y modificar lo necesario al script anterior para utilizar la orden select en lugar del argumento 1 para indicar la orden a a utilizar (while, for o until), incluyendo una opción para finalizar

3) Utilice funciones para permitir que el script del apartado 2 se ejecute correctamente varias veces seguidas sin finalizar

4) Generalice el script del apartado 3 para que el nombre de las opciones esté en un array declarado al comienzo del tipo ORDENES=(for while until finalizar).

5) Crear un nuevo script que muestre la dirección de red a partir de una dirección IP y su máscara de red. Es necesario crear una función que calcule solamente un byte de la dirección de red resultante. El script recibirá la dirección IP y la máscara como argumentos en la llamada.


text:
typedef struct _mapper_having_fields_state_t {
	slls_t*  pfield_names;
	lhmsi_t* pfield_name_set; // xxx make this a true set now that i wrote one :/ ;)
	int      criterion;
} mapper_having_fields_state_t;

// ----------------------------------------------------------------
// record = a,b,c,d,e
// at least b,c
static sllv_t* mapper_having_fields_at_least_process(lrec_t* pinrec, context_t* pctx, void* pvstate) {
	if (pinrec == NULL)
		return sllv_single(NULL);
	mapper_having_fields_state_t* pstate = (mapper_having_fields_state_t*)pvstate;
	int num_found = 0;
	for (lrece_t* pe = pinrec->phead; pe != NULL; pe = pe->pnext) {
		if (lhmsi_has_key(pstate->pfield_name_set, pe->key)) {
			num_found++;
			if (num_found == pstate->pfield_name_set->num_occupied)
				return sllv_single(pinrec);
		}
	}
	lrec_free(pinrec);
	return NULL;
}

static sllv_t* mapper_having_fields_which_are_process(lrec_t* pinrec, context_t* pctx, void* pvstate) {
	if (pinrec == NULL)
		return sllv_single(NULL);
	mapper_having_fields_state_t* pstate = (mapper_having_fields_state_t*)pvstate;
	if (pinrec->field_count != pstate->pfield_name_set->num_occupied) {
		lrec_free(pinrec);
		return NULL;
	}
	for (lrece_t* pe = pinrec->phead; pe != NULL; pe = pe->pnext) {
		if (!lhmsi_has_key(pstate->pfield_name_set, pe->key)) {
			lrec_free(pinrec);
			return NULL;
		}
	}
	return sllv_single(pinrec);
}

// ----------------------------------------------------------------
static sllv_t* mapper_having_fields_at_most_process(lrec_t* pinrec, context_t* pctx, void* pvstate) {
	if (pinrec == NULL)
		return sllv_single(NULL); // xxx cmt all of these, in all mappers
	mapper_having_fields_state_t* pstate = (mapper_having_fields_state_t*)pvstate;
	for (lrece_t* pe = pinrec->phead; pe != NULL; pe = pe->pnext) {
		if (!lhmsi_has_key(pstate->pfield_name_set, pe->key)) {
			lrec_free(pinrec);
			return NULL; // xxx cmt all of these, in all mappers
		}
	}
	return sllv_single(pinrec);
}

// ----------------------------------------------------------------
static void mapper_having_fields_free(void* pvstate) {
	mapper_having_fields_state_t* pstate = (mapper_having_fields_state_t*)pvstate;
	if (pstate->pfield_names != NULL)
		slls_free(pstate->pfield_names);
	if (pstate->pfield_name_set != NULL)
		lhmsi_free(pstate->pfield_name_set);
}

static mapper_t* mapper_having_fields_alloc(slls_t* pfield_names, int criterion) {
	mapper_t* pmapper = mlr_malloc_or_die(sizeof(mapper_t));

	mapper_having_fields_state_t* pstate = mlr_malloc_or_die(sizeof(mapper_having_fields_state_t));
	pstate->pfield_names    = pfield_names;
	pstate->pfield_name_set = lhmsi_alloc();
	for (sllse_t* pe = pfield_names->phead; pe != NULL; pe = pe->pnext)
		lhmsi_put(pstate->pfield_name_set, pe->value, 0);
	pstate->criterion = criterion;

	pmapper->pvstate = (void*)pstate;
	if (criterion == HAVING_FIELDS_AT_LEAST)
		pmapper->pprocess_func = mapper_having_fields_at_least_process;
	else if (criterion == HAVING_FIELDS_WHICH_ARE)
		pmapper->pprocess_func = mapper_having_fields_which_are_process;
	else if (criterion == HAVING_FIELDS_AT_MOST)
		pmapper->pprocess_func = mapper_having_fields_at_most_process;
	pmapper->pfree_func = mapper_having_fields_free;

	return pmapper;
}

// ----------------------------------------------------------------
static void mapper_having_fields_usage(char* argv0, char* verb) {
	fprintf(stdout, "Usage: %s %s [options]\n", argv0, verb);
	fprintf(stdout, "--at-least  {a,b,c}\n");
	fprintf(stdout, "--which-are {a,b,c}\n");
	fprintf(stdout, "--at-most   {a,b,c}\n");
	fprintf(stdout, "Conditionally passes through records depending on each record's field names.\n");
}

// ----------------------------------------------------------------
static mapper_t* mapper_having_fields_parse_cli(int* pargi, int argc, char** argv) {
	slls_t* pfield_names  = NULL;
	int     criterion     = FALSE;

	char* verb = argv[(*pargi)++];

	int argi = *pargi;
	while (argi < argc && argv[argi][0] == '-') {
		if (streq(argv[argi], "--at-least")) {
			criterion = HAVING_FIELDS_AT_LEAST;
		} else if (streq(argv[argi], "--which-are")) {
			criterion = HAVING_FIELDS_WHICH_ARE;
		} else if (streq(argv[argi], "--at-most")) {
			criterion = HAVING_FIELDS_AT_MOST;
		} else {
			mapper_having_fields_usage(argv[0], verb);
			return NULL;
		}

		if (argc - argi < 2) {
			return NULL;
		}
		if (pfield_names != NULL)
			slls_free(pfield_names);
		pfield_names = slls_from_line(argv[argi+1], ',', FALSE);
		argi += 2;
	}

	if (pfield_names == NULL) {
		mapper_having_fields_usage(argv[0], verb);
		return NULL;
	}
	if (criterion == FALSE) {
		mapper_having_fields_usage(argv[0], verb);
		return NULL;
	}

	*pargi = argi;
	return mapper_having_fields_alloc(pfield_names, criterion);
}

// ----------------------------------------------------------------
mapper_setup_t mapper_having_fields_setup = {
	.verb = "having-fields",
	.pusage_func = mapper_having_fields_usage,
	.pparse_func = mapper_having_fields_parse_cli,
};


text:
"""
    zine.utils.datastructures
    ~~~~~~~~~~~~~~~~~~~~~~~~~

    Various data structures.

    :copyright: (c) 2010 by the Zine Team, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
"""
from itertools import izip, imap
from copy import deepcopy

class _Missing(object):

    def __reduce__(self):
        return 'missing'

    def __repr__(self):
        return 'no default'

missing = _Missing()
del _Missing

class ReadOnlyMultiMapping(object):
    """Provides a read only view to multiple mappings."""

    def __init__(self, *mappings):
        self.__dict__['mappings'] = mappings

    @property
    def mappings(self):
        """The tuple of mappings this multi mapping looks up."""
        return self.__dict__['mappings']

    def __getitem__(self, name):
        for mapping in self.mappings:
            if name in mapping:
                return mapping[name]
        raise KeyError(name)

    def get(self, name, default=None):
        """Return a key or the default value if no value exists."""
        try:
            return self[name]
        except KeyError:
            return default

    def __contains__(self, name):
        try:
            self[name]
        except KeyError:
            return False
        return True

    def _dict_method(name):
        def proxy(self):
            return getattr(self.as_dict(), name)()
        proxy.__name__ = name
        proxy.__doc__ = getattr(dict, name).__doc__
        return proxy

    __iter__ = iterkeys = _dict_method('iterkeys')
    itervalues = _dict_method('itervalues')
    iteritems = _dict_method('iteritems')
    keys = _dict_method('keys')
    values = _dict_method('values')
    items = _dict_method('items')
    __len__ = _dict_method('__len__')
    del _dict_method

    def as_dict(self):
        result = {}
        for mapping in reversed(self.mappings):
            result.update(mapping)
        return result

class _PickleProtocol2Sucks(object):
    """This class implements a dummy container that just eats up all
    the stuff appended to it.  It exists because pickle protocol 2 feeds
    stuff to the ordered dict with opcodes *before* `__setstate__` is
    called.  As a matter of fact no `_keys` is present on the dict that point
    and the unpickling crashes with an `AttributeError`.

    This behavior is confusing and yet undocumented, see `#4612`_.

    .. _#4612: http://bugs.python.org/issue4712
    """

    def append(self, value):
        pass

class OrderedDict(dict):
    """Simple ordered dict implementation.

    It's a dict subclass and provides some list functions.  The implementation
    of this class is inspired by the implementation of Babel but incorporates
    some ideas from the `ordereddict`_ and Django's ordered dict.

    The constructor and `update()` both accept iterables of tuples as well as
    mappings:

    >>> d = OrderedDict([('a', 'b'), ('c', 'd')])
    >>> d.update({'foo': 'bar'})
    >>> d
    OrderedDict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])

    Keep in mind that when updating from dict-literals the order is not
    preserved as these dicts are unsorted!

    You can copy an OrderedDict like a dict by using the constructor, `copy.copy`
    or the `copy` method and make deep copies with `copy.deepcopy`:

    >>> from copy import copy, deepcopy
    >>> copy(d)
    OrderedDict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
    >>> d.copy()
    OrderedDict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
    >>> OrderedDict(d)
    OrderedDict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
    >>> d['spam'] = []
    >>> d2 = deepcopy(d)
    >>> d2['spam'].append('eggs')
    >>> d
    OrderedDict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])])
    >>> d2
    OrderedDict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', ['eggs'])])

    All iteration methods as well as `keys`, `values` and `items` return
    the values ordered by the the time the key-value pair is inserted:

    >>> d.keys()
    ['a', 'c', 'foo', 'spam']
    >>> d.values()
    ['b', 'd', 'bar', []]
    >>> d.items()
    [('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])]
    >>> list(d.iterkeys())
    ['a', 'c', 'foo', 'spam']
    >>> list(d.itervalues())
    ['b', 'd', 'bar', []]
    >>> list(d.iteritems())
    [('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])]

    Index based lookup is supported too by `byindex` which returns the
    key/value pair for an index:

    >>> d.byindex(2)
    ('foo', 'bar')

    You can reverse the OrderedDict as well:

    >>> d.reverse()
    >>> d
    OrderedDict([('spam', []), ('foo', 'bar'), ('c', 'd'), ('a', 'b')])

    And sort it like a list:

    >>> d.sort(key=lambda x: x[0].lower())
    >>> d
    OrderedDict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])])

    For performance reasons the ordering is not taken into account when
    comparing two ordered dicts.

    .. _ordereddict: http://www.xs4all.nl/~anthon/Python/ordereddict/
    """
    _keys = _PickleProtocol2Sucks()

    def __init__(self, *args, **kwargs):
        dict.__init__(self)
        self._keys = []
        self.update(*args, **kwargs)

    def __delitem__(self, key):
        dict.__delitem__(self, key)
        self._keys.remove(key)

    def __setitem__(self, key, item):
        if key not in self:
            self._keys.append(key)
        dict.__setitem__(self, key, item)

    def __deepcopy__(self, memo):
        d = memo.get(id(self), missing)
        memo[id(self)] = d = self.__class__()
        dict.__init__(d, deepcopy(self.items(), memo))
        d._keys = self._keys[:]
        return d

    def __getstate__(self):
        return {'items': dict(self), 'keys': self._keys}

    def __setstate__(self, d):
        self._keys = d['keys']
        dict.update(self, d['items'])

    def __reversed__(self):
        return reversed(self._keys)

    @classmethod
    def fromkeys(cls, iterable, default=None):
        return cls((key, default) for key in iterable)

    def clear(self):
        del self._keys[:]
        dict.clear(self)

    def copy(self):
        return self.__class__(self)

    def items(self):
        return zip(self._keys, self.values())

    def iteritems(self):
        return izip(self._keys, self.itervalues())

    def keys(self):
        return self._keys[:]

    def iterkeys(self):
        return iter(self._keys)

    def pop(self, key, default=missing):
        if default is missing:
            return dict.pop(self, key)
        elif key not in self:
            return default
        self._keys.remove(key)
        return dict.pop(self, key, default)

    def popitem(self, key):
        self._keys.remove(key)
        return dict.popitem(self, key)

    def setdefault(self, key, default=None):
        if key not in self:
            self._keys.append(key)
        dict.setdefault(self, key, default)

    def update(self, *args, **kwargs):
        sources = []
        if len(args) == 1:
            if hasattr(args[0], 'iteritems'):
                sources.append(args[0].iteritems())
            else:
                sources.append(iter(args[0]))
        elif args:
            raise TypeError('expected at most one positional argument')
        if kwargs:
            sources.append(kwargs.iteritems())
        for iterable in sources:
            for key, val in iterable:
                self[key] = val

    def values(self):
        return map(self.get, self._keys)

    def itervalues(self):
        return imap(self.get, self._keys)

    def index(self, item):
        return self._keys.index(item)

    def byindex(self, item):
        key = self._keys[item]
        return (key, dict.__getitem__(self, key))

    def reverse(self):
        self._keys.reverse()

    def sort(self, cmp=None, key=None, reverse=False):
        if key is not None:
            self._keys.sort(key=lambda k: key((k, self[k])))
        elif cmp is not None:
            self._keys.sort(lambda a, b: cmp((a, self[a]), (b, self[b])))
        else:
            self._keys.sort()
        if reverse:
            self._keys.reverse()

    def __repr__(self):
        return '%s(%r)' % (type(self).__name__, self.items())

    __copy__ = copy
    __iter__ = iterkeys


text:
@implementation BuyInfoCell

#pragma mark - 懒加载
// 注意,使用懒加载时,调用属性最好用self.,因为第一次调用一定要用self.
- (UIImageView *)mainImageView
{
    if (!_mainImageView) {
        _mainImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        [self.contentView addSubview:_mainImageView];
    }
    return _mainImageView;
}

#pragma mark - 布局
- (void)layoutSubviews
{
    [super layoutSubviews];

    self.mainImageView.frame = CGRectMake(0, 0, kWidthOfScreen, kHeightOfBuyInfo);

}

#pragma mark - 显示数据
- (void)showInfo:(Model *)model
{
    self.mainImageView.image = [UIImage imageNamed:model.imageName2];

    [self layoutSubviews];
}

@end


text:
"""The analyzer helper interface."""

from dfvfs.lib import errors

class AnalyzerHelper(object):
  """Analyzer helper interface."""

  # pylint: disable=redundant-returns-doc

  def __init__(self):
    """Initializes an analyzer helper.

    Raises:
      ValueError: if a derived analyzer helper class does not define format
          categories or a type indicator.
    """
    super(AnalyzerHelper, self).__init__()

    if not getattr(self, 'TYPE_INDICATOR', None):
      raise ValueError('Missing type indicator.')

    if not getattr(self, 'FORMAT_CATEGORIES', None):
      raise ValueError('Missing format categories.')

  @property
  def format_categories(self):
    """set[str]: format categories, such as archive file or file system.

    The format categories are defined in definitions.FORMAT_CATEGORIES.
    """
    # pylint: disable=no-member
    return self.FORMAT_CATEGORIES

  @property
  def type_indicator(self):
    """str: type indicator."""
    # pylint: disable=no-member
    return self.TYPE_INDICATOR

  def AnalyzeFileObject(self, file_object):  # pylint: disable=useless-type-doc
    """Retrieves the format specification.

    This is the fall through implementation that raises a RuntimeError.

    Args:
      file_object (FileIO): file-like object.

    Returns:
      str: type indicator if the file-like object contains a supported format
          or None otherwise.

    Raises:
      NotSupported: since this is the fall through implementation.
    """
    raise errors.NotSupported(
        'Missing implementation to analyze file-like object.')

  def GetFormatSpecification(self):
    """Retrieves the format specification.

    This is the fall through implementation that returns None.

    Returns:
      FormatSpecification: format specification or None if the format cannot
          be defined by a specification object.
    """
    return None

  def IsEnabled(self):
    """Determines if the analyzer helper is enabled.

    Returns:
      bool: True if the analyzer helper is enabled.
    """
    return True


text:
PID::PID()
{
  this->Kp = 0.0;
  this->Ki = 0.0;
  this->Kd = 0.0;
  this->min_output = 0.0;
  this->max_output = 100.0;
}

PID::PID(double Kp, double Ki, double Kd)
{
  this->Kp = Kp;
  this->Ki = Ki;
  this->Kd = Kd;
  this->min_output = 0.0;
  this->max_output = 100.0;
}

PID::PID(double Kp, double Ki, double Kd, double min_output, double max_output)
{
  this->Kp = Kp;
  this->Ki = Ki;
  this->Kd = Kd;
  this->min_output = min_output;
  this->max_output = max_output;
}

double PID::getValue(double curValue, double desValue, double time_step)
{
  static double sumError = 0;
  static double prevError = 0;

  double error = desValue - curValue;

  // calc potential term
  double potentialTerm = Kp * error;

  // calc integral term
  sumError += error;
  double integralTerm = Ki *  sumError;

  integralTerm = this->bound(integralTerm);

  // calc differential term
  double diffError = (error - prevError) / time_step;
  double differentialTerm = Kd * diffError;

  // calculate the PID value
  double pidValue = potentialTerm + integralTerm + differentialTerm;

  pidValue = this->bound(pidValue);

  return pidValue;
}

double PID::bound(double value)
{
	//bound the output
  if(value > this->max_output)
  {
    value = this->max_output;
  } else if(value < this->min_output)
  {
    value = this->min_output;
  }

  return value;

}


text:
project_path: /web/fundamentals/_project.yaml
book_path: /web/fundamentals/_book.yaml

{# wf_updated_on: 2018-09-20 #}
{# wf_published_on: 2016-09-28 #}
{# wf_blink_components: Blink>Storage #}

# Web Storage Overview {: .page-title }

{% include "web/_shared/contributors/mco.html" %}

It's important to choose the right storage mechanisms, both for local device
storage and for cloud based server storage. A good storage engine makes sure
your information is saved reliably, reduces bandwidth, and improves
responsiveness. The right storage caching strategy is a core building block for
enabling offline mobile web experiences.

This article provides a brief foundation for evaluating storage APIs and
services, after which we'll provide a comparison table and some general
guidance. In the near future, we plan to add resources for understanding
selected storage topics in greater depth.

## Storage Taxonomy

Let's start by understanding some of the dimensions by which we can analyze data
storage for web apps. Later, we'll use this framework to enumerate and evaluate
the many storage options available to web developers.

### Data Model

The model for storing units of data determines how data is organized internally,
which impacts ease of use, cost and performance of storage and retrieval
requests.

* **Structured:** Data stored in tables with predefined fields, as is typical
of SQL based database management systems, lends itself well to flexible and
dynamic queries, where the full range of query types may not be be known a
priori. A prominent example of a structured datastore in the
browser is IndexedDB.

* **Key/Value:** Key/Value datastores, and related NoSQL databases, offer the
ability to store and retrieve unstructured data indexed by a unique key.
Key/Value datastores are like hash tables in that they allow constant-time
access to indexed, opaque data. Prominent examples of key/value datastores are
the Cache API in the browser and Apache Cassandra on the server.

* **Byte Streams:** This simple model stores data as a variable length, opaque
string of bytes, leaving any form of internal organization to the application
layer. This model is particularly good for file systems and other hierarchically
organized blobs of data. Prominent examples of byte stream datastores include
file systems and cloud storage services.

### Persistence

Storage methods for web apps can be analyzed according to the scope over which
data is made persistent.

* **Session Persistence:** Data in this category is retained only as long as a
single web session or browser tab remains active. An example of a storage
mechanism with session persistence is the Session Storage API.

* **Device Persistence:** Data in this category is retained across sessions and
browser tabs/windows, within a particular device. An example of a storage
mechanism with device persistence is the Cache API.

* **Global Persistence:** Data in this category is retained across sessions and
devices. As such, it is the most robust form of data persistence. An example of
a storage mechanism with global persistence is Google Cloud Storage.

### Browser Support

Developers should choose an API best suited to their problem domain; however,
they should also take into account the fact that standardized and well
established APIs are preferable to custom or proprietary interfaces, because
they tend to be longer lived and more widely supported. They may also enjoy a
broader knowledge base and a richer developer ecosystem.

### Transactions

Often, it is important for a collection of related storage operations to
succeed or fail atomically. Database management systems have traditionally
supported this feature using the transaction model, where related updates may be
grouped into arbitrary units. While not always necessary, this is a convenient,
and sometimes essential, feature in some problem domains.

### Sync/Async

Some storage APIs are synchronous in the sense that storage or retrieval
requests block the currently active thread until the request is completed. This
is particularly onerous in web browsers, where the storage request is sharing
the main thread with the UI. For efficiency and performance reasons,
asynchronous storage APIs are to be preferred.

## Debugging storage in Chrome DevTools {: #devtools }

Check out the following docs to learn more about using Chrome DevTools to
inspect and debug your web storage API of choice. APIs not mentioned
here are either not supported in DevTools or are not applicable.

* [Local Storage](/web/tools/chrome-devtools/manage-data/local-storage#local-storage)
* [Session Storage](/web/tools/chrome-devtools/manage-data/local-storage#session-storage)
* [Cookies](/web/tools/chrome-devtools/manage-data/cookies)
* [Web SQL](/web/tools/chrome-devtools/manage-data/local-storage#web-sql)
* [Cache](/web/tools/chrome-devtools/progressive-web-apps#caches)
* [IndexedDB](/web/tools/chrome-devtools/manage-data/local-storage#indexeddb)

If you're using multiple storage APIs, check out the Clear Storage feature of
DevTools. This feature lets you clear multiple stores with a single button
click. See [Clear service workers, storage, databases, and
caches](/web/tools/chrome-devtools/manage-data/local-storage#clear-storage) for
more information.

## Where to go next…

Now that we've reviewed some of the relevant ways to think about storage
mechanisms and compared the most popular APIs and services available today,
we'll be adding more content soon to dive more deeply into one or more topics
of interest:

* [Storage for the web](https://web.dev/storage-for-the-web/){: .external }
* [Cache API: An introduction](https://web.dev/cache-api-quick-guide/){: .external }

## Feedback {: #feedback }

{% include "web/_shared/helpful.html" %}


text:
export { AccordionComponent } from './accordion/accordion.component';
export { AccordionPanelComponent } from './accordion/accordion-group.component';
export declare const ACCORDION_DIRECTIVES: Array<any>;


text:
require_relative 'state_data'

class VirusPredictor
  # initializes the class, when a new object is created it sets up the instance variables
  def initialize(state_of_origin, population_density, population)
    @state = state_of_origin
    @population = population
    @population_density = population_density
  end
  # this calls 2 private methods pedicted_deaths and speed_of_spread
  def virus_effects
    predicted_deaths #(@population_density, @population, @state)
    speed_of_spread #(@population_density, @state)
  end

  private
  # based on population_density this methods determines how many whole people are going to die!!! eek! (returns a string)
  def predicted_deaths #(population_density, population, state)

    # Pro Tip: You can set a variable equal to the RESULT of a conditional statement.
    number_of_deaths = if @population_density >= 200
                          (@population * 0.4).floor
                        elsif @population_density >= 150
                          (@population * 0.3).floor
                        elsif @population_density >= 100
                          (@population * 0.2).floor
                        elsif @population_density >= 50
                          (@population * 0.1).floor
                        else
                          (@population * 0.05).floor
                        end

    # if @population_density >= 200
    #   number_of_deaths = (@population * 0.4).floor
    # elsif @population_density >= 150
    #   number_of_deaths = (@population * 0.3).floor
    # elsif @population_density >= 100
    #   number_of_deaths = (@population * 0.2).floor
    # elsif @population_density >= 50
    #   number_of_deaths = (@population * 0.1).floor
    # else
    #   number_of_deaths = (@population * 0.05).floor
    # end

    print "#{@state} will lose #{number_of_deaths} people in this outbreak"

  end
  # based on population_density this method defines how fast the virus will spread and puts half of the string
  def speed_of_spread #(population_density, state) #in months
    # We are still perfecting our formula here. The speed is also affected
    # by additional factors we haven't added into this functionality.
    # speed = 0.0
    if @population_density >= 200
      speed = 0.5
    elsif @population_density >= 150
      speed = 1
    elsif @population_density >= 100
      speed = 1.5
    elsif @population_density >= 50
      speed = 2
    else
      speed = 2.5
    end

    puts " and will spread across the state in #{speed} months.\n\n"
  end

end

def new_report(state_data_hash)
  raise ArguementError.new("Invalid hash") unless state_data_hash.size == 51

  state_data_hash.each do |state_name, state_data|
    current_state = VirusPredictor.new(state_name,  state_data[:population_density], state_data[:population])

    current_state.virus_effects
  end
end

new_report(STATE_DATA)

# DRIVER CODE

# alabama = VirusPredictor.new("Alabama", STATE_DATA["Alabama"][:population_density], STATE_DATA["Alabama"][:population])
# alabama.virus_effects

# jersey = VirusPredictor.new("New Jersey", STATE_DATA["New Jersey"][:population_density], STATE_DATA["New Jersey"][:population])
# jersey.virus_effects

# california = VirusPredictor.new("California", STATE_DATA["California"][:population_density], STATE_DATA["California"][:population])
# california.virus_effects

# alaska = VirusPredictor.new("Alaska", STATE_DATA["Alaska"][:population_density], STATE_DATA["Alaska"][:population])
# alaska.virus_effects

#=======================================================================
# Reflection

# What are the differences between the two different hash syntaxes shown in the state_data file?

# The first rocket notation (using the => symbol) can be used for any type of object.
# However, the colon notation can only be used for integers and symbols.

# What does require_relative do? How is it different from require?

# As we stated above, require_relative loads another file from the same directory.
# this means you have access to variables, methods and other data in the relative file
# in your working file or program. When you use require on its own, you must specify
# the entire path and it's useful if the file you want to load is not in the same
# directory.

# What are some ways to iterate through a hash?

# There are plenty of fun ways to iterate through a hash using built in hash methods
# in the ruby docs. We used each in our solution but all the familiar guys like map work
# as well. They operate slightly differently on hashse becuase you're able to use both
# the key and value.

# When refactoring virus_effects, what stood out to you about the variables, if anything?

# nothing... they weren't needed

# What concept did you most solidify in this challenge?

# I think this challenge came way too late - we already had a lot of challenges in the
# ruby weeks that required us to use and research hashes. This was not much new but it was
# fun to play around with the class and I learned some cool stuff from the guide.