#Fabrication d'une carte en svg avec un pgm perl
#Les colonnes des fichiers sont supposées séparées par des tabulations (\t)
#L'identifiant pivot est commun à tous les fichiers, il précise une surface.
#Exemple: D01, D75, FRA (pour France), etc.
#Les objets associés (cercles, texte, etc.) auront la même racine: D75C pour le cercle de D75, D75T pour le texte associé à D75, etc.
# Penser aux tirets: composantes connexes sinon jeux avec Z dans une même ligne

###Attention: repérage des surfaces changé (C au lieu de D). Non générique car existe aussi un calque des dpts
#Changer le stroke-width des cercles s'ils surchargent la carte

#1. Cercles si présents
open (C,"centrescommunes") or $centresabsents=1; #Fichier des centres. "or": A ne pas reproduire!
while (<C>)
	{
	chop;
	($dpt,$cx,$cy)=split(/\t/);
	$debutcercle{$dpt}="<circle id=\"".$dpt."C\" cx=\"".$cx."\" cy=\"".$cy."\" ";
	$memocercle{$dpt}++; # permettra d'éviter de faire des cercles pour des entités sans centre
	}
close (C);

$divisionrayon=4; #20 pour la France et ses dpts


open (P,"PopApproxCommunes") or $centresabsents=1; #Fichier données pour cercles. Ex. de ligne: D75	500	500
$minpop=1000000000000;
$maxpop=-1000000000000;
while (<P>)
	{
	chop;
	($dpt,$pop)=split("\t");
	next if ! defined $memocercle{$dpt}; # Si on n'a pas les centres...

	#Tout de suite, on calcule le min et le max des population: pour les rayons et la légende
	$maxpop=$pop if $maxpop<=$pop;
	$minpop=$pop if $minpop>=$pop;
	$popul{$dpt}=$pop;
	if (! defined $centresabsents)
		{
		$rayon{$dpt}= sprintf("%.2f",sqrt($pop)/$divisionrayon); # Formule à adapter selon pays et valeurs. Mais garder sqrt!
		}
	else
		{
		$rayon{$dpt}=0;
		}	
	$calquecercle.=$debutcercle{$dpt}." r=\"".$rayon{$dpt}."\" > <\/circle>\n";
#		fin dessin complet du cercle; on peut faire + simple avec des CSS	
	}
close (P);	
print  "Le minpop vaut $minpop et le maxpop $maxpop\n"; 

#On dessine le calque des cercles
$calquecercle="<g id=\"lescercles\" stroke=\"green\" stroke-width=\"1px\" fill=\"none\" opacity=\"0.5\">\n".$calquecercle."\n<\/g>\n"; #paramètres modifiables
#Fin calque cercles

#Légende des cercles: min, max, sqrt(min et max) (moy harmonique)
#On ne sait pas encore où la mettre: d'où un $xlegendecercles et un $ylegendecercles à adapter
#C'est lent, pour faire simple. On pourrait faire + vite, mais ce serait au delà de notre programme d'initiation
$xlegendecercles=200;
$ylegendecercles=700;
if (! defined $centresabsents)
	{
$rayonpetitcercle= sprintf("%.2f",sqrt($minpop)/$divisionrayon); #On applique la même formule
$rayongrandcercle= sprintf("%.2f",sqrt($maxpop)/$divisionrayon); #On applique la même formule
$rayonmoyencercle= sprintf("%.2f", sqrt($rayonpetitcercle*$rayongrandcercle));
	}
else
	{
	$rayonpetitcercle= $rayongrandcercle=$rayonmoyencercle=0;
	}	
#On fabrique les cercles et les textes à côté
$cypetitcercle=$ylegendecercles-$rayonpetitcercle;
$cymoyencercle=$ylegendecercles-$rayonmoyencercle;
$cygrandcercle=$ylegendecercles-$rayongrandcercle; #Ainsi, tous les cercles ont la même base

$xtextecercles=$rayongrandcercle*1.5+$xlegendecercles; #le x de base pour les valeurs des cercles
#La suite dépend de la taille de la police et donc de la carte
$ytextepetitcercle= $cypetitcercle-$rayonpetitcercle;
$ytextemoyencercle= $cymoyencercle-$rayonmoyencercle;
$ytextegrandcercle= $cygrandcercle-$rayongrandcercle;

#On reconstitue les valeurs associées: il faut inverser la formule $rayon{$dpt}= int(sqrt($pop)/20);
$textepetitcercle=int(($divisionrayon*$rayonpetitcercle)**2); #au carré
$textemoyencercle=int(($divisionrayon*$rayonmoyencercle)**2);
$textegrandcercle=int(($divisionrayon*$rayongrandcercle)**2);
#Il faudrait ajouter des lignes horizontales mais c'est suffisamment besogneux comme ça...

$troiscerclesleg="<circle id=\"petitc\"  cx=\"$xlegendecercles\" cy=\"$cypetitcercle\" r=\"$rayonpetitcercle\" stroke=\"black\" stroke-width=\"2\" fill=\"none\" opacity=\"0.5\" >  <\/circle> 
<circle id=\"moyenc\" cx=\"$xlegendecercles\" cy=\"$cymoyencercle\" r=\"$rayonmoyencercle\" stroke=\"black\" stroke-width=\"2\" fill=\"none\"  opacity=\"0.5\" >  <\/circle> 
<circle id=\"grandc\" cx=\"$xlegendecercles\" cy=\"$cygrandcercle\" r=\"$rayongrandcercle\" stroke=\"black\" stroke-width=\"2\" fill=\"none\" opacity=\"0.5\" >  <\/circle> \n";

$troiscerclesleg.=
"<text x=\"$xtextecercles\" y=\"$ytextepetitcercle\" style=\"font-size:30px\">  $textepetitcercle<\/text>
<text x=\"$xtextecercles\" y=\"$ytextemoyencercle\" style=\"font-size:30px\">  $textemoyencercle<\/text>
<text x=\"$xtextecercles\" y=\"$ytextegrandcercle\" style=\"font-size:30px\"> $textegrandcercle<\/text>\n";
#On encapsule dans un calque
$troiscerclesleg="<g id=\"legcercles\">\n".$troiscerclesleg."<\/g>\n";
#Fin Légende des cercles; c'était un peu besogneux, avouons le

$nouveaucalque=$troiscerclesleg;
$nouveaucalque= "" if defined $centresabsents;

#2. Couleurs surfaces
open (M,"pcAbst"); #Fichier données pour plages de couleurs
$min=10000000000;
$max=-10000000000;
while (<M>)
	{
	chop;
	($dept,$pcmorts)=split(/\t/);
	$covid{$dept}=$pcmorts; # tableau %covid	
	$max=$pcmorts if $max<=$pcmorts;
	$min=$pcmorts if $min>=$pcmorts;
	}
close (M);
print "Le min vaut $min et le max $max\n"; 

#Légende et coloration
$departycaisson=2200;
@seuils=(15,22,30,40); #si 3 seuils, donc 4 couleurs; si 4 seuils, 5 couleurs, etc.
@couleurs=('lemonchiffon','gold','darkorange','red','darkred');
$couleurvaleursmanquantes="turquoise";

$caissonbase="<rect x=\"100\" y=\"hauteury\" width=\"80\" height=\"50\"  fill=\"couleur\"/>";
$textecaissonbase="<text x=\"230\" y=\"hauteurytexte\" style=\"font-size:40px\">  valeurcaisson</text>";

foreach $u (0..$#seuils+2) # la dernière limite de @seuils: vaut 2 si @seuils contient 3 élements, etc.
#ON rajoute 1 pour les valeurs manquantes
	{
	$caissson=$caissonbase;
	$ynew=$departycaisson-$u*100; # -, sinon 3-$u
	$caissson=~s/hauteury/$ynew/; #	print $caissson,"\n";
	$textecaisson=$textecaissonbase;
	$ynew2=$ynew+30;
	$textecaisson=~s/hauteurytexte/$ynew2/;
	
	if ($u <=$#seuils+1)
		{
		$caissson=~s/couleur/$couleurs[$u]/;
		$texteleg="≤ ".$seuils[$u]; 
		$texteleg="≤ ".$max if $u ==$#seuils+1;
		$textecaisson=~s/valeurcaisson/$texteleg/; 
		$nouveaucalque.=$caissson."\n".$textecaisson."\n";
		}
	else
		{	
		$textecaisson=~s/valeurcaisson/Valeur manquante/;
		$caissson=~s/couleur/$couleurvaleursmanquantes/ ;
		$nouveaucalque.=$caissson."\n".$textecaisson."\n";
		}
	}

#Mettre tout dans un calque
$nouveaucalque="\n<g id=\"caissons\">\n".$nouveaucalque."<\/g>\n\n";

#3. Finalisation et ajout infos
#On finit par la coloration des surfaces et on en profite pour compléter les infos
open (F,"SurfaceCommunes.html"); #Fichier minimal pour le calque des surfaces à colorer (dépts, pays, etc.)
# Attention, une ligne par entité surfacique
# Chaque entité est simplissime. On demande juste une couleur: fill="blue" (peut être changée, complétée, etc.)
#Ex.: <path id="D95"   fill="blue" stroke-width="1"  stroke="rgb(0,0,0)"  d="M1620 833 L1617 833 ... z"/> 

#D'abord les infos complémentaires éventuelles
#On est ici brutal: si le fichier n'existe pas, le pgm fonctionnera quand même
open (K,"nomscommunes");
while (<K>)
	{
	chop;
	($dpt,$nomdpt)=split("\t");
	$info2{$dpt}=$nomdpt;
	}
close (K);
	
open (F2,">CarteFinale.html");
$infoinit="<g id =\"infosurface\" pointer-events=\"none\" font-size=\"50\" font-family=\"Helvetica\" visibility=\"hidden\">\n";
#Pour les infos 

while (<F>)
	{		
	#spécial communes: C\d+
	if (/<path id=\"(C\d+[A-Z]*\d*)([-\d+]*)\"/ || /<path id=\"([A-Z]+)([-\d+]*)\"/) #[-\d+] si plusieurs composantes conn: -1, -2 etc.
	#Ah, la Corse!
		{	
		$dpt=$1;		
		$dptsuite=$2;
		$infoligne1=$dpt." $info2{$dpt} taux: ".$covid{$dpt}."; pop: ".$popul{$dpt};
		$infoligne1=$dpt." $info2{$dpt} taux: ".$covid{$dpt} if  defined $centresabsents;
		$ajoutdpt=" onmouseover=\"document.getElementById('$dpt"."T').setAttribute('visibility','visible')\" onmouseout=\"document.getElementById('$dpt"."T').setAttribute('visibility','hidden')\" "; 
#On ajoute donc ce qui permet l'affichage en deux temps

$infoinit.="<g id =\"$dpt"."T\"  ><text  x=\"200\" y=\"400\"  style=\"font-size:40px; font-family:Helvetica\">$infoligne1<\/text><\/g>\n";
		if (! defined $covid{$dpt} || ($covid{$dpt}!~/\d/)) #On peut mieux faire...
			{
			$couleurtmp{$dpt}=$couleurvaleursmanquantes;
			}
		else
			{	
			foreach $s (0..$#seuils)
				{
				if ($covid{$dpt}<=$seuils[$#seuils-$s])
					{
					$couleurtmp{$dpt}=$couleurs[$#seuils-$s];
					}				
				}		
			if  ($covid{$dpt}>$seuils[$#seuils]) #on est près du max
				{
				$couleurtmp{$dpt}=$couleurs[$#seuils+1];
				}	
			}
		s/blue\"/$couleurtmp{$dpt}\" $ajoutdpt /; 
		}		
	if (/<\/svg>/)
		{$infoinit.="<\/g>\n";		
		$nouveaucalque.=$infoinit;
		s/$_/$nouveaucalque\n$calquecercle<\/svg>\n/;		
		}	
	print F2;	
	}
close (F); close (F2);	
