// JavaScript Document
function templateSwitcher(mode,location) {
	if(mode == "open")
		document.write("<form action='"+ location +"' method='post'>");
	else
		document.write("<\/form>");
}

function displaymail() {
	var prefixe = "info" ;
	var domaine = "openfluke" ;
	var extension = "net" ;
	
	document.write("<a href='mailto:"+prefixe+"@"+domaine+"."+extension+"'>"+prefixe+" chez "+domaine+" point "+extension+"</a>");
}

function confirm_del_cat(id_cat, nom_cat)
{
	if(confirm("Voulez-vous vraiment supprimer la catégorie "+nom_cat+" de la base ?"))
	{ // clic sur OK
		document.location.href="/backoffice/blog/del_cat.php?cat_id="+id_cat;
	}
  // clic sur annuler, il se passera rien.		
}

function confirm_del_chap(id_chap, nom_col, num_chap)
{
	if(confirm("Voulez-vous vraiment supprimer le chapitre "+num_chap+" de "+nom_col+" de la base ?"))
	{ // clic sur OK
		document.location.href="/backoffice/manga/chapitre/del_chap.php?id_chap="+id_chap;
	}
  // clic sur annuler, il se passera rien.		
}

function confirm_del_vol(id_vol, nom_col, num_vol)
{
	if(confirm("Voulez-vous vraiment supprimer le volume "+num_vol+" de "+nom_col+" de la base ?"))
	{ // clic sur OK
		document.location.href="/backoffice/manga/volume/del_vol.php?id_vol="+id_vol;
	}
  // clic sur annuler, il se passera rien.		
}

function confirm_del_col(id_col, nom_col)
{
	if(confirm("Voulez-vous vraiment supprimer la série "+nom_col+" de la base ?"))
	{ // clic sur OK
		document.location.href="/backoffice/manga/collection/del_col.php?id_col="+id_col;
	}
  // clic sur annuler, il se passera rien.		
}

function confirm_del_ed(id_ed, nom_ed)
{
	if(confirm("Voulez-vous vraiment supprimer l'éditeur "+nom_ed+" de la base ?"))
	{ // clic sur OK
		document.location.href="/backoffice/manga/editeur/del_editeur.php?id_ed="+id_ed;
	}
  // clic sur annuler, il se passera rien.		
}

function confirm_del_aut(id_aut, nom_aut)
{
	if(confirm("Voulez-vous vraiment supprimer le mangaka "+nom_aut+" de la base ?"))
	{ // clic sur OK
		document.location.href="/backoffice/manga/auteur/del_auteur.php?id_aut="+id_aut;
	}
  // clic sur annuler, il se passera rien.		
}

// ##############################################################################################################
// ###################### CONVERTISSEUR OCTAL ---> CHAINE DE CARACTERE ##########################################
// ##############################################################################################################

// Le but est de saisir une valeur octal (integer) dans le formulaire de saisi.
// On récupère la valeur et on la convertit en chaine de caractère. On parcours 
// la chaine caractère par caractère, et on les stockes dans 3 variables différentes.
// Les 3 variables sont alors reconvertis en un intier. On fait le traitement du calcul
// On affiche le résultat dans les checkbox du formulaire.

function ctrlOctal(temp, temp0, temp1, temp2)
{
 if(temp=="")
 	{alert("Erreur de saisie : Le champ octal est vide"); return -1 ;}
 else if(temp0>7)
 	{alert("Erreur de saisie : la base 8 n'autorise que des chiffres de 0 à 7"); return -1 ;}
 else if(temp1>7)
	{alert("Erreur de saisie : la base 8 n'autorise que des chiffres de 0 à 7"); return -1 ;}
 else if(temp2>7)
	{alert("Erreur de saisie : la base 8 n'autorise que des chiffres de 0 à 7"); return -1 ;}
}

// Traduit l'entier en symbole de droit unix
function traduct(temp)
{
 var result ;
 switch(temp)
 {
  case 0: result = "---" ; break ;
  case 1: result = "--x" ; break ; 
  case 2: result = "-w-" ; break ; 
  case 3: result = "-wx" ; break ; 
  case 4: result = "r--" ; break ; 
  case 5: result = "r-x" ; break ; 
  case 6: result = "rw-" ; break ; 
  case 7: result = "rwx" ; break ; 
 }
 result = result.substring(0,3) ;
 return result ;
}

// coche les checkbox pour la zone User
function proceedUser(temp)
{
 switch(temp)
 {
  case "---" :  break ;
  case "--x" :  document.convert_octal_char.user_x.checked=true ;
  				break ;
  case "-w-" :  document.convert_octal_char.user_w.checked=true ;
				break ;
  case "r--" :  document.convert_octal_char.user_r.checked=true ;
  				break ;
  case "-wx" :  document.convert_octal_char.user_w.checked=true ;
				document.convert_octal_char.user_x.checked=true ;
  				break ;
  case "rw-" :  document.convert_octal_char.user_r.checked=true ;
  				document.convert_octal_char.user_w.checked=true ;
				break ;
  case "r-x" :  document.convert_octal_char.user_r.checked=true ;
  				document.convert_octal_char.user_x.checked=true ;
  				break ;
  case "rwx" :  document.convert_octal_char.user_r.checked=true ;
  				document.convert_octal_char.user_w.checked=true ;
				document.convert_octal_char.user_x.checked=true ;
  				break ;
 }
}
// coche les checkbox pour la zone Group
function proceedGroup(temp)
{
 switch(temp)
 {
  case "---" : 	break ;
  case "--x" :  document.convert_octal_char.group_x.checked=true ;
  				break ;
  case "-w-" :  document.convert_octal_char.group_w.checked=true ;
				break ;
  case "r--" :  document.convert_octal_char.group_r.checked=true ;
  				break ;
  case "-wx" :  document.convert_octal_char.group_w.checked=true ;
				document.convert_octal_char.group_x.checked=true ;
  				break ;
  case "rw-" :  document.convert_octal_char.group_r.checked=true ;
  				document.convert_octal_char.group_w.checked=true ;
				break ;
  case "r-x" :  document.convert_octal_char.group_r.checked=true ;
  				document.convert_octal_char.group_x.checked=true ;
  				break ;
  case "rwx" :  document.convert_octal_char.group_r.checked=true ;
  				document.convert_octal_char.group_w.checked=true ;
				document.convert_octal_char.group_x.checked=true ;
  				break ;
 }
}
// coche les checkbox pour la zone Other
function proceedOther(temp)
{
 switch(temp)
 {
  case "---" :	break ;
  case "--x" :  document.convert_octal_char.other_x.checked=true ;
  				break ;
  case "-w-" :  document.convert_octal_char.other_w.checked=true ;
				break ;
  case "r--" :  document.convert_octal_char.other_r.checked=true ;
  				break ;
  case "-wx" :  document.convert_octal_char.other_w.checked=true ;
				document.convert_octal_char.other_x.checked=true ;
  				break ;
  case "rw-" :	document.convert_octal_char.other_r.checked=true ;
				document.convert_octal_char.other_w.checked=true ;
  				break ;
  case "r-x" :  document.convert_octal_char.other_r.checked=true ;
  				document.convert_octal_char.other_x.checked=true ;
  				break ;
  case "rwx" :  document.convert_octal_char.other_r.checked=true ;
  				document.convert_octal_char.other_w.checked=true ;
				document.convert_octal_char.other_x.checked=true ;
  				break ;
 }
}

function octal_conver_char()
{
var octal = document.forms["convert_octal_char"].elements["val_octal"].value ; // valeur saisie dans le formulaire...
// conversion de la valeur integer saisie en chaine de caractère...
octal = octal.toString();
// concatène 00 si l'utilisateur a saisi qu'un seul chiffre dans le champ ou bien 0 s'il a saisi deux chiffres
if(octal.length==1)
{ octal = "00"+octal ; }
else if(octal.length==2)
{ octal = "0"+octal ; }
// reconvertion de chaque chiffre (type char) en int
var char0 = parseInt(octal.charAt(0));
var char1 = parseInt(octal.charAt(1));
var char2 = parseInt(octal.charAt(2));
// contrôle de la valeur octal
var code = ctrlOctal(octal, char0, char1, char2);
if(code == -1)
	{return 0 ;}
else
	{	
// On traduit alors chaque entier stocké dans les variables en symbole unix
	char0 = traduct(char0) ; // traduit l'entier pour les droits Utilisateur
	char1 = traduct(char1) ; // traduit l'entier pour les droits Groupe
	char2 = traduct(char2) ; // traduit l'entier pour les droits Autres
	
	proceedUser(char0) ; // affiche dans les 3 checkbox de la zone User la traduction symbolique de l'entier
	proceedGroup(char1) ; // affiche dans les 3 checkbox de la zone Group la traduction symbolique de l'entier
	proceedOther(char2) ; // affiche dans les 3 checkbox de la zone Other la traduction symbolique de l'entier
	}
}

// #################################################################################################################
// ######################### CONVERTISSEUR CHAINE DE CARACTERE ---> OCTAL ##########################################
// #################################################################################################################

function char_conv_octal()
{
 var user_r, user_w, user_x, group_r, group_w, group_x, other_r, other_w, other_x, resultat ;
 // on stocke dans des variables l'état booléen de chaque checkbox
 user_r = document.forms["convert_char_octal"].elements["user_r"].checked ; 
 user_w = document.forms["convert_char_octal"].elements["user_w"].checked ;
 user_x = document.forms["convert_char_octal"].elements["user_x"].checked ; 
 group_r = document.forms["convert_char_octal"].elements["group_r"].checked ; 
 group_w = document.forms["convert_char_octal"].elements["group_w"].checked ; 
 group_x = document.forms["convert_char_octal"].elements["group_x"].checked ; 
 other_r = document.forms["convert_char_octal"].elements["other_r"].checked ; 
 other_w = document.forms["convert_char_octal"].elements["other_w"].checked ; 
 other_x = document.forms["convert_char_octal"].elements["other_x"].checked ;
 // pour chaque checkbox, on attribut une valeur entière si la checkbox est cochée
 // Cas de la zone utilisateur :
 if(user_r==true)
	{user_r = 400 ;}
 else
	{user_r = 0 ;}
 if(user_w==true)
	{user_w = 200 ;}
 else
	{user_w = 0 ;}
 if(user_x==true)
	{user_x = 100 ;}
 else
	{user_x = 0 ;}	
 // Cas de la zone groupe :
 if(group_r==true)
	{group_r = 40 ;}
 else
	{group_r = 0 ;}
 if(group_w==true)
	{group_w = 20 ;}
 else
	{group_w = 0 ;}
 if(group_x==true)
	{group_x = 10 ;}
 else
	{group_x = 0 ;}	
// Cas de la zone autre :
 if(other_r==true)
	{other_r = 4 ;}
 else
	{other_r = 0 ;}
 if(other_w==true)
	{other_w = 2 ;}
 else
	{other_w = 0 ;}
 if(other_x==true)
	{other_x = 1 ;}
 else
	{other_x = 0 ;}	

 resultat = user_r + user_w + user_x + group_r + group_w + group_x + other_r + other_w + other_x ;
 document.forms["convert_char_octal"].elements["resultat"].value = resultat ;
}




		function displaySize() {
			// Etape 1 : récupération de la valeur saisie et son unité
			var valuein = document.forms["conOctetByte"].elements["valueask"].value ;
			// On vérifie que la variable valuein n'est pas vide, sinon, on affiche un message d'erreur à l'utilisateur
			if(valuein == "") {
				alert("Erreur saisie : vous n'avez pas saisie de valeur dans le champs d'entree.");
				return -1 ;
			} 
			else {
			// on convertit la valeur saisie en type float. C'est un contrôle de saisie pour valider que : 
			// 1°/ l'utilisateur a bien saisi un nombre dans le champs et pas une chaine de caractere
			// 2°/ l'utilisation a saisie une valeur numérique strictement positive, sinon, on prends sa valeur absolue selon la règle mathématique
				valuein = Math.abs(parseFloat(valuein));
			}
						
			var unitein = document.forms["conOctetByte"].elements["unite"].options[document.forms["conOctetByte"].elements['unite'].selectedIndex].value ;
			// Etape 2 : calcul des différentes tailles possibles
			switch (unitein) {
				case "o":
					var valtera = "" ;			
					var valgiga = "" ;
					var valmega = "" ;
					var valkilo = "" ;
					var valunit =  valuein ;
					break ;
				case "ko":
					var valtera = "" ;			
					var valgiga = "" ;
					var valmega = "" ;
					var valkilo =  valuein ;
					var valunit =  valuein * 1024 ;
					break ;
				case "mo":
					var valtera = "";
					var valgiga = "";
					var valmega =  valuein ;
					var valkilo =  valmega * 1024 ;
					var valunit =  valkilo * 1024 ;
					break ;
				case "go":
					var valtera =  ""			
					var valgiga =  valuein ;
					var valmega =  valgiga * 1024 ;
					var valkilo =  valmega * 1024 ;
					var valunit =  valkilo * 1024 ;
					break ;
				case "to":
					var valtera =  valuein ;			
					var valgiga =  valtera * 1024 ;
					var valmega =  valgiga * 1024 ;
					var valkilo =  valmega * 1024 ;
					var valunit =  valkilo * 1024 ;
					break ;
			}
			
			// Etape 3 : Afficher les résultats sur le formulaire
			// On réaffiche la valeur saisie dans le champs de saisie en cas de saisie non conforme a ce qui est attendu pour montrer ce que le script a compris...
			document.forms["conOctetByte"].elements["valueask"].value = valuein ;
			
			document.forms["conOctetByte"].elements["valunit"].value = valunit ;
			document.forms["conOctetByte"].elements["valkilo"].value = valkilo ;
			document.forms["conOctetByte"].elements["valmega"].value = valmega ;
			document.forms["conOctetByte"].elements["valgiga"].value = valgiga ;
			document.forms["conOctetByte"].elements["valtera"].value = valtera ;
			
		}
		
		function calcSizeFree() {
			var pesize = document.forms["step01"].elements["pesize"].value ;
			//var pesize = document.forms[0].elements["pesize"].value ;
			var pefree = document.forms["step01"].elements["pefree"].value ;
			//var pefree = document.forms[0].elements["pefree"].value ;
			var sizemo = pesize * pefree ;
			var sizego = sizemo / 1024 ;
			sizego = Math.round(sizego*1000)/1000 ;
			
			document.forms["step01"].elements["sizemo"].value = sizemo ;
			document.forms["step01"].elements["sizego"].value = sizego ;
		}

		function calcExtendLv() {
			var vgname = document.forms["step02"].elements["vgname"].value ;
			var lvname = document.forms["step02"].elements["lvname"].value ;
			var mountname = document.forms["step02"].elements["mountname"].value ;
			var sizemocur = document.forms["step02"].elements["sizemocur"].value ;
			var sizemoask = document.forms["step02"].elements["sizemoask"].value ;
			
			var sizemodif = sizemoask - sizemocur ;
			var sizekodif = sizemodif * 1024 ;
			var sizekoask = sizemoask * 1024 ;			
			if(document.forms["step02"].elements["jfs"].checked)
				var cmd = "# Package OnlineJFS installe !\n> fsadm -F vxfs -b "+sizekodif+" "+mountname+"\n\n> bdf "+vgname+"/"+lvname+"\n# Valeur attendue (colonne kbytes) : "+sizekoask ;
			else
				var cmd = "# Package OnlineJFS non installe...\n> umount "+mountname+"\n> lvextend -L "+sizemoask+"M "+vgname+"/"+lvname+"\n> extendfs -F vxfs "+sizemodif+"M "+vgname+"/r"+lvname+"\n> mount "+mountname+"\n\n> bdf "+vgname+"/"+lvname+"\n# Valeur attendue (colonne kbytes) : "+sizekoask ;
			
			document.forms["step02"].elements["cmdshell"].value = cmd ;
		}

		function calcCreateLv(vgname, lvname, mountname, sizemoask) {
			/*var vgname = document.forms["step02"].elements["vgname"].value ;
			var lvname = document.forms["step02"].elements["lvname"].value ;
			var mountname = document.forms["step02"].elements["mountname"].value ;
			var sizemoask = document.forms["step02"].elements["sizemoask"].value ;*/
			var typefs = document.forms["step02"].elements["listfs"].options[document.step02.elements["listfs"].selectedIndex].value ;
			
			var cmd = "> lvcreate -L "+sizemoask+"M -n "+lvname+" "+vgname+"\n> newfs -F "+typefs+" "+vgname+"/r"+lvname+"\n\n# Ajoutez la ligne ci-dessous dans le fichier /etc/fstab\n"+vgname+"/"+lvname+" "+mountname+" "+typefs+" delaylog 0 2\n\n# Monter le nouveau File System "+lvname+"\n> mount "+mountname ;

			document.forms["step02"].elements["cmdshell"].value = cmd ;
		}

		function calcCreateLvLinux(vgname, lvname, mountname, sizemoask) {
			/*var vgname = document.forms["step02"].elements["vgname"].value ;
			var lvname = document.forms["step02"].elements["lvname"].value ;
			var mountname = document.forms["step02"].elements["mountname"].value ;
			var sizemoask = document.forms["step02"].elements["sizemoask"].value ;*/
			var typefs = document.forms["step02"].elements["listfs"].options[document.step02.elements["listfs"].selectedIndex].value ;
			
			var cmd = "> lvcreate -L "+sizemoask+"M -n "+lvname+" "+vgname+"\n> mkfs -t "+typefs+" "+vgname+"/"+lvname+"\n\n# Ajoutez la ligne ci-dessous dans le fichier /etc/fstab\n"+vgname+"/"+lvname+" "+mountname+" "+typefs+" defaults 1 2\n\n# Monter le nouveau File System "+lvname+"\n> mount "+mountname ;

			document.forms["step02"].elements["cmdshell"].value = cmd ;
		}
		
		function checkInput() {
			// Recuperation des valeurs saisies dans les champs du formulaire...
			var vgname = document.forms["step02"].elements["vgname"].value ;
			var lvname = document.forms["step02"].elements["lvname"].value ;
			var mountname = document.forms["step02"].elements["mountname"].value ;
			var sizemoask = document.forms["step02"].elements["sizemoask"].value ;
			
			// Si l'un des 4 champs est vide, on affiche un message d'erreur et l'ecran Terminal X reste vierge.
			if (vgname=="" || lvname=="" || mountname=="" || sizemoask=="") {
				alert("Impossible d'afficher les commandes shell.\n\nL\'assistant n'est pas complété correctement."); return -1 ;
			} else {
				// les champs ne sont pas vides, mais on verifie malgre tout que le champs "LV Size" est bien un nombre.
				// A programmer...
				
				calcCreateLv(vgname, lvname, mountname, sizemoask);
			} // fin du bloc else
		}
		
		function checkInputLinux() {
			// Recuperation des valeurs saisies dans les champs du formulaire...
			var vgname = document.forms["step02"].elements["vgname"].value ;
			var lvname = document.forms["step02"].elements["lvname"].value ;
			var mountname = document.forms["step02"].elements["mountname"].value ;
			var sizemoask = document.forms["step02"].elements["sizemoask"].value ;
			
			// Si l'un des 4 champs est vide, on affiche un message d'erreur et l'ecran Terminal X reste vierge.
			if (vgname=="" || lvname=="" || mountname=="" || sizemoask=="") {
				alert("Impossible d'afficher les commandes shell.\n\nL\'assistant n'est pas complété correctement."); return -1 ;
			} else {
				// les champs ne sont pas vides, mais on verifie malgre tout que le champs "LV Size" est bien un nombre.
				// A programmer...
				
				calcCreateLvLinux(vgname, lvname, mountname, sizemoask);
			} // fin du bloc else
		}
		
/*Fonction qui genere les lignes pour le fichier /etc/hostname.XX
# Avec deux cas de figure :
# 1. L'interface active
# 2. L'interface de réserve */
function makeHostname(host, grp, cardAct, cardRes, numAct, numRes, ipAct, ipRes, aliasVir, aliasAct, aliasRes) {
	var lineHostnameAct, lineHostnameRes ;
	
	lineHostnameAct = aliasAct+" netmask + broadcast + deprecated –failover group "+grp+" up\naddif "+aliasVir+" netmask + broadcast + failover up" ;
	lineHostnameRes = aliasRes+" netmask + broadcast + deprecated -failover standby group "+grp+" up" ;
	
	document.getElementById("hostnameAct").innerHTML = "/etc/hostname."+cardAct+numAct ; document.forms["formIpmp"].elements["hostnameAct"].value = lineHostnameAct ;
	document.getElementById("hostnameRes").innerHTML = "/etc/hostname."+cardRes+numRes ; document.forms["formIpmp"].elements["hostnameRes"].value = lineHostnameRes ;
}

// Fonction qui genere les lignes pour le fichier /etc/hosts
function makeHosts(host, ipAct, ipRes, ipVir, aliasVir, aliasAct, aliasRes) { 
	//var linesHosts = host+"-vir\t"+ipVir+"\n"+aliasAct+"\t"+ipAct+"\n"+aliasRes+"\t"+ipRes+"\n" ;
	var linesHosts = ipVir+"\t"+aliasVir+"\n"+ipAct+"\t"+aliasAct+"\n"+ipRes+"\t"+aliasRes+"\n" ;
	
	document.forms["formIpmp"].elements["etcHosts"].value = linesHosts ;
}

// Fonction qui genere les informations IPMP que la commande IFCONFIG doit retourner
function makeIfconfig(cardAct, cardRes, numAct, numRes, ipAct, ipRes, ipVir) {
	var lineHead = "Statut IPMP en situation nominal :\n" ;
	var linePreAct = "l\'adresse "+ipAct+" apparaitra sur l\'interface "+cardAct+numAct+" NOFAILOVER\n" ;
	var linePreVir = "l\'adresse "+ipVir+" apparaitra sur l\'interface "+cardAct+numAct+":1\n" ;
	var linePreRes = "l\'adresse "+ipRes+" apparaitra sur l\'interface "+cardRes+numRes+" STANDBY, INACTIVE\n" ;
	var lineMiddle = "\nStatut IPMP en cas de defaillance sur "+cardAct+numAct+"...\n" ;
	var linePostAct = "l\'adresse "+ipAct+" apparaitra sur l\'interface "+cardAct+numAct+" OFFLINE\n" ;
	var linePostVir = "l\'adresse "+ipRes+" apparaitra sur l\'interface "+cardRes+numRes+" NOFAILOVER, STANDBY\n" ;
	var linePostRes = "l\'adresse "+ipVir+" apparaitra sur l\'interface "+cardRes+numRes+":1 STANDBY\n" ;	
	
	var lineAll = lineHead+linePreAct+linePreVir+linePreRes+lineMiddle+linePostAct+linePostVir+linePostRes ;
	
	document.forms["formIpmp"].elements["outIfconfig"].value = lineAll ;
}

/* Fonction qui recupere les valeurs d'entree du formulaire
# champ Hostname : "hostname"
# champ groupe : "groupe"
# champ numero interface active : "numIntAct"
# champ numero interface de reserve : "numIntRes"
# champ ip interface active : "ipIntAct"
# champ ip interface de reserve : "ipIntRes"
# champ ip interface virtuelle : "ipIntVir" */

function getInput() {
	var host, grp, ipVir, aliasVir, cardAct, cardRes, numAct, numRes, ipAct, aliasAct, numRes, ipRes, aliasRes ;
	
	host = document.forms["formIpmp"].elements["hostname"].value ;
	grp = document.forms["formIpmp"].elements["groupe"].value ;
	ipVir = document.forms["formIpmp"].elements["ipIntVir"].value ;
	// Type carte reseau interface active
	cardAct = document.forms["formIpmp"].elements["cardAct"].options[document.formIpmp.elements["cardAct"].selectedIndex].value ;
	// Type carte reseau interface de reserve
	cardRes = document.forms["formIpmp"].elements["cardRes"].options[document.formIpmp.elements["cardRes"].selectedIndex].value ;

	numAct = document.forms["formIpmp"].elements["numIntAct"].value ;
	numRes = document.forms["formIpmp"].elements["numIntRes"].value ;
	ipAct = document.forms["formIpmp"].elements["ipIntAct"].value ;
	ipRes = document.forms["formIpmp"].elements["ipIntRes"].value ;
	aliasVir = document.forms["formIpmp"].elements["aliasIntVir"].value ;
	aliasAct = document.forms["formIpmp"].elements["aliasIntAct"].value ;
	aliasRes = document.forms["formIpmp"].elements["aliasIntRes"].value ;
	// Envoie des variables a makeHostname()
	makeHostname(host, grp, cardAct, cardRes, numAct, numRes, ipAct, ipRes, aliasVir, aliasAct, aliasRes) ;
	
	// Envoie des variables a makeHosts()
	makeHosts(host, ipAct, ipRes, ipVir, aliasVir, aliasAct, aliasRes) ;
	
	// Envoie des variables a makeIfconfig();
	makeIfconfig(cardAct, cardRes, numAct, numRes, ipAct, ipRes, ipVir) ;
}