#!/usr/bin/perl
#use strict;
use warnings;

open (FICHIN, "hamlet.xml");

# hashtables et listes
my @list_acts=();  # index: $act_nb-1 => values: @list_scenes_in_act
my @list_scenes_in_act=();   # index:  $scene_nb-1 => values: %hash_scene
my %hash_scene=(); # keys: $perso  => values: nb_speak

# listes de personnages
my @play_personae=();   # list of personae
my @personae_keys=();   # list of hash keys
my @act_personae=();   # list of personae in act
my @scene_personae=();   # list of personae in scene
my @personae=();

# tags
my $ancrTitle = "TITLE";
my $ancrPlay = "PLAY";
my $ancrPerso = "PERSONA";
my $ancrAct = "ACT";
my $ancrScene = "SCENE";
my $ancrSpeak = "SPEAKER";
my $ancrDidasc = "STAGEDIR";

# variables
my $line;
my $title;
my $act_nb=0;
my $scene_nb=0;
my $total_scene_nb=0;
my $perso_nb;
my $speak_nb;
my $perso;
my $scene;
my $didascalie;
my $href = {};  # href will return HASH for scenes
my $lref = [];  # lref will return a list for each act
my $cle;
my $i=0;

while (<FICHIN>) {
    chomp;
 
    # title of the play:
    # d'abord la balise <PLAY>
    if($_ =~ /^<$ancrPlay>(.*)/){
        #sur la ligne suivante: les balises <TITLE>...</TITLE>
        $line = <FICHIN>;
        chomp($line);
	$line =~ /^<$ancrTitle>(.*)<\/$ancrTitle>$/;
        print "Title of the play: \"$1\" \n";
    }

    # list of personae
    if($_ =~ /^<$ancrPerso>(.*)<\/$ancrPerso>$/){
        $perso = $1;
        if ($perso !~ /,\s*[A-Z]/){ # pas de virgule suivie d'une majuscule
            push(@play_personae,$perso);
        }
        else {
	    # découpage selon les virgules suivies d'espaces 
            @personae = split(/,\s*/, $perso);
            for $perso (@personae){
		# substituer 'and ' par rien
		$perso =~ s/and //;
                push(@play_personae, $perso);                    
            }            
        }
    }

    # begin act
    if($_ =~ /^<$ancrAct>.*/){
        # reinitialisation pour les scenes
        $scene_nb =0;
        # reference vers nouvelle liste
        $lref=[];
        $act_nb++;
    }

    # begin scene
    if($_ =~ /^<$ancrScene>.*/){
        # reinitialisation liste personae 
	@scene_personae=();
        # reference vers nouvelle hashtable (Perso => nb de prises de parole)
	$href = {};
        $scene_nb++;
        $total_scene_nb++;
    }

    # 	personnages des didascalies <STAGEDIR>
    if($_ =~ /^<$ancrDidasc>(.*)<\/$ancrDidasc>$/){
        $didascalie = $1;

        # personnages, avec leur titre, en majuscules:
        # \b délimite les mots
        # maj. répétées, éventuellement suivi d'espaces puis de maj. répétées
        # /g pour trouver plusieurs occurrences et les afficher dans la boucle while
        while ($didascalie =~ /(\b[A-Z]+(\s+[A-Z]+)*\b)/g){
            $perso = $1;
            # perso en deux mots: on ne garde que le 2ème
            if ($perso =~ /\s+([A-Z]+)\b/){
                $href->{$1} = 0;
            }
            elsif ($perso ne "GHOST"){
                # $href adresse de la hashtable
                $href->{$perso} = 0;
            }
        }
    }

    # prise de parole
    if($_ =~/^<$ancrSpeak>(.*)<\/$ancrSpeak>$/){
	$perso = $1;
        # perso en deux mots: on ne garde que le 2ème
        if ($perso =~ /\s+([A-Z]+)\b/){
            $href->{$1}++;
        }
	elsif ($perso ne "All" and $perso ne "Prologue"){
            # $href adresse de la hashtable
            $href->{$perso}++ ;
	}       
    }
    
    # recherche de la phrase "To be or not to be"
    # \W : tout sauf un caractère de mot
    if ($_ =~ /^<LINE>(.*)<\/LINE>$/){
        if ($1 =~ /To\W+be\W+or\W+not\W+to\W+be/){
            print "\n\n TO BE OR NOT TO BE \n";
            print " -->> C'EST ICI: acte $act_nb scene $scene_nb \n";
        }
    }

    # end scene
    if($_ =~ /^<\/$ancrScene>.*/){
        print "\nacte ", $act_nb," scene ", $scene_nb, "\n";
        # @{$lref}: la liste dont l'adresse est $lref
        # ajout de la référence de la hashtable courante dans la liste
	push (@{$lref}, $href );
        # %{$href}: la hashtable dont l'adresse est $href 
	print "nb personae in scene $scene_nb: ", scalar(keys(%{$href})),"\n"; 
	print "personae in scene $scene_nb: ", join("-",keys(%{$href})), "\n";
	# affichage de la hashtable des prises de paroles
        foreach $cle (keys(%{$href})) {
            print "cle: $cle, valeur: $href->{$cle}\n";
        }
    }

    # end act
    if($_ =~ /^<\/$ancrAct>.*/){
        print "\n acte ", $act_nb, ": nb scene: ", $scene_nb, "\n";
        # ajout de la référence de la liste de scenes
        # dans la liste des actes
	push(@list_acts,$lref);
    }
}

close(FICHIN);


###############
### Affichage
###############
## Question 1:
print "\n\n 1) Affichage du nombre de personnages dans la pièce et de leurs noms:\n\n";
print "nombre de personnages dans la pièce:: ",scalar(@play_personae),"\n";

print "\n\n 1) Affichage du nombre d'actes, de scenes et de scenes/acte: \n";
print "nb actes: ", $act_nb,  "\n";
print "nb total de scenes: ", $total_scene_nb,  "\n";
print "nb de scenes par acts:\n";
for $lref (@list_acts){
    @list_scenes_in_act = @$lref;
    print "nb de scenes: ",scalar(@list_scenes_in_act),"\n";
}

## Question 2:

print "\n\n 2) Affichage du nombre de personnages par act (a) ou par scene (s): \n";
# lecture du choix de l'utilisateur:
my $enter = <STDIN>;
chomp $enter;
$enter =~ /^a|s$/ or die("Tapez a ou s");

$act_nb=1;
$scene_nb=1;

# par acte:
if ($enter eq "a"){
    print "\n\n Affichage du nombre de personnages par acte", "\n";
    for $lref (@list_acts) {
        print "ACT ",$act_nb,"\n";
        for $href (@$lref) {
            %hash_scene = %{$href};
            for $perso (keys(%hash_scene)){
                if ( "@act_personae" !~ /$perso/) {
                    push (@act_personae, $perso);
                } 
            }
        }
        print "nombre de personnages dans l'acte ", $act_nb++, ": ", scalar(@act_personae),"\n";
        print join (" ",@act_personae),"\n";
    }  
}

# par scene:
if ($enter eq "s"){
    print " Affichage du nombre de personnages par scene", "\n";
    for $lref (@list_acts) {
        print "ACT ",$act_nb++,"\n";
        $scene_nb=1;
        # @$lref: la liste des adresses de hashtables pour les scenes de l'acte courant  
        for $href (@$lref) {
            # %$href: une hashtable perso => nb prises de parole pour la scene courante
	    %hash_scene = %{$href};
            print "nb personae dans scene ",$scene_nb++,": ", scalar(keys(%hash_scene)),"\n";
	    print join (" ",keys(%hash_scene)),"\n";
        }
    }

}

## Question 3:

print "\n\n 3) Affichage des personnages par ordre alphabétique: \n";

# 1ère solution:
print "Les personnages de la liste <PERSONAE> dans l'ordre alphabétique:\n", join("\n", sort @play_personae),"\n";

# 2ème solution: 
print "\nLes personnages clés des tables de hash: ", "\n";
# construction de la liste de toutes les cles:
for $lref (@list_acts) {
    for $href (@$lref) {
        for $cle (keys(%{$href})){
            # ajout d'une clé non déjà présente
            if ("@personae_keys" !~ $cle){
                push (@personae_keys, $cle);
            }
        }
    }
}


## Question 4:
print "\n\n 4) Affichage du nombre de fois où chaque personnage prend la parole: ", "\n";
for $perso (@personae_keys){
    $speak_nb = 0;
    for $lref (@list_acts) {
        for $href (@$lref) {
            if (exists($href->{$perso})){
                $speak_nb += $href->{$perso};
            }
        }
    }
    if ($speak_nb != 0){
        print "$perso parle $speak_nb fois\n";
    }
    else {
        print "  Personnage muet: $perso\n";
    }
        
}
        
## Question 5:
print "\n\n 5) Affichage du nombre de scenes où Hamlet parle, où Hamlet et Ophélia parlent: \n";
$scene_nb=0;
$i = 0;
for $lref (@list_acts) {
    for $href (@$lref) {
        if (exists($href->{"HAMLET"})){
            $scene_nb++;
            if (exists($href->{"OPHELIA"})){
                $i++;
            }            
        }
    }
}
print "Hamlet parle dans $scene_nb scenes \n";
print "Hamlet et Ophélia parlent ensemblent dans $i scenes \n";


## Question 6:
print "\n\n 6) Quand (acte et scène) Hamlet prononce t-il la célèbre réplique : “To be, or not to be : that is the question” ? \n";


