Skip to content

Commit e50b77a

Browse files
committed
This will update the pgeditor to use the pgcritic to analyze a problem.
1 parent 5743ae9 commit e50b77a

File tree

5 files changed

+182
-2
lines changed

5 files changed

+182
-2
lines changed

htdocs/js/PGProblemEditor/pgproblemeditor.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,30 @@
231231
.catch((err) => showMessage(`Error: ${err?.message ?? err}`));
232232
};
233233

234+
// Send a request to the server to run the PG critic in the CodeMirror editor.
235+
const runPGCritic = () => {
236+
const request_object = { courseID: document.getElementsByName('courseID')[0]?.value };
237+
238+
const user = document.getElementsByName('user')[0];
239+
if (user) request_object.user = user.value;
240+
const sessionKey = document.getElementsByName('key')[0];
241+
if (sessionKey) request_object.key = sessionKey.value;
242+
243+
request_object.rpc_command = 'runPGCritic';
244+
request_object.pgCode =
245+
webworkConfig?.pgCodeMirror?.source ?? document.getElementById('problemContents')?.value ?? '';
246+
247+
fetch(webserviceURL, { method: 'post', mode: 'same-origin', body: new URLSearchParams(request_object) })
248+
.then((response) => response.json())
249+
.then((data) => {
250+
renderArea.innerHTML = data.result_data.html;
251+
})
252+
.catch((err) => {
253+
console.log(err);
254+
showMessage(`Error: ${err?.message ?? err}`);
255+
});
256+
};
257+
234258
document.getElementById('take_action')?.addEventListener('click', async (e) => {
235259
if (document.getElementById('current_action')?.value === 'format_code') {
236260
e.preventDefault();
@@ -240,6 +264,8 @@
240264
document.querySelector('input[name="action.format_code"]:checked').value == 'convertCodeToPGML'
241265
) {
242266
convertCodeToPGML();
267+
} else if (document.querySelector('input[name="action.format_code"]:checked').value == 'runPGCritic') {
268+
runPGCritic();
243269
}
244270
return;
245271
}

lib/WebworkWebservice.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ sub command_permission {
255255
putPastAnswer => 'problem_grader',
256256
tidyPGCode => 'access_instructor_tools',
257257
convertCodeToPGML => 'access_instructor_tools',
258+
runPGCritic => 'access_instructor_tools',
258259

259260
# WebworkWebservice::RenderProblem
260261
renderProblem => 'proctor_quiz_login',

lib/WebworkWebservice/ProblemActions.pm

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ use warnings;
66

77
use Data::Structure::Util qw(unbless);
88

9-
use WeBWorK::PG::Tidy qw(pgtidy);
10-
use WeBWorK::PG::ConvertToPGML qw(convertToPGML);
9+
use WeBWorK::PG::Tidy qw(pgtidy);
10+
use WeBWorK::PG::ConvertToPGML qw(convertToPGML);
11+
use WeBWorK::PG::PGProblemCritic qw(analyzePGcode);
1112

1213
sub getUserProblem {
1314
my ($invocant, $self, $params) = @_;
@@ -165,4 +166,21 @@ sub convertCodeToPGML {
165166

166167
}
167168

169+
sub runPGCritic {
170+
my ($invocant, $self, $params) = @_;
171+
my $pg_critic_results = analyzePGcode($params->{pgCode});
172+
173+
my $html_output = $self->c->render_to_string(
174+
template => 'ContentGenerator/Instructor/PGProblemEditor/pg_critic',
175+
results => $pg_critic_results
176+
);
177+
178+
return {
179+
ra_out => {
180+
html => $html_output
181+
},
182+
text => 'The script pg-critic has been run successfully.'
183+
};
184+
}
185+
168186
1;

templates/ContentGenerator/Instructor/PGProblemEditor/format_code_form.html.ep

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,18 @@
3030
<span class="visually-hidden"><%= maketext('PGML Conversion Help') %></span>
3131
</a>
3232
</div>
33+
<div class="form-check">
34+
<%= radio_button 'action.format_code' => 'runPGCritic',
35+
id => 'action_format_code_run_pgcritic', class => 'form-check-input'=%>
36+
<%= label_for 'action_format_code_run_pgcritic', class => 'form-check-label', begin =%>
37+
<%== maketext('Run the PG Critic Analyzer') =%>
38+
<% end =%>
39+
<a class="help-popup" data-bs-content="<%== maketext('This option runs the PG Critic '
40+
. 'code analyzer, which gives suggestions on using more modern PG constructs and '
41+
. 'ensure that you include important features. ') =%>"
42+
data-bs-placement="top" data-bs-toggle="popover" role="button">
43+
<i aria-hidden="true" class="fas fa-question-circle"></i>
44+
<span class="visually-hidden"><%= maketext('PG Critic Help') %></span>
45+
</a>
46+
</div>
3347
</div>
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<div class="m-3" style="overflow: scroll">
2+
<h2>PG Critic Results</h2>
3+
4+
<h3>Metadata</h3>
5+
6+
<p>The following lists required metadata. If any is missing, the given tag must be filled in.
7+
However, make sure that the categories are correct, especially if the problem has been
8+
copied.</p>
9+
10+
% sub showIcon { my $show = shift;
11+
% return $show ? q!<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check-square text-success" viewBox="0 0 16 16">
12+
% <path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
13+
% <path d="M10.97 4.97a.75.75 0 0 1 1.071 1.05l-3.992 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425z"/>
14+
% </svg>! : q!<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-square text-danger" viewBox="0 0 16 16">
15+
% <path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
16+
% <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/>
17+
% </svg>!;
18+
%}
19+
20+
<table class="table table-bordered">
21+
<tbody>
22+
<tr><th>DBsubject</th><td> <%== showIcon($results->{metadata}{DBsection}) %> </td></tr>
23+
<tr><th>DBchapter</th><td> <%== showIcon($results->{metadata}{DBchapter}) %> </td></tr>
24+
<tr><th>DBsection</th><td> <%== showIcon($results->{metadata}{DBsection}) %> </td></tr>
25+
<tr><th>Keywords</th><td> <%== showIcon($results->{metadata}{KEYWORDS}) %> </td></tr>
26+
</table>
27+
28+
<h3>You done good with the following</h3>
29+
30+
<table class="table table-bordered">
31+
<tbody>
32+
% if ($results->{good}{PGML}) {
33+
<tr><th>PGML</th><td>This problem uses PGML, the current preferred way to write problem (text), solution and hint
34+
blocks.</td></tr>
35+
%}
36+
% if ($results->{good}{solution}) {
37+
<tr><th>Solutions</th><td>This problem has a solution block. Every problem should have solutions that the
38+
student can view after the answer data. </td></tr>
39+
%}
40+
% if ($results->{good}{hint}) {
41+
<tr><th>Hints</th><td>This problem has a hint. This can be helpful for students after attempting the problem
42+
a few times (this can be set by the instructor).
43+
%}
44+
</tbody>
45+
</table>
46+
47+
48+
% if( scalar(@{$results->{deprecated_macros}}) > 0) {
49+
<h3>Deprecated Macros</h3>
50+
<p>This problem has the following deprecated macros: <%= join(', ',@{$results->{deprecated_macros}} ) %> </p>
51+
52+
<p>These should be removed from the problem in that these macros will be deleted from PG in a future
53+
version. The functions from these macros may be listed below to help aid in transitioning away from
54+
these macros. </p>
55+
% }
56+
57+
58+
% my $has_bad_features = 0;
59+
% $has_bad_features += $results->{bad}{$_} for (keys %{$results->{bad}});
60+
61+
% # <%== dumper $results->{bad} %>
62+
63+
% if ($has_bad_features) {
64+
<h3>You can improve on the following:</h3>
65+
<p> There are features in this problem that contain old or deprecated features. The following
66+
list gives feedback of how the problem can be improved. </p>
67+
%}
68+
69+
<ul>
70+
% if ($results->{bad}{BEGIN_TEXT}) {
71+
<li>This problem contains older formatting blocks like BEGIN_TEXT. Consider use PGML.
72+
In the <em>Format Code</em> section of the PG Editor, the "Convert to PGML" should be used
73+
as a start to get the problem switched.
74+
</li>
75+
%}
76+
% if ($results->{bad}{beginproblem}) {
77+
<li>This problem contains the line <tt>TEXT(beginproblem())</tt>. This is no longer necessary and should be removed. </li>
78+
%}
79+
% if ($results->{bad}{context_texstrings}) {
80+
<li>This problem contains the line <tt>Context()->texStrings;</tt>. This is no longer necessary and should be removed. </li>
81+
%}
82+
% if ($results->{bad}{oldtable}) {
83+
<li>This problem contains the deprecated <tt>begintable</tt> command. This is not assessible and often cannot be
84+
converted to hardcopy. This table should be written using <tt>nicetables</tt> or a PGML table. </li>
85+
%}
86+
% if ($results->{bad}{showPartialCorrect}) {
87+
<li>This problem contains the line <tt>$showPartialCorrectAnswers = 1</tt>. This is enabled by default and needed only
88+
if set to 0.</li>
89+
% }
90+
% if (!$results->{good}{solution}) {
91+
<li>This problem does not have a solution. Consider adding one.</li>
92+
% }
93+
% if ($results->{bad}{fun_cmp} || $results->{bad}{str_cmp} || $results->{bad}{num_cmp}) {
94+
<li>This problem contains the functioins <tt>num_cmp</tt>, <tt>str_cmp</tt> or <tt>fun_cmp</tt>.
95+
These are old ways of checking answers. These should be converted to MathObjects.
96+
% }
97+
% if ($results->{bad}{multiple_loadmacros}) {
98+
<li>This problem contains two <tt>loadMacros</tt> function call. Combine the function
99+
calls and make sure that all macros are needed for your problem. </li>
100+
% }
101+
% if ($results->{bad}{old_multiple_choice}) {
102+
<li>This problem contains old versions of multiple choice. The sample problems
103+
<a href="https://openwebwork.github.io/pg-docs/sample-problems/Misc/MultipleChoiceCheckbox.html">
104+
Multiple Choice with Checkbox</a>, <a href="https://openwebwork.github.io/pg-docs/sample-problems/Misc/MultipleChoicePopup.html">
105+
Multiple Choice with Popup</a> and <a href="https://openwebwork.github.io/pg-docs/sample-problems/Misc/MultipleChoiceRadio.html">
106+
Multiple Choice with Radio Buttons</a> should be examined as well the macros:
107+
<a href="https://openwebwork.github.io/pg-docs/pod/pg/macros/parsers/parserPopUp.html">parserPopUp.pl</a>,
108+
<a href="https://openwebwork.github.io/pg-docs/pod/pg/macros/parsers/parserCheckboxList.html">parserCheckboxList.pl</a> and
109+
<a href="https://openwebwork.github.io/pg-docs/pod/pg/macros/parsers/parserRadioButtons.html">parserRadioButtons.pl</a>.
110+
111+
</li>
112+
% }
113+
% if ($results->{bad}{lines_below_enddocument}) {
114+
<li>There is content (code or other text), below the <tt>ENDDOCUMENT()</tt> line. Although this
115+
is ignored, there shouldn't be content in this area.</li>
116+
% }
117+
118+
</ul>
119+
120+
121+
</div>

0 commit comments

Comments
 (0)