1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| #!/usr/bin/perl
use strict;
use warnings;
use Carp;
use List::Util qw(sum);
{
my $fsm_state;
# Méthode d'initialisation de la machine d'état (définition du premier état)
sub fsm_start {
my $fsm = shift;
$fsm_state = shift;
croak "Un hashage de définition de machine d'état doit être fourni\n" if !%$fsm;
croak "Un état de démarrage doit être spécifié parmi les suivants".(join ", ", keys %$fsm)."\n"
if !defined $fsm_state || !exists $fsm->{$fsm_state};
}
# Méthode d'exécution de la machine d'état (calcule l'état suivant selon l'état courant)
sub fsm {
my $fsm = shift;
croak "fsm_start doit être appelé avec un état initial valide avant d'exécuter cette fonction\n"
if !defined $fsm_state;
confess "Erreur pannique, l'état courant [$fsm_state] n'existe pas dans la machine d'état"
if !exists $fsm->{$fsm_state};
# changer d'état, sauf si l'état est indéfini ou vide
my $next_state = $fsm->{$fsm_state}->() || $fsm_state;
warn "$fsm_state => $next_state\n";
croak "Le nouvel état proposé depuis l'état [$fsm_state] n'existe pas dans la machine d'état ([".($next_state || "aucun")."])\n"
if !exists $fsm->{$next_state};
$fsm_state = $next_state;
}
}
my @req = ();
my ($req, $val);
# Fonction d'affichage des requètes
sub affiche {
my ($request) = @_;
print join(" ", @{$_}), "\n" foreach @$request;
@$request = ();
}
# Fonction de calcul du cumul de temps des requètes
sub tps {
my ($request) = @_;
# retourner la somme des valeurs (2e élément de chaque requete)
my $tps = sum(map $_->[1], @$request);
@$request = ();
return $tps;
}
# Définition de état de la machine d'état (chaque valeur est une fermeture qui retourne le nouvel état)
my %fsm = ( "init" => sub {
my $next_state;
if ($req eq "req1") {
$next_state = "conn_1";
}
elsif ($req eq "req0") {
$next_state = "deco_1";
}
elsif ($req eq "req5") {
$next_state = "other_1";
}
else {
affiche(\@req);
}
$next_state;
},
"conn_1" => sub {
my $next_state;
if ($req eq "req2") {
$next_state = "conn_2";
}
else {
affiche(\@req);
}
$next_state;
},
"conn_2" => sub {
if ($req eq "req3") {
# On remplace les requètes par une requète connexion
@req = ([ "connexion ", tps(\@req) ]);
}
affiche(\@req);
"init";
},
"deco_1" => sub {
if ($req eq "req6") {
# On remplace les requètes par une requète deconnexion
@req = ([ "deconnexion ", tps(\@req) ]);
}
affiche(\@req);
"init";
},
"other_1" => sub {
my $next_state = "init";
if ($req eq "req8") {
$next_state = "rech";
}
else {
if ($req eq "req3") {
# On remplace les requètes par une requète accueil
@req = ([ "accueil", tps(\@req) ]);
}
affiche(\@req);
}
$next_state;
},
"rech" => sub {
if ($req eq "req9") {
# On remplace les requètes par une requète recherche
@req = ([ "recherche ", tps(\@req) ]);
}
affiche(\@req);
"init";
},
);
fsm_start(\%fsm, "init");
while (<STDIN>) {
($req, $val) = split /\s+/;
push @req, [ $req, $val ];
fsm(\%fsm);
} |
Partager