Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STAR CLASS: Adding the pl-snap element along with the snap repo and a… #19

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
26 changes: 26 additions & 0 deletions elements/pl-snap/Docker setup/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Set the base image.
# Version: 1.1
FROM node:slim

RUN mkdir /usr/src/cache
WORKDIR /usr/src/cache

# We don't need the standalone Chromium
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true

# Install Google Chrome Stable and fonts
# Note: this installs the necessary libs to make the browser work with Puppeteer.
RUN apt-get update && apt-get install curl gnupg -y \
&& curl --location --silent https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update \
&& apt-get install google-chrome-stable -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/*

# Install the application's dependencies into the node_modules's cache directory.
COPY package.json ./
COPY package-lock.json ./
COPY autograder/autograder.js ./
COPY autograder/run_autograder ./
RUN npm install

12 changes: 12 additions & 0 deletions elements/pl-snap/Docker setup/SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Locally run:
docker run -it --rm -p 3000:3000 -v $PWD:/course -v "$PWD/pl_ag_jobs:/jobs" -e HOST_JOBS_DIR="$PWD/pl_ag_jobs" -v /var/run/docker.sock:/var/run/docker.sock --add-host=host.docker.internal:172.17.0.1 prairielearn/prairielearn:latest

https://stackoverflow.com/questions/72228079/docker-pull-from-local-repository-fails
docker run -d -p 5000:5000 --name registry registry:2
docker pull jryl/grader-snap
docker image tag jryl/grader-snap localhost:5000/snap-test-new
docker push localhost:5000/snap-test-new

docker build -t snap-test-new .

docker run -it --rm -p 3000:3000 -v %cd%:/course -v "%cd%/pl_ag_jobs:/jobs" -e HOST_JOBS_DIR="%cd%/pl_ag_jobs" -v /var/run/docker.sock:/var/run/docker.sock --add-host=host.docker.internal:172.17.0.1 prairielearn/prairielearn:latest
128 changes: 128 additions & 0 deletions elements/pl-snap/Docker setup/autograder/autograder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
const path = require("path");
const fs = require("fs");
const puppeteer = require("puppeteer");

// Puppeteer PageFunctions.
function loadProject(projectXML) {
const ide = world.children[0];
ide.onNextStep = null;
ide.world().animations = [];
ide.rawOpenProjectString(projectXML);
}

function loadSprite(spriteXML) {
world.children[0].rawOpenSpritesString(spriteXML);
}

function setTurboMode(turnOn) {
const ide = world.children[0];
if (turnOn) {
ide.startFastTracking();
} else {
ide.stopFastTracking();
}
}

function setEnableJSFunctions(boolean) {
Process.prototype.enableJS = boolean;
const ide = world.children[0];
ide.flushBlocksCache('operators');
ide.refreshPalette();
ide.categories.refreshEmpty();
}

function grade(secretNumber) {
const ide = world.children[0];
const sprite = ide.sprites.asArray().at(-1);

sprite.variables.setVar("secret number", 0);

return new Promise((resolve) => {
ide.broadcast("run autograder", () => {
resolve(sprite.variables.getVar("results"));
});
});
}

// Utility function.
function readXML(filePath) {
return fs.readFileSync(filePath).toString();
}

async function main() {
console.time("Grading Time");
console.log("Grading submission...");
const url = "https://snap.berkeley.edu/snap/snap.html",
submissionPath = "/usr/src/cache/submission.xml",
resultsPath = "/grade/results/results.json",
autograderPath = "/grade/tests/autograder.xml",
secretNumber = 0;

let results;

const browser = await puppeteer.launch({
executablePath: "/usr/bin/google-chrome",
args: ["--no-sandbox", "--disable-setuid-sandbox"],
});
const page = await browser.newPage();

try {
// Block unnecessary requests
await page.setRequestInterception(true);
page.on('request', (req) => {
if (req.resourceType() === 'font' || req.resourceType() === 'image' || req.resourceType() === 'stylesheet') {
req.abort();
}
else {
req.continue();
}
});

// page.on('console', msg => console.log('PAGE LOG:', msg.text()));

console.time("Page Load Time")
Promise.all([
await page.goto(url, { waitUntil: "domcontentloaded" }),
submission = readXML(submissionPath),
autograder = readXML(autograderPath),
]);
console.timeLog("Page Load Time", "Page loaded");
await Promise.all([
page.evaluate(loadProject, submission),
page.evaluate(loadSprite, autograder),
page.evaluate(setTurboMode, true),
page.evaluate(setEnableJSFunctions, true),
]);
console.timeLog("Page Load Time", "Project and Autograder loaded");
results = await page.evaluate(grade, secretNumber);
console.timeEnd("Page Load Time");
} catch (e) {
results = JSON.stringify({
"score": 0,
"output": (
"Failed to grade submission. Make sure:\n" +
"1) Your filename follows the specified format.\n" +
"2) Your code doesn't cause any Snap! error.\n" +
"3) Your code runs in a reasonable amount of time." +
e
)
});
} finally {
// Define the directory path
const dir = '/grade/results';

// Create the directory if it doesn't exist
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.writeFileSync(resultsPath, results);
await browser.close();

console.log("Grading completed.");
console.timeEnd("Grading Time");
}
}

if (typeof require !== "undefined" && require.main === module) {
main();
}
9 changes: 9 additions & 0 deletions elements/pl-snap/Docker setup/autograder/run_autograder
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh
start=`date +%s` # Get the current time in seconds
SUBMISSION=`find /grade/student -regex ".*\.xml"`
cp "$SUBMISSION" /usr/src/cache/submission.xml
cd /usr/src/cache
node autograder.js
end=`date +%s` # Get the current time in seconds
runtime=$((end-start)) # Calculate the difference
echo "Script runtime: $runtime seconds"
Loading
Loading