line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
7
|
use strict; use warnings; |
|
1
|
|
|
1
|
|
2
|
|
|
1
|
|
|
|
|
32
|
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
2
|
|
|
|
|
|
|
package RosettaCode::Task; |
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
5
|
use IO::All; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
5
|
1
|
|
|
1
|
|
55
|
use Carp 'confess'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
56
|
|
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
7
|
use Mo qw'build default xxx'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
extends 'RosettaCode'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
has name => ''; |
12
|
|
|
|
|
|
|
has path => ''; |
13
|
|
|
|
|
|
|
has url => ''; |
14
|
|
|
|
|
|
|
has meta => {}; |
15
|
|
|
|
|
|
|
has lang => ''; |
16
|
|
|
|
|
|
|
has prog => []; |
17
|
|
|
|
|
|
|
has tasks => {}; |
18
|
|
|
|
|
|
|
has langs => {}; |
19
|
|
|
|
|
|
|
has bot => ''; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub fetch_task { |
22
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
23
|
0
|
|
|
|
|
|
my $file = io->file("Cache/Task/$self->{path}")->utf8; |
24
|
|
|
|
|
|
|
|
25
|
0
|
0
|
0
|
|
|
|
if ($file->exists and time - $file->mtime < $self->CACHE_TIME) { |
26
|
0
|
|
|
|
|
|
$self->text($file->all); |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
else { |
29
|
0
|
|
|
|
|
|
my $text = $self->get_text($self->name); |
30
|
0
|
|
|
|
|
|
$file->assert->print($text); |
31
|
0
|
|
|
|
|
|
$self->text($text); |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub build_task { |
36
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
37
|
|
|
|
|
|
|
|
38
|
0
|
|
|
|
|
|
my $name = $self->name; |
39
|
0
|
|
|
|
|
|
my $text = $self->text; |
40
|
0
|
|
|
|
|
|
$text =~ s/\r//g; |
41
|
0
|
0
|
|
|
|
|
$text =~ s/\n?\z/\n/ if length $text; |
42
|
|
|
|
|
|
|
|
43
|
0
|
|
|
|
|
|
$self->log("TASK $name"); |
44
|
0
|
|
|
|
|
|
my @sections = split /^==+ ?\{\{header\|(.+?)\}\}.*\n/m, $text; |
45
|
0
|
0
|
0
|
|
|
|
if (@sections < 3 or $text !~ /<syntaxhighlight/) { |
46
|
0
|
|
|
|
|
|
$self->log("ERROR: No implementations for '$name'"); |
47
|
|
|
|
|
|
|
} |
48
|
0
|
|
|
|
|
|
my $head_section = shift @sections; |
49
|
0
|
0
|
|
|
|
|
if (@sections % 2) { |
50
|
0
|
|
|
|
|
|
$self->log("ERROR: Bad task page for '$name'"); |
51
|
0
|
|
|
|
|
|
return; |
52
|
|
|
|
|
|
|
} |
53
|
0
|
|
|
|
|
|
$self->parse_head_section($head_section); |
54
|
0
|
|
|
|
|
|
my $path = $self->path; |
55
|
0
|
|
|
|
|
|
my $file = lc($path); |
56
|
|
|
|
|
|
|
|
57
|
0
|
|
|
|
|
|
while (@sections) { |
58
|
0
|
|
|
|
|
|
my ($lang, $text) = splice(@sections, 0, 2); |
59
|
0
|
|
|
|
|
|
$lang =~ s/\|.*//; |
60
|
0
|
|
|
|
|
|
$self->log(" $lang"); |
61
|
0
|
|
|
|
|
|
my $info = $self->langs->{lc $lang}; |
62
|
0
|
0
|
|
|
|
|
if (not defined $info) { |
63
|
0
|
|
|
|
|
|
$self->log("ERROR: Unknown lang '$lang' ($name)"); |
64
|
0
|
|
|
|
|
|
next; |
65
|
|
|
|
|
|
|
} |
66
|
0
|
|
|
|
|
|
$self->parse_task_lang_section($text, $lang); |
67
|
0
|
|
|
|
|
|
my $programs = $self->prog; |
68
|
0
|
0
|
|
|
|
|
next unless @$programs; |
69
|
0
|
|
|
|
|
|
my $lang_path = $info->{path}; |
70
|
0
|
|
|
|
|
|
my $ext = $info->{ext}; |
71
|
0
|
|
|
|
|
|
my $source = "Lang/$lang_path/$path"; |
72
|
0
|
|
|
|
|
|
my $target = "../../Task/$path/$lang_path"; |
73
|
0
|
|
|
|
|
|
$self->write_symlink($source, $target, 2); |
74
|
0
|
0
|
|
|
|
|
if (@$programs == 1) { |
75
|
0
|
|
|
|
|
|
$self->write_file( |
76
|
|
|
|
|
|
|
"Task/$path/$lang_path/$file.$ext", |
77
|
|
|
|
|
|
|
$programs->[0], |
78
|
|
|
|
|
|
|
2, |
79
|
|
|
|
|
|
|
); |
80
|
0
|
|
|
|
|
|
next; |
81
|
|
|
|
|
|
|
} |
82
|
0
|
|
|
|
|
|
my $count = 1; |
83
|
0
|
|
|
|
|
|
for (@$programs) { |
84
|
0
|
|
|
|
|
|
$self->write_file( |
85
|
|
|
|
|
|
|
"Task/$path/$lang_path/$file-$count.$ext", |
86
|
|
|
|
|
|
|
$_, |
87
|
|
|
|
|
|
|
2, |
88
|
|
|
|
|
|
|
); |
89
|
0
|
|
|
|
|
|
$count++; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
0
|
|
|
|
|
|
$self->meta->{from} = "http://rosettacode.org/wiki/$self->{url}"; |
94
|
|
|
|
|
|
|
$self->write_file( |
95
|
|
|
|
|
|
|
"Task/$path/00-TASK.txt", |
96
|
|
|
|
|
|
|
delete $self->meta->{description}, |
97
|
0
|
|
|
|
|
|
1, |
98
|
|
|
|
|
|
|
); |
99
|
|
|
|
|
|
|
$self->dump_file( |
100
|
|
|
|
|
|
|
"Task/$path/00-META.yaml", |
101
|
|
|
|
|
|
|
$self->meta, |
102
|
|
|
|
|
|
|
1, |
103
|
0
|
0
|
|
|
|
|
) if %{$self->meta}; |
|
0
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub parse_head_section { |
107
|
0
|
|
|
0
|
0
|
|
my ($self, $text) = @_; |
108
|
0
|
|
|
|
|
|
$_ = $text; |
109
|
0
|
|
|
|
|
|
my $meta = $self->meta({}); |
110
|
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
|
my $length = length; |
112
|
0
|
|
|
|
|
|
while (1) { |
113
|
0
|
|
|
|
|
|
s/\A<!--.*-->\s*//; |
114
|
0
|
|
|
|
|
|
s/\A\[\[File:.*\s*//; |
115
|
0
|
|
|
|
|
|
s/\A\{\{alertbox\|.*\n\s*//; |
116
|
0
|
|
|
|
|
|
s/\A\{\{[Cc]larified-review\}\}\s*//; |
117
|
0
|
|
|
|
|
|
s/\A\{\{[Cc]larify task\}\}\s*//; |
118
|
0
|
|
|
|
|
|
s/\A\{\{[Oo]mit from\|.*\}\}\s*//; |
119
|
0
|
|
|
|
|
|
s/\A\[\[[Ff]ile:.*\]\]\s*//; |
120
|
0
|
|
|
|
|
|
s/\A\{\{[Ww]ikipedia[^\}]*\}\}\s*//; |
121
|
|
|
|
|
|
|
|
122
|
0
|
0
|
|
|
|
|
if (s/\A\s*\{\{requires\|(\w[\w ]*)\}\}\s*//) { |
123
|
0
|
|
0
|
|
|
|
$meta->{requires} ||= []; |
124
|
0
|
|
|
|
|
|
push @{$meta->{requires}}, $1; |
|
0
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
} |
126
|
0
|
0
|
|
|
|
|
if (s/\A\s*\[\[Category: *(\w[\w ]*)\]\]\s*//) { |
127
|
0
|
|
0
|
|
|
|
$meta->{category} ||= []; |
128
|
0
|
|
|
|
|
|
push @{$meta->{category}}, $1; |
|
0
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
} |
130
|
0
|
0
|
|
|
|
|
if (s/\A\{\{(?:[Dd]raft\s+)?[Tt]ask(?:\|([^\}]*?))?\}\}\s*//s) { |
131
|
0
|
0
|
|
|
|
|
$meta->{note} = $1 if $1; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
0
|
0
|
|
|
|
|
last if length == $length; |
135
|
0
|
|
|
|
|
|
$length = length; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# Get task description text: |
139
|
0
|
0
|
|
|
|
|
$meta->{description} = $_ if $_; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub parse_task_lang_section { |
143
|
0
|
|
|
0
|
0
|
|
my ($self, $text, $lang) = @_; |
144
|
0
|
|
|
|
|
|
local $_ = $text; |
145
|
0
|
|
|
|
|
|
$self->lang($lang); |
146
|
0
|
|
|
|
|
|
my $programs = $self->prog([]); |
147
|
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
while (s/<syntaxhighlight.*?>(.*?)(?:<\/syntaxhighlight>|\z)//si) { |
149
|
0
|
|
|
|
|
|
my $program = $1; |
150
|
0
|
|
|
|
|
|
$program =~ s/\A\s*\n//; |
151
|
0
|
|
|
|
|
|
$program =~ s/ *$//mg; |
152
|
0
|
0
|
|
|
|
|
$program =~ s/\n*\z/\n/ if length($program); |
153
|
0
|
|
|
|
|
|
push @$programs, $program; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
1; |