From 581d4ec7106d75ca0ceef95d1ff272407c60104a Mon Sep 17 00:00:00 2001
From: Lun <tin.lun@aalto.fi>
Date: Tue, 24 Aug 2021 15:13:59 +0300
Subject: [PATCH] Edit the exercise descriptions based on Antti's suggestions

---
 content.js | 339 +++++++++++++++++++++++++++++------------------------
 1 file changed, 187 insertions(+), 152 deletions(-)

diff --git a/content.js b/content.js
index 48d7dc1..3d81c1f 100644
--- a/content.js
+++ b/content.js
@@ -1,48 +1,52 @@
 /* global module, require, console */
 /* jshint globalstrict: true */
-'use strict';
+"use strict";
 
 let Content = {
-
   click_for_points: {
-    instructions: "This is an example of how automatically graded assignments appear in this course. Always <strong>carefully read assignment instructions</strong> before starting to do anything. At this time, there is no problem to solve. You are only expected to click the button on left to receive your first points.",
-    html: "<button class=\"green\">Click Me!</button>",
+    instructions:
+      "This is an example of how automatically graded assignments appear in this course. Always <strong>carefully read assignment instructions</strong> before starting to do anything. At this time, there is no problem to solve. You are only expected to click the button on left to receive your first points.",
+    html: '<button class="green">Click Me!</button>',
     selector: ".exercise button",
     events: "click",
     points: function ($element, config, event) {
       return {
         points: 10,
-        feedback: 'Congratulations!'
+        feedback: "Congratulations!",
       };
     },
     maxPoints: 10,
     title: "Click for points",
     description: "An example of how these assignments work.",
     concepts: ["Automatic assessment"],
-    order: 0
+    order: 0,
   },
 
   fix_typo: {
-    instructions: "On the left, you see a message that unfortunately contains a typo. Your task is to open the browser inspector tool, find the paragraph element <strong>&lt;p&gt;</strong> containing the message and then edit the element body correctly to contain the intended message \"<strong>Hello World!</strong>\".",
-    html: "<div class=\"acos-webdev-poi\"><p>Hello Wordl!</p></div>",
+    instructions:
+      'On the left, you see a message that unfortunately contains a typo. Your task is to open the browser inspector tool, find the paragraph element <strong>&lt;p&gt;</strong> containing the message and then edit the element body correctly to contain the intended message "<strong>Hello World!</strong>".',
+    html: '<div class="acos-webdev-poi"><p>Hello Wordl!</p></div>',
     mutations: true,
     points: function ($element, config, mutations) {
-      let $p = $element.find('.exercise p');
+      let $p = $element.find(".exercise p");
       if ($p.length != 1) {
         return {
           points: 0,
-          feedback: 'The document is altered beyond repair. Avoid accidentally removing nodes. You should reset the assignment to start over.'
+          feedback:
+            "The document is altered beyond repair. Avoid accidentally removing nodes. You should reset the assignment to start over.",
         };
-      } else if ($p.eq(0).text() != 'Hello Wordl!') {
-        if ($p.eq(0).text() != 'Hello World!') {
+      } else if ($p.eq(0).text() != "Hello Wordl!") {
+        if ($p.eq(0).text() != "Hello World!") {
           return {
             points: 5,
-            feedback: 'Almost there! You were able to change the node contents, but the message is not exactly as requested.'
+            feedback:
+              "Almost there! You were able to change the node contents, but the message is not exactly as requested.",
           };
         } else {
           return {
             points: 10,
-            feedback: 'Great work! You were able to change the node contents as requested.'
+            feedback:
+              "Great work! You were able to change the node contents as requested.",
           };
         }
       }
@@ -52,25 +56,30 @@ let Content = {
     title: "Fix typo",
     description: "Find and change element body",
     concepts: ["Inspector", "DOM", "HTML"],
-    order: 1
+    order: 1,
   },
 
   change_color: {
-    instructions: "The blue area on left contains barely visible text. Your task is to use the browser inspector tool and locate the paragraph element <strong>&lt;p&gt;</strong> containing the barely visible text and then add a CSS property to apply another <strong>color</strong>. <em>Note that editing existing CSS rules does not grade the exercise.</em>",
-    html: "<div class=\"acos-webdev-poi blue\" style=\"max-width: 280px;\"><p>The quick brown fox jumps over the lazy dog's back.</p></div>",
+    instructions:
+      "The blue area on left contains barely visible text. Your task is to use the browser inspector tool and locate the paragraph element <strong>&lt;p&gt;</strong> containing the barely visible text and then add a CSS property to apply another <strong>color</strong>. <em>Note that editing existing CSS rules does not grade the exercise.</em>",
+    html: '<div class="acos-webdev-poi blue" style="max-width: 280px;"><p>The quick brown fox jumps over the lazy dog\'s back.</p></div>',
     mutations: true,
     points: function ($element, config, mutations) {
-      let $p = $element.find('.exercise p');
+      let $p = $element.find(".exercise p");
       if ($p.length != 1) {
         return {
           points: 0,
-          feedback: 'The document is altered beyond repair. Avoid accidentally removing nodes. You should reset the assignment to start over.'
+          feedback:
+            "The document is altered beyond repair. Avoid accidentally removing nodes. You should reset the assignment to start over.",
         };
-      } else if (!config.graded && $p.eq(0).css('color') != 'rgb(173, 216, 230)') {
+      } else if (
+        !config.graded &&
+        $p.eq(0).css("color") != "rgb(173, 216, 230)"
+      ) {
         config.graded = true;
         return {
           points: 10,
-          feedback: 'Excellent! You changed the color of the text.'
+          feedback: "Excellent! You changed the color of the text.",
         };
       }
       return undefined;
@@ -79,41 +88,43 @@ let Content = {
     title: "Change text color",
     description: "Find and change text color using CSS",
     concepts: ["Inspector", "DOM", "CSS"],
-    order: 2
+    order: 2,
   },
 
   disabled_button: {
-    instructions: "You need to click the button on the left to receive your points from this assigment. Too bad that the button is disabled. Your task is to use the browser inspector tool to locate the <strong>button</strong>, remove the <strong>disabled</strong> attribute and finally click it.",
-    html: "<button class=\"green\" disabled>Click Me!</button>",
+    instructions:
+      "You need to click the button on the left to receive your points from this assigment. Too bad that the button is disabled. Your task is to use the browser inspector tool to locate the <strong>button</strong>, remove the <strong>disabled</strong> attribute and finally click it.",
+    html: '<button class="green" disabled>Click Me!</button>',
     selector: ".exercise button",
     events: "click",
     points: function ($element, config, event) {
       return {
         points: 10,
-        feedback: 'Congratulations!'
+        feedback: "Congratulations!",
       };
     },
     maxPoints: 10,
     title: "Disabled button",
     description: "Find and enable button",
     concepts: ["Inspector", "DOM", "HTML"],
-    order: 3
+    order: 3,
   },
 
   console_command: {
-    instructions: "This time the area on the left does not have any visible content. However, this exercise defines a JavaScript function that can grant you points. Your task is to use the browser console to call the function like this: <code>giveMePoints();</code>",
-    html: "<div id=\"events\"><p>First, make sure that your browser <em>console</em> is open and it has the <em>top</em> JavaScript context selected (dropdown selection in Chrome). Then, type in the command given in instruction.</p></div>",
+    instructions:
+      "This time the area on the left does not have any visible content. However, this exercise defines a JavaScript function that can grant you points. Your task is to use the browser console to call the function like this: <code>giveMePoints();</code>",
+    html: '<div id="events"><p>First, make sure that your browser <em>console</em> is open and it has the <em>top</em> JavaScript context selected (dropdown selection in Chrome). Then, type in the command given in instruction.</p></div>',
     script: function giveMePoints() {
-      window.postMessage('grade');
-      return 'Granting points my lord!';
+      window.postMessage("grade");
+      return "Granting points my lord!";
     },
     selector: "$window",
     events: "message",
     points: function ($element, config, event) {
-      if (event.originalEvent.data == 'grade') {
+      if (event.originalEvent.data == "grade") {
         return {
           points: 10,
-          feedback: 'Congratulations!'
+          feedback: "Congratulations!",
         };
       }
       return undefined;
@@ -122,17 +133,19 @@ let Content = {
     title: "Console command",
     description: "Call function in browser console",
     concepts: ["Console", "JavaScript"],
-    order: 4
+    order: 4,
   },
 
   readonly_attribute: {
-      instructions: "First try to fill the form on the left. One of the inputs does not allow you to enter anything in it. Using the browser developer tools, inspect the <em>&lt;input&gt;</em> element which has the <em>readonly</em> attribute set. Remove the attribute and try filling the <em>&lt;input&gt;</em>. You can also submit the form.",
-      script: function formSubmitted(e) {
-        e.preventDefault();
-        document.getElementById('form-submitted').innerHTML = "Thank you for submitting this form! :)";
-      },
-      selector: "$document",
-      html: `
+    instructions:
+      "First try to fill the form on the left. One of the inputs does not allow you to enter anything in it. Using the browser developer tools, inspect the <em>&lt;input&gt;</em> element which has the <em>readonly</em> attribute set. Remove the attribute and try filling the <em>&lt;input&gt;</em>. You can also submit the form.",
+    script: function formSubmitted(e) {
+      e.preventDefault();
+      document.getElementById("form-submitted").innerHTML =
+        "Thank you for submitting this form! :)";
+    },
+    selector: "$document",
+    html: `
       <style>
         #readonly-attribute {
           font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
@@ -160,35 +173,37 @@ let Content = {
         </form>
         <p id=\"form-submitted\"></p>
       </div>`,
-      mutations: true,
-      points: function ($element, config, event) {
-        let $email = $element.find('#form-age-field');
-        let $inputs = $element.find('#readonly-attribute input')
-        if($email.length == 0 || $inputs.length < 3){
-          return {
-            points: 0,
-            feedback: 'The document is altered beyond repair. Avoid accidentally removing nodes or ids. You should reset the assignment to start over.'
-          };
-        } else if(!config.graded && $email['0'].readOnly === false) {
-          config.graded = true;
-          return {
-            points: 10,
-            feedback: 'Congratulations!'
-          };
-          return undefined;
-        }
-      },
-      maxPoints: 10,
-      title: "Disable readonly attribute",
-      description: "Find and disable the readonly attribute",
-      concepts: ["Inspector", "DOM", "CSS", "readonly"],
-      order: 5
+    mutations: true,
+    points: function ($element, config, event) {
+      let $email = $element.find("#form-age-field");
+      let $inputs = $element.find("#readonly-attribute input");
+      if ($email.length == 0 || $inputs.length < 3) {
+        return {
+          points: 0,
+          feedback:
+            "The document is altered beyond repair. Avoid accidentally removing nodes or ids. You should reset the assignment to start over.",
+        };
+      } else if (!config.graded && $email["0"].readOnly === false) {
+        config.graded = true;
+        return {
+          points: 10,
+          feedback: "Congratulations!",
+        };
+        return undefined;
+      }
     },
+    maxPoints: 10,
+    title: "Disable readonly attribute",
+    description: "Find and disable the readonly attribute",
+    concepts: ["Inspector", "DOM", "CSS", "readonly"],
+    order: 5,
+  },
 
-    modify_list: {
-      instructions: "A malicious hacker has managed to break into our database and has modified our perfect pizza recipe, now the pizza does no long taste as before :'(. Please, help us find and remove (delete the element) the malicious ingredient.",
-      selector: "$document",
-      html: `
+  modify_list: {
+    instructions:
+      "A malicious hacker has managed to break into our database and has modified our perfect pizza recipe, now the pizza does no long taste as before :'(. Please, help us find and remove (delete the element) the malicious ingredient. Hint: right click on the element in the inspector and select the correct option.",
+    selector: "$document",
+    html: `
       <style>
       #pizza_ingredients {
         font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
@@ -214,80 +229,91 @@ let Content = {
           <li id="basil">Fresh basil (add on top when the pizza is ready)</li>
         </ul>
       </div>`,
-      mutations: true,
-      script: function getToppingIds(ul) {
-        let toppingIds = [];
-        Object.keys(ul).forEach(k => {
-          if(!isNaN(k)) {
-            toppingIds.push(ul[k].id);
-          };
+    mutations: true,
+    script: function getToppingIds(ul) {
+      let toppingIds = [];
+      Object.keys(ul).forEach((k) => {
+        if (!isNaN(k)) {
+          toppingIds.push(ul[k].id);
+        }
+      });
+      return toppingIds;
+    },
+    points: function ($element, config, event) {
+      let $ol = $element.find("#pizza-ol li");
+      let $ul = $element.find("#pizza-ul li");
+      let toppings = [
+        "tomato",
+        "mozzarella",
+        "olive-oil",
+        "pineapple",
+        "basil",
+      ];
+      if ($ol.length < 4) {
+        return {
+          points: 0,
+          feedback:
+            "The dough should be fine as it is, we think that the problem might be in some nasty topping... Reset to try again",
+        };
+      }
+      if ($ul.length < 4) {
+        return {
+          points: 0,
+          feedback:
+            "Yes you are right, a good pizza does not need many toppings, but we can't remove so many, otherwise we will be still hungry after dinner... Reset to try again",
+        };
+      }
+      if ($ul.length === 4) {
+        let wrongTopping = false;
+        let toppingIds = getToppingIds($ul);
+        toppings.forEach((topping) => {
+          let toppingMissing = !toppingIds.some((id) => id === topping);
+          let wrongMissing = topping !== "pineapple" && toppingMissing;
+          wrongTopping = wrongMissing ? topping : wrongTopping;
         });
-        return toppingIds;
-      },
-      points: function ($element, config, event) {
-        let $ol = $element.find('#pizza-ol li');
-        let $ul = $element.find('#pizza-ul li');
-        let toppings = ["tomato", "mozzarella", "olive-oil", "pineapple", "basil"];
-        if($ol.length < 4) {
+        if (wrongTopping) {
           return {
             points: 0,
-            feedback: 'The dough should be fine as it is, we think that the problem might be in some nasty topping... Reset to try again'
+            feedback: `Are you sure? Please try again, we have used ${wrongTopping} for ages and it is a good topping... Reset to try again`,
           };
-        }
-        if($ul.length < 4) {
+        } else {
           return {
-            points: 0,
-            feedback: "Yes you are right, a good pizza does not need many toppings, but we can't remove so many, otherwise we will be still hungry after dinner... Reset to try again"
+            points: 10,
+            feedback:
+              "Thank you! Pineapple does not really belong on a pizza! What kind of evil hacker could do that to us?",
           };
         }
-        if($ul.length === 4) {
-          let wrongTopping = false;
-          let toppingIds = getToppingIds($ul);
-          toppings.forEach(topping => {
-            let toppingMissing = !toppingIds.some(id => id === topping);
-            let wrongMissing = (topping !== "pineapple" && toppingMissing);
-            wrongTopping = wrongMissing ? topping : wrongTopping;
-          });
-          if(wrongTopping) {
-            return {
-              points: 0,
-              feedback: `Are you sure? Please try again, we have used ${wrongTopping} for ages and it is a good topping... Reset to try again`
-            };
-          } else {
-            return {
-              points: 10,
-              feedback: 'Thank you! Pineapple does not really belong on a pizza! What kind of evil hacker could do that to us?'
-            };
-          }
-        }
-        return undefined;
-      },
-      maxPoints: 10,
-      title: "Remove the right element from the list",
-      description: "Find and remove the element which does not belong in the list",
-      concepts: ["Inspector", "DOM", "CSS", "list"],
-      order: 6
+      }
+      return undefined;
     },
+    maxPoints: 10,
+    title: "Remove the right element from the list",
+    description:
+      "Find and remove the element which does not belong in the list",
+    concepts: ["Inspector", "DOM", "CSS", "list"],
+    order: 6,
+  },
   radio_points: {
-    instructions: "Select the amount of points you would like to have and whether you will be awarded points. You might need to remove a <em>disabled</em> for the desired point amount.",
-    html: "<div id=\"radio-inputs\"><form method=\"post\" action=\"#\" id=\"award-points-form\">Award points?<br>No  <input type=\"radio\" name=\"give-points\" value=\"no\"><br>Yes <input type=\"radio\" name=\"give-points\" value=\"yes\"><br><hr>How many points?<br>No Points <input type=\"radio\" name=\"point-amount\" value=\"0\" checked=\"\"><br>Half points <input type=\"radio\" name=\"point-amount\" value=\"5\"><br>Full Points <input type=\"radio\" name=\"point-amount\" value=\"10\" disabled=\"\"><br><input type=\"submit\" id=\"award-points\" value=\"Award Points\"></form></div>",
+    instructions:
+      "Select the amount of points you would like to have and whether you will be awarded points. You might need to remove a <em>disabled</em> for the desired point amount.",
+    html: '<div id="radio-inputs"><form method="post" action="#" id="award-points-form">Award points?<br>No  <input type="radio" name="give-points" value="no"><br>Yes <input type="radio" name="give-points" value="yes"><br><hr>How many points?<br>No Points <input type="radio" name="point-amount" value="0" checked=""><br>Half points <input type="radio" name="point-amount" value="5"><br>Full Points <input type="radio" name="point-amount" value="10" disabled=""><br><input type="submit" id="award-points" value="Award Points"></form></div>',
     selector: "#award-points-form",
     events: "submit",
     points: function ($element, config, event) {
-      const form = document.getElementById('award-points-form');
-      const givePoints = form.elements['give-points'].value;
-      const pointAmount = parseInt(form.elements['point-amount'].value);
+      const form = document.getElementById("award-points-form");
+      const givePoints = form.elements["give-points"].value;
+      const pointAmount = parseInt(form.elements["point-amount"].value);
 
       event.preventDefault();
-      if(givePoints === 'yes') {
+      if (givePoints === "yes") {
         return {
           points: pointAmount,
-          feedback: 'Congratulations! You got ' + pointAmount + ' points.'
+          feedback: "Congratulations! You got " + pointAmount + " points.",
         };
       } else {
         return {
           points: 0,
-          feedback: 'You selected not to have points.'
+          feedback: "You selected not to have points.",
         };
       }
     },
@@ -295,10 +321,11 @@ let Content = {
     title: "Radio Points",
     description: "Points for selecting correct radio inputs",
     concepts: ["HTML", "Input", "radio", "disabled", "checked"],
-    order: 7
+    order: 7,
   },
   change_border_color: {
-    instructions: "This looks quite horrible, please change the border color and the background color of the element on the left. You can use any value you prefer. In order to get the points you will have to use the developer tools console, and change the color in the <em>element</em> selector. Also remember that the values you use should be valid ones.",
+    instructions:
+      "This looks quite horrible, please change the border color and the background color of the element on the left. You can use any value you prefer. In order to get the points you will have to use the developer tools console, and change the color in the <em>element</em> selector. Also remember that the values you use should be valid ones.",
     html: `
       <style>
         div#color-element {
@@ -320,59 +347,66 @@ let Content = {
     selector: "#color-form",
     events: "submit",
     points: function ($element, config, event) {
-      let borderColor = document.getElementById('color-element').style.borderColor;
-      let backgroundColor = document.getElementById('color-element').style.backgroundColor;
+      let borderColor =
+        document.getElementById("color-element").style.borderColor;
+      let backgroundColor =
+        document.getElementById("color-element").style.backgroundColor;
       let pointAmount = 10;
       event.preventDefault();
-      let colorsChanged = (borderColor !== "rgb(47, 252, 252)" && backgroundColor !== "rgb(252, 47, 252)");
-      let colorsDefined = (borderColor.length > 0 && backgroundColor.length > 0)
+      let colorsChanged =
+        borderColor !== "rgb(47, 252, 252)" &&
+        backgroundColor !== "rgb(252, 47, 252)";
+      let colorsDefined = borderColor.length > 0 && backgroundColor.length > 0;
 
-      if(colorsChanged && colorsDefined) {
-      document.getElementById('color-element').innerHTML = "Thank you, that's much better!"
+      if (colorsChanged && colorsDefined) {
+        document.getElementById("color-element").innerHTML =
+          "Thank you, that's much better!";
         return {
           points: pointAmount,
-          feedback: 'Congratulations, nice colors! You got ' + pointAmount + ' points.'
+          feedback:
+            "Congratulations, nice colors! You got " + pointAmount + " points.",
         };
       } else {
         return {
           points: 0,
-          feedback: 'You have to change both the border color and background color with any valid value of your choice.'
+          feedback:
+            "You have to change both the border color and background color with any valid value of your choice.",
         };
       }
-
     },
     maxPoints: 10,
     title: "Change border color",
     description: "Points for changing the border color to the right value",
     concepts: ["HTML", "Input", "CSS", "color"],
-    order: 8
+    order: 8,
   },
- css_checked_pseudo: {
-    instructions: "You need to add a new style rule (little + icon in the developer tools). That adds a <code>text-decoration</code> property with a value of <code>line-through</code> to any label elements that are <em>adjacent siblings</em> to a checked input. Hint: you can use <code>:checked</code> pseudo-element to select only those inputs which have been checked. To add the new style with the developer tools, right click on the exercise window and choose \"Inspect\". If you go directly to the deveoper tools, the browser might not apply the style.",
-    html: "<form id=\"todo-list-form\"><input type=\"checkbox\" name=\"todo-list\" id=\"exercise\"><label for=\"excercise\">Exercise</label><br><input type=\"checkbox\" name=\"todo-list\" id=\"shopping\"><label for=\"shopping\">Shopping</label><br><input type=\"checkbox\" name=\"todo-list\" id=\"clean\"><label for=\"clean\">Clean</label></form>",
+  css_checked_pseudo: {
+    instructions:
+      'You need to add a new style rule (little + icon in the developer tools). That adds a <code>text-decoration</code> property with a value of <code>line-through</code> to any label elements that are <em>adjacent siblings</em> to a checked input. Hint: you can use <code>:checked</code> pseudo-element to select only those inputs which have been checked. To add the new style with the developer tools, right click on the exercise window and choose "Inspect". If you go directly to the deveoper tools, the browser might not apply the style.',
+    html: '<form id="todo-list-form"><input type="checkbox" name="todo-list" id="exercise"><label for="excercise">Exercise</label><br><input type="checkbox" name="todo-list" id="shopping"><label for="shopping">Shopping</label><br><input type="checkbox" name="todo-list" id="clean"><label for="clean">Clean</label></form>',
     selector: "#todo-list-form",
     events: "change",
     points: function ($element, config, event) {
       let givePoints = true;
       let feedback = "";
-      const checkedLabels = $('#todo-list-form input:checked + label');
-      const allLabels = $('#todo-list-form input + label');
-      const inputs = $('#todo-list-form input');
+      const checkedLabels = $("#todo-list-form input:checked + label");
+      const allLabels = $("#todo-list-form input + label");
+      const inputs = $("#todo-list-form input");
       let checkedSeen = false;
 
-      inputs.map( (idx, input) => {
+      inputs.map((idx, input) => {
         let $label = $(input).next();
 
-        if($(input).prop('checked')){
-          if ($label.css('text-decoration').indexOf('line-through') > -1) {
+        if ($(input).prop("checked")) {
+          if ($label.css("text-decoration").indexOf("line-through") > -1) {
             checkedSeen = true;
           } else {
-            feedback = "Line-through NOT found for label for checked input."
+            feedback = "Line-through NOT found for label for checked input.";
             givePoints = false;
           }
         } else {
-          if ($label.css('text-decoration').indexOf('line-through') > -1) {
-            feedback = "Line-through found for label for NOT checked input."
+          if ($label.css("text-decoration").indexOf("line-through") > -1) {
+            feedback = "Line-through found for label for NOT checked input.";
             givePoints = false;
             checkedSeen = true;
           } else {
@@ -380,29 +414,30 @@ let Content = {
         }
       });
 
-      if(checkedSeen == false) {
+      if (checkedSeen == false) {
         givePoints = false;
-        feedback += " You need to have at least one input checked."
+        feedback += " You need to have at least one input checked.";
       }
 
-      if(givePoints) {
+      if (givePoints) {
         return {
           points: 10,
-          feedback: feedback
+          feedback: feedback,
         };
       } else {
         return {
           points: 0,
-          feedback: feedback
+          feedback: feedback,
         };
       }
     },
 
     maxPoints: 10,
     title: "CSS pseudo-element",
-    description: "Add a new CSS rule that applies to adjacent siblings of a checked input",
+    description:
+      "Add a new CSS rule that applies to adjacent siblings of a checked input",
     concepts: ["HTML", "Input", "CSS", "checked", "pseudo-element"],
-    order: 9
+    order: 9,
   },
 };
 
-- 
GitLab