Sources
Miscellaneous sources
Google Sites and Forms sources
Due to the limitations of Google Sites and Google Forms, we cannot share the source of the site itself nor the sources of the forms without allowing anyone to edit them. So, if you would like a copy of the site's source or any of the Google Forms sources, please email us and we will create a copy for you.
Online Readiness Course [Sites]
Post-course assessment [Forms]
Pre-course assessment [Forms]
Student Feedback [Forms]
Submodule 1.2 personality quiz [Forms]
Submodule 1.3 drag and drop [Forms]
Submodule 1.7 true/false [Forms]
Submodule 2.1 readiness assessment [Forms]
Submodule 2.2 itemization chart [Forms]
Submodule 3.5 true/false quiz [Forms]
Google Apps Script sources
Due to the limitations of container-bound Google Apps Scripts, we cannot share the projects. However, we can share the source code and triggers needed to construct the project.
Submodule 1.2 personality quiz results selector
function doGet() {
return HtmlService.createHtmlOutputFromFile('index').setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
function processForm(formObject) {
var dateTime = formObject.myDateTime;
var personalID = formObject.myID;
return getResult(dateTime, personalID);
}
function getResult(resultDateTime, personalID)
{
timeZone = new Date().getTimezoneOffset();
resultDateTime = Utilities.formatDate(new Date(resultDateTime), timeZone, "yyyy-MM-dd'T'HH:mm");
personalID = Utilities.computeDigest(
Utilities.DigestAlgorithm.SHA_256, resultDateTime + personalID, Utilities.Charset.US_ASCII
).toString();
var results = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1tUj-T4RQG7aYVDXs9JFto7Tkr5MuLMh4JvKNLO0CLkI/edit#gid=0').getActiveSheet().getDataRange().getValues();
var asyncPercent;
var syncPercent;
var hybridPercent;
for (var i = 1; i < results.length; i++)
{
thisDateTime = Utilities.formatDate(new Date(results[i][0]), 'UTC', "yyyy-MM-dd'T'HH:mm");
if (thisDateTime == resultDateTime && results[i][2] == personalID)
{
asyncPercent = results[i][3];
syncPercent = results[i][4];
hybridPercent = results[i][5];
return (
'<p>Here are the probabilities that each course type is best for you. '
+ 'Note that these are not based on your likelihood of academic success, '
+ 'but instead, your likelihood of enjoyment and getting something out of each course type.</p>'
+ '<dl>'
+ '<div>'
+ '<dt>Asynchronous course</dt><dd>' + asyncPercent * 100 + '%</dd>'
+ '</div>'
+ '<div>'
+ '<dt>Synchronous course</dt><dd>' + syncPercent * 100 + '%</dd>'
+ '</div>'
+ '<div>'
+ '<dt>Hybrid course</dt><dd>' + hybridPercent * 100 + '%</dd>'
+ '</div>'
+ '</dl>'
);
}
}
return '<p>Result not found. Check your input and try again.</p>';
}
Submodule 1.2 personality quiz (Print version)
Triggers:
Event: From document - On open
Function: myFunction
function myFunction()
{
const H1_STYLE =
{
[DocumentApp.Attribute.FONT_FAMILY]: 'Noto Sans',
[DocumentApp.Attribute.FOREGROUND_COLOR]: '#0041A5',
[DocumentApp.Attribute.BOLD]: true,
[DocumentApp.Attribute.FONT_SIZE]: 18
};
const H2_STYLE =
{
[DocumentApp.Attribute.FONT_FAMILY]: 'Noto Sans',
[DocumentApp.Attribute.FOREGROUND_COLOR]: '#000000',
[DocumentApp.Attribute.FONT_SIZE]: 18
};
const H3_STYLE =
{
[DocumentApp.Attribute.FONT_FAMILY]: 'Noto Sans',
[DocumentApp.Attribute.FOREGROUND_COLOR]: '#000000',
[DocumentApp.Attribute.FONT_SIZE]: 14
};
const P_STYLE =
{
[DocumentApp.Attribute.FONT_FAMILY]: 'Noto Sans',
[DocumentApp.Attribute.FOREGROUND_COLOR]: '#000000',
[DocumentApp.Attribute.FONT_SIZE]: 12
};
const SMALL_STYLE =
{
[DocumentApp.Attribute.FONT_FAMILY]: 'Noto Sans',
[DocumentApp.Attribute.FOREGROUND_COLOR]: '#000000',
[DocumentApp.Attribute.FONT_SIZE]: 10
}
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody().clear();
// "Submodule 1.2 personality quiz"
var form = FormApp.openByUrl("https://docs.google.com/forms/d/1DuE8avUXLJWhN9xziPvryVM-dlvVrzF0Pske3NDsm40/edit");
// "Submodule 1.2 personality quiz total points (auto updated - don't edit)"
var sheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1Zh4O6tzMoPD1h1Uggu-M-RcHcXRRiua0pf9v9q-KP58/edit#gid=0").getActiveSheet();
var asyncWeight = sheet.getRange("A1").getValue();
// grab values for each category from the auto generated sheet
var syncWeight = sheet.getRange("S1").getValue();
var hybridWeight = sheet.getRange("H1").getValue();
body.getChild(0).setText(form.getTitle());
// Title of the original form that's used as reference
body.getChild(0).setHeading(DocumentApp.ParagraphHeading.HEADING1).setAttributes(H1_STYLE);
// people get confused so need a back link
body.appendParagraph(
"This version has opened in a new tab. To go back to the site, close this tab."
).setAttributes(SMALL_STYLE);
// Grab heading from the document maybe use doc var here instead?
body.appendParagraph("Questions").setHeading(DocumentApp.ParagraphHeading.HEADING2).setAttributes(H2_STYLE);
var questions = form.getItems(FormApp.ItemType.GRID);
var points = form.getItems(FormApp.ItemType.MULTIPLE_CHOICE);
for (var i = 0; i < questions.length; i++)
{
// Questions \\
// handle "(Select all that apply)"
if (questions[i].getTitle().endsWith("(Select all that apply)"))
{
var qTitle = questions[i].getTitle().replace("(Select all that apply)", "");
var selectN = "Select all that apply";
}
else
{
var qTitle = questions[i].getTitle();
var selectN = "Select one";
}
body.appendParagraph(qTitle).setHeading(DocumentApp.ParagraphHeading.HEADING3).setAttributes(H3_STYLE);
body.appendParagraph(selectN).setAttributes(SMALL_STYLE);
var question = questions[i].asGridItem();
var rows = question.getRows();
var rowPoints = points[i].asMultipleChoiceItem().getChoices();
for (var j = 0; j < rows.length; j++)
{
// Question Answers \\
/*Possible Scores Letter Translate
0 None
1 H
100 S
101 SH
10000 A
10001 AH
10100 AS
10101 AHS
*/
var asyncPoints = Math.floor(rowPoints[j].getValue() / 10000);
var syncPoints = Math.floor((rowPoints[j].getValue() - (asyncPoints * 10000)) / 100);
var hybridPoints = Math.floor((rowPoints[j].getValue() - (asyncPoints * 10000) - (syncPoints * 100) / 1));
var thisAnsScore = "";
if (asyncPoints != 0)
{
thisAnsScore = " (A)";
}
if (syncPoints != 0)
{
thisAnsScore = thisAnsScore + " (S)";
}
if (hybridPoints != 0)
{
thisAnsScore = thisAnsScore + " (H)";
}
body.appendListItem(
rows[j] + thisAnsScore
).setGlyphType(
DocumentApp.GlyphType.HOLLOW_BULLET
).setAttributes(
P_STYLE
);
}
}
body.appendParagraph("Results").setHeading(DocumentApp.ParagraphHeading.HEADING2).setAttributes(H2_STYLE);
//body.appendParagraph("").setAttributes(P_STYLE);
body.appendParagraph("Write the number of answers you selected with an (A) at the end: _______").setAttributes(P_STYLE);
body.appendParagraph("Write the number of answers you selected with an (S) at the end: _______").setAttributes(P_STYLE);
body.appendParagraph("Write the number of answers you selected with an (H) at the end: _______").setAttributes(P_STYLE);
body.appendParagraph("").setAttributes(P_STYLE);
body.appendParagraph("Asynchronous score (number of (A)s / " + asyncWeight + " × 100): _______%").setAttributes(P_STYLE);
body.appendParagraph("Synchronous score (number of (S)s / " + syncWeight + " × 100): _______%").setAttributes(P_STYLE);
body.appendParagraph("Hybrid score (number of (H)s / " + hybridWeight + " × 100): _______%").setAttributes(P_STYLE);
body.appendParagraph("").setAttributes(P_STYLE);
body.appendParagraph(
"Note that these percentages are not based on your likelihood of academic success,"
+ " but instead, your likelihood of enjoyment and getting something out of each course type."
).setAttributes(P_STYLE);
// body.clear() fails if last item is a list
//body.appendParagraph("").setAttributes(P_STYLE);
DocumentApp.getUi().alert('Document updated.');
}
Submodule 1.2 personality quiz (Responses)
Triggers:
Event: From spreadsheet - On form submit
Function: myFunction
function myFunction(e) {
// auto-updated weights sheet
var sheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1Zh4O6tzMoPD1h1Uggu-M-RcHcXRRiua0pf9v9q-KP58/edit#gid=0").getActiveSheet();
// "Submodule 1.2 personality quiz (Public data)"
var publicScores = SpreadsheetApp.openByUrl(
'https://docs.google.com/spreadsheets/d/1tUj-T4RQG7aYVDXs9JFto7Tkr5MuLMh4JvKNLO0CLkI/edit#gid=0'
).getSheetByName('Sheet1');
var score = e.values[2].split(" / "); // AASSHH / aasshh
var points = parseFloat(score[0]);
var weights = parseFloat(score[1]);
var asyncPoints = Math.floor(points / 10000);
var asyncWeight = Math.floor(weights / 10000);
points = points - (asyncPoints * 10000);
weights = weights - (asyncWeight * 10000);
var syncPoints = Math.floor(points / 100);
var syncWeight = Math.floor(weights / 100);
points = points - (syncPoints * 100);
weights = weights - (syncWeight * 100);
var hybridPoints = Math.floor(points / 1);
var hybridWeight = Math.floor(weights / 1);
sheet.getRange("A1").setValue(asyncWeight);
sheet.getRange("S1").setValue(syncWeight);
sheet.getRange("H1").setValue(hybridWeight);
asyncPercent = Math.round(asyncPoints / asyncWeight * 100) + "%";
syncPercent = Math.round(syncPoints / syncWeight * 100) + "%";
hybridPercent = Math.round(hybridPoints / hybridWeight * 100) + "%";
// store result in publicScores spreadsheet
var resultDateTime = Utilities.formatDate(new Date(e.values[25]), 'UTC', "yyyy-MM-dd'T'HH:mm");
var resultTime = e.values[35];
var personalID = e.values[36];
// Salt and hash personalID for privacy reasons,
// as publicScores is partially publicly accessible.
// This does not need to be *as* secure as a password hash,
// which is good because there's a monthly computation time limit for Apps Script.
// We're going to use Sha256 because it's fast,
// and because we're only even salting *just in case* the ID is personally identifiable information.
personalID = Utilities.computeDigest(
Utilities.DigestAlgorithm.SHA_256, resultDateTime + personalID, Utilities.Charset.US_ASCII
).toString();
publicScores.appendRow(
[
resultDateTime,
resultTime,
personalID,
asyncPercent,
syncPercent,
hybridPercent
]
);
/*
htmlBody = "<p>Here are the probabilities that each course type is best for you. "
+ "Note that these are not based on your likelihood of academic success, "
+ "but instead, your likelihood of enjoyment and getting something out of each course type.</p>"
+ "<table><tr><th style=\"text-align: right;\">Asynchronous course: </th><td>"
+ asyncPercent + "</td></tr><tr><th style=\"text-align: right;\">Synchronous course: </th><td>"
+ syncPercent + "</td></tr><tr><th style=\"text-align: right;\">Hybrid course: </th><td>"
+ hybridPercent + "</td></tr></table>";
textBody = "Here are the probabilities that each course type is best for you. "
+ "Note that these are not based on your likelihood of academic success, "
+ "but instead, your likelihood of enjoyment and getting something out of each course type.\n\n"
+ "\tAsynchronous course: " + asyncPercent + "\n"
+ "\tSynchronous course: " + syncPercent + "\n"
+ "\tHybrid course: " + hybridPercent + "\n";
MailApp.sendEmail({
to: email,
name: "Online Readiness",
replyTo: "northeastregionalconsortium@gmail.com",
subject: "[Online Readiness] Lesson 1.2 Quiz Results",
htmlBody: htmlBody,
body: textBody
});
//GmailApp.sendEmail(email, "[Online Readiness] Lesson 1.2 Quiz Results", textBody);
*/
}