Archived
1
0
Fork 0

New parser for traces

This commit is contained in:
Mercier Pierre-Olivier 2013-11-11 16:09:53 +01:00
commit 15f89a5e39
3 changed files with 238 additions and 133 deletions

View file

@ -111,7 +111,7 @@ sub insert ($$$)
$self->{ids}{$_[0]} = $_[1]; $self->{ids}{$_[0]} = $_[1];
} }
sub fill ($$) sub fill
{ {
my $self = shift; my $self = shift;
my $ids = shift; my $ids = shift;

View file

@ -9,16 +9,13 @@ use Carp;
use utf8; use utf8;
use open qw(:encoding(UTF-8) :std); use open qw(:encoding(UTF-8) :std);
use XML::LibXML; use XML::LibXML;
use XML::SAX::ParserFactory;
sub new sub new
{ {
my $class = shift; my $class = shift;
my $self = { my $self = {
ids => {},
infos => {}, infos => {},
comments => {}, groups => [],
who => {},
}; };
bless $self, $class; bless $self, $class;
@ -33,10 +30,47 @@ sub _initialize ($$)
{ {
my $self = shift; my $self = shift;
my $sax_handler = TraceHandler->new($self); my $dom = XML::LibXML->load_xml(string => shift);
my $parser = XML::SAX::ParserFactory->parser( Handler => $sax_handler ); $self->{groups} = $self->parseTrace($dom->documentElement());
$self->{type} = $dom->documentElement()->getAttribute("type") // "mill";
$self->{version} = $dom->documentElement()->getAttribute("version") // 1;
}
$parser->parse_file(shift); sub parseTrace($$)
{
my $self = shift;
my $tree = shift;
my $ret = [];
foreach my $node ($tree->childNodes())
{
if ($node->nodeName eq "info")
{
my $tmp = $node->textContent;
chomp($tmp);
$self->{infos}{ $node->getAttribute("name") } = $tmp;
}
elsif ($node->nodeName eq "group")
{
my $g = Trace::Group->new(
$node->getAttribute("id"),
$node->getAttribute("name")
);
$g->append(@{ $self->parseTrace($node) });
push @$ret, $g;
}
elsif ($node->nodeName eq "eval")
{
my $e = Trace::Eval->new(
$node->getAttribute("id"),
$node->getAttribute("type"),
$node
);
push @$ret, $e;
}
}
return $ret;
} }
sub getVersion ($) sub getVersion ($)
@ -63,64 +97,63 @@ sub getInfos ($)
return $self->{infos}; return $self->{infos};
} }
sub getComment ($$) sub getIds
{ {
my $self = shift; my $self = shift;
return $self->{comments}{$_[0]}; my $login = shift;
my %ids;
foreach my $group (@{ $self->{groups} })
{
my %tmp = $group->getIds($login);
while (my ($key, $value) = each %tmp)
{
%ids{$key} = $value;
}
}
return %ids;
} }
sub getComments ($) sub getValue
{ {
my $self = shift; my $self = shift;
return $self->{comments}; my $id = shift;
my $login = shift;
my $value = 0;
foreach my $group (@{ $self->{groups} })
{
$value += $group->getValue($id, $login);
}
return $value;
} }
sub getWho ($$) sub getWho ($$)
{ {
my $self = shift; my $self = shift;
return $self->{who}{$_[0]}; return $self->getWhos()->{$_[0]};
} }
sub getFirstWho ($) sub getFirstWho ($)
{ {
my $self = shift; my $self = shift;
return $self->getWhos()->{def1_end_group};
return $self->{who}{def1_end_group};
} }
sub getWhos ($) sub getWhos
{ {
my $self = shift; my $self = shift;
return $self->{who}; my $ret = {};
}
sub getValue ($$) foreach my $group (@{ $self->{groups} })
{ {
my $self = shift; my $whos = $group->getWhos();
return $self->{ids}{$_[0]}; foreach my $who (keys %{ $whos }) {
} $ret->{ $who } = $whos->{$who};
}
}
sub getIds ($) return $ret;
{
my $self = shift;
return $self->{ids};
}
sub addId($$;$)
{
my $self = shift;
my $key = shift;
my $value = shift // 1;
$self->{ids}{$key} = $value;
}
sub delId($$)
{
my $self = shift;
my $key = shift;
delete $self->{ids}{$key};
} }
sub toString ($;$) sub toString ($;$)
@ -153,23 +186,20 @@ sub toString ($;$)
} }
package TraceHandler; package Trace::Group;
use v5.10.1;
use strict;
use warnings;
use Carp; use Carp;
use constant NO_ID_VALUE => "__#";
sub new ($$) sub new ($$)
{ {
my $class = shift; my $class = shift;
my $self = { my $self = {
groups => [], id => shift,
parsed => shift, name => shift,
inComment => "", groups => []
inEval => "",
inInfo => "",
inValue => "",
inWho => "",
values => ""
}; };
bless $self, $class; bless $self, $class;
@ -177,113 +207,188 @@ sub new ($$)
return $self; return $self;
} }
sub start_element sub append ($@)
{ {
my ($self, $element) = @_; my $self = shift;
if ($element->{Name} eq "trace") { push @{ $self->{groups} }, @_;
$self->{parsed}{version} = $element->{Attributes}{"{}version"}{Value};
$self->{parsed}{type} = $element->{Attributes}{"{}type"}{Value};
}
elsif ($element->{Name} eq "info") {
$self->{inInfo} = $element->{Attributes}{"{}name"}{Value};
$self->{parsed}{infos}{ $self->{inInfo} } = 0;
$self->{values} = "";
}
elsif ($element->{Name} eq "eval") {
my $tmp = $element->{Attributes}{"{}id"}{Value};
if ($tmp) {
$self->{inEval} = $tmp;
$self->{parsed}{ids}{ $self->{inEval} } = 0;
}
}
elsif ($element->{Name} eq "comment" && $self->{inEval}) {
$self->{inComment} = $self->{inEval};
$self->{values} = "";
}
elsif ($element->{Name} eq "who" && $self->{inEval}) {
$self->{inWho} = $self->{inEval};
$self->{values} = "";
}
elsif ($element->{Name} eq "value") {
if ($element->{Attributes}{"{}id"}{Value}) {
$self->{inValue} = $element->{Attributes}{"{}id"}{Value};
} else {
$self->{inValue} = NO_ID_VALUE;
}
$self->{values} = "";
}
elsif ($element->{Name} eq "group")
{
push @{ $self->{groups} }, ($element->{Attributes}{"{}id"}{Value} // "");
}
elsif ($element->{Name} ne "name" && $element->{Name} ne "statut" && $element->{Name} ne "status" && $element->{Name} ne "log") {
croak "Not a valid trace XML: unknown tag ".$element->{Name};
}
} }
sub characters sub getIds
{ {
my ($self, $characters) = @_; my $self = shift;
my $login = shift;
if ($self->{inValue} || $self->{inInfo} || $self->{inComment} || $self->{inWho}) { my %ids;
$self->{values} .= $characters->{Data}; foreach my $group (@{ $self->{groups} })
}
}
sub end_element
{
my ($self, $element) = @_;
if ($element->{Name} eq "value")
{ {
if ($self->{values} =~ /([-+]?[0-9]+(.[0-9]+)?)/) my %tmp = $group->getIds($login);
while (($key, $value) = each %tmp)
{ {
$self->{parsed}{ids}{ $self->{inEval} } += $1; %ids{$key} = $value;
if ($self->{inValue} ne NO_ID_VALUE and $1) { }
$self->{parsed}{ids}{ $self->{inValue} } = $1; }
}
if ($self->{groups}) { %ids{ $self->{id} } = $self->getValue($self->{id}, $login);
my $key = @{ $self->{groups} }[$#{ $self->{groups} }];
$self->{parsed}{ids}{ $key } += $1; return %ids;
}
sub getValue
{
my $self = shift;
my $id = shift // $self->{id};
my $login = shift
if ($id eq $self->{id})
{
my $value = 0;
foreach my $group (@{ $self->{groups} })
{
$value += $group->getValue(undef, $login);
}
return $value;
}
else
{
my $value = 0;
foreach my $group (@{ $self->{groups} })
{
$value += $group->getValue($id, $login);
}
return $value;
}
}
sub getWhos
{
my $self = shift;
my $ret = {};
foreach my $group (@{ $self->{groups} })
{
my $whos = $group->getWhos();
foreach my $who (keys %{ $whos }) {
$ret->{ $who } = $whos->{$who};
}
}
return $ret;
}
package Trace::Eval;
use v5.10.1;
use strict;
use warnings;
use Carp;
sub new ($$;$)
{
my $class = shift;
my $self = {
id => shift,
type => shift // "test",
values => {},
logs => {},
};
bless $self, $class;
if ($#_ >= 0) {
$self->parseEval(@_);
}
return $self;
}
sub parseEval
{
my $self = shift;
my $tree = shift;
foreach my $node ($tree->childNodes())
{
my $val = $node->textContent;
chomp($val);
if ($node->nodeName eq "value")
{
my $key;
if ($node->hasAttribute("id")) {
$key = $node->getAttribute("id");
} else {
$key = "";
} }
$self->{values}{ $key } = 0 if (!exists $self->{values}{ $key });
$self->{values}{ $key } += $val;
} }
$self->{inValue} = ""; elsif ($node->nodeName eq "name")
} {
elsif ($element->{Name} eq "eval") $self->{name} = $val;
{
# Remove empty identifier
delete $self->{parsed}{ids}{ $self->{inEval} } if (!$self->{parsed}{ids}{ $self->{inEval} });
$self->{inEval} = "";
}
elsif ($element->{Name} eq "comment")
{
if ($self->{values} =~ /([^\s].*[^\s]|[^\s])/) {
$self->{parsed}{comments}{ $self->{inComment} } = $1;
} }
$self->{inComment} = ""; elsif ($node->nodeName eq "status")
} {
elsif ($element->{Name} eq "who") $self->{status} = $val;
{
if ($self->{values} =~ /([^\s].*[^\s]|[^\s])/) {
$self->{parsed}{who}{ $self->{inWho} } = $1;
} }
$self->{inComment} = ""; elsif ($node->nodeName eq "log")
} {
elsif ($element->{Name} eq "info") my $key = $node->getAttribute("type") // "stdout";
{
if ($self->{values} =~ /([^\s].*[^\s]|[^\s])/) { $self->{logs}{ $key } = $val;
$self->{parsed}{infos}{ $self->{inInfo} } = $1; }
elsif ($node->nodeName eq "who")
{
$self->{who} = {
login => $val,
type => $node->getAttribute("type") // "login"
};
} }
$self->{inInfo} = "";
} }
elsif ($element->{Name} eq "group") }
sub getIds
{
my $self = shift;
my $login = shift;
my %ids;
if (!$login || $self->{who}{type} eq "group" || $self->{who}{login} eq $login)
{ {
my $key = pop @{ $self->{groups} }; while (my ($key, $value) = each %{ $self->{who}{values} })
# Remove empty identifier {
delete $self->{parsed}{ids}{ $key } if ($key && !$self->{parsed}{ids}{ $key }); %ids{$key} = $value if ($key);
}
} }
%ids{ $self->{id} } = $self->getValue($self->{id}, $login);
return %ids;
}
sub getValue
{
my $self = shift;
my $id = shift // $self->{id};
my $login = shift;
my $value = 0;
if (!$login || $self->{who}{type} eq "group" || $self->{who}{login} eq $login)
{
foreach my $key (%{ $self->{values} })
{
$value += $self->{values}{$key} if ($id eq $self->{id} || !$key || $key eq $id);
}
}
return $value;
}
sub getWhos
{
my $self = shift;
return { $self->{id} => $self->{who} };
} }
1; 1;

View file

@ -133,7 +133,7 @@ sub grades_generate
if (-f "$basedir/$tr_file") if (-f "$basedir/$tr_file")
{ {
open my $xmltrace, "<", "$basedir/$tr_file" or croak "$tr_file: $!"; open my $xmltrace, "<", "$basedir/$tr_file" or die "$tr_file: $!";
binmode $xmltrace; binmode $xmltrace;
my $trace = Trace->new($xmltrace); my $trace = Trace->new($xmltrace);
close $xmltrace; close $xmltrace;