Development Environments

Assignments From Chapter 26

Solutions to Assignments from Chapter 26

Assignment DE.1.0

Now assume the following JavaScript assignment:

Flip a coin 10 times. Count the heads and the tails. Finish by printing the number of heads and tails.

I have created a naive model solution to this problem. It resides at the repo:

https://phidip@bitbucket.org/phidip/coinflipping.git
  • Clone this to your own computer, ie in a terminal do:
    • mkdir testdir
    • cd testdir
    • git clone https://phidip@bitbucket.org/phidip/coinflipping.git
    • The code is ready for your work.
  • Improve the solution, if nothing else, just put in a comment with your name. Name the solution cf1.js.
  • Create an empty repo on bitbucket.org, gitlab.com, or github.com,
  • Do not forget to change your git remote add … so that it points to your new repo, and not to ours.
  • git push your local repo to the above remote repo.

Now create the html file for testing the above in a web setting. Name the solution cf1.html, and the JavaScript cf1.js.

If you have named the files properly, save them in the same repo you used for the above assignment.

Commit your work.

Model Solution Assignment DE.1.0

Todays solutions don't have any code manifestation. you should do something, and you did.

Assignments From Chapter 28

Model Solutions to Assignments DE.3

Assignment DE.3.0

I will give you a naive example of a function that returns true if a given number is prime, and false if it is not.

Example B.101. Naive isPrime
const isPrime = function (arg) {
    for (var i = 2; i < arg; i += 1) {
        if (arg % i === 0) {
            return false;
        }
    }
    return true;
}

Your assignment is as follows:

  1. Place the given function in a JavaScript library file.
  2. Write a simple HTML5 document and include the library in the head.
  3. Write another js-file that requires the user to enter a positive integer with max-size of 253-1 = 9007199254740991, eg 9007195909437503 :)

    Then it must call isPrime with the entered number as input. The result must be displayed on the page. The code must time the function as follows:

    let start = new Date();
    let b = isPrime(arg);
    let stop = new Date();
    let elapsed = stop - start;
  4. Put the three files into their own repo. Test, commit, and correct until it works.
  5. Create a git branch and change isPrime in the branch to a less naive, and faster version. Test, commit, and correct until it works.
  6. Create a second git branch from the previous branch, and change isPrime in the branch to an even less naive, and faster version. Test, commit, and correct until it works.

Hand in the repo with all three branches. This means that you have three working versions of isPrime.

Model Solution Assignment JS.DE.3
Example B.102. Repo master, File primeLib.js
'use strict';

const isPrime = function (arg) {
    for (var i = 2; i < arg; i += 1) {
        if (arg % i === 0) {
            return false;
        }
    }
    return true;
}

Example B.103. Repo firstSoph, File primeLib.js
'use strict';

var isPrime = function (arg) {
    if (arg % 2 === 0)
        return false;
    for (var i = 3; i <= Math.sqrt(arg); i += 2) {
        if (arg % i === 0) {
            return false;
        }
    }
    return true;
}

Example B.104. Repo bestPractice, File primeLib.js
'use strict';

const isPrime = function (arg) {
    if (arg === 2 || arg === 3)
        return true;
    if (arg % 2 === 0 || arg % 3 === 0)
        return false;

    var i = 1;
    var lim = Math.sqrt(arg);
    var divm1 = 6 * i - 1;
    var divp1 = 6 * i + 1;

    while (divm1 <= lim || divp1 <= lim) {
        if (arg % divm1 === 0 || arg % divp1 === 0)
            return false;
        i++;
        divm1 = 6 * i - 1;
        divp1 = 6 * i + 1;
    }
    return true;
}

Example B.105. Execution Code
'use strict';
let arg = Number(window.prompt('Enter large integer, please'));

let start = new Date();
let b = isPrime(arg);
let stop = new Date();
let elapsed = stop - start;

let primeTime = `Is ${arg} prime: ${b}, duration: ${elapsed} ms`;
document.write(`${primeTime}`);

Example B.106. Host HTML5
<!doctype html>
<html>
    <head>
        <title>Test Prime</title>
        <meta charset='utf-8'/>
        <script src='primeLib.js'></script>
    </head>
    <body>
        <h1>Test and Time <code>isPrime</code></h1>
        <script src='executionCode.js'></script>
</html>

Test! Test with:

  1. 2**53 - 1 = 9007199254740991
  2. 2^53-111 = 9007199254740881
  3. 94906249 * 94906247 = 9007195909437503

The git part

git checkout -b firstSoph       # do some work
git add .
git commit -m 'first sophistication'
git push origin firstSoph       # upload that branch

git checkout -b bestPractice    # do some work
git add .
git commit -m 'best practice'
git push origin bestPractice    # upload that branch

$ git clone https://gitlab.com/arosano/ideprime.git
Cloning into 'ideprime'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 14 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (14/14), 1.97 KiB | 1010.00 KiB/s, done.
$ cd ideprime
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/bestPractice
  remotes/origin/firstSoph
  remotes/origin/master
$ git checkout firstSoph
Branch 'firstSoph' set up to track remote branch 'firstSoph' from 'origin'.
Switched to a new branch 'firstSoph'
$ git branch -a
* firstSoph
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/bestPractice
  remotes/origin/firstSoph
  remotes/origin/master
$     

Assignments From Chapter 32

Assignments DE.Modules

Assignment DE.Mod.1

In this assignment you must, by the use of modules, create a new architecture for your solution to the section called “Assignment DE.5.0 - Project I, Fall 2020”. For each game think in terms of at least three JavaScript files:

  • A library file with functions that you identify as usable in all three games.
  • A library file with functions relevant to this particular game.
  • A JavaScript file with the executable JavaScript that executes the game in this particular page.

We suggest that you start with restructuring the unaltered solution that you handed in. Hand that in as one branch. Then create another branch and think in terms of improving the solution by compartmentalizing the code to have more functions each of which does less. A function should do one thing, and do it well.

Finally this is also an opportunity to improve the yatsy solution with things you didn't have time for in the project.

This assignment may be solved in the groups from the original project, or it may be solved individually if you like the challenge, or if you fell out with the group :-|

Model Solution Assignment DE.Mod.1
Example B.107. Frontpage, Three Games index.html
<!doctype html>
<html>
    <head>
        <meta charset='utf-8'/>
        <title>Project 39</title>
        <link rel='stylesheet' href='./index.css'/>
        <script type='module' src='./index.js'></script>
    </head>
    <body>
        <header>
            <nav>
                <h1>Three Games</h1>
                <ul>
                    <li><a href='./pages/guess/guessNum0.html'>Guess a Number</a></li>
                    <li><a href='./pages/hang/hangman0.html'>Hangman</a></li>
                    <li><a href='./pages/yatzy/yatzy1.html'>Yatzy</a></li>
                </ul>
            </nav>
        </header>
        <main class='vc1'>
            <p>
                42
            </p>
        </main>
        <footer>
            <article id="cpryear"></article>
        </footer>
    </body>
</html>

Click here!


Guess a Number
Example B.108. Game Page guessNum0.html
<!doctype html>
<html>
    <head>
        <title>Guess a Number with JS</title>
        <meta charset='utf-8'/>
        <meta name='viewport' content='width=device-width, initial-scale=1.0'>
        <link rel='stylesheet' href='./number.css'/>
        <script type='module' src='./numberPlay.js'></script>
    </head>
    <body>
        <header>
            <h1>Project 39</h1>
        </header>
        <main>
            <h2>Guess a Number Between 1 - 1000</h2>
            <form name='form22' action='#' method='get'>
                <div id='vola'>
                    <h2>Take a guess:</h2>
                    <p>
                        <input type='text' id='guess' name='guess' size='4' maxlength='4'/>
                    </p>
                    <p>
                        <input type='button' value='Shoot' id='shoot'/>
                    </p>
                    <p id='feedback'>&nbsp;</p>
                </div>
                <p>
                    <input type='button' value='New Game' id='newgame'/>
                    <input type='button' value='Go Home' id='gohome'/>
                </p>
            </form>
        </main>
        <footer>
            <!-- footer if relevant -->
        </footer>
    </body>
</html>

Example B.109. Execute from Game Page numberPlay.js
import {$, roll} from '../../modules/nmlQ.js';

/*
 * Guess a number gameplay
 */
const numbers = function() {
    let guess = Number(document.form22.guess.value);
    if ( guess === "") {
        $('feedback').innerHTML = 'Nothing entered';
    } else {
        countTries += 1;
        if (countTries >= 10) {
            $('feedback').innerHTML = 'Commiserations, the number was: ' + secretNumber;
            $('shoot').removeEventListener('click', numbers);
        } else {
            if (guess > secretNumber) {
                $('feedback').innerHTML = 'Too high';
            } else if (guess < secretNumber) {
                $('feedback').innerHTML = 'Too low';
            } else {
                $('feedback').innerHTML = 'Lucky You, guessed it in ' + countTries + ' attempts';
                $('shoot').removeEventListener('click', numbers);
            }
        }
    }
    $('guess').select();
}

const startNew = function () {
    secretNumber = roll(1000);
    countTries = 0;
    document.form22.guess.value = "";
    $('feedback').innerHTML = "";
    $('vola').style.display = 'block';
    $('shoot').addEventListener('click', numbers);
}

const init = function () {
    $('newgame').addEventListener('click', startNew);
    $('gohome').addEventListener('click', function () {
        window.location = '../..';
    });
}

let secretNumber;
let countTries;

window.addEventListener('load', init);

Example B.110. General Module nmlQ.js
/*
 * nmlQ
 * @version 0.999, 2020-10
 * @author nml
 */

export const $ = function(foo) {
    return document.getElementById(foo);
};

export const roll = function(foo) {
    return Math.floor(Math.random() * foo + 1);
};

/*
 * replace some char with char 'c' in string at pos 'j'
 * s: input string
 * c: replacement character
 * j: position
 */
export const strCharRepl = function(s, c, j) {
    let ns = "";
    for (let i = 0; i < s.length; i++) {
        if (j === i) {
            ns += c;
        } else {
            ns += s.charAt(i);
        }
    }
    return ns;
};

export const copyr = function(bar) {
    let now = new Date();
    let sml = document.createElement("small");
    let cpr = document.createTextNode(`\u00a9nml, ${bar}-${now.getFullYear()}`);
    sml.appendChild(cpr);
    $('cpryear').appendChild(sml);
};

Hangman
Example B.111. Game Page hangman0.html
<!doctype html>
<html>
    <head>
        <title>Guess a Word with JS - Hangman</title>
        <meta charset='utf-8'/>
        <meta name='viewport' content='width=device-width, initial-scale=1.0'>
        <link rel='stylesheet' href='./hangman.css'/>
        <script type='module' src='./hangman.js'></script>
    </head>
    <body>
        <header>
            <h1>Niels' Hangman</h1>
        </header>
        <main>
            <h2>Guess a Long Word Using the Keyboard</h2>
            <section id='game'>
                <div id='theword'>&nbsp;</div>
                <div id='failed'>
                    <h3>Failed Letters</h3>
                    <p id='bads'>&nbsp;</p>
                </div>
                <div>
                    <h3>Attempts</h3>
                    <p id='attempts'>&nbsp;</p>
                </div>
            </section>
            <p>
                <input type='button' value='New Game' id='newgame'/>
                <input type='button' value='Home' id='gohome'/>
            </p>
        </main>
        <footer>
            <!-- footer if relevant -->
        </footer>
    </body>
</html>

Example B.112. Execute from Game Page hangman.js
/*
 * Hangman JavaScript
 */
import {$, roll, strCharRepl} from '../../modules/nmlQ.js';

const gameon = function () {
    $('theword').style.display = 'block';
    $('failed').style.display = 'block';
    $('bads').style.display = 'block';

    countTries = 0;
    secretWord = words[roll(words.length) - 1];
    secretWord = secretWord.toLowerCase();

    word = "";
    for (let i = 0; i < secretWord.length; i++) {
        word += '-';
    }
    $('theword').innerHTML = word;

    $('attempts').innerHTML = countTries;
    $('bads').innerHTML = '';
}

const init = function () {
    $('newgame').addEventListener('click', gameon);
    $('gohome').addEventListener('click', function () {
        window.location = '../..';
    });
    document.addEventListener('keydown', function x(e) {
        let letter = e.key;
        let used = false;
        for (let i = 0; i < secretWord.length; i++) {
            if (secretWord.charAt(i) === letter) {
                used = true;
                word = strCharRepl(word, letter, i);
            }
        }
        $('theword').innerHTML = word;
        if (!used) {
            $('bads').innerHTML += letter;
        }
        countTries += 1;
        $('attempts').innerHTML = countTries;
    });
}

const words = [
    'addEventListener',
    'function',
    'statement',
    'bug',
    'schnittstellenvervielfacher',
    'multiplexer'
];
let countTries;
let secretWord;
let word;

window.addEventListener('load', init);

Example B.113. General Module nmlQ.js
/*
 * nmlQ
 * @version 0.999, 2020-10
 * @author nml
 */

export const $ = function(foo) {
    return document.getElementById(foo);
};

export const roll = function(foo) {
    return Math.floor(Math.random() * foo + 1);
};

/*
 * replace some char with char 'c' in string at pos 'j'
 * s: input string
 * c: replacement character
 * j: position
 */
export const strCharRepl = function(s, c, j) {
    let ns = "";
    for (let i = 0; i < s.length; i++) {
        if (j === i) {
            ns += c;
        } else {
            ns += s.charAt(i);
        }
    }
    return ns;
};

export const copyr = function(bar) {
    let now = new Date();
    let sml = document.createElement("small");
    let cpr = document.createTextNode(`\u00a9nml, ${bar}-${now.getFullYear()}`);
    sml.appendChild(cpr);
    $('cpryear').appendChild(sml);
};

Yatzy
Example B.114. Game Page yatzy1.html
<!doctype html>
<html>
    <head>
        <title>Yatzy, DE.5.0</title>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <link rel='stylesheet' href='./styles.css'/>
        <script type='module' src='./nYPlay.js'></script>
    </head>
    <body>
        <main>
            <h1>Assignment Yatzy</h1>
            <div id='divtop' class='av'></div>

            <div id='divleft'></div>
            <div id='divright'></div>

            <p class='bav'>
                <input type='button' value='New Game' id='newgame'/>
                <input type='button' value='Home' id='gohome'/>
            </p>
        </main>
    </body>
</html>

Example B.115. Execute from Game Page nYPlay.js
import {$} from '../../modules/nmlQ.js';
import {play, disPlay, clrElm} from '../../modules/nYVisual.js';
import {disScorePad} from '../../modules/nYPad.js';
import {clrArrays, dice, locked, magic} from '../../modules/nYLogics.js';

/*
 * nYPlay
 * @version 0.9, 2020
 * @author nml
 */

const gameon = function () {
    clrArrays();
    clrElm(baz);
    clrElm(bar);
    let d = document.createElement('div');
    d.setAttribute('class', 'av');
    let b = document.createElement('button');
    b.setAttribute('id', 'rollthem');
    let t = document.createTextNode('Roll Them');
    b.appendChild(t);
    b.addEventListener('click', function () {
        play();
        disPlay(foo);
    });
    d.appendChild(b);
    $(baz).appendChild(d);
    disScorePad(bar);
}


const init = function () {
    $('newgame').addEventListener('click', gameon);
    $('gohome').addEventListener('click', function () {
        window.location = '../..';
    });
}

const foo = 'divleft';
const bar = 'divright';
const baz = 'divtop';

window.addEventListener('load', init);

Example B.116. Special Module nYVisual.js
import {$, roll} from './nmlQ.js';
import {dice, locked, magic} from './nYLogics.js';
/*
 * nYLogics
 * @version 0.9, 2020
 * @author nml
 */

let play = function () {
    // init magic array
    for (let i = 0; i < magic.length; i++) {
        magic[i] = 0;
    }
    // loop through array of dice, roll if not locked
    for (let i = 0; i < dice.length; i++) {
        let eyes = roll(6);
        if (! locked[i])
            dice[i] = eyes;
    }
    // tap array of dice, create magic array content
    for (let i = 0; i < dice.length; i++) {
        magic[dice[i]]++;
        magic[0] += dice[i];
    }
    // debugging info
    console.log(dice);
    console.log(locked);
    console.log(magic);
}


const clrElm = function(qux) {
    let p = $(qux);
    while (p.firstChild) {
        let elm = p.firstChild;
        p.removeChild(elm);
    }
}

const disPlay = function(qux) {
    clrElm(qux);
    let i = 0;
    while (i < dice.length) {
        let d = document.createElement("div");
        d.setAttribute("class", "die");
        d.setAttribute("id", "d_" + i);
        if (locked[i]) {
            d.style.backgroundColor = "yellow";
        }
        let t = document.createTextNode(dice[i]);
        d.appendChild(t);
        $(qux).appendChild(d);

        d.addEventListener("click", function(e) {
            let j = Number(e.target.id.charAt(e.target.id.length - 1));
            if (locked[j]) {
                e.target.style.backgroundColor = "white";
                locked[j] = false;
            } else {
                e.target.style.backgroundColor = "yellow";
                locked[j] = true;
            }
        });

        i += 1;
    }
}

export {play, disPlay, clrElm};

Example B.117. Special Module nYPad.js
import {$} from './nQuery.js';
//import {record, dice, locked, magic} from './nYLogics.js';

/*
 * nYPad.js Niels' Yatzy Pad
 * @version 0.9, 2016-04
 * @author nml
 */

const NoOfDice = 5;
const headers = ["Play", " ", "You", "Opponent"];
export let rec;

const plays = [
    ["1's", NoOfDice * 1],
    ["2's", NoOfDice * 2],
    ["3's", NoOfDice * 3],
    ["4's", NoOfDice * 4],
    ["5's", NoOfDice * 5],
    ["6's", NoOfDice * 6],
    ["Sum", NoOfDice * 21],
    ["Bonus", 50],
    ["One pair", 2 * 6],
    ["Two pairs", 2 * 6 + 2 * 5],
    ["Three alike", 3 * 6],
    ["Four alike", 4 * 6],
    ["Small straight", 1+2+3+4+5],
    ["Large straight", 2+3+4+5+6],
    ["Full house", 3 * 6 + 2 * 5],
    ["Chance", NoOfDice * 6],
    ["Yatzy", 50],
    ["Total", "x"]
];

const generate = function() {
    let tab = document.createElement("table");
    tab.setAttribute("id", "ytable");

    let row = document.createElement("tr");
    for (let i = 0; i < headers.length; i++) {
        let cell = document.createElement("td");
        let t = document.createTextNode(headers[i]);
        cell.appendChild(t);
        row.appendChild(cell);
    }
    tab.appendChild(row);

    for (let i = 0; i < plays.length; i++) {
        let row = document.createElement("tr");

        let cell = document.createElement("td");
        if (i === 6 || i === 7 || i === plays.length - 1) {
            cell.setAttribute("style", "font-weight: 900");
        }
        let t1 = document.createTextNode(plays[i][0]);
        cell.appendChild(t1);
        row.appendChild(cell);

        cell = document.createElement("td");
        cell.setAttribute("class", "right");
        t1 = document.createTextNode(plays[i][1]);
        cell.appendChild(t1);
        row.appendChild(cell);

        let t2 = document.createTextNode(" ");
        cell = document.createElement("td");
        cell.setAttribute("id", "me" + i);
        cell.setAttribute("class", "right");
        if (!(i === 6 || i === 7 || i === plays.length - 1)) {
            cell.addEventListener("click", function rec() {
                record("me" + i);
                console.log(cell.getAttribute("id"));
            });
        }
        cell.appendChild(t2);
        row.appendChild(cell);

        cell = document.createElement("td");
        cell.setAttribute("id", "they" + i);
        cell.appendChild(t2);
        row.appendChild(cell);

        tab.appendChild(row);
    }
    return tab;
}

export const disScorePad = function(foo) {
    let c = generate();
    $(foo).appendChild(c);
}

Example B.118. General Module nmlQ.js
/*
 * nmlQ
 * @version 0.999, 2020-10
 * @author nml
 */

export const $ = function(foo) {
    return document.getElementById(foo);
};

export const roll = function(foo) {
    return Math.floor(Math.random() * foo + 1);
};

/*
 * replace some char with char 'c' in string at pos 'j'
 * s: input string
 * c: replacement character
 * j: position
 */
export const strCharRepl = function(s, c, j) {
    let ns = "";
    for (let i = 0; i < s.length; i++) {
        if (j === i) {
            ns += c;
        } else {
            ns += s.charAt(i);
        }
    }
    return ns;
};

export const copyr = function(bar) {
    let now = new Date();
    let sml = document.createElement("small");
    let cpr = document.createTextNode(`\u00a9nml, ${bar}-${now.getFullYear()}`);
    sml.appendChild(cpr);
    $('cpryear').appendChild(sml);
};

Assignments From Chapter 33

Assignments DE.Modules II

Assignment DE.Mod.11

In this assignment you must create two different git repos.

You will notice that the software in the second repo depends on the software in the first. This may cause some disturbance. I want you to write a short resume of this part on the work, what happened, and what you did to overcome it. When you are done, hand in both repos.

First repo

Create a Multiple Choice question. Such a question has several constituents:

The properties must be a category, an array of possible answers, the correct answer.

  • A category
  • The Question
  • A number of possible answers
  • The Correct Answer

When organizing this you may explore arrays inside arrays aka multidimensional arrays.

Then create a quiz as an array of Multiple Choice questions. The quiz must have a name. When a quiz is completed it must offer the result to the hosting page/application.

The necessary functionality has functions to pose the questions, print them on the page, record and score the answers, and so forth.

Last you must create an HTML5 page as a testcase for the quiz using the above. As much as possible must be stored in modules. The test page must host the quiz just by providing a script reference to it, and an empty area such as a div or a section where the quiz will live. For the test one or two questions should suffice.

Commit frequently until you are satisfied that the quiz works as planned and desired.

Second repo
Here you must create a website with a real quiz. This means creating a site with a front page, and a page with a quiz. This page must use the software developed for the first repo, and it must contains at least five questions, each with at least 3 answers, where one must be correct. All five questions must be related by category. The category must be one of JavaScript, Git, or HTML5.

Commit frequently until it works.

Model Solution Assignment DE.Mod.11
Repo I, the Prototype
Example B.119. The Solution Files
nmlX240 quizArrayProto  $ tree
.
├── data
│   └── quiz0.js
├── index.css
├── index.html
├── index.js
├── modules
│   ├── nmlQ.js
│   ├── question.js
│   └── quiz.js
└── pages
    ├── quiz.css
    ├── quiz.html
    └── quizExec.js

3 directories, 10 files

Example B.120. Sample Front Page quizArrayProto/index.html
<!doctype html>
<html>
    <head>
        <meta charset='utf-8'/>
        <title>Quiz Prototyping</title>
        <meta name='viewport' content='width=device-width, initial-scale=1.0'>
        <link href='index.css' rel='stylesheet'/>
        <script type='module' src='index.js'></script>
    </head>
    <body>
        <header>
            <nav>
                <h1>Quiz Prototyping</h1>
                <ul>
                    <li><a href='#'>dummy</a></li>
                    <li><a href='#'>dummy</a></li>
                    <li><a href='./pages/quiz.html'>Quiz Prototype</a></li>
                </ul>
            </nav>
        </header>
        <main class='vc1'>
            <p>
                42
            </p>
        </main>
        <footer>
            <article id="cpryear"></article>
        </footer>
    </body>
</html>

Click here!


Example B.121. Sample Quiz Page quizArrayProto/pages/quiz.html
<!doctype html>
<html>
    <head>
        <title>Quiz Prototype</title>
        <meta charset='utf-8'/>
        <meta name='viewport' content='width=device-width, initial-scale=1.0'>
        <link href='./quiz.css' rel='stylesheet'/>
        <script type='module' src='./quizExec.js'></script>
    </head>
    <body>
        <main>
            <h1>Quiz Prototype</h1>
            <section id='quiz'></section>
        </main>
        <nav id='navbot'>
            <a href='../index.html'>Home</a>
        </nav>
    </body>
</html>

Example B.122. Sample Executive JavaScript quizArrayProto/pages/quizExec.js
/* quizExec.js */
'use strict';

import {$} from '../modules/nmlQ.js';
import {qz2html} from '../modules/quiz.js';
import {quiz0} from '../data/quiz0.js';

const printQuiz = function (qz) {
    $('quiz').appendChild(qz2html(qz));
}

const init = function () {
    printQuiz(quiz0);
}

window.addEventListener('load', init);

Example B.123. Sample Test Quiz quizArrayProto/data/quiz0.js
/* quiz0.js a sample quiz as a module */

/*
 * a quiz is an array of a name and an array of questions
 */
 
/*
 * a question is an array of
 * category, question,
 * an array of possible answers,
 * and a pointer to the correct answer
 */
export const quiz0 = [
    'Testquiz',
    [
        [
            'Git',
            'What is a repo?',
            [
                'Another term for an array',
                'A reproduction of an old painting',
                'Directories and files of a project'
            ],
            2
        ],
        [
            'Git',
            'What is a commit?',
            [
                'A checkpoint snapshot of a project repo',
                'A copy of a file',
                'A marriage certificate'
            ],
            0
        ],
        [
            'Git',
            'What is a branch?',
            [
                'A bank on a neighbourhood corner',
                'A separate copy of project files meant for secure development',
                'A subdirectory of the filesystem'
            ],
            1
        ]
    ]
];

Example B.124. The Quiz Module quizArrayProto/modules/quiz.js
/* the quiz module */
'use strict';

import {$, roll} from './nmlQ.js';
import {q2html} from './question.js';

const score = function (c, a) {
    let tot = 0;
    for (let i = 0; i < c.length; i++) {
        if (c[i] === a[i])
            ++tot;
    }
    return tot;
}

export const qzSetName = function (quiz, name) {
        quiz[0] = name;
};

export const qzAddQ = function (quiz, question) {
    quiz[1].push(question);
};

export const qz2html = function (quiz) {
    let quizHtmlElm = document.createElement('section');

    let h2 = document.createElement('h2');
    let tx = document.createTextNode(quiz[0]);
    h2.appendChild(tx);
    quizHtmlElm.appendChild(h2);

    let corrects = [];
    let answers = [];

    for(let i = 0; i < quiz[1].length; i++) {
        corrects[i] = quiz[1][i][3];
        quizHtmlElm.appendChild(q2html(quiz[1][i], i, corrects, answers));
    }

    let btn = document.createElement('button');
    tx = document.createTextNode('Score the Quiz');
    btn.appendChild(tx);
    btn.addEventListener('click', function scx() {
        btn.removeEventListener('click', scx);
        let quizHtmlElmSc = document.createElement('section');

        let h2 = document.createElement('h2');
        let tx = document.createTextNode(`${quiz[0]} Score`);
        h2.appendChild(tx);
        quizHtmlElmSc.appendChild(h2);
        let d = document.createElement('div');
        d.style.fontSize = '1.5em';

        let scoreElm = document.createElement('span');
        scoreElm.setAttribute('id', 'score');
        tx = document.createTextNode(`${score(corrects, answers)}/${quiz[1].length}`);
        scoreElm.appendChild(tx);
        d.appendChild(scoreElm);

        quizHtmlElmSc.appendChild(d);
        $('quiz').appendChild(quizHtmlElmSc);

    });
    quizHtmlElm.appendChild(btn);

    return quizHtmlElm;
};

Example B.125. The Question Module quizArrayProto/modules/question.js
/* the question module */
'use strict';

import {$} from './nmlQ.js';

export const setCat = function (q, cat) {
        q[0] = cat;
};

export const setQuestion = function (q, question) {
        q[1] = question;
};

export const addAnswer = function (q, answer) {
        q[2].push(answer);
};

export const setCorrect = function (q, index) {
        q[3] = index;
};

export const q2html = function (q, no, c, a) {
    let qn = document.createElement('article');

    let h3 = document.createElement('h3');
    let tx = document.createTextNode(`Category: ${q[0]}, Question: ${no + 1}`);
    h3.appendChild(tx);
    qn.appendChild(h3);
    
    let quep = document.createElement('p');
    let em = document.createElement('em');
    let quet = document.createTextNode(`${q[1]}`);
    em.appendChild(quet);
    quep.appendChild(em);
    qn.appendChild(quep);
    
    let quea = document.createElement('p');
    for (let i = 0; i < q[2].length; i++) {
        let span = document.createElement('span');
        let r = document.createElement('input');
        r.setAttribute('type', 'radio');
        let name = 'q' + (no + 1);
        r.setAttribute('name', name);
        let idpart = 'a' + '_' + (no + 1) + '_';
        let id = idpart + i;
        r.setAttribute('id', id);

        r.addEventListener('click', function(e) {
            for (let j = 0; j < q[2].length; j++) {
                if (e.target.id === idpart + j) {
                    a[no] = j; 
                }
            }
        });

        let la = document.createElement('label');
        la.setAttribute('for', id);
        la.setAttribute('id', 'q' + i + 'lab');
        tx = document.createTextNode(' ' + q[2][i]);
        la.appendChild(tx);
        span.appendChild(r);
        span.appendChild(la);
        quea.appendChild(span);
        quea.appendChild(document.createElement('br'));
    };
    // create lock to make radio readonly
    qn.appendChild(quea);
    return qn;
}

Repo II, the Implementation
Example B.126. The Solution Files
nmlX240 quizArrayImp0  $ tree
.
├── data
│   └── quizJS.js
├── index.css
├── index.html
├── index.js
├── modules
│   ├── nmlQ.js -> ../../quizArrayProto/modules/nmlQ.js
│   ├── question.js -> ../../quizArrayProto/modules/question.js
│   └── quiz.js -> ../../quizArrayProto/modules/quiz.js
└── pages
    ├── quiz.css
    ├── quiz.html
    └── quizExec.js

3 directories, 10 files

Example B.127. Implementation Website Front Page quizArrayImp0/index.html
<!doctype html>
<html>
    <head>
        <meta charset='utf-8'/>
        <title>IT Quizzes</title>
        <meta name='viewport' content='width=device-width, initial-scale=1.0'>
        <link href='index.css' rel='stylesheet'/>
        <script type='module' src='index.js'></script>
    </head>
    <body>
        <header>
            <nav>
                <h1>IT Quizzes</h1>
                <ul>
                    <li><a href='./pages/quiz.html'>JavaScript Quiz</a></li>
                    <li><a href='#'>dummy</a></li>
                    <li><a href='#'>dummy about</a></li>
                </ul>
            </nav>
        </header>
        <main class='vc1'>
            <p>
                Programming and Development Quizzes
            </p>
        </main>
        <footer>
            <article id="cpryear"></article>
        </footer>
    </body>
</html>

Click here!


Example B.128. Implementation Website Quiz Page quizArrayImp0/pages/quiz.html
<!doctype html>
<html>
    <head>
        <title>Quiz</title>
        <meta charset='utf-8'/>
        <meta name='viewport' content='width=device-width, initial-scale=1.0'>
        <link href='./quiz.css' rel='stylesheet'/>
        <script type='module' src='./quizExec.js'></script>
    </head>
    <body>
        <main>
            <h1>Quiz</h1>
            <section id='quiz'></section>
        </main>
        <nav id='navbot'>
            <a href='../index.html'>Home</a>
        </nav>
    </body>
</html>

Example B.129. Implementation Website Executive JavaScript quizArrayImp0/pages/quizExec.js
/* quizExec.js */
'use strict';

import {$} from '../modules/nmlQ.js';
import {qz2html} from '../modules/quiz.js';
import {quiz0} from '../data/quizJS.js';

const printQuiz = function (qz) {
    $('quiz').appendChild(qz2html(qz));
}

const init = function () {
    printQuiz(quiz0);
}

window.addEventListener('load', init);

Example B.130. Implemented Quiz quizArrayImp0/data/quizJS.js
/* quiz0.js a sample quiz as a module */

/*
 * a quiz is an array of a name and an array of questions
 */

/*
 * a question is an array of
 * category, question,
 * an array of possible answers,
 * and a pointer to the correct answer
 */
export const quiz0 = [
    'JavaScript Quiz',
    [
        [
            'JavaScript in the Browser',
            'Which of the following lists contain only JavaScript types?',
            [
                'Boolean, Number, Text, Array',
                'Boolean, Number, Text, Collection',
                'Boolean, Integer, Float, Text, Array',
                'Boolean, Number, String, Array, Null'
            ],
            3
        ],
        [
            'JavaScript in the Browser',
            'Which of the following statements makes a module available to JavaScript?',
            [
                'require',
                'request',
                'import',
                'require once'
            ],
            2
        ],
        [
            'JavaScript in the Browser',
            'What is AJaX?',
            [
                'A window cleaning chemical',
                'A way for JavaScript to access a server',
                'An iPhone app written in JavaScript',
                'A specific integrated development environment'
            ],
            1
        ],
        [
            'JavaScript in the Browser',
            'How do you add 1 to the variable foo?',
            [
                'foo = foo + 1;',
                'foo++;',
                'foo += 1;',
                '++foo;',
                'any of the above;',
                'none of the above'
            ],
            4
        ],
        [
            'JavaScript in the Browser',
            'How do you define an array in JavaScript?',
            [
                "let arr = (1, 2, 'a', b);",
                "let arr = (1; 2; 'a'; b);",
                "let arr = [1, 2, 'a', b];",
                "let arr = 1, 2, 'a', b;",
                "let arr = \"1, 2, 'a', b\";",
            ],
            2
        ]
    ]
];

Example B.131. The Quiz Module quizArrayImp0/modules/quiz.js

Is a link to the prototype at Example B.124.


Example B.132. The Question Module quizArrayImp0/modules/question.js

Is a link to the prototype at Example B.125.


Assignments From Chapter 34

Assignments DE.SVG.0

Assignment DE.SVG.0

Create an HTML5 page with an inlined SVG with a viewbox of 400 x 200 pixel. The SVG must contain a yellow disk in the center. Thid disk must have a 10 pixel radius. The SVG must also have blue ellipsis drawn so that its horisontal and vertical minimum and maximum coordinates are just 10 pixel inside the size of the SVG viewbox. The SVG background color must be black. You must code the SVG by hand. No drawing programs allowed.

Model Solution Assignment DE.SVG.0
Example B.133. desvg0M.html
<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>svg</title>
    </head>
    <body>
        <div>
            <svg xmlns="http://www.w3.org/2000/svg"
                 viewbox='0 0 400 200'>
                 <style>    <!-- styling legal in svg -->
                    svg {
                        outline: 1px solid fuchsia;
                        height: 200px;
                        width: 400px;
                        background: #000;
                    }
                 </style>
                 <ellipse cx="200" cy="100" rx="190" ry="90" 
                          stroke-width="1" stroke="blue"/>
                 <circle cx="200" cy="100" r="10" fill="yellow"/>
            </svg>
        </div>
    </body>
</html>

Click here!


Assignment DE.SVG.1

In the previous assignment the term viewbox was used. In this assignment I want you to do some independent research on this subject.

You must make a short documentation on

  • What is a viewbox?
  • What is a viewport?
  • How do they relate to each other?
  • How to scale an SVG drawing's appearance on a web page?

You may use your solution to the previous assignment as illustration of your research, or you may create more targeted examples for that. Handin as an HTML5 page with your research as content.

Model Solution Assignment DE.SVG.1
What is a viewbox?
Værdien af viewbox attributten er en liste af fire tal, min-x, min-y, bredde, og højde, adskilt af mellemrum eller komma, sættes som attribut på svg elementet.
What is a viewport?
Viewport er et HTML-element, der specificerer et rektangel på skærmen. Det kan være img, object, iframe eller svg elementet selv. Indholdet er det ønske SVG billede. Dimensioner sættes med width og height attributter, eller tilsvarende i CSS.
How do they relate to each other?
Viewboxen placeres inden i viewporten.
How to scale an SVG drawing's appearance on a web page?
Viewboxen skalerer til viewportens størrelse, dvs skalering kan ske ved ændring af viewportens bredde og højde.

Assignments From Chapter 35

Assignments DE.SVG.1

Assignment DE.SVG.11

You must, in JavaScript, create an SVG of the flag of Greenland. Use functions in such a way that the size may be adapted to differently sized viewports. If the viewport does not fit the proportions, adapt the flag so that it scales properly within the viewport. Display it on an HTML5 page. The necessary info on dimensions:

The entire flag measures 18 by 12 parts; each stripe measures 6 parts; the disk is 8 parts in diametre, horizontally offset by 7 parts from the hoist to the centre of the circle, and vertically centered.[21]
Assignment DE.SVG.12

You must, in JavaScript, create an SVG of the flag of Denmark. Use functions in such a way that the size may be adapted to differently sized viewports. If the viewport does not fit the proportions, adapt the flag so that it scales properly within the viewport. Display it on an HTML5 page. The necessary info on dimensions:

A red field charged with a white Nordic cross that extends to the edges; the vertical part of the cross is shifted to the hoist side. Dimensions: 3:1:3 width / 3:1:4.5 to 3:1:5.25 length.[22]
Assignment DE.SVG.13

You must, in JavaScript, create an SVG of the flag of the USA. Use functions in such a way that the size may be adapted to differently sized viewports. If the viewport does not fit the proportions, adapt the flag so that it scales properly within the viewport. Display it on an HTML5 page. The necessary info on dimensions:

Dimensions 10:19. Thirteen horizontal stripes alternating red and white; in the canton, 50 white stars of alternating numbers of six and five per horizontal row on a blue field.[23]
Model Solution Assignment DE.SVG.10
Example B.134. Flags Test Pageindex.html
<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>svg</title>
        <style>
            html {
                background: silver;
            }
            svg {
                display: inline-block;
                height: 100px;
                margin: 0 10px;
                padding: 0;
                width: 200px;
            }
        </style>
        <script type='module'>
            'use strict';
            import {$} from './svg96.js';
            import {denmarknew, denmark, denmarka, greenland} from './flags.js';

            let init = function() {
                $('container').appendChild(denmarknew());
                $('container').appendChild(denmark());
                $('container').appendChild(denmarka());
                $('container').appendChild(greenland());
            }
            window.addEventListener('load', init);
        </script>
    </head>
    <body>
        <section id='container'></section>
    </body>
</html>

Click here!


Example B.135. SVG Functions, flags.js
'use strict';
const xmlns = "http://www.w3.org/2000/svg";

export const $ = function(foo) { return document.getElementById(foo); }

export const doSVG = function (wpx, wpy, wbx, wby, bg='white') {
    let svg = document.createElementNS(xmlns, 'svg');
//    svg.setAttributeNS(null, 'width', '100%');
//    svg.setAttributeNS(null, 'height', '100%');
    svg.setAttributeNS(null, 'viewbox', `0 0 ${wbx} ${wby}`);
    svg.appendChild(doRect(0, 0, wpx, wpy, bg));
    return svg;
}

export const doRect = function (x, y, width, height, background) {
    let rect = document.createElementNS(xmlns, 'rect');
    rect.setAttributeNS(null, 'x', x);
    rect.setAttributeNS(null, 'y', y);
    rect.setAttributeNS(null, 'width', width);
    rect.setAttributeNS(null, 'height', height);
    rect.setAttributeNS(null, 'fill', background);
    return rect;
}

export const doArc = function (d, background) {
    let arc = document.createElementNS(xmlns, 'path');
    arc.setAttributeNS(null, "d", d);
    arc.setAttributeNS(null, "fill", background);
    return arc;
}

Example B.136. Flag Functions, flags.js
'use strict';
import {doSVG, doRect, doArc} from './svg96.js';

export const denmarknew = function() {
    let svg = doSVG(85, 70, 85, 70);
    let r1 = doRect(0, 0, 85, 35, 'yellow');
    svg.appendChild(r1);
    svg.appendChild(doRect(0, 35, 85, 35, 'green'));
    return svg;
}
export const denmark = function() {
    // 3:1:3 x 3:1:4.5
    let svg = doSVG(85, 70, 85, 70);
    let r1 = doRect(0, 0, 30, 30, 'red');
    svg.appendChild(r1);
    svg.appendChild(doRect(0, 40, 30, 30, 'red'));
    svg.appendChild(doRect(40, 0, 45, 30, 'red'));
    svg.appendChild(doRect(40, 40, 45, 30, 'red'));
    return svg;
}
export const denmarka = function() {
    // 3:1:3 x 3:1:4.5
    let svg = doSVG(85, 70, 85, 70);
    svg.appendChild(doRect(0, 0, '100%', '100%', 'red'));
    svg.appendChild(doRect(30/85*100+'%', 0, 10/85*100+'%', '100%', 'white'));
    svg.appendChild(doRect(0, 30/70*100+'%', '100%', 10/70*100+'%', 'white'));
    return svg;
}
export const greenland = function() {
    // 18:12
    let svg = doSVG(105, 70, 90, 60);
    svg.appendChild(doRect(0, 0, '100%', '50%', 'white'));
    svg.appendChild(doRect(0, '50%', '100%', '50%', 'red'));
    svg.appendChild(doArc('M15,30 A20,20 0 0 1 55,30', 'red'))
    svg.appendChild(doArc('M15,30 A20,20 0 0 0 55,30', 'white'))
    return svg;
}