WebFund 2024F: Tutorial 6
In this tutorial you will be playing with Tutorial Validator
Tasks
- Create a file that validates correctly.
- When validated, what is printed in the browser console? What produces this output?
- Save a local copy of the validator and run it. Does it run any differently from the version on homeostasis?
- Setup a web server (using past tutorial/assignment code) on a class VM that serves this application.
- Change the validator so it validates Assignment 3, where Assignment 3 has 10 questions.
- Change the font of the page to Times New Roman or any other font.
- Reduce the size of the border around the page to half of its current value.
- Change the validator so it only accepts MS-DOS text files (CRLF) and processes them appropriately.
- Where is hideAnalysis() called? Why can't it be called right after it is declared?
- Change the validator so it accepts a field "Section: " at the top of of the assignment just after the Student ID. This section should be added to the output of the validation.
- Change the questions so that they are all of the form "Q1: " rather than "1.". Note that the specification for the questions should not require a Q prefix.
- Walk through the code and see if you can understand every line. Which lines are confusing? How did you figure out what each line did?
Code
Runnable version: Tutorial Validator
(Save the page locally to edit.)
<!DOCTYPE html>
<html>
<head>
<title>COMP 2406 2024F Tutorial Validator</title>
<style>
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
</style>
<script type="text/javascript">
const filePrefix = "comp2406-tutorial6";
const submissionName = "COMP 2406 2024F Tutorial 6"
const expectedQuestionList = "1,2,3,4,5";
var analysisSection;
function loadAssignment(fileInput) {
analysisSection.hidden = false;
if(fileInput.files[0] == undefined) {
updateTag("status", "ERROR: No files to examine.")
return;
}
var reader = new FileReader();
reader.onload = function(ev) {
var content = ev.target.result;
checkSubmission(fileInput.files[0].name, content);
};
reader.onerror = function(err) {
updateTag("status", "ERROR: Failed to read file");
}
reader.readAsText(fileInput.files[0]);
}
var numQuestions = expectedQuestionList.split(",").length;
function updateTag(id, val) {
document.getElementById(id).innerHTML = val;
}
function lineEncoding(lines) {
var n, i, s;
for (i = 0; i < lines.length; i++) {
s = lines[i];
n = s.length;
if (s[n-1] === '\r') {
return "DOS/Windows Text (CR/LF)";
}
}
return "UNIX";
}
function checkSubmission(fn, f) {
var lines = f.split('\n')
var c = 0;
var questionList = [];
var questionString;
var q = {};
var e = {};
var i;
var lastQuestion = null;
const fnPattern = filePrefix + "-[a-zA-Z0-9]+\.txt";
const fnRexp = new RegExp(fnPattern);
if (!fnRexp.test(fn)) {
updateTag("status", "ERROR " + fn +
" doesn't follow the pattern " + fnRexp);
return;
}
if (fn === filePrefix + "-template.txt") {
updateTag("status", "ERROR " + fn +
" has the default name, please change template to your mycarletonone username");
return;
}
updateTag("filename", fn);
let encoding = lineEncoding(lines);
if (encoding !== "UNIX") {
updateTag("status", "ERROR " + fn +
" is not a UNIX textfile, it is a "
+ encoding + " file.");
return;
}
if (submissionName !== lines[0]) {
updateTag("status", "ERROR " + fn +
" doesn't start with \"" + submissionName + "\"");
return;
}
try {
e.name = lines[1].match(/^Name:(.+)/m)[1].trim();
e.id = lines[2].match(/^Student ID:(.+)/m)[1].trim();
} catch (error) {
updateTag("status", "ERROR " + fn +
" has bad Name or Student ID field");
return;
}
updateTag("name", e.name);
updateTag("studentID", e.id);
var questionRE = /^([0-9a-g]+)\.(.*)/;
for (i = 4; i < lines.length; i++) {
if (typeof(lines[i]) === 'string') {
lines[i] = lines[i].replace('\r','');
}
let m = lines[i].match(questionRE);
if (m) {
c++;
questionList.push(m[1]);
q[m[1]] = m[2];
lastQuestion = m[1];
} else {
if (lastQuestion !== null) {
if ((q[lastQuestion] === '') || (q[lastQuestion] === ' ')) {
q[lastQuestion] = lines[i];
} else {
q[lastQuestion] = q[lastQuestion] + "\n" + lines[i];
}
}
}
}
console.log(JSON.stringify(q, null, ' '));
questionString = questionList.toString();
if (questionString !== expectedQuestionList) {
updateTag("status", "ERROR expected questions " +
expectedQuestionList + " but got questions " +
questionString);
} else {
updateTag("status", "PASSED " +
fn + ": " + e.name + " (" + e.id + ")");
}
var newP, newText, newPre, newPreText;
let questionDiv = document.getElementById("questions");
for (let qName of questionList) {
let qText = q[qName];
newP = document.createElement("p");
newText = document.createTextNode(qName + ":");
newP.appendChild(newText);
questionDiv.appendChild(newP);
newPre = document.createElement("pre");
newPreText = document.createTextNode(qText);
newPre.appendChild(newPreText);
newP.appendChild(newPre);
}
return;
}
function hideAnalysis() {
analysisSection = document.getElementById("analysis");
analysisSection.hidden = true;
}
</script>
</head>
<body onload="hideAnalysis()">
<h1>COMP 2406 2024F Tutorial Validator</h1>
<input type="file" id="assignmentFile" onchange="loadAssignment(this)" />
<div id="analysis">
<p><b>Status:</b> <span id="status">UNKNOWN</span></p>
<p>Filename: <span id="filename"></span></p>
<p>Name: <span id="name"></span><br>
Student ID: <span id="studentID"></span> <i>(Please check that your ID number is correct!)</i></p>
<hr>
<div id="questions"><p><b>Questions:</b> <i>(Please check that your answers are numbered correctly!)</i></p></div>
</div>
</body>
</html>