Skip to content

Commit 2d2c709

Browse files
authored
Merge pull request #924 from drgrice1/generate-release-workflow
Create a workflow that generates an OPL META release.
2 parents 1ef85ff + 8e6b2f5 commit 2d2c709

File tree

4 files changed

+1174
-0
lines changed

4 files changed

+1174
-0
lines changed

Diff for: .github/workflows/bin/Tags.pm

+226
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
################################################################################
2+
# WeBWorK Online Homework Delivery System
3+
# Copyright © 2000-2022 The WeBWorK Project, https://github.com/openwebwork
4+
#
5+
# This program is free software; you can redistribute it and/or modify it under
6+
# the terms of either: (a) the GNU General Public License as published by the
7+
# Free Software Foundation; either version 2, or (at your option) any later
8+
# version, or (b) the "Artistic License" which comes with this package.
9+
#
10+
# This program is distributed in the hope that it will be useful, but WITHOUT
11+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12+
# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
13+
# Artistic License for more details.
14+
################################################################################
15+
16+
package Tags;
17+
use base qw(Exporter);
18+
19+
use strict;
20+
use warnings;
21+
22+
use Carp;
23+
use IO::File;
24+
25+
our @EXPORT = ();
26+
our @EXPORT_OK = qw();
27+
28+
use constant BASIC =>
29+
qw(DBsubject DBchapter DBsection Date Institution Author MLT MLTleader Level Language Static MO Status);
30+
use constant NUMBERED => qw(TitleText AuthorText EditionText Section Problem);
31+
32+
# KEYWORDS and RESOURCES are treated specially since each takes a list of values
33+
34+
my $basics = join('|', BASIC);
35+
my $re = qr/#\s*\b($basics)\s*\(\s*'?(.*?)'?\s*\)\s*$/;
36+
37+
sub keywordcleaner {
38+
my $string = shift;
39+
my @spl1 = split /,/, $string;
40+
return (@spl1);
41+
}
42+
43+
# Set a tag with a value
44+
sub maybenewtext {
45+
my $textno = shift;
46+
my $textinfo = shift;
47+
return $textinfo if defined($textinfo->[ $textno - 1 ]);
48+
49+
$textinfo->[ $textno - 1 ] = {
50+
TitleText => '',
51+
AuthorText => '',
52+
EditionText => '',
53+
section => '',
54+
chapter => '',
55+
problems => []
56+
};
57+
return $textinfo;
58+
}
59+
60+
sub gettextnos {
61+
my $textinfo = shift;
62+
return grep { defined $textinfo->[$_] } (0 .. (scalar(@{$textinfo}) - 1));
63+
}
64+
65+
sub tidytextinfo {
66+
my $self = shift;
67+
my @textnos = gettextnos($self->{textinfo});
68+
my $ntxts = scalar(@textnos);
69+
if ($ntxts and ($ntxts - 1) != $textnos[-1]) {
70+
$self->{modified} = 1;
71+
my @tmptexts = grep { defined $_ } @{ $self->{textinfo} };
72+
$self->{textinfo} = \@tmptexts;
73+
}
74+
}
75+
76+
# name is a path
77+
sub new {
78+
my $class = shift;
79+
my $name = shift;
80+
my $self = {};
81+
82+
$self->{isplaceholder} = 0;
83+
$self->{modified} = 0;
84+
my $lasttag = 1;
85+
86+
my ($text, $edition, $textauthor, $textsection, $textproblem);
87+
my $textno;
88+
my $textinfo = [];
89+
90+
open(IN, '<:encoding(UTF-8)', "$name") or die "can not open $name: $!";
91+
if ($name !~ /pg$/ && $name !~ /\.pg\.[-a-zA-Z0-9_.@]*\.tmp$/) {
92+
warn "Not a pg file"; #print caused trouble with XMLRPC
93+
$self->{file} = undef;
94+
bless($self, $class);
95+
return $self;
96+
}
97+
my $lineno = 0;
98+
$self->{file} = $name;
99+
100+
# Initialize some values
101+
for my $tagname (BASIC) {
102+
$self->{$tagname} = '';
103+
}
104+
$self->{keywords} = [];
105+
$self->{resources} = [];
106+
107+
while (<IN>) {
108+
$lineno++;
109+
eval {
110+
SWITCH: {
111+
if (/#\s*\bKEYWORDS\((.*)\)/i) {
112+
113+
my @keyword = keywordcleaner($1);
114+
@keyword = grep { not /^\s*'?\s*'?\s*$/ } @keyword;
115+
$self->{keywords} = [@keyword];
116+
$lasttag = $lineno;
117+
last SWITCH;
118+
}
119+
if (/#\s*\bRESOURCES\((.*)\)/i) {
120+
my @resc = keywordcleaner($1);
121+
s/["'\s]*$//g for (@resc);
122+
s/^["'\s]*//g for (@resc);
123+
@resc = grep { not /^\s*'?\s*'?\s*$/ } @resc;
124+
$self->{resources} = [@resc];
125+
$lasttag = $lineno;
126+
last SWITCH;
127+
}
128+
if (/$re/) { # Checks all other un-numbered tags
129+
my $tmp1 = $1;
130+
my $tmp = $2;
131+
$tmp =~ s/\s+$//;
132+
$tmp =~ s/^\s+//;
133+
$self->{$tmp1} = $tmp;
134+
$lasttag = $lineno;
135+
last SWITCH;
136+
}
137+
138+
if (/#\s*\bTitleText(\d+)\(\s*'?(.*?)'?\s*\)/) {
139+
$textno = $1;
140+
$text = $2;
141+
$text =~ s/'/\'/g;
142+
if ($text =~ /\S/) {
143+
$textinfo = maybenewtext($textno, $textinfo);
144+
$textinfo->[ $textno - 1 ]->{TitleText} = $text;
145+
}
146+
$lasttag = $lineno;
147+
last SWITCH;
148+
}
149+
if (/#\s*\bEditionText(\d+)\(\s*'?(.*?)'?\s*\)/) {
150+
$textno = $1;
151+
$edition = $2;
152+
$edition =~ s/'/\'/g;
153+
if ($edition =~ /\S/) {
154+
$textinfo = maybenewtext($textno, $textinfo);
155+
$textinfo->[ $textno - 1 ]->{EditionText} = $edition;
156+
}
157+
$lasttag = $lineno;
158+
last SWITCH;
159+
}
160+
if (/#\s*\bAuthorText(\d+)\(\s*'?(.*?)'?\s*\)/) {
161+
$textno = $1;
162+
$textauthor = $2;
163+
$textauthor =~ s/'/\'/g;
164+
if ($textauthor =~ /\S/) {
165+
$textinfo = maybenewtext($textno, $textinfo);
166+
$textinfo->[ $textno - 1 ]->{AuthorText} = $textauthor;
167+
}
168+
$lasttag = $lineno;
169+
last SWITCH;
170+
}
171+
if (/#\s*\bSection(\d+)\(\s*'?(.*?)'?\s*\)/) {
172+
$textno = $1;
173+
$textsection = $2;
174+
$textsection =~ s/'/\'/g;
175+
$textsection =~ s/[^\d\.]//g;
176+
if ($textsection =~ /\S/) {
177+
$textinfo = maybenewtext($textno, $textinfo);
178+
if ($textsection =~ /(\d*?)\.(\d*)/) {
179+
$textinfo->[ $textno - 1 ]->{chapter} = $1;
180+
$textinfo->[ $textno - 1 ]->{section} = $2;
181+
} else {
182+
$textinfo->[ $textno - 1 ]->{chapter} = $textsection;
183+
$textinfo->[ $textno - 1 ]->{section} = -1;
184+
}
185+
}
186+
$lasttag = $lineno;
187+
last SWITCH;
188+
}
189+
if (/#\s*\bProblem(\d+)\(\s*(.*?)\s*\)/) {
190+
$textno = $1;
191+
$textproblem = $2;
192+
$textproblem =~ s/\D/ /g;
193+
my @textproblems = (-1);
194+
@textproblems = split /\s+/, $textproblem;
195+
@textproblems = grep { $_ =~ /\S/ } @textproblems;
196+
if (scalar(@textproblems) or defined($textinfo->[$textno])) {
197+
@textproblems = (-1) unless (scalar(@textproblems));
198+
$textinfo = maybenewtext($textno, $textinfo);
199+
$textinfo->[ $textno - 1 ]->{problems} = \@textproblems;
200+
}
201+
$lasttag = $lineno;
202+
last SWITCH;
203+
}
204+
}
205+
};
206+
warn "error reading problem $name $!, $@ " if $@;
207+
}
208+
$self->{textinfo} = $textinfo;
209+
210+
if (defined($self->{DBchapter}) and $self->{DBchapter} eq 'ZZZ-Inserted Text') {
211+
$self->{isplaceholder} = 1;
212+
}
213+
214+
$self->{lasttagline} = $lasttag;
215+
bless($self, $class);
216+
$self->tidytextinfo();
217+
return $self;
218+
}
219+
220+
sub istagged {
221+
my $self = shift;
222+
return 1 if (defined($self->{DBsubject}) and $self->{DBsubject} and (not $self->{isplaceholder}));
223+
return 0;
224+
}
225+
226+
1;

Diff for: .github/workflows/bin/generate-OPL-set-def-lists.pl

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/env perl
2+
################################################################################
3+
# WeBWorK Online Homework Delivery System
4+
# Copyright &copy; 2000-2022 The WeBWorK Project, https://github.com/openwebwork
5+
#
6+
# This program is free software; you can redistribute it and/or modify it under
7+
# the terms of either: (a) the GNU General Public License as published by the
8+
# Free Software Foundation; either version 2, or (at your option) any later
9+
# version, or (b) the "Artistic License" which comes with this package.
10+
#
11+
# This program is distributed in the hope that it will be useful, but WITHOUT
12+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13+
# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
14+
# Artistic License for more details.
15+
################################################################################
16+
17+
use strict;
18+
use warnings;
19+
20+
use File::Find;
21+
use JSON;
22+
23+
my $libraryRoot = "$ENV{GITHUB_WORKSPACE}/OpenProblemLibrary";
24+
my $contribRoot = "$ENV{GITHUB_WORKSPACE}/Contrib";
25+
26+
# Search the OPL directory for set definition files.
27+
my @opl_set_defs;
28+
find(
29+
{
30+
wanted => sub {
31+
push @opl_set_defs, $_ =~ s|^$libraryRoot/?|Library/|r if m|/set[^/]*\.def$|;
32+
},
33+
follow_fast => 1,
34+
no_chdir => 1
35+
},
36+
$libraryRoot
37+
);
38+
39+
# Search the Contrib directory for set definition files.
40+
my @contrib_set_defs;
41+
find(
42+
{
43+
wanted => sub {
44+
push @contrib_set_defs, $_ =~ s|^$contribRoot/?|Contrib/|r if m|/set[^/]*\.def$|;
45+
},
46+
follow_fast => 1,
47+
no_chdir => 1
48+
},
49+
$contribRoot
50+
);
51+
52+
sub depth_then_iname_sort {
53+
my $file_list = shift;
54+
my @file_depths;
55+
my @uc_file_names;
56+
for (@$file_list) {
57+
push @file_depths, scalar(@{ [ $_ =~ /\//g ] });
58+
push @uc_file_names, uc($_);
59+
}
60+
@$file_list =
61+
@$file_list[ sort { $file_depths[$a] <=> $file_depths[$b] || $uc_file_names[$a] cmp $uc_file_names[$b] }
62+
0 .. $#$file_list ];
63+
}
64+
65+
# Sort the files first by depth then by path.
66+
depth_then_iname_sort(\@opl_set_defs);
67+
depth_then_iname_sort(\@contrib_set_defs);
68+
69+
sub writeJSONtoFile {
70+
my ($data, $filename) = @_;
71+
72+
open my $fh, ">", $filename or die "Cannot open $filename";
73+
print $fh JSON->new->utf8->encode($data);
74+
close $fh;
75+
}
76+
77+
# Directory to hold the json files.
78+
my $dataDir = "$ENV{GITHUB_WORKSPACE}/webwork-open-problem-library/JSON-SAVED";
79+
`mkdir -p $dataDir` if !-d $dataDir;
80+
81+
# Write the lists to the files in ./DATA.
82+
writeJSONtoFile(\@opl_set_defs, "$dataDir/library-set-defs.json");
83+
writeJSONtoFile(\@contrib_set_defs, "$dataDir/contrib-set-defs.json");
84+
85+
print 'Set definition list generation complete.';

0 commit comments

Comments
 (0)